From b1ab9ed8d0e0f1c3b66d7daa8fd5564444c56195 Mon Sep 17 00:00:00 2001 From: Apple Date: Mon, 2 Jul 2012 20:53:56 +0000 Subject: [PATCH] Security-55163.44.tar.gz --- APPLE_LICENSE | 680 ++- Security.xcodeproj/project.pbxproj | 4684 +++++++++------ .../xcshareddata/WorkspaceSettings.xcsettings | 8 + .../xcshareddata/xcschemes/Security.xcscheme | 72 + .../xcschemes/Security_executables.xcscheme | 58 + .../xcschemes/Security_frameworks.xcscheme | 58 + .../xcshareddata/xcschemes/World.xcscheme | 58 + .../xcschemes/copyHeaders.xcscheme | 58 + .../xcshareddata/xcschemes/secd.xcscheme | 85 + config/base.xcconfig | 8 + config/debug.xcconfig | 3 + config/lib.xcconfig | 24 + config/release.xcconfig | 3 + config/security.xcconfig | 24 + include/security_agent_client | 1 + include/security_asn1 | 1 + include/security_cdsa_client | 1 + include/security_cdsa_plugin | 1 + include/security_cdsa_utilities | 1 + include/security_cdsa_utils | 1 + include/security_codesigning | 1 + include/security_comcryption | 1 + include/security_cryptkit | 1 + include/security_filedb | 1 + include/security_keychain | 1 + include/security_ocspd | 1 + include/security_pkcs12 | 1 + include/security_smime | 1 + include/security_utilities | 1 + include/securityd_client | 1 + FDEPrefs.plist => lib/FDEPrefs.plist | 2 - .../Info-Security.plist | 2 +- .../en.lproj}/FDELocalizable.strings | 0 .../en.lproj}/InfoPlist.strings | Bin {plugins => lib/plugins}/csparser-Info.plist | 2 +- {plugins => lib/plugins}/csparser.cpp | 0 {plugins => lib/plugins}/csparser.exp | 0 lib/security.exp | 37 + .../Info-security_apple_csp.plist | 5 + libsecurity_apple_csp/README | 32 + libsecurity_apple_csp/TODO | 1 + .../docs/libsecurity_apple_csp.plist | 42 + .../docs/libsecurity_apple_csp.txt | 60 + libsecurity_apple_csp/lib/AppleCSP.cpp | 661 +++ libsecurity_apple_csp/lib/AppleCSP.h | 87 + libsecurity_apple_csp/lib/AppleCSPBuiltin.cpp | 32 + libsecurity_apple_csp/lib/AppleCSPContext.cpp | 274 + libsecurity_apple_csp/lib/AppleCSPContext.h | 181 + libsecurity_apple_csp/lib/AppleCSPKeys.cpp | 89 + libsecurity_apple_csp/lib/AppleCSPKeys.h | 118 + libsecurity_apple_csp/lib/AppleCSPPlugin.cpp | 31 + libsecurity_apple_csp/lib/AppleCSPSession.h | 238 + libsecurity_apple_csp/lib/AppleCSPUtils.cpp | 689 +++ libsecurity_apple_csp/lib/AppleCSPUtils.h | 184 + libsecurity_apple_csp/lib/BinaryKey.h | 124 + libsecurity_apple_csp/lib/BlockCryptor.cpp | 636 +++ libsecurity_apple_csp/lib/BlockCryptor.h | 190 + libsecurity_apple_csp/lib/CryptKitSpace.h | 37 + libsecurity_apple_csp/lib/DH_csp.cpp | 71 + libsecurity_apple_csp/lib/DH_csp.h | 53 + libsecurity_apple_csp/lib/DH_exchange.cpp | 118 + libsecurity_apple_csp/lib/DH_exchange.h | 34 + libsecurity_apple_csp/lib/DH_keys.cpp | 533 ++ libsecurity_apple_csp/lib/DH_keys.h | 149 + libsecurity_apple_csp/lib/DH_utils.cpp | 185 + libsecurity_apple_csp/lib/DH_utils.h | 75 + libsecurity_apple_csp/lib/DigestContext.cpp | 58 + libsecurity_apple_csp/lib/DigestContext.h | 51 + .../lib/FEEAsymmetricContext.cpp | 604 ++ .../lib/FEEAsymmetricContext.h | 146 + libsecurity_apple_csp/lib/FEECSPUtils.cpp | 353 ++ libsecurity_apple_csp/lib/FEECSPUtils.h | 92 + libsecurity_apple_csp/lib/FEEKeys.cpp | 454 ++ libsecurity_apple_csp/lib/FEEKeys.h | 117 + .../lib/FEESignatureObject.cpp | 242 + .../lib/FEESignatureObject.h | 147 + libsecurity_apple_csp/lib/HMACSHA1.c | 37 + libsecurity_apple_csp/lib/HMACSHA1.h | 51 + libsecurity_apple_csp/lib/MD2Object.cpp | 61 + libsecurity_apple_csp/lib/MD2Object.h | 47 + libsecurity_apple_csp/lib/MacContext.cpp | 176 + libsecurity_apple_csp/lib/MacContext.h | 99 + libsecurity_apple_csp/lib/NullCryptor.h | 89 + libsecurity_apple_csp/lib/RSA_DSA_csp.cpp | 234 + libsecurity_apple_csp/lib/RSA_DSA_csp.h | 53 + libsecurity_apple_csp/lib/RSA_DSA_keys.cpp | 829 +++ libsecurity_apple_csp/lib/RSA_DSA_keys.h | 241 + .../lib/RSA_DSA_signature.cpp | 394 ++ libsecurity_apple_csp/lib/RSA_DSA_signature.h | 135 + libsecurity_apple_csp/lib/RSA_DSA_utils.cpp | 623 ++ libsecurity_apple_csp/lib/RSA_DSA_utils.h | 124 + libsecurity_apple_csp/lib/RSA_asymmetric.cpp | 224 + libsecurity_apple_csp/lib/RSA_asymmetric.h | 86 + libsecurity_apple_csp/lib/RawSigner.h | 95 + libsecurity_apple_csp/lib/SHA1_MD5_Object.cpp | 108 + libsecurity_apple_csp/lib/SHA1_MD5_Object.h | 71 + libsecurity_apple_csp/lib/SHA2_Object.cpp | 170 + libsecurity_apple_csp/lib/SHA2_Object.h | 105 + .../lib/SignatureContext.cpp | 127 + libsecurity_apple_csp/lib/SignatureContext.h | 83 + .../lib/YarrowConnection.cpp | 48 + libsecurity_apple_csp/lib/YarrowConnection.h | 46 + libsecurity_apple_csp/lib/aesCommon.h | 42 + libsecurity_apple_csp/lib/aescsp.cpp | 243 + libsecurity_apple_csp/lib/aescspi.h | 102 + libsecurity_apple_csp/lib/algmaker.cpp | 333 ++ libsecurity_apple_csp/lib/ascContext.cpp | 373 ++ libsecurity_apple_csp/lib/ascContext.h | 61 + libsecurity_apple_csp/lib/ascFactory.h | 34 + libsecurity_apple_csp/lib/bfContext.cpp | 120 + libsecurity_apple_csp/lib/bfContext.h | 81 + libsecurity_apple_csp/lib/boxes-ref.c | 228 + libsecurity_apple_csp/lib/boxes-ref.h | 51 + libsecurity_apple_csp/lib/bsafeAsymmetric.cpp | 87 + libsecurity_apple_csp/lib/bsafeContext.cpp | 448 ++ libsecurity_apple_csp/lib/bsafeKeyGen.cpp | 461 ++ libsecurity_apple_csp/lib/bsafePKCS1.cpp | 137 + libsecurity_apple_csp/lib/bsafePKCS1.h | 73 + libsecurity_apple_csp/lib/bsafeSymmetric.cpp | 289 + libsecurity_apple_csp/lib/bsafecsp.h | 58 + libsecurity_apple_csp/lib/bsafecspi.h | 463 ++ libsecurity_apple_csp/lib/bsobjects.h | 64 + libsecurity_apple_csp/lib/castContext.cpp | 133 + libsecurity_apple_csp/lib/castContext.h | 93 + libsecurity_apple_csp/lib/cryptkitcsp.cpp | 218 + libsecurity_apple_csp/lib/cryptkitcsp.h | 59 + libsecurity_apple_csp/lib/cspdebugging.c | 83 + libsecurity_apple_csp/lib/cspdebugging.h | 161 + libsecurity_apple_csp/lib/cssmplugin.exp | 4 + libsecurity_apple_csp/lib/deriveKey.cpp | 436 ++ libsecurity_apple_csp/lib/desContext.cpp | 197 + libsecurity_apple_csp/lib/desContext.h | 95 + libsecurity_apple_csp/lib/gladmanContext.cpp | 173 + libsecurity_apple_csp/lib/gladmanContext.h | 82 + libsecurity_apple_csp/lib/memory.cpp | 53 + libsecurity_apple_csp/lib/miscAlgFactory.cpp | 375 ++ libsecurity_apple_csp/lib/miscAlgFactory.h | 47 + libsecurity_apple_csp/lib/miscalgorithms.cpp | 152 + libsecurity_apple_csp/lib/opensshCoding.cpp | 683 +++ libsecurity_apple_csp/lib/opensshCoding.h | 112 + libsecurity_apple_csp/lib/opensshWrap.cpp | 728 +++ 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/pkcs12Derive.cpp | 447 ++ libsecurity_apple_csp/lib/pkcs12Derive.h | 48 + libsecurity_apple_csp/lib/pkcs8.cpp | 211 + libsecurity_apple_csp/lib/pkcs8.h | 44 + libsecurity_apple_csp/lib/rc2Context.cpp | 127 + libsecurity_apple_csp/lib/rc2Context.h | 58 + libsecurity_apple_csp/lib/rc4Context.cpp | 97 + libsecurity_apple_csp/lib/rc4Context.h | 63 + libsecurity_apple_csp/lib/rc5Context.cpp | 125 + libsecurity_apple_csp/lib/rc5Context.h | 57 + libsecurity_apple_csp/lib/rijndael-alg-ref.c | 615 ++ libsecurity_apple_csp/lib/rijndael-alg-ref.h | 82 + libsecurity_apple_csp/lib/rijndaelApi.c | 276 + libsecurity_apple_csp/lib/rijndaelApi.h | 119 + libsecurity_apple_csp/lib/vRijndael-alg-ref.c | 684 +++ libsecurity_apple_csp/lib/wrapKey.cpp | 742 +++ libsecurity_apple_csp/lib/wrapKeyCms.cpp | 468 ++ .../project.pbxproj | 1460 +++++ .../mds/csp_capabilities.mdsinfo | 18 + .../mds/csp_capabilities_common.mds | 903 +++ libsecurity_apple_csp/mds/csp_common.mdsinfo | 30 + libsecurity_apple_csp/mds/csp_primary.mdsinfo | 36 + libsecurity_apple_csp/open_ssl/LICENSE | 60 + libsecurity_apple_csp/open_ssl/bf/COPYRIGHT | 46 + libsecurity_apple_csp/open_ssl/bf/README | 8 + libsecurity_apple_csp/open_ssl/bf/bf_ecb.c | 96 + libsecurity_apple_csp/open_ssl/bf/bf_enc.c | 306 + libsecurity_apple_csp/open_ssl/bf/bf_locl.h | 232 + libsecurity_apple_csp/open_ssl/bf/bf_pi.h | 325 ++ libsecurity_apple_csp/open_ssl/bf/bf_skey.c | 116 + libsecurity_apple_csp/open_ssl/bio/bio_lib.c | 552 ++ libsecurity_apple_csp/open_ssl/bio/bss_file.c | 328 ++ libsecurity_apple_csp/open_ssl/bn/bn_add.c | 325 ++ libsecurity_apple_csp/open_ssl/bn/bn_asm.c | 855 +++ libsecurity_apple_csp/open_ssl/bn/bn_blind.c | 162 + libsecurity_apple_csp/open_ssl/bn/bn_ctx.c | 162 + libsecurity_apple_csp/open_ssl/bn/bn_div.c | 398 ++ libsecurity_apple_csp/open_ssl/bn/bn_err.c | 140 + libsecurity_apple_csp/open_ssl/bn/bn_exp.c | 901 +++ libsecurity_apple_csp/open_ssl/bn/bn_exp2.c | 217 + libsecurity_apple_csp/open_ssl/bn/bn_gcd.c | 228 + libsecurity_apple_csp/open_ssl/bn/bn_lcl.h | 419 ++ libsecurity_apple_csp/open_ssl/bn/bn_lib.c | 778 +++ libsecurity_apple_csp/open_ssl/bn/bn_mont.c | 357 ++ libsecurity_apple_csp/open_ssl/bn/bn_mpi.c | 147 + libsecurity_apple_csp/open_ssl/bn/bn_mul.c | 812 +++ libsecurity_apple_csp/open_ssl/bn/bn_prime.c | 483 ++ libsecurity_apple_csp/open_ssl/bn/bn_prime.h | 343 ++ libsecurity_apple_csp/open_ssl/bn/bn_print.c | 350 ++ libsecurity_apple_csp/open_ssl/bn/bn_rand.c | 223 + libsecurity_apple_csp/open_ssl/bn/bn_recp.c | 238 + libsecurity_apple_csp/open_ssl/bn/bn_shift.c | 218 + libsecurity_apple_csp/open_ssl/bn/bn_sqr.c | 306 + libsecurity_apple_csp/open_ssl/bn/bn_word.c | 212 + libsecurity_apple_csp/open_ssl/bn/bnspeed.c | 251 + libsecurity_apple_csp/open_ssl/bn/bntest.c | 1096 ++++ libsecurity_apple_csp/open_ssl/bn/divtest.c | 59 + libsecurity_apple_csp/open_ssl/bn/exp.c | 80 + libsecurity_apple_csp/open_ssl/bn/expspeed.c | 233 + libsecurity_apple_csp/open_ssl/bn/exptest.c | 205 + .../open_ssl/bn/vms-helper.c | 84 + .../open_ssl/buffer/buf_err.c | 113 + .../open_ssl/buffer/buffer.c | 162 + libsecurity_apple_csp/open_ssl/cryptlib.c | 350 ++ libsecurity_apple_csp/open_ssl/cryptlib.h | 114 + libsecurity_apple_csp/open_ssl/dh/dh_check.c | 137 + libsecurity_apple_csp/open_ssl/dh/dh_err.c | 116 + libsecurity_apple_csp/open_ssl/dh/dh_gen.c | 170 + libsecurity_apple_csp/open_ssl/dh/dh_key.c | 230 + libsecurity_apple_csp/open_ssl/dh/dh_lib.c | 203 + libsecurity_apple_csp/open_ssl/dsa/dsa_asn1.c | 120 + libsecurity_apple_csp/open_ssl/dsa/dsa_err.c | 124 + libsecurity_apple_csp/open_ssl/dsa/dsa_gen.c | 312 + libsecurity_apple_csp/open_ssl/dsa/dsa_key.c | 129 + libsecurity_apple_csp/open_ssl/dsa/dsa_lib.c | 266 + libsecurity_apple_csp/open_ssl/dsa/dsa_ossl.c | 339 ++ libsecurity_apple_csp/open_ssl/dsa/dsa_sign.c | 112 + libsecurity_apple_csp/open_ssl/dsa/dsa_vrf.c | 114 + libsecurity_apple_csp/open_ssl/err/err.c | 781 +++ libsecurity_apple_csp/open_ssl/err/err_prn.c | 123 + libsecurity_apple_csp/open_ssl/ex_data.c | 241 + libsecurity_apple_csp/open_ssl/lhash/lhash.c | 479 ++ libsecurity_apple_csp/open_ssl/mem.c | 279 + libsecurity_apple_csp/open_ssl/misc/rc2_cbc.c | 256 + .../open_ssl/misc/rc2_locl.h | 174 + .../open_ssl/misc/rc2_skey.c | 156 + libsecurity_apple_csp/open_ssl/misc/rc5_enc.c | 243 + .../open_ssl/misc/rc5_locl.h | 205 + .../open_ssl/misc/rc5_skey.c | 131 + libsecurity_apple_csp/open_ssl/openssl/asn1.h | 1085 ++++ libsecurity_apple_csp/open_ssl/openssl/bio.h | 685 +++ .../open_ssl/openssl/blowfish.h | 131 + libsecurity_apple_csp/open_ssl/openssl/bn.h | 544 ++ .../open_ssl/openssl/buffer.h | 116 + libsecurity_apple_csp/open_ssl/openssl/cast.h | 103 + .../open_ssl/openssl/crypto.h | 391 ++ libsecurity_apple_csp/open_ssl/openssl/dh.h | 221 + libsecurity_apple_csp/open_ssl/openssl/dsa.h | 259 + libsecurity_apple_csp/open_ssl/openssl/e_os.h | 464 ++ .../open_ssl/openssl/e_os2.h | 56 + libsecurity_apple_csp/open_ssl/openssl/err.h | 285 + libsecurity_apple_csp/open_ssl/openssl/evp.h | 761 +++ .../open_ssl/openssl/lhash.h | 163 + .../open_ssl/openssl/objects.h | 1050 ++++ .../open_ssl/openssl/openssl_pkcs7.h | 516 ++ .../open_ssl/openssl/opensslconf.h | 111 + .../open_ssl/openssl/opensslv.h | 50 + libsecurity_apple_csp/open_ssl/openssl/rand.h | 135 + libsecurity_apple_csp/open_ssl/openssl/rc2.h | 123 + libsecurity_apple_csp/open_ssl/openssl/rc5.h | 150 + libsecurity_apple_csp/open_ssl/openssl/rsa.h | 364 ++ .../open_ssl/openssl/safestack.h | 147 + .../open_ssl/openssl/stack.h | 125 + libsecurity_apple_csp/open_ssl/openssl/x509.h | 1222 ++++ .../open_ssl/openssl/x509_vfy.h | 380 ++ .../open_ssl/opensslUtils/opensslAsn1.cpp | 1837 ++++++ .../open_ssl/opensslUtils/opensslAsn1.h | 181 + .../open_ssl/opensslUtils/opensslUtils.cpp | 231 + .../open_ssl/opensslUtils/opensslUtils.h | 66 + libsecurity_apple_csp/open_ssl/rsa/rsa_chk.c | 202 + libsecurity_apple_csp/open_ssl/rsa/rsa_eay.c | 514 ++ libsecurity_apple_csp/open_ssl/rsa/rsa_err.c | 166 + libsecurity_apple_csp/open_ssl/rsa/rsa_gen.c | 216 + libsecurity_apple_csp/open_ssl/rsa/rsa_lib.c | 453 ++ libsecurity_apple_csp/open_ssl/rsa/rsa_none.c | 116 + libsecurity_apple_csp/open_ssl/rsa/rsa_null.c | 167 + libsecurity_apple_csp/open_ssl/rsa/rsa_pk1.c | 242 + libsecurity_apple_csp/open_ssl/rsa/rsa_saos.c | 162 + libsecurity_apple_csp/open_ssl/rsa/rsa_sign.c | 239 + libsecurity_apple_csp/open_ssl/rsa/rsa_ssl.c | 177 + libsecurity_apple_csp/open_ssl/stack/stack.c | 329 ++ libsecurity_apple_csp/tests/t-dsa.cpp | 143 + libsecurity_apple_csp/tests/t-rsa.cpp | 129 + libsecurity_apple_csp/tests/t.cpp | 113 + .../Info-security_apple_cspdl.plist | 5 + .../lib/AppleCSPDLBuiltin.cpp | 32 + .../lib/AppleCSPDLPlugin.cpp | 31 + libsecurity_apple_cspdl/lib/CSPDLDatabase.cpp | 36 + libsecurity_apple_cspdl/lib/CSPDLDatabase.h | 40 + libsecurity_apple_cspdl/lib/CSPDLPlugin.cpp | 78 + libsecurity_apple_cspdl/lib/CSPDLPlugin.h | 56 + .../lib/SSCSPDLSession.cpp | 208 + libsecurity_apple_cspdl/lib/SSCSPDLSession.h | 55 + libsecurity_apple_cspdl/lib/SSCSPSession.cpp | 608 ++ libsecurity_apple_cspdl/lib/SSCSPSession.h | 174 + libsecurity_apple_cspdl/lib/SSContext.cpp | 622 ++ libsecurity_apple_cspdl/lib/SSContext.h | 168 + libsecurity_apple_cspdl/lib/SSDLSession.cpp | 1437 +++++ libsecurity_apple_cspdl/lib/SSDLSession.h | 194 + libsecurity_apple_cspdl/lib/SSDatabase.cpp | 439 ++ libsecurity_apple_cspdl/lib/SSDatabase.h | 142 + libsecurity_apple_cspdl/lib/SSFactory.cpp | 82 + libsecurity_apple_cspdl/lib/SSFactory.h | 39 + libsecurity_apple_cspdl/lib/SSKey.cpp | 347 ++ libsecurity_apple_cspdl/lib/SSKey.h | 87 + .../project.pbxproj | 335 ++ .../mds/cspdl_common.mdsinfo | 30 + .../mds/cspdl_csp_capabilities.mdsinfo | 18 + .../mds/cspdl_csp_primary.mdsinfo | 61 + .../mds/cspdl_dl_primary.mdsinfo | 73 + .../Info-security_apple_file_dl.plist | 5 + libsecurity_apple_file_dl/TODO | 49 + libsecurity_apple_file_dl/doc/FORMAT | 153 + libsecurity_apple_file_dl/doc/ISSUES | 61 + .../lib/AppleDLBuiltin.cpp | 32 + .../lib/AppleDLPlugin.cpp | 31 + libsecurity_apple_file_dl/lib/AppleFileDL.cpp | 81 + libsecurity_apple_file_dl/lib/AppleFileDL.h | 46 + .../project.pbxproj | 264 + .../mds/dl_common.mdsinfo | 30 + .../mds/dl_primary.mdsinfo | 48 + .../Info-plugin_apple_x509_cl.plist | 26 + .../Info-security_apple_x509_cl.plist | 5 + libsecurity_apple_x509_cl/TODO | 1 + libsecurity_apple_x509_cl/lib/AppleX509CL.cpp | 63 + libsecurity_apple_x509_cl/lib/AppleX509CL.h | 48 + .../lib/AppleX509CLBuiltin.cpp | 32 + .../lib/AppleX509CLPlugin.cpp | 31 + .../lib/AppleX509CLSession.cpp | 87 + .../lib/AppleX509CLSession.h | 321 ++ .../lib/CLCachedEntry.cpp | 67 + libsecurity_apple_x509_cl/lib/CLCachedEntry.h | 130 + .../lib/CLCertExtensions.cpp | 1265 +++++ .../lib/CLCertExtensions.h | 64 + .../lib/CLCrlExtensions.cpp | 153 + .../lib/CLCrlExtensions.h | 49 + .../lib/CLFieldsCommon.cpp | 502 ++ .../lib/CLFieldsCommon.h | 147 + libsecurity_apple_x509_cl/lib/CSPAttacher.cpp | 180 + libsecurity_apple_x509_cl/lib/CSPAttacher.h | 47 + libsecurity_apple_x509_cl/lib/CertFields.cpp | 860 +++ libsecurity_apple_x509_cl/lib/CrlFields.cpp | 733 +++ libsecurity_apple_x509_cl/lib/DecodedCert.cpp | 260 + libsecurity_apple_x509_cl/lib/DecodedCert.h | 119 + libsecurity_apple_x509_cl/lib/DecodedCrl.cpp | 115 + libsecurity_apple_x509_cl/lib/DecodedCrl.h | 107 + .../lib/DecodedExtensions.cpp | 527 ++ .../lib/DecodedExtensions.h | 160 + libsecurity_apple_x509_cl/lib/DecodedItem.cpp | 99 + libsecurity_apple_x509_cl/lib/DecodedItem.h | 231 + libsecurity_apple_x509_cl/lib/LockedMap.h | 93 + libsecurity_apple_x509_cl/lib/Session_CRL.cpp | 436 ++ libsecurity_apple_x509_cl/lib/Session_CSR.cpp | 225 + .../lib/Session_Cert.cpp | 411 ++ .../lib/Session_Crypto.cpp | 367 ++ libsecurity_apple_x509_cl/lib/clNameUtils.cpp | 747 +++ libsecurity_apple_x509_cl/lib/clNameUtils.h | 124 + libsecurity_apple_x509_cl/lib/clNssUtils.cpp | 1386 +++++ libsecurity_apple_x509_cl/lib/clNssUtils.h | 273 + libsecurity_apple_x509_cl/lib/cldebugging.h | 38 + .../project.pbxproj | 487 ++ .../mds/cl_common.mdsinfo | 30 + .../mds/cl_primary.mdsinfo | 38 + .../Info-security_apple_x509_tp.plist | 5 + libsecurity_apple_x509_tp/lib/AppleTP.cpp | 62 + libsecurity_apple_x509_tp/lib/AppleTP.h | 48 + .../lib/AppleTPSession.cpp | 312 + .../lib/AppleTPSession.h | 265 + .../lib/AppleX509TPBuiltin.cpp | 32 + .../lib/AppleX509TPPlugin.cpp | 31 + libsecurity_apple_x509_tp/lib/TPCertInfo.cpp | 2289 ++++++++ libsecurity_apple_x509_tp/lib/TPCertInfo.h | 612 ++ libsecurity_apple_x509_tp/lib/TPCrlInfo.cpp | 788 +++ libsecurity_apple_x509_tp/lib/TPCrlInfo.h | 238 + libsecurity_apple_x509_tp/lib/TPDatabase.cpp | 506 ++ libsecurity_apple_x509_tp/lib/TPDatabase.h | 73 + libsecurity_apple_x509_tp/lib/TPNetwork.cpp | 511 ++ libsecurity_apple_x509_tp/lib/TPNetwork.h | 64 + .../lib/certGroupUtils.cpp | 618 ++ .../lib/certGroupUtils.h | 114 + libsecurity_apple_x509_tp/lib/cuEnc64.c | 586 ++ libsecurity_apple_x509_tp/lib/cuEnc64.h | 77 + libsecurity_apple_x509_tp/lib/ocspRequest.cpp | 214 + libsecurity_apple_x509_tp/lib/ocspRequest.h | 83 + libsecurity_apple_x509_tp/lib/tpCertGroup.cpp | 1003 ++++ .../lib/tpCredRequest.cpp | 828 +++ libsecurity_apple_x509_tp/lib/tpCrlVerify.cpp | 469 ++ libsecurity_apple_x509_tp/lib/tpCrlVerify.h | 168 + libsecurity_apple_x509_tp/lib/tpOcspCache.cpp | 319 ++ libsecurity_apple_x509_tp/lib/tpOcspCache.h | 62 + .../lib/tpOcspCertVfy.cpp | 591 ++ libsecurity_apple_x509_tp/lib/tpOcspCertVfy.h | 65 + .../lib/tpOcspVerify.cpp | 870 +++ libsecurity_apple_x509_tp/lib/tpOcspVerify.h | 47 + libsecurity_apple_x509_tp/lib/tpPolicies.cpp | 2762 +++++++++ libsecurity_apple_x509_tp/lib/tpPolicies.h | 88 + libsecurity_apple_x509_tp/lib/tpTime.c | 365 ++ libsecurity_apple_x509_tp/lib/tpTime.h | 95 + libsecurity_apple_x509_tp/lib/tpdebugging.h | 67 + .../project.pbxproj | 393 ++ .../mds/tp_common.mdsinfo | 30 + .../mds/tp_policyOids.mdsinfo | 46 + .../mds/tp_primary.mdsinfo | 34 + libsecurity_asn1/APPLE_LICENSE | 335 ++ libsecurity_asn1/CHANGES.Apple | 58 + libsecurity_asn1/Info-security_asn1.plist | 5 + libsecurity_asn1/Makefile | 101 + libsecurity_asn1/MozillaPublicLicense1.1.html | 796 +++ libsecurity_asn1/Security | 1 + libsecurity_asn1/asn1/README | 2 + libsecurity_asn1/asn1/appleoids.asn | 237 + libsecurity_asn1/asn1/asn-useful.asn1 | 108 + libsecurity_asn1/asn1/pkcs1.asn1 | 205 + libsecurity_asn1/asn1/pkcs10.asn | 53 + libsecurity_asn1/asn1/pkcs1oids.asn | 46 + libsecurity_asn1/asn1/pkcs5.asn1 | 141 + libsecurity_asn1/asn1/pkcs7.asn | 63 + libsecurity_asn1/asn1/pkcs8.asn | 40 + libsecurity_asn1/asn1/pkcs9oids.asn | 19 + libsecurity_asn1/asn1/rfc3161.asn1 | 137 + libsecurity_asn1/asn1/sm_cms.asn | 431 ++ libsecurity_asn1/asn1/sm_ess.asn | 238 + libsecurity_asn1/asn1/sm_vdatypes.asn | 13 + libsecurity_asn1/asn1/sm_x411mtsas.asn | 158 + libsecurity_asn1/asn1/sm_x411ub.asn | 131 + libsecurity_asn1/asn1/sm_x501if.asn | 48 + libsecurity_asn1/asn1/sm_x501ud.asn | 136 + libsecurity_asn1/asn1/sm_x509af.asn | 225 + libsecurity_asn1/asn1/sm_x509ce.asn | 265 + libsecurity_asn1/asn1/sm_x509cmn.asn | 44 + libsecurity_asn1/asn1/sm_x520sa.asn | 196 + libsecurity_asn1/config/base.xcconfig | 8 + libsecurity_asn1/config/debug.xcconfig | 3 + libsecurity_asn1/config/lib.xcconfig | 34 + libsecurity_asn1/config/release.xcconfig | 2 + libsecurity_asn1/docs/libsecurity_asn1.plist | 24 + libsecurity_asn1/docs/libsecurity_asn1.txt | 146 + libsecurity_asn1/lib/SecAsn1Coder.c | 220 + libsecurity_asn1/lib/SecAsn1Coder.h | 149 + libsecurity_asn1/lib/SecAsn1Templates.c | 373 ++ libsecurity_asn1/lib/SecAsn1Templates.h | 131 + libsecurity_asn1/lib/SecAsn1Types.h | 241 + libsecurity_asn1/lib/SecNssCoder.cpp | 194 + libsecurity_asn1/lib/SecNssCoder.h | 161 + libsecurity_asn1/lib/X509Templates.c | 222 + libsecurity_asn1/lib/X509Templates.h | 199 + libsecurity_asn1/lib/asn1Templates.h | 33 + libsecurity_asn1/lib/certExtensionTemplates.c | 322 ++ libsecurity_asn1/lib/certExtensionTemplates.h | 274 + libsecurity_asn1/lib/csrTemplates.c | 69 + libsecurity_asn1/lib/csrTemplates.h | 77 + libsecurity_asn1/lib/keyTemplates.c | 225 + libsecurity_asn1/lib/keyTemplates.h | 276 + libsecurity_asn1/lib/nameTemplates.c | 272 + libsecurity_asn1/lib/nameTemplates.h | 195 + libsecurity_asn1/lib/nsprPortX.c | 250 + libsecurity_asn1/lib/nssUtils.c | 68 + libsecurity_asn1/lib/nssUtils.h | 54 + libsecurity_asn1/lib/nssilckt.h | 220 + libsecurity_asn1/lib/nssilock.h | 316 + libsecurity_asn1/lib/nsslocks.h | 67 + libsecurity_asn1/lib/ocspTemplates.c | 298 + libsecurity_asn1/lib/ocspTemplates.h | 337 ++ libsecurity_asn1/lib/oidsalg.c | 469 ++ libsecurity_asn1/lib/oidsalg.h | 159 + libsecurity_asn1/lib/oidsattr.c | 506 ++ libsecurity_asn1/lib/oidsattr.h | 225 + libsecurity_asn1/lib/oidsbase.h | 356 ++ libsecurity_asn1/lib/oidsocsp.c | 41 + libsecurity_asn1/lib/oidsocsp.h | 50 + libsecurity_asn1/lib/osKeyTemplates.c | 163 + libsecurity_asn1/lib/osKeyTemplates.h | 208 + libsecurity_asn1/lib/pkcs12Templates.c | 289 + libsecurity_asn1/lib/pkcs12Templates.h | 284 + libsecurity_asn1/lib/pkcs7Templates.c | 162 + libsecurity_asn1/lib/pkcs7Templates.h | 165 + libsecurity_asn1/lib/plarena.c | 381 ++ libsecurity_asn1/lib/plarena.h | 216 + libsecurity_asn1/lib/plarenas.h | 117 + libsecurity_asn1/lib/plstr.h | 467 ++ libsecurity_asn1/lib/prbit.h | 108 + libsecurity_asn1/lib/prcpucfg.h | 192 + libsecurity_asn1/lib/prcvar.h | 123 + libsecurity_asn1/lib/prenv.h | 154 + libsecurity_asn1/lib/prerr.h | 275 + libsecurity_asn1/lib/prerror.h | 323 ++ libsecurity_asn1/lib/prinit.h | 240 + libsecurity_asn1/lib/prinrval.h | 172 + libsecurity_asn1/lib/prlock.h | 123 + libsecurity_asn1/lib/prlog.h | 262 + libsecurity_asn1/lib/prlong.h | 425 ++ libsecurity_asn1/lib/prmem.h | 156 + libsecurity_asn1/lib/prmon.h | 110 + libsecurity_asn1/lib/protypes.h | 251 + libsecurity_asn1/lib/prthread.h | 283 + libsecurity_asn1/lib/prtime.h | 295 + libsecurity_asn1/lib/prtypes.h | 560 ++ libsecurity_asn1/lib/prvrsion.h | 134 + libsecurity_asn1/lib/secErrorStr.c | 208 + libsecurity_asn1/lib/secasn1.h | 219 + libsecurity_asn1/lib/secasn1d.c | 3155 ++++++++++ libsecurity_asn1/lib/secasn1e.c | 1639 ++++++ libsecurity_asn1/lib/secasn1t.h | 143 + libsecurity_asn1/lib/secasn1u.c | 115 + libsecurity_asn1/lib/seccomon.h | 125 + libsecurity_asn1/lib/secerr.h | 206 + libsecurity_asn1/lib/secport.c | 632 ++ libsecurity_asn1/lib/secport.h | 290 + libsecurity_asn1/lib/security_asn1.exp | 166 + .../project.pbxproj | 459 ++ libsecurity_asn1/security_asn1 | 1 + libsecurity_authorization/APPLE_LICENSE | 335 ++ .../Info-security_authorization.plist | 5 + libsecurity_authorization/lib/AuthSession.h | 194 + .../lib/Authorization.cpp | 491 ++ libsecurity_authorization/lib/Authorization.h | 462 ++ .../lib/AuthorizationDB.h | 160 + .../lib/AuthorizationPlugin.h | 309 + .../lib/AuthorizationPriv.h | 101 + .../lib/AuthorizationTags.h | 80 + .../lib/AuthorizationTagsPriv.h | 299 + libsecurity_authorization/lib/privPort.h | 59 + .../lib/security_authorization.exp | 40 + .../lib/trampolineClient.cpp | 237 + .../lib/trampolineServer.cpp | 68 + .../project.pbxproj | 285 + .../Info-security_cdsa_client.plist | 5 + libsecurity_cdsa_client/lib/DLDBList.cpp | 53 + libsecurity_cdsa_client/lib/DLDBList.h | 74 + libsecurity_cdsa_client/lib/aclclient.cpp | 324 ++ libsecurity_cdsa_client/lib/aclclient.h | 199 + libsecurity_cdsa_client/lib/clclient.cpp | 54 + libsecurity_cdsa_client/lib/clclient.h | 75 + libsecurity_cdsa_client/lib/cryptoclient.cpp | 142 + libsecurity_cdsa_client/lib/cryptoclient.h | 115 + libsecurity_cdsa_client/lib/cspclient.cpp | 260 + libsecurity_cdsa_client/lib/cspclient.h | 268 + libsecurity_cdsa_client/lib/cssmclient.cpp | 515 ++ libsecurity_cdsa_client/lib/cssmclient.h | 375 ++ libsecurity_cdsa_client/lib/dl_standard.cpp | 195 + libsecurity_cdsa_client/lib/dl_standard.h | 167 + libsecurity_cdsa_client/lib/dlclient.cpp | 878 +++ libsecurity_cdsa_client/lib/dlclient.h | 556 ++ libsecurity_cdsa_client/lib/dlclientpriv.cpp | 35 + libsecurity_cdsa_client/lib/dliterators.cpp | 127 + libsecurity_cdsa_client/lib/dliterators.h | 272 + libsecurity_cdsa_client/lib/dlquery.cpp | 128 + libsecurity_cdsa_client/lib/dlquery.h | 131 + libsecurity_cdsa_client/lib/genkey.cpp | 93 + libsecurity_cdsa_client/lib/genkey.h | 79 + libsecurity_cdsa_client/lib/keychainacl.cpp | 133 + libsecurity_cdsa_client/lib/keychainacl.h | 89 + libsecurity_cdsa_client/lib/keyclient.cpp | 117 + libsecurity_cdsa_client/lib/keyclient.h | 113 + libsecurity_cdsa_client/lib/macclient.cpp | 98 + libsecurity_cdsa_client/lib/macclient.h | 90 + libsecurity_cdsa_client/lib/mds_standard.cpp | 228 + libsecurity_cdsa_client/lib/mds_standard.h | 205 + libsecurity_cdsa_client/lib/mdsclient.cpp | 158 + libsecurity_cdsa_client/lib/mdsclient.h | 102 + libsecurity_cdsa_client/lib/multidldb.cpp | 233 + libsecurity_cdsa_client/lib/multidldb.h | 101 + libsecurity_cdsa_client/lib/securestorage.cpp | 646 +++ libsecurity_cdsa_client/lib/securestorage.h | 343 ++ libsecurity_cdsa_client/lib/signclient.cpp | 96 + libsecurity_cdsa_client/lib/signclient.h | 93 + libsecurity_cdsa_client/lib/tpclient.cpp | 136 + libsecurity_cdsa_client/lib/tpclient.h | 108 + libsecurity_cdsa_client/lib/wrapkey.cpp | 193 + libsecurity_cdsa_client/lib/wrapkey.h | 127 + .../project.pbxproj | 382 ++ .../Info-security_cdsa_plugin.plist | 5 + libsecurity_cdsa_plugin/lib/ACsession.h | 52 + libsecurity_cdsa_plugin/lib/CLsession.h | 51 + libsecurity_cdsa_plugin/lib/CSPsession.cpp | 1156 ++++ libsecurity_cdsa_plugin/lib/CSPsession.h | 545 ++ libsecurity_cdsa_plugin/lib/DLsession.cpp | 57 + libsecurity_cdsa_plugin/lib/DLsession.h | 57 + libsecurity_cdsa_plugin/lib/Database.cpp | 232 + libsecurity_cdsa_plugin/lib/Database.h | 248 + .../lib/DatabaseSession.cpp | 687 +++ libsecurity_cdsa_plugin/lib/DatabaseSession.h | 140 + libsecurity_cdsa_plugin/lib/DbContext.cpp | 44 + libsecurity_cdsa_plugin/lib/DbContext.h | 76 + libsecurity_cdsa_plugin/lib/TPsession.h | 56 + libsecurity_cdsa_plugin/lib/c++plugin.h | 42 + libsecurity_cdsa_plugin/lib/csputilities.cpp | 152 + libsecurity_cdsa_plugin/lib/cssmplugin.cpp | 184 + libsecurity_cdsa_plugin/lib/cssmplugin.h | 132 + libsecurity_cdsa_plugin/lib/generator.cfg | 59 + libsecurity_cdsa_plugin/lib/generator.mk | 29 + libsecurity_cdsa_plugin/lib/generator.pl | 247 + libsecurity_cdsa_plugin/lib/pluginsession.cpp | 91 + libsecurity_cdsa_plugin/lib/pluginsession.h | 92 + libsecurity_cdsa_plugin/lib/pluginspi.h | 99 + .../project.pbxproj | 450 ++ libsecurity_cdsa_utilities/APPLE_LICENSE | 335 ++ .../Info-security_cdsa_utilities.plist | 5 + .../lib/AuthorizationData.cpp | 362 ++ .../lib/AuthorizationData.h | 201 + .../lib/AuthorizationWalkers.h | 82 + libsecurity_cdsa_utilities/lib/KeySchema.h | 70 + libsecurity_cdsa_utilities/lib/KeySchema.m4 | 129 + libsecurity_cdsa_utilities/lib/Schema.h | 129 + libsecurity_cdsa_utilities/lib/Schema.m4 | 466 ++ libsecurity_cdsa_utilities/lib/acl_any.cpp | 63 + libsecurity_cdsa_utilities/lib/acl_any.h | 60 + .../lib/acl_codesigning.cpp | 198 + .../lib/acl_codesigning.h | 95 + .../lib/acl_comment.cpp | 154 + libsecurity_cdsa_utilities/lib/acl_comment.h | 71 + .../lib/acl_password.cpp | 114 + libsecurity_cdsa_utilities/lib/acl_password.h | 75 + .../lib/acl_preauth.cpp | 238 + libsecurity_cdsa_utilities/lib/acl_preauth.h | 132 + .../lib/acl_process.cpp | 157 + libsecurity_cdsa_utilities/lib/acl_process.h | 93 + .../lib/acl_prompted.cpp | 130 + libsecurity_cdsa_utilities/lib/acl_prompted.h | 85 + .../lib/acl_protectedpw.cpp | 121 + .../lib/acl_protectedpw.h | 75 + libsecurity_cdsa_utilities/lib/acl_secret.cpp | 127 + libsecurity_cdsa_utilities/lib/acl_secret.h | 99 + .../lib/acl_threshold.cpp | 180 + .../lib/acl_threshold.h | 86 + libsecurity_cdsa_utilities/lib/aclsubject.cpp | 160 + libsecurity_cdsa_utilities/lib/aclsubject.h | 223 + libsecurity_cdsa_utilities/lib/callback.cpp | 122 + libsecurity_cdsa_utilities/lib/callback.h | 113 + libsecurity_cdsa_utilities/lib/constdata.cpp | 44 + libsecurity_cdsa_utilities/lib/constdata.h | 89 + libsecurity_cdsa_utilities/lib/context.cpp | 189 + libsecurity_cdsa_utilities/lib/context.h | 379 ++ libsecurity_cdsa_utilities/lib/cssmacl.cpp | 28 + libsecurity_cdsa_utilities/lib/cssmacl.h | 63 + libsecurity_cdsa_utilities/lib/cssmaclpod.cpp | 222 + libsecurity_cdsa_utilities/lib/cssmaclpod.h | 356 ++ libsecurity_cdsa_utilities/lib/cssmalloc.cpp | 87 + libsecurity_cdsa_utilities/lib/cssmalloc.h | 155 + libsecurity_cdsa_utilities/lib/cssmbridge.h | 62 + libsecurity_cdsa_utilities/lib/cssmcert.cpp | 88 + libsecurity_cdsa_utilities/lib/cssmcert.h | 125 + libsecurity_cdsa_utilities/lib/cssmcred.cpp | 112 + libsecurity_cdsa_utilities/lib/cssmcred.h | 191 + libsecurity_cdsa_utilities/lib/cssmdata.cpp | 248 + libsecurity_cdsa_utilities/lib/cssmdata.h | 561 ++ libsecurity_cdsa_utilities/lib/cssmdates.cpp | 195 + libsecurity_cdsa_utilities/lib/cssmdates.h | 127 + libsecurity_cdsa_utilities/lib/cssmdb.cpp | 590 ++ libsecurity_cdsa_utilities/lib/cssmdb.h | 866 +++ libsecurity_cdsa_utilities/lib/cssmdbname.cpp | 149 + libsecurity_cdsa_utilities/lib/cssmdbname.h | 131 + libsecurity_cdsa_utilities/lib/cssmendian.cpp | 53 + libsecurity_cdsa_utilities/lib/cssmendian.h | 50 + libsecurity_cdsa_utilities/lib/cssmerrors.cpp | 129 + libsecurity_cdsa_utilities/lib/cssmerrors.h | 68 + libsecurity_cdsa_utilities/lib/cssmkey.cpp | 56 + libsecurity_cdsa_utilities/lib/cssmkey.h | 151 + libsecurity_cdsa_utilities/lib/cssmlist.cpp | 313 + libsecurity_cdsa_utilities/lib/cssmlist.h | 269 + libsecurity_cdsa_utilities/lib/cssmpods.cpp | 168 + libsecurity_cdsa_utilities/lib/cssmpods.h | 221 + libsecurity_cdsa_utilities/lib/cssmtrust.cpp | 48 + libsecurity_cdsa_utilities/lib/cssmtrust.h | 178 + .../lib/cssmwalkers.cpp | 28 + libsecurity_cdsa_utilities/lib/cssmwalkers.h | 233 + libsecurity_cdsa_utilities/lib/db++.cpp | 144 + libsecurity_cdsa_utilities/lib/db++.h | 91 + libsecurity_cdsa_utilities/lib/digestobject.h | 134 + libsecurity_cdsa_utilities/lib/generator.mk | 26 + libsecurity_cdsa_utilities/lib/generator.pl | 89 + .../lib/handleobject.cpp | 31 + libsecurity_cdsa_utilities/lib/handleobject.h | 47 + .../lib/handletemplates.cpp | 39 + .../lib/handletemplates.h | 294 + .../lib/handletemplates_defs.h | 204 + libsecurity_cdsa_utilities/lib/objectacl.cpp | 660 +++ libsecurity_cdsa_utilities/lib/objectacl.h | 250 + .../lib/osxverifier.cpp | 177 + libsecurity_cdsa_utilities/lib/osxverifier.h | 93 + .../lib/u32handleobject.cpp | 27 + .../lib/u32handleobject.h | 43 + .../lib/uniformrandom.cpp | 37 + .../lib/uniformrandom.h | 56 + libsecurity_cdsa_utilities/lib/walkers.cpp | 47 + libsecurity_cdsa_utilities/lib/walkers.h | 393 ++ .../project.pbxproj | 699 +++ .../Info-security_cdsa_utils.plist | 5 + libsecurity_cdsa_utils/lib/cuCdsaUtils.cpp | 777 +++ libsecurity_cdsa_utils/lib/cuCdsaUtils.h | 161 + libsecurity_cdsa_utils/lib/cuDbUtils.cpp | 574 ++ libsecurity_cdsa_utils/lib/cuDbUtils.h | 71 + libsecurity_cdsa_utils/lib/cuEnc64.c | 392 ++ libsecurity_cdsa_utils/lib/cuEnc64.h | 67 + libsecurity_cdsa_utils/lib/cuFileIo.c | 113 + libsecurity_cdsa_utils/lib/cuFileIo.h | 41 + libsecurity_cdsa_utils/lib/cuOidParser.cpp | 314 + libsecurity_cdsa_utils/lib/cuOidParser.h | 62 + libsecurity_cdsa_utils/lib/cuPem.cpp | 198 + libsecurity_cdsa_utils/lib/cuPem.h | 50 + libsecurity_cdsa_utils/lib/cuPrintCert.cpp | 1500 +++++ libsecurity_cdsa_utils/lib/cuPrintCert.h | 64 + libsecurity_cdsa_utils/lib/cuTimeStr.cpp | 293 + libsecurity_cdsa_utils/lib/cuTimeStr.h | 75 + .../project.pbxproj | 270 + libsecurity_checkpw/APPLE_LICENSE | 335 ++ .../Info-security_checkpw.plist | 5 + libsecurity_checkpw/checkpw.pam | 3 + libsecurity_checkpw/lib/checkpw.c | 107 + libsecurity_checkpw/lib/checkpw.h | 63 + libsecurity_checkpw/lib/security_checkpw.exp | 2 + .../project.pbxproj | 385 ++ libsecurity_checkpw/test/perf-checkpw.c | 24 + libsecurity_checkpw/test/test-checkpw.c | 35 + libsecurity_cms/APPLE_LICENSE | 335 ++ libsecurity_cms/Info-security_cms.plist | 5 + libsecurity_cms/lib/CMSDecoder.cpp | 958 ++++ libsecurity_cms/lib/CMSDecoder.h | 362 ++ libsecurity_cms/lib/CMSEncoder.cpp | 1437 +++++ libsecurity_cms/lib/CMSEncoder.h | 403 ++ libsecurity_cms/lib/CMSPrivate.h | 132 + libsecurity_cms/lib/CMSUtils.cpp | 145 + libsecurity_cms/lib/CMSUtils.h | 84 + libsecurity_cms/lib/security_cms.exp | 46 + .../libsecurity_cms.xcodeproj/project.pbxproj | 215 + libsecurity_codesigning/APPLE_LICENSE | 335 ++ .../Info-security_codesigning.plist | 5 + .../dtrace/codesign-watch.d | 368 ++ libsecurity_codesigning/dtrace/reqint.d | 133 + libsecurity_codesigning/dtrace/sp-watch.d | 52 + libsecurity_codesigning/gke/gkclear | 84 + libsecurity_codesigning/gke/gkgenerate | 101 + libsecurity_codesigning/gke/gkhandmake | 109 + libsecurity_codesigning/gke/gklist | 18 + libsecurity_codesigning/gke/gkmerge | 50 + libsecurity_codesigning/gke/gkrecord | 198 + libsecurity_codesigning/lib/CSCommon.h | 298 + libsecurity_codesigning/lib/CSCommonPriv.h | 118 + libsecurity_codesigning/lib/Code.cpp | 284 + libsecurity_codesigning/lib/Code.h | 89 + libsecurity_codesigning/lib/CodeSigner.cpp | 262 + libsecurity_codesigning/lib/CodeSigner.h | 98 + libsecurity_codesigning/lib/CodeSigning.h | 37 + .../lib/RequirementKeywords.h | 24 + .../lib/RequirementLexer.cpp | 1268 +++++ .../lib/RequirementLexer.hpp | 77 + .../lib/RequirementParser.cpp | 1303 +++++ .../lib/RequirementParser.hpp | 153 + .../lib/RequirementParserTokenTypes.hpp | 75 + .../lib/RequirementParserTokenTypes.txt | 55 + libsecurity_codesigning/lib/Requirements.cpp | 92 + libsecurity_codesigning/lib/Requirements.h | 64 + libsecurity_codesigning/lib/SecAssessment.cpp | 387 ++ libsecurity_codesigning/lib/SecAssessment.h | 296 + libsecurity_codesigning/lib/SecCode.cpp | 268 + libsecurity_codesigning/lib/SecCode.h | 431 ++ libsecurity_codesigning/lib/SecCodeHost.cpp | 117 + libsecurity_codesigning/lib/SecCodeHost.h | 241 + libsecurity_codesigning/lib/SecCodeHostLib.c | 124 + libsecurity_codesigning/lib/SecCodeHostLib.h | 110 + libsecurity_codesigning/lib/SecCodePriv.h | 185 + libsecurity_codesigning/lib/SecCodeSigner.cpp | 110 + libsecurity_codesigning/lib/SecCodeSigner.h | 218 + libsecurity_codesigning/lib/SecIntegrity.cpp | 26 + libsecurity_codesigning/lib/SecIntegrity.h | 49 + libsecurity_codesigning/lib/SecIntegrityLib.c | 23 + libsecurity_codesigning/lib/SecIntegrityLib.h | 55 + .../lib/SecRequirement.cpp | 307 + libsecurity_codesigning/lib/SecRequirement.h | 140 + .../lib/SecRequirementPriv.h | 197 + libsecurity_codesigning/lib/SecStaticCode.cpp | 301 + libsecurity_codesigning/lib/SecStaticCode.h | 156 + .../lib/SecStaticCodePriv.h | 48 + libsecurity_codesigning/lib/SecTask.c | 235 + libsecurity_codesigning/lib/SecTask.h | 103 + libsecurity_codesigning/lib/StaticCode.cpp | 1192 ++++ libsecurity_codesigning/lib/StaticCode.h | 237 + libsecurity_codesigning/lib/antlrplugin.cpp | 124 + libsecurity_codesigning/lib/antlrplugin.h | 74 + libsecurity_codesigning/lib/bundlediskrep.cpp | 480 ++ libsecurity_codesigning/lib/bundlediskrep.h | 127 + libsecurity_codesigning/lib/cdbuilder.cpp | 217 + libsecurity_codesigning/lib/cdbuilder.h | 95 + libsecurity_codesigning/lib/cfmdiskrep.cpp | 224 + libsecurity_codesigning/lib/cfmdiskrep.h | 112 + libsecurity_codesigning/lib/codedirectory.cpp | 270 + libsecurity_codesigning/lib/codedirectory.h | 265 + libsecurity_codesigning/lib/cs.cpp | 63 + libsecurity_codesigning/lib/cs.h | 184 + libsecurity_codesigning/lib/cscdefs.c | 4 + libsecurity_codesigning/lib/cscdefs.h | 89 + libsecurity_codesigning/lib/csdatabase.cpp | 175 + libsecurity_codesigning/lib/csdatabase.h | 78 + libsecurity_codesigning/lib/cserror.cpp | 88 + libsecurity_codesigning/lib/cserror.h | 67 + libsecurity_codesigning/lib/csgeneric.cpp | 218 + libsecurity_codesigning/lib/csgeneric.h | 82 + libsecurity_codesigning/lib/cskernel.cpp | 195 + libsecurity_codesigning/lib/cskernel.h | 86 + libsecurity_codesigning/lib/csprocess.cpp | 51 + libsecurity_codesigning/lib/csprocess.h | 66 + libsecurity_codesigning/lib/csutilities.cpp | 188 + libsecurity_codesigning/lib/csutilities.h | 167 + libsecurity_codesigning/lib/detachedrep.cpp | 103 + libsecurity_codesigning/lib/detachedrep.h | 69 + libsecurity_codesigning/lib/diskrep.cpp | 298 + libsecurity_codesigning/lib/diskrep.h | 219 + libsecurity_codesigning/lib/drmaker.cpp | 197 + libsecurity_codesigning/lib/drmaker.h | 69 + libsecurity_codesigning/lib/filediskrep.cpp | 191 + libsecurity_codesigning/lib/filediskrep.h | 93 + libsecurity_codesigning/lib/kerneldiskrep.cpp | 91 + libsecurity_codesigning/lib/kerneldiskrep.h | 64 + libsecurity_codesigning/lib/machorep.cpp | 383 ++ libsecurity_codesigning/lib/machorep.h | 102 + libsecurity_codesigning/lib/policydb.cpp | 410 ++ libsecurity_codesigning/lib/policydb.h | 133 + libsecurity_codesigning/lib/policyengine.cpp | 886 +++ libsecurity_codesigning/lib/policyengine.h | 86 + libsecurity_codesigning/lib/quarantine++.cpp | 107 + libsecurity_codesigning/lib/quarantine++.h | 77 + libsecurity_codesigning/lib/renum.cpp | 80 + libsecurity_codesigning/lib/renum.h | 58 + libsecurity_codesigning/lib/reqdumper.cpp | 353 ++ libsecurity_codesigning/lib/reqdumper.h | 100 + libsecurity_codesigning/lib/reqinterp.cpp | 573 ++ libsecurity_codesigning/lib/reqinterp.h | 88 + libsecurity_codesigning/lib/reqmaker.cpp | 169 + libsecurity_codesigning/lib/reqmaker.h | 134 + libsecurity_codesigning/lib/reqparser.cpp | 125 + libsecurity_codesigning/lib/reqparser.h | 66 + libsecurity_codesigning/lib/reqreader.cpp | 93 + libsecurity_codesigning/lib/reqreader.h | 86 + libsecurity_codesigning/lib/requirement.cpp | 173 + libsecurity_codesigning/lib/requirement.h | 217 + libsecurity_codesigning/lib/resources.cpp | 216 + libsecurity_codesigning/lib/resources.h | 118 + .../lib/security_codesigning.d | 96 + .../lib/security_codesigning.exp | 161 + libsecurity_codesigning/lib/sigblob.cpp | 65 + libsecurity_codesigning/lib/sigblob.h | 81 + libsecurity_codesigning/lib/signer.cpp | 426 ++ libsecurity_codesigning/lib/signer.h | 87 + libsecurity_codesigning/lib/signerutils.cpp | 363 ++ libsecurity_codesigning/lib/signerutils.h | 201 + libsecurity_codesigning/lib/singlediskrep.cpp | 127 + libsecurity_codesigning/lib/singlediskrep.h | 89 + libsecurity_codesigning/lib/slcrep.cpp | 162 + libsecurity_codesigning/lib/slcrep.h | 93 + libsecurity_codesigning/lib/syspolicy.sql | 197 + libsecurity_codesigning/lib/xar++.cpp | 96 + libsecurity_codesigning/lib/xar++.h | 66 + libsecurity_codesigning/lib/xpcengine.cpp | 191 + libsecurity_codesigning/lib/xpcengine.h | 44 + .../project.pbxproj | 1326 +++++ libsecurity_codesigning/req/cfm.ireqs | 4 + libsecurity_codesigning/req/ppc-host.ireq | 4 + libsecurity_codesigning/requirements.grammar | 488 ++ .../Info-security_comcryption.plist | 5 + libsecurity_comcryption/lib/comDebug.h | 212 + libsecurity_comcryption/lib/comcryptPriv.c | 537 ++ libsecurity_comcryption/lib/comcryptPriv.h | 487 ++ libsecurity_comcryption/lib/comcryption.c | 1444 +++++ libsecurity_comcryption/lib/comcryption.h | 169 + .../project.pbxproj | 200 + .../Info-security_cryptkit.plist | 5 + libsecurity_cryptkit/ckutils/Makefile | 21 + libsecurity_cryptkit/ckutils/Makefile.common | 88 + .../ckutils/atomTime/Makefile | 53 + .../ckutils/atomTime/atomTime.c | 662 +++ libsecurity_cryptkit/ckutils/badsig/Makefile | 51 + libsecurity_cryptkit/ckutils/badsig/badsig.c | 461 ++ .../ckutils/blobtest/Makefile | 51 + .../ckutils/blobtest/blobtest.c | 344 ++ .../ckutils/cfileTest/Makefile | 51 + .../ckutils/cfileTest/cfileTest.c | 579 ++ .../ckutils/ckutilsPlatform.h | 106 + .../ckutils/giantAsmBench/Makefile | 51 + .../ckutils/giantAsmBench/giantAsmBench.c | 215 + .../ckutils/giantBench/Makefile | 51 + .../ckutils/giantBench/giantBench.c | 259 + .../ckutils/giantDvt/Makefile | 51 + .../ckutils/giantDvt/giantDvt.c | 535 ++ libsecurity_cryptkit/ckutils/sigTime/Makefile | 55 + .../ckutils/sigTime/sigTime.cpp | 269 + libsecurity_cryptkit/lib/ByteRep.txt | 293 + libsecurity_cryptkit/lib/CipherFileDES.c | 586 ++ libsecurity_cryptkit/lib/CipherFileDES.h | 67 + libsecurity_cryptkit/lib/CipherFileFEED.c | 460 ++ libsecurity_cryptkit/lib/CipherFileFEED.h | 69 + libsecurity_cryptkit/lib/CipherFileTypes.h | 83 + libsecurity_cryptkit/lib/Crypt.h | 60 + libsecurity_cryptkit/lib/CryptKit.def | 113 + libsecurity_cryptkit/lib/CryptKit.h | 28 + libsecurity_cryptkit/lib/CryptKitAsn1.cpp | 82 + libsecurity_cryptkit/lib/CryptKitAsn1.h | 138 + libsecurity_cryptkit/lib/CryptKitDER.cpp | 1151 ++++ libsecurity_cryptkit/lib/CryptKitDER.h | 162 + libsecurity_cryptkit/lib/CryptKitSA.h | 23 + .../lib/CurveParamDocs/FEEDaffine.nb | 253 + .../lib/CurveParamDocs/FEEDsansY.nb | 324 ++ .../lib/CurveParamDocs/README | 62 + .../lib/CurveParamDocs/curvegen.c | 105 + .../lib/CurveParamDocs/curverecords.nb | 898 +++ .../lib/CurveParamDocs/disc.h | 312 + .../lib/CurveParamDocs/ellproj.c | 448 ++ .../lib/CurveParamDocs/ellproj.h | 59 + .../lib/CurveParamDocs/factor.c | 844 +++ .../lib/CurveParamDocs/fmodule.c | 410 ++ .../lib/CurveParamDocs/fmodule.h | 36 + .../lib/CurveParamDocs/giants.c | 3517 ++++++++++++ .../lib/CurveParamDocs/giants.h | 314 + .../lib/CurveParamDocs/schoof.c | 1100 ++++ .../lib/CurveParamDocs/schoofs.c | 1044 ++++ .../lib/CurveParamDocs/tools.c | 445 ++ .../lib/CurveParamDocs/tools.h | 65 + libsecurity_cryptkit/lib/ECDSA_Profile.h | 91 + .../lib/ECDSA_Verify_Prefix.h | 6 + libsecurity_cryptkit/lib/HmacSha1Legacy.c | 167 + libsecurity_cryptkit/lib/HmacSha1Legacy.h | 70 + libsecurity_cryptkit/lib/Mathematica.FEE | 57 + libsecurity_cryptkit/lib/NSCipherFile.h | 111 + libsecurity_cryptkit/lib/NSCipherFile.m | 360 ++ libsecurity_cryptkit/lib/NSCryptors.h | 83 + libsecurity_cryptkit/lib/NSDESCryptor.h | 39 + libsecurity_cryptkit/lib/NSDESCryptor.m | 130 + libsecurity_cryptkit/lib/NSFEEPublicKey.h | 74 + libsecurity_cryptkit/lib/NSFEEPublicKey.m | 496 ++ .../lib/NSFEEPublicKeyPrivate.h | 36 + libsecurity_cryptkit/lib/NSMD5Hash.h | 34 + libsecurity_cryptkit/lib/NSMD5Hash.m | 79 + .../lib/NSRandomNumberGenerator.h | 36 + .../lib/NSRandomNumberGenerator.m | 83 + libsecurity_cryptkit/lib/README | 221 + libsecurity_cryptkit/lib/TOP_README | 30 + libsecurity_cryptkit/lib/buildSrcTree | 34 + libsecurity_cryptkit/lib/byteRep.c | 476 ++ libsecurity_cryptkit/lib/byteRep.h | 80 + libsecurity_cryptkit/lib/changes | 222 + libsecurity_cryptkit/lib/ckDES.c | 546 ++ libsecurity_cryptkit/lib/ckDES.h | 70 + libsecurity_cryptkit/lib/ckMD5.c | 365 ++ libsecurity_cryptkit/lib/ckMD5.h | 90 + libsecurity_cryptkit/lib/ckSHA1.c | 227 + libsecurity_cryptkit/lib/ckSHA1.h | 75 + libsecurity_cryptkit/lib/ckSHA1_priv.c | 321 ++ libsecurity_cryptkit/lib/ckSHA1_priv.h | 60 + libsecurity_cryptkit/lib/ckconfig.h | 106 + libsecurity_cryptkit/lib/ckutilities.c | 416 ++ libsecurity_cryptkit/lib/ckutilities.h | 47 + libsecurity_cryptkit/lib/curveParamData.h | 540 ++ libsecurity_cryptkit/lib/curveParamDataOld.h | 350 ++ libsecurity_cryptkit/lib/curveParams.c | 1399 +++++ libsecurity_cryptkit/lib/curveParams.h | 230 + libsecurity_cryptkit/lib/elliptic.c | 1438 +++++ libsecurity_cryptkit/lib/elliptic.h | 165 + libsecurity_cryptkit/lib/ellipticMeasure.h | 86 + libsecurity_cryptkit/lib/ellipticProj.c | 566 ++ libsecurity_cryptkit/lib/ellipticProj.h | 76 + libsecurity_cryptkit/lib/enc64.c | 417 ++ libsecurity_cryptkit/lib/enc64.h | 65 + libsecurity_cryptkit/lib/engineNSA127.c | 543 ++ libsecurity_cryptkit/lib/falloc.c | 109 + libsecurity_cryptkit/lib/falloc.h | 47 + libsecurity_cryptkit/lib/feeCipherFile.c | 280 + libsecurity_cryptkit/lib/feeCipherFile.h | 164 + libsecurity_cryptkit/lib/feeCipherFileAtom.c | 400 ++ libsecurity_cryptkit/lib/feeDES.c | 529 ++ libsecurity_cryptkit/lib/feeDES.h | 141 + libsecurity_cryptkit/lib/feeDebug.h | 195 + .../lib/feeDigitalSignature.c | 674 +++ .../lib/feeDigitalSignature.h | 111 + libsecurity_cryptkit/lib/feeECDSA.c | 666 +++ libsecurity_cryptkit/lib/feeECDSA.h | 82 + libsecurity_cryptkit/lib/feeFEED.c | 1233 ++++ libsecurity_cryptkit/lib/feeFEED.h | 140 + libsecurity_cryptkit/lib/feeFEEDExp.c | 735 +++ libsecurity_cryptkit/lib/feeFEEDExp.h | 126 + libsecurity_cryptkit/lib/feeFunctions.h | 69 + libsecurity_cryptkit/lib/feeHash.c | 110 + libsecurity_cryptkit/lib/feeHash.h | 81 + libsecurity_cryptkit/lib/feePublicKey.c | 1608 ++++++ libsecurity_cryptkit/lib/feePublicKey.h | 341 ++ .../lib/feePublicKeyPrivate.h | 43 + libsecurity_cryptkit/lib/feeRandom.c | 206 + libsecurity_cryptkit/lib/feeRandom.h | 49 + libsecurity_cryptkit/lib/feeTypes.h | 168 + libsecurity_cryptkit/lib/giantFFT.c | 520 ++ libsecurity_cryptkit/lib/giantIntegers.c | 1748 ++++++ libsecurity_cryptkit/lib/giantIntegers.h | 163 + libsecurity_cryptkit/lib/giantPortCommon.h | 46 + libsecurity_cryptkit/lib/giantPort_Generic.h | 165 + libsecurity_cryptkit/lib/giantPort_PPC.c | 236 + libsecurity_cryptkit/lib/giantPort_PPC.h | 119 + libsecurity_cryptkit/lib/giantPort_PPC_Gnu.h | 83 + libsecurity_cryptkit/lib/giantPort_PPC_Gnu.s | 282 + libsecurity_cryptkit/lib/giantPort_i486.h | 126 + libsecurity_cryptkit/lib/giantPort_i486.s | 149 + libsecurity_cryptkit/lib/mutils.h | 36 + libsecurity_cryptkit/lib/mutils.m | 44 + libsecurity_cryptkit/lib/platform.c | 197 + libsecurity_cryptkit/lib/platform.h | 73 + libsecurity_cryptkit/lib/unixMakefile | 102 + .../project.pbxproj | 762 +++ libsecurity_cssm/APPLE_LICENSE | 335 ++ libsecurity_cssm/Info-security_cssm.plist | 5 + libsecurity_cssm/lib/attachfactory.cpp | 111 + libsecurity_cssm/lib/attachfactory.h | 85 + libsecurity_cssm/lib/attachment.cpp | 205 + libsecurity_cssm/lib/attachment.h | 199 + libsecurity_cssm/lib/certextensions.h | 640 +++ libsecurity_cssm/lib/cspattachment.cpp | 31 + libsecurity_cssm/lib/cspattachment.h | 45 + libsecurity_cssm/lib/cssm.cpp | 224 + libsecurity_cssm/lib/cssm.h | 35 + libsecurity_cssm/lib/cssmaci.h | 60 + libsecurity_cssm/lib/cssmapi.h | 2212 +++++++ libsecurity_cssm/lib/cssmapple.h | 1154 ++++ libsecurity_cssm/lib/cssmapplePriv.h | 153 + libsecurity_cssm/lib/cssmcli.h | 242 + libsecurity_cssm/lib/cssmconfig.h | 95 + libsecurity_cssm/lib/cssmcontext.cpp | 204 + libsecurity_cssm/lib/cssmcontext.h | 123 + libsecurity_cssm/lib/cssmcspi.h | 367 ++ libsecurity_cssm/lib/cssmdli.h | 151 + libsecurity_cssm/lib/cssmerr.h | 823 +++ libsecurity_cssm/lib/cssmint.h | 80 + libsecurity_cssm/lib/cssmkrapi.h | 243 + libsecurity_cssm/lib/cssmkrspi.h | 111 + libsecurity_cssm/lib/cssmmds.cpp | 46 + libsecurity_cssm/lib/cssmmds.h | 57 + libsecurity_cssm/lib/cssmspi.h | 132 + libsecurity_cssm/lib/cssmtpi.h | 202 + libsecurity_cssm/lib/cssmtype.h | 2079 +++++++ libsecurity_cssm/lib/eisl.h | 326 ++ libsecurity_cssm/lib/emmspi.h | 94 + libsecurity_cssm/lib/emmtype.h | 53 + libsecurity_cssm/lib/generator.cfg | 13 + libsecurity_cssm/lib/generator.mk | 33 + libsecurity_cssm/lib/generator.pl | 250 + libsecurity_cssm/lib/guids.cpp | 116 + libsecurity_cssm/lib/manager.cpp | 220 + libsecurity_cssm/lib/manager.h | 115 + libsecurity_cssm/lib/modload_plugin.cpp | 118 + libsecurity_cssm/lib/modload_plugin.h | 65 + libsecurity_cssm/lib/modload_static.cpp | 79 + libsecurity_cssm/lib/modload_static.h | 64 + libsecurity_cssm/lib/modloader.cpp | 105 + libsecurity_cssm/lib/modloader.h | 99 + libsecurity_cssm/lib/module.cpp | 164 + libsecurity_cssm/lib/module.h | 103 + libsecurity_cssm/lib/oidsalg.c | 158 + libsecurity_cssm/lib/oidsbase.h | 459 ++ libsecurity_cssm/lib/oidscert.cpp | 405 ++ libsecurity_cssm/lib/oidscert.h | 208 + libsecurity_cssm/lib/oidscrl.cpp | 179 + libsecurity_cssm/lib/oidscrl.h | 99 + libsecurity_cssm/lib/security_cssm.exp | 643 +++ libsecurity_cssm/lib/transition.cpp | 514 ++ libsecurity_cssm/lib/x509defs.h | 230 + .../project.pbxproj | 484 ++ libsecurity_cssm/mds/cssm.mdsinfo | 24 + libsecurity_filedb/Info-security_filedb.plist | 5 + libsecurity_filedb/lib/AppleDatabase.cpp | 2561 +++++++++ libsecurity_filedb/lib/AppleDatabase.h | 666 +++ libsecurity_filedb/lib/AtomicFile.cpp | 1267 +++++ libsecurity_filedb/lib/AtomicFile.h | 257 + libsecurity_filedb/lib/DbIndex.cpp | 476 ++ libsecurity_filedb/lib/DbIndex.h | 198 + libsecurity_filedb/lib/DbQuery.cpp | 30 + libsecurity_filedb/lib/DbQuery.h | 45 + libsecurity_filedb/lib/DbValue.cpp | 555 ++ libsecurity_filedb/lib/DbValue.h | 213 + libsecurity_filedb/lib/MetaAttribute.cpp | 158 + libsecurity_filedb/lib/MetaAttribute.h | 162 + libsecurity_filedb/lib/MetaRecord.cpp | 580 ++ libsecurity_filedb/lib/MetaRecord.h | 176 + libsecurity_filedb/lib/OverUnderflowCheck.h | 85 + libsecurity_filedb/lib/ReadWriteSection.cpp | 53 + libsecurity_filedb/lib/ReadWriteSection.h | 209 + libsecurity_filedb/lib/SelectionPredicate.cpp | 51 + libsecurity_filedb/lib/SelectionPredicate.h | 52 + .../project.pbxproj | 285 + libsecurity_keychain/APPLE_LICENSE | 335 ++ .../Info-security_keychain.plist | 5 + libsecurity_keychain/lib/ACL.cpp | 434 ++ libsecurity_keychain/lib/ACL.h | 157 + libsecurity_keychain/lib/Access.cpp | 380 ++ libsecurity_keychain/lib/Access.h | 139 + libsecurity_keychain/lib/CCallbackMgr.cp | 240 + libsecurity_keychain/lib/CCallbackMgr.h | 102 + libsecurity_keychain/lib/Certificate.cpp | 1262 ++++ libsecurity_keychain/lib/Certificate.h | 146 + .../lib/CertificateRequest.cpp | 857 +++ libsecurity_keychain/lib/CertificateRequest.h | 154 + .../lib/CertificateValues.cpp | 562 ++ libsecurity_keychain/lib/CertificateValues.h | 70 + libsecurity_keychain/lib/DLDBListCFPref.cpp | 1068 ++++ libsecurity_keychain/lib/DLDBListCFPref.h | 222 + libsecurity_keychain/lib/DynamicDLDBList.cpp | 235 + libsecurity_keychain/lib/DynamicDLDBList.h | 74 + .../lib/ExtendedAttribute.cpp | 193 + libsecurity_keychain/lib/ExtendedAttribute.h | 91 + libsecurity_keychain/lib/Globals.cpp | 66 + libsecurity_keychain/lib/Globals.h | 73 + libsecurity_keychain/lib/Identity.cpp | 93 + libsecurity_keychain/lib/Identity.h | 67 + libsecurity_keychain/lib/IdentityCursor.cpp | 351 ++ libsecurity_keychain/lib/IdentityCursor.h | 89 + libsecurity_keychain/lib/Item.cpp | 1397 +++++ libsecurity_keychain/lib/Item.h | 195 + libsecurity_keychain/lib/KCCursor.cpp | 300 + libsecurity_keychain/lib/KCCursor.h | 85 + libsecurity_keychain/lib/KCEventNotifier.cpp | 79 + libsecurity_keychain/lib/KCEventNotifier.h | 60 + libsecurity_keychain/lib/KCExceptions.h | 97 + libsecurity_keychain/lib/KCUtilities.cpp | 30 + libsecurity_keychain/lib/KCUtilities.h | 46 + libsecurity_keychain/lib/KeyItem.cpp | 1350 +++++ libsecurity_keychain/lib/KeyItem.h | 139 + libsecurity_keychain/lib/Keychains.cpp | 1372 +++++ libsecurity_keychain/lib/Keychains.h | 263 + libsecurity_keychain/lib/MacOSErrorStrings.h | 61 + libsecurity_keychain/lib/Password.cpp | 147 + libsecurity_keychain/lib/Password.h | 81 + libsecurity_keychain/lib/Policies.cpp | 313 + libsecurity_keychain/lib/Policies.h | 87 + libsecurity_keychain/lib/PolicyCursor.cpp | 108 + libsecurity_keychain/lib/PolicyCursor.h | 90 + libsecurity_keychain/lib/PrimaryKey.cpp | 134 + libsecurity_keychain/lib/PrimaryKey.h | 75 + libsecurity_keychain/lib/SecACL.cpp | 294 + libsecurity_keychain/lib/SecACL.h | 220 + libsecurity_keychain/lib/SecAccess.cpp | 673 +++ libsecurity_keychain/lib/SecAccess.h | 217 + libsecurity_keychain/lib/SecAccessPriv.h | 76 + libsecurity_keychain/lib/SecAsn1TypesP.h | 241 + libsecurity_keychain/lib/SecBase.cpp | 1119 ++++ libsecurity_keychain/lib/SecBase.h | 619 ++ libsecurity_keychain/lib/SecBase64P.c | 489 ++ libsecurity_keychain/lib/SecBase64P.h | 247 + libsecurity_keychain/lib/SecBaseP.h | 91 + libsecurity_keychain/lib/SecBasePriv.h | 91 + libsecurity_keychain/lib/SecBridge.h | 69 + libsecurity_keychain/lib/SecCFTypes.cpp | 70 + libsecurity_keychain/lib/SecCFTypes.h | 107 + libsecurity_keychain/lib/SecCertificate.cpp | 901 +++ libsecurity_keychain/lib/SecCertificate.h | 466 ++ .../lib/SecCertificateBundle.cpp | 82 + .../lib/SecCertificateBundle.h | 77 + .../lib/SecCertificateInternalP.h | 311 + libsecurity_keychain/lib/SecCertificateOIDs.h | 168 + libsecurity_keychain/lib/SecCertificateP.c | 4711 +++++++++++++++ libsecurity_keychain/lib/SecCertificateP.h | 102 + libsecurity_keychain/lib/SecCertificatePriv.h | 181 + .../lib/SecCertificatePrivP.h | 183 + .../lib/SecCertificateRequest.cpp | 190 + .../lib/SecCertificateRequest.h | 191 + libsecurity_keychain/lib/SecExport.cpp | 341 ++ libsecurity_keychain/lib/SecExternalRep.cpp | 536 ++ libsecurity_keychain/lib/SecExternalRep.h | 181 + .../lib/SecFDERecoveryAsymmetricCrypto.cpp | 188 + .../lib/SecFDERecoveryAsymmetricCrypto.h | 63 + libsecurity_keychain/lib/SecFrameworkP.c | 263 + libsecurity_keychain/lib/SecFrameworkP.h | 64 + libsecurity_keychain/lib/SecIdentity.cpp | 1109 ++++ libsecurity_keychain/lib/SecIdentity.h | 198 + libsecurity_keychain/lib/SecIdentityPriv.h | 152 + .../lib/SecIdentitySearch.cpp | 116 + libsecurity_keychain/lib/SecIdentitySearch.h | 87 + .../lib/SecIdentitySearchPriv.h | 87 + libsecurity_keychain/lib/SecImport.cpp | 412 ++ libsecurity_keychain/lib/SecImportExport.c | 335 ++ libsecurity_keychain/lib/SecImportExport.h | 657 +++ .../lib/SecImportExportAgg.cpp | 881 +++ libsecurity_keychain/lib/SecImportExportAgg.h | 82 + .../lib/SecImportExportCrypto.cpp | 737 +++ .../lib/SecImportExportCrypto.h | 123 + .../lib/SecImportExportOpenSSH.cpp | 635 +++ .../lib/SecImportExportOpenSSH.h | 81 + .../lib/SecImportExportPem.cpp | 505 ++ libsecurity_keychain/lib/SecImportExportPem.h | 71 + .../lib/SecImportExportPkcs8.cpp | 978 ++++ .../lib/SecImportExportPkcs8.h | 63 + .../lib/SecImportExportUtils.cpp | 935 +++ .../lib/SecImportExportUtils.h | 219 + libsecurity_keychain/lib/SecInternal.h | 63 + libsecurity_keychain/lib/SecInternalP.h | 66 + libsecurity_keychain/lib/SecItem.cpp | 3700 ++++++++++++ libsecurity_keychain/lib/SecItem.h | 937 +++ libsecurity_keychain/lib/SecItemConstants.c | 221 + libsecurity_keychain/lib/SecItemPriv.h | 295 + libsecurity_keychain/lib/SecKey.cpp | 2109 +++++++ libsecurity_keychain/lib/SecKey.h | 588 ++ libsecurity_keychain/lib/SecKeyPriv.h | 405 ++ libsecurity_keychain/lib/SecKeychain.cpp | 1100 ++++ libsecurity_keychain/lib/SecKeychain.h | 646 +++ .../lib/SecKeychainAddIToolsPassword.cpp | 105 + libsecurity_keychain/lib/SecKeychainItem.cpp | 606 ++ libsecurity_keychain/lib/SecKeychainItem.h | 340 ++ .../lib/SecKeychainItemExtendedAttributes.cpp | 358 ++ .../lib/SecKeychainItemExtendedAttributes.h | 126 + .../lib/SecKeychainItemPriv.h | 164 + libsecurity_keychain/lib/SecKeychainPriv.h | 89 + .../lib/SecKeychainSearch.cpp | 89 + libsecurity_keychain/lib/SecKeychainSearch.h | 76 + .../lib/SecKeychainSearchPriv.h | 57 + .../lib/SecNetscapeTemplates.cpp | 69 + .../lib/SecNetscapeTemplates.h | 93 + libsecurity_keychain/lib/SecPassword.cpp | 246 + libsecurity_keychain/lib/SecPassword.h | 95 + .../lib/SecPkcs8Templates.cpp | 94 + libsecurity_keychain/lib/SecPkcs8Templates.h | 110 + libsecurity_keychain/lib/SecPolicy.cpp | 281 + libsecurity_keychain/lib/SecPolicy.h | 301 + libsecurity_keychain/lib/SecPolicyPriv.h | 72 + libsecurity_keychain/lib/SecPolicySearch.cpp | 77 + libsecurity_keychain/lib/SecPolicySearch.h | 83 + libsecurity_keychain/lib/SecRSAKeyP.h | 67 + libsecurity_keychain/lib/SecRandom.c | 64 + libsecurity_keychain/lib/SecRandom.h | 66 + libsecurity_keychain/lib/SecRandomP.h | 58 + .../lib/SecRecoveryPassword.c | 480 ++ .../lib/SecRecoveryPassword.h | 106 + libsecurity_keychain/lib/SecTrust.cpp | 533 ++ libsecurity_keychain/lib/SecTrust.h | 489 ++ libsecurity_keychain/lib/SecTrustPriv.h | 157 + libsecurity_keychain/lib/SecTrustSettings.cpp | 892 +++ libsecurity_keychain/lib/SecTrustSettings.h | 321 ++ .../lib/SecTrustSettingsPriv.h | 143 + .../lib/SecTrustedApplication.cpp | 236 + .../lib/SecTrustedApplication.h | 82 + .../lib/SecTrustedApplicationPriv.h | 175 + libsecurity_keychain/lib/SecWrappedKeys.cpp | 495 ++ libsecurity_keychain/lib/Security.h | 101 + libsecurity_keychain/lib/StorageManager.cpp | 1833 ++++++ libsecurity_keychain/lib/StorageManager.h | 181 + libsecurity_keychain/lib/Trust.cpp | 805 +++ libsecurity_keychain/lib/Trust.h | 168 + libsecurity_keychain/lib/TrustAdditions.cpp | 1187 ++++ libsecurity_keychain/lib/TrustAdditions.h | 52 + libsecurity_keychain/lib/TrustItem.cpp | 192 + libsecurity_keychain/lib/TrustItem.h | 81 + libsecurity_keychain/lib/TrustKeychains.h | 53 + libsecurity_keychain/lib/TrustRevocation.cpp | 633 +++ libsecurity_keychain/lib/TrustSettings.cpp | 1559 +++++ libsecurity_keychain/lib/TrustSettings.h | 256 + .../lib/TrustSettingsSchema.h | 150 + .../lib/TrustSettingsUtils.cpp | 100 + libsecurity_keychain/lib/TrustSettingsUtils.h | 58 + libsecurity_keychain/lib/TrustStore.cpp | 254 + libsecurity_keychain/lib/TrustStore.h | 79 + .../lib/TrustedApplication.cpp | 202 + libsecurity_keychain/lib/TrustedApplication.h | 97 + .../lib/UnlockReferralItem.cpp | 127 + libsecurity_keychain/lib/UnlockReferralItem.h | 66 + libsecurity_keychain/lib/certextensionsP.h | 546 ++ libsecurity_keychain/lib/cssmdatetime.cpp | 465 ++ libsecurity_keychain/lib/cssmdatetime.h | 67 + libsecurity_keychain/lib/debuggingP.c | 151 + libsecurity_keychain/lib/debuggingP.h | 48 + libsecurity_keychain/lib/defaultcreds.cpp | 195 + libsecurity_keychain/lib/defaultcreds.h | 78 + .../lib/generateErrStrings.pl | 98 + .../lib/security_keychain.exp | 712 +++ libsecurity_keychain/lib/tsaDERUtilities.c | 121 + libsecurity_keychain/lib/tsaDERUtilities.h | 45 + libsecurity_keychain/libDER/README.txt | 34 + .../Tests/AppleMobilePersonalizedTicket.h | 114 + .../libDER/Tests/DER_Ticket.c | 188 + .../libDER/Tests/DER_Ticket.h | 81 + .../certsCrls/EndCertificateCP.01.01.crt | Bin 0 -> 650 bytes .../libDER/Tests/certsCrls/Test_CRL_CA1.crl | Bin 0 -> 483 bytes .../Tests/certsCrls/Test_CRL_CA1.crl.pem | 13 + .../Tests/certsCrls/TrustAnchorCP.01.01.crt | Bin 0 -> 624 bytes .../certsCrls/TrustAnchorCRLCP.01.01.crl | Bin 0 -> 371 bytes .../libDER/Tests/certsCrls/apple_v3.000.cer | Bin 0 -> 1158 bytes .../libDER/Tests/certsCrls/apple_v3.001.cer | Bin 0 -> 903 bytes .../libDER/Tests/certsCrls/entrust_v3.100.cer | Bin 0 -> 1351 bytes .../libDER/Tests/certsCrls/entrust_v3.101.cer | Bin 0 -> 1244 bytes .../libDER/Tests/certsCrls/keybank_v3.100.cer | Bin 0 -> 1131 bytes .../libDER/Tests/certsCrls/keybank_v3.101.cer | Bin 0 -> 903 bytes .../libDER/Tests/certsCrls/keybank_v3.102.cer | Bin 0 -> 576 bytes libsecurity_keychain/libDER/Tests/parseCert.c | 149 + libsecurity_keychain/libDER/Tests/parseCrl.c | 167 + .../libDER/Tests/parseTicket.c | 586 ++ .../libDER/config/base.xcconfig | 8 + .../libDER/config/debug.xcconfig | 3 + .../libDER/config/lib.xcconfig | 32 + .../libDER/config/release.xcconfig | 2 + .../libDER/libDER.xcodeproj/project.pbxproj | 734 +++ .../libDER/libDER/DER_CertCrl.c | 319 ++ .../libDER/libDER/DER_CertCrl.h | 237 + .../libDER/libDER/DER_Decode.c | 584 ++ .../libDER/libDER/DER_Decode.h | 195 + .../libDER/libDER/DER_Digest.c | 162 + .../libDER/libDER/DER_Digest.h | 74 + .../libDER/libDER/DER_Encode.c | 342 ++ .../libDER/libDER/DER_Encode.h | 103 + libsecurity_keychain/libDER/libDER/DER_Keys.c | 167 + 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.c | 479 ++ libsecurity_keychain/libDER/libDER/oids.h | 102 + .../libDER/libDERUtils/fileIo.c | 85 + .../libDER/libDERUtils/fileIo.h | 29 + .../libDER/libDERUtils/libDERUtils.c | 36 + .../libDER/libDERUtils/libDERUtils.h | 29 + .../libDER/libDERUtils/printFields.c | 343 ++ .../libDER/libDERUtils/printFields.h | 57 + .../project.pbxproj | 1205 ++++ .../plist/iToolsTrustedApps.plist | 28 + .../xpc-tsa/XPCTimeStampingService-Info.plist | 54 + libsecurity_keychain/xpc-tsa/main-tsa.m | 302 + .../xpc-tsa/timestampclient.h | 50 + .../xpc-tsa/timestampclient.m | 98 + .../xpc/XPCKeychainSandboxCheck-Info.plist | 54 + libsecurity_keychain/xpc/main.c | 412 ++ libsecurity_manifest/APPLE_LICENSE | 335 ++ .../Info-security_manifest.plist | 5 + libsecurity_manifest/lib/AppleManifest.cpp | 857 +++ libsecurity_manifest/lib/AppleManifest.h | 76 + libsecurity_manifest/lib/Download.cpp | 409 ++ libsecurity_manifest/lib/Download.h | 88 + libsecurity_manifest/lib/Manifest.cpp | 49 + libsecurity_manifest/lib/Manifest.h | 61 + libsecurity_manifest/lib/ManifestInternal.cpp | 1162 ++++ libsecurity_manifest/lib/ManifestInternal.h | 279 + libsecurity_manifest/lib/ManifestSigner.cpp | 32 + libsecurity_manifest/lib/ManifestSigner.h | 52 + libsecurity_manifest/lib/SecManifest.cpp | 223 + libsecurity_manifest/lib/SecManifest.h | 215 + libsecurity_manifest/lib/SecureDownload.cpp | 189 + libsecurity_manifest/lib/SecureDownload.h | 224 + .../lib/SecureDownloadInternal.c | 877 +++ .../lib/SecureDownloadInternal.h | 24 + .../lib/security_manifest.exp | 41 + .../project.pbxproj | 327 ++ libsecurity_mds/Info-security_mds.plist | 5 + libsecurity_mds/README | 85 + libsecurity_mds/lib/MDSAttrParser.cpp | 612 ++ libsecurity_mds/lib/MDSAttrParser.h | 166 + libsecurity_mds/lib/MDSAttrStrings.cpp | 747 +++ libsecurity_mds/lib/MDSAttrStrings.h | 111 + libsecurity_mds/lib/MDSAttrUtils.cpp | 304 + libsecurity_mds/lib/MDSAttrUtils.h | 120 + libsecurity_mds/lib/MDSDatabase.cpp | 221 + libsecurity_mds/lib/MDSDatabase.h | 158 + libsecurity_mds/lib/MDSDictionary.cpp | 597 ++ libsecurity_mds/lib/MDSDictionary.h | 130 + libsecurity_mds/lib/MDSModule.cpp | 134 + libsecurity_mds/lib/MDSModule.h | 66 + libsecurity_mds/lib/MDSPrefs.cpp | 143 + libsecurity_mds/lib/MDSPrefs.h | 47 + libsecurity_mds/lib/MDSSchema.cpp | 823 +++ libsecurity_mds/lib/MDSSchema.h | 107 + libsecurity_mds/lib/MDSSession.cpp | 1863 ++++++ libsecurity_mds/lib/MDSSession.h | 177 + libsecurity_mds/lib/mds.h | 153 + libsecurity_mds/lib/mds_schema.h | 192 + libsecurity_mds/lib/mdsapi.cpp | 329 ++ libsecurity_mds/lib/mdspriv.h | 57 + libsecurity_mds/lib/security_mds.exp | 6 + .../libsecurity_mds.xcodeproj/project.pbxproj | 319 ++ libsecurity_ocspd/Info-security_ocspd.plist | 5 + libsecurity_ocspd/client/ocspdClient.cpp | 433 ++ libsecurity_ocspd/client/ocspdClient.h | 151 + libsecurity_ocspd/common/ocspExtensions.cpp | 200 + libsecurity_ocspd/common/ocspExtensions.h | 179 + libsecurity_ocspd/common/ocspResponse.cpp | 559 ++ libsecurity_ocspd/common/ocspResponse.h | 229 + libsecurity_ocspd/common/ocspdClient.h | 1 + libsecurity_ocspd/common/ocspdDbSchema.cpp | 54 + libsecurity_ocspd/common/ocspdDbSchema.h | 106 + libsecurity_ocspd/common/ocspdDebug.h | 66 + libsecurity_ocspd/common/ocspdTypes.h | 41 + libsecurity_ocspd/common/ocspdUtils.cpp | 329 ++ libsecurity_ocspd/common/ocspdUtils.h | 98 + .../project.pbxproj | 400 ++ libsecurity_ocspd/mig/mig.mk | 45 + libsecurity_ocspd/mig/ocspd.defs | 145 + libsecurity_pkcs12/APPLE_LICENSE | 335 ++ libsecurity_pkcs12/Info-security_pkcs12.plist | 5 + libsecurity_pkcs12/lib/SecPkcs12.cpp | 913 +++ libsecurity_pkcs12/lib/SecPkcs12.h | 571 ++ libsecurity_pkcs12/lib/pkcs12BagAttrs.cpp | 165 + libsecurity_pkcs12/lib/pkcs12BagAttrs.h | 123 + libsecurity_pkcs12/lib/pkcs12Coder.cpp | 415 ++ libsecurity_pkcs12/lib/pkcs12Coder.h | 419 ++ libsecurity_pkcs12/lib/pkcs12Crypto.cpp | 647 +++ libsecurity_pkcs12/lib/pkcs12Crypto.h | 172 + libsecurity_pkcs12/lib/pkcs12Debug.h | 48 + libsecurity_pkcs12/lib/pkcs12Decode.cpp | 532 ++ libsecurity_pkcs12/lib/pkcs12Encode.cpp | 497 ++ libsecurity_pkcs12/lib/pkcs12Keychain.cpp | 459 ++ libsecurity_pkcs12/lib/pkcs12SafeBag.cpp | 528 ++ libsecurity_pkcs12/lib/pkcs12SafeBag.h | 297 + libsecurity_pkcs12/lib/pkcs12Templates.cpp | 289 + libsecurity_pkcs12/lib/pkcs12Templates.h | 286 + libsecurity_pkcs12/lib/pkcs12Utils.cpp | 833 +++ libsecurity_pkcs12/lib/pkcs12Utils.h | 187 + libsecurity_pkcs12/lib/pkcs7Templates.cpp | 162 + libsecurity_pkcs12/lib/pkcs7Templates.h | 167 + libsecurity_pkcs12/lib/pkcsoids.cpp | 35 + libsecurity_pkcs12/lib/pkcsoids.h | 45 + .../project.pbxproj | 318 ++ libsecurity_sd_cspdl/APPLE_LICENSE | 335 ++ .../Info-security_sd_cspdl.plist | 5 + libsecurity_sd_cspdl/lib/SDCSPDLBuiltin.cpp | 37 + libsecurity_sd_cspdl/lib/SDCSPDLDatabase.cpp | 42 + libsecurity_sd_cspdl/lib/SDCSPDLDatabase.h | 46 + libsecurity_sd_cspdl/lib/SDCSPDLPlugin.cpp | 108 + libsecurity_sd_cspdl/lib/SDCSPDLPlugin.h | 69 + libsecurity_sd_cspdl/lib/SDCSPDLSession.cpp | 82 + libsecurity_sd_cspdl/lib/SDCSPDLSession.h | 53 + libsecurity_sd_cspdl/lib/SDCSPSession.cpp | 612 ++ libsecurity_sd_cspdl/lib/SDCSPSession.h | 179 + libsecurity_sd_cspdl/lib/SDContext.cpp | 604 ++ libsecurity_sd_cspdl/lib/SDContext.h | 174 + libsecurity_sd_cspdl/lib/SDDLSession.cpp | 517 ++ libsecurity_sd_cspdl/lib/SDDLSession.h | 156 + libsecurity_sd_cspdl/lib/SDFactory.cpp | 88 + libsecurity_sd_cspdl/lib/SDFactory.h | 45 + libsecurity_sd_cspdl/lib/SDKey.cpp | 344 ++ libsecurity_sd_cspdl/lib/SDKey.h | 86 + .../project.pbxproj | 318 ++ .../mds/sd_cspdl_common.mdsinfo | 30 + libsecurity_smime/APPLE_LICENSE | 335 ++ libsecurity_smime/Info-security_smime.plist | 5 + libsecurity_smime/TODO | 9 + .../docs/libsecurity_smime.plist | 24 + libsecurity_smime/docs/libsecurity_smime.txt | 146 + libsecurity_smime/lib/SecCmsBase.h | 511 ++ libsecurity_smime/lib/SecCmsContentInfo.h | 212 + libsecurity_smime/lib/SecCmsDecoder.h | 143 + libsecurity_smime/lib/SecCmsDigestContext.h | 78 + libsecurity_smime/lib/SecCmsDigestedData.h | 77 + libsecurity_smime/lib/SecCmsEncoder.h | 129 + libsecurity_smime/lib/SecCmsEncryptedData.h | 76 + libsecurity_smime/lib/SecCmsEnvelopedData.h | 80 + libsecurity_smime/lib/SecCmsMessage.h | 163 + libsecurity_smime/lib/SecCmsRecipientInfo.h | 81 + libsecurity_smime/lib/SecCmsSignedData.h | 197 + libsecurity_smime/lib/SecCmsSignerInfo.h | 247 + libsecurity_smime/lib/SecSMIME.h | 56 + libsecurity_smime/lib/SecSMIMEPriv.h | 170 + libsecurity_smime/lib/cert.c | 813 +++ libsecurity_smime/lib/cert.h | 117 + libsecurity_smime/lib/cmsarray.c | 214 + libsecurity_smime/lib/cmsasn1.c | 596 ++ libsecurity_smime/lib/cmsattr.c | 450 ++ libsecurity_smime/lib/cmscinfo.c | 420 ++ libsecurity_smime/lib/cmscipher.c | 1199 ++++ libsecurity_smime/lib/cmsdecode.c | 728 +++ libsecurity_smime/lib/cmsdigdata.c | 229 + libsecurity_smime/lib/cmsdigest.c | 261 + libsecurity_smime/lib/cmsencdata.c | 294 + libsecurity_smime/lib/cmsencode.c | 785 +++ libsecurity_smime/lib/cmsenvdata.c | 440 ++ libsecurity_smime/lib/cmslocal.h | 346 ++ libsecurity_smime/lib/cmsmessage.c | 362 ++ libsecurity_smime/lib/cmspriv.h | 501 ++ libsecurity_smime/lib/cmspubkey.c | 1449 +++++ libsecurity_smime/lib/cmsrecinfo.c | 703 +++ libsecurity_smime/lib/cmsreclist.c | 237 + libsecurity_smime/lib/cmsreclist.h | 57 + libsecurity_smime/lib/cmssigdata.c | 1184 ++++ libsecurity_smime/lib/cmssiginfo.c | 1407 +++++ libsecurity_smime/lib/cmstpriv.h | 502 ++ libsecurity_smime/lib/cmsutil.c | 412 ++ libsecurity_smime/lib/cryptohi.c | 552 ++ libsecurity_smime/lib/cryptohi.h | 143 + libsecurity_smime/lib/plhash.c | 538 ++ libsecurity_smime/lib/plhash.h | 164 + libsecurity_smime/lib/secalgid.c | 172 + libsecurity_smime/lib/secitem.c | 304 + libsecurity_smime/lib/secitem.h | 117 + libsecurity_smime/lib/secoid.c | 1483 +++++ libsecurity_smime/lib/secoid.h | 118 + libsecurity_smime/lib/secoidt.h | 61 + libsecurity_smime/lib/security_smime.exp | 133 + libsecurity_smime/lib/siginfoUtils.cpp | 62 + libsecurity_smime/lib/smimeutil.c | 801 +++ libsecurity_smime/lib/testcms | 43 + libsecurity_smime/lib/tsaSupport.c | 1400 +++++ libsecurity_smime/lib/tsaSupport.h | 54 + libsecurity_smime/lib/tsaSupportPriv.h | 59 + libsecurity_smime/lib/tsaTemplates.c | 252 + libsecurity_smime/lib/tsaTemplates.h | 129 + .../project.pbxproj | 502 ++ libsecurity_ssl/Info-security_ssl.plist | 5 + libsecurity_ssl/README | 45 + libsecurity_ssl/Security/CipherSuite.h | 217 + libsecurity_ssl/Security/SecureTransport.h | 1333 +++++ .../Security/SecureTransportPriv.h | 430 ++ libsecurity_ssl/config/base.xcconfig | 8 + libsecurity_ssl/config/debug.xcconfig | 3 + libsecurity_ssl/config/lib.xcconfig | 30 + libsecurity_ssl/config/release.xcconfig | 2 + libsecurity_ssl/lib/ModuleAttacher.c | 159 + libsecurity_ssl/lib/ModuleAttacher.h | 49 + libsecurity_ssl/lib/appleCdsa.c | 2147 +++++++ libsecurity_ssl/lib/appleCdsa.h | 222 + libsecurity_ssl/lib/appleSession.c | 468 ++ libsecurity_ssl/lib/appleSession.h | 55 + libsecurity_ssl/lib/cipherSpecs.c | 1589 ++++++ libsecurity_ssl/lib/cipherSpecs.h | 83 + libsecurity_ssl/lib/cryptType.h | 194 + libsecurity_ssl/lib/securetransport++.cpp | 307 + libsecurity_ssl/lib/securetransport++.h | 112 + libsecurity_ssl/lib/security_ssl.exp | 92 + libsecurity_ssl/lib/ssl.h | 36 + libsecurity_ssl/lib/ssl3Callouts.c | 789 +++ libsecurity_ssl/lib/sslAlertMessage.c | 413 ++ libsecurity_ssl/lib/sslAlertMessage.h | 91 + libsecurity_ssl/lib/sslBER.c | 371 ++ libsecurity_ssl/lib/sslBER.h | 100 + libsecurity_ssl/lib/sslBuildFlags.h | 101 + libsecurity_ssl/lib/sslCert.c | 788 +++ libsecurity_ssl/lib/sslChangeCipher.c | 139 + libsecurity_ssl/lib/sslContext.c | 2410 ++++++++ libsecurity_ssl/lib/sslContext.h | 441 ++ libsecurity_ssl/lib/sslCrypto.c | 1283 +++++ libsecurity_ssl/lib/sslCrypto.h | 233 + libsecurity_ssl/lib/sslDebug.h | 154 + libsecurity_ssl/lib/sslDigests.c | 411 ++ libsecurity_ssl/lib/sslDigests.h | 72 + libsecurity_ssl/lib/sslHandshake.c | 1362 +++++ libsecurity_ssl/lib/sslHandshake.h | 205 + libsecurity_ssl/lib/sslHandshakeFinish.c | 160 + libsecurity_ssl/lib/sslHandshakeHello.c | 960 ++++ libsecurity_ssl/lib/sslKeyExchange.c | 2008 +++++++ libsecurity_ssl/lib/sslKeychain.c | 478 ++ libsecurity_ssl/lib/sslKeychain.h | 74 + libsecurity_ssl/lib/sslMemory.c | 159 + libsecurity_ssl/lib/sslMemory.h | 71 + libsecurity_ssl/lib/sslNullCipher.c | 83 + libsecurity_ssl/lib/sslPriv.h | 89 + libsecurity_ssl/lib/sslRecord.c | 308 + libsecurity_ssl/lib/sslRecord.h | 75 + libsecurity_ssl/lib/sslSession.c | 359 ++ libsecurity_ssl/lib/sslSession.h | 60 + libsecurity_ssl/lib/sslTransport.c | 594 ++ libsecurity_ssl/lib/sslUtils.c | 318 ++ libsecurity_ssl/lib/sslUtils.h | 143 + libsecurity_ssl/lib/symCipher.c | 112 + libsecurity_ssl/lib/symCipher.h | 61 + libsecurity_ssl/lib/tls1Callouts.c | 870 +++ libsecurity_ssl/lib/tls_hmac.c | 527 ++ libsecurity_ssl/lib/tls_hmac.h | 112 + libsecurity_ssl/lib/tls_ssl.h | 134 + .../libsecurity_ssl.xcodeproj/project.pbxproj | 476 ++ libsecurity_ssl/security_ssl | 1 + 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/printCert.c | 218 + libsecurity_ssl/sslViewer/printCert.h | 48 + libsecurity_ssl/sslViewer/sslAppUtils.cpp | 1646 ++++++ libsecurity_ssl/sslViewer/sslAppUtils.h | 163 + libsecurity_ssl/sslViewer/sslServer.1 | 79 + libsecurity_ssl/sslViewer/sslServer.cpp | 1062 ++++ libsecurity_ssl/sslViewer/sslViewer.1 | 79 + libsecurity_ssl/sslViewer/sslViewer.cpp | 1870 ++++++ .../sslViewer.xcodeproj/project.pbxproj | 454 ++ libsecurity_transform/100-sha2.m | 337 ++ .../libsecurity_transform.Default.xcconfig | 5 + .../libsecurity_transform_Deployment.xcconfig | 2 + ...libsecurity_transform_Development.xcconfig | 6 + .../libsecurity_transform_core.xcconfig | 26 + .../security_transform_Default.xcconfig | 8 + .../security_transform_Deployment.xcconfig | 10 + .../security_transform_Development.xcconfig | 13 + .../Info-security_transform.plist | 5 + libsecurity_transform/NSData+HexString.h | 12 + libsecurity_transform/NSData+HexString.m | 31 + libsecurity_transform/custom.h | 16 + libsecurity_transform/custom.mm | 5060 +++++++++++++++++ libsecurity_transform/lib/CEncryptDecrypt.c | 73 + .../lib/CoreFoundationBasics.cpp | 283 + .../lib/CoreFoundationBasics.h | 70 + libsecurity_transform/lib/Digest.cpp | 592 ++ libsecurity_transform/lib/Digest.h | 202 + libsecurity_transform/lib/Digest_block.c | 85 + libsecurity_transform/lib/Digest_block.h | 9 + .../lib/EncodeDecodeTransforms.c | 1001 ++++ .../lib/EncryptTransform.cpp | 1098 ++++ libsecurity_transform/lib/EncryptTransform.h | 132 + .../lib/EncryptTransformUtilities.cpp | 189 + .../lib/EncryptTransformUtilities.h | 87 + libsecurity_transform/lib/GroupTransform.cpp | 542 ++ libsecurity_transform/lib/GroupTransform.h | 59 + libsecurity_transform/lib/LinkedList.cpp | 29 + libsecurity_transform/lib/LinkedList.h | 22 + libsecurity_transform/lib/Monitor.cpp | 108 + libsecurity_transform/lib/Monitor.h | 43 + libsecurity_transform/lib/NullTransform.cpp | 61 + libsecurity_transform/lib/NullTransform.h | 26 + .../lib/SecCollectTransform.cpp | 252 + .../lib/SecCollectTransform.h | 60 + .../lib/SecCustomTransform.cpp | 1134 ++++ .../lib/SecCustomTransform.h | 943 +++ .../lib/SecDecodeTransform.h | 74 + .../lib/SecDigestTransform.cpp | 49 + .../lib/SecDigestTransform.h | 150 + .../lib/SecEncodeTransform.h | 113 + .../lib/SecEncryptTransform.cpp | 94 + .../lib/SecEncryptTransform.h | 185 + .../lib/SecExternalSourceTransform.cpp | 41 + .../lib/SecExternalSourceTransform.h | 65 + .../lib/SecGroupTransform.cpp | 36 + libsecurity_transform/lib/SecGroupTransform.h | 23 + .../lib/SecMaskGenerationFunctionTransform.c | 162 + .../lib/SecMaskGenerationFunctionTransform.h | 64 + .../lib/SecNullTransform.cpp | 9 + libsecurity_transform/lib/SecNullTransform.h | 25 + libsecurity_transform/lib/SecReadTransform.h | 2 + .../lib/SecSignVerifyTransform.c | 702 +++ .../lib/SecSignVerifyTransform.h | 95 + libsecurity_transform/lib/SecTransform.cpp | 545 ++ libsecurity_transform/lib/SecTransform.h | 618 ++ .../lib/SecTransformInternal.h | 33 + .../lib/SecTransformReadTransform.cpp | 124 + .../lib/SecTransformReadTransform.h | 66 + .../lib/SecTransformValidator.h | 48 + .../lib/SingleShotSource.cpp | 61 + libsecurity_transform/lib/SingleShotSource.h | 25 + libsecurity_transform/lib/Source.cpp | 96 + libsecurity_transform/lib/Source.h | 33 + libsecurity_transform/lib/StreamSource.cpp | 124 + libsecurity_transform/lib/StreamSource.h | 36 + libsecurity_transform/lib/Transform.cpp | 1842 ++++++ libsecurity_transform/lib/Transform.h | 241 + .../lib/TransformFactory.cpp | 123 + libsecurity_transform/lib/TransformFactory.h | 36 + libsecurity_transform/lib/Utilities.cpp | 116 + libsecurity_transform/lib/Utilities.h | 69 + libsecurity_transform/lib/c++utils.cpp | 59 + libsecurity_transform/lib/c++utils.h | 27 + libsecurity_transform/lib/misc.c | 145 + libsecurity_transform/lib/misc.h | 36 + .../lib/security_transform.exp | 99 + .../project.pbxproj | 863 +++ libsecurity_transform/misc/base32alpha2vals | 29 + libsecurity_transform/misc/speed-test.h | 16 + libsecurity_transform/misc/speed-test.mm | 92 + libsecurity_transform/unit-tests-Info.plist | 22 + libsecurity_utilities/APPLE_LICENSE | 335 ++ .../Info-security_utilities.plist | 5 + libsecurity_utilities/lib/adornments.cpp | 93 + libsecurity_utilities/lib/adornments.h | 202 + libsecurity_utilities/lib/alloc.cpp | 159 + libsecurity_utilities/lib/alloc.h | 240 + libsecurity_utilities/lib/blob.cpp | 130 + libsecurity_utilities/lib/blob.h | 208 + libsecurity_utilities/lib/bufferfifo.cpp | 94 + libsecurity_utilities/lib/bufferfifo.h | 76 + libsecurity_utilities/lib/buffers.cpp | 106 + libsecurity_utilities/lib/buffers.h | 162 + libsecurity_utilities/lib/ccaudit.cpp | 152 + libsecurity_utilities/lib/ccaudit.h | 189 + libsecurity_utilities/lib/cfclass.cpp | 250 + libsecurity_utilities/lib/cfclass.h | 55 + libsecurity_utilities/lib/cfmach++.cpp | 129 + libsecurity_utilities/lib/cfmach++.h | 71 + libsecurity_utilities/lib/cfmunge.cpp | 597 ++ libsecurity_utilities/lib/cfmunge.h | 136 + libsecurity_utilities/lib/cfutilities.cpp | 269 + libsecurity_utilities/lib/cfutilities.h | 608 ++ libsecurity_utilities/lib/coderepository.cpp | 90 + libsecurity_utilities/lib/coderepository.h | 110 + libsecurity_utilities/lib/crc.c | 61 + libsecurity_utilities/lib/crc.h | 18 + libsecurity_utilities/lib/daemon.cpp | 112 + libsecurity_utilities/lib/daemon.h | 43 + libsecurity_utilities/lib/debugging.cpp | 517 ++ libsecurity_utilities/lib/debugging.h | 154 + libsecurity_utilities/lib/debugsupport.h | 210 + libsecurity_utilities/lib/devrandom.cpp | 82 + libsecurity_utilities/lib/devrandom.h | 67 + libsecurity_utilities/lib/dtrace.mk | 2 + libsecurity_utilities/lib/dyld_cache_format.h | 69 + libsecurity_utilities/lib/dyldcache.cpp | 138 + libsecurity_utilities/lib/dyldcache.h | 154 + libsecurity_utilities/lib/endian.cpp | 33 + libsecurity_utilities/lib/endian.h | 139 + libsecurity_utilities/lib/errors.cpp | 157 + libsecurity_utilities/lib/errors.h | 124 + libsecurity_utilities/lib/fdmover.cpp | 104 + libsecurity_utilities/lib/fdmover.h | 93 + libsecurity_utilities/lib/fdsel.cpp | 96 + libsecurity_utilities/lib/fdsel.h | 80 + libsecurity_utilities/lib/globalizer.cpp | 150 + libsecurity_utilities/lib/globalizer.h | 201 + libsecurity_utilities/lib/hashing.cpp | 53 + libsecurity_utilities/lib/hashing.h | 186 + libsecurity_utilities/lib/headermap.cpp | 150 + libsecurity_utilities/lib/headermap.h | 93 + libsecurity_utilities/lib/hosts.cpp | 151 + libsecurity_utilities/lib/hosts.h | 82 + libsecurity_utilities/lib/inetreply.cpp | 91 + libsecurity_utilities/lib/inetreply.h | 100 + libsecurity_utilities/lib/iodevices.cpp | 272 + libsecurity_utilities/lib/iodevices.h | 166 + libsecurity_utilities/lib/ip++.cpp | 381 ++ libsecurity_utilities/lib/ip++.h | 278 + libsecurity_utilities/lib/kq++.cpp | 69 + libsecurity_utilities/lib/kq++.h | 95 + libsecurity_utilities/lib/ktracecodes.h | 144 + libsecurity_utilities/lib/logging.cpp | 112 + libsecurity_utilities/lib/logging.h | 73 + libsecurity_utilities/lib/mach++.cpp | 456 ++ libsecurity_utilities/lib/mach++.h | 325 ++ libsecurity_utilities/lib/mach_notify.c | 542 ++ libsecurity_utilities/lib/mach_notify.h | 136 + libsecurity_utilities/lib/macho++.cpp | 612 ++ libsecurity_utilities/lib/macho++.h | 221 + .../lib/machrunloopserver.cpp | 111 + libsecurity_utilities/lib/machrunloopserver.h | 80 + libsecurity_utilities/lib/machserver.cpp | 606 ++ libsecurity_utilities/lib/machserver.h | 250 + libsecurity_utilities/lib/memstreams.h | 168 + libsecurity_utilities/lib/memutils.h | 124 + libsecurity_utilities/lib/muscle++.cpp | 256 + libsecurity_utilities/lib/muscle++.h | 198 + libsecurity_utilities/lib/osxcode.cpp | 260 + libsecurity_utilities/lib/osxcode.h | 136 + libsecurity_utilities/lib/pcsc++.cpp | 416 ++ libsecurity_utilities/lib/pcsc++.h | 199 + libsecurity_utilities/lib/powerwatch.cpp | 235 + libsecurity_utilities/lib/powerwatch.h | 112 + libsecurity_utilities/lib/refcount.h | 153 + libsecurity_utilities/lib/seccfobject.cpp | 263 + libsecurity_utilities/lib/seccfobject.h | 175 + .../lib/security_utilities.d | 84 + .../lib/security_utilities.h | 67 + libsecurity_utilities/lib/selector.cpp | 204 + libsecurity_utilities/lib/selector.h | 125 + libsecurity_utilities/lib/simpleprefs.cpp | 496 ++ libsecurity_utilities/lib/simpleprefs.h | 206 + libsecurity_utilities/lib/socks++.cpp | 162 + libsecurity_utilities/lib/socks++.h | 222 + libsecurity_utilities/lib/socks++4.cpp | 134 + libsecurity_utilities/lib/socks++4.h | 86 + libsecurity_utilities/lib/socks++5.cpp | 208 + libsecurity_utilities/lib/socks++5.h | 125 + libsecurity_utilities/lib/sqlite++.cpp | 431 ++ libsecurity_utilities/lib/sqlite++.h | 283 + libsecurity_utilities/lib/streams.cpp | 144 + libsecurity_utilities/lib/streams.h | 192 + libsecurity_utilities/lib/superblob.cpp | 10 + libsecurity_utilities/lib/superblob.h | 237 + libsecurity_utilities/lib/threading.cpp | 265 + libsecurity_utilities/lib/threading.h | 358 ++ .../lib/threading_internal.h | 125 + libsecurity_utilities/lib/timeflow.cpp | 117 + libsecurity_utilities/lib/timeflow.h | 162 + libsecurity_utilities/lib/tqueue.cpp | 33 + libsecurity_utilities/lib/tqueue.h | 141 + .../lib/trackingallocator.cpp | 89 + libsecurity_utilities/lib/trackingallocator.h | 65 + libsecurity_utilities/lib/transactions.cpp | 54 + libsecurity_utilities/lib/transactions.h | 107 + libsecurity_utilities/lib/typedvalue.cpp | 38 + libsecurity_utilities/lib/typedvalue.h | 86 + libsecurity_utilities/lib/unix++.cpp | 477 ++ libsecurity_utilities/lib/unix++.h | 333 ++ libsecurity_utilities/lib/unixchild.cpp | 502 ++ libsecurity_utilities/lib/unixchild.h | 136 + libsecurity_utilities/lib/url.cpp | 150 + libsecurity_utilities/lib/url.h | 82 + libsecurity_utilities/lib/utilities.cpp | 125 + libsecurity_utilities/lib/utilities.h | 315 + libsecurity_utilities/lib/utility_config.h | 113 + libsecurity_utilities/lib/vproc++.cpp | 55 + libsecurity_utilities/lib/vproc++.h | 63 + .../project.pbxproj | 843 +++ libsecurityd/APPLE_LICENSE | 335 ++ libsecurityd/Info-securityd_client.plist | 5 + libsecurityd/Info-securityd_server.plist | 5 + libsecurityd/lib/SharedMemoryClient.cpp | 189 + libsecurityd/lib/SharedMemoryClient.h | 46 + libsecurityd/lib/SharedMemoryCommon.h | 20 + libsecurityd/lib/dictionary.cpp | 365 ++ libsecurityd/lib/dictionary.h | 98 + libsecurityd/lib/eventlistener.cpp | 310 + libsecurityd/lib/eventlistener.h | 62 + libsecurityd/lib/handletypes.h | 86 + libsecurityd/lib/sec_xdr.c | 293 + libsecurityd/lib/sec_xdr.h | 70 + libsecurityd/lib/sec_xdr_array.c | 170 + libsecurityd/lib/sec_xdr_reference.c | 158 + libsecurityd/lib/sec_xdr_sizeof.c | 217 + libsecurityd/lib/sec_xdrmem.c | 287 + libsecurityd/lib/ss_types.h | 105 + libsecurityd/lib/ssblob.cpp | 80 + libsecurityd/lib/ssblob.h | 224 + libsecurityd/lib/ssclient.cpp | 223 + libsecurityd/lib/ssclient.h | 452 ++ libsecurityd/lib/sscommon.h | 104 + libsecurityd/lib/ssnotify.h | 118 + libsecurityd/lib/sstransit.cpp | 173 + libsecurityd/lib/sstransit.h | 136 + libsecurityd/lib/transition.cpp | 1042 ++++ libsecurityd/lib/ucsp_types.h | 43 + libsecurityd/lib/xdr_auth.c | 83 + libsecurityd/lib/xdr_auth.h | 41 + libsecurityd/lib/xdr_cssm.c | 845 +++ libsecurityd/lib/xdr_cssm.h | 222 + libsecurityd/lib/xdr_dldb.cpp | 56 + libsecurityd/lib/xdr_dldb.h | 74 + .../libsecurityd.xcodeproj/project.pbxproj | 766 +++ libsecurityd/mig/cshosting.defs | 56 + libsecurityd/mig/mig.mk | 61 + libsecurityd/mig/ss_types.defs | 194 + libsecurityd/mig/ucsp.defs | 331 ++ libsecurityd/mig/ucspNotify.defs | 50 + sec/Security/SecBase.h | 90 + sec/Security/SecBase64.c | 489 ++ sec/Security/SecBase64.h | 247 + sec/Security/SecBasePriv.h | 129 + sec/Security/SecCMS.c | 664 +++ sec/Security/SecCMS.h | 175 + sec/Security/SecCertificate.c | 4817 ++++++++++++++++ sec/Security/SecCertificate.h | 91 + sec/Security/SecCertificateInternal.h | 310 + sec/Security/SecCertificatePath.c | 545 ++ sec/Security/SecCertificatePath.h | 126 + sec/Security/SecCertificatePriv.h | 177 + sec/Security/SecCertificateRequest.c | 1113 ++++ sec/Security/SecCertificateRequest.h | 127 + sec/Security/SecDH.c | 302 + sec/Security/SecDH.h | 164 + sec/Security/SecECKey.c | 579 ++ sec/Security/SecECKey.h | 83 + sec/Security/SecFramework.c | 254 + sec/Security/SecFramework.h | 68 + sec/Security/SecFrameworkStrings.h | 189 + sec/Security/SecIdentity.c | 136 + sec/Security/SecIdentity.h | 79 + sec/Security/SecIdentityPriv.h | 52 + sec/Security/SecImportExport.c | 159 + sec/Security/SecImportExport.h | 98 + sec/Security/SecInternal.h | 84 + sec/Security/SecItem.c | 763 +++ sec/Security/SecItem.h | 921 +++ sec/Security/SecItemConstants.c | 207 + sec/Security/SecItemInternal.h | 51 + sec/Security/SecItemPriv.h | 344 ++ sec/Security/SecKey.c | 946 +++ sec/Security/SecKey.h | 280 + sec/Security/SecKeyInternal.h | 44 + sec/Security/SecKeyPriv.h | 266 + sec/Security/SecPBKDF.c | 59 + sec/Security/SecPBKDF.h | 60 + sec/Security/SecPolicy.c | 1184 ++++ sec/Security/SecPolicy.h | 80 + sec/Security/SecPolicyInternal.h | 122 + sec/Security/SecPolicyPriv.h | 247 + sec/Security/SecRSAKey.c | 1094 ++++ sec/Security/SecRSAKey.h | 67 + sec/Security/SecRSAKeyPriv.h | 46 + sec/Security/SecRandom.h | 65 + sec/Security/SecSCEP.c | 881 +++ sec/Security/SecSCEP.h | 120 + sec/Security/SecTrust.c | 1159 ++++ sec/Security/SecTrust.h | 270 + sec/Security/SecTrustPriv.h | 209 + sec/Security/SecTrustSettings.c | 565 ++ sec/Security/SecTrustSettings.h | 247 + sec/Security/SecTrustSettingsPriv.h | 218 + sec/Security/SecTrustStore.c | 129 + sec/Security/SecTrustStore.h | 63 + sec/Security/Security.h | 32 + sec/Security/certextensions.h | 546 ++ sec/Security/p12import.c | 508 ++ sec/Security/p12import.h | 52 + sec/Security/p12pbegen.c | 345 ++ sec/Security/p12pbegen.h | 35 + sec/Security/pbkdf2.c | 105 + sec/Security/pbkdf2.h | 78 + sec/Security/vmdh.c | 62 + sec/Security/vmdh.h | 62 + sec/config/base.xcconfig | 8 + sec/config/debug.xcconfig | 3 + sec/config/lib.xcconfig | 30 + sec/config/release.xcconfig | 4 + sec/ipc/client.c | 331 ++ sec/ipc/com.apple.secd.plist | 23 + sec/ipc/com.apple.securityd.plist | 29 + sec/ipc/securityd_client.h | 93 + sec/ipc/securityd_ipc_types.h | 28 + sec/ipc/securityd_rep.defs | 39 + sec/ipc/securityd_req.defs | 40 + sec/ipc/securityd_server.h | 36 + sec/ipc/server.c | 667 +++ sec/sec.xcodeproj/project.pbxproj | 731 +++ sec/securityd/SecCAIssuerCache.c | 442 ++ sec/securityd/SecCAIssuerCache.h | 60 + sec/securityd/SecCAIssuerRequest.c | 200 + sec/securityd/SecCAIssuerRequest.h | 14 + sec/securityd/SecItemServer.c | 4768 ++++++++++++++++ sec/securityd/SecItemServer.h | 56 + sec/securityd/SecOCSPCache.c | 550 ++ sec/securityd/SecOCSPCache.h | 238 + sec/securityd/SecOCSPRequest.c | 159 + sec/securityd/SecOCSPRequest.h | 82 + sec/securityd/SecOCSPResponse.c | 635 +++ sec/securityd/SecOCSPResponse.h | 160 + sec/securityd/SecPolicyServer.c | 2592 +++++++++ sec/securityd/SecPolicyServer.h | 129 + sec/securityd/SecTrustServer.c | 1257 ++++ sec/securityd/SecTrustServer.h | 99 + sec/securityd/SecTrustStoreServer.c | 477 ++ sec/securityd/SecTrustStoreServer.h | 59 + sec/securityd/asynchttp.c | 460 ++ sec/securityd/asynchttp.h | 72 + sec/securityd/entitlements.plist | 10 + sec/securityd/keystore.c | 237 + sec/securityd/keystore.h | 160 + sec/securityd/policytree.c | 298 + sec/securityd/policytree.h | 88 + sec/securityd/spi.c | 36 + sec/securityd/spi.h | 39 + security_utilities/debugging.c | 145 + security_utilities/debugging.h | 61 + security_utilities/fileIo.c | 97 + security_utilities/fileIo.h | 26 + security_utilities/sqlutils.h | 37 + 1927 files changed, 508483 insertions(+), 1993 deletions(-) create mode 100644 Security.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings create mode 100644 Security.xcodeproj/xcshareddata/xcschemes/Security.xcscheme create mode 100644 Security.xcodeproj/xcshareddata/xcschemes/Security_executables.xcscheme create mode 100644 Security.xcodeproj/xcshareddata/xcschemes/Security_frameworks.xcscheme create mode 100644 Security.xcodeproj/xcshareddata/xcschemes/World.xcscheme create mode 100644 Security.xcodeproj/xcshareddata/xcschemes/copyHeaders.xcscheme create mode 100644 Security.xcodeproj/xcshareddata/xcschemes/secd.xcscheme create mode 100644 config/base.xcconfig create mode 100644 config/debug.xcconfig create mode 100644 config/lib.xcconfig create mode 100644 config/release.xcconfig create mode 100644 config/security.xcconfig create mode 120000 include/security_agent_client create mode 120000 include/security_asn1 create mode 120000 include/security_cdsa_client create mode 120000 include/security_cdsa_plugin create mode 120000 include/security_cdsa_utilities create mode 120000 include/security_cdsa_utils create mode 120000 include/security_codesigning create mode 120000 include/security_comcryption create mode 120000 include/security_cryptkit create mode 120000 include/security_filedb create mode 120000 include/security_keychain create mode 120000 include/security_ocspd create mode 120000 include/security_pkcs12 create mode 120000 include/security_smime create mode 120000 include/security_utilities create mode 120000 include/securityd_client rename FDEPrefs.plist => lib/FDEPrefs.plist (74%) rename Info-Security.plist => lib/Info-Security.plist (96%) rename {intl/English.lproj => lib/en.lproj}/FDELocalizable.strings (100%) rename {intl/English.lproj => lib/en.lproj}/InfoPlist.strings (100%) rename {plugins => lib/plugins}/csparser-Info.plist (96%) rename {plugins => lib/plugins}/csparser.cpp (100%) rename {plugins => lib/plugins}/csparser.exp (100%) create mode 100644 libsecurity_apple_csp/Info-security_apple_csp.plist create mode 100644 libsecurity_apple_csp/README create mode 100644 libsecurity_apple_csp/TODO create mode 100644 libsecurity_apple_csp/docs/libsecurity_apple_csp.plist create mode 100644 libsecurity_apple_csp/docs/libsecurity_apple_csp.txt create mode 100644 libsecurity_apple_csp/lib/AppleCSP.cpp create mode 100644 libsecurity_apple_csp/lib/AppleCSP.h create mode 100644 libsecurity_apple_csp/lib/AppleCSPBuiltin.cpp create mode 100644 libsecurity_apple_csp/lib/AppleCSPContext.cpp create mode 100644 libsecurity_apple_csp/lib/AppleCSPContext.h create mode 100644 libsecurity_apple_csp/lib/AppleCSPKeys.cpp create mode 100644 libsecurity_apple_csp/lib/AppleCSPKeys.h create mode 100644 libsecurity_apple_csp/lib/AppleCSPPlugin.cpp create mode 100644 libsecurity_apple_csp/lib/AppleCSPSession.h create mode 100644 libsecurity_apple_csp/lib/AppleCSPUtils.cpp create mode 100644 libsecurity_apple_csp/lib/AppleCSPUtils.h create mode 100644 libsecurity_apple_csp/lib/BinaryKey.h create mode 100644 libsecurity_apple_csp/lib/BlockCryptor.cpp create mode 100644 libsecurity_apple_csp/lib/BlockCryptor.h create mode 100755 libsecurity_apple_csp/lib/CryptKitSpace.h create mode 100644 libsecurity_apple_csp/lib/DH_csp.cpp create mode 100644 libsecurity_apple_csp/lib/DH_csp.h create mode 100644 libsecurity_apple_csp/lib/DH_exchange.cpp create mode 100644 libsecurity_apple_csp/lib/DH_exchange.h create mode 100644 libsecurity_apple_csp/lib/DH_keys.cpp create mode 100644 libsecurity_apple_csp/lib/DH_keys.h create mode 100644 libsecurity_apple_csp/lib/DH_utils.cpp create mode 100644 libsecurity_apple_csp/lib/DH_utils.h create mode 100644 libsecurity_apple_csp/lib/DigestContext.cpp create mode 100644 libsecurity_apple_csp/lib/DigestContext.h create mode 100644 libsecurity_apple_csp/lib/FEEAsymmetricContext.cpp create mode 100644 libsecurity_apple_csp/lib/FEEAsymmetricContext.h create mode 100644 libsecurity_apple_csp/lib/FEECSPUtils.cpp create mode 100644 libsecurity_apple_csp/lib/FEECSPUtils.h create mode 100644 libsecurity_apple_csp/lib/FEEKeys.cpp create mode 100644 libsecurity_apple_csp/lib/FEEKeys.h create mode 100644 libsecurity_apple_csp/lib/FEESignatureObject.cpp create mode 100644 libsecurity_apple_csp/lib/FEESignatureObject.h create mode 100644 libsecurity_apple_csp/lib/HMACSHA1.c create mode 100644 libsecurity_apple_csp/lib/HMACSHA1.h create mode 100644 libsecurity_apple_csp/lib/MD2Object.cpp create mode 100644 libsecurity_apple_csp/lib/MD2Object.h create mode 100644 libsecurity_apple_csp/lib/MacContext.cpp create mode 100644 libsecurity_apple_csp/lib/MacContext.h create mode 100644 libsecurity_apple_csp/lib/NullCryptor.h create mode 100644 libsecurity_apple_csp/lib/RSA_DSA_csp.cpp create mode 100644 libsecurity_apple_csp/lib/RSA_DSA_csp.h create mode 100644 libsecurity_apple_csp/lib/RSA_DSA_keys.cpp create mode 100644 libsecurity_apple_csp/lib/RSA_DSA_keys.h create mode 100644 libsecurity_apple_csp/lib/RSA_DSA_signature.cpp create mode 100644 libsecurity_apple_csp/lib/RSA_DSA_signature.h create mode 100644 libsecurity_apple_csp/lib/RSA_DSA_utils.cpp create mode 100644 libsecurity_apple_csp/lib/RSA_DSA_utils.h create mode 100644 libsecurity_apple_csp/lib/RSA_asymmetric.cpp create mode 100644 libsecurity_apple_csp/lib/RSA_asymmetric.h create mode 100644 libsecurity_apple_csp/lib/RawSigner.h create mode 100644 libsecurity_apple_csp/lib/SHA1_MD5_Object.cpp create mode 100644 libsecurity_apple_csp/lib/SHA1_MD5_Object.h create mode 100644 libsecurity_apple_csp/lib/SHA2_Object.cpp create mode 100644 libsecurity_apple_csp/lib/SHA2_Object.h create mode 100644 libsecurity_apple_csp/lib/SignatureContext.cpp create mode 100644 libsecurity_apple_csp/lib/SignatureContext.h create mode 100644 libsecurity_apple_csp/lib/YarrowConnection.cpp create mode 100644 libsecurity_apple_csp/lib/YarrowConnection.h create mode 100644 libsecurity_apple_csp/lib/aesCommon.h create mode 100644 libsecurity_apple_csp/lib/aescsp.cpp create mode 100644 libsecurity_apple_csp/lib/aescspi.h create mode 100644 libsecurity_apple_csp/lib/algmaker.cpp create mode 100644 libsecurity_apple_csp/lib/ascContext.cpp create mode 100644 libsecurity_apple_csp/lib/ascContext.h create mode 100644 libsecurity_apple_csp/lib/ascFactory.h create mode 100644 libsecurity_apple_csp/lib/bfContext.cpp create mode 100644 libsecurity_apple_csp/lib/bfContext.h create mode 100644 libsecurity_apple_csp/lib/boxes-ref.c create mode 100644 libsecurity_apple_csp/lib/boxes-ref.h create mode 100644 libsecurity_apple_csp/lib/bsafeAsymmetric.cpp create mode 100644 libsecurity_apple_csp/lib/bsafeContext.cpp create mode 100644 libsecurity_apple_csp/lib/bsafeKeyGen.cpp create mode 100644 libsecurity_apple_csp/lib/bsafePKCS1.cpp create mode 100644 libsecurity_apple_csp/lib/bsafePKCS1.h create mode 100644 libsecurity_apple_csp/lib/bsafeSymmetric.cpp create mode 100644 libsecurity_apple_csp/lib/bsafecsp.h create mode 100644 libsecurity_apple_csp/lib/bsafecspi.h create mode 100644 libsecurity_apple_csp/lib/bsobjects.h create mode 100644 libsecurity_apple_csp/lib/castContext.cpp create mode 100644 libsecurity_apple_csp/lib/castContext.h create mode 100644 libsecurity_apple_csp/lib/cryptkitcsp.cpp create mode 100644 libsecurity_apple_csp/lib/cryptkitcsp.h create mode 100644 libsecurity_apple_csp/lib/cspdebugging.c create mode 100644 libsecurity_apple_csp/lib/cspdebugging.h create mode 100644 libsecurity_apple_csp/lib/cssmplugin.exp create mode 100644 libsecurity_apple_csp/lib/deriveKey.cpp create mode 100644 libsecurity_apple_csp/lib/desContext.cpp create mode 100644 libsecurity_apple_csp/lib/desContext.h create mode 100644 libsecurity_apple_csp/lib/gladmanContext.cpp create mode 100644 libsecurity_apple_csp/lib/gladmanContext.h create mode 100644 libsecurity_apple_csp/lib/memory.cpp create mode 100644 libsecurity_apple_csp/lib/miscAlgFactory.cpp create mode 100644 libsecurity_apple_csp/lib/miscAlgFactory.h create mode 100644 libsecurity_apple_csp/lib/miscalgorithms.cpp create mode 100644 libsecurity_apple_csp/lib/opensshCoding.cpp create mode 100644 libsecurity_apple_csp/lib/opensshCoding.h create mode 100644 libsecurity_apple_csp/lib/opensshWrap.cpp create mode 100644 libsecurity_apple_csp/lib/pbkdDigest.cpp create mode 100644 libsecurity_apple_csp/lib/pbkdDigest.h create mode 100644 libsecurity_apple_csp/lib/pbkdf2.c create mode 100644 libsecurity_apple_csp/lib/pbkdf2.h create mode 100644 libsecurity_apple_csp/lib/pkcs12Derive.cpp create mode 100644 libsecurity_apple_csp/lib/pkcs12Derive.h create mode 100644 libsecurity_apple_csp/lib/pkcs8.cpp create mode 100644 libsecurity_apple_csp/lib/pkcs8.h create mode 100644 libsecurity_apple_csp/lib/rc2Context.cpp create mode 100644 libsecurity_apple_csp/lib/rc2Context.h create mode 100644 libsecurity_apple_csp/lib/rc4Context.cpp create mode 100644 libsecurity_apple_csp/lib/rc4Context.h create mode 100644 libsecurity_apple_csp/lib/rc5Context.cpp create mode 100644 libsecurity_apple_csp/lib/rc5Context.h create mode 100644 libsecurity_apple_csp/lib/rijndael-alg-ref.c create mode 100644 libsecurity_apple_csp/lib/rijndael-alg-ref.h create mode 100644 libsecurity_apple_csp/lib/rijndaelApi.c create mode 100644 libsecurity_apple_csp/lib/rijndaelApi.h create mode 100644 libsecurity_apple_csp/lib/vRijndael-alg-ref.c create mode 100644 libsecurity_apple_csp/lib/wrapKey.cpp create mode 100644 libsecurity_apple_csp/lib/wrapKeyCms.cpp create mode 100644 libsecurity_apple_csp/libsecurity_apple_csp.xcodeproj/project.pbxproj create mode 100644 libsecurity_apple_csp/mds/csp_capabilities.mdsinfo create mode 100644 libsecurity_apple_csp/mds/csp_capabilities_common.mds create mode 100644 libsecurity_apple_csp/mds/csp_common.mdsinfo create mode 100644 libsecurity_apple_csp/mds/csp_primary.mdsinfo create mode 100644 libsecurity_apple_csp/open_ssl/LICENSE create mode 100644 libsecurity_apple_csp/open_ssl/bf/COPYRIGHT create mode 100644 libsecurity_apple_csp/open_ssl/bf/README create mode 100644 libsecurity_apple_csp/open_ssl/bf/bf_ecb.c create mode 100644 libsecurity_apple_csp/open_ssl/bf/bf_enc.c create mode 100644 libsecurity_apple_csp/open_ssl/bf/bf_locl.h create mode 100644 libsecurity_apple_csp/open_ssl/bf/bf_pi.h create mode 100644 libsecurity_apple_csp/open_ssl/bf/bf_skey.c create mode 100644 libsecurity_apple_csp/open_ssl/bio/bio_lib.c create mode 100644 libsecurity_apple_csp/open_ssl/bio/bss_file.c create mode 100644 libsecurity_apple_csp/open_ssl/bn/bn_add.c create mode 100644 libsecurity_apple_csp/open_ssl/bn/bn_asm.c create mode 100644 libsecurity_apple_csp/open_ssl/bn/bn_blind.c create mode 100644 libsecurity_apple_csp/open_ssl/bn/bn_ctx.c create mode 100644 libsecurity_apple_csp/open_ssl/bn/bn_div.c create mode 100644 libsecurity_apple_csp/open_ssl/bn/bn_err.c create mode 100644 libsecurity_apple_csp/open_ssl/bn/bn_exp.c create mode 100644 libsecurity_apple_csp/open_ssl/bn/bn_exp2.c create mode 100644 libsecurity_apple_csp/open_ssl/bn/bn_gcd.c create mode 100644 libsecurity_apple_csp/open_ssl/bn/bn_lcl.h create mode 100644 libsecurity_apple_csp/open_ssl/bn/bn_lib.c create mode 100644 libsecurity_apple_csp/open_ssl/bn/bn_mont.c create mode 100644 libsecurity_apple_csp/open_ssl/bn/bn_mpi.c create mode 100644 libsecurity_apple_csp/open_ssl/bn/bn_mul.c create mode 100644 libsecurity_apple_csp/open_ssl/bn/bn_prime.c create mode 100644 libsecurity_apple_csp/open_ssl/bn/bn_prime.h create mode 100644 libsecurity_apple_csp/open_ssl/bn/bn_print.c create mode 100644 libsecurity_apple_csp/open_ssl/bn/bn_rand.c create mode 100644 libsecurity_apple_csp/open_ssl/bn/bn_recp.c create mode 100644 libsecurity_apple_csp/open_ssl/bn/bn_shift.c create mode 100644 libsecurity_apple_csp/open_ssl/bn/bn_sqr.c create mode 100644 libsecurity_apple_csp/open_ssl/bn/bn_word.c create mode 100644 libsecurity_apple_csp/open_ssl/bn/bnspeed.c create mode 100644 libsecurity_apple_csp/open_ssl/bn/bntest.c create mode 100644 libsecurity_apple_csp/open_ssl/bn/divtest.c create mode 100644 libsecurity_apple_csp/open_ssl/bn/exp.c create mode 100644 libsecurity_apple_csp/open_ssl/bn/expspeed.c create mode 100644 libsecurity_apple_csp/open_ssl/bn/exptest.c create mode 100644 libsecurity_apple_csp/open_ssl/bn/vms-helper.c create mode 100644 libsecurity_apple_csp/open_ssl/buffer/buf_err.c create mode 100644 libsecurity_apple_csp/open_ssl/buffer/buffer.c create mode 100644 libsecurity_apple_csp/open_ssl/cryptlib.c create mode 100644 libsecurity_apple_csp/open_ssl/cryptlib.h create mode 100644 libsecurity_apple_csp/open_ssl/dh/dh_check.c create mode 100644 libsecurity_apple_csp/open_ssl/dh/dh_err.c create mode 100644 libsecurity_apple_csp/open_ssl/dh/dh_gen.c create mode 100644 libsecurity_apple_csp/open_ssl/dh/dh_key.c create mode 100644 libsecurity_apple_csp/open_ssl/dh/dh_lib.c create mode 100644 libsecurity_apple_csp/open_ssl/dsa/dsa_asn1.c create mode 100644 libsecurity_apple_csp/open_ssl/dsa/dsa_err.c create mode 100644 libsecurity_apple_csp/open_ssl/dsa/dsa_gen.c create mode 100644 libsecurity_apple_csp/open_ssl/dsa/dsa_key.c create mode 100644 libsecurity_apple_csp/open_ssl/dsa/dsa_lib.c create mode 100644 libsecurity_apple_csp/open_ssl/dsa/dsa_ossl.c create mode 100644 libsecurity_apple_csp/open_ssl/dsa/dsa_sign.c create mode 100644 libsecurity_apple_csp/open_ssl/dsa/dsa_vrf.c create mode 100644 libsecurity_apple_csp/open_ssl/err/err.c create mode 100644 libsecurity_apple_csp/open_ssl/err/err_prn.c create mode 100644 libsecurity_apple_csp/open_ssl/ex_data.c create mode 100644 libsecurity_apple_csp/open_ssl/lhash/lhash.c create mode 100644 libsecurity_apple_csp/open_ssl/mem.c create mode 100644 libsecurity_apple_csp/open_ssl/misc/rc2_cbc.c create mode 100644 libsecurity_apple_csp/open_ssl/misc/rc2_locl.h create mode 100644 libsecurity_apple_csp/open_ssl/misc/rc2_skey.c create mode 100644 libsecurity_apple_csp/open_ssl/misc/rc5_enc.c create mode 100644 libsecurity_apple_csp/open_ssl/misc/rc5_locl.h create mode 100644 libsecurity_apple_csp/open_ssl/misc/rc5_skey.c create mode 100644 libsecurity_apple_csp/open_ssl/openssl/asn1.h create mode 100644 libsecurity_apple_csp/open_ssl/openssl/bio.h create mode 100644 libsecurity_apple_csp/open_ssl/openssl/blowfish.h create mode 100644 libsecurity_apple_csp/open_ssl/openssl/bn.h create mode 100644 libsecurity_apple_csp/open_ssl/openssl/buffer.h create mode 100644 libsecurity_apple_csp/open_ssl/openssl/cast.h create mode 100644 libsecurity_apple_csp/open_ssl/openssl/crypto.h create mode 100644 libsecurity_apple_csp/open_ssl/openssl/dh.h create mode 100644 libsecurity_apple_csp/open_ssl/openssl/dsa.h create mode 100644 libsecurity_apple_csp/open_ssl/openssl/e_os.h create mode 100644 libsecurity_apple_csp/open_ssl/openssl/e_os2.h create mode 100644 libsecurity_apple_csp/open_ssl/openssl/err.h create mode 100644 libsecurity_apple_csp/open_ssl/openssl/evp.h create mode 100644 libsecurity_apple_csp/open_ssl/openssl/lhash.h create mode 100644 libsecurity_apple_csp/open_ssl/openssl/objects.h create mode 100644 libsecurity_apple_csp/open_ssl/openssl/openssl_pkcs7.h create mode 100644 libsecurity_apple_csp/open_ssl/openssl/opensslconf.h create mode 100644 libsecurity_apple_csp/open_ssl/openssl/opensslv.h create mode 100644 libsecurity_apple_csp/open_ssl/openssl/rand.h create mode 100644 libsecurity_apple_csp/open_ssl/openssl/rc2.h create mode 100644 libsecurity_apple_csp/open_ssl/openssl/rc5.h create mode 100644 libsecurity_apple_csp/open_ssl/openssl/rsa.h create mode 100644 libsecurity_apple_csp/open_ssl/openssl/safestack.h create mode 100644 libsecurity_apple_csp/open_ssl/openssl/stack.h create mode 100644 libsecurity_apple_csp/open_ssl/openssl/x509.h create mode 100644 libsecurity_apple_csp/open_ssl/openssl/x509_vfy.h create mode 100644 libsecurity_apple_csp/open_ssl/opensslUtils/opensslAsn1.cpp create mode 100644 libsecurity_apple_csp/open_ssl/opensslUtils/opensslAsn1.h create mode 100644 libsecurity_apple_csp/open_ssl/opensslUtils/opensslUtils.cpp create mode 100644 libsecurity_apple_csp/open_ssl/opensslUtils/opensslUtils.h create mode 100644 libsecurity_apple_csp/open_ssl/rsa/rsa_chk.c create mode 100644 libsecurity_apple_csp/open_ssl/rsa/rsa_eay.c create mode 100644 libsecurity_apple_csp/open_ssl/rsa/rsa_err.c create mode 100644 libsecurity_apple_csp/open_ssl/rsa/rsa_gen.c create mode 100644 libsecurity_apple_csp/open_ssl/rsa/rsa_lib.c create mode 100644 libsecurity_apple_csp/open_ssl/rsa/rsa_none.c create mode 100644 libsecurity_apple_csp/open_ssl/rsa/rsa_null.c create mode 100644 libsecurity_apple_csp/open_ssl/rsa/rsa_pk1.c create mode 100644 libsecurity_apple_csp/open_ssl/rsa/rsa_saos.c create mode 100644 libsecurity_apple_csp/open_ssl/rsa/rsa_sign.c create mode 100644 libsecurity_apple_csp/open_ssl/rsa/rsa_ssl.c create mode 100644 libsecurity_apple_csp/open_ssl/stack/stack.c create mode 100644 libsecurity_apple_csp/tests/t-dsa.cpp create mode 100644 libsecurity_apple_csp/tests/t-rsa.cpp create mode 100644 libsecurity_apple_csp/tests/t.cpp create mode 100644 libsecurity_apple_cspdl/Info-security_apple_cspdl.plist create mode 100644 libsecurity_apple_cspdl/lib/AppleCSPDLBuiltin.cpp create mode 100644 libsecurity_apple_cspdl/lib/AppleCSPDLPlugin.cpp create mode 100644 libsecurity_apple_cspdl/lib/CSPDLDatabase.cpp create mode 100644 libsecurity_apple_cspdl/lib/CSPDLDatabase.h create mode 100644 libsecurity_apple_cspdl/lib/CSPDLPlugin.cpp create mode 100644 libsecurity_apple_cspdl/lib/CSPDLPlugin.h create mode 100644 libsecurity_apple_cspdl/lib/SSCSPDLSession.cpp create mode 100644 libsecurity_apple_cspdl/lib/SSCSPDLSession.h create mode 100644 libsecurity_apple_cspdl/lib/SSCSPSession.cpp create mode 100644 libsecurity_apple_cspdl/lib/SSCSPSession.h create mode 100644 libsecurity_apple_cspdl/lib/SSContext.cpp create mode 100644 libsecurity_apple_cspdl/lib/SSContext.h create mode 100644 libsecurity_apple_cspdl/lib/SSDLSession.cpp create mode 100644 libsecurity_apple_cspdl/lib/SSDLSession.h create mode 100644 libsecurity_apple_cspdl/lib/SSDatabase.cpp create mode 100644 libsecurity_apple_cspdl/lib/SSDatabase.h create mode 100644 libsecurity_apple_cspdl/lib/SSFactory.cpp create mode 100644 libsecurity_apple_cspdl/lib/SSFactory.h create mode 100644 libsecurity_apple_cspdl/lib/SSKey.cpp create mode 100644 libsecurity_apple_cspdl/lib/SSKey.h create mode 100644 libsecurity_apple_cspdl/libsecurity_apple_cspdl.xcodeproj/project.pbxproj create mode 100644 libsecurity_apple_cspdl/mds/cspdl_common.mdsinfo create mode 100644 libsecurity_apple_cspdl/mds/cspdl_csp_capabilities.mdsinfo create mode 100644 libsecurity_apple_cspdl/mds/cspdl_csp_primary.mdsinfo create mode 100644 libsecurity_apple_cspdl/mds/cspdl_dl_primary.mdsinfo create mode 100644 libsecurity_apple_file_dl/Info-security_apple_file_dl.plist create mode 100644 libsecurity_apple_file_dl/TODO create mode 100644 libsecurity_apple_file_dl/doc/FORMAT create mode 100644 libsecurity_apple_file_dl/doc/ISSUES create mode 100644 libsecurity_apple_file_dl/lib/AppleDLBuiltin.cpp create mode 100644 libsecurity_apple_file_dl/lib/AppleDLPlugin.cpp create mode 100644 libsecurity_apple_file_dl/lib/AppleFileDL.cpp create mode 100644 libsecurity_apple_file_dl/lib/AppleFileDL.h create mode 100644 libsecurity_apple_file_dl/libsecurity_apple_file_dl.xcodeproj/project.pbxproj create mode 100644 libsecurity_apple_file_dl/mds/dl_common.mdsinfo create mode 100644 libsecurity_apple_file_dl/mds/dl_primary.mdsinfo create mode 100644 libsecurity_apple_x509_cl/Info-plugin_apple_x509_cl.plist create mode 100644 libsecurity_apple_x509_cl/Info-security_apple_x509_cl.plist create mode 100644 libsecurity_apple_x509_cl/TODO create mode 100644 libsecurity_apple_x509_cl/lib/AppleX509CL.cpp create mode 100644 libsecurity_apple_x509_cl/lib/AppleX509CL.h create mode 100644 libsecurity_apple_x509_cl/lib/AppleX509CLBuiltin.cpp create mode 100644 libsecurity_apple_x509_cl/lib/AppleX509CLPlugin.cpp create mode 100644 libsecurity_apple_x509_cl/lib/AppleX509CLSession.cpp create mode 100644 libsecurity_apple_x509_cl/lib/AppleX509CLSession.h create mode 100644 libsecurity_apple_x509_cl/lib/CLCachedEntry.cpp create mode 100644 libsecurity_apple_x509_cl/lib/CLCachedEntry.h create mode 100644 libsecurity_apple_x509_cl/lib/CLCertExtensions.cpp create mode 100644 libsecurity_apple_x509_cl/lib/CLCertExtensions.h create mode 100644 libsecurity_apple_x509_cl/lib/CLCrlExtensions.cpp create mode 100644 libsecurity_apple_x509_cl/lib/CLCrlExtensions.h create mode 100644 libsecurity_apple_x509_cl/lib/CLFieldsCommon.cpp create mode 100644 libsecurity_apple_x509_cl/lib/CLFieldsCommon.h create mode 100644 libsecurity_apple_x509_cl/lib/CSPAttacher.cpp create mode 100644 libsecurity_apple_x509_cl/lib/CSPAttacher.h create mode 100644 libsecurity_apple_x509_cl/lib/CertFields.cpp create mode 100644 libsecurity_apple_x509_cl/lib/CrlFields.cpp create mode 100644 libsecurity_apple_x509_cl/lib/DecodedCert.cpp create mode 100644 libsecurity_apple_x509_cl/lib/DecodedCert.h create mode 100644 libsecurity_apple_x509_cl/lib/DecodedCrl.cpp create mode 100644 libsecurity_apple_x509_cl/lib/DecodedCrl.h create mode 100644 libsecurity_apple_x509_cl/lib/DecodedExtensions.cpp create mode 100644 libsecurity_apple_x509_cl/lib/DecodedExtensions.h create mode 100644 libsecurity_apple_x509_cl/lib/DecodedItem.cpp create mode 100644 libsecurity_apple_x509_cl/lib/DecodedItem.h create mode 100644 libsecurity_apple_x509_cl/lib/LockedMap.h create mode 100644 libsecurity_apple_x509_cl/lib/Session_CRL.cpp create mode 100644 libsecurity_apple_x509_cl/lib/Session_CSR.cpp create mode 100644 libsecurity_apple_x509_cl/lib/Session_Cert.cpp create mode 100644 libsecurity_apple_x509_cl/lib/Session_Crypto.cpp create mode 100644 libsecurity_apple_x509_cl/lib/clNameUtils.cpp create mode 100644 libsecurity_apple_x509_cl/lib/clNameUtils.h create mode 100644 libsecurity_apple_x509_cl/lib/clNssUtils.cpp create mode 100644 libsecurity_apple_x509_cl/lib/clNssUtils.h create mode 100644 libsecurity_apple_x509_cl/lib/cldebugging.h create mode 100644 libsecurity_apple_x509_cl/libsecurity_apple_x509_cl.xcodeproj/project.pbxproj create mode 100644 libsecurity_apple_x509_cl/mds/cl_common.mdsinfo create mode 100644 libsecurity_apple_x509_cl/mds/cl_primary.mdsinfo create mode 100644 libsecurity_apple_x509_tp/Info-security_apple_x509_tp.plist create mode 100644 libsecurity_apple_x509_tp/lib/AppleTP.cpp create mode 100644 libsecurity_apple_x509_tp/lib/AppleTP.h create mode 100644 libsecurity_apple_x509_tp/lib/AppleTPSession.cpp create mode 100644 libsecurity_apple_x509_tp/lib/AppleTPSession.h create mode 100644 libsecurity_apple_x509_tp/lib/AppleX509TPBuiltin.cpp create mode 100644 libsecurity_apple_x509_tp/lib/AppleX509TPPlugin.cpp create mode 100644 libsecurity_apple_x509_tp/lib/TPCertInfo.cpp create mode 100644 libsecurity_apple_x509_tp/lib/TPCertInfo.h create mode 100644 libsecurity_apple_x509_tp/lib/TPCrlInfo.cpp create mode 100644 libsecurity_apple_x509_tp/lib/TPCrlInfo.h create mode 100644 libsecurity_apple_x509_tp/lib/TPDatabase.cpp create mode 100644 libsecurity_apple_x509_tp/lib/TPDatabase.h create mode 100644 libsecurity_apple_x509_tp/lib/TPNetwork.cpp create mode 100644 libsecurity_apple_x509_tp/lib/TPNetwork.h create mode 100644 libsecurity_apple_x509_tp/lib/certGroupUtils.cpp create mode 100644 libsecurity_apple_x509_tp/lib/certGroupUtils.h create mode 100644 libsecurity_apple_x509_tp/lib/cuEnc64.c create mode 100644 libsecurity_apple_x509_tp/lib/cuEnc64.h create mode 100644 libsecurity_apple_x509_tp/lib/ocspRequest.cpp create mode 100644 libsecurity_apple_x509_tp/lib/ocspRequest.h create mode 100644 libsecurity_apple_x509_tp/lib/tpCertGroup.cpp create mode 100644 libsecurity_apple_x509_tp/lib/tpCredRequest.cpp create mode 100644 libsecurity_apple_x509_tp/lib/tpCrlVerify.cpp create mode 100644 libsecurity_apple_x509_tp/lib/tpCrlVerify.h create mode 100644 libsecurity_apple_x509_tp/lib/tpOcspCache.cpp create mode 100644 libsecurity_apple_x509_tp/lib/tpOcspCache.h create mode 100644 libsecurity_apple_x509_tp/lib/tpOcspCertVfy.cpp create mode 100644 libsecurity_apple_x509_tp/lib/tpOcspCertVfy.h create mode 100644 libsecurity_apple_x509_tp/lib/tpOcspVerify.cpp create mode 100644 libsecurity_apple_x509_tp/lib/tpOcspVerify.h create mode 100644 libsecurity_apple_x509_tp/lib/tpPolicies.cpp create mode 100644 libsecurity_apple_x509_tp/lib/tpPolicies.h create mode 100644 libsecurity_apple_x509_tp/lib/tpTime.c create mode 100644 libsecurity_apple_x509_tp/lib/tpTime.h create mode 100644 libsecurity_apple_x509_tp/lib/tpdebugging.h create mode 100644 libsecurity_apple_x509_tp/libsecurity_apple_x509_tp.xcodeproj/project.pbxproj create mode 100644 libsecurity_apple_x509_tp/mds/tp_common.mdsinfo create mode 100644 libsecurity_apple_x509_tp/mds/tp_policyOids.mdsinfo create mode 100644 libsecurity_apple_x509_tp/mds/tp_primary.mdsinfo create mode 100644 libsecurity_asn1/APPLE_LICENSE create mode 100644 libsecurity_asn1/CHANGES.Apple create mode 100644 libsecurity_asn1/Info-security_asn1.plist create mode 100644 libsecurity_asn1/Makefile create mode 100644 libsecurity_asn1/MozillaPublicLicense1.1.html create mode 120000 libsecurity_asn1/Security create mode 100644 libsecurity_asn1/asn1/README create mode 100644 libsecurity_asn1/asn1/appleoids.asn create mode 100644 libsecurity_asn1/asn1/asn-useful.asn1 create mode 100644 libsecurity_asn1/asn1/pkcs1.asn1 create mode 100644 libsecurity_asn1/asn1/pkcs10.asn create mode 100644 libsecurity_asn1/asn1/pkcs1oids.asn create mode 100644 libsecurity_asn1/asn1/pkcs5.asn1 create mode 100644 libsecurity_asn1/asn1/pkcs7.asn create mode 100644 libsecurity_asn1/asn1/pkcs8.asn create mode 100644 libsecurity_asn1/asn1/pkcs9oids.asn create mode 100644 libsecurity_asn1/asn1/rfc3161.asn1 create mode 100644 libsecurity_asn1/asn1/sm_cms.asn create mode 100644 libsecurity_asn1/asn1/sm_ess.asn create mode 100644 libsecurity_asn1/asn1/sm_vdatypes.asn create mode 100644 libsecurity_asn1/asn1/sm_x411mtsas.asn create mode 100644 libsecurity_asn1/asn1/sm_x411ub.asn create mode 100644 libsecurity_asn1/asn1/sm_x501if.asn create mode 100644 libsecurity_asn1/asn1/sm_x501ud.asn create mode 100644 libsecurity_asn1/asn1/sm_x509af.asn create mode 100644 libsecurity_asn1/asn1/sm_x509ce.asn create mode 100644 libsecurity_asn1/asn1/sm_x509cmn.asn create mode 100644 libsecurity_asn1/asn1/sm_x520sa.asn create mode 100644 libsecurity_asn1/config/base.xcconfig create mode 100644 libsecurity_asn1/config/debug.xcconfig create mode 100644 libsecurity_asn1/config/lib.xcconfig create mode 100644 libsecurity_asn1/config/release.xcconfig create mode 100644 libsecurity_asn1/docs/libsecurity_asn1.plist create mode 100644 libsecurity_asn1/docs/libsecurity_asn1.txt create mode 100644 libsecurity_asn1/lib/SecAsn1Coder.c create mode 100644 libsecurity_asn1/lib/SecAsn1Coder.h create mode 100644 libsecurity_asn1/lib/SecAsn1Templates.c create mode 100644 libsecurity_asn1/lib/SecAsn1Templates.h create mode 100644 libsecurity_asn1/lib/SecAsn1Types.h create mode 100644 libsecurity_asn1/lib/SecNssCoder.cpp create mode 100644 libsecurity_asn1/lib/SecNssCoder.h create mode 100644 libsecurity_asn1/lib/X509Templates.c create mode 100644 libsecurity_asn1/lib/X509Templates.h create mode 100644 libsecurity_asn1/lib/asn1Templates.h create mode 100644 libsecurity_asn1/lib/certExtensionTemplates.c create mode 100644 libsecurity_asn1/lib/certExtensionTemplates.h create mode 100644 libsecurity_asn1/lib/csrTemplates.c create mode 100644 libsecurity_asn1/lib/csrTemplates.h create mode 100644 libsecurity_asn1/lib/keyTemplates.c create mode 100644 libsecurity_asn1/lib/keyTemplates.h create mode 100644 libsecurity_asn1/lib/nameTemplates.c create mode 100644 libsecurity_asn1/lib/nameTemplates.h create mode 100644 libsecurity_asn1/lib/nsprPortX.c create mode 100644 libsecurity_asn1/lib/nssUtils.c create mode 100644 libsecurity_asn1/lib/nssUtils.h create mode 100644 libsecurity_asn1/lib/nssilckt.h create mode 100644 libsecurity_asn1/lib/nssilock.h create mode 100644 libsecurity_asn1/lib/nsslocks.h create mode 100644 libsecurity_asn1/lib/ocspTemplates.c create mode 100644 libsecurity_asn1/lib/ocspTemplates.h create mode 100644 libsecurity_asn1/lib/oidsalg.c create mode 100644 libsecurity_asn1/lib/oidsalg.h create mode 100644 libsecurity_asn1/lib/oidsattr.c create mode 100644 libsecurity_asn1/lib/oidsattr.h create mode 100644 libsecurity_asn1/lib/oidsbase.h create mode 100644 libsecurity_asn1/lib/oidsocsp.c create mode 100644 libsecurity_asn1/lib/oidsocsp.h create mode 100644 libsecurity_asn1/lib/osKeyTemplates.c create mode 100644 libsecurity_asn1/lib/osKeyTemplates.h create mode 100644 libsecurity_asn1/lib/pkcs12Templates.c create mode 100644 libsecurity_asn1/lib/pkcs12Templates.h create mode 100644 libsecurity_asn1/lib/pkcs7Templates.c create mode 100644 libsecurity_asn1/lib/pkcs7Templates.h create mode 100644 libsecurity_asn1/lib/plarena.c create mode 100644 libsecurity_asn1/lib/plarena.h create mode 100644 libsecurity_asn1/lib/plarenas.h create mode 100644 libsecurity_asn1/lib/plstr.h create mode 100644 libsecurity_asn1/lib/prbit.h create mode 100644 libsecurity_asn1/lib/prcpucfg.h create mode 100644 libsecurity_asn1/lib/prcvar.h create mode 100644 libsecurity_asn1/lib/prenv.h create mode 100644 libsecurity_asn1/lib/prerr.h create mode 100644 libsecurity_asn1/lib/prerror.h create mode 100644 libsecurity_asn1/lib/prinit.h create mode 100644 libsecurity_asn1/lib/prinrval.h create mode 100644 libsecurity_asn1/lib/prlock.h create mode 100644 libsecurity_asn1/lib/prlog.h create mode 100644 libsecurity_asn1/lib/prlong.h create mode 100644 libsecurity_asn1/lib/prmem.h create mode 100644 libsecurity_asn1/lib/prmon.h create mode 100644 libsecurity_asn1/lib/protypes.h create mode 100644 libsecurity_asn1/lib/prthread.h create mode 100644 libsecurity_asn1/lib/prtime.h create mode 100644 libsecurity_asn1/lib/prtypes.h create mode 100644 libsecurity_asn1/lib/prvrsion.h create mode 100644 libsecurity_asn1/lib/secErrorStr.c create mode 100644 libsecurity_asn1/lib/secasn1.h create mode 100644 libsecurity_asn1/lib/secasn1d.c create mode 100644 libsecurity_asn1/lib/secasn1e.c create mode 100644 libsecurity_asn1/lib/secasn1t.h create mode 100644 libsecurity_asn1/lib/secasn1u.c create mode 100644 libsecurity_asn1/lib/seccomon.h create mode 100644 libsecurity_asn1/lib/secerr.h create mode 100644 libsecurity_asn1/lib/secport.c create mode 100644 libsecurity_asn1/lib/secport.h create mode 100644 libsecurity_asn1/lib/security_asn1.exp create mode 100644 libsecurity_asn1/libsecurity_asn1.xcodeproj/project.pbxproj create mode 120000 libsecurity_asn1/security_asn1 create mode 100644 libsecurity_authorization/APPLE_LICENSE create mode 100644 libsecurity_authorization/Info-security_authorization.plist create mode 100644 libsecurity_authorization/lib/AuthSession.h create mode 100644 libsecurity_authorization/lib/Authorization.cpp create mode 100644 libsecurity_authorization/lib/Authorization.h create mode 100644 libsecurity_authorization/lib/AuthorizationDB.h create mode 100644 libsecurity_authorization/lib/AuthorizationPlugin.h create mode 100644 libsecurity_authorization/lib/AuthorizationPriv.h create mode 100644 libsecurity_authorization/lib/AuthorizationTags.h create mode 100644 libsecurity_authorization/lib/AuthorizationTagsPriv.h create mode 100644 libsecurity_authorization/lib/privPort.h create mode 100644 libsecurity_authorization/lib/security_authorization.exp create mode 100644 libsecurity_authorization/lib/trampolineClient.cpp create mode 100644 libsecurity_authorization/lib/trampolineServer.cpp create mode 100644 libsecurity_authorization/libsecurity_authorization.xcodeproj/project.pbxproj create mode 100644 libsecurity_cdsa_client/Info-security_cdsa_client.plist create mode 100644 libsecurity_cdsa_client/lib/DLDBList.cpp create mode 100644 libsecurity_cdsa_client/lib/DLDBList.h create mode 100644 libsecurity_cdsa_client/lib/aclclient.cpp create mode 100644 libsecurity_cdsa_client/lib/aclclient.h create mode 100644 libsecurity_cdsa_client/lib/clclient.cpp create mode 100644 libsecurity_cdsa_client/lib/clclient.h create mode 100644 libsecurity_cdsa_client/lib/cryptoclient.cpp create mode 100644 libsecurity_cdsa_client/lib/cryptoclient.h create mode 100644 libsecurity_cdsa_client/lib/cspclient.cpp create mode 100644 libsecurity_cdsa_client/lib/cspclient.h create mode 100644 libsecurity_cdsa_client/lib/cssmclient.cpp create mode 100644 libsecurity_cdsa_client/lib/cssmclient.h create mode 100644 libsecurity_cdsa_client/lib/dl_standard.cpp create mode 100644 libsecurity_cdsa_client/lib/dl_standard.h create mode 100644 libsecurity_cdsa_client/lib/dlclient.cpp create mode 100644 libsecurity_cdsa_client/lib/dlclient.h create mode 100644 libsecurity_cdsa_client/lib/dlclientpriv.cpp create mode 100644 libsecurity_cdsa_client/lib/dliterators.cpp create mode 100644 libsecurity_cdsa_client/lib/dliterators.h create mode 100644 libsecurity_cdsa_client/lib/dlquery.cpp create mode 100644 libsecurity_cdsa_client/lib/dlquery.h create mode 100644 libsecurity_cdsa_client/lib/genkey.cpp create mode 100644 libsecurity_cdsa_client/lib/genkey.h create mode 100644 libsecurity_cdsa_client/lib/keychainacl.cpp create mode 100644 libsecurity_cdsa_client/lib/keychainacl.h create mode 100644 libsecurity_cdsa_client/lib/keyclient.cpp create mode 100644 libsecurity_cdsa_client/lib/keyclient.h create mode 100644 libsecurity_cdsa_client/lib/macclient.cpp create mode 100644 libsecurity_cdsa_client/lib/macclient.h create mode 100644 libsecurity_cdsa_client/lib/mds_standard.cpp create mode 100644 libsecurity_cdsa_client/lib/mds_standard.h create mode 100644 libsecurity_cdsa_client/lib/mdsclient.cpp create mode 100644 libsecurity_cdsa_client/lib/mdsclient.h create mode 100644 libsecurity_cdsa_client/lib/multidldb.cpp create mode 100644 libsecurity_cdsa_client/lib/multidldb.h create mode 100644 libsecurity_cdsa_client/lib/securestorage.cpp create mode 100644 libsecurity_cdsa_client/lib/securestorage.h create mode 100644 libsecurity_cdsa_client/lib/signclient.cpp create mode 100644 libsecurity_cdsa_client/lib/signclient.h create mode 100644 libsecurity_cdsa_client/lib/tpclient.cpp create mode 100644 libsecurity_cdsa_client/lib/tpclient.h create mode 100644 libsecurity_cdsa_client/lib/wrapkey.cpp create mode 100644 libsecurity_cdsa_client/lib/wrapkey.h create mode 100644 libsecurity_cdsa_client/libsecurity_cdsa_client.xcodeproj/project.pbxproj create mode 100644 libsecurity_cdsa_plugin/Info-security_cdsa_plugin.plist create mode 100644 libsecurity_cdsa_plugin/lib/ACsession.h create mode 100644 libsecurity_cdsa_plugin/lib/CLsession.h create mode 100644 libsecurity_cdsa_plugin/lib/CSPsession.cpp create mode 100644 libsecurity_cdsa_plugin/lib/CSPsession.h create mode 100644 libsecurity_cdsa_plugin/lib/DLsession.cpp create mode 100644 libsecurity_cdsa_plugin/lib/DLsession.h create mode 100644 libsecurity_cdsa_plugin/lib/Database.cpp create mode 100644 libsecurity_cdsa_plugin/lib/Database.h create mode 100644 libsecurity_cdsa_plugin/lib/DatabaseSession.cpp create mode 100644 libsecurity_cdsa_plugin/lib/DatabaseSession.h create mode 100644 libsecurity_cdsa_plugin/lib/DbContext.cpp create mode 100644 libsecurity_cdsa_plugin/lib/DbContext.h create mode 100644 libsecurity_cdsa_plugin/lib/TPsession.h create mode 100644 libsecurity_cdsa_plugin/lib/c++plugin.h create mode 100644 libsecurity_cdsa_plugin/lib/csputilities.cpp create mode 100644 libsecurity_cdsa_plugin/lib/cssmplugin.cpp create mode 100644 libsecurity_cdsa_plugin/lib/cssmplugin.h create mode 100644 libsecurity_cdsa_plugin/lib/generator.cfg create mode 100644 libsecurity_cdsa_plugin/lib/generator.mk create mode 100644 libsecurity_cdsa_plugin/lib/generator.pl create mode 100644 libsecurity_cdsa_plugin/lib/pluginsession.cpp create mode 100644 libsecurity_cdsa_plugin/lib/pluginsession.h create mode 100644 libsecurity_cdsa_plugin/lib/pluginspi.h create mode 100644 libsecurity_cdsa_plugin/libsecurity_cdsa_plugin.xcodeproj/project.pbxproj create mode 100644 libsecurity_cdsa_utilities/APPLE_LICENSE create mode 100644 libsecurity_cdsa_utilities/Info-security_cdsa_utilities.plist create mode 100644 libsecurity_cdsa_utilities/lib/AuthorizationData.cpp create mode 100644 libsecurity_cdsa_utilities/lib/AuthorizationData.h create mode 100644 libsecurity_cdsa_utilities/lib/AuthorizationWalkers.h create mode 100644 libsecurity_cdsa_utilities/lib/KeySchema.h create mode 100644 libsecurity_cdsa_utilities/lib/KeySchema.m4 create mode 100644 libsecurity_cdsa_utilities/lib/Schema.h create mode 100644 libsecurity_cdsa_utilities/lib/Schema.m4 create mode 100644 libsecurity_cdsa_utilities/lib/acl_any.cpp create mode 100644 libsecurity_cdsa_utilities/lib/acl_any.h create mode 100644 libsecurity_cdsa_utilities/lib/acl_codesigning.cpp create mode 100644 libsecurity_cdsa_utilities/lib/acl_codesigning.h create mode 100644 libsecurity_cdsa_utilities/lib/acl_comment.cpp create mode 100644 libsecurity_cdsa_utilities/lib/acl_comment.h create mode 100644 libsecurity_cdsa_utilities/lib/acl_password.cpp create mode 100644 libsecurity_cdsa_utilities/lib/acl_password.h create mode 100644 libsecurity_cdsa_utilities/lib/acl_preauth.cpp create mode 100644 libsecurity_cdsa_utilities/lib/acl_preauth.h create mode 100644 libsecurity_cdsa_utilities/lib/acl_process.cpp create mode 100644 libsecurity_cdsa_utilities/lib/acl_process.h create mode 100644 libsecurity_cdsa_utilities/lib/acl_prompted.cpp create mode 100644 libsecurity_cdsa_utilities/lib/acl_prompted.h create mode 100644 libsecurity_cdsa_utilities/lib/acl_protectedpw.cpp create mode 100644 libsecurity_cdsa_utilities/lib/acl_protectedpw.h create mode 100644 libsecurity_cdsa_utilities/lib/acl_secret.cpp create mode 100644 libsecurity_cdsa_utilities/lib/acl_secret.h create mode 100644 libsecurity_cdsa_utilities/lib/acl_threshold.cpp create mode 100644 libsecurity_cdsa_utilities/lib/acl_threshold.h create mode 100644 libsecurity_cdsa_utilities/lib/aclsubject.cpp create mode 100644 libsecurity_cdsa_utilities/lib/aclsubject.h create mode 100644 libsecurity_cdsa_utilities/lib/callback.cpp create mode 100644 libsecurity_cdsa_utilities/lib/callback.h create mode 100644 libsecurity_cdsa_utilities/lib/constdata.cpp create mode 100644 libsecurity_cdsa_utilities/lib/constdata.h create mode 100644 libsecurity_cdsa_utilities/lib/context.cpp create mode 100644 libsecurity_cdsa_utilities/lib/context.h create mode 100644 libsecurity_cdsa_utilities/lib/cssmacl.cpp create mode 100644 libsecurity_cdsa_utilities/lib/cssmacl.h create mode 100644 libsecurity_cdsa_utilities/lib/cssmaclpod.cpp create mode 100644 libsecurity_cdsa_utilities/lib/cssmaclpod.h create mode 100644 libsecurity_cdsa_utilities/lib/cssmalloc.cpp create mode 100644 libsecurity_cdsa_utilities/lib/cssmalloc.h create mode 100644 libsecurity_cdsa_utilities/lib/cssmbridge.h create mode 100644 libsecurity_cdsa_utilities/lib/cssmcert.cpp create mode 100644 libsecurity_cdsa_utilities/lib/cssmcert.h create mode 100644 libsecurity_cdsa_utilities/lib/cssmcred.cpp create mode 100644 libsecurity_cdsa_utilities/lib/cssmcred.h create mode 100644 libsecurity_cdsa_utilities/lib/cssmdata.cpp create mode 100644 libsecurity_cdsa_utilities/lib/cssmdata.h create mode 100644 libsecurity_cdsa_utilities/lib/cssmdates.cpp create mode 100644 libsecurity_cdsa_utilities/lib/cssmdates.h create mode 100644 libsecurity_cdsa_utilities/lib/cssmdb.cpp create mode 100644 libsecurity_cdsa_utilities/lib/cssmdb.h create mode 100644 libsecurity_cdsa_utilities/lib/cssmdbname.cpp create mode 100644 libsecurity_cdsa_utilities/lib/cssmdbname.h create mode 100644 libsecurity_cdsa_utilities/lib/cssmendian.cpp create mode 100644 libsecurity_cdsa_utilities/lib/cssmendian.h create mode 100644 libsecurity_cdsa_utilities/lib/cssmerrors.cpp create mode 100644 libsecurity_cdsa_utilities/lib/cssmerrors.h create mode 100644 libsecurity_cdsa_utilities/lib/cssmkey.cpp create mode 100644 libsecurity_cdsa_utilities/lib/cssmkey.h create mode 100644 libsecurity_cdsa_utilities/lib/cssmlist.cpp create mode 100644 libsecurity_cdsa_utilities/lib/cssmlist.h create mode 100644 libsecurity_cdsa_utilities/lib/cssmpods.cpp create mode 100644 libsecurity_cdsa_utilities/lib/cssmpods.h create mode 100644 libsecurity_cdsa_utilities/lib/cssmtrust.cpp create mode 100644 libsecurity_cdsa_utilities/lib/cssmtrust.h create mode 100644 libsecurity_cdsa_utilities/lib/cssmwalkers.cpp create mode 100644 libsecurity_cdsa_utilities/lib/cssmwalkers.h create mode 100644 libsecurity_cdsa_utilities/lib/db++.cpp create mode 100644 libsecurity_cdsa_utilities/lib/db++.h create mode 100644 libsecurity_cdsa_utilities/lib/digestobject.h create mode 100644 libsecurity_cdsa_utilities/lib/generator.mk create mode 100644 libsecurity_cdsa_utilities/lib/generator.pl create mode 100644 libsecurity_cdsa_utilities/lib/handleobject.cpp create mode 100644 libsecurity_cdsa_utilities/lib/handleobject.h create mode 100644 libsecurity_cdsa_utilities/lib/handletemplates.cpp create mode 100644 libsecurity_cdsa_utilities/lib/handletemplates.h create mode 100644 libsecurity_cdsa_utilities/lib/handletemplates_defs.h create mode 100644 libsecurity_cdsa_utilities/lib/objectacl.cpp create mode 100644 libsecurity_cdsa_utilities/lib/objectacl.h create mode 100644 libsecurity_cdsa_utilities/lib/osxverifier.cpp create mode 100644 libsecurity_cdsa_utilities/lib/osxverifier.h create mode 100644 libsecurity_cdsa_utilities/lib/u32handleobject.cpp create mode 100644 libsecurity_cdsa_utilities/lib/u32handleobject.h create mode 100644 libsecurity_cdsa_utilities/lib/uniformrandom.cpp create mode 100644 libsecurity_cdsa_utilities/lib/uniformrandom.h create mode 100644 libsecurity_cdsa_utilities/lib/walkers.cpp create mode 100644 libsecurity_cdsa_utilities/lib/walkers.h create mode 100644 libsecurity_cdsa_utilities/libsecurity_cdsa_utilities.xcodeproj/project.pbxproj create mode 100644 libsecurity_cdsa_utils/Info-security_cdsa_utils.plist create mode 100644 libsecurity_cdsa_utils/lib/cuCdsaUtils.cpp create mode 100644 libsecurity_cdsa_utils/lib/cuCdsaUtils.h create mode 100644 libsecurity_cdsa_utils/lib/cuDbUtils.cpp create mode 100644 libsecurity_cdsa_utils/lib/cuDbUtils.h create mode 100644 libsecurity_cdsa_utils/lib/cuEnc64.c create mode 100644 libsecurity_cdsa_utils/lib/cuEnc64.h create mode 100644 libsecurity_cdsa_utils/lib/cuFileIo.c create mode 100644 libsecurity_cdsa_utils/lib/cuFileIo.h create mode 100644 libsecurity_cdsa_utils/lib/cuOidParser.cpp create mode 100644 libsecurity_cdsa_utils/lib/cuOidParser.h create mode 100644 libsecurity_cdsa_utils/lib/cuPem.cpp create mode 100644 libsecurity_cdsa_utils/lib/cuPem.h create mode 100644 libsecurity_cdsa_utils/lib/cuPrintCert.cpp create mode 100644 libsecurity_cdsa_utils/lib/cuPrintCert.h create mode 100644 libsecurity_cdsa_utils/lib/cuTimeStr.cpp create mode 100644 libsecurity_cdsa_utils/lib/cuTimeStr.h create mode 100644 libsecurity_cdsa_utils/libsecurity_cdsa_utils.xcodeproj/project.pbxproj create mode 100644 libsecurity_checkpw/APPLE_LICENSE create mode 100644 libsecurity_checkpw/Info-security_checkpw.plist create mode 100644 libsecurity_checkpw/checkpw.pam create mode 100644 libsecurity_checkpw/lib/checkpw.c create mode 100644 libsecurity_checkpw/lib/checkpw.h create mode 100644 libsecurity_checkpw/lib/security_checkpw.exp create mode 100644 libsecurity_checkpw/libsecurity_checkpw.xcodeproj/project.pbxproj create mode 100644 libsecurity_checkpw/test/perf-checkpw.c create mode 100644 libsecurity_checkpw/test/test-checkpw.c create mode 100644 libsecurity_cms/APPLE_LICENSE create mode 100644 libsecurity_cms/Info-security_cms.plist create mode 100644 libsecurity_cms/lib/CMSDecoder.cpp create mode 100644 libsecurity_cms/lib/CMSDecoder.h create mode 100644 libsecurity_cms/lib/CMSEncoder.cpp create mode 100644 libsecurity_cms/lib/CMSEncoder.h create mode 100644 libsecurity_cms/lib/CMSPrivate.h create mode 100644 libsecurity_cms/lib/CMSUtils.cpp create mode 100644 libsecurity_cms/lib/CMSUtils.h create mode 100644 libsecurity_cms/lib/security_cms.exp create mode 100644 libsecurity_cms/libsecurity_cms.xcodeproj/project.pbxproj create mode 100644 libsecurity_codesigning/APPLE_LICENSE create mode 100644 libsecurity_codesigning/Info-security_codesigning.plist create mode 100755 libsecurity_codesigning/dtrace/codesign-watch.d create mode 100755 libsecurity_codesigning/dtrace/reqint.d create mode 100755 libsecurity_codesigning/dtrace/sp-watch.d create mode 100755 libsecurity_codesigning/gke/gkclear create mode 100755 libsecurity_codesigning/gke/gkgenerate create mode 100755 libsecurity_codesigning/gke/gkhandmake create mode 100755 libsecurity_codesigning/gke/gklist create mode 100755 libsecurity_codesigning/gke/gkmerge create mode 100755 libsecurity_codesigning/gke/gkrecord create mode 100644 libsecurity_codesigning/lib/CSCommon.h create mode 100644 libsecurity_codesigning/lib/CSCommonPriv.h create mode 100644 libsecurity_codesigning/lib/Code.cpp create mode 100644 libsecurity_codesigning/lib/Code.h create mode 100644 libsecurity_codesigning/lib/CodeSigner.cpp create mode 100644 libsecurity_codesigning/lib/CodeSigner.h create mode 100644 libsecurity_codesigning/lib/CodeSigning.h create mode 100644 libsecurity_codesigning/lib/RequirementKeywords.h create mode 100644 libsecurity_codesigning/lib/RequirementLexer.cpp create mode 100644 libsecurity_codesigning/lib/RequirementLexer.hpp create mode 100644 libsecurity_codesigning/lib/RequirementParser.cpp create mode 100644 libsecurity_codesigning/lib/RequirementParser.hpp create mode 100644 libsecurity_codesigning/lib/RequirementParserTokenTypes.hpp create mode 100644 libsecurity_codesigning/lib/RequirementParserTokenTypes.txt create mode 100644 libsecurity_codesigning/lib/Requirements.cpp create mode 100644 libsecurity_codesigning/lib/Requirements.h create mode 100644 libsecurity_codesigning/lib/SecAssessment.cpp create mode 100644 libsecurity_codesigning/lib/SecAssessment.h create mode 100644 libsecurity_codesigning/lib/SecCode.cpp create mode 100644 libsecurity_codesigning/lib/SecCode.h create mode 100644 libsecurity_codesigning/lib/SecCodeHost.cpp create mode 100644 libsecurity_codesigning/lib/SecCodeHost.h create mode 100644 libsecurity_codesigning/lib/SecCodeHostLib.c create mode 100644 libsecurity_codesigning/lib/SecCodeHostLib.h create mode 100644 libsecurity_codesigning/lib/SecCodePriv.h create mode 100644 libsecurity_codesigning/lib/SecCodeSigner.cpp create mode 100644 libsecurity_codesigning/lib/SecCodeSigner.h create mode 100644 libsecurity_codesigning/lib/SecIntegrity.cpp create mode 100644 libsecurity_codesigning/lib/SecIntegrity.h create mode 100644 libsecurity_codesigning/lib/SecIntegrityLib.c create mode 100644 libsecurity_codesigning/lib/SecIntegrityLib.h create mode 100644 libsecurity_codesigning/lib/SecRequirement.cpp create mode 100644 libsecurity_codesigning/lib/SecRequirement.h create mode 100644 libsecurity_codesigning/lib/SecRequirementPriv.h create mode 100644 libsecurity_codesigning/lib/SecStaticCode.cpp create mode 100644 libsecurity_codesigning/lib/SecStaticCode.h create mode 100644 libsecurity_codesigning/lib/SecStaticCodePriv.h create mode 100644 libsecurity_codesigning/lib/SecTask.c create mode 100644 libsecurity_codesigning/lib/SecTask.h create mode 100644 libsecurity_codesigning/lib/StaticCode.cpp create mode 100644 libsecurity_codesigning/lib/StaticCode.h create mode 100644 libsecurity_codesigning/lib/antlrplugin.cpp create mode 100644 libsecurity_codesigning/lib/antlrplugin.h create mode 100644 libsecurity_codesigning/lib/bundlediskrep.cpp create mode 100644 libsecurity_codesigning/lib/bundlediskrep.h create mode 100644 libsecurity_codesigning/lib/cdbuilder.cpp create mode 100644 libsecurity_codesigning/lib/cdbuilder.h create mode 100644 libsecurity_codesigning/lib/cfmdiskrep.cpp create mode 100644 libsecurity_codesigning/lib/cfmdiskrep.h create mode 100644 libsecurity_codesigning/lib/codedirectory.cpp create mode 100644 libsecurity_codesigning/lib/codedirectory.h create mode 100644 libsecurity_codesigning/lib/cs.cpp create mode 100644 libsecurity_codesigning/lib/cs.h create mode 100644 libsecurity_codesigning/lib/cscdefs.c create mode 100644 libsecurity_codesigning/lib/cscdefs.h create mode 100644 libsecurity_codesigning/lib/csdatabase.cpp create mode 100644 libsecurity_codesigning/lib/csdatabase.h create mode 100644 libsecurity_codesigning/lib/cserror.cpp create mode 100644 libsecurity_codesigning/lib/cserror.h create mode 100644 libsecurity_codesigning/lib/csgeneric.cpp create mode 100644 libsecurity_codesigning/lib/csgeneric.h create mode 100644 libsecurity_codesigning/lib/cskernel.cpp create mode 100644 libsecurity_codesigning/lib/cskernel.h create mode 100644 libsecurity_codesigning/lib/csprocess.cpp create mode 100644 libsecurity_codesigning/lib/csprocess.h create mode 100644 libsecurity_codesigning/lib/csutilities.cpp create mode 100644 libsecurity_codesigning/lib/csutilities.h create mode 100644 libsecurity_codesigning/lib/detachedrep.cpp create mode 100644 libsecurity_codesigning/lib/detachedrep.h create mode 100644 libsecurity_codesigning/lib/diskrep.cpp create mode 100644 libsecurity_codesigning/lib/diskrep.h create mode 100644 libsecurity_codesigning/lib/drmaker.cpp create mode 100644 libsecurity_codesigning/lib/drmaker.h create mode 100644 libsecurity_codesigning/lib/filediskrep.cpp create mode 100644 libsecurity_codesigning/lib/filediskrep.h create mode 100644 libsecurity_codesigning/lib/kerneldiskrep.cpp create mode 100644 libsecurity_codesigning/lib/kerneldiskrep.h create mode 100644 libsecurity_codesigning/lib/machorep.cpp create mode 100644 libsecurity_codesigning/lib/machorep.h create mode 100644 libsecurity_codesigning/lib/policydb.cpp create mode 100644 libsecurity_codesigning/lib/policydb.h create mode 100644 libsecurity_codesigning/lib/policyengine.cpp create mode 100644 libsecurity_codesigning/lib/policyengine.h create mode 100644 libsecurity_codesigning/lib/quarantine++.cpp create mode 100644 libsecurity_codesigning/lib/quarantine++.h create mode 100644 libsecurity_codesigning/lib/renum.cpp create mode 100644 libsecurity_codesigning/lib/renum.h create mode 100644 libsecurity_codesigning/lib/reqdumper.cpp create mode 100644 libsecurity_codesigning/lib/reqdumper.h create mode 100644 libsecurity_codesigning/lib/reqinterp.cpp create mode 100644 libsecurity_codesigning/lib/reqinterp.h create mode 100644 libsecurity_codesigning/lib/reqmaker.cpp create mode 100644 libsecurity_codesigning/lib/reqmaker.h create mode 100644 libsecurity_codesigning/lib/reqparser.cpp create mode 100644 libsecurity_codesigning/lib/reqparser.h create mode 100644 libsecurity_codesigning/lib/reqreader.cpp create mode 100644 libsecurity_codesigning/lib/reqreader.h create mode 100644 libsecurity_codesigning/lib/requirement.cpp create mode 100644 libsecurity_codesigning/lib/requirement.h create mode 100644 libsecurity_codesigning/lib/resources.cpp create mode 100644 libsecurity_codesigning/lib/resources.h create mode 100644 libsecurity_codesigning/lib/security_codesigning.d create mode 100644 libsecurity_codesigning/lib/security_codesigning.exp create mode 100644 libsecurity_codesigning/lib/sigblob.cpp create mode 100644 libsecurity_codesigning/lib/sigblob.h create mode 100644 libsecurity_codesigning/lib/signer.cpp create mode 100644 libsecurity_codesigning/lib/signer.h create mode 100644 libsecurity_codesigning/lib/signerutils.cpp create mode 100644 libsecurity_codesigning/lib/signerutils.h create mode 100644 libsecurity_codesigning/lib/singlediskrep.cpp create mode 100644 libsecurity_codesigning/lib/singlediskrep.h create mode 100644 libsecurity_codesigning/lib/slcrep.cpp create mode 100644 libsecurity_codesigning/lib/slcrep.h create mode 100644 libsecurity_codesigning/lib/syspolicy.sql create mode 100644 libsecurity_codesigning/lib/xar++.cpp create mode 100644 libsecurity_codesigning/lib/xar++.h create mode 100644 libsecurity_codesigning/lib/xpcengine.cpp create mode 100644 libsecurity_codesigning/lib/xpcengine.h create mode 100644 libsecurity_codesigning/libsecurity_codesigning.xcodeproj/project.pbxproj create mode 100644 libsecurity_codesigning/req/cfm.ireqs create mode 100644 libsecurity_codesigning/req/ppc-host.ireq create mode 100644 libsecurity_codesigning/requirements.grammar create mode 100644 libsecurity_comcryption/Info-security_comcryption.plist create mode 100644 libsecurity_comcryption/lib/comDebug.h create mode 100644 libsecurity_comcryption/lib/comcryptPriv.c create mode 100644 libsecurity_comcryption/lib/comcryptPriv.h create mode 100644 libsecurity_comcryption/lib/comcryption.c create mode 100644 libsecurity_comcryption/lib/comcryption.h create mode 100644 libsecurity_comcryption/libsecurity_comcryption.xcodeproj/project.pbxproj create mode 100644 libsecurity_cryptkit/Info-security_cryptkit.plist create mode 100644 libsecurity_cryptkit/ckutils/Makefile create mode 100644 libsecurity_cryptkit/ckutils/Makefile.common create mode 100644 libsecurity_cryptkit/ckutils/atomTime/Makefile create mode 100644 libsecurity_cryptkit/ckutils/atomTime/atomTime.c create mode 100644 libsecurity_cryptkit/ckutils/badsig/Makefile create mode 100644 libsecurity_cryptkit/ckutils/badsig/badsig.c create mode 100644 libsecurity_cryptkit/ckutils/blobtest/Makefile create mode 100644 libsecurity_cryptkit/ckutils/blobtest/blobtest.c create mode 100644 libsecurity_cryptkit/ckutils/cfileTest/Makefile create mode 100644 libsecurity_cryptkit/ckutils/cfileTest/cfileTest.c create mode 100644 libsecurity_cryptkit/ckutils/ckutilsPlatform.h create mode 100644 libsecurity_cryptkit/ckutils/giantAsmBench/Makefile create mode 100644 libsecurity_cryptkit/ckutils/giantAsmBench/giantAsmBench.c create mode 100644 libsecurity_cryptkit/ckutils/giantBench/Makefile create mode 100644 libsecurity_cryptkit/ckutils/giantBench/giantBench.c create mode 100644 libsecurity_cryptkit/ckutils/giantDvt/Makefile create mode 100644 libsecurity_cryptkit/ckutils/giantDvt/giantDvt.c create mode 100644 libsecurity_cryptkit/ckutils/sigTime/Makefile create mode 100644 libsecurity_cryptkit/ckutils/sigTime/sigTime.cpp create mode 100644 libsecurity_cryptkit/lib/ByteRep.txt create mode 100644 libsecurity_cryptkit/lib/CipherFileDES.c create mode 100644 libsecurity_cryptkit/lib/CipherFileDES.h create mode 100644 libsecurity_cryptkit/lib/CipherFileFEED.c create mode 100644 libsecurity_cryptkit/lib/CipherFileFEED.h create mode 100644 libsecurity_cryptkit/lib/CipherFileTypes.h create mode 100644 libsecurity_cryptkit/lib/Crypt.h create mode 100644 libsecurity_cryptkit/lib/CryptKit.def create mode 100644 libsecurity_cryptkit/lib/CryptKit.h create mode 100644 libsecurity_cryptkit/lib/CryptKitAsn1.cpp create mode 100644 libsecurity_cryptkit/lib/CryptKitAsn1.h create mode 100644 libsecurity_cryptkit/lib/CryptKitDER.cpp create mode 100644 libsecurity_cryptkit/lib/CryptKitDER.h create mode 100644 libsecurity_cryptkit/lib/CryptKitSA.h create mode 100644 libsecurity_cryptkit/lib/CurveParamDocs/FEEDaffine.nb create mode 100644 libsecurity_cryptkit/lib/CurveParamDocs/FEEDsansY.nb create mode 100644 libsecurity_cryptkit/lib/CurveParamDocs/README create mode 100644 libsecurity_cryptkit/lib/CurveParamDocs/curvegen.c create mode 100644 libsecurity_cryptkit/lib/CurveParamDocs/curverecords.nb create mode 100644 libsecurity_cryptkit/lib/CurveParamDocs/disc.h create mode 100644 libsecurity_cryptkit/lib/CurveParamDocs/ellproj.c create mode 100644 libsecurity_cryptkit/lib/CurveParamDocs/ellproj.h create mode 100644 libsecurity_cryptkit/lib/CurveParamDocs/factor.c create mode 100644 libsecurity_cryptkit/lib/CurveParamDocs/fmodule.c create mode 100644 libsecurity_cryptkit/lib/CurveParamDocs/fmodule.h create mode 100644 libsecurity_cryptkit/lib/CurveParamDocs/giants.c create mode 100644 libsecurity_cryptkit/lib/CurveParamDocs/giants.h create mode 100644 libsecurity_cryptkit/lib/CurveParamDocs/schoof.c create mode 100644 libsecurity_cryptkit/lib/CurveParamDocs/schoofs.c create mode 100644 libsecurity_cryptkit/lib/CurveParamDocs/tools.c create mode 100644 libsecurity_cryptkit/lib/CurveParamDocs/tools.h create mode 100644 libsecurity_cryptkit/lib/ECDSA_Profile.h create mode 100644 libsecurity_cryptkit/lib/ECDSA_Verify_Prefix.h create mode 100644 libsecurity_cryptkit/lib/HmacSha1Legacy.c create mode 100644 libsecurity_cryptkit/lib/HmacSha1Legacy.h create mode 100644 libsecurity_cryptkit/lib/Mathematica.FEE create mode 100644 libsecurity_cryptkit/lib/NSCipherFile.h create mode 100644 libsecurity_cryptkit/lib/NSCipherFile.m create mode 100644 libsecurity_cryptkit/lib/NSCryptors.h create mode 100644 libsecurity_cryptkit/lib/NSDESCryptor.h create mode 100644 libsecurity_cryptkit/lib/NSDESCryptor.m create mode 100644 libsecurity_cryptkit/lib/NSFEEPublicKey.h create mode 100644 libsecurity_cryptkit/lib/NSFEEPublicKey.m create mode 100644 libsecurity_cryptkit/lib/NSFEEPublicKeyPrivate.h create mode 100644 libsecurity_cryptkit/lib/NSMD5Hash.h create mode 100644 libsecurity_cryptkit/lib/NSMD5Hash.m create mode 100644 libsecurity_cryptkit/lib/NSRandomNumberGenerator.h create mode 100644 libsecurity_cryptkit/lib/NSRandomNumberGenerator.m create mode 100644 libsecurity_cryptkit/lib/README create mode 100644 libsecurity_cryptkit/lib/TOP_README create mode 100644 libsecurity_cryptkit/lib/buildSrcTree create mode 100644 libsecurity_cryptkit/lib/byteRep.c create mode 100644 libsecurity_cryptkit/lib/byteRep.h create mode 100644 libsecurity_cryptkit/lib/changes create mode 100644 libsecurity_cryptkit/lib/ckDES.c create mode 100644 libsecurity_cryptkit/lib/ckDES.h create mode 100644 libsecurity_cryptkit/lib/ckMD5.c create mode 100644 libsecurity_cryptkit/lib/ckMD5.h create mode 100644 libsecurity_cryptkit/lib/ckSHA1.c create mode 100644 libsecurity_cryptkit/lib/ckSHA1.h create mode 100644 libsecurity_cryptkit/lib/ckSHA1_priv.c create mode 100644 libsecurity_cryptkit/lib/ckSHA1_priv.h create mode 100644 libsecurity_cryptkit/lib/ckconfig.h create mode 100644 libsecurity_cryptkit/lib/ckutilities.c create mode 100644 libsecurity_cryptkit/lib/ckutilities.h create mode 100644 libsecurity_cryptkit/lib/curveParamData.h create mode 100644 libsecurity_cryptkit/lib/curveParamDataOld.h create mode 100644 libsecurity_cryptkit/lib/curveParams.c create mode 100644 libsecurity_cryptkit/lib/curveParams.h create mode 100644 libsecurity_cryptkit/lib/elliptic.c create mode 100644 libsecurity_cryptkit/lib/elliptic.h create mode 100644 libsecurity_cryptkit/lib/ellipticMeasure.h create mode 100644 libsecurity_cryptkit/lib/ellipticProj.c create mode 100644 libsecurity_cryptkit/lib/ellipticProj.h create mode 100644 libsecurity_cryptkit/lib/enc64.c create mode 100644 libsecurity_cryptkit/lib/enc64.h create mode 100644 libsecurity_cryptkit/lib/engineNSA127.c create mode 100644 libsecurity_cryptkit/lib/falloc.c create mode 100644 libsecurity_cryptkit/lib/falloc.h create mode 100644 libsecurity_cryptkit/lib/feeCipherFile.c create mode 100644 libsecurity_cryptkit/lib/feeCipherFile.h create mode 100644 libsecurity_cryptkit/lib/feeCipherFileAtom.c create mode 100644 libsecurity_cryptkit/lib/feeDES.c create mode 100644 libsecurity_cryptkit/lib/feeDES.h create mode 100644 libsecurity_cryptkit/lib/feeDebug.h create mode 100644 libsecurity_cryptkit/lib/feeDigitalSignature.c create mode 100644 libsecurity_cryptkit/lib/feeDigitalSignature.h create mode 100644 libsecurity_cryptkit/lib/feeECDSA.c create mode 100644 libsecurity_cryptkit/lib/feeECDSA.h create mode 100644 libsecurity_cryptkit/lib/feeFEED.c create mode 100644 libsecurity_cryptkit/lib/feeFEED.h create mode 100644 libsecurity_cryptkit/lib/feeFEEDExp.c create mode 100644 libsecurity_cryptkit/lib/feeFEEDExp.h create mode 100644 libsecurity_cryptkit/lib/feeFunctions.h create mode 100644 libsecurity_cryptkit/lib/feeHash.c create mode 100644 libsecurity_cryptkit/lib/feeHash.h create mode 100644 libsecurity_cryptkit/lib/feePublicKey.c create mode 100644 libsecurity_cryptkit/lib/feePublicKey.h create mode 100644 libsecurity_cryptkit/lib/feePublicKeyPrivate.h create mode 100644 libsecurity_cryptkit/lib/feeRandom.c create mode 100644 libsecurity_cryptkit/lib/feeRandom.h create mode 100644 libsecurity_cryptkit/lib/feeTypes.h create mode 100644 libsecurity_cryptkit/lib/giantFFT.c create mode 100644 libsecurity_cryptkit/lib/giantIntegers.c create mode 100644 libsecurity_cryptkit/lib/giantIntegers.h create mode 100644 libsecurity_cryptkit/lib/giantPortCommon.h create mode 100644 libsecurity_cryptkit/lib/giantPort_Generic.h create mode 100644 libsecurity_cryptkit/lib/giantPort_PPC.c create mode 100644 libsecurity_cryptkit/lib/giantPort_PPC.h create mode 100644 libsecurity_cryptkit/lib/giantPort_PPC_Gnu.h create mode 100644 libsecurity_cryptkit/lib/giantPort_PPC_Gnu.s create mode 100644 libsecurity_cryptkit/lib/giantPort_i486.h create mode 100644 libsecurity_cryptkit/lib/giantPort_i486.s create mode 100644 libsecurity_cryptkit/lib/mutils.h create mode 100644 libsecurity_cryptkit/lib/mutils.m create mode 100644 libsecurity_cryptkit/lib/platform.c create mode 100644 libsecurity_cryptkit/lib/platform.h create mode 100644 libsecurity_cryptkit/lib/unixMakefile create mode 100644 libsecurity_cryptkit/libsecurity_cryptkit.xcodeproj/project.pbxproj create mode 100644 libsecurity_cssm/APPLE_LICENSE create mode 100644 libsecurity_cssm/Info-security_cssm.plist create mode 100644 libsecurity_cssm/lib/attachfactory.cpp create mode 100644 libsecurity_cssm/lib/attachfactory.h create mode 100644 libsecurity_cssm/lib/attachment.cpp create mode 100644 libsecurity_cssm/lib/attachment.h create mode 100644 libsecurity_cssm/lib/certextensions.h create mode 100644 libsecurity_cssm/lib/cspattachment.cpp create mode 100644 libsecurity_cssm/lib/cspattachment.h create mode 100644 libsecurity_cssm/lib/cssm.cpp create mode 100644 libsecurity_cssm/lib/cssm.h create mode 100644 libsecurity_cssm/lib/cssmaci.h create mode 100644 libsecurity_cssm/lib/cssmapi.h create mode 100644 libsecurity_cssm/lib/cssmapple.h create mode 100644 libsecurity_cssm/lib/cssmapplePriv.h create mode 100644 libsecurity_cssm/lib/cssmcli.h create mode 100644 libsecurity_cssm/lib/cssmconfig.h create mode 100644 libsecurity_cssm/lib/cssmcontext.cpp create mode 100644 libsecurity_cssm/lib/cssmcontext.h create mode 100644 libsecurity_cssm/lib/cssmcspi.h create mode 100644 libsecurity_cssm/lib/cssmdli.h create mode 100644 libsecurity_cssm/lib/cssmerr.h create mode 100644 libsecurity_cssm/lib/cssmint.h create mode 100644 libsecurity_cssm/lib/cssmkrapi.h create mode 100644 libsecurity_cssm/lib/cssmkrspi.h create mode 100644 libsecurity_cssm/lib/cssmmds.cpp create mode 100644 libsecurity_cssm/lib/cssmmds.h create mode 100644 libsecurity_cssm/lib/cssmspi.h create mode 100644 libsecurity_cssm/lib/cssmtpi.h create mode 100644 libsecurity_cssm/lib/cssmtype.h create mode 100644 libsecurity_cssm/lib/eisl.h create mode 100644 libsecurity_cssm/lib/emmspi.h create mode 100644 libsecurity_cssm/lib/emmtype.h create mode 100644 libsecurity_cssm/lib/generator.cfg create mode 100644 libsecurity_cssm/lib/generator.mk create mode 100644 libsecurity_cssm/lib/generator.pl create mode 100644 libsecurity_cssm/lib/guids.cpp create mode 100644 libsecurity_cssm/lib/manager.cpp create mode 100644 libsecurity_cssm/lib/manager.h create mode 100644 libsecurity_cssm/lib/modload_plugin.cpp create mode 100644 libsecurity_cssm/lib/modload_plugin.h create mode 100644 libsecurity_cssm/lib/modload_static.cpp create mode 100644 libsecurity_cssm/lib/modload_static.h create mode 100644 libsecurity_cssm/lib/modloader.cpp create mode 100644 libsecurity_cssm/lib/modloader.h create mode 100644 libsecurity_cssm/lib/module.cpp create mode 100644 libsecurity_cssm/lib/module.h create mode 100644 libsecurity_cssm/lib/oidsalg.c create mode 100644 libsecurity_cssm/lib/oidsbase.h create mode 100644 libsecurity_cssm/lib/oidscert.cpp create mode 100644 libsecurity_cssm/lib/oidscert.h create mode 100644 libsecurity_cssm/lib/oidscrl.cpp create mode 100644 libsecurity_cssm/lib/oidscrl.h create mode 100644 libsecurity_cssm/lib/security_cssm.exp create mode 100644 libsecurity_cssm/lib/transition.cpp create mode 100644 libsecurity_cssm/lib/x509defs.h create mode 100644 libsecurity_cssm/libsecurity_cssm.xcodeproj/project.pbxproj create mode 100644 libsecurity_cssm/mds/cssm.mdsinfo create mode 100644 libsecurity_filedb/Info-security_filedb.plist create mode 100644 libsecurity_filedb/lib/AppleDatabase.cpp create mode 100644 libsecurity_filedb/lib/AppleDatabase.h create mode 100644 libsecurity_filedb/lib/AtomicFile.cpp create mode 100644 libsecurity_filedb/lib/AtomicFile.h create mode 100644 libsecurity_filedb/lib/DbIndex.cpp create mode 100644 libsecurity_filedb/lib/DbIndex.h create mode 100644 libsecurity_filedb/lib/DbQuery.cpp create mode 100644 libsecurity_filedb/lib/DbQuery.h create mode 100644 libsecurity_filedb/lib/DbValue.cpp create mode 100644 libsecurity_filedb/lib/DbValue.h create mode 100644 libsecurity_filedb/lib/MetaAttribute.cpp create mode 100644 libsecurity_filedb/lib/MetaAttribute.h create mode 100644 libsecurity_filedb/lib/MetaRecord.cpp create mode 100644 libsecurity_filedb/lib/MetaRecord.h create mode 100644 libsecurity_filedb/lib/OverUnderflowCheck.h create mode 100644 libsecurity_filedb/lib/ReadWriteSection.cpp create mode 100644 libsecurity_filedb/lib/ReadWriteSection.h create mode 100644 libsecurity_filedb/lib/SelectionPredicate.cpp create mode 100644 libsecurity_filedb/lib/SelectionPredicate.h create mode 100644 libsecurity_filedb/libsecurity_filedb.xcodeproj/project.pbxproj create mode 100644 libsecurity_keychain/APPLE_LICENSE create mode 100644 libsecurity_keychain/Info-security_keychain.plist create mode 100644 libsecurity_keychain/lib/ACL.cpp create mode 100644 libsecurity_keychain/lib/ACL.h create mode 100644 libsecurity_keychain/lib/Access.cpp create mode 100644 libsecurity_keychain/lib/Access.h create mode 100644 libsecurity_keychain/lib/CCallbackMgr.cp create mode 100644 libsecurity_keychain/lib/CCallbackMgr.h create mode 100644 libsecurity_keychain/lib/Certificate.cpp create mode 100644 libsecurity_keychain/lib/Certificate.h create mode 100644 libsecurity_keychain/lib/CertificateRequest.cpp create mode 100644 libsecurity_keychain/lib/CertificateRequest.h create mode 100644 libsecurity_keychain/lib/CertificateValues.cpp create mode 100644 libsecurity_keychain/lib/CertificateValues.h create mode 100644 libsecurity_keychain/lib/DLDBListCFPref.cpp create mode 100644 libsecurity_keychain/lib/DLDBListCFPref.h create mode 100644 libsecurity_keychain/lib/DynamicDLDBList.cpp create mode 100644 libsecurity_keychain/lib/DynamicDLDBList.h create mode 100644 libsecurity_keychain/lib/ExtendedAttribute.cpp create mode 100644 libsecurity_keychain/lib/ExtendedAttribute.h create mode 100644 libsecurity_keychain/lib/Globals.cpp create mode 100644 libsecurity_keychain/lib/Globals.h create mode 100644 libsecurity_keychain/lib/Identity.cpp create mode 100644 libsecurity_keychain/lib/Identity.h create mode 100644 libsecurity_keychain/lib/IdentityCursor.cpp create mode 100644 libsecurity_keychain/lib/IdentityCursor.h create mode 100644 libsecurity_keychain/lib/Item.cpp create mode 100644 libsecurity_keychain/lib/Item.h create mode 100644 libsecurity_keychain/lib/KCCursor.cpp create mode 100644 libsecurity_keychain/lib/KCCursor.h create mode 100644 libsecurity_keychain/lib/KCEventNotifier.cpp create mode 100644 libsecurity_keychain/lib/KCEventNotifier.h create mode 100644 libsecurity_keychain/lib/KCExceptions.h create mode 100644 libsecurity_keychain/lib/KCUtilities.cpp create mode 100644 libsecurity_keychain/lib/KCUtilities.h create mode 100644 libsecurity_keychain/lib/KeyItem.cpp create mode 100644 libsecurity_keychain/lib/KeyItem.h create mode 100644 libsecurity_keychain/lib/Keychains.cpp create mode 100644 libsecurity_keychain/lib/Keychains.h create mode 100644 libsecurity_keychain/lib/MacOSErrorStrings.h create mode 100644 libsecurity_keychain/lib/Password.cpp create mode 100644 libsecurity_keychain/lib/Password.h create mode 100644 libsecurity_keychain/lib/Policies.cpp create mode 100644 libsecurity_keychain/lib/Policies.h create mode 100644 libsecurity_keychain/lib/PolicyCursor.cpp create mode 100644 libsecurity_keychain/lib/PolicyCursor.h create mode 100644 libsecurity_keychain/lib/PrimaryKey.cpp create mode 100644 libsecurity_keychain/lib/PrimaryKey.h create mode 100644 libsecurity_keychain/lib/SecACL.cpp create mode 100644 libsecurity_keychain/lib/SecACL.h create mode 100644 libsecurity_keychain/lib/SecAccess.cpp create mode 100644 libsecurity_keychain/lib/SecAccess.h create mode 100644 libsecurity_keychain/lib/SecAccessPriv.h create mode 100644 libsecurity_keychain/lib/SecAsn1TypesP.h create mode 100644 libsecurity_keychain/lib/SecBase.cpp create mode 100644 libsecurity_keychain/lib/SecBase.h create mode 100644 libsecurity_keychain/lib/SecBase64P.c create mode 100644 libsecurity_keychain/lib/SecBase64P.h create mode 100644 libsecurity_keychain/lib/SecBaseP.h create mode 100644 libsecurity_keychain/lib/SecBasePriv.h create mode 100644 libsecurity_keychain/lib/SecBridge.h create mode 100644 libsecurity_keychain/lib/SecCFTypes.cpp create mode 100644 libsecurity_keychain/lib/SecCFTypes.h create mode 100644 libsecurity_keychain/lib/SecCertificate.cpp create mode 100644 libsecurity_keychain/lib/SecCertificate.h create mode 100644 libsecurity_keychain/lib/SecCertificateBundle.cpp create mode 100644 libsecurity_keychain/lib/SecCertificateBundle.h create mode 100644 libsecurity_keychain/lib/SecCertificateInternalP.h create mode 100644 libsecurity_keychain/lib/SecCertificateOIDs.h create mode 100644 libsecurity_keychain/lib/SecCertificateP.c create mode 100644 libsecurity_keychain/lib/SecCertificateP.h create mode 100644 libsecurity_keychain/lib/SecCertificatePriv.h create mode 100644 libsecurity_keychain/lib/SecCertificatePrivP.h create mode 100644 libsecurity_keychain/lib/SecCertificateRequest.cpp create mode 100644 libsecurity_keychain/lib/SecCertificateRequest.h create mode 100644 libsecurity_keychain/lib/SecExport.cpp create mode 100644 libsecurity_keychain/lib/SecExternalRep.cpp create mode 100644 libsecurity_keychain/lib/SecExternalRep.h create mode 100644 libsecurity_keychain/lib/SecFDERecoveryAsymmetricCrypto.cpp create mode 100644 libsecurity_keychain/lib/SecFDERecoveryAsymmetricCrypto.h create mode 100644 libsecurity_keychain/lib/SecFrameworkP.c create mode 100644 libsecurity_keychain/lib/SecFrameworkP.h create mode 100644 libsecurity_keychain/lib/SecIdentity.cpp create mode 100644 libsecurity_keychain/lib/SecIdentity.h create mode 100644 libsecurity_keychain/lib/SecIdentityPriv.h create mode 100644 libsecurity_keychain/lib/SecIdentitySearch.cpp create mode 100644 libsecurity_keychain/lib/SecIdentitySearch.h create mode 100644 libsecurity_keychain/lib/SecIdentitySearchPriv.h create mode 100644 libsecurity_keychain/lib/SecImport.cpp create mode 100644 libsecurity_keychain/lib/SecImportExport.c create mode 100644 libsecurity_keychain/lib/SecImportExport.h create mode 100644 libsecurity_keychain/lib/SecImportExportAgg.cpp create mode 100644 libsecurity_keychain/lib/SecImportExportAgg.h create mode 100644 libsecurity_keychain/lib/SecImportExportCrypto.cpp create mode 100644 libsecurity_keychain/lib/SecImportExportCrypto.h create mode 100644 libsecurity_keychain/lib/SecImportExportOpenSSH.cpp create mode 100644 libsecurity_keychain/lib/SecImportExportOpenSSH.h create mode 100644 libsecurity_keychain/lib/SecImportExportPem.cpp create mode 100644 libsecurity_keychain/lib/SecImportExportPem.h create mode 100644 libsecurity_keychain/lib/SecImportExportPkcs8.cpp create mode 100644 libsecurity_keychain/lib/SecImportExportPkcs8.h create mode 100644 libsecurity_keychain/lib/SecImportExportUtils.cpp create mode 100644 libsecurity_keychain/lib/SecImportExportUtils.h create mode 100644 libsecurity_keychain/lib/SecInternal.h create mode 100644 libsecurity_keychain/lib/SecInternalP.h create mode 100644 libsecurity_keychain/lib/SecItem.cpp create mode 100644 libsecurity_keychain/lib/SecItem.h create mode 100644 libsecurity_keychain/lib/SecItemConstants.c create mode 100644 libsecurity_keychain/lib/SecItemPriv.h create mode 100644 libsecurity_keychain/lib/SecKey.cpp create mode 100644 libsecurity_keychain/lib/SecKey.h create mode 100644 libsecurity_keychain/lib/SecKeyPriv.h create mode 100644 libsecurity_keychain/lib/SecKeychain.cpp create mode 100644 libsecurity_keychain/lib/SecKeychain.h create mode 100644 libsecurity_keychain/lib/SecKeychainAddIToolsPassword.cpp create mode 100644 libsecurity_keychain/lib/SecKeychainItem.cpp create mode 100644 libsecurity_keychain/lib/SecKeychainItem.h create mode 100644 libsecurity_keychain/lib/SecKeychainItemExtendedAttributes.cpp create mode 100644 libsecurity_keychain/lib/SecKeychainItemExtendedAttributes.h create mode 100644 libsecurity_keychain/lib/SecKeychainItemPriv.h create mode 100644 libsecurity_keychain/lib/SecKeychainPriv.h create mode 100644 libsecurity_keychain/lib/SecKeychainSearch.cpp create mode 100644 libsecurity_keychain/lib/SecKeychainSearch.h create mode 100644 libsecurity_keychain/lib/SecKeychainSearchPriv.h create mode 100644 libsecurity_keychain/lib/SecNetscapeTemplates.cpp create mode 100644 libsecurity_keychain/lib/SecNetscapeTemplates.h create mode 100644 libsecurity_keychain/lib/SecPassword.cpp create mode 100644 libsecurity_keychain/lib/SecPassword.h create mode 100644 libsecurity_keychain/lib/SecPkcs8Templates.cpp create mode 100644 libsecurity_keychain/lib/SecPkcs8Templates.h create mode 100644 libsecurity_keychain/lib/SecPolicy.cpp create mode 100644 libsecurity_keychain/lib/SecPolicy.h create mode 100644 libsecurity_keychain/lib/SecPolicyPriv.h create mode 100644 libsecurity_keychain/lib/SecPolicySearch.cpp create mode 100644 libsecurity_keychain/lib/SecPolicySearch.h create mode 100644 libsecurity_keychain/lib/SecRSAKeyP.h create mode 100644 libsecurity_keychain/lib/SecRandom.c create mode 100644 libsecurity_keychain/lib/SecRandom.h create mode 100644 libsecurity_keychain/lib/SecRandomP.h create mode 100644 libsecurity_keychain/lib/SecRecoveryPassword.c create mode 100644 libsecurity_keychain/lib/SecRecoveryPassword.h create mode 100644 libsecurity_keychain/lib/SecTrust.cpp create mode 100644 libsecurity_keychain/lib/SecTrust.h create mode 100644 libsecurity_keychain/lib/SecTrustPriv.h create mode 100644 libsecurity_keychain/lib/SecTrustSettings.cpp create mode 100644 libsecurity_keychain/lib/SecTrustSettings.h create mode 100644 libsecurity_keychain/lib/SecTrustSettingsPriv.h create mode 100644 libsecurity_keychain/lib/SecTrustedApplication.cpp create mode 100644 libsecurity_keychain/lib/SecTrustedApplication.h create mode 100644 libsecurity_keychain/lib/SecTrustedApplicationPriv.h create mode 100644 libsecurity_keychain/lib/SecWrappedKeys.cpp create mode 100644 libsecurity_keychain/lib/Security.h create mode 100644 libsecurity_keychain/lib/StorageManager.cpp create mode 100644 libsecurity_keychain/lib/StorageManager.h create mode 100644 libsecurity_keychain/lib/Trust.cpp create mode 100644 libsecurity_keychain/lib/Trust.h create mode 100644 libsecurity_keychain/lib/TrustAdditions.cpp create mode 100644 libsecurity_keychain/lib/TrustAdditions.h create mode 100644 libsecurity_keychain/lib/TrustItem.cpp create mode 100644 libsecurity_keychain/lib/TrustItem.h create mode 100644 libsecurity_keychain/lib/TrustKeychains.h create mode 100644 libsecurity_keychain/lib/TrustRevocation.cpp create mode 100644 libsecurity_keychain/lib/TrustSettings.cpp create mode 100644 libsecurity_keychain/lib/TrustSettings.h create mode 100644 libsecurity_keychain/lib/TrustSettingsSchema.h create mode 100644 libsecurity_keychain/lib/TrustSettingsUtils.cpp create mode 100644 libsecurity_keychain/lib/TrustSettingsUtils.h create mode 100644 libsecurity_keychain/lib/TrustStore.cpp create mode 100644 libsecurity_keychain/lib/TrustStore.h create mode 100644 libsecurity_keychain/lib/TrustedApplication.cpp create mode 100644 libsecurity_keychain/lib/TrustedApplication.h create mode 100644 libsecurity_keychain/lib/UnlockReferralItem.cpp create mode 100644 libsecurity_keychain/lib/UnlockReferralItem.h create mode 100644 libsecurity_keychain/lib/certextensionsP.h create mode 100644 libsecurity_keychain/lib/cssmdatetime.cpp create mode 100644 libsecurity_keychain/lib/cssmdatetime.h create mode 100644 libsecurity_keychain/lib/debuggingP.c create mode 100644 libsecurity_keychain/lib/debuggingP.h create mode 100644 libsecurity_keychain/lib/defaultcreds.cpp create mode 100644 libsecurity_keychain/lib/defaultcreds.h create mode 100644 libsecurity_keychain/lib/generateErrStrings.pl create mode 100644 libsecurity_keychain/lib/security_keychain.exp create mode 100644 libsecurity_keychain/lib/tsaDERUtilities.c create mode 100644 libsecurity_keychain/lib/tsaDERUtilities.h create mode 100644 libsecurity_keychain/libDER/README.txt create mode 100644 libsecurity_keychain/libDER/Tests/AppleMobilePersonalizedTicket.h create mode 100644 libsecurity_keychain/libDER/Tests/DER_Ticket.c create mode 100644 libsecurity_keychain/libDER/Tests/DER_Ticket.h create mode 100644 libsecurity_keychain/libDER/Tests/certsCrls/EndCertificateCP.01.01.crt create mode 100644 libsecurity_keychain/libDER/Tests/certsCrls/Test_CRL_CA1.crl create mode 100644 libsecurity_keychain/libDER/Tests/certsCrls/Test_CRL_CA1.crl.pem create mode 100644 libsecurity_keychain/libDER/Tests/certsCrls/TrustAnchorCP.01.01.crt create mode 100644 libsecurity_keychain/libDER/Tests/certsCrls/TrustAnchorCRLCP.01.01.crl create mode 100644 libsecurity_keychain/libDER/Tests/certsCrls/apple_v3.000.cer create mode 100644 libsecurity_keychain/libDER/Tests/certsCrls/apple_v3.001.cer create mode 100644 libsecurity_keychain/libDER/Tests/certsCrls/entrust_v3.100.cer create mode 100644 libsecurity_keychain/libDER/Tests/certsCrls/entrust_v3.101.cer create mode 100644 libsecurity_keychain/libDER/Tests/certsCrls/keybank_v3.100.cer create mode 100644 libsecurity_keychain/libDER/Tests/certsCrls/keybank_v3.101.cer create mode 100644 libsecurity_keychain/libDER/Tests/certsCrls/keybank_v3.102.cer create mode 100644 libsecurity_keychain/libDER/Tests/parseCert.c create mode 100644 libsecurity_keychain/libDER/Tests/parseCrl.c create mode 100644 libsecurity_keychain/libDER/Tests/parseTicket.c create mode 100644 libsecurity_keychain/libDER/config/base.xcconfig create mode 100644 libsecurity_keychain/libDER/config/debug.xcconfig create mode 100644 libsecurity_keychain/libDER/config/lib.xcconfig create mode 100644 libsecurity_keychain/libDER/config/release.xcconfig create mode 100644 libsecurity_keychain/libDER/libDER.xcodeproj/project.pbxproj create mode 100644 libsecurity_keychain/libDER/libDER/DER_CertCrl.c create mode 100644 libsecurity_keychain/libDER/libDER/DER_CertCrl.h create mode 100644 libsecurity_keychain/libDER/libDER/DER_Decode.c create mode 100644 libsecurity_keychain/libDER/libDER/DER_Decode.h create mode 100644 libsecurity_keychain/libDER/libDER/DER_Digest.c create mode 100644 libsecurity_keychain/libDER/libDER/DER_Digest.h create mode 100644 libsecurity_keychain/libDER/libDER/DER_Encode.c create mode 100644 libsecurity_keychain/libDER/libDER/DER_Encode.h create mode 100644 libsecurity_keychain/libDER/libDER/DER_Keys.c create mode 100644 libsecurity_keychain/libDER/libDER/DER_Keys.h create mode 100644 libsecurity_keychain/libDER/libDER/asn1Types.h create mode 100644 libsecurity_keychain/libDER/libDER/libDER.h create mode 100644 libsecurity_keychain/libDER/libDER/libDER_config.h create mode 100644 libsecurity_keychain/libDER/libDER/oids.c create mode 100644 libsecurity_keychain/libDER/libDER/oids.h create mode 100644 libsecurity_keychain/libDER/libDERUtils/fileIo.c create mode 100644 libsecurity_keychain/libDER/libDERUtils/fileIo.h create mode 100644 libsecurity_keychain/libDER/libDERUtils/libDERUtils.c create mode 100644 libsecurity_keychain/libDER/libDERUtils/libDERUtils.h create mode 100644 libsecurity_keychain/libDER/libDERUtils/printFields.c create mode 100644 libsecurity_keychain/libDER/libDERUtils/printFields.h create mode 100644 libsecurity_keychain/libsecurity_keychain.xcodeproj/project.pbxproj create mode 100644 libsecurity_keychain/plist/iToolsTrustedApps.plist create mode 100644 libsecurity_keychain/xpc-tsa/XPCTimeStampingService-Info.plist create mode 100644 libsecurity_keychain/xpc-tsa/main-tsa.m create mode 100644 libsecurity_keychain/xpc-tsa/timestampclient.h create mode 100644 libsecurity_keychain/xpc-tsa/timestampclient.m create mode 100644 libsecurity_keychain/xpc/XPCKeychainSandboxCheck-Info.plist create mode 100644 libsecurity_keychain/xpc/main.c create mode 100644 libsecurity_manifest/APPLE_LICENSE create mode 100644 libsecurity_manifest/Info-security_manifest.plist create mode 100644 libsecurity_manifest/lib/AppleManifest.cpp create mode 100644 libsecurity_manifest/lib/AppleManifest.h create mode 100644 libsecurity_manifest/lib/Download.cpp create mode 100644 libsecurity_manifest/lib/Download.h create mode 100644 libsecurity_manifest/lib/Manifest.cpp create mode 100644 libsecurity_manifest/lib/Manifest.h create mode 100644 libsecurity_manifest/lib/ManifestInternal.cpp create mode 100644 libsecurity_manifest/lib/ManifestInternal.h create mode 100644 libsecurity_manifest/lib/ManifestSigner.cpp create mode 100644 libsecurity_manifest/lib/ManifestSigner.h create mode 100644 libsecurity_manifest/lib/SecManifest.cpp create mode 100644 libsecurity_manifest/lib/SecManifest.h create mode 100644 libsecurity_manifest/lib/SecureDownload.cpp create mode 100644 libsecurity_manifest/lib/SecureDownload.h create mode 100644 libsecurity_manifest/lib/SecureDownloadInternal.c create mode 100644 libsecurity_manifest/lib/SecureDownloadInternal.h create mode 100644 libsecurity_manifest/lib/security_manifest.exp create mode 100644 libsecurity_manifest/libsecurity_manifest.xcodeproj/project.pbxproj create mode 100644 libsecurity_mds/Info-security_mds.plist create mode 100644 libsecurity_mds/README create mode 100644 libsecurity_mds/lib/MDSAttrParser.cpp create mode 100644 libsecurity_mds/lib/MDSAttrParser.h create mode 100644 libsecurity_mds/lib/MDSAttrStrings.cpp create mode 100644 libsecurity_mds/lib/MDSAttrStrings.h create mode 100644 libsecurity_mds/lib/MDSAttrUtils.cpp create mode 100644 libsecurity_mds/lib/MDSAttrUtils.h create mode 100644 libsecurity_mds/lib/MDSDatabase.cpp create mode 100644 libsecurity_mds/lib/MDSDatabase.h create mode 100644 libsecurity_mds/lib/MDSDictionary.cpp create mode 100644 libsecurity_mds/lib/MDSDictionary.h create mode 100644 libsecurity_mds/lib/MDSModule.cpp create mode 100644 libsecurity_mds/lib/MDSModule.h create mode 100644 libsecurity_mds/lib/MDSPrefs.cpp create mode 100644 libsecurity_mds/lib/MDSPrefs.h create mode 100644 libsecurity_mds/lib/MDSSchema.cpp create mode 100644 libsecurity_mds/lib/MDSSchema.h create mode 100644 libsecurity_mds/lib/MDSSession.cpp create mode 100644 libsecurity_mds/lib/MDSSession.h create mode 100644 libsecurity_mds/lib/mds.h create mode 100644 libsecurity_mds/lib/mds_schema.h create mode 100644 libsecurity_mds/lib/mdsapi.cpp create mode 100644 libsecurity_mds/lib/mdspriv.h create mode 100644 libsecurity_mds/lib/security_mds.exp create mode 100644 libsecurity_mds/libsecurity_mds.xcodeproj/project.pbxproj create mode 100644 libsecurity_ocspd/Info-security_ocspd.plist create mode 100644 libsecurity_ocspd/client/ocspdClient.cpp create mode 100644 libsecurity_ocspd/client/ocspdClient.h create mode 100644 libsecurity_ocspd/common/ocspExtensions.cpp create mode 100644 libsecurity_ocspd/common/ocspExtensions.h create mode 100644 libsecurity_ocspd/common/ocspResponse.cpp create mode 100644 libsecurity_ocspd/common/ocspResponse.h create mode 120000 libsecurity_ocspd/common/ocspdClient.h create mode 100644 libsecurity_ocspd/common/ocspdDbSchema.cpp create mode 100644 libsecurity_ocspd/common/ocspdDbSchema.h create mode 100644 libsecurity_ocspd/common/ocspdDebug.h create mode 100644 libsecurity_ocspd/common/ocspdTypes.h create mode 100644 libsecurity_ocspd/common/ocspdUtils.cpp create mode 100644 libsecurity_ocspd/common/ocspdUtils.h create mode 100644 libsecurity_ocspd/libsecurity_ocspd.xcodeproj/project.pbxproj create mode 100644 libsecurity_ocspd/mig/mig.mk create mode 100644 libsecurity_ocspd/mig/ocspd.defs create mode 100644 libsecurity_pkcs12/APPLE_LICENSE create mode 100644 libsecurity_pkcs12/Info-security_pkcs12.plist create mode 100644 libsecurity_pkcs12/lib/SecPkcs12.cpp create mode 100644 libsecurity_pkcs12/lib/SecPkcs12.h create mode 100644 libsecurity_pkcs12/lib/pkcs12BagAttrs.cpp create mode 100644 libsecurity_pkcs12/lib/pkcs12BagAttrs.h create mode 100644 libsecurity_pkcs12/lib/pkcs12Coder.cpp create mode 100644 libsecurity_pkcs12/lib/pkcs12Coder.h create mode 100644 libsecurity_pkcs12/lib/pkcs12Crypto.cpp create mode 100644 libsecurity_pkcs12/lib/pkcs12Crypto.h create mode 100644 libsecurity_pkcs12/lib/pkcs12Debug.h create mode 100644 libsecurity_pkcs12/lib/pkcs12Decode.cpp create mode 100644 libsecurity_pkcs12/lib/pkcs12Encode.cpp create mode 100644 libsecurity_pkcs12/lib/pkcs12Keychain.cpp create mode 100644 libsecurity_pkcs12/lib/pkcs12SafeBag.cpp create mode 100644 libsecurity_pkcs12/lib/pkcs12SafeBag.h create mode 100644 libsecurity_pkcs12/lib/pkcs12Templates.cpp create mode 100644 libsecurity_pkcs12/lib/pkcs12Templates.h create mode 100644 libsecurity_pkcs12/lib/pkcs12Utils.cpp create mode 100644 libsecurity_pkcs12/lib/pkcs12Utils.h create mode 100644 libsecurity_pkcs12/lib/pkcs7Templates.cpp create mode 100644 libsecurity_pkcs12/lib/pkcs7Templates.h create mode 100644 libsecurity_pkcs12/lib/pkcsoids.cpp create mode 100644 libsecurity_pkcs12/lib/pkcsoids.h create mode 100644 libsecurity_pkcs12/libsecurity_pkcs12.xcodeproj/project.pbxproj create mode 100644 libsecurity_sd_cspdl/APPLE_LICENSE create mode 100644 libsecurity_sd_cspdl/Info-security_sd_cspdl.plist create mode 100644 libsecurity_sd_cspdl/lib/SDCSPDLBuiltin.cpp create mode 100644 libsecurity_sd_cspdl/lib/SDCSPDLDatabase.cpp create mode 100644 libsecurity_sd_cspdl/lib/SDCSPDLDatabase.h create mode 100644 libsecurity_sd_cspdl/lib/SDCSPDLPlugin.cpp create mode 100644 libsecurity_sd_cspdl/lib/SDCSPDLPlugin.h create mode 100644 libsecurity_sd_cspdl/lib/SDCSPDLSession.cpp create mode 100644 libsecurity_sd_cspdl/lib/SDCSPDLSession.h create mode 100644 libsecurity_sd_cspdl/lib/SDCSPSession.cpp create mode 100644 libsecurity_sd_cspdl/lib/SDCSPSession.h create mode 100644 libsecurity_sd_cspdl/lib/SDContext.cpp create mode 100644 libsecurity_sd_cspdl/lib/SDContext.h create mode 100644 libsecurity_sd_cspdl/lib/SDDLSession.cpp create mode 100644 libsecurity_sd_cspdl/lib/SDDLSession.h create mode 100644 libsecurity_sd_cspdl/lib/SDFactory.cpp create mode 100644 libsecurity_sd_cspdl/lib/SDFactory.h create mode 100644 libsecurity_sd_cspdl/lib/SDKey.cpp create mode 100644 libsecurity_sd_cspdl/lib/SDKey.h create mode 100644 libsecurity_sd_cspdl/libsecurity_sd_cspdl.xcodeproj/project.pbxproj create mode 100644 libsecurity_sd_cspdl/mds/sd_cspdl_common.mdsinfo create mode 100644 libsecurity_smime/APPLE_LICENSE create mode 100644 libsecurity_smime/Info-security_smime.plist create mode 100644 libsecurity_smime/TODO create mode 100644 libsecurity_smime/docs/libsecurity_smime.plist create mode 100644 libsecurity_smime/docs/libsecurity_smime.txt create mode 100644 libsecurity_smime/lib/SecCmsBase.h create mode 100644 libsecurity_smime/lib/SecCmsContentInfo.h create mode 100644 libsecurity_smime/lib/SecCmsDecoder.h create mode 100644 libsecurity_smime/lib/SecCmsDigestContext.h create mode 100644 libsecurity_smime/lib/SecCmsDigestedData.h create mode 100644 libsecurity_smime/lib/SecCmsEncoder.h create mode 100644 libsecurity_smime/lib/SecCmsEncryptedData.h create mode 100644 libsecurity_smime/lib/SecCmsEnvelopedData.h create mode 100644 libsecurity_smime/lib/SecCmsMessage.h create mode 100644 libsecurity_smime/lib/SecCmsRecipientInfo.h create mode 100644 libsecurity_smime/lib/SecCmsSignedData.h create mode 100644 libsecurity_smime/lib/SecCmsSignerInfo.h create mode 100644 libsecurity_smime/lib/SecSMIME.h create mode 100644 libsecurity_smime/lib/SecSMIMEPriv.h create mode 100644 libsecurity_smime/lib/cert.c create mode 100644 libsecurity_smime/lib/cert.h create mode 100644 libsecurity_smime/lib/cmsarray.c create mode 100644 libsecurity_smime/lib/cmsasn1.c create mode 100644 libsecurity_smime/lib/cmsattr.c create mode 100644 libsecurity_smime/lib/cmscinfo.c create mode 100644 libsecurity_smime/lib/cmscipher.c create mode 100644 libsecurity_smime/lib/cmsdecode.c create mode 100644 libsecurity_smime/lib/cmsdigdata.c create mode 100644 libsecurity_smime/lib/cmsdigest.c create mode 100644 libsecurity_smime/lib/cmsencdata.c create mode 100644 libsecurity_smime/lib/cmsencode.c create mode 100644 libsecurity_smime/lib/cmsenvdata.c create mode 100644 libsecurity_smime/lib/cmslocal.h create mode 100644 libsecurity_smime/lib/cmsmessage.c create mode 100644 libsecurity_smime/lib/cmspriv.h create mode 100644 libsecurity_smime/lib/cmspubkey.c create mode 100644 libsecurity_smime/lib/cmsrecinfo.c create mode 100644 libsecurity_smime/lib/cmsreclist.c create mode 100644 libsecurity_smime/lib/cmsreclist.h create mode 100644 libsecurity_smime/lib/cmssigdata.c create mode 100644 libsecurity_smime/lib/cmssiginfo.c create mode 100644 libsecurity_smime/lib/cmstpriv.h create mode 100644 libsecurity_smime/lib/cmsutil.c create mode 100644 libsecurity_smime/lib/cryptohi.c create mode 100644 libsecurity_smime/lib/cryptohi.h create mode 100644 libsecurity_smime/lib/plhash.c create mode 100644 libsecurity_smime/lib/plhash.h create mode 100644 libsecurity_smime/lib/secalgid.c create mode 100644 libsecurity_smime/lib/secitem.c create mode 100644 libsecurity_smime/lib/secitem.h create mode 100644 libsecurity_smime/lib/secoid.c create mode 100644 libsecurity_smime/lib/secoid.h create mode 100644 libsecurity_smime/lib/secoidt.h create mode 100644 libsecurity_smime/lib/security_smime.exp create mode 100644 libsecurity_smime/lib/siginfoUtils.cpp create mode 100644 libsecurity_smime/lib/smimeutil.c create mode 100755 libsecurity_smime/lib/testcms create mode 100644 libsecurity_smime/lib/tsaSupport.c create mode 100644 libsecurity_smime/lib/tsaSupport.h create mode 100644 libsecurity_smime/lib/tsaSupportPriv.h create mode 100644 libsecurity_smime/lib/tsaTemplates.c create mode 100644 libsecurity_smime/lib/tsaTemplates.h create mode 100644 libsecurity_smime/libsecurity_smime.xcodeproj/project.pbxproj create mode 100644 libsecurity_ssl/Info-security_ssl.plist create mode 100644 libsecurity_ssl/README create mode 100644 libsecurity_ssl/Security/CipherSuite.h create mode 100644 libsecurity_ssl/Security/SecureTransport.h create mode 100644 libsecurity_ssl/Security/SecureTransportPriv.h create mode 100644 libsecurity_ssl/config/base.xcconfig create mode 100644 libsecurity_ssl/config/debug.xcconfig create mode 100644 libsecurity_ssl/config/lib.xcconfig create mode 100644 libsecurity_ssl/config/release.xcconfig create mode 100644 libsecurity_ssl/lib/ModuleAttacher.c create mode 100644 libsecurity_ssl/lib/ModuleAttacher.h create mode 100644 libsecurity_ssl/lib/appleCdsa.c create mode 100644 libsecurity_ssl/lib/appleCdsa.h create mode 100644 libsecurity_ssl/lib/appleSession.c create mode 100644 libsecurity_ssl/lib/appleSession.h create mode 100644 libsecurity_ssl/lib/cipherSpecs.c create mode 100644 libsecurity_ssl/lib/cipherSpecs.h create mode 100644 libsecurity_ssl/lib/cryptType.h create mode 100644 libsecurity_ssl/lib/securetransport++.cpp create mode 100644 libsecurity_ssl/lib/securetransport++.h create mode 100644 libsecurity_ssl/lib/security_ssl.exp create mode 100644 libsecurity_ssl/lib/ssl.h create mode 100644 libsecurity_ssl/lib/ssl3Callouts.c create mode 100644 libsecurity_ssl/lib/sslAlertMessage.c create mode 100644 libsecurity_ssl/lib/sslAlertMessage.h create mode 100644 libsecurity_ssl/lib/sslBER.c create mode 100644 libsecurity_ssl/lib/sslBER.h create mode 100644 libsecurity_ssl/lib/sslBuildFlags.h create mode 100644 libsecurity_ssl/lib/sslCert.c create mode 100644 libsecurity_ssl/lib/sslChangeCipher.c create mode 100644 libsecurity_ssl/lib/sslContext.c create mode 100644 libsecurity_ssl/lib/sslContext.h create mode 100644 libsecurity_ssl/lib/sslCrypto.c create mode 100644 libsecurity_ssl/lib/sslCrypto.h create mode 100644 libsecurity_ssl/lib/sslDebug.h create mode 100644 libsecurity_ssl/lib/sslDigests.c create mode 100644 libsecurity_ssl/lib/sslDigests.h create mode 100644 libsecurity_ssl/lib/sslHandshake.c create mode 100644 libsecurity_ssl/lib/sslHandshake.h create mode 100644 libsecurity_ssl/lib/sslHandshakeFinish.c create mode 100644 libsecurity_ssl/lib/sslHandshakeHello.c create mode 100644 libsecurity_ssl/lib/sslKeyExchange.c create mode 100644 libsecurity_ssl/lib/sslKeychain.c create mode 100644 libsecurity_ssl/lib/sslKeychain.h create mode 100644 libsecurity_ssl/lib/sslMemory.c create mode 100644 libsecurity_ssl/lib/sslMemory.h create mode 100644 libsecurity_ssl/lib/sslNullCipher.c create mode 100644 libsecurity_ssl/lib/sslPriv.h create mode 100644 libsecurity_ssl/lib/sslRecord.c create mode 100644 libsecurity_ssl/lib/sslRecord.h create mode 100644 libsecurity_ssl/lib/sslSession.c create mode 100644 libsecurity_ssl/lib/sslSession.h create mode 100644 libsecurity_ssl/lib/sslTransport.c create mode 100644 libsecurity_ssl/lib/sslUtils.c create mode 100644 libsecurity_ssl/lib/sslUtils.h create mode 100644 libsecurity_ssl/lib/symCipher.c create mode 100644 libsecurity_ssl/lib/symCipher.h create mode 100644 libsecurity_ssl/lib/tls1Callouts.c create mode 100644 libsecurity_ssl/lib/tls_hmac.c create mode 100644 libsecurity_ssl/lib/tls_hmac.h create mode 100644 libsecurity_ssl/lib/tls_ssl.h create mode 100644 libsecurity_ssl/libsecurity_ssl.xcodeproj/project.pbxproj create mode 120000 libsecurity_ssl/security_ssl create mode 100644 libsecurity_ssl/sslViewer/fileIo.c create mode 100644 libsecurity_ssl/sslViewer/fileIo.h create mode 100644 libsecurity_ssl/sslViewer/ioSock.c create mode 100644 libsecurity_ssl/sslViewer/ioSock.h create mode 100644 libsecurity_ssl/sslViewer/printCert.c create mode 100644 libsecurity_ssl/sslViewer/printCert.h create mode 100644 libsecurity_ssl/sslViewer/sslAppUtils.cpp create mode 100644 libsecurity_ssl/sslViewer/sslAppUtils.h create mode 100644 libsecurity_ssl/sslViewer/sslServer.1 create mode 100644 libsecurity_ssl/sslViewer/sslServer.cpp create mode 100644 libsecurity_ssl/sslViewer/sslViewer.1 create mode 100644 libsecurity_ssl/sslViewer/sslViewer.cpp create mode 100644 libsecurity_ssl/sslViewer/sslViewer.xcodeproj/project.pbxproj create mode 100644 libsecurity_transform/100-sha2.m create mode 100644 libsecurity_transform/Configurations/libsecurity_transform.Default.xcconfig create mode 100644 libsecurity_transform/Configurations/libsecurity_transform_Deployment.xcconfig create mode 100644 libsecurity_transform/Configurations/libsecurity_transform_Development.xcconfig create mode 100644 libsecurity_transform/Configurations/libsecurity_transform_core.xcconfig create mode 100644 libsecurity_transform/Configurations/security_transform_Default.xcconfig create mode 100644 libsecurity_transform/Configurations/security_transform_Deployment.xcconfig create mode 100644 libsecurity_transform/Configurations/security_transform_Development.xcconfig create mode 100644 libsecurity_transform/Info-security_transform.plist create mode 100644 libsecurity_transform/NSData+HexString.h create mode 100644 libsecurity_transform/NSData+HexString.m create mode 100644 libsecurity_transform/custom.h create mode 100644 libsecurity_transform/custom.mm create mode 100644 libsecurity_transform/lib/CEncryptDecrypt.c create mode 100644 libsecurity_transform/lib/CoreFoundationBasics.cpp create mode 100644 libsecurity_transform/lib/CoreFoundationBasics.h create mode 100644 libsecurity_transform/lib/Digest.cpp create mode 100644 libsecurity_transform/lib/Digest.h create mode 100644 libsecurity_transform/lib/Digest_block.c create mode 100644 libsecurity_transform/lib/Digest_block.h create mode 100644 libsecurity_transform/lib/EncodeDecodeTransforms.c create mode 100644 libsecurity_transform/lib/EncryptTransform.cpp create mode 100644 libsecurity_transform/lib/EncryptTransform.h create mode 100644 libsecurity_transform/lib/EncryptTransformUtilities.cpp create mode 100644 libsecurity_transform/lib/EncryptTransformUtilities.h create mode 100644 libsecurity_transform/lib/GroupTransform.cpp create mode 100644 libsecurity_transform/lib/GroupTransform.h create mode 100644 libsecurity_transform/lib/LinkedList.cpp create mode 100644 libsecurity_transform/lib/LinkedList.h create mode 100644 libsecurity_transform/lib/Monitor.cpp create mode 100644 libsecurity_transform/lib/Monitor.h create mode 100644 libsecurity_transform/lib/NullTransform.cpp create mode 100644 libsecurity_transform/lib/NullTransform.h create mode 100644 libsecurity_transform/lib/SecCollectTransform.cpp create mode 100644 libsecurity_transform/lib/SecCollectTransform.h create mode 100644 libsecurity_transform/lib/SecCustomTransform.cpp create mode 100644 libsecurity_transform/lib/SecCustomTransform.h create mode 100644 libsecurity_transform/lib/SecDecodeTransform.h create mode 100644 libsecurity_transform/lib/SecDigestTransform.cpp create mode 100644 libsecurity_transform/lib/SecDigestTransform.h create mode 100644 libsecurity_transform/lib/SecEncodeTransform.h create mode 100644 libsecurity_transform/lib/SecEncryptTransform.cpp create mode 100644 libsecurity_transform/lib/SecEncryptTransform.h create mode 100644 libsecurity_transform/lib/SecExternalSourceTransform.cpp create mode 100644 libsecurity_transform/lib/SecExternalSourceTransform.h create mode 100644 libsecurity_transform/lib/SecGroupTransform.cpp create mode 100644 libsecurity_transform/lib/SecGroupTransform.h create mode 100644 libsecurity_transform/lib/SecMaskGenerationFunctionTransform.c create mode 100644 libsecurity_transform/lib/SecMaskGenerationFunctionTransform.h create mode 100644 libsecurity_transform/lib/SecNullTransform.cpp create mode 100644 libsecurity_transform/lib/SecNullTransform.h create mode 100644 libsecurity_transform/lib/SecReadTransform.h create mode 100644 libsecurity_transform/lib/SecSignVerifyTransform.c create mode 100644 libsecurity_transform/lib/SecSignVerifyTransform.h create mode 100644 libsecurity_transform/lib/SecTransform.cpp create mode 100644 libsecurity_transform/lib/SecTransform.h create mode 100644 libsecurity_transform/lib/SecTransformInternal.h create mode 100644 libsecurity_transform/lib/SecTransformReadTransform.cpp create mode 100644 libsecurity_transform/lib/SecTransformReadTransform.h create mode 100644 libsecurity_transform/lib/SecTransformValidator.h create mode 100644 libsecurity_transform/lib/SingleShotSource.cpp create mode 100644 libsecurity_transform/lib/SingleShotSource.h create mode 100644 libsecurity_transform/lib/Source.cpp create mode 100644 libsecurity_transform/lib/Source.h create mode 100644 libsecurity_transform/lib/StreamSource.cpp create mode 100644 libsecurity_transform/lib/StreamSource.h create mode 100644 libsecurity_transform/lib/Transform.cpp create mode 100644 libsecurity_transform/lib/Transform.h create mode 100644 libsecurity_transform/lib/TransformFactory.cpp create mode 100644 libsecurity_transform/lib/TransformFactory.h create mode 100644 libsecurity_transform/lib/Utilities.cpp create mode 100644 libsecurity_transform/lib/Utilities.h create mode 100644 libsecurity_transform/lib/c++utils.cpp create mode 100644 libsecurity_transform/lib/c++utils.h create mode 100644 libsecurity_transform/lib/misc.c create mode 100644 libsecurity_transform/lib/misc.h create mode 100644 libsecurity_transform/lib/security_transform.exp create mode 100644 libsecurity_transform/libsecurity_transform.xcodeproj/project.pbxproj create mode 100755 libsecurity_transform/misc/base32alpha2vals create mode 100644 libsecurity_transform/misc/speed-test.h create mode 100644 libsecurity_transform/misc/speed-test.mm create mode 100644 libsecurity_transform/unit-tests-Info.plist create mode 100644 libsecurity_utilities/APPLE_LICENSE create mode 100644 libsecurity_utilities/Info-security_utilities.plist create mode 100644 libsecurity_utilities/lib/adornments.cpp create mode 100644 libsecurity_utilities/lib/adornments.h create mode 100644 libsecurity_utilities/lib/alloc.cpp create mode 100644 libsecurity_utilities/lib/alloc.h create mode 100644 libsecurity_utilities/lib/blob.cpp create mode 100644 libsecurity_utilities/lib/blob.h create mode 100644 libsecurity_utilities/lib/bufferfifo.cpp create mode 100644 libsecurity_utilities/lib/bufferfifo.h create mode 100644 libsecurity_utilities/lib/buffers.cpp create mode 100644 libsecurity_utilities/lib/buffers.h create mode 100644 libsecurity_utilities/lib/ccaudit.cpp create mode 100644 libsecurity_utilities/lib/ccaudit.h create mode 100644 libsecurity_utilities/lib/cfclass.cpp create mode 100644 libsecurity_utilities/lib/cfclass.h create mode 100644 libsecurity_utilities/lib/cfmach++.cpp create mode 100644 libsecurity_utilities/lib/cfmach++.h create mode 100644 libsecurity_utilities/lib/cfmunge.cpp create mode 100644 libsecurity_utilities/lib/cfmunge.h create mode 100644 libsecurity_utilities/lib/cfutilities.cpp create mode 100644 libsecurity_utilities/lib/cfutilities.h create mode 100644 libsecurity_utilities/lib/coderepository.cpp create mode 100644 libsecurity_utilities/lib/coderepository.h create mode 100644 libsecurity_utilities/lib/crc.c create mode 100644 libsecurity_utilities/lib/crc.h create mode 100644 libsecurity_utilities/lib/daemon.cpp create mode 100644 libsecurity_utilities/lib/daemon.h create mode 100644 libsecurity_utilities/lib/debugging.cpp create mode 100644 libsecurity_utilities/lib/debugging.h create mode 100644 libsecurity_utilities/lib/debugsupport.h create mode 100644 libsecurity_utilities/lib/devrandom.cpp create mode 100644 libsecurity_utilities/lib/devrandom.h create mode 100644 libsecurity_utilities/lib/dtrace.mk create mode 100644 libsecurity_utilities/lib/dyld_cache_format.h create mode 100644 libsecurity_utilities/lib/dyldcache.cpp create mode 100644 libsecurity_utilities/lib/dyldcache.h create mode 100644 libsecurity_utilities/lib/endian.cpp create mode 100644 libsecurity_utilities/lib/endian.h create mode 100644 libsecurity_utilities/lib/errors.cpp create mode 100644 libsecurity_utilities/lib/errors.h create mode 100644 libsecurity_utilities/lib/fdmover.cpp create mode 100644 libsecurity_utilities/lib/fdmover.h create mode 100644 libsecurity_utilities/lib/fdsel.cpp create mode 100644 libsecurity_utilities/lib/fdsel.h create mode 100644 libsecurity_utilities/lib/globalizer.cpp create mode 100644 libsecurity_utilities/lib/globalizer.h create mode 100644 libsecurity_utilities/lib/hashing.cpp create mode 100644 libsecurity_utilities/lib/hashing.h create mode 100644 libsecurity_utilities/lib/headermap.cpp create mode 100644 libsecurity_utilities/lib/headermap.h create mode 100644 libsecurity_utilities/lib/hosts.cpp create mode 100644 libsecurity_utilities/lib/hosts.h create mode 100644 libsecurity_utilities/lib/inetreply.cpp create mode 100644 libsecurity_utilities/lib/inetreply.h create mode 100644 libsecurity_utilities/lib/iodevices.cpp create mode 100644 libsecurity_utilities/lib/iodevices.h create mode 100644 libsecurity_utilities/lib/ip++.cpp create mode 100644 libsecurity_utilities/lib/ip++.h create mode 100644 libsecurity_utilities/lib/kq++.cpp create mode 100644 libsecurity_utilities/lib/kq++.h create mode 100644 libsecurity_utilities/lib/ktracecodes.h create mode 100644 libsecurity_utilities/lib/logging.cpp create mode 100644 libsecurity_utilities/lib/logging.h create mode 100644 libsecurity_utilities/lib/mach++.cpp create mode 100644 libsecurity_utilities/lib/mach++.h create mode 100644 libsecurity_utilities/lib/mach_notify.c create mode 100644 libsecurity_utilities/lib/mach_notify.h create mode 100644 libsecurity_utilities/lib/macho++.cpp create mode 100644 libsecurity_utilities/lib/macho++.h create mode 100644 libsecurity_utilities/lib/machrunloopserver.cpp create mode 100644 libsecurity_utilities/lib/machrunloopserver.h create mode 100644 libsecurity_utilities/lib/machserver.cpp create mode 100644 libsecurity_utilities/lib/machserver.h create mode 100644 libsecurity_utilities/lib/memstreams.h create mode 100644 libsecurity_utilities/lib/memutils.h create mode 100644 libsecurity_utilities/lib/muscle++.cpp create mode 100644 libsecurity_utilities/lib/muscle++.h create mode 100644 libsecurity_utilities/lib/osxcode.cpp create mode 100644 libsecurity_utilities/lib/osxcode.h create mode 100644 libsecurity_utilities/lib/pcsc++.cpp create mode 100644 libsecurity_utilities/lib/pcsc++.h create mode 100644 libsecurity_utilities/lib/powerwatch.cpp create mode 100644 libsecurity_utilities/lib/powerwatch.h create mode 100644 libsecurity_utilities/lib/refcount.h create mode 100644 libsecurity_utilities/lib/seccfobject.cpp create mode 100644 libsecurity_utilities/lib/seccfobject.h create mode 100644 libsecurity_utilities/lib/security_utilities.d create mode 100644 libsecurity_utilities/lib/security_utilities.h create mode 100644 libsecurity_utilities/lib/selector.cpp create mode 100644 libsecurity_utilities/lib/selector.h create mode 100644 libsecurity_utilities/lib/simpleprefs.cpp create mode 100644 libsecurity_utilities/lib/simpleprefs.h create mode 100644 libsecurity_utilities/lib/socks++.cpp create mode 100644 libsecurity_utilities/lib/socks++.h create mode 100644 libsecurity_utilities/lib/socks++4.cpp create mode 100644 libsecurity_utilities/lib/socks++4.h create mode 100644 libsecurity_utilities/lib/socks++5.cpp create mode 100644 libsecurity_utilities/lib/socks++5.h create mode 100644 libsecurity_utilities/lib/sqlite++.cpp create mode 100644 libsecurity_utilities/lib/sqlite++.h create mode 100644 libsecurity_utilities/lib/streams.cpp create mode 100644 libsecurity_utilities/lib/streams.h create mode 100644 libsecurity_utilities/lib/superblob.cpp create mode 100644 libsecurity_utilities/lib/superblob.h create mode 100644 libsecurity_utilities/lib/threading.cpp create mode 100644 libsecurity_utilities/lib/threading.h create mode 100644 libsecurity_utilities/lib/threading_internal.h create mode 100644 libsecurity_utilities/lib/timeflow.cpp create mode 100644 libsecurity_utilities/lib/timeflow.h create mode 100644 libsecurity_utilities/lib/tqueue.cpp create mode 100644 libsecurity_utilities/lib/tqueue.h create mode 100644 libsecurity_utilities/lib/trackingallocator.cpp create mode 100644 libsecurity_utilities/lib/trackingallocator.h create mode 100644 libsecurity_utilities/lib/transactions.cpp create mode 100644 libsecurity_utilities/lib/transactions.h create mode 100644 libsecurity_utilities/lib/typedvalue.cpp create mode 100644 libsecurity_utilities/lib/typedvalue.h create mode 100644 libsecurity_utilities/lib/unix++.cpp create mode 100644 libsecurity_utilities/lib/unix++.h create mode 100644 libsecurity_utilities/lib/unixchild.cpp create mode 100644 libsecurity_utilities/lib/unixchild.h create mode 100644 libsecurity_utilities/lib/url.cpp create mode 100644 libsecurity_utilities/lib/url.h create mode 100644 libsecurity_utilities/lib/utilities.cpp create mode 100644 libsecurity_utilities/lib/utilities.h create mode 100644 libsecurity_utilities/lib/utility_config.h create mode 100644 libsecurity_utilities/lib/vproc++.cpp create mode 100644 libsecurity_utilities/lib/vproc++.h create mode 100644 libsecurity_utilities/libsecurity_utilities.xcodeproj/project.pbxproj create mode 100644 libsecurityd/APPLE_LICENSE create mode 100644 libsecurityd/Info-securityd_client.plist create mode 100644 libsecurityd/Info-securityd_server.plist create mode 100644 libsecurityd/lib/SharedMemoryClient.cpp create mode 100644 libsecurityd/lib/SharedMemoryClient.h create mode 100644 libsecurityd/lib/SharedMemoryCommon.h create mode 100644 libsecurityd/lib/dictionary.cpp create mode 100644 libsecurityd/lib/dictionary.h create mode 100644 libsecurityd/lib/eventlistener.cpp create mode 100644 libsecurityd/lib/eventlistener.h create mode 100644 libsecurityd/lib/handletypes.h create mode 100644 libsecurityd/lib/sec_xdr.c create mode 100644 libsecurityd/lib/sec_xdr.h create mode 100644 libsecurityd/lib/sec_xdr_array.c create mode 100644 libsecurityd/lib/sec_xdr_reference.c create mode 100644 libsecurityd/lib/sec_xdr_sizeof.c create mode 100644 libsecurityd/lib/sec_xdrmem.c create mode 100644 libsecurityd/lib/ss_types.h create mode 100644 libsecurityd/lib/ssblob.cpp create mode 100644 libsecurityd/lib/ssblob.h create mode 100644 libsecurityd/lib/ssclient.cpp create mode 100644 libsecurityd/lib/ssclient.h create mode 100644 libsecurityd/lib/sscommon.h create mode 100644 libsecurityd/lib/ssnotify.h create mode 100644 libsecurityd/lib/sstransit.cpp create mode 100644 libsecurityd/lib/sstransit.h create mode 100644 libsecurityd/lib/transition.cpp create mode 100644 libsecurityd/lib/ucsp_types.h create mode 100644 libsecurityd/lib/xdr_auth.c create mode 100644 libsecurityd/lib/xdr_auth.h create mode 100644 libsecurityd/lib/xdr_cssm.c create mode 100644 libsecurityd/lib/xdr_cssm.h create mode 100644 libsecurityd/lib/xdr_dldb.cpp create mode 100644 libsecurityd/lib/xdr_dldb.h create mode 100644 libsecurityd/libsecurityd.xcodeproj/project.pbxproj create mode 100644 libsecurityd/mig/cshosting.defs create mode 100644 libsecurityd/mig/mig.mk create mode 100644 libsecurityd/mig/ss_types.defs create mode 100644 libsecurityd/mig/ucsp.defs create mode 100644 libsecurityd/mig/ucspNotify.defs create mode 100644 sec/Security/SecBase.h create mode 100644 sec/Security/SecBase64.c create mode 100644 sec/Security/SecBase64.h create mode 100644 sec/Security/SecBasePriv.h create mode 100644 sec/Security/SecCMS.c create mode 100644 sec/Security/SecCMS.h create mode 100644 sec/Security/SecCertificate.c create mode 100644 sec/Security/SecCertificate.h create mode 100644 sec/Security/SecCertificateInternal.h create mode 100644 sec/Security/SecCertificatePath.c create mode 100644 sec/Security/SecCertificatePath.h create mode 100644 sec/Security/SecCertificatePriv.h create mode 100644 sec/Security/SecCertificateRequest.c create mode 100644 sec/Security/SecCertificateRequest.h create mode 100644 sec/Security/SecDH.c create mode 100644 sec/Security/SecDH.h create mode 100644 sec/Security/SecECKey.c create mode 100644 sec/Security/SecECKey.h create mode 100644 sec/Security/SecFramework.c create mode 100644 sec/Security/SecFramework.h create mode 100644 sec/Security/SecFrameworkStrings.h create mode 100644 sec/Security/SecIdentity.c create mode 100644 sec/Security/SecIdentity.h create mode 100644 sec/Security/SecIdentityPriv.h create mode 100644 sec/Security/SecImportExport.c create mode 100644 sec/Security/SecImportExport.h create mode 100644 sec/Security/SecInternal.h create mode 100644 sec/Security/SecItem.c create mode 100644 sec/Security/SecItem.h create mode 100644 sec/Security/SecItemConstants.c create mode 100644 sec/Security/SecItemInternal.h create mode 100644 sec/Security/SecItemPriv.h create mode 100644 sec/Security/SecKey.c create mode 100644 sec/Security/SecKey.h create mode 100644 sec/Security/SecKeyInternal.h create mode 100644 sec/Security/SecKeyPriv.h create mode 100644 sec/Security/SecPBKDF.c create mode 100644 sec/Security/SecPBKDF.h create mode 100644 sec/Security/SecPolicy.c create mode 100644 sec/Security/SecPolicy.h create mode 100644 sec/Security/SecPolicyInternal.h create mode 100644 sec/Security/SecPolicyPriv.h create mode 100644 sec/Security/SecRSAKey.c create mode 100644 sec/Security/SecRSAKey.h create mode 100644 sec/Security/SecRSAKeyPriv.h create mode 100644 sec/Security/SecRandom.h create mode 100644 sec/Security/SecSCEP.c create mode 100644 sec/Security/SecSCEP.h create mode 100644 sec/Security/SecTrust.c create mode 100644 sec/Security/SecTrust.h create mode 100644 sec/Security/SecTrustPriv.h create mode 100644 sec/Security/SecTrustSettings.c create mode 100644 sec/Security/SecTrustSettings.h create mode 100644 sec/Security/SecTrustSettingsPriv.h create mode 100644 sec/Security/SecTrustStore.c create mode 100644 sec/Security/SecTrustStore.h create mode 100644 sec/Security/Security.h create mode 100644 sec/Security/certextensions.h create mode 100644 sec/Security/p12import.c create mode 100644 sec/Security/p12import.h create mode 100644 sec/Security/p12pbegen.c create mode 100644 sec/Security/p12pbegen.h create mode 100644 sec/Security/pbkdf2.c create mode 100644 sec/Security/pbkdf2.h create mode 100644 sec/Security/vmdh.c create mode 100644 sec/Security/vmdh.h create mode 100644 sec/config/base.xcconfig create mode 100644 sec/config/debug.xcconfig create mode 100644 sec/config/lib.xcconfig create mode 100644 sec/config/release.xcconfig create mode 100644 sec/ipc/client.c create mode 100644 sec/ipc/com.apple.secd.plist create mode 100644 sec/ipc/com.apple.securityd.plist create mode 100644 sec/ipc/securityd_client.h create mode 100644 sec/ipc/securityd_ipc_types.h create mode 100644 sec/ipc/securityd_rep.defs create mode 100644 sec/ipc/securityd_req.defs create mode 100644 sec/ipc/securityd_server.h create mode 100644 sec/ipc/server.c create mode 100644 sec/sec.xcodeproj/project.pbxproj create mode 100644 sec/securityd/SecCAIssuerCache.c create mode 100644 sec/securityd/SecCAIssuerCache.h create mode 100644 sec/securityd/SecCAIssuerRequest.c create mode 100644 sec/securityd/SecCAIssuerRequest.h create mode 100644 sec/securityd/SecItemServer.c create mode 100644 sec/securityd/SecItemServer.h create mode 100644 sec/securityd/SecOCSPCache.c create mode 100644 sec/securityd/SecOCSPCache.h create mode 100644 sec/securityd/SecOCSPRequest.c create mode 100644 sec/securityd/SecOCSPRequest.h create mode 100644 sec/securityd/SecOCSPResponse.c create mode 100644 sec/securityd/SecOCSPResponse.h create mode 100644 sec/securityd/SecPolicyServer.c create mode 100644 sec/securityd/SecPolicyServer.h create mode 100644 sec/securityd/SecTrustServer.c create mode 100644 sec/securityd/SecTrustServer.h create mode 100644 sec/securityd/SecTrustStoreServer.c create mode 100644 sec/securityd/SecTrustStoreServer.h create mode 100644 sec/securityd/asynchttp.c create mode 100644 sec/securityd/asynchttp.h create mode 100644 sec/securityd/entitlements.plist create mode 100644 sec/securityd/keystore.c create mode 100644 sec/securityd/keystore.h create mode 100644 sec/securityd/policytree.c create mode 100644 sec/securityd/policytree.h create mode 100644 sec/securityd/spi.c create mode 100644 sec/securityd/spi.h create mode 100644 security_utilities/debugging.c create mode 100644 security_utilities/debugging.h create mode 100644 security_utilities/fileIo.c create mode 100644 security_utilities/fileIo.h create mode 100644 security_utilities/sqlutils.h diff --git a/APPLE_LICENSE b/APPLE_LICENSE index fe81a60c..71fe6fd7 100644 --- a/APPLE_LICENSE +++ b/APPLE_LICENSE @@ -1,367 +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. - -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 +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, +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 +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 +(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 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. +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." +distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS +OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT +LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS 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/Security.xcodeproj/project.pbxproj b/Security.xcodeproj/project.pbxproj index c0f7771c..29b940f8 100644 --- a/Security.xcodeproj/project.pbxproj +++ b/Security.xcodeproj/project.pbxproj @@ -7,1130 +7,2810 @@ objects = { /* Begin PBXAggregateTarget section */ - C224637B0B86213C00626F1B /* World */ = { + 182BB598146FE295000BF1F3 /* World */ = { isa = PBXAggregateTarget; - buildConfigurationList = C22463800B86216400626F1B /* Build configuration list for PBXAggregateTarget "World" */; + buildConfigurationList = 182BB599146FE295000BF1F3 /* Build configuration list for PBXAggregateTarget "World" */; buildPhases = ( ); dependencies = ( - C224637D0B86214100626F1B /* PBXTargetDependency */, - C224637F0B86214600626F1B /* PBXTargetDependency */, + 186F779914E5A06500434E1F /* PBXTargetDependency */, + 186F779B14E5A06800434E1F /* PBXTargetDependency */, ); name = World; - productName = 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 = ( + 186F779114E5A00F00434E1F /* PBXTargetDependency */, + ); + name = Security_executables; + productName = Other; }; /* End PBXAggregateTarget section */ /* Begin PBXBuildFile section */ - 0504B1B506517D230011D5F5 /* osKeyTemplates.h in Headers */ = {isa = PBXBuildFile; fileRef = 0504B1B406517D230011D5F5 /* osKeyTemplates.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 050CCC3A0A115F96004DFCA9 /* SecTrustSettings.h in Headers */ = {isa = PBXBuildFile; fileRef = 050CCC390A115F96004DFCA9 /* SecTrustSettings.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 050CCC3D0A115FAC004DFCA9 /* SecTrustSettingsPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 050CCC3B0A115FAC004DFCA9 /* SecTrustSettingsPriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 050CCC3E0A115FAC004DFCA9 /* TrustSettingsSchema.h in Headers */ = {isa = PBXBuildFile; fileRef = 050CCC3C0A115FAC004DFCA9 /* TrustSettingsSchema.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 052C080E0989535300E7641D /* CMSDecoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 052C080C0989535300E7641D /* CMSDecoder.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 052C080F0989535300E7641D /* CMSEncoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 052C080D0989535300E7641D /* CMSEncoder.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 052C08110989535F00E7641D /* CMSPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 052C08100989535F00E7641D /* CMSPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 053C8C9406503DD80047C7CA /* SecAsn1Templates.h in Headers */ = {isa = PBXBuildFile; fileRef = 053C8C8D06503DD80047C7CA /* SecAsn1Templates.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 053C8C9506503DD80047C7CA /* certExtensionTemplates.h in Headers */ = {isa = PBXBuildFile; fileRef = 053C8C8E06503DD80047C7CA /* certExtensionTemplates.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 053C8C9606503DD80047C7CA /* csrTemplates.h in Headers */ = {isa = PBXBuildFile; fileRef = 053C8C8F06503DD80047C7CA /* csrTemplates.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 053C8C9706503DD80047C7CA /* keyTemplates.h in Headers */ = {isa = PBXBuildFile; fileRef = 053C8C9006503DD80047C7CA /* keyTemplates.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 053C8C9806503DD80047C7CA /* nameTemplates.h in Headers */ = {isa = PBXBuildFile; fileRef = 053C8C9106503DD80047C7CA /* nameTemplates.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 053C8C9906503DD80047C7CA /* SecAsn1Coder.h in Headers */ = {isa = PBXBuildFile; fileRef = 053C8C9206503DD80047C7CA /* SecAsn1Coder.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 053C8C9A06503DD80047C7CA /* secasn1t.h in Headers */ = {isa = PBXBuildFile; fileRef = 053C8C9306503DD80047C7CA /* secasn1t.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 05792F4F065082C100C80DB3 /* X509Templates.h in Headers */ = {isa = PBXBuildFile; fileRef = 05792F4E065082C100C80DB3 /* X509Templates.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 059D38360AB7866600CEF189 /* SecKeychainItemExtendedAttributes.h in Headers */ = {isa = PBXBuildFile; fileRef = 059D38350AB7866600CEF189 /* SecKeychainItemExtendedAttributes.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 05ABB7B20989321500FA0183 /* SecAsn1Types.h in Headers */ = {isa = PBXBuildFile; fileRef = 05ABB7B10989321500FA0183 /* SecAsn1Types.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 05ABB7C00989391A00FA0183 /* asn1Templates.h in Headers */ = {isa = PBXBuildFile; fileRef = 05ABB7BF0989391A00FA0183 /* asn1Templates.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 05B063C805DB2C1C006FA9A6 /* SecImportExport.h in Headers */ = {isa = PBXBuildFile; fileRef = 05B063C705DB2C1C006FA9A6 /* SecImportExport.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 05D0BC8406A87338001F9A43 /* cssmapplePriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 05D0BC8206A87338001F9A43 /* cssmapplePriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 05D0BC8506A87338001F9A43 /* ocspTemplates.h in Headers */ = {isa = PBXBuildFile; fileRef = 05D0BC8306A87338001F9A43 /* ocspTemplates.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 089C1668FE841158C02AAC07 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C1666FE841158C02AAC07 /* InfoPlist.strings */; }; - 12D4A8AC1226F92D00C2B581 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 12D4A8AB1226F92D00C2B581 /* libz.dylib */; }; - 12D4A8BF1226FAD900C2B581 /* SecRandomP.h in Headers */ = {isa = PBXBuildFile; fileRef = 12D4A8BE1226FAD900C2B581 /* SecRandomP.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 12D4A8F212270ABC00C2B581 /* SecRandom.h in Headers */ = {isa = PBXBuildFile; fileRef = 12D4A8F112270ABC00C2B581 /* SecRandom.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 1B40AAEE062F63E7009BAE74 /* SecKeychainSearchPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 1B40AAED062F63E7009BAE74 /* SecKeychainSearchPriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 1C4A135111066573006A16DA /* libpam.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 1C4A135011066564006A16DA /* libpam.dylib */; }; - 309CD1FA062B3D1900B66530 /* SecIdentitySearchPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 309CD1F9062B3D1900B66530 /* SecIdentitySearchPriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 40A2A721066FE6B300858603 /* SecPassword.h in Headers */ = {isa = PBXBuildFile; fileRef = 40A2A720066FE6B200858603 /* SecPassword.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 44B9317D11CC0917005FBCF1 /* FDEPrefs.plist in Resources */ = {isa = PBXBuildFile; fileRef = 44B9317C11CC0917005FBCF1 /* FDEPrefs.plist */; }; - 44DAD0F411CAB4F8007A9244 /* FDELocalizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 44DAD0F211CAB4F8007A9244 /* FDELocalizable.strings */; }; - 4C2495B305811D3200DDE4A6 /* security_exports.s in Sources */ = {isa = PBXBuildFile; fileRef = 4CAF731A05363BD700D9DA7C /* security_exports.s */; }; - 4C596A41058115A0001507D4 /* Authorization.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C5969E5058115A0001507D4 /* Authorization.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 4C596A42058115A0001507D4 /* AuthorizationDB.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C5969E6058115A0001507D4 /* AuthorizationDB.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 4C596A43058115A0001507D4 /* AuthorizationTags.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C5969E7058115A0001507D4 /* AuthorizationTags.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 4C596A44058115A0001507D4 /* AuthSession.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C5969E8058115A0001507D4 /* AuthSession.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 4C596A45058115A0001507D4 /* certextensions.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C5969E9058115A0001507D4 /* certextensions.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 4C596A46058115A0001507D4 /* checkpw.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C5969EA058115A0001507D4 /* checkpw.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 4C596A47058115A0001507D4 /* CipherSuite.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C5969EB058115A0001507D4 /* CipherSuite.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 4C596A48058115A0001507D4 /* cssm.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C5969EC058115A0001507D4 /* cssm.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 4C596A49058115A0001507D4 /* cssmaci.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C5969ED058115A0001507D4 /* cssmaci.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 4C596A4A058115A0001507D4 /* cssmapi.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C5969EE058115A0001507D4 /* cssmapi.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 4C596A4B058115A0001507D4 /* cssmapple.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C5969EF058115A0001507D4 /* cssmapple.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 4C596A4C058115A0001507D4 /* cssmcli.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C5969F0058115A0001507D4 /* cssmcli.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 4C596A4D058115A0001507D4 /* cssmconfig.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C5969F1058115A0001507D4 /* cssmconfig.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 4C596A4E058115A0001507D4 /* cssmcspi.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C5969F2058115A0001507D4 /* cssmcspi.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 4C596A4F058115A0001507D4 /* cssmdli.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C5969F3058115A0001507D4 /* cssmdli.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 4C596A50058115A0001507D4 /* cssmerr.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C5969F4058115A0001507D4 /* cssmerr.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 4C596A51058115A0001507D4 /* cssmkrapi.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C5969F5058115A0001507D4 /* cssmkrapi.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 4C596A52058115A0001507D4 /* cssmkrspi.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C5969F6058115A0001507D4 /* cssmkrspi.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 4C596A53058115A0001507D4 /* cssmspi.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C5969F7058115A0001507D4 /* cssmspi.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 4C596A54058115A0001507D4 /* cssmtpi.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C5969F8058115A0001507D4 /* cssmtpi.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 4C596A55058115A0001507D4 /* cssmtype.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C5969F9058115A0001507D4 /* cssmtype.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 4C596A56058115A0001507D4 /* eisl.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C5969FA058115A0001507D4 /* eisl.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 4C596A57058115A0001507D4 /* emmspi.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C5969FB058115A0001507D4 /* emmspi.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 4C596A58058115A0001507D4 /* emmtype.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C5969FC058115A0001507D4 /* emmtype.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 4C596A59058115A0001507D4 /* mds.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C5969FD058115A0001507D4 /* mds.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 4C596A5A058115A0001507D4 /* mds_schema.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C5969FE058115A0001507D4 /* mds_schema.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 4C596A5B058115A0001507D4 /* oidsalg.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C5969FF058115A0001507D4 /* oidsalg.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 4C596A5C058115A0001507D4 /* oidsattr.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C596A00058115A0001507D4 /* oidsattr.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 4C596A5D058115A0001507D4 /* oidsbase.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C596A01058115A0001507D4 /* oidsbase.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 4C596A5E058115A0001507D4 /* oidscert.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C596A02058115A0001507D4 /* oidscert.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 4C596A5F058115A0001507D4 /* oidscrl.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C596A03058115A0001507D4 /* oidscrl.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 4C596A60058115A0001507D4 /* SecAccess.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C596A04058115A0001507D4 /* SecAccess.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 4C596A61058115A0001507D4 /* SecACL.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C596A05058115A0001507D4 /* SecACL.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 4C596A62058115A0001507D4 /* SecBase.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C596A06058115A0001507D4 /* SecBase.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 4C596A63058115A0001507D4 /* SecCertificate.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C596A07058115A0001507D4 /* SecCertificate.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 4C596A64058115A0001507D4 /* SecIdentity.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C596A08058115A0001507D4 /* SecIdentity.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 4C596A65058115A0001507D4 /* SecIdentitySearch.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C596A09058115A0001507D4 /* SecIdentitySearch.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 4C596A66058115A0001507D4 /* SecKey.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C596A0A058115A0001507D4 /* SecKey.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 4C596A67058115A0001507D4 /* SecKeychain.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C596A0B058115A0001507D4 /* SecKeychain.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 4C596A69058115A0001507D4 /* SecKeychainItem.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C596A0D058115A0001507D4 /* SecKeychainItem.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 4C596A6A058115A0001507D4 /* SecKeychainSearch.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C596A0E058115A0001507D4 /* SecKeychainSearch.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 4C596A6B058115A0001507D4 /* SecPolicy.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C596A0F058115A0001507D4 /* SecPolicy.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 4C596A6C058115A0001507D4 /* SecPolicySearch.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C596A10058115A0001507D4 /* SecPolicySearch.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 4C596A6D058115A0001507D4 /* SecTrust.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C596A11058115A0001507D4 /* SecTrust.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 4C596A6E058115A0001507D4 /* SecTrustedApplication.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C596A12058115A0001507D4 /* SecTrustedApplication.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 4C596A6F058115A0001507D4 /* SecureTransport.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C596A13058115A0001507D4 /* SecureTransport.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 4C596A70058115A0001507D4 /* Security.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C596A14058115A0001507D4 /* Security.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 4C596A71058115A0001507D4 /* x509defs.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C596A15058115A0001507D4 /* x509defs.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 4C596A72058115A0001507D4 /* AuthorizationPlugin.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C596A18058115A0001507D4 /* AuthorizationPlugin.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 4C596A73058115A0001507D4 /* AuthorizationPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C596A19058115A0001507D4 /* AuthorizationPriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 4C596A74058115A0001507D4 /* AuthorizationTagsPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C596A1A058115A0001507D4 /* AuthorizationTagsPriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 4C596A75058115A0001507D4 /* SecAccessPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C596A1B058115A0001507D4 /* SecAccessPriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 4C596A76058115A0001507D4 /* SecCertificateBundle.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C596A1C058115A0001507D4 /* SecCertificateBundle.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 4C596A77058115A0001507D4 /* SecCertificatePriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C596A1D058115A0001507D4 /* SecCertificatePriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 4C596A78058115A0001507D4 /* SecCertificateRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C596A1E058115A0001507D4 /* SecCertificateRequest.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 4C596A79058115A0001507D4 /* SecIdentityPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C596A1F058115A0001507D4 /* SecIdentityPriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 4C596A7B058115A0001507D4 /* SecKeychainItemPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C596A21058115A0001507D4 /* SecKeychainItemPriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 4C596A7C058115A0001507D4 /* SecKeychainPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C596A22058115A0001507D4 /* SecKeychainPriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 4C596A7D058115A0001507D4 /* SecKeyPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C596A23058115A0001507D4 /* SecKeyPriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 4C596A7E058115A0001507D4 /* SecPolicyPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C596A24058115A0001507D4 /* SecPolicyPriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 4C596A7F058115A0001507D4 /* SecTrustedApplicationPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C596A25058115A0001507D4 /* SecTrustedApplicationPriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 4C596A80058115A0001507D4 /* SecTrustPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C596A26058115A0001507D4 /* SecTrustPriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 4C596A81058115A0001507D4 /* SecureTransportPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C596A27058115A0001507D4 /* SecureTransportPriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 4C596A82058115A0001507D4 /* cl_common.mdsinfo in Resources */ = {isa = PBXBuildFile; fileRef = 4C596A2A058115A0001507D4 /* cl_common.mdsinfo */; }; - 4C596A83058115A0001507D4 /* cl_primary.mdsinfo in Resources */ = {isa = PBXBuildFile; fileRef = 4C596A2B058115A0001507D4 /* cl_primary.mdsinfo */; }; - 4C596A84058115A0001507D4 /* csp_capabilities.mdsinfo in Resources */ = {isa = PBXBuildFile; fileRef = 4C596A2C058115A0001507D4 /* csp_capabilities.mdsinfo */; }; - 4C596A85058115A0001507D4 /* csp_capabilities_common.mds in Resources */ = {isa = PBXBuildFile; fileRef = 4C596A2D058115A0001507D4 /* csp_capabilities_common.mds */; }; - 4C596A86058115A0001507D4 /* csp_common.mdsinfo in Resources */ = {isa = PBXBuildFile; fileRef = 4C596A2E058115A0001507D4 /* csp_common.mdsinfo */; }; - 4C596A87058115A0001507D4 /* csp_primary.mdsinfo in Resources */ = {isa = PBXBuildFile; fileRef = 4C596A2F058115A0001507D4 /* csp_primary.mdsinfo */; }; - 4C596A88058115A0001507D4 /* cspdl_common.mdsinfo in Resources */ = {isa = PBXBuildFile; fileRef = 4C596A30058115A0001507D4 /* cspdl_common.mdsinfo */; }; - 4C596A89058115A0001507D4 /* cspdl_csp_capabilities.mdsinfo in Resources */ = {isa = PBXBuildFile; fileRef = 4C596A31058115A0001507D4 /* cspdl_csp_capabilities.mdsinfo */; }; - 4C596A8A058115A0001507D4 /* cspdl_csp_primary.mdsinfo in Resources */ = {isa = PBXBuildFile; fileRef = 4C596A32058115A0001507D4 /* cspdl_csp_primary.mdsinfo */; }; - 4C596A8B058115A0001507D4 /* cspdl_dl_primary.mdsinfo in Resources */ = {isa = PBXBuildFile; fileRef = 4C596A33058115A0001507D4 /* cspdl_dl_primary.mdsinfo */; }; - 4C596A8C058115A0001507D4 /* cssm.mdsinfo in Resources */ = {isa = PBXBuildFile; fileRef = 4C596A34058115A0001507D4 /* cssm.mdsinfo */; }; - 4C596A8D058115A0001507D4 /* dl_common.mdsinfo in Resources */ = {isa = PBXBuildFile; fileRef = 4C596A35058115A0001507D4 /* dl_common.mdsinfo */; }; - 4C596A8E058115A0001507D4 /* dl_primary.mdsinfo in Resources */ = {isa = PBXBuildFile; fileRef = 4C596A36058115A0001507D4 /* dl_primary.mdsinfo */; }; - 4C596A90058115A0001507D4 /* tp_common.mdsinfo in Resources */ = {isa = PBXBuildFile; fileRef = 4C596A38058115A0001507D4 /* tp_common.mdsinfo */; }; - 4C596A91058115A0001507D4 /* tp_policyOids.mdsinfo in Resources */ = {isa = PBXBuildFile; fileRef = 4C596A39058115A0001507D4 /* tp_policyOids.mdsinfo */; }; - 4C596A92058115A0001507D4 /* tp_primary.mdsinfo in Resources */ = {isa = PBXBuildFile; fileRef = 4C596A3A058115A0001507D4 /* tp_primary.mdsinfo */; }; - 4C868463058A56780072F261 /* SecBasePriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C868462058A56780072F261 /* SecBasePriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 4C8C2C1606D1AE6A00B00C2F /* sd_cspdl_common.mdsinfo in Resources */ = {isa = PBXBuildFile; fileRef = 4C8C2C1506D1AE6A00B00C2F /* sd_cspdl_common.mdsinfo */; }; - 4CA9BECA063726BD0013F16F /* SecCmsBase.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CA9BEBD063726BD0013F16F /* SecCmsBase.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 4CA9BECB063726BD0013F16F /* SecCmsContentInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CA9BEBE063726BD0013F16F /* SecCmsContentInfo.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 4CA9BECC063726BD0013F16F /* SecCmsDecoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CA9BEBF063726BD0013F16F /* SecCmsDecoder.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 4CA9BECD063726BD0013F16F /* SecCmsDigestContext.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CA9BEC0063726BD0013F16F /* SecCmsDigestContext.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 4CA9BECE063726BD0013F16F /* SecCmsDigestedData.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CA9BEC1063726BD0013F16F /* SecCmsDigestedData.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 4CA9BECF063726BD0013F16F /* SecCmsEncoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CA9BEC2063726BD0013F16F /* SecCmsEncoder.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 4CA9BED0063726BD0013F16F /* SecCmsEncryptedData.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CA9BEC3063726BD0013F16F /* SecCmsEncryptedData.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 4CA9BED1063726BD0013F16F /* SecCmsEnvelopedData.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CA9BEC4063726BD0013F16F /* SecCmsEnvelopedData.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 4CA9BED2063726BD0013F16F /* SecCmsMessage.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CA9BEC5063726BD0013F16F /* SecCmsMessage.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 4CA9BED3063726BD0013F16F /* SecCmsRecipientInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CA9BEC6063726BD0013F16F /* SecCmsRecipientInfo.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 4CA9BED4063726BD0013F16F /* SecCmsSignedData.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CA9BEC7063726BD0013F16F /* SecCmsSignedData.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 4CA9BED5063726BD0013F16F /* SecCmsSignerInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CA9BEC8063726BD0013F16F /* SecCmsSignerInfo.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 4CA9BED6063726BD0013F16F /* SecSMIME.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CA9BEC9063726BD0013F16F /* SecSMIME.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 52008CCC11496FB700E8CA78 /* SecCertificateInternalP.h in Headers */ = {isa = PBXBuildFile; fileRef = 52008CCB11496FB700E8CA78 /* SecCertificateInternalP.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 52141F5809771DAB002C0FF6 /* SecDebugErrorMessages.strings in Resources */ = {isa = PBXBuildFile; fileRef = 52141F5709771DAB002C0FF6 /* SecDebugErrorMessages.strings */; }; - 521F28F215758C66002B3975 /* TimeStampingPrefs.plist in Resources */ = {isa = PBXBuildFile; fileRef = 521F28F115758C66002B3975 /* TimeStampingPrefs.plist */; }; - 5270685507024D6F00C5D30E /* iToolsTrustedApps.plist in Resources */ = {isa = PBXBuildFile; fileRef = 5270685407024D6F00C5D30E /* iToolsTrustedApps.plist */; }; - 52B88E9511DD5D96005BCA6B /* SecFDERecoveryAsymmetricCrypto.h in Headers */ = {isa = PBXBuildFile; fileRef = 52B88E9411DD5CCF005BCA6B /* SecFDERecoveryAsymmetricCrypto.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 52EEE6FB15893A5000D20784 /* tsaSupport.h in Headers */ = {isa = PBXBuildFile; fileRef = 52EEE6FA15893A5000D20784 /* tsaSupport.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 52EEE6FD15893ADA00D20784 /* cmspriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 52EEE6FC15893ADA00D20784 /* cmspriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 52FB469D11481F39006D3B0A /* SecCertificateOIDs.h in Headers */ = {isa = PBXBuildFile; fileRef = 52FB469C11481F39006D3B0A /* SecCertificateOIDs.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 5D97B436114EFC260033D0F9 /* SecDecodeTransform.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D97B3F9114EF0D00033D0F9 /* SecDecodeTransform.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 5D97B437114EFC260033D0F9 /* SecEncodeTransform.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D97B3FA114EF0D00033D0F9 /* SecEncodeTransform.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 5D97B438114EFC260033D0F9 /* SecEncryptTransform.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D97B3FB114EF0D00033D0F9 /* SecEncryptTransform.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 5D97B439114EFC260033D0F9 /* SecSignVerifyTransform.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D97B3FC114EF0D00033D0F9 /* SecSignVerifyTransform.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 5DCB819012073F90007A7D84 /* SecCustomTransform.h in Headers */ = {isa = PBXBuildFile; fileRef = 5DCB818F12073F90007A7D84 /* SecCustomTransform.h */; settings = {ATTRIBUTES = (Public, ); }; }; - AA5C5A66138E25FB00D9E6C1 /* SecReadTransform.h in Headers */ = {isa = PBXBuildFile; fileRef = AA19373F138E25430029DDC3 /* SecReadTransform.h */; settings = {ATTRIBUTES = (Public, ); }; }; - AA7CA2E91117BE2B00901AF5 /* SecNullTransform.h in Headers */ = {isa = PBXBuildFile; fileRef = AA8AC7B31117BDF30002A07F /* SecNullTransform.h */; settings = {ATTRIBUTES = (Private, ); }; }; - AA8AC7AF1117BDD10002A07F /* security_transform.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AA3ED3C81117BD76001DD41A /* security_transform.framework */; }; - AA928D21123AEEBD0030D59E /* SecTransformReadTransform.h in Headers */ = {isa = PBXBuildFile; fileRef = AA928D07123AEE3C0030D59E /* SecTransformReadTransform.h */; settings = {ATTRIBUTES = (Public, ); }; }; - AACB24E71117BEC100B236A2 /* SecDigestTransform.h in Headers */ = {isa = PBXBuildFile; fileRef = AA7CA2EB1117BE7600901AF5 /* SecDigestTransform.h */; settings = {ATTRIBUTES = (Public, ); }; }; - AACB24E81117BEC100B236A2 /* SecTransform.h in Headers */ = {isa = PBXBuildFile; fileRef = AA7CA2EC1117BE7600901AF5 /* SecTransform.h */; settings = {ATTRIBUTES = (Public, ); }; }; - AAEB7DB211A61DF40011AE9E /* SecTransformInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = AA963A0B11A61D3500AE419B /* SecTransformInternal.h */; settings = {ATTRIBUTES = (Private, ); }; }; - BE4AFDB00F85EEAB002B2F42 /* SecItem.h in Headers */ = {isa = PBXBuildFile; fileRef = BE4AFDAF0F85EEAB002B2F42 /* SecItem.h */; settings = {ATTRIBUTES = (Public, ); }; }; - BE4AFDB50F85EEE7002B2F42 /* SecItemPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = BE4AFDB40F85EEE7002B2F42 /* SecItemPriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; - C2022A110DE26911009A9816 /* SecCodePriv.h in Headers */ = {isa = PBXBuildFile; fileRef = C2022A010DE267FC009A9816 /* SecCodePriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; - C2022A120DE26911009A9816 /* SecRequirementPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = C2022A020DE267FC009A9816 /* SecRequirementPriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; - C2022A130DE26911009A9816 /* SecStaticCodePriv.h in Headers */ = {isa = PBXBuildFile; fileRef = C2022A030DE267FC009A9816 /* SecStaticCodePriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; - C2022A140DE26927009A9816 /* CodeSigning.h in Headers */ = {isa = PBXBuildFile; fileRef = C2CACF930DE26792003057A0 /* CodeSigning.h */; settings = {ATTRIBUTES = (Public, ); }; }; - C2022A150DE26927009A9816 /* CSCommon.h in Headers */ = {isa = PBXBuildFile; fileRef = C2CACF940DE26792003057A0 /* CSCommon.h */; settings = {ATTRIBUTES = (Public, ); }; }; - C2022A160DE26927009A9816 /* SecCode.h in Headers */ = {isa = PBXBuildFile; fileRef = C2CACF950DE26792003057A0 /* SecCode.h */; settings = {ATTRIBUTES = (Public, ); }; }; - C2022A170DE26927009A9816 /* SecRequirement.h in Headers */ = {isa = PBXBuildFile; fileRef = C2CACF960DE26792003057A0 /* SecRequirement.h */; settings = {ATTRIBUTES = (Public, ); }; }; - C2022A180DE26927009A9816 /* SecStaticCode.h in Headers */ = {isa = PBXBuildFile; fileRef = C2CACF970DE26792003057A0 /* SecStaticCode.h */; settings = {ATTRIBUTES = (Public, ); }; }; - C21204A5056D89280018F475 /* SecErrorMessages.strings in Resources */ = {isa = PBXBuildFile; fileRef = C21204A4056D89280018F475 /* SecErrorMessages.strings */; }; - C234BC48069DBAB2006A5163 /* mdspriv.h in Headers */ = {isa = PBXBuildFile; fileRef = C234BC47069DBAB2006A5163 /* mdspriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; - C27262F60B8624BE00D889AF /* csparser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C27262F50B8624BE00D889AF /* csparser.cpp */; }; - C27263200B86288B00D889AF /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 034768E0FF38A50411DB9C8B /* Security.framework */; }; - C273608C1433F36D00A9A5FF /* SecAssessment.h in Headers */ = {isa = PBXBuildFile; fileRef = C273608B1433F36D00A9A5FF /* SecAssessment.h */; settings = {ATTRIBUTES = (Private, ); }; }; - C2884AA8148411DF00DF0CD1 /* libxar-nossl.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = C2884AA7148411DF00DF0CD1 /* libxar-nossl.dylib */; }; - C29B69340AD326CE007D7504 /* SecCodeSigner.h in Headers */ = {isa = PBXBuildFile; fileRef = C29B69330AD326B3007D7504 /* SecCodeSigner.h */; settings = {ATTRIBUTES = (Private, ); }; }; - C2A1D3DA0F58C1A100BD09F8 /* libbsm.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = C2A1D3D90F58C1A100BD09F8 /* libbsm.dylib */; }; - C2A4879B0B79160900849490 /* SecCodeHostLib.h in Headers */ = {isa = PBXBuildFile; fileRef = C2A487990B79160900849490 /* SecCodeHostLib.h */; settings = {ATTRIBUTES = (Private, ); }; }; - C2A4879C0B79160900849490 /* SecIntegrity.h in Headers */ = {isa = PBXBuildFile; fileRef = C2A4879A0B79160900849490 /* SecIntegrity.h */; settings = {ATTRIBUTES = (Private, ); }; }; - C2CC31360B85271C005FA59D /* SecIntegrityLib.h in Headers */ = {isa = PBXBuildFile; fileRef = C2CC31350B85271C005FA59D /* SecIntegrityLib.h */; settings = {ATTRIBUTES = (Private, ); }; }; - C2CFBA030DF87990003F57E4 /* SecCodeHost.h in Headers */ = {isa = PBXBuildFile; fileRef = C2CFB9FC0DF8794A003F57E4 /* SecCodeHost.h */; settings = {ATTRIBUTES = (Public, ); }; }; - C2D50D0C0E155F720059A195 /* CSCommonPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = C2D50D0B0E155F5E0059A195 /* CSCommonPriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; - C2FBE3530E3E5B0A00BC6617 /* libsqlite3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = C2FBE3520E3E5B0A00BC6617 /* libsqlite3.dylib */; }; - D619986109F6FC4800699932 /* SecureDownload.h in Headers */ = {isa = PBXBuildFile; fileRef = D619986009F6FC4800699932 /* SecureDownload.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D619986309F6FC5A00699932 /* SecureDownloadInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = D619986209F6FC5A00699932 /* SecureDownloadInternal.h */; settings = {ATTRIBUTES = (Private, ); }; }; - D6FB4E6A05F934DC0015312A /* SecManifest.h in Headers */ = {isa = PBXBuildFile; fileRef = D6FB4E6805F934DC0015312A /* SecManifest.h */; settings = {ATTRIBUTES = (Private, ); }; }; - EB286952157EA8FC008BAF8C /* libOpenScriptingUtil.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = EB286951157EA8FC008BAF8C /* libOpenScriptingUtil.dylib */; }; - FE2D0DC110DC0E8D00726AB5 /* SecTask.h in Headers */ = {isa = PBXBuildFile; fileRef = FE2D0DC010DC0E6A00726AB5 /* SecTask.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18270EE714CF292100B05E7F /* libsecurity.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 18D4053B14CE2C1600A2BE4E /* libsecurity.a */; }; + 18270EE814CF294500B05E7F /* libsecurityd.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 18270C7D14CE573D00B05E7F /* libsecurityd.a */; }; + 18270EF414CF334A00B05E7F /* securityd_rep.defs in Sources */ = {isa = PBXBuildFile; fileRef = 18270EF014CF333400B05E7F /* securityd_rep.defs */; settings = {ATTRIBUTES = (Client, Server, ); }; }; + 18270EF514CF334A00B05E7F /* securityd_req.defs in Sources */ = {isa = PBXBuildFile; fileRef = 18270EF114CF333400B05E7F /* securityd_req.defs */; settings = {ATTRIBUTES = (Server, Client, ); }; }; + 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 */; }; + 18270F3C14CF44C400B05E7F /* debugging.c in Sources */ = {isa = PBXBuildFile; fileRef = 18270F3A14CF44C400B05E7F /* debugging.c */; }; + 18270F4114CF465700B05E7F /* client.c in Sources */ = {isa = PBXBuildFile; fileRef = 18270EEC14CF333400B05E7F /* client.c */; }; + 18270F6114CF656E00B05E7F /* libsecipc_client.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 18270F6014CF655B00B05E7F /* libsecipc_client.a */; }; + 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 */; }; + 182BB594146FE1EE000BF1F3 /* libantlr2c++.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 182BB593146FE1ED000BF1F3 /* libantlr2c++.a */; }; + 182BB597146FE286000BF1F3 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1807384B146D0D4E00F05C24 /* Security.framework */; }; + 182BB5A8146FE6D4000BF1F3 /* security_exports.s in Sources */ = {isa = PBXBuildFile; fileRef = 182BB5A7146FE6D4000BF1F3 /* security_exports.s */; }; + 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 */; }; + 182BB5B0146FEFE2000BF1F3 /* libstdc++.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 182BB5AF146FEFE2000BF1F3 /* libstdc++.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 */; }; + 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 */; }; + 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 */; }; + 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 */; }; + 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, ); }; }; + 18FE68601471A46600A2CBE3 /* SecCertificateInternalP.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB1CD146EAD5D000BF1F3 /* SecCertificateInternalP.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, ); }; }; + 4C8313C914F5A26500DF7FDC /* libcorecrypto.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C8313C814F5A26500DF7FDC /* libcorecrypto.dylib */; }; + 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, ); }; }; + C288A0891505796F00E773B7 /* libOpenScriptingUtil.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = C288A0881505795D00E773B7 /* libOpenScriptingUtil.dylib */; settings = {ATTRIBUTES = (Weak, ); }; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ - 4C68458205814C85003AC7B2 /* PBXContainerItemProxy */ = { + 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 = 0867D690FE84028FC02AAC07 /* Project object */; + containerPortal = 18073841146D0D4E00F05C24 /* Project object */; proxyType = 1; - remoteGlobalIDString = 4C60A0A605811A4300C8A016; - remoteInfo = "copy pieces"; + 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; + }; + 18FE688E1471A4C900A2CBE3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 18073841146D0D4E00F05C24 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 18FE67E91471A3AA00A2CBE3; + remoteInfo = copyHeaders; + }; + 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; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 18BEB19914CF7F0B00C8BD36 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = /System/Library/LaunchDaemons; + dstSubfolderSpec = 0; + files = ( + 18BEB19A14CF7F8100C8BD36 /* com.apple.secd.plist in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 1; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 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 = ""; }; + 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; }; + 182BB1CD146EAD5D000BF1F3 /* SecCertificateInternalP.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecCertificateInternalP.h; path = libsecurity_keychain/lib/SecCertificateInternalP.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 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.exports; path = security.exp; 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 = ""; }; + 182BB5A7146FE6D4000BF1F3 /* security_exports.s */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; name = security_exports.s; path = derived_src/security_exports.s; sourceTree = BUILT_PRODUCTS_DIR; }; + 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 = ""; }; + 182BB5AF146FEFE2000BF1F3 /* libstdc++.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = "libstdc++.dylib"; path = "/usr/lib/libstdc++.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; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; + 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 = ""; }; + 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 = ""; }; + 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 = ""; }; + 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 = ""; }; + 18FE67EA1471A3AA00A2CBE3 /* Security.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Security.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 4C8313C814F5A26500DF7FDC /* libcorecrypto.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libcorecrypto.dylib; path = /usr/lib/system/libcorecrypto.dylib; 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; }; + C288A0881505795D00E773B7 /* libOpenScriptingUtil.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libOpenScriptingUtil.dylib; path = ../../../../../usr/lib/libOpenScriptingUtil.dylib; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 18073847146D0D4E00F05C24 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 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 */, + 182BB5B0146FEFE2000BF1F3 /* libstdc++.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 */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 18270ED314CF282600B05E7F /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 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 */, + 18270EE714CF292100B05E7F /* libsecurity.a in Frameworks */, + 18270EF814CF424900B05E7F /* CoreFoundation.framework in Frameworks */, + 18270EFC14CF427800B05E7F /* CFNetwork.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 182BB565146F4DCA000BF1F3 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 182BB597146FE286000BF1F3 /* Security.framework in Frameworks */, + 182BB594146FE1EE000BF1F3 /* libantlr2c++.a in Frameworks */, + 182BB592146FE1D7000BF1F3 /* CoreFoundation.framework in Frameworks */, + 182BB591146FE12F000BF1F3 /* libsecurity_utilities.a in Frameworks */, + 182BB590146FE125000BF1F3 /* libsecurity_cdsa_utilities.a in Frameworks */, + 182BB589146FE013000BF1F3 /* libsecurity_codesigning.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 1807383F146D0D4E00F05C24 = { + isa = PBXGroup; + children = ( + 18073854146D0D4E00F05C24 /* lib */, + 181EA3D0146D1ED200A6D320 /* libsecurity */, + 186CDD0314CA10E700AF9171 /* sec */, + 186CDE7914CA3A3800AF9171 /* secd */, + 181EA421146D4A2A00A6D320 /* config */, + 1807384D146D0D4E00F05C24 /* Frameworks */, + 1807384C146D0D4E00F05C24 /* Products */, + ); + sourceTree = ""; + }; + 1807384C146D0D4E00F05C24 /* Products */ = { + isa = PBXGroup; + children = ( + 1807384B146D0D4E00F05C24 /* Security.framework */, + 182BB568146F4DCA000BF1F3 /* csparser.bundle */, + 18FE67EA1471A3AA00A2CBE3 /* Security.framework */, + 18270ED614CF282600B05E7F /* secd */, + ); + name = Products; + sourceTree = ""; + }; + 1807384D146D0D4E00F05C24 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 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 */, + 182BB5AF146FEFE2000BF1F3 /* libstdc++.dylib */, + 182BB5AD146FEF43000BF1F3 /* libsqlite3.dylib */, + 182BB5AB146FEF14000BF1F3 /* libpam.dylib */, + 182BB593146FE1ED000BF1F3 /* libantlr2c++.a */, + C288A0881505795D00E773B7 /* libOpenScriptingUtil.dylib */, + 182BB569146F4DCA000BF1F3 /* CoreFoundation.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 18073854146D0D4E00F05C24 /* lib */ = { + isa = PBXGroup; + children = ( + 1879B4A6146DC971007E536C /* Headers */, + 1879B4A7146DC999007E536C /* PrivateHeaders */, + 182BB228146F0674000BF1F3 /* Resources */, + 18073855146D0D4E00F05C24 /* Supporting Files */, + 182BB555146F450F000BF1F3 /* plugins */, + 182BB5A9146FEB27000BF1F3 /* derived_src */, + ); + path = lib; + sourceTree = ""; + }; + 18073855146D0D4E00F05C24 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 182BB562146F4C73000BF1F3 /* security.exp */, + 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 = ( + 18BBC6801471EF1600F2B224 /* security.xcconfig */, + 181EA422146D4A2A00A6D320 /* base.xcconfig */, + 181EA423146D4A2A00A6D320 /* debug.xcconfig */, + 181EA424146D4A2A00A6D320 /* lib.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 = ( + 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 */, + 182BB5A7146FE6D4000BF1F3 /* security_exports.s */, + ); + name = derived_src; + sourceTree = ""; + }; + 184461A4146E9D3200B12992 /* Products */ = { + isa = PBXGroup; + children = ( + 184461B1146E9D3300B12992 /* libsecurityd_client.a */, + 184461B5146E9D3300B12992 /* libsecurityd_server.a */, + 184461B9146E9D3300B12992 /* ucspc.a */, + ); + name = Products; + sourceTree = ""; }; - 4CAF730305363B1200D9DA7C /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 0867D690FE84028FC02AAC07 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 4C216213053639A600CCA0BB; - remoteInfo = generate; + 186CDD0314CA10E700AF9171 /* sec */ = { + isa = PBXGroup; + children = ( + 186CDD1614CA11C700AF9171 /* sec.xcodeproj */, + ); + path = sec; + sourceTree = ""; }; - C224637C0B86214100626F1B /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 0867D690FE84028FC02AAC07 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 0867D69CFE84028FC02AAC07; - remoteInfo = Security; + 186CDD1714CA11C700AF9171 /* Products */ = { + isa = PBXGroup; + children = ( + 18D4053B14CE2C1600A2BE4E /* libsecurity.a */, + 18270C7D14CE573D00B05E7F /* libsecurityd.a */, + 186CDD1E14CA11C700AF9171 /* libSecItemShimOSX.a */, + 18270F6014CF655B00B05E7F /* libsecipc_client.a */, + ); + name = Products; + sourceTree = ""; }; - C224637E0B86214600626F1B /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 0867D690FE84028FC02AAC07 /* Project object */; - proxyType = 1; - remoteGlobalIDString = C22463700B86212100626F1B; - remoteInfo = csparser; + 186CDE7914CA3A3800AF9171 /* secd */ = { + isa = PBXGroup; + children = ( + 18270EEB14CF331500B05E7F /* ipc */, + 18270F3114CF448600B05E7F /* security_utilities */, + ); + name = secd; + sourceTree = ""; }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXFileReference section */ - 034768E0FF38A50411DB9C8B /* Security.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = Security.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 0504B1B406517D230011D5F5 /* osKeyTemplates.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = osKeyTemplates.h; sourceTree = ""; }; - 050CCC390A115F96004DFCA9 /* SecTrustSettings.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecTrustSettings.h; sourceTree = ""; }; - 050CCC3B0A115FAC004DFCA9 /* SecTrustSettingsPriv.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecTrustSettingsPriv.h; sourceTree = ""; }; - 050CCC3C0A115FAC004DFCA9 /* TrustSettingsSchema.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = TrustSettingsSchema.h; sourceTree = ""; }; - 052C0802098950D000E7641D /* security_cms.exp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.exports; path = security_cms.exp; sourceTree = ""; }; - 052C080C0989535300E7641D /* CMSDecoder.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = CMSDecoder.h; sourceTree = ""; }; - 052C080D0989535300E7641D /* CMSEncoder.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = CMSEncoder.h; sourceTree = ""; }; - 052C08100989535F00E7641D /* CMSPrivate.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = CMSPrivate.h; sourceTree = ""; }; - 053105C105E19ED400044101 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = ""; }; - 053C8C8D06503DD80047C7CA /* SecAsn1Templates.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecAsn1Templates.h; sourceTree = ""; }; - 053C8C8E06503DD80047C7CA /* certExtensionTemplates.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = certExtensionTemplates.h; sourceTree = ""; }; - 053C8C8F06503DD80047C7CA /* csrTemplates.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = csrTemplates.h; sourceTree = ""; }; - 053C8C9006503DD80047C7CA /* keyTemplates.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = keyTemplates.h; sourceTree = ""; }; - 053C8C9106503DD80047C7CA /* nameTemplates.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = nameTemplates.h; sourceTree = ""; }; - 053C8C9206503DD80047C7CA /* SecAsn1Coder.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecAsn1Coder.h; sourceTree = ""; }; - 053C8C9306503DD80047C7CA /* secasn1t.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = secasn1t.h; sourceTree = ""; }; - 053C8CC706503E9E0047C7CA /* security_asn1.exp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.exports; path = security_asn1.exp; sourceTree = ""; }; - 05792F4E065082C100C80DB3 /* X509Templates.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = X509Templates.h; sourceTree = ""; }; - 059D38350AB7866600CEF189 /* SecKeychainItemExtendedAttributes.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecKeychainItemExtendedAttributes.h; sourceTree = ""; }; - 05ABB7B10989321500FA0183 /* SecAsn1Types.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecAsn1Types.h; sourceTree = ""; }; - 05ABB7BF0989391A00FA0183 /* asn1Templates.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = asn1Templates.h; sourceTree = ""; }; - 05B063C705DB2C1C006FA9A6 /* SecImportExport.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecImportExport.h; sourceTree = ""; }; - 05D0BC8206A87338001F9A43 /* cssmapplePriv.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cssmapplePriv.h; sourceTree = ""; }; - 05D0BC8306A87338001F9A43 /* ocspTemplates.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ocspTemplates.h; sourceTree = ""; }; - 089C1667FE841158C02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = ""; }; - 12D4A8AB1226F92D00C2B581 /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = /usr/lib/libz.dylib; sourceTree = ""; }; - 12D4A8BE1226FAD900C2B581 /* SecRandomP.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecRandomP.h; sourceTree = ""; }; - 12D4A8F112270ABC00C2B581 /* SecRandom.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecRandom.h; sourceTree = ""; }; - 1B40AAED062F63E7009BAE74 /* SecKeychainSearchPriv.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecKeychainSearchPriv.h; sourceTree = ""; }; - 1C4A135011066564006A16DA /* libpam.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libpam.dylib; path = /usr/lib/libpam.dylib; sourceTree = ""; }; - 309CD1F9062B3D1900B66530 /* SecIdentitySearchPriv.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecIdentitySearchPriv.h; sourceTree = ""; }; - 40A2A720066FE6B200858603 /* SecPassword.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecPassword.h; sourceTree = ""; }; - 44B9317C11CC0917005FBCF1 /* FDEPrefs.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = FDEPrefs.plist; sourceTree = SOURCE_ROOT; }; - 44DAD0F311CAB4F8007A9244 /* English */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/FDELocalizable.strings; sourceTree = ""; }; - 48C16F4411D162D60037E993 /* SecRecoveryPassword.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecRecoveryPassword.h; sourceTree = ""; }; - 4C01DDF20540D04C00A9C9B2 /* security_apple_csp.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = security_apple_csp.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 4C01DDF30540D04C00A9C9B2 /* security_apple_cspdl.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = security_apple_cspdl.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 4C01DDF40540D04C00A9C9B2 /* security_apple_file_dl.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = security_apple_file_dl.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 4C01DDF50540D04C00A9C9B2 /* security_apple_x509_cl.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = security_apple_x509_cl.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 4C01DDF60540D04C00A9C9B2 /* security_apple_x509_tp.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = security_apple_x509_tp.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 4C01DDF70540D04C00A9C9B2 /* security_asn1.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = security_asn1.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 4C01DDF80540D04C00A9C9B2 /* security_cdsa_client.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = security_cdsa_client.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 4C01DDF90540D04C00A9C9B2 /* security_cdsa_plugin.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = security_cdsa_plugin.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 4C01DDFA0540D04C00A9C9B2 /* security_cdsa_utilities.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = security_cdsa_utilities.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 4C01DDFB0540D04C00A9C9B2 /* security_cdsa_utils.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = security_cdsa_utils.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 4C01DDFC0540D04C00A9C9B2 /* security_checkpw.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = security_checkpw.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 4C01DDFD0540D04C00A9C9B2 /* security_cssm.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = security_cssm.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 4C01DDFE0540D04C00A9C9B2 /* security_filedb.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = security_filedb.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 4C01DDFF0540D04C00A9C9B2 /* security_keychain.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = security_keychain.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 4C01DE000540D04C00A9C9B2 /* security_mds.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = security_mds.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 4C01DE010540D04C00A9C9B2 /* security_ssl.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = security_ssl.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 4C01DE020540D04C00A9C9B2 /* security_utilities.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = security_utilities.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 4C01DE040540D04C00A9C9B2 /* securityd_client.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = securityd_client.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 4C01DE050540D04C00A9C9B2 /* securityd_server.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = securityd_server.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 4C216214053639A600CCA0BB /* generate */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; path = generate; sourceTree = BUILT_PRODUCTS_DIR; }; - 4C5969DD058115A0001507D4 /* security_checkpw.exp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.exports; path = security_checkpw.exp; sourceTree = ""; }; - 4C5969DE058115A0001507D4 /* security_cssm.exp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.exports; path = security_cssm.exp; sourceTree = ""; }; - 4C5969DF058115A0001507D4 /* security_keychain.exp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.exports; path = security_keychain.exp; sourceTree = ""; }; - 4C5969E0058115A0001507D4 /* security_mds.exp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.exports; path = security_mds.exp; sourceTree = ""; }; - 4C5969E1058115A0001507D4 /* security_ssl.exp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.exports; path = security_ssl.exp; sourceTree = ""; }; - 4C5969E2058115A0001507D4 /* securityd_client.exp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.exports; path = securityd_client.exp; sourceTree = ""; }; - 4C5969E5058115A0001507D4 /* Authorization.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Authorization.h; sourceTree = ""; }; - 4C5969E6058115A0001507D4 /* AuthorizationDB.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = AuthorizationDB.h; sourceTree = ""; }; - 4C5969E7058115A0001507D4 /* AuthorizationTags.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = AuthorizationTags.h; sourceTree = ""; }; - 4C5969E8058115A0001507D4 /* AuthSession.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = AuthSession.h; sourceTree = ""; }; - 4C5969E9058115A0001507D4 /* certextensions.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = certextensions.h; sourceTree = ""; }; - 4C5969EA058115A0001507D4 /* checkpw.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = checkpw.h; sourceTree = ""; }; - 4C5969EB058115A0001507D4 /* CipherSuite.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = CipherSuite.h; sourceTree = ""; }; - 4C5969EC058115A0001507D4 /* cssm.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cssm.h; sourceTree = ""; }; - 4C5969ED058115A0001507D4 /* cssmaci.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cssmaci.h; sourceTree = ""; }; - 4C5969EE058115A0001507D4 /* cssmapi.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cssmapi.h; sourceTree = ""; }; - 4C5969EF058115A0001507D4 /* cssmapple.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cssmapple.h; sourceTree = ""; }; - 4C5969F0058115A0001507D4 /* cssmcli.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cssmcli.h; sourceTree = ""; }; - 4C5969F1058115A0001507D4 /* cssmconfig.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cssmconfig.h; sourceTree = ""; }; - 4C5969F2058115A0001507D4 /* cssmcspi.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cssmcspi.h; sourceTree = ""; }; - 4C5969F3058115A0001507D4 /* cssmdli.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cssmdli.h; sourceTree = ""; }; - 4C5969F4058115A0001507D4 /* cssmerr.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cssmerr.h; sourceTree = ""; }; - 4C5969F5058115A0001507D4 /* cssmkrapi.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cssmkrapi.h; sourceTree = ""; }; - 4C5969F6058115A0001507D4 /* cssmkrspi.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cssmkrspi.h; sourceTree = ""; }; - 4C5969F7058115A0001507D4 /* cssmspi.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cssmspi.h; sourceTree = ""; }; - 4C5969F8058115A0001507D4 /* cssmtpi.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cssmtpi.h; sourceTree = ""; }; - 4C5969F9058115A0001507D4 /* cssmtype.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cssmtype.h; sourceTree = ""; }; - 4C5969FA058115A0001507D4 /* eisl.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = eisl.h; sourceTree = ""; }; - 4C5969FB058115A0001507D4 /* emmspi.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = emmspi.h; sourceTree = ""; }; - 4C5969FC058115A0001507D4 /* emmtype.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = emmtype.h; sourceTree = ""; }; - 4C5969FD058115A0001507D4 /* mds.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = mds.h; sourceTree = ""; }; - 4C5969FE058115A0001507D4 /* mds_schema.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = mds_schema.h; sourceTree = ""; }; - 4C5969FF058115A0001507D4 /* oidsalg.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = oidsalg.h; sourceTree = ""; }; - 4C596A00058115A0001507D4 /* oidsattr.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = oidsattr.h; sourceTree = ""; }; - 4C596A01058115A0001507D4 /* oidsbase.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = oidsbase.h; sourceTree = ""; }; - 4C596A02058115A0001507D4 /* oidscert.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = oidscert.h; sourceTree = ""; }; - 4C596A03058115A0001507D4 /* oidscrl.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = oidscrl.h; sourceTree = ""; }; - 4C596A04058115A0001507D4 /* SecAccess.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecAccess.h; sourceTree = ""; }; - 4C596A05058115A0001507D4 /* SecACL.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecACL.h; sourceTree = ""; }; - 4C596A06058115A0001507D4 /* SecBase.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecBase.h; sourceTree = ""; }; - 4C596A07058115A0001507D4 /* SecCertificate.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecCertificate.h; sourceTree = ""; }; - 4C596A08058115A0001507D4 /* SecIdentity.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecIdentity.h; sourceTree = ""; }; - 4C596A09058115A0001507D4 /* SecIdentitySearch.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecIdentitySearch.h; sourceTree = ""; }; - 4C596A0A058115A0001507D4 /* SecKey.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecKey.h; sourceTree = ""; }; - 4C596A0B058115A0001507D4 /* SecKeychain.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecKeychain.h; sourceTree = ""; }; - 4C596A0D058115A0001507D4 /* SecKeychainItem.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecKeychainItem.h; sourceTree = ""; }; - 4C596A0E058115A0001507D4 /* SecKeychainSearch.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecKeychainSearch.h; sourceTree = ""; }; - 4C596A0F058115A0001507D4 /* SecPolicy.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecPolicy.h; sourceTree = ""; }; - 4C596A10058115A0001507D4 /* SecPolicySearch.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecPolicySearch.h; sourceTree = ""; }; - 4C596A11058115A0001507D4 /* SecTrust.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecTrust.h; sourceTree = ""; }; - 4C596A12058115A0001507D4 /* SecTrustedApplication.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecTrustedApplication.h; sourceTree = ""; }; - 4C596A13058115A0001507D4 /* SecureTransport.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecureTransport.h; sourceTree = ""; }; - 4C596A14058115A0001507D4 /* Security.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Security.h; sourceTree = ""; }; - 4C596A15058115A0001507D4 /* x509defs.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = x509defs.h; sourceTree = ""; }; - 4C596A18058115A0001507D4 /* AuthorizationPlugin.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = AuthorizationPlugin.h; sourceTree = ""; }; - 4C596A19058115A0001507D4 /* AuthorizationPriv.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = AuthorizationPriv.h; sourceTree = ""; }; - 4C596A1A058115A0001507D4 /* AuthorizationTagsPriv.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = AuthorizationTagsPriv.h; sourceTree = ""; }; - 4C596A1B058115A0001507D4 /* SecAccessPriv.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecAccessPriv.h; sourceTree = ""; }; - 4C596A1C058115A0001507D4 /* SecCertificateBundle.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecCertificateBundle.h; sourceTree = ""; }; - 4C596A1D058115A0001507D4 /* SecCertificatePriv.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecCertificatePriv.h; sourceTree = ""; }; - 4C596A1E058115A0001507D4 /* SecCertificateRequest.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecCertificateRequest.h; sourceTree = ""; }; - 4C596A1F058115A0001507D4 /* SecIdentityPriv.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecIdentityPriv.h; sourceTree = ""; }; - 4C596A21058115A0001507D4 /* SecKeychainItemPriv.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecKeychainItemPriv.h; sourceTree = ""; }; - 4C596A22058115A0001507D4 /* SecKeychainPriv.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecKeychainPriv.h; sourceTree = ""; }; - 4C596A23058115A0001507D4 /* SecKeyPriv.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecKeyPriv.h; sourceTree = ""; }; - 4C596A24058115A0001507D4 /* SecPolicyPriv.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecPolicyPriv.h; sourceTree = ""; }; - 4C596A25058115A0001507D4 /* SecTrustedApplicationPriv.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecTrustedApplicationPriv.h; sourceTree = ""; }; - 4C596A26058115A0001507D4 /* SecTrustPriv.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecTrustPriv.h; sourceTree = ""; }; - 4C596A27058115A0001507D4 /* SecureTransportPriv.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecureTransportPriv.h; sourceTree = ""; }; - 4C596A2A058115A0001507D4 /* cl_common.mdsinfo */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.xml; path = cl_common.mdsinfo; sourceTree = ""; }; - 4C596A2B058115A0001507D4 /* cl_primary.mdsinfo */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.xml; path = cl_primary.mdsinfo; sourceTree = ""; }; - 4C596A2C058115A0001507D4 /* csp_capabilities.mdsinfo */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.xml; path = csp_capabilities.mdsinfo; sourceTree = ""; }; - 4C596A2D058115A0001507D4 /* csp_capabilities_common.mds */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.xml; path = csp_capabilities_common.mds; sourceTree = ""; }; - 4C596A2E058115A0001507D4 /* csp_common.mdsinfo */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.xml; path = csp_common.mdsinfo; sourceTree = ""; }; - 4C596A2F058115A0001507D4 /* csp_primary.mdsinfo */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.xml; path = csp_primary.mdsinfo; sourceTree = ""; }; - 4C596A30058115A0001507D4 /* cspdl_common.mdsinfo */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.xml; path = cspdl_common.mdsinfo; sourceTree = ""; }; - 4C596A31058115A0001507D4 /* cspdl_csp_capabilities.mdsinfo */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.xml; path = cspdl_csp_capabilities.mdsinfo; sourceTree = ""; }; - 4C596A32058115A0001507D4 /* cspdl_csp_primary.mdsinfo */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.xml; path = cspdl_csp_primary.mdsinfo; sourceTree = ""; }; - 4C596A33058115A0001507D4 /* cspdl_dl_primary.mdsinfo */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.xml; path = cspdl_dl_primary.mdsinfo; sourceTree = ""; }; - 4C596A34058115A0001507D4 /* cssm.mdsinfo */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.xml; path = cssm.mdsinfo; sourceTree = ""; }; - 4C596A35058115A0001507D4 /* dl_common.mdsinfo */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.xml; path = dl_common.mdsinfo; sourceTree = ""; }; - 4C596A36058115A0001507D4 /* dl_primary.mdsinfo */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.xml; path = dl_primary.mdsinfo; sourceTree = ""; }; - 4C596A38058115A0001507D4 /* tp_common.mdsinfo */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.xml; path = tp_common.mdsinfo; sourceTree = ""; }; - 4C596A39058115A0001507D4 /* tp_policyOids.mdsinfo */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.xml; path = tp_policyOids.mdsinfo; sourceTree = ""; }; - 4C596A3A058115A0001507D4 /* tp_primary.mdsinfo */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.xml; path = tp_primary.mdsinfo; sourceTree = ""; }; - 4C60A0B105811AC800C8A016 /* copy_pieces.mk */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = copy_pieces.mk; sourceTree = ""; }; - 4C868462058A56780072F261 /* SecBasePriv.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecBasePriv.h; sourceTree = ""; }; - 4C8C2C1506D1AE6A00B00C2F /* sd_cspdl_common.mdsinfo */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.xml; path = sd_cspdl_common.mdsinfo; sourceTree = ""; }; - 4CA9BEBD063726BD0013F16F /* SecCmsBase.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecCmsBase.h; sourceTree = ""; }; - 4CA9BEBE063726BD0013F16F /* SecCmsContentInfo.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecCmsContentInfo.h; sourceTree = ""; }; - 4CA9BEBF063726BD0013F16F /* SecCmsDecoder.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecCmsDecoder.h; sourceTree = ""; }; - 4CA9BEC0063726BD0013F16F /* SecCmsDigestContext.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecCmsDigestContext.h; sourceTree = ""; }; - 4CA9BEC1063726BD0013F16F /* SecCmsDigestedData.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecCmsDigestedData.h; sourceTree = ""; }; - 4CA9BEC2063726BD0013F16F /* SecCmsEncoder.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecCmsEncoder.h; sourceTree = ""; }; - 4CA9BEC3063726BD0013F16F /* SecCmsEncryptedData.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecCmsEncryptedData.h; sourceTree = ""; }; - 4CA9BEC4063726BD0013F16F /* SecCmsEnvelopedData.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecCmsEnvelopedData.h; sourceTree = ""; }; - 4CA9BEC5063726BD0013F16F /* SecCmsMessage.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecCmsMessage.h; sourceTree = ""; }; - 4CA9BEC6063726BD0013F16F /* SecCmsRecipientInfo.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecCmsRecipientInfo.h; sourceTree = ""; }; - 4CA9BEC7063726BD0013F16F /* SecCmsSignedData.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecCmsSignedData.h; sourceTree = ""; }; - 4CA9BEC8063726BD0013F16F /* SecCmsSignerInfo.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecCmsSignerInfo.h; sourceTree = ""; }; - 4CA9BEC9063726BD0013F16F /* SecSMIME.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecSMIME.h; sourceTree = ""; }; - 4CA9BEDD0637274A0013F16F /* security_smime.exp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.exports; path = security_smime.exp; sourceTree = ""; }; - 4CAF731A05363BD700D9DA7C /* security_exports.s */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.asm; path = security_exports.s; sourceTree = ""; }; - 4CD8084D0536046D009F54B0 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = /System/Library/Frameworks/CoreFoundation.framework; sourceTree = ""; }; - 4ED0DD500E887E6400F626D0 /* security_cryptkit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = security_cryptkit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 52008CCB11496FB700E8CA78 /* SecCertificateInternalP.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecCertificateInternalP.h; sourceTree = ""; }; - 52141F5709771DAB002C0FF6 /* SecDebugErrorMessages.strings */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.plist.strings; path = SecDebugErrorMessages.strings; sourceTree = ""; }; - 521F28F115758C66002B3975 /* TimeStampingPrefs.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = TimeStampingPrefs.plist; sourceTree = ""; }; - 5270685407024D6F00C5D30E /* iToolsTrustedApps.plist */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.plist; path = iToolsTrustedApps.plist; sourceTree = ""; }; - 52B88E9411DD5CCF005BCA6B /* SecFDERecoveryAsymmetricCrypto.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecFDERecoveryAsymmetricCrypto.h; sourceTree = ""; }; - 52EEE6FA15893A5000D20784 /* tsaSupport.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = tsaSupport.h; path = tsaSupport.h; sourceTree = ""; }; - 52EEE6FC15893ADA00D20784 /* cmspriv.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = cmspriv.h; path = cmspriv.h; sourceTree = ""; }; - 52FB469C11481F39006D3B0A /* SecCertificateOIDs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecCertificateOIDs.h; sourceTree = ""; }; - 5D97B3F9114EF0D00033D0F9 /* SecDecodeTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecDecodeTransform.h; sourceTree = ""; }; - 5D97B3FA114EF0D00033D0F9 /* SecEncodeTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecEncodeTransform.h; sourceTree = ""; }; - 5D97B3FB114EF0D00033D0F9 /* SecEncryptTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecEncryptTransform.h; sourceTree = ""; }; - 5D97B3FC114EF0D00033D0F9 /* SecSignVerifyTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecSignVerifyTransform.h; sourceTree = ""; }; - 5DCB818F12073F90007A7D84 /* SecCustomTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecCustomTransform.h; sourceTree = ""; }; - AA19373F138E25430029DDC3 /* SecReadTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecReadTransform.h; sourceTree = ""; }; - AA3ED3C81117BD76001DD41A /* security_transform.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = security_transform.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - AA4F5B6811405CAB00388604 /* SecCustomTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecCustomTransform.h; sourceTree = ""; }; - AA7CA2EB1117BE7600901AF5 /* SecDigestTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecDigestTransform.h; sourceTree = ""; }; - AA7CA2EC1117BE7600901AF5 /* SecTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecTransform.h; sourceTree = ""; }; - AA8AC7B31117BDF30002A07F /* SecNullTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecNullTransform.h; sourceTree = ""; }; - AA928D07123AEE3C0030D59E /* SecTransformReadTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecTransformReadTransform.h; sourceTree = ""; }; - AA963A0B11A61D3500AE419B /* SecTransformInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecTransformInternal.h; sourceTree = ""; }; - BE4AFDAF0F85EEAB002B2F42 /* SecItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecItem.h; sourceTree = ""; }; - BE4AFDB40F85EEE7002B2F42 /* SecItemPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecItemPriv.h; sourceTree = ""; }; - C2022A010DE267FC009A9816 /* SecCodePriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecCodePriv.h; sourceTree = ""; }; - C2022A020DE267FC009A9816 /* SecRequirementPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecRequirementPriv.h; sourceTree = ""; }; - C2022A030DE267FC009A9816 /* SecStaticCodePriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecStaticCodePriv.h; sourceTree = ""; }; - C21204A2056D891E0018F475 /* English */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/SecErrorMessages.strings; sourceTree = ""; }; - C22463710B86212100626F1B /* csparser.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = csparser.bundle; sourceTree = BUILT_PRODUCTS_DIR; }; - C22463720B86212100626F1B /* csparser-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "csparser-Info.plist"; sourceTree = ""; }; - C234BC47069DBAB2006A5163 /* mdspriv.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = mdspriv.h; sourceTree = ""; }; - C27262E80B86236100D889AF /* csparser.exp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.exports; path = csparser.exp; sourceTree = ""; }; - C27262F50B8624BE00D889AF /* csparser.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = csparser.cpp; sourceTree = ""; }; - C273608B1433F36D00A9A5FF /* SecAssessment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecAssessment.h; sourceTree = ""; }; - C2884AA7148411DF00DF0CD1 /* libxar-nossl.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = "libxar-nossl.dylib"; path = "../../../../../usr/lib/libxar-nossl.dylib"; sourceTree = ""; }; - C299D086056BF15B004BB123 /* generateErrStrings.pl */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.script.perl; path = generateErrStrings.pl; sourceTree = ""; }; - C29B69330AD326B3007D7504 /* SecCodeSigner.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecCodeSigner.h; sourceTree = ""; }; - C2A1D3D90F58C1A100BD09F8 /* libbsm.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libbsm.dylib; path = /usr/lib/libbsm.dylib; sourceTree = ""; }; - C2A487990B79160900849490 /* SecCodeHostLib.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecCodeHostLib.h; sourceTree = ""; }; - C2A4879A0B79160900849490 /* SecIntegrity.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecIntegrity.h; sourceTree = ""; }; - C2CACF930DE26792003057A0 /* CodeSigning.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CodeSigning.h; sourceTree = ""; }; - C2CACF940DE26792003057A0 /* CSCommon.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSCommon.h; sourceTree = ""; }; - C2CACF950DE26792003057A0 /* SecCode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecCode.h; sourceTree = ""; }; - C2CACF960DE26792003057A0 /* SecRequirement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecRequirement.h; sourceTree = ""; }; - C2CACF970DE26792003057A0 /* SecStaticCode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecStaticCode.h; sourceTree = ""; }; - C2CC31350B85271C005FA59D /* SecIntegrityLib.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecIntegrityLib.h; sourceTree = ""; }; - C2CFB9FC0DF8794A003F57E4 /* SecCodeHost.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecCodeHost.h; sourceTree = ""; }; - C2D50D0B0E155F5E0059A195 /* CSCommonPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSCommonPriv.h; sourceTree = ""; }; - C2FBE3520E3E5B0A00BC6617 /* libsqlite3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libsqlite3.dylib; path = /usr/lib/libsqlite3.dylib; sourceTree = ""; }; - C4294290053B28F100470431 /* Security.order */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = Security.order; sourceTree = ""; }; - D619986009F6FC4800699932 /* SecureDownload.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecureDownload.h; sourceTree = ""; }; - D619986209F6FC5A00699932 /* SecureDownloadInternal.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecureDownloadInternal.h; sourceTree = ""; }; - D6FB4E6805F934DC0015312A /* SecManifest.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecManifest.h; sourceTree = ""; }; - D6FB4E6F05F935690015312A /* security_manifest.exp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.exports; path = security_manifest.exp; sourceTree = ""; }; - D6FB4E9405F937900015312A /* security_manifest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = security_manifest.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - D6FB4E9505F937900015312A /* security_smime.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = security_smime.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - EB286951157EA8FC008BAF8C /* libOpenScriptingUtil.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libOpenScriptingUtil.dylib; path = ../../../../../../usr/lib/libOpenScriptingUtil.dylib; sourceTree = ""; }; - FE2D0DC010DC0E6A00726AB5 /* SecTask.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecTask.h; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 0867D6A0FE84028FC02AAC07 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - EB286952157EA8FC008BAF8C /* libOpenScriptingUtil.dylib in Frameworks */, - AA8AC7AF1117BDD10002A07F /* security_transform.framework in Frameworks */, - 1C4A135111066573006A16DA /* libpam.dylib in Frameworks */, - C2FBE3530E3E5B0A00BC6617 /* libsqlite3.dylib in Frameworks */, - C2A1D3DA0F58C1A100BD09F8 /* libbsm.dylib in Frameworks */, - 12D4A8AC1226F92D00C2B581 /* libz.dylib in Frameworks */, - C2884AA8148411DF00DF0CD1 /* libxar-nossl.dylib in Frameworks */, + 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 */, + 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 */, + 182BB3A5146F1BEC000BF1F3 /* SecTransform.h */, + 182BB3AB146F1BEC000BF1F3 /* SecTransformReadTransform.h */, + 182BB194146EAD4C000BF1F3 /* SecTrust.h */, + 182BB195146EAD4C000BF1F3 /* SecTrustedApplication.h */, + 182BB198146EAD4C000BF1F3 /* SecTrustSettings.h */, + 182BB315146F0E7E000BF1F3 /* SecureDownload.h */, + 182BB36F146F13B4000BF1F3 /* SecureTransport.h */, + 182BB196146EAD4C000BF1F3 /* Security.h */, + 1879B4C4146DCA84007E536C /* x509defs.h */, ); - runOnlyForDeploymentPostprocessing = 0; + name = Headers; + sourceTree = ""; }; - C224636F0B86212100626F1B /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - C27263200B86288B00D889AF /* Security.framework in Frameworks */, + 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 */, + 18446099146DFCB700B12992 /* secasn1t.h */, + 18446194146E9A8F00B12992 /* SecAssessment.h */, + 182BB1B3146EAD5D000BF1F3 /* SecBasePriv.h */, + 182BB1B4146EAD5D000BF1F3 /* SecCertificateBundle.h */, + 182BB1CD146EAD5D000BF1F3 /* SecCertificateInternalP.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 */, + 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 */, + 182BB1C8146EAD5D000BF1F3 /* TrustSettingsSchema.h */, + 1844609E146DFCB700B12992 /* X509Templates.h */, + 52B5A9C01519330300664F11 /* tsaSupport.h */, + 52AEA484153C7581005AFC59 /* tsaSupportPriv.h */, + 52B5A9C11519330300664F11 /* tsaTemplates.h */, ); - runOnlyForDeploymentPostprocessing = 0; + name = PrivateHeaders; + sourceTree = ""; }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 034768DFFF38A50411DB9C8B /* Products */ = { + 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 = ( - 034768E0FF38A50411DB9C8B /* Security.framework */, - 4C216214053639A600CCA0BB /* generate */, - C22463710B86212100626F1B /* csparser.bundle */, + 1879B538146DDBE5007E536C /* libsecurity_utilities.a */, ); name = Products; sourceTree = ""; }; - 0867D691FE84028FC02AAC07 /* Security */ = { + 1879B548146DE212007E536C /* Products */ = { isa = PBXGroup; children = ( - EB286951157EA8FC008BAF8C /* libOpenScriptingUtil.dylib */, - 4CD808CC05360655009F54B0 /* lib */, - C27262DF0B86228400D889AF /* plugins */, - 089C1665FE841158C02AAC07 /* intl */, - 4CAF731305363B5200D9DA7C /* derived_src */, - 4C5969DA058115A0001507D4 /* SecurityPieces */, - 0867D69AFE84028FC02AAC07 /* External Frameworks and Libraries */, - 034768DFFF38A50411DB9C8B /* Products */, - 12D4A8AB1226F92D00C2B581 /* libz.dylib */, + 1879B54F146DE212007E536C /* libsecurity_cdsa_utils.a */, ); - name = Security; + name = Products; sourceTree = ""; }; - 0867D69AFE84028FC02AAC07 /* External Frameworks and Libraries */ = { + 1879B551146DE227007E536C /* Products */ = { isa = PBXGroup; children = ( - 1058C7B0FEA5585E11CA2CBB /* Linked Frameworks */, - 1058C7B2FEA5585E11CA2CBB /* Other Frameworks */, + 1879B55A146DE227007E536C /* libsecurity_cdsa_utilities.a */, + 1879B55C146DE227007E536C /* Schemas */, ); - name = "External Frameworks and Libraries"; + name = Products; sourceTree = ""; }; - 089C1665FE841158C02AAC07 /* intl */ = { + 1879B55E146DE244007E536C /* Products */ = { isa = PBXGroup; children = ( - 44DAD0F211CAB4F8007A9244 /* FDELocalizable.strings */, - 089C1666FE841158C02AAC07 /* InfoPlist.strings */, + 1879B565146DE244007E536C /* libsecurity_cssm.a */, ); - path = intl; + name = Products; sourceTree = ""; }; - 1058C7B0FEA5585E11CA2CBB /* Linked Frameworks */ = { + 1879B5BD146DE6C8007E536C /* Products */ = { isa = PBXGroup; children = ( - C2884AA7148411DF00DF0CD1 /* libxar-nossl.dylib */, - 1C4A135011066564006A16DA /* libpam.dylib */, - 4C01DDF20540D04C00A9C9B2 /* security_apple_csp.framework */, - 4C01DDF30540D04C00A9C9B2 /* security_apple_cspdl.framework */, - 4C01DDF40540D04C00A9C9B2 /* security_apple_file_dl.framework */, - 4C01DDF50540D04C00A9C9B2 /* security_apple_x509_cl.framework */, - 4C01DDF60540D04C00A9C9B2 /* security_apple_x509_tp.framework */, - 4C01DDF70540D04C00A9C9B2 /* security_asn1.framework */, - 4C01DDF80540D04C00A9C9B2 /* security_cdsa_client.framework */, - 4C01DDF90540D04C00A9C9B2 /* security_cdsa_plugin.framework */, - 4C01DDFA0540D04C00A9C9B2 /* security_cdsa_utilities.framework */, - 4C01DDFB0540D04C00A9C9B2 /* security_cdsa_utils.framework */, - 4C01DDFC0540D04C00A9C9B2 /* security_checkpw.framework */, - 4C01DDFD0540D04C00A9C9B2 /* security_cssm.framework */, - 4C01DDFF0540D04C00A9C9B2 /* security_keychain.framework */, - 4C01DE000540D04C00A9C9B2 /* security_mds.framework */, - 4C01DE010540D04C00A9C9B2 /* security_ssl.framework */, - 4C01DE020540D04C00A9C9B2 /* security_utilities.framework */, - 4C01DE040540D04C00A9C9B2 /* securityd_client.framework */, - 4C01DE050540D04C00A9C9B2 /* securityd_server.framework */, - D6FB4E9405F937900015312A /* security_manifest.framework */, - 4ED0DD500E887E6400F626D0 /* security_cryptkit.framework */, - D6FB4E9505F937900015312A /* security_smime.framework */, - 4C01DDFE0540D04C00A9C9B2 /* security_filedb.framework */, - 4CD8084D0536046D009F54B0 /* CoreFoundation.framework */, - 053105C105E19ED400044101 /* Foundation.framework */, - C2FBE3520E3E5B0A00BC6617 /* libsqlite3.dylib */, - C2A1D3D90F58C1A100BD09F8 /* libbsm.dylib */, - AA3ED3C81117BD76001DD41A /* security_transform.framework */, - ); - name = "Linked Frameworks"; + 1879B5C6146DE6C8007E536C /* libsecurity_apple_csp.a */, + ); + name = Products; sourceTree = ""; }; - 1058C7B2FEA5585E11CA2CBB /* Other Frameworks */ = { + 1879B5CA146DE6CE007E536C /* Products */ = { isa = PBXGroup; children = ( + 1879B5D2146DE6CE007E536C /* libsecurity_apple_cspdl.a */, ); - name = "Other Frameworks"; + name = Products; sourceTree = ""; }; - 4C5969DA058115A0001507D4 /* SecurityPieces */ = { + 1879B5D6146DE6D7007E536C /* Products */ = { isa = PBXGroup; children = ( - 4C5969DB058115A0001507D4 /* Exports */, - 4C5969E3058115A0001507D4 /* Headers */, - 4C596A16058115A0001507D4 /* PrivateHeaders */, - 4C596A28058115A0001507D4 /* Resources */, + 1879B5DE146DE6D7007E536C /* libsecurity_apple_file_dl.a */, ); - path = SecurityPieces; - sourceTree = BUILT_PRODUCTS_DIR; + 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 = ""; }; - 4C5969DB058115A0001507D4 /* Exports */ = { + 1879B5FD146DE704007E536C /* Products */ = { isa = PBXGroup; children = ( - 4C5969DC058115A0001507D4 /* Security */, + 1885B3F914D8D9B100519375 /* libASN1.a */, ); - path = Exports; + name = Products; sourceTree = ""; }; - 4C5969DC058115A0001507D4 /* Security */ = { + 1879B60A146DE70A007E536C /* Products */ = { isa = PBXGroup; children = ( - 053C8CC706503E9E0047C7CA /* security_asn1.exp */, - 4C5969DD058115A0001507D4 /* security_checkpw.exp */, - 052C0802098950D000E7641D /* security_cms.exp */, - 4C5969DE058115A0001507D4 /* security_cssm.exp */, - 4C5969DF058115A0001507D4 /* security_keychain.exp */, - D6FB4E6F05F935690015312A /* security_manifest.exp */, - 4C5969E0058115A0001507D4 /* security_mds.exp */, - 4CA9BEDD0637274A0013F16F /* security_smime.exp */, - 4C5969E1058115A0001507D4 /* security_ssl.exp */, - 4C5969E2058115A0001507D4 /* securityd_client.exp */, - ); - path = Security; + 1879B612146DE70A007E536C /* libsecurity_authorization.a */, + ); + name = Products; sourceTree = ""; }; - 4C5969E3058115A0001507D4 /* Headers */ = { + 1879B616146DE715007E536C /* Products */ = { isa = PBXGroup; children = ( - 4C5969E4058115A0001507D4 /* Security */, + 1879B61E146DE715007E536C /* libsecurity_cdsa_client.a */, ); - path = Headers; + name = Products; sourceTree = ""; }; - 4C5969E4058115A0001507D4 /* Security */ = { + 1879B622146DE720007E536C /* Products */ = { isa = PBXGroup; children = ( - AA19373F138E25430029DDC3 /* SecReadTransform.h */, - AA928D07123AEE3C0030D59E /* SecTransformReadTransform.h */, - 12D4A8F112270ABC00C2B581 /* SecRandom.h */, - 5DCB818F12073F90007A7D84 /* SecCustomTransform.h */, - 52FB469C11481F39006D3B0A /* SecCertificateOIDs.h */, - AA7CA2EB1117BE7600901AF5 /* SecDigestTransform.h */, - AA7CA2EC1117BE7600901AF5 /* SecTransform.h */, - 5D97B3F9114EF0D00033D0F9 /* SecDecodeTransform.h */, - 5D97B3FA114EF0D00033D0F9 /* SecEncodeTransform.h */, - 5D97B3FB114EF0D00033D0F9 /* SecEncryptTransform.h */, - 5D97B3FC114EF0D00033D0F9 /* SecSignVerifyTransform.h */, - C2CACF930DE26792003057A0 /* CodeSigning.h */, - C2CACF940DE26792003057A0 /* CSCommon.h */, - C2CACF950DE26792003057A0 /* SecCode.h */, - C2CACF960DE26792003057A0 /* SecRequirement.h */, - C2CACF970DE26792003057A0 /* SecStaticCode.h */, - C2CFB9FC0DF8794A003F57E4 /* SecCodeHost.h */, - 050CCC390A115F96004DFCA9 /* SecTrustSettings.h */, - D619986009F6FC4800699932 /* SecureDownload.h */, - 052C080C0989535300E7641D /* CMSDecoder.h */, - 052C080D0989535300E7641D /* CMSEncoder.h */, - 4C5969E5058115A0001507D4 /* Authorization.h */, - 4C5969E6058115A0001507D4 /* AuthorizationDB.h */, - 4C596A18058115A0001507D4 /* AuthorizationPlugin.h */, - 4C5969E7058115A0001507D4 /* AuthorizationTags.h */, - 4C5969E8058115A0001507D4 /* AuthSession.h */, - 4C5969E9058115A0001507D4 /* certextensions.h */, - 4C5969EB058115A0001507D4 /* CipherSuite.h */, - 4C5969EC058115A0001507D4 /* cssm.h */, - 4C5969ED058115A0001507D4 /* cssmaci.h */, - 4C5969EE058115A0001507D4 /* cssmapi.h */, - 4C5969EF058115A0001507D4 /* cssmapple.h */, - 4C5969F0058115A0001507D4 /* cssmcli.h */, - 4C5969F1058115A0001507D4 /* cssmconfig.h */, - 4C5969F2058115A0001507D4 /* cssmcspi.h */, - 4C5969F3058115A0001507D4 /* cssmdli.h */, - 4C5969F4058115A0001507D4 /* cssmerr.h */, - 4C5969F5058115A0001507D4 /* cssmkrapi.h */, - 4C5969F6058115A0001507D4 /* cssmkrspi.h */, - 4C5969F7058115A0001507D4 /* cssmspi.h */, - 4C5969F8058115A0001507D4 /* cssmtpi.h */, - 4C5969F9058115A0001507D4 /* cssmtype.h */, - 4C5969FA058115A0001507D4 /* eisl.h */, - 4C5969FB058115A0001507D4 /* emmspi.h */, - 4C5969FC058115A0001507D4 /* emmtype.h */, - 4C5969FD058115A0001507D4 /* mds.h */, - 4C5969FE058115A0001507D4 /* mds_schema.h */, - 4C5969FF058115A0001507D4 /* oidsalg.h */, - 4C596A00058115A0001507D4 /* oidsattr.h */, - 4C596A01058115A0001507D4 /* oidsbase.h */, - 4C596A02058115A0001507D4 /* oidscert.h */, - 4C596A03058115A0001507D4 /* oidscrl.h */, - 4C596A04058115A0001507D4 /* SecAccess.h */, - 4C596A05058115A0001507D4 /* SecACL.h */, - 053C8C9206503DD80047C7CA /* SecAsn1Coder.h */, - 053C8C8D06503DD80047C7CA /* SecAsn1Templates.h */, - 05ABB7B10989321500FA0183 /* SecAsn1Types.h */, - 4C596A06058115A0001507D4 /* SecBase.h */, - 4C596A07058115A0001507D4 /* SecCertificate.h */, - 4C596A08058115A0001507D4 /* SecIdentity.h */, - 4C596A09058115A0001507D4 /* SecIdentitySearch.h */, - 05B063C705DB2C1C006FA9A6 /* SecImportExport.h */, - BE4AFDAF0F85EEAB002B2F42 /* SecItem.h */, - 4C596A0A058115A0001507D4 /* SecKey.h */, - 4C596A0B058115A0001507D4 /* SecKeychain.h */, - 4C596A0D058115A0001507D4 /* SecKeychainItem.h */, - 4C596A0E058115A0001507D4 /* SecKeychainSearch.h */, - 4C596A0F058115A0001507D4 /* SecPolicy.h */, - 4C596A10058115A0001507D4 /* SecPolicySearch.h */, - FE2D0DC010DC0E6A00726AB5 /* SecTask.h */, - 4C596A11058115A0001507D4 /* SecTrust.h */, - 4C596A12058115A0001507D4 /* SecTrustedApplication.h */, - 4C596A13058115A0001507D4 /* SecureTransport.h */, - 4C596A14058115A0001507D4 /* Security.h */, - 4C596A15058115A0001507D4 /* x509defs.h */, - ); - path = Security; + 1879B62B146DE720007E536C /* libsecurity_cdsa_plugin.a */, + ); + name = Products; sourceTree = ""; }; - 4C596A16058115A0001507D4 /* PrivateHeaders */ = { + 1879B638146DE748007E536C /* Products */ = { isa = PBXGroup; children = ( - 4C596A17058115A0001507D4 /* Security */, + 1879B644146DE748007E536C /* libsecurity_checkpw.a */, + 1879B648146DE748007E536C /* test-checkpw */, + 1879B64A146DE748007E536C /* perf-checkpw */, ); - path = PrivateHeaders; + name = Products; sourceTree = ""; }; - 4C596A17058115A0001507D4 /* Security */ = { + 1879B64C146DE750007E536C /* Products */ = { isa = PBXGroup; children = ( - 52EEE6FC15893ADA00D20784 /* cmspriv.h */, - 52EEE6FA15893A5000D20784 /* tsaSupport.h */, - 12D4A8BE1226FAD900C2B581 /* SecRandomP.h */, - 52B88E9411DD5CCF005BCA6B /* SecFDERecoveryAsymmetricCrypto.h */, - AA963A0B11A61D3500AE419B /* SecTransformInternal.h */, - 52008CCB11496FB700E8CA78 /* SecCertificateInternalP.h */, - AA4F5B6811405CAB00388604 /* SecCustomTransform.h */, - AA8AC7B31117BDF30002A07F /* SecNullTransform.h */, - C2D50D0B0E155F5E0059A195 /* CSCommonPriv.h */, - C2022A010DE267FC009A9816 /* SecCodePriv.h */, - C273608B1433F36D00A9A5FF /* SecAssessment.h */, - C2022A020DE267FC009A9816 /* SecRequirementPriv.h */, - C2022A030DE267FC009A9816 /* SecStaticCodePriv.h */, - C2CC31350B85271C005FA59D /* SecIntegrityLib.h */, - C2A487990B79160900849490 /* SecCodeHostLib.h */, - C2A4879A0B79160900849490 /* SecIntegrity.h */, - C29B69330AD326B3007D7504 /* SecCodeSigner.h */, - D619986209F6FC5A00699932 /* SecureDownloadInternal.h */, - 052C08100989535F00E7641D /* CMSPrivate.h */, - 05ABB7BF0989391A00FA0183 /* asn1Templates.h */, - 4C596A19058115A0001507D4 /* AuthorizationPriv.h */, - 4C596A1A058115A0001507D4 /* AuthorizationTagsPriv.h */, - 053C8C8E06503DD80047C7CA /* certExtensionTemplates.h */, - 4C5969EA058115A0001507D4 /* checkpw.h */, - 053C8C8F06503DD80047C7CA /* csrTemplates.h */, - 053C8C9006503DD80047C7CA /* keyTemplates.h */, - C234BC47069DBAB2006A5163 /* mdspriv.h */, - 053C8C9106503DD80047C7CA /* nameTemplates.h */, - 0504B1B406517D230011D5F5 /* osKeyTemplates.h */, - 4C596A1B058115A0001507D4 /* SecAccessPriv.h */, - 053C8C9306503DD80047C7CA /* secasn1t.h */, - 4C868462058A56780072F261 /* SecBasePriv.h */, - 4C596A1C058115A0001507D4 /* SecCertificateBundle.h */, - 4C596A1D058115A0001507D4 /* SecCertificatePriv.h */, - 4C596A1E058115A0001507D4 /* SecCertificateRequest.h */, - 4CA9BEBD063726BD0013F16F /* SecCmsBase.h */, - 4CA9BEBE063726BD0013F16F /* SecCmsContentInfo.h */, - 4CA9BEBF063726BD0013F16F /* SecCmsDecoder.h */, - 4CA9BEC0063726BD0013F16F /* SecCmsDigestContext.h */, - 4CA9BEC1063726BD0013F16F /* SecCmsDigestedData.h */, - 4CA9BEC2063726BD0013F16F /* SecCmsEncoder.h */, - 4CA9BEC3063726BD0013F16F /* SecCmsEncryptedData.h */, - 4CA9BEC4063726BD0013F16F /* SecCmsEnvelopedData.h */, - 4CA9BEC5063726BD0013F16F /* SecCmsMessage.h */, - 4CA9BEC6063726BD0013F16F /* SecCmsRecipientInfo.h */, - 4CA9BEC7063726BD0013F16F /* SecCmsSignedData.h */, - 4CA9BEC8063726BD0013F16F /* SecCmsSignerInfo.h */, - 4C596A1F058115A0001507D4 /* SecIdentityPriv.h */, - 309CD1F9062B3D1900B66530 /* SecIdentitySearchPriv.h */, - BE4AFDB40F85EEE7002B2F42 /* SecItemPriv.h */, - 4C596A21058115A0001507D4 /* SecKeychainItemPriv.h */, - 059D38350AB7866600CEF189 /* SecKeychainItemExtendedAttributes.h */, - 4C596A22058115A0001507D4 /* SecKeychainPriv.h */, - 1B40AAED062F63E7009BAE74 /* SecKeychainSearchPriv.h */, - 4C596A23058115A0001507D4 /* SecKeyPriv.h */, - D6FB4E6805F934DC0015312A /* SecManifest.h */, - 40A2A720066FE6B200858603 /* SecPassword.h */, - 4C596A24058115A0001507D4 /* SecPolicyPriv.h */, - 48C16F4411D162D60037E993 /* SecRecoveryPassword.h */, - 4CA9BEC9063726BD0013F16F /* SecSMIME.h */, - 4C596A25058115A0001507D4 /* SecTrustedApplicationPriv.h */, - 4C596A26058115A0001507D4 /* SecTrustPriv.h */, - 050CCC3B0A115FAC004DFCA9 /* SecTrustSettingsPriv.h */, - 4C596A27058115A0001507D4 /* SecureTransportPriv.h */, - 050CCC3C0A115FAC004DFCA9 /* TrustSettingsSchema.h */, - 05792F4E065082C100C80DB3 /* X509Templates.h */, - 05D0BC8206A87338001F9A43 /* cssmapplePriv.h */, - 05D0BC8306A87338001F9A43 /* ocspTemplates.h */, - ); - path = Security; + 1879B654146DE750007E536C /* libsecurity_cms.a */, + ); + name = Products; sourceTree = ""; }; - 4C596A28058115A0001507D4 /* Resources */ = { + 1879B658146DE756007E536C /* Products */ = { isa = PBXGroup; children = ( - 4C596A29058115A0001507D4 /* Security */, + 1879B666146DE757007E536C /* libsecurity_codesigning.a */, + 1879B66A146DE757007E536C /* libintegrity.a */, + 1879B66C146DE757007E536C /* libcodehost.a */, ); - path = Resources; + name = Products; sourceTree = ""; }; - 4C596A29058115A0001507D4 /* Security */ = { + 1879B66E146DE75D007E536C /* Products */ = { isa = PBXGroup; children = ( - 5270685407024D6F00C5D30E /* iToolsTrustedApps.plist */, - 4C596A2A058115A0001507D4 /* cl_common.mdsinfo */, - 4C596A2B058115A0001507D4 /* cl_primary.mdsinfo */, - 4C596A2C058115A0001507D4 /* csp_capabilities.mdsinfo */, - 4C596A2D058115A0001507D4 /* csp_capabilities_common.mds */, - 4C596A2E058115A0001507D4 /* csp_common.mdsinfo */, - 4C596A2F058115A0001507D4 /* csp_primary.mdsinfo */, - 4C596A30058115A0001507D4 /* cspdl_common.mdsinfo */, - 4C596A31058115A0001507D4 /* cspdl_csp_capabilities.mdsinfo */, - 4C596A32058115A0001507D4 /* cspdl_csp_primary.mdsinfo */, - 4C596A33058115A0001507D4 /* cspdl_dl_primary.mdsinfo */, - 4C596A34058115A0001507D4 /* cssm.mdsinfo */, - 4C596A35058115A0001507D4 /* dl_common.mdsinfo */, - 4C596A36058115A0001507D4 /* dl_primary.mdsinfo */, - 4C8C2C1506D1AE6A00B00C2F /* sd_cspdl_common.mdsinfo */, - 4C596A38058115A0001507D4 /* tp_common.mdsinfo */, - 4C596A39058115A0001507D4 /* tp_policyOids.mdsinfo */, - 4C596A3A058115A0001507D4 /* tp_primary.mdsinfo */, - ); - path = Security; + 1879B676146DE75E007E536C /* libsecurity_comcryption.a */, + ); + name = Products; sourceTree = ""; }; - 4CAF731305363B5200D9DA7C /* derived_src */ = { + 1879B67A146DE76E007E536C /* Products */ = { isa = PBXGroup; children = ( - 52141F5709771DAB002C0FF6 /* SecDebugErrorMessages.strings */, - 4CAF731A05363BD700D9DA7C /* security_exports.s */, - C21204A4056D89280018F475 /* SecErrorMessages.strings */, + 1879B684146DE76F007E536C /* libsecurity_cryptkit.a */, + 1879B688146DE76F007E536C /* libCryptKit.a */, + 1879B68A146DE76F007E536C /* CryptKitSignature.a */, ); - path = derived_src; - sourceTree = BUILT_PRODUCTS_DIR; + name = Products; + sourceTree = ""; }; - 4CD808CC05360655009F54B0 /* lib */ = { + 1879B695146DE797007E536C /* Products */ = { isa = PBXGroup; children = ( - 521F28F115758C66002B3975 /* TimeStampingPrefs.plist */, - 44B9317C11CC0917005FBCF1 /* FDEPrefs.plist */, - 4C60A0B105811AC800C8A016 /* copy_pieces.mk */, - C299D086056BF15B004BB123 /* generateErrStrings.pl */, - C4294290053B28F100470431 /* Security.order */, + 1879B69D146DE797007E536C /* libsecurity_filedb.a */, ); - path = lib; + name = Products; sourceTree = ""; }; - C27262DF0B86228400D889AF /* plugins */ = { + 1879B6A1146DE79F007E536C /* Products */ = { isa = PBXGroup; children = ( - C27262F50B8624BE00D889AF /* csparser.cpp */, - C22463720B86212100626F1B /* csparser-Info.plist */, - C27262E80B86236100D889AF /* csparser.exp */, + 1879B6B3146DE7A0007E536C /* libsecurity_keychain.a */, + 1879B6B7146DE7A0007E536C /* XPCKeychainSandboxCheck.xpc */, + 52B5A8F6151928B400664F11 /* XPCTimeStampingService.xpc */, ); - path = plugins; + 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 */, + ); + name = Products; + sourceTree = ""; + }; + 1879B720146DE839007E536C /* Products */ = { + isa = PBXGroup; + children = ( + 1879B728146DE839007E536C /* libsecurity_ssl.a */, + ); + 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 = ""; }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ - 0867D69DFE84028FC02AAC07 /* Headers */ = { + 18073848146D0D4E00F05C24 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - AA5C5A66138E25FB00D9E6C1 /* SecReadTransform.h in Headers */, - AA928D21123AEEBD0030D59E /* SecTransformReadTransform.h in Headers */, - 52B88E9511DD5D96005BCA6B /* SecFDERecoveryAsymmetricCrypto.h in Headers */, - AAEB7DB211A61DF40011AE9E /* SecTransformInternal.h in Headers */, - 52008CCC11496FB700E8CA78 /* SecCertificateInternalP.h in Headers */, - 52FB469D11481F39006D3B0A /* SecCertificateOIDs.h in Headers */, - AACB24E71117BEC100B236A2 /* SecDigestTransform.h in Headers */, - AACB24E81117BEC100B236A2 /* SecTransform.h in Headers */, - AA7CA2E91117BE2B00901AF5 /* SecNullTransform.h in Headers */, - 5D97B436114EFC260033D0F9 /* SecDecodeTransform.h in Headers */, - 5D97B437114EFC260033D0F9 /* SecEncodeTransform.h in Headers */, - 5D97B438114EFC260033D0F9 /* SecEncryptTransform.h in Headers */, - 5D97B439114EFC260033D0F9 /* SecSignVerifyTransform.h in Headers */, - FE2D0DC110DC0E8D00726AB5 /* SecTask.h in Headers */, - C2CFBA030DF87990003F57E4 /* SecCodeHost.h in Headers */, - C2022A140DE26927009A9816 /* CodeSigning.h in Headers */, - C2022A150DE26927009A9816 /* CSCommon.h in Headers */, - C2D50D0C0E155F720059A195 /* CSCommonPriv.h in Headers */, - C2022A160DE26927009A9816 /* SecCode.h in Headers */, - C2022A170DE26927009A9816 /* SecRequirement.h in Headers */, - C2022A180DE26927009A9816 /* SecStaticCode.h in Headers */, - C2022A110DE26911009A9816 /* SecCodePriv.h in Headers */, - C2022A120DE26911009A9816 /* SecRequirementPriv.h in Headers */, - C2022A130DE26911009A9816 /* SecStaticCodePriv.h in Headers */, - C2CC31360B85271C005FA59D /* SecIntegrityLib.h in Headers */, - C2A4879B0B79160900849490 /* SecCodeHostLib.h in Headers */, - C2A4879C0B79160900849490 /* SecIntegrity.h in Headers */, - C29B69340AD326CE007D7504 /* SecCodeSigner.h in Headers */, - 4C596A41058115A0001507D4 /* Authorization.h in Headers */, - 4C596A42058115A0001507D4 /* AuthorizationDB.h in Headers */, - 4C596A43058115A0001507D4 /* AuthorizationTags.h in Headers */, - 4C596A44058115A0001507D4 /* AuthSession.h in Headers */, - 4C596A45058115A0001507D4 /* certextensions.h in Headers */, - 4C596A47058115A0001507D4 /* CipherSuite.h in Headers */, - 4C596A48058115A0001507D4 /* cssm.h in Headers */, - 4C596A49058115A0001507D4 /* cssmaci.h in Headers */, - 4C596A4A058115A0001507D4 /* cssmapi.h in Headers */, - 4C596A4B058115A0001507D4 /* cssmapple.h in Headers */, - 4C596A4C058115A0001507D4 /* cssmcli.h in Headers */, - 4C596A4D058115A0001507D4 /* cssmconfig.h in Headers */, - 4C596A4E058115A0001507D4 /* cssmcspi.h in Headers */, - 4C596A4F058115A0001507D4 /* cssmdli.h in Headers */, - 4C596A50058115A0001507D4 /* cssmerr.h in Headers */, - 4C596A51058115A0001507D4 /* cssmkrapi.h in Headers */, - 4C596A52058115A0001507D4 /* cssmkrspi.h in Headers */, - 4C596A53058115A0001507D4 /* cssmspi.h in Headers */, - 4C596A54058115A0001507D4 /* cssmtpi.h in Headers */, - 4C596A55058115A0001507D4 /* cssmtype.h in Headers */, - 4C596A56058115A0001507D4 /* eisl.h in Headers */, - 4C596A57058115A0001507D4 /* emmspi.h in Headers */, - 4C596A58058115A0001507D4 /* emmtype.h in Headers */, - 4C596A59058115A0001507D4 /* mds.h in Headers */, - C234BC48069DBAB2006A5163 /* mdspriv.h in Headers */, - 4C596A5A058115A0001507D4 /* mds_schema.h in Headers */, - 4C596A5B058115A0001507D4 /* oidsalg.h in Headers */, - 4C596A5C058115A0001507D4 /* oidsattr.h in Headers */, - 4C596A5D058115A0001507D4 /* oidsbase.h in Headers */, - 4C596A5E058115A0001507D4 /* oidscert.h in Headers */, - 4C596A5F058115A0001507D4 /* oidscrl.h in Headers */, - 4C596A60058115A0001507D4 /* SecAccess.h in Headers */, - 4C596A61058115A0001507D4 /* SecACL.h in Headers */, - 4C596A62058115A0001507D4 /* SecBase.h in Headers */, - 4C596A63058115A0001507D4 /* SecCertificate.h in Headers */, - 4C596A64058115A0001507D4 /* SecIdentity.h in Headers */, - 4C596A65058115A0001507D4 /* SecIdentitySearch.h in Headers */, - 05B063C805DB2C1C006FA9A6 /* SecImportExport.h in Headers */, - 4C596A66058115A0001507D4 /* SecKey.h in Headers */, - 4C596A67058115A0001507D4 /* SecKeychain.h in Headers */, - 4C596A69058115A0001507D4 /* SecKeychainItem.h in Headers */, - 4C596A6A058115A0001507D4 /* SecKeychainSearch.h in Headers */, - 4C596A6B058115A0001507D4 /* SecPolicy.h in Headers */, - 4C596A6C058115A0001507D4 /* SecPolicySearch.h in Headers */, - 4C596A6D058115A0001507D4 /* SecTrust.h in Headers */, - 4C596A6E058115A0001507D4 /* SecTrustedApplication.h in Headers */, - 4C596A6F058115A0001507D4 /* SecureTransport.h in Headers */, - 4C596A70058115A0001507D4 /* Security.h in Headers */, - 4C596A71058115A0001507D4 /* x509defs.h in Headers */, - 4C596A72058115A0001507D4 /* AuthorizationPlugin.h in Headers */, - 4C596A73058115A0001507D4 /* AuthorizationPriv.h in Headers */, - 4C596A74058115A0001507D4 /* AuthorizationTagsPriv.h in Headers */, - 4C596A46058115A0001507D4 /* checkpw.h in Headers */, - 4C596A75058115A0001507D4 /* SecAccessPriv.h in Headers */, - 4C868463058A56780072F261 /* SecBasePriv.h in Headers */, - 4C596A76058115A0001507D4 /* SecCertificateBundle.h in Headers */, - 4C596A77058115A0001507D4 /* SecCertificatePriv.h in Headers */, - 4C596A78058115A0001507D4 /* SecCertificateRequest.h in Headers */, - 4CA9BECA063726BD0013F16F /* SecCmsBase.h in Headers */, - 4CA9BECB063726BD0013F16F /* SecCmsContentInfo.h in Headers */, - 4CA9BECC063726BD0013F16F /* SecCmsDecoder.h in Headers */, - 4CA9BECD063726BD0013F16F /* SecCmsDigestContext.h in Headers */, - 4CA9BECE063726BD0013F16F /* SecCmsDigestedData.h in Headers */, - 4CA9BECF063726BD0013F16F /* SecCmsEncoder.h in Headers */, - 4CA9BED0063726BD0013F16F /* SecCmsEncryptedData.h in Headers */, - 4CA9BED1063726BD0013F16F /* SecCmsEnvelopedData.h in Headers */, - 4CA9BED2063726BD0013F16F /* SecCmsMessage.h in Headers */, - 4CA9BED3063726BD0013F16F /* SecCmsRecipientInfo.h in Headers */, - 4CA9BED4063726BD0013F16F /* SecCmsSignedData.h in Headers */, - 4CA9BED5063726BD0013F16F /* SecCmsSignerInfo.h in Headers */, - 4C596A79058115A0001507D4 /* SecIdentityPriv.h in Headers */, - 309CD1FA062B3D1900B66530 /* SecIdentitySearchPriv.h in Headers */, - 4C596A7B058115A0001507D4 /* SecKeychainItemPriv.h in Headers */, - 059D38360AB7866600CEF189 /* SecKeychainItemExtendedAttributes.h in Headers */, - 4C596A7C058115A0001507D4 /* SecKeychainPriv.h in Headers */, - 1B40AAEE062F63E7009BAE74 /* SecKeychainSearchPriv.h in Headers */, - 4C596A7D058115A0001507D4 /* SecKeyPriv.h in Headers */, - D6FB4E6A05F934DC0015312A /* SecManifest.h in Headers */, - 4C596A7E058115A0001507D4 /* SecPolicyPriv.h in Headers */, - 4CA9BED6063726BD0013F16F /* SecSMIME.h in Headers */, - 053C8C9406503DD80047C7CA /* SecAsn1Templates.h in Headers */, - 053C8C9506503DD80047C7CA /* certExtensionTemplates.h in Headers */, - 053C8C9606503DD80047C7CA /* csrTemplates.h in Headers */, - 053C8C9706503DD80047C7CA /* keyTemplates.h in Headers */, - 053C8C9806503DD80047C7CA /* nameTemplates.h in Headers */, - 053C8C9906503DD80047C7CA /* SecAsn1Coder.h in Headers */, - 053C8C9A06503DD80047C7CA /* secasn1t.h in Headers */, - 4C596A7F058115A0001507D4 /* SecTrustedApplicationPriv.h in Headers */, - 4C596A80058115A0001507D4 /* SecTrustPriv.h in Headers */, - 4C596A81058115A0001507D4 /* SecureTransportPriv.h in Headers */, - 05792F4F065082C100C80DB3 /* X509Templates.h in Headers */, - 0504B1B506517D230011D5F5 /* osKeyTemplates.h in Headers */, - 40A2A721066FE6B300858603 /* SecPassword.h in Headers */, - 05D0BC8406A87338001F9A43 /* cssmapplePriv.h in Headers */, - 05D0BC8506A87338001F9A43 /* ocspTemplates.h in Headers */, - 05ABB7B20989321500FA0183 /* SecAsn1Types.h in Headers */, - 05ABB7C00989391A00FA0183 /* asn1Templates.h in Headers */, - 052C080E0989535300E7641D /* CMSDecoder.h in Headers */, - 052C080F0989535300E7641D /* CMSEncoder.h in Headers */, - 052C08110989535F00E7641D /* CMSPrivate.h in Headers */, - D619986109F6FC4800699932 /* SecureDownload.h in Headers */, - D619986309F6FC5A00699932 /* SecureDownloadInternal.h in Headers */, - 050CCC3A0A115F96004DFCA9 /* SecTrustSettings.h in Headers */, - 050CCC3D0A115FAC004DFCA9 /* SecTrustSettingsPriv.h in Headers */, - 050CCC3E0A115FAC004DFCA9 /* TrustSettingsSchema.h in Headers */, - BE4AFDB00F85EEAB002B2F42 /* SecItem.h in Headers */, - BE4AFDB50F85EEE7002B2F42 /* SecItemPriv.h in Headers */, - 5DCB819012073F90007A7D84 /* SecCustomTransform.h in Headers */, - 12D4A8BF1226FAD900C2B581 /* SecRandomP.h in Headers */, - 12D4A8F212270ABC00C2B581 /* SecRandom.h in Headers */, - C273608C1433F36D00A9A5FF /* SecAssessment.h in Headers */, - 52EEE6FB15893A5000D20784 /* tsaSupport.h in Headers */, - 52EEE6FD15893ADA00D20784 /* cmspriv.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; -/* End PBXHeadersBuildPhase section */ - -/* Begin PBXLegacyTarget section */ - 4C60A0A605811A4300C8A016 /* copy pieces */ = { - isa = PBXLegacyTarget; - buildArgumentsString = "-f lib/copy_pieces.mk $ACTION"; - buildConfigurationList = C23B0C7309A2987F00B7FCED /* Build configuration list for PBXLegacyTarget "copy pieces" */; - buildPhases = ( - ); - buildToolPath = /usr/bin/gnumake; - buildWorkingDirectory = ""; - dependencies = ( + 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 */, + 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 */, + 18FE68601471A46600A2CBE3 /* SecCertificateInternalP.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 */, + 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 */, + 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 */, ); - name = "copy pieces"; - passBuildSettingsInEnvironment = 1; - productName = "copy pieces"; + runOnlyForDeploymentPostprocessing = 0; }; -/* End PBXLegacyTarget section */ +/* End PBXHeadersBuildPhase section */ /* Begin PBXNativeTarget section */ - 0867D69CFE84028FC02AAC07 /* Security */ = { + 1807384A146D0D4E00F05C24 /* Security */ = { isa = PBXNativeTarget; - buildConfigurationList = C23B0C7F09A2987F00B7FCED /* Build configuration list for PBXNativeTarget "Security" */; + buildConfigurationList = 18073875146D0D4E00F05C24 /* Build configuration list for PBXNativeTarget "Security" */; buildPhases = ( - 0867D69DFE84028FC02AAC07 /* Headers */, - 0867D69EFE84028FC02AAC07 /* Resources */, - 0867D69FFE84028FC02AAC07 /* Sources */, - 0867D6A0FE84028FC02AAC07 /* Frameworks */, - 4C77DA7506DD0A0200139C22 /* ShellScript */, + 18500F9214708073006F9AB4 /* Run Script Generate Source */, + 18073846146D0D4E00F05C24 /* Sources */, + 18073847146D0D4E00F05C24 /* Frameworks */, + 18073848146D0D4E00F05C24 /* Headers */, + 18500F961470828E006F9AB4 /* Run Script Generate Strings */, + 18073849146D0D4E00F05C24 /* Resources */, + 18500F9114707E10006F9AB4 /* Run Script Copy XPC Service */, ); buildRules = ( ); dependencies = ( - 4CAF730405363B1200D9DA7C /* PBXTargetDependency */, + 18FE688F1471A4C900A2CBE3 /* PBXTargetDependency */, + 1885B45114D9AB3D00519375 /* PBXTargetDependency */, + 18270F5D14CF655B00B05E7F /* PBXTargetDependency */, + 18AD56A614CDED59008233F2 /* PBXTargetDependency */, + 1879B545146DE18D007E536C /* 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 */, + 182BB22C146F07DD000BF1F3 /* PBXTargetDependency */, + 529FF2201523BD7F0029D842 /* PBXTargetDependency */, ); name = Security; - productInstallPath = "$(SYSTEM_LIBRARY_DIR)/Frameworks"; productName = Security; - productReference = 034768E0FF38A50411DB9C8B /* Security.framework */; + productReference = 1807384B146D0D4E00F05C24 /* Security.framework */; productType = "com.apple.product-type.framework"; }; - 4C216213053639A600CCA0BB /* generate */ = { + 18270ED514CF282600B05E7F /* secd */ = { isa = PBXNativeTarget; - buildConfigurationList = C23B0C7909A2987F00B7FCED /* Build configuration list for PBXNativeTarget "generate" */; + buildConfigurationList = 18270EDD14CF282600B05E7F /* Build configuration list for PBXNativeTarget "secd" */; buildPhases = ( - 4CAF72FE053639C900D9DA7C /* ShellScript */, + 18270ED214CF282600B05E7F /* Sources */, + 18270ED314CF282600B05E7F /* Frameworks */, + 18BEB19914CF7F0B00C8BD36 /* CopyFiles */, ); buildRules = ( ); dependencies = ( - 4C68458305814C85003AC7B2 /* PBXTargetDependency */, + 18270EE314CF28D900B05E7F /* PBXTargetDependency */, + 18270EE114CF28D000B05E7F /* PBXTargetDependency */, ); - name = generate; - productInstallPath = /usr/local/bin; - productName = generate; - productReference = 4C216214053639A600CCA0BB /* generate */; + name = secd; + productName = secd; + productReference = 18270ED614CF282600B05E7F /* secd */; productType = "com.apple.product-type.tool"; }; - C22463700B86212100626F1B /* csparser */ = { + 182BB567146F4DCA000BF1F3 /* csparser */ = { isa = PBXNativeTarget; - buildConfigurationList = C22463730B86212200626F1B /* Build configuration list for PBXNativeTarget "csparser" */; + buildConfigurationList = 182BB572146F4DCB000BF1F3 /* Build configuration list for PBXNativeTarget "csparser" */; buildPhases = ( - C224636D0B86212100626F1B /* Resources */, - C224636E0B86212100626F1B /* Sources */, - C224636F0B86212100626F1B /* Frameworks */, - C2A118A30B863B7500F60A3D /* ShellScript */, + 182BB564146F4DCA000BF1F3 /* Sources */, + 182BB565146F4DCA000BF1F3 /* Frameworks */, + 182BB566146F4DCA000BF1F3 /* Resources */, + 182BB583146FDD3C000BF1F3 /* ShellScript */, ); buildRules = ( ); dependencies = ( + 182BB596146FE27F000BF1F3 /* PBXTargetDependency */, + 182BB58F146FE11C000BF1F3 /* PBXTargetDependency */, + 182BB58D146FE0FF000BF1F3 /* PBXTargetDependency */, + 182BB588146FE001000BF1F3 /* PBXTargetDependency */, ); name = csparser; productName = csparser; - productReference = C22463710B86212100626F1B /* csparser.bundle */; + productReference = 182BB568146F4DCA000BF1F3 /* csparser.bundle */; productType = "com.apple.product-type.bundle"; }; + 18FE67E91471A3AA00A2CBE3 /* copyHeaders */ = { + isa = PBXNativeTarget; + buildConfigurationList = 18FE67FB1471A3AA00A2CBE3 /* Build configuration list for PBXNativeTarget "copyHeaders" */; + buildPhases = ( + 18FE67E71471A3AA00A2CBE3 /* Headers */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = copyHeaders; + productName = copyHeaders; + productReference = 18FE67EA1471A3AA00A2CBE3 /* Security.framework */; + productType = "com.apple.product-type.framework"; + }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ - 0867D690FE84028FC02AAC07 /* Project object */ = { + 18073841146D0D4E00F05C24 /* Project object */ = { isa = PBXProject; attributes = { LastUpgradeCheck = 0420; }; - buildConfigurationList = C23B0C8509A2987F00B7FCED /* Build configuration list for PBXProject "Security" */; + buildConfigurationList = 18073844146D0D4E00F05C24 /* Build configuration list for PBXProject "Security" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; - hasScannedForEncodings = 1; + hasScannedForEncodings = 0; knownRegions = ( - English, - Japanese, - French, - German, - Engish, - ); - mainGroup = 0867D691FE84028FC02AAC07 /* Security */; - productRefGroup = 034768DFFF38A50411DB9C8B /* Products */; + 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 = 186CDD1714CA11C700AF9171 /* Products */; + ProjectRef = 186CDD1614CA11C700AF9171 /* sec.xcodeproj */; + }, + ); projectRoot = ""; targets = ( - C224637B0B86213C00626F1B /* World */, - 0867D69CFE84028FC02AAC07 /* Security */, - 4C216213053639A600CCA0BB /* generate */, - 4C60A0A605811A4300C8A016 /* copy pieces */, - C22463700B86212100626F1B /* csparser */, + 186F778814E59FB200434E1F /* Security_frameworks */, + 186F778C14E59FDA00434E1F /* Security_executables */, + 182BB598146FE295000BF1F3 /* World */, + 1807384A146D0D4E00F05C24 /* Security */, + 182BB567146F4DCA000BF1F3 /* csparser */, + 18FE67E91471A3AA00A2CBE3 /* copyHeaders */, + 18270ED514CF282600B05E7F /* secd */, ); }; -/* End PBXProject section */ +/* End PBXProject section */ + +/* Begin PBXReferenceProxy section */ + 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; + }; + 52B5A8F6151928B400664F11 /* XPCTimeStampingService.xpc */ = { + isa = PBXReferenceProxy; + fileType = wrapper.application; + path = XPCTimeStampingService.xpc; + remoteRef = 52B5A8F5151928B400664F11 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; +/* End PBXReferenceProxy section */ /* Begin PBXResourcesBuildPhase section */ - 0867D69EFE84028FC02AAC07 /* Resources */ = { + 18073849146D0D4E00F05C24 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - 089C1668FE841158C02AAC07 /* InfoPlist.strings in Resources */, - 5270685507024D6F00C5D30E /* iToolsTrustedApps.plist in Resources */, - C21204A5056D89280018F475 /* SecErrorMessages.strings in Resources */, - 4C596A82058115A0001507D4 /* cl_common.mdsinfo in Resources */, - 4C596A83058115A0001507D4 /* cl_primary.mdsinfo in Resources */, - 4C596A84058115A0001507D4 /* csp_capabilities.mdsinfo in Resources */, - 4C596A85058115A0001507D4 /* csp_capabilities_common.mds in Resources */, - 4C596A86058115A0001507D4 /* csp_common.mdsinfo in Resources */, - 4C596A87058115A0001507D4 /* csp_primary.mdsinfo in Resources */, - 4C596A88058115A0001507D4 /* cspdl_common.mdsinfo in Resources */, - 4C596A89058115A0001507D4 /* cspdl_csp_capabilities.mdsinfo in Resources */, - 4C596A8A058115A0001507D4 /* cspdl_csp_primary.mdsinfo in Resources */, - 4C596A8B058115A0001507D4 /* cspdl_dl_primary.mdsinfo in Resources */, - 4C596A8C058115A0001507D4 /* cssm.mdsinfo in Resources */, - 4C596A8D058115A0001507D4 /* dl_common.mdsinfo in Resources */, - 4C596A8E058115A0001507D4 /* dl_primary.mdsinfo in Resources */, - 4C8C2C1606D1AE6A00B00C2F /* sd_cspdl_common.mdsinfo in Resources */, - 4C596A90058115A0001507D4 /* tp_common.mdsinfo in Resources */, - 4C596A91058115A0001507D4 /* tp_policyOids.mdsinfo in Resources */, - 4C596A92058115A0001507D4 /* tp_primary.mdsinfo in Resources */, - 52141F5809771DAB002C0FF6 /* SecDebugErrorMessages.strings in Resources */, - 44DAD0F411CAB4F8007A9244 /* FDELocalizable.strings in Resources */, - 44B9317D11CC0917005FBCF1 /* FDEPrefs.plist in Resources */, - 521F28F215758C66002B3975 /* TimeStampingPrefs.plist in Resources */, + 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 */, + 188AD8DC1471FE3E0081C619 /* FDELocalizable.strings in Resources */, + 188AD8DD1471FE3E0081C619 /* InfoPlist.strings in Resources */, + 52B006C015238F76005D4556 /* TimeStampingPrefs.plist in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; - C224636D0B86212100626F1B /* Resources */ = { + 182BB566146F4DCA000BF1F3 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( @@ -1140,874 +2820,612 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ - 4C77DA7506DD0A0200139C22 /* ShellScript */ = { + 182BB583146FDD3C000BF1F3 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "ditto -v ${TARGET_BUILD_DIR}/${FULL_PRODUCT_NAME} ${BUILT_PRODUCTS_DIR}/Security.framework/PlugIns/${FULL_PRODUCT_NAME}\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 = "mkdir -p ${SYMROOT}/${PRODUCT_NAME}.framework\nfor variant in ${BUILD_VARIANTS}\ndo\n\tpostfix=`echo _${variant} | sed 's/_normal//'`\n\tln -fs Versions/Current/${PRODUCT_NAME}${postfix} ${SYMROOT}/${PRODUCT_NAME}.framework/${PRODUCT_NAME}${postfix}\ndone\n\ncp -rp /usr/local/SecurityPieces/XPC/Security.framework/* ${DSTROOT}//System/Library/Frameworks/Security.framework\nfind ${DSTROOT}//System/Library/Frameworks/Security.framework/XPCServices -type f -perm -111 -print0 | xargs -0 strip -Sx\n"; + shellScript = "XPC_SERVICE=XPCKeychainSandboxCheck.xpc\nditto -v ${TARGET_BUILD_DIR}/${XPC_SERVICE} ${BUILT_PRODUCTS_DIR}/Security.framework/XPCServices/${XPC_SERVICE}\nXPC_SERVICE=XPCTimeStampingService.xpc\nditto -v ${TARGET_BUILD_DIR}/${XPC_SERVICE} ${BUILT_PRODUCTS_DIR}/Security.framework/XPCServices/${XPC_SERVICE}\nexit 0"; + showEnvVarsInLog = 0; }; - 4CAF72FE053639C900D9DA7C /* ShellScript */ = { + 18500F9214708073006F9AB4 /* Run Script Generate Source */ = { isa = PBXShellScriptBuildPhase; - buildActionMask = 12; + buildActionMask = 2147483647; files = ( ); inputPaths = ( ); + name = "Run Script Generate Source"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "DERIVED_SRC=${BUILT_PRODUCTS_DIR}/derived_src\nmkdir -p ${DERIVED_SRC}\n\n# make force loader stub\nEXPORTS=${DERIVED_SRC}/Security.exp\nsort -u ${BUILT_PRODUCTS_DIR}/SecurityPieces/Exports/Security/*.exp | grep -v '^#' > ${EXPORTS}.new\ncmp -s ${EXPORTS}.new ${EXPORTS} || mv ${EXPORTS}.new ${EXPORTS}\nTARGET=${DERIVED_SRC}/security_exports.s\nsed 's/^/.reference /' < ${EXPORTS} > ${TARGET}.new\ncmp -s ${TARGET}.new ${TARGET} || mv ${TARGET}.new ${TARGET}\n\n# make error message string files\n\nGENDEBUGSTRS[0]=YES; ERRORSTRINGS[0]=${DERIVED_SRC}/SecDebugErrorMessages.strings\nGENDEBUGSTRS[1]=NO ; ERRORSTRINGS[1]=${DERIVED_SRC}/English.lproj/SecErrorMessages.strings\n\nmkdir -p ${DERIVED_SRC}/English.lproj\n\nfor ((ix=0;ix<2;ix++)) ; do\n\tperl lib/generateErrStrings.pl \\\n\t\t${GENDEBUGSTRS[ix]} \\\n\t\t${DERIVED_SRC} \\\n\t\t${ERRORSTRINGS[ix]} \\\n\t\t${BUILT_PRODUCTS_DIR}/SecurityPieces/Headers/Security/Authorization.h \\\n\t\t${BUILT_PRODUCTS_DIR}/SecurityPieces/Headers/Security/AuthSession.h \\\n\t\t${BUILT_PRODUCTS_DIR}/SecurityPieces/Headers/Security/SecureTransport.h \\\n\t\t${BUILT_PRODUCTS_DIR}/SecurityPieces/Headers/Security/SecBase.h \\\n\t\t${BUILT_PRODUCTS_DIR}/SecurityPieces/Headers/Security/cssmerr.h \\\n\t\t${BUILT_PRODUCTS_DIR}/SecurityPieces/Headers/Security/cssmapple.h \\\n\t\t${BUILT_PRODUCTS_DIR}/SecurityPieces/Headers/Security/CSCommon.h \\\n\t\t${BUILT_PRODUCTS_DIR}/SecurityPieces/PrivateHeaders/Security/AuthorizationPriv.h \\\n\t\t${BUILT_PRODUCTS_DIR}/SecurityPieces/PrivateHeaders/Security/MacOSErrorStrings.h \\\n\t\t${BUILT_PRODUCTS_DIR}/SecurityPieces/PrivateHeaders/Security/SecureTransportPriv.h\ndone\n"; + shellScript = "DERIVED_SRC=${BUILT_PRODUCTS_DIR}/derived_src\nmkdir -p ${DERIVED_SRC}\n\nEXPORTS=${PROJECT_DIR}/lib/security.exp\nEXPORTS_DST=${DERIVED_SRC}/security.exp\nsort -u ${EXPORTS} | grep -v '^#' | grep -v '^$' > ${EXPORTS_DST}\n\nTARGET=${DERIVED_SRC}/security_exports.s\n\nsed 's/^/.reference /' < ${EXPORTS_DST} > ${TARGET}\n"; + showEnvVarsInLog = 0; }; - C2A118A30B863B7500F60A3D /* ShellScript */ = { + 18500F961470828E006F9AB4 /* Run Script Generate Strings */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); + name = "Run Script Generate Strings"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "ditto -v ${TARGET_BUILD_DIR}/${FULL_PRODUCT_NAME} ${BUILT_PRODUCTS_DIR}/Security.framework/PlugIns/${FULL_PRODUCT_NAME}\nexit 0"; + 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; }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ - 0867D69FFE84028FC02AAC07 /* Sources */ = { + 18073846146D0D4E00F05C24 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 182BB5A8146FE6D4000BF1F3 /* security_exports.s in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 18270ED214CF282600B05E7F /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 4C2495B305811D3200DDE4A6 /* security_exports.s in Sources */, + 18270F4114CF465700B05E7F /* client.c in Sources */, + 18270EF414CF334A00B05E7F /* securityd_rep.defs in Sources */, + 18270EF514CF334A00B05E7F /* securityd_req.defs in Sources */, + 18270EF614CF334A00B05E7F /* server.c in Sources */, + 18270F3C14CF44C400B05E7F /* debugging.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; - C224636E0B86212100626F1B /* Sources */ = { + 182BB564146F4DCA000BF1F3 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - C27262F60B8624BE00D889AF /* csparser.cpp in Sources */, + 182BB57F146F51A5000BF1F3 /* csparser.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ - 4C68458305814C85003AC7B2 /* PBXTargetDependency */ = { + 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; - target = 4C60A0A605811A4300C8A016 /* copy pieces */; - targetProxy = 4C68458205814C85003AC7B2 /* PBXContainerItemProxy */; + name = sec; + targetProxy = 18AD56A514CDED59008233F2 /* PBXContainerItemProxy */; }; - 4CAF730405363B1200D9DA7C /* PBXTargetDependency */ = { + 18B9655C1472F83C005A4D2E /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = 4C216213053639A600CCA0BB /* generate */; - targetProxy = 4CAF730305363B1200D9DA7C /* PBXContainerItemProxy */; + name = world; + targetProxy = 18B9655B1472F83C005A4D2E /* PBXContainerItemProxy */; }; - C224637D0B86214100626F1B /* PBXTargetDependency */ = { + 18FE688F1471A4C900A2CBE3 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = 0867D69CFE84028FC02AAC07 /* Security */; - targetProxy = C224637C0B86214100626F1B /* PBXContainerItemProxy */; + target = 18FE67E91471A3AA00A2CBE3 /* copyHeaders */; + targetProxy = 18FE688E1471A4C900A2CBE3 /* PBXContainerItemProxy */; }; - C224637F0B86214600626F1B /* PBXTargetDependency */ = { + 529FF2201523BD7F0029D842 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = C22463700B86212100626F1B /* csparser */; - targetProxy = C224637E0B86214600626F1B /* PBXContainerItemProxy */; + name = XPCTimeStampingService; + targetProxy = 529FF21F1523BD7F0029D842 /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ /* Begin PBXVariantGroup section */ - 089C1666FE841158C02AAC07 /* InfoPlist.strings */ = { + 18500F9F14708F19006F9AB4 /* SecErrorMessages.strings */ = { isa = PBXVariantGroup; children = ( - 089C1667FE841158C02AAC07 /* English */, + 18500FA014708F19006F9AB4 /* en */, ); - name = InfoPlist.strings; - sourceTree = ""; + name = SecErrorMessages.strings; + path = ../../Security; + sourceTree = BUILT_PRODUCTS_DIR; }; - 44DAD0F211CAB4F8007A9244 /* FDELocalizable.strings */ = { + 188AD8D81471FE3D0081C619 /* FDELocalizable.strings */ = { isa = PBXVariantGroup; children = ( - 44DAD0F311CAB4F8007A9244 /* English */, + 188AD8D91471FE3D0081C619 /* en */, ); name = FDELocalizable.strings; sourceTree = ""; }; - C21204A4056D89280018F475 /* SecErrorMessages.strings */ = { + 188AD8DA1471FE3D0081C619 /* InfoPlist.strings */ = { isa = PBXVariantGroup; children = ( - C21204A2056D891E0018F475 /* English */, + 188AD8DB1471FE3E0081C619 /* en */, ); - name = SecErrorMessages.strings; + name = InfoPlist.strings; sourceTree = ""; }; /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ - C22463740B86212200626F1B /* Development */ = { + 18073873146D0D4E00F05C24 /* Debug */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 18BBC6801471EF1600F2B224 /* security.xcconfig */; buildSettings = { - COPY_PHASE_STRIP = NO; - EXPORTED_SYMBOLS_FILE = "$(SRCROOT)/plugins/csparser.exp"; - FRAMEWORK_SEARCH_PATHS = ( - /usr/local/SecurityPieces/Components/Security, - /usr/local/SecurityPieces/Frameworks, - ); - GCC_DYNAMIC_NO_PIC = NO; - GCC_MODEL_TUNING = G5; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PRECOMPILE_PREFIX_HEADER = YES; - INFOPLIST_FILE = "plugins/csparser-Info.plist"; - INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Frameworks/Security.framework/PlugIns"; - OTHER_LDFLAGS = ( - "-framework", - CoreFoundation, - "-lantlr2c++", - ); - OTHER_LDFLAGS_debug = "-framework security_codesigning,_debug -framework security_cdsa_utilities,_debug -framework security_utilities,_debug"; - OTHER_LDFLAGS_normal = "-framework security_codesigning -framework security_cdsa_utilities -framework security_utilities"; - OTHER_LDFLAGS_profile = "-framework security_codesigning,_profile -framework security_cdsa_utilities,_profile -framework security_utilities,_profile"; - PRODUCT_NAME = csparser; - WRAPPER_EXTENSION = bundle; - ZERO_LINK = YES; }; - name = Development; + name = Debug; }; - C22463750B86212200626F1B /* Deployment */ = { + 18073874146D0D4E00F05C24 /* Release */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 18BBC6801471EF1600F2B224 /* security.xcconfig */; buildSettings = { - COPY_PHASE_STRIP = YES; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - EXPORTED_SYMBOLS_FILE = "$(SRCROOT)/plugins/csparser.exp"; - FRAMEWORK_SEARCH_PATHS = ( - /usr/local/SecurityPieces/Components/Security, - /usr/local/SecurityPieces/Frameworks, - ); - GCC_MODEL_TUNING = G5; - GCC_PRECOMPILE_PREFIX_HEADER = YES; - INFOPLIST_FILE = "plugins/csparser-Info.plist"; - INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Frameworks/Security.framework/PlugIns"; - OTHER_LDFLAGS = ( - "-framework", - CoreFoundation, - "-lantlr2c++", - ); - OTHER_LDFLAGS_debug = "-framework security_codesigning,_debug -framework security_cdsa_utilities,_debug -framework security_utilities,_debug"; - OTHER_LDFLAGS_normal = "-framework security_codesigning -framework security_cdsa_utilities -framework security_utilities"; - OTHER_LDFLAGS_profile = "-framework security_codesigning,_profile -framework security_cdsa_utilities,_profile -framework security_utilities,_profile"; - PRODUCT_NAME = csparser; - WRAPPER_EXTENSION = bundle; - ZERO_LINK = NO; }; - name = Deployment; + name = Release; }; - C22463760B86212200626F1B /* Darwin */ = { + 18073876146D0D4E00F05C24 /* Debug */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 181EA423146D4A2A00A6D320 /* debug.xcconfig */; buildSettings = { - EXPORTED_SYMBOLS_FILE = "$(SRCROOT)/plugins/csparser.exp"; - FRAMEWORK_SEARCH_PATHS = ( - /usr/local/SecurityPieces/Components/Security, - /usr/local/SecurityPieces/Frameworks, - ); - GCC_MODEL_TUNING = G5; - GCC_PRECOMPILE_PREFIX_HEADER = YES; - INFOPLIST_FILE = "plugins/csparser-Info.plist"; - INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Frameworks/Security.framework/PlugIns"; - OTHER_LDFLAGS = ( - "-framework", - CoreFoundation, - "-lantlr2c++", + EXPORTED_SYMBOLS_FILE = lib/security.exp; + INFOPLIST_FILE = "lib/Info-Security.plist"; + INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Frameworks"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + /usr/lib/system, ); - OTHER_LDFLAGS_debug = "-framework security_codesigning,_debug -framework security_cdsa_utilities,_debug -framework security_utilities,_debug"; - OTHER_LDFLAGS_normal = "-framework security_codesigning -framework security_cdsa_utilities -framework security_utilities"; - OTHER_LDFLAGS_profile = "-framework security_codesigning,_profile -framework security_cdsa_utilities,_profile -framework security_utilities,_profile"; - PRODUCT_NAME = csparser; - WRAPPER_EXTENSION = bundle; - ZERO_LINK = YES; }; - name = Darwin; + name = Debug; }; - C22463770B86212200626F1B /* normal with debug */ = { + 18073877146D0D4E00F05C24 /* Release */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 181EA425146D4A2A00A6D320 /* release.xcconfig */; buildSettings = { - EXPORTED_SYMBOLS_FILE = "$(SRCROOT)/plugins/csparser.exp"; - FRAMEWORK_SEARCH_PATHS = ( - /usr/local/SecurityPieces/Components/Security, - /usr/local/SecurityPieces/Frameworks, - ); - GCC_MODEL_TUNING = G5; - GCC_PRECOMPILE_PREFIX_HEADER = YES; - INFOPLIST_FILE = "plugins/csparser-Info.plist"; - INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Frameworks/Security.framework/PlugIns"; - OTHER_LDFLAGS = ( - "-framework", - CoreFoundation, - "-lantlr2c++", + EXPORTED_SYMBOLS_FILE = lib/security.exp; + INFOPLIST_FILE = "lib/Info-Security.plist"; + INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Frameworks"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + /usr/lib/system, ); - OTHER_LDFLAGS_debug = "-framework security_codesigning,_debug -framework security_cdsa_utilities,_debug -framework security_utilities,_debug"; - OTHER_LDFLAGS_normal = "-framework security_codesigning -framework security_cdsa_utilities -framework security_utilities"; - OTHER_LDFLAGS_profile = "-framework security_codesigning,_profile -framework security_cdsa_utilities,_profile -framework security_utilities,_profile"; - PRODUCT_NAME = csparser; - WRAPPER_EXTENSION = bundle; - ZERO_LINK = YES; + ORDER_FILE = lib/Security.order; + SECTORDER_FLAGS = "-order_file_statistics"; }; - name = "normal with debug"; + name = Release; }; - C22463780B86212200626F1B /* Default */ = { + 18270EDE14CF282600B05E7F /* Debug */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 181EA423146D4A2A00A6D320 /* debug.xcconfig */; buildSettings = { - EXPORTED_SYMBOLS_FILE = "$(SRCROOT)/plugins/csparser.exp"; - FRAMEWORK_SEARCH_PATHS = ( - /usr/local/SecurityPieces/Components/Security, - /usr/local/SecurityPieces/Frameworks, + GCC_PREPROCESSOR_DEFINITIONS = ( + "SECITEM_SHIM_OSX=1", + "$(inherited)", ); - GCC_MODEL_TUNING = G5; - GCC_PRECOMPILE_PREFIX_HEADER = YES; - INFOPLIST_FILE = "plugins/csparser-Info.plist"; - INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Frameworks/Security.framework/PlugIns"; - OTHER_LDFLAGS = ( - "-framework", - CoreFoundation, - "-lantlr2c++", + HEADER_SEARCH_PATHS = ( + "$(PROJECT_DIR)/sec", + "$(PROJECT_DIR)/sec/securityd", + "$(PROJECT_DIR)/sec/ipc", + "$(PROJECT_DIR)", + "$(PROJECT_DIR)/../ios/asn1", + "$(PROJECT_DIR)/../libsecurity_keychain/libDER", + "$(SYSTEM_LIBRARY_DIR)/Frameworks/CoreServices.framework/Frameworks/CarbonCore.framework/Headers", + "$(inherited)", ); - OTHER_LDFLAGS_debug = "-framework security_codesigning,_debug -framework security_cdsa_utilities,_debug -framework security_utilities,_debug"; - OTHER_LDFLAGS_normal = "-framework security_codesigning -framework security_cdsa_utilities -framework security_utilities"; - OTHER_LDFLAGS_profile = "-framework security_codesigning,_profile -framework security_cdsa_utilities,_profile -framework security_utilities,_profile"; - PRODUCT_NAME = csparser; - WRAPPER_EXTENSION = bundle; - ZERO_LINK = YES; - }; - name = Default; - }; - C22463810B86216400626F1B /* Development */ = { - isa = XCBuildConfiguration; - buildSettings = { - COPY_PHASE_STRIP = NO; - GCC_DYNAMIC_NO_PIC = NO; - GCC_OPTIMIZATION_LEVEL = 0; - PRODUCT_NAME = World; - }; - name = Development; - }; - C22463820B86216400626F1B /* Deployment */ = { - isa = XCBuildConfiguration; - buildSettings = { - COPY_PHASE_STRIP = YES; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - PRODUCT_NAME = World; - ZERO_LINK = NO; - }; - name = Deployment; - }; - C22463830B86216400626F1B /* Darwin */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = World; - }; - name = Darwin; - }; - C22463840B86216400626F1B /* normal with debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = World; - }; - name = "normal with debug"; - }; - C22463850B86216400626F1B /* Default */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = World; - }; - name = Default; - }; - C23B0C7409A2987F00B7FCED /* Development */ = { - isa = XCBuildConfiguration; - buildSettings = { - BUILD_VARIANTS = debug; - PRODUCT_NAME = "copy pieces"; - SECTORDER_FLAGS = ""; - WARNING_LDFLAGS = ""; - }; - name = Development; - }; - C23B0C7509A2987F00B7FCED /* Deployment */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "copy pieces"; - ZERO_LINK = NO; - }; - name = Deployment; - }; - C23B0C7609A2987F00B7FCED /* Darwin */ = { - isa = XCBuildConfiguration; - buildSettings = { - OTHER_LDFLAGS = ""; - PRODUCT_NAME = "copy pieces"; - }; - name = Darwin; - }; - C23B0C7709A2987F00B7FCED /* normal with debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - BUILD_VARIANTS = normal; - COPY_PHASE_STRIP = NO; - CSSM_HEADERS = "$(BUILT_PRODUCTS_DIR)/SecurityPieces/Headers/Security"; - GCC_OPTIMIZATION_LEVEL = 0; - OPT_LDFLAGS = ""; - OPT_LDXFLAGS = ""; - OPT_LDXNOPIC = ""; - OTHER_ASFLAGS_normal = "$(OTHER_CFLAGS)"; - OTHER_CFLAGS_normal = "$(OTHER_CFLAGS) -O0 -fno-inline"; - OTHER_CPLUSPLUSFLAGS_normal = "$(OTHER_CFLAGS) -O0 -fno-inline"; - PRODUCT_NAME = "copy pieces"; - SECTORDER_FLAGS = ""; - }; - name = "normal with debug"; - }; - C23B0C7809A2987F00B7FCED /* Default */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "copy pieces"; + INSTALL_PATH = /usr/libexec; + USE_HEADERMAP = NO; }; - name = Default; + name = Debug; }; - C23B0C7A09A2987F00B7FCED /* Development */ = { + 18270EDF14CF282600B05E7F /* Release */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 181EA425146D4A2A00A6D320 /* release.xcconfig */; buildSettings = { - BUILD_VARIANTS = debug; - EXECUTABLE_PREFIX = ""; - EXECUTABLE_SUFFIX = ""; - FRAMEWORK_SEARCH_PATHS = ( - /usr/local/SecurityPieces/Components/Security, - /usr/local/SecurityPieces/Frameworks, + GCC_PREPROCESSOR_DEFINITIONS = ( + "SECITEM_SHIM_OSX=1", + "$(inherited)", ); HEADER_SEARCH_PATHS = ( - "$(BUILT_PRODUCTS_DIR)/SecurityPieces/Headers", - "$(BUILT_PRODUCTS_DIR)/SecurityPieces/PrivateHeaders", - /usr/local/SecurityPieces/Headers, - /usr/local/SecurityPieces/PrivateHeaders, + "$(PROJECT_DIR)/sec", + "$(PROJECT_DIR)/sec/securityd", + "$(PROJECT_DIR)/sec/ipc", + "$(PROJECT_DIR)", + "$(PROJECT_DIR)/../ios/asn1", + "$(PROJECT_DIR)/../libsecurity_keychain/libDER", + "$(SYSTEM_LIBRARY_DIR)/Frameworks/CoreServices.framework/Frameworks/CarbonCore.framework/Headers", + "$(inherited)", ); - PRODUCT_NAME = generate; - SECTORDER_FLAGS = ""; - WARNING_LDFLAGS = ""; + INSTALL_PATH = /usr/libexec; + USE_HEADERMAP = NO; }; - name = Development; + name = Release; }; - C23B0C7B09A2987F00B7FCED /* Deployment */ = { + 182BB573146F4DCB000BF1F3 /* Debug */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 181EA423146D4A2A00A6D320 /* debug.xcconfig */; buildSettings = { - EXECUTABLE_PREFIX = ""; - EXECUTABLE_SUFFIX = ""; - FRAMEWORK_SEARCH_PATHS = ( - /usr/local/SecurityPieces/Components/Security, - /usr/local/SecurityPieces/Frameworks, - ); - HEADER_SEARCH_PATHS = ( - "$(BUILT_PRODUCTS_DIR)/SecurityPieces/Headers", - "$(BUILT_PRODUCTS_DIR)/SecurityPieces/PrivateHeaders", - /usr/local/SecurityPieces/Headers, - /usr/local/SecurityPieces/PrivateHeaders, - ); - PRODUCT_NAME = generate; - ZERO_LINK = NO; + 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/PlugIns"; + WRAPPER_EXTENSION = bundle; }; - name = Deployment; + name = Debug; }; - C23B0C7C09A2987F00B7FCED /* Darwin */ = { + 182BB574146F4DCB000BF1F3 /* Release */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 181EA425146D4A2A00A6D320 /* release.xcconfig */; buildSettings = { - EXECUTABLE_PREFIX = ""; - EXECUTABLE_SUFFIX = ""; - FRAMEWORK_SEARCH_PATHS = ( - /usr/local/SecurityPieces/Components/Security, - /usr/local/SecurityPieces/Frameworks, - ); - HEADER_SEARCH_PATHS = ( - "$(BUILT_PRODUCTS_DIR)/SecurityPieces/Headers", - "$(BUILT_PRODUCTS_DIR)/SecurityPieces/PrivateHeaders", - /usr/local/SecurityPieces/Headers, - /usr/local/SecurityPieces/PrivateHeaders, - ); - OTHER_LDFLAGS = ""; - PRODUCT_NAME = generate; + 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/PlugIns"; + WRAPPER_EXTENSION = bundle; }; - name = Darwin; + name = Release; }; - C23B0C7D09A2987F00B7FCED /* normal with debug */ = { + 182BB59A146FE295000BF1F3 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - BUILD_VARIANTS = normal; - COPY_PHASE_STRIP = NO; - CSSM_HEADERS = "$(BUILT_PRODUCTS_DIR)/SecurityPieces/Headers/Security"; - EXECUTABLE_PREFIX = ""; - EXECUTABLE_SUFFIX = ""; - FRAMEWORK_SEARCH_PATHS = ( - /usr/local/SecurityPieces/Components/Security, - /usr/local/SecurityPieces/Frameworks, - ); - GCC_OPTIMIZATION_LEVEL = 0; - HEADER_SEARCH_PATHS = ( - "$(BUILT_PRODUCTS_DIR)/SecurityPieces/Headers", - "$(BUILT_PRODUCTS_DIR)/SecurityPieces/PrivateHeaders", - /usr/local/SecurityPieces/Headers, - /usr/local/SecurityPieces/PrivateHeaders, - ); - OPT_LDFLAGS = ""; - OPT_LDXFLAGS = ""; - OPT_LDXNOPIC = ""; - OTHER_ASFLAGS_normal = "$(OTHER_CFLAGS)"; - OTHER_CFLAGS_normal = "$(OTHER_CFLAGS) -O0 -fno-inline"; - OTHER_CPLUSPLUSFLAGS_normal = "$(OTHER_CFLAGS) -O0 -fno-inline"; - PRODUCT_NAME = generate; - SECTORDER_FLAGS = ""; + PRODUCT_NAME = "$(TARGET_NAME)"; }; - name = "normal with debug"; + name = Debug; }; - C23B0C7E09A2987F00B7FCED /* Default */ = { + 182BB59B146FE295000BF1F3 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - EXECUTABLE_PREFIX = ""; - EXECUTABLE_SUFFIX = ""; - FRAMEWORK_SEARCH_PATHS = ( - /usr/local/SecurityPieces/Components/Security, - /usr/local/SecurityPieces/Frameworks, - ); - HEADER_SEARCH_PATHS = ( - "$(BUILT_PRODUCTS_DIR)/SecurityPieces/Headers", - "$(BUILT_PRODUCTS_DIR)/SecurityPieces/PrivateHeaders", - /usr/local/SecurityPieces/Headers, - /usr/local/SecurityPieces/PrivateHeaders, - ); - PRODUCT_NAME = generate; + PRODUCT_NAME = "$(TARGET_NAME)"; }; - name = Default; + name = Release; }; - C23B0C8009A2987F00B7FCED /* Development */ = { + 186F778A14E59FB200434E1F /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - BUILD_VARIANTS = debug; - CURRENT_PROJECT_VERSION = 55148.6; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 55148.6; - EXECUTABLE_PREFIX = ""; - EXECUTABLE_SUFFIX = ""; - EXPORTED_SYMBOLS_FILE = "${BUILT_PRODUCTS_DIR}/derived_src/Security.exp"; - FRAMEWORK_SEARCH_PATHS = ( - /usr/local/SecurityPieces/Components/Security, - /usr/local/SecurityPieces/Frameworks, - "\"$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks\"", - ); - FRAMEWORK_VERSION = A; - GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO; - INFOPLIST_FILE = "Info-Security.plist"; - INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Frameworks"; - LD = "$(DEVELOPER_BIN_DIR)/g++"; - LIBRARY_SEARCH_PATHS = ""; - OPT_LDFLAGS = "-dead_strip"; - 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 = ( - "-framework", - security_comcryption, - "-L/usr/local/lib", - "-lantlr2c++", - "-lz", - "-lauto", - "-lobjc", - ); - OTHER_LDFLAGS_debug = "-framework security_codesigning,_debug -framework security_ssl,_debug -framework security_keychain,_debug -framework security_cssm,_debug -framework security_mds,_debug -framework security_apple_x509_tp,_debug -framework security_apple_x509_cl,_debug -framework security_apple_file_dl,_debug -framework security_apple_cspdl,_debug -framework security_apple_csp,_debug -framework security_sd_cspdl,_debug -framework security_filedb,_debug -framework security_cdsa_plugin,_debug -framework security_cdsa_client,_debug -framework security_authorization,_debug -framework securityd_client,_debug -framework security_cdsa_utilities,_debug -framework security_utilities,_debug -framework security_checkpw,_debug -framework security_authorization,_debug -framework security_pkcs12,_debug -framework security_smime,_debug -framework security_manifest,_debug -framework security_asn1,_debug -framework security_cdsa_utils,_debug -framework security_ocspd,_debug -framework security_cms,_debug -framework security_cryptkit,_debug -lstdc++ -framework CoreFoundation $(OTHER_LDFLAGS)"; - OTHER_LDFLAGS_nopic = "$(OPT_LDFLAGS) -framework security_codesigning -framework security_ssl -framework security_keychain -framework security_cssm -framework security_mds -framework security_apple_x509_tp -framework security_apple_x509_cl -framework security_apple_file_dl -framework security_apple_cspdl -framework security_apple_csp -framework security_sd_cspdl -framework security_filedb -framework security_cdsa_plugin -framework security_cdsa_client -framework security_authorization -framework securityd_client -framework security_cdsa_utilities -framework security_utilities -framework security_checkpw -framework security_authorization -framework security_pkcs12 -framework security_smime -framework security_manifest -framework security_asn1 -framework security_cdsa_utils -framework security_ocspd -framework security_cms -framework security_cryptkit -lstdc++ -framework CoreFoundation $(OTHER_LDFLAGS)"; - OTHER_LDFLAGS_normal = "$(OPT_LDFLAGS) -framework security_codesigning -framework security_ssl -framework security_keychain -framework security_cssm -framework security_mds -framework security_apple_x509_tp -framework security_apple_x509_cl -framework security_apple_file_dl -framework security_apple_cspdl -framework security_apple_csp -framework security_sd_cspdl -framework security_filedb -framework security_cdsa_plugin -framework security_cdsa_client -framework security_authorization -framework securityd_client -framework security_cdsa_utilities -framework security_utilities -framework security_checkpw -framework security_authorization -framework security_pkcs12 -framework security_smime -framework security_manifest -framework security_asn1 -framework security_cdsa_utils -framework security_ocspd -framework security_cms -framework security_cryptkit -lstdc++ -framework CoreFoundation $(OTHER_LDFLAGS)"; - OTHER_LDFLAGS_profile = "$(OPT_LDFLAGS) -pg -framework security_codesigning,_profile -framework security_ssl,_profile -framework security_keychain,_profile -framework security_cssm,_profile -framework security_mds,_profile -framework security_apple_x509_tp,_profile -framework security_apple_x509_cl,_profile -framework security_apple_file_dl,_profile -framework security_apple_cspdl,_profile -framework security_apple_csp,_profile -framework security_sd_cspdl,_profile -framework security_filedb,_profile -framework security_cdsa_plugin,_profile -framework security_cdsa_client,_profile -framework security_authorization,_profile -framework securityd_client,_profile -framework security_cdsa_utilities,_profile -framework security_utilities,_profile -framework security_checkpw,_profile -framework security_authorization,_profile -framework security_pkcs12,_profile -framework security_smime,_profile -framework security_manifest,_profile -framework security_asn1,_profile -framework security_cdsa_utils,_profile -framework security_ocspd,_profile -framework security_cms,_profile -framework security_cryptkit -lstdc++ -framework CoreFoundation $(OTHER_LDFLAGS)"; - PRODUCT_NAME = Security; - SECTORDER_FLAGS = ""; - STRIPFLAGS_FOR_GM = "-x"; - VERSIONING_SYSTEM = "apple-generic"; - WARNING_CFLAGS = ( - "-Wmost", - "-Wno-four-char-constants", - "-Wno-unknown-pragmas", - ); - WARNING_LDFLAGS = ""; - WRAPPER_EXTENSION = framework; + PRODUCT_NAME = "$(TARGET_NAME)"; }; - name = Development; + name = Debug; }; - C23B0C8109A2987F00B7FCED /* Deployment */ = { + 186F778B14E59FB200434E1F /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - BUILD_VARIANTS = ( - normal, - debug, - ); - CURRENT_PROJECT_VERSION = 55148.6; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 55148.6; - EXECUTABLE_PREFIX = ""; - EXECUTABLE_SUFFIX = ""; - EXPORTED_SYMBOLS_FILE = "${BUILT_PRODUCTS_DIR}/derived_src/Security.exp"; - FRAMEWORK_SEARCH_PATHS = ( - /usr/local/SecurityPieces/Components/Security, - /usr/local/SecurityPieces/Frameworks, - "\"$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks\"", - ); - FRAMEWORK_VERSION = A; - GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO; - INFOPLIST_FILE = "Info-Security.plist"; - INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Frameworks"; - LD = "$(DEVELOPER_BIN_DIR)/g++"; - LIBRARY_SEARCH_PATHS = ""; - OPT_LDFLAGS = "-dead_strip"; - ORDER_FILE = "$(SRCROOT)/lib/Security.order"; - 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 = ( - "-framework", - security_comcryption, - "-L/usr/local/lib", - "-lantlr2c++", - "-lz", - "-lauto", - "-lobjc", - ); - OTHER_LDFLAGS_debug = "-framework security_codesigning,_debug -framework security_ssl,_debug -framework security_keychain,_debug -framework security_cssm,_debug -framework security_mds,_debug -framework security_apple_x509_tp,_debug -framework security_apple_x509_cl,_debug -framework security_apple_file_dl,_debug -framework security_apple_cspdl,_debug -framework security_apple_csp,_debug -framework security_sd_cspdl,_debug -framework security_filedb,_debug -framework security_cdsa_plugin,_debug -framework security_cdsa_client,_debug -framework security_authorization,_debug -framework securityd_client,_debug -framework security_cdsa_utilities,_debug -framework security_utilities,_debug -framework security_checkpw,_debug -framework security_authorization,_debug -framework security_pkcs12,_debug -framework security_smime,_debug -framework security_manifest,_debug -framework security_asn1,_debug -framework security_cdsa_utils,_debug -framework security_ocspd,_debug -framework security_cms,_debug -framework security_cryptkit,_debug -lstdc++ -framework CoreFoundation $(OTHER_LDFLAGS)"; - OTHER_LDFLAGS_nopic = "$(OPT_LDFLAGS) -framework security_codesigning -framework security_ssl -framework security_keychain -framework security_cssm -framework security_mds -framework security_apple_x509_tp -framework security_apple_x509_cl -framework security_apple_file_dl -framework security_apple_cspdl -framework security_apple_csp -framework security_sd_cspdl -framework security_filedb -framework security_cdsa_plugin -framework security_cdsa_client -framework security_authorization -framework securityd_client -framework security_cdsa_utilities -framework security_utilities -framework security_checkpw -framework security_authorization -framework security_pkcs12 -framework security_smime -framework security_manifest -framework security_asn1 -framework security_cdsa_utils -framework security_ocspd -framework security_cms -framework security_cryptkit -lstdc++ -framework CoreFoundation $(OTHER_LDFLAGS)"; - OTHER_LDFLAGS_normal = "$(OPT_LDFLAGS) -framework security_codesigning -framework security_ssl -framework security_keychain -framework security_cssm -framework security_mds -framework security_apple_x509_tp -framework security_apple_x509_cl -framework security_apple_file_dl -framework security_apple_cspdl -framework security_apple_csp -framework security_sd_cspdl -framework security_filedb -framework security_cdsa_plugin -framework security_cdsa_client -framework security_authorization -framework securityd_client -framework security_cdsa_utilities -framework security_utilities -framework security_checkpw -framework security_authorization -framework security_pkcs12 -framework security_smime -framework security_manifest -framework security_asn1 -framework security_cdsa_utils -framework security_ocspd -framework security_cms -framework security_cryptkit -lstdc++ -framework CoreFoundation $(OTHER_LDFLAGS)"; - OTHER_LDFLAGS_profile = "$(OPT_LDFLAGS) -pg -framework security_codesigning,_profile-lstdc++ -framework security_ssl,_profile -framework security_keychain,_profile -framework security_cssm,_profile -framework security_mds,_profile -framework security_apple_x509_tp,_profile -framework security_apple_x509_cl,_profile -framework security_apple_file_dl,_profile -framework security_apple_cspdl,_profile -framework security_apple_csp,_profile -framework security_sd_cspdl,_profile -framework security_filedb,_profile -framework security_cdsa_plugin,_profile -framework security_cdsa_client,_profile -framework security_authorization,_profile -framework securityd_client,_profile -framework security_cdsa_utilities,_profile -framework security_utilities,_profile -framework security_checkpw,_profile -framework security_authorization,_profile -framework security_pkcs12,_profile -framework security_smime,_profile -framework security_manifest,_profile -framework security_asn1,_profile -framework security_cdsa_utils,_profile -framework security_ocspd,_profile -framework security_cms,_profile -framework security_cryptkit -framework CoreFoundation $(OTHER_LDFLAGS)"; - PRODUCT_NAME = Security; - SECTORDER_FLAGS = "-order_file_statistics"; - STRIPFLAGS_FOR_GM = "-x"; - VERSIONING_SYSTEM = "apple-generic"; - WARNING_CFLAGS = ( - "-Wmost", - "-Wno-four-char-constants", - "-Wno-unknown-pragmas", - ); - WRAPPER_EXTENSION = framework; - ZERO_LINK = NO; + PRODUCT_NAME = "$(TARGET_NAME)"; }; - name = Deployment; + name = Release; }; - C23B0C8209A2987F00B7FCED /* Darwin */ = { + 186F778E14E59FDA00434E1F /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - BUILD_VARIANTS = normal; - CURRENT_PROJECT_VERSION = 55148.6; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 55148.6; - EXECUTABLE_PREFIX = ""; - EXECUTABLE_SUFFIX = ""; - EXPORTED_SYMBOLS_FILE = "${BUILT_PRODUCTS_DIR}/derived_src/Security.exp"; - FRAMEWORK_SEARCH_PATHS = ( - /usr/local/SecurityPieces/Components/Security, - /usr/local/SecurityPieces/Frameworks, - "\"$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks\"", - ); - FRAMEWORK_VERSION = A; - GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO; - INFOPLIST_FILE = "Info-Security.plist"; - INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Frameworks"; - LD = "$(DEVELOPER_BIN_DIR)/g++"; - LIBRARY_SEARCH_PATHS = ""; - OPT_LDFLAGS = "-dead_strip"; - ORDER_FILE = "$(SRCROOT)/lib/Security.order"; - 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 = ""; - OTHER_LDFLAGS_debug = "-framework security_codesigning,_debug -framework security_ssl,_debug -framework security_keychain,_debug -framework security_cssm,_debug -framework security_mds,_debug -framework security_apple_x509_tp,_debug -framework security_apple_x509_cl,_debug -framework security_apple_file_dl,_debug -framework security_apple_cspdl,_debug -framework security_apple_csp,_debug -framework security_sd_cspdl,_debug -framework security_filedb,_debug -framework security_cdsa_plugin,_debug -framework security_cdsa_client,_debug -framework security_authorization,_debug -framework securityd_client,_debug -framework security_cdsa_utilities,_debug -framework security_utilities,_debug -framework security_checkpw,_debug -framework security_authorization,_debug -framework security_pkcs12,_debug -framework security_smime,_debug -framework security_manifest,_debug -framework security_asn1,_debug -framework security_cdsa_utils,_debug -framework security_ocspd,_debug -framework security_cms,_debug -lstdc++ -framework CoreFoundation $(OTHER_LDFLAGS)"; - OTHER_LDFLAGS_nopic = "$(OPT_LDFLAGS) -framework security_codesigning -framework security_ssl -framework security_keychain -framework security_cssm -framework security_mds -framework security_apple_x509_tp -framework security_apple_x509_cl -framework security_apple_file_dl -framework security_apple_cspdl -framework security_apple_csp -framework security_sd_cspdl -framework security_filedb -framework security_cdsa_plugin -framework security_cdsa_client -framework security_authorization -framework securityd_client -framework security_cdsa_utilities -framework security_utilities -framework security_checkpw -framework security_authorization -framework security_pkcs12 -framework security_smime -framework security_manifest -framework security_asn1 -framework security_cdsa_utils -framework security_ocspd -framework security_cms -lstdc++ -framework CoreFoundation $(OTHER_LDFLAGS)"; - OTHER_LDFLAGS_normal = "$(OPT_LDFLAGS) -framework security_codesigning -framework security_ssl -framework security_keychain -framework security_cssm -framework security_mds -framework security_apple_x509_tp -framework security_apple_x509_cl -framework security_apple_file_dl -framework security_apple_cspdl -framework security_apple_csp -framework security_sd_cspdl -framework security_filedb -framework security_cdsa_plugin -framework security_cdsa_client -framework security_authorization -framework securityd_client -framework security_cdsa_utilities -framework security_utilities -framework security_checkpw -framework security_authorization -framework security_pkcs12 -framework security_smime -framework security_manifest -framework security_asn1 -framework security_cdsa_utils -framework security_ocspd -framework security_cms -lstdc++ -framework CoreFoundation $(OTHER_LDFLAGS)"; - OTHER_LDFLAGS_profile = "$(OPT_LDFLAGS) -pg -framework security_codesigning,_profile -framework security_ssl,_profile -framework security_keychain,_profile -framework security_cssm,_profile -framework security_mds,_profile -framework security_apple_x509_tp,_profile -framework security_apple_x509_cl,_profile -framework security_apple_file_dl,_profile -framework security_apple_cspdl,_profile -framework security_apple_csp,_profile -framework security_sd_cspdl,_profile -framework security_filedb,_profile -framework security_cdsa_plugin,_profile -framework security_cdsa_client,_profile -framework security_authorization,_profile -framework securityd_client,_profile -framework security_cdsa_utilities,_profile -framework security_utilities,_profile -framework security_checkpw,_profile -framework security_authorization,_profile -framework security_pkcs12,_profile -framework security_smime,_profile -framework security_manifest,_profile -framework security_asn1,_profile -framework security_cdsa_utils,_profile -framework security_ocspd,_profile -framework security_cms,_profile -lstdc++ -framework CoreFoundation $(OTHER_LDFLAGS)"; - PRODUCT_NAME = Security; - SECTORDER_FLAGS = ""; - STRIPFLAGS_FOR_GM = "-x"; - VERSIONING_SYSTEM = "apple-generic"; - WARNING_CFLAGS = ( - "-Wmost", - "-Wno-four-char-constants", - "-Wno-unknown-pragmas", - ); - WRAPPER_EXTENSION = framework; + PRODUCT_NAME = "$(TARGET_NAME)"; }; - name = Darwin; + name = Debug; }; - C23B0C8309A2987F00B7FCED /* normal with debug */ = { + 186F778F14E59FDA00434E1F /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - BUILD_VARIANTS = normal; - COPY_PHASE_STRIP = NO; - CSSM_HEADERS = "$(BUILT_PRODUCTS_DIR)/SecurityPieces/Headers/Security"; - CURRENT_PROJECT_VERSION = 55148.6; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 55148.6; - EXECUTABLE_PREFIX = ""; - EXECUTABLE_SUFFIX = ""; - EXPORTED_SYMBOLS_FILE = "${BUILT_PRODUCTS_DIR}/derived_src/Security.exp"; - FRAMEWORK_SEARCH_PATHS = ( - /usr/local/SecurityPieces/Components/Security, - /usr/local/SecurityPieces/Frameworks, - "\"$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks\"", - ); - FRAMEWORK_VERSION = A; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO; - INFOPLIST_FILE = "Info-Security.plist"; - INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Frameworks"; - LD = "$(DEVELOPER_BIN_DIR)/g++"; - LIBRARY_SEARCH_PATHS = ""; - OPT_LDFLAGS = ""; - OPT_LDXFLAGS = ""; - OPT_LDXNOPIC = ""; - OTHER_ASFLAGS_debug = "$(OTHER_CFLAGS)"; - OTHER_ASFLAGS_normal = "$(OTHER_CFLAGS)"; - OTHER_ASFLAGS_profile = "-DNDEBUG $(OTHER_CFLAGS) -pg"; - OTHER_CFLAGS_debug = "$(OTHER_CFLAGS) -O0 -fno-inline"; - OTHER_CFLAGS_normal = "$(OTHER_CFLAGS) -O0 -fno-inline"; - OTHER_CFLAGS_profile = "-DNDEBUG $(OTHER_CFLAGS) -pg"; - OTHER_CPLUSPLUSFLAGS_debug = "$(OTHER_CFLAGS) -O0 -fno-inline"; - OTHER_CPLUSPLUSFLAGS_normal = "$(OTHER_CFLAGS) -O0 -fno-inline"; - OTHER_CPLUSPLUSFLAGS_profile = "-DNDEBUG $(OTHER_CFLAGS) -pg"; - OTHER_LDFLAGS = ( - "-framework", - security_comcryption, - "-L/usr/local/lib", - "-lantlr2c++", - "-lz", - "-lauto", - "-lobjc", - ); - OTHER_LDFLAGS_debug = "-framework security_codesigning,_debug -framework security_ssl,_debug -framework security_keychain,_debug -framework security_cssm,_debug -framework security_mds,_debug -framework security_apple_x509_tp,_debug -framework security_apple_x509_cl,_debug -framework security_apple_file_dl,_debug -framework security_apple_cspdl,_debug -framework security_apple_csp,_debug -framework security_sd_cspdl,_debug -framework security_filedb,_debug -framework security_cdsa_plugin,_debug -framework security_cdsa_client,_debug -framework security_authorization,_debug -framework securityd_client,_debug -framework security_cdsa_utilities,_debug -framework security_utilities,_debug -framework security_checkpw,_debug -framework security_authorization,_debug -framework security_pkcs12,_debug -framework security_smime,_debug -framework security_manifest,_debug -framework security_asn1,_debug -framework security_cdsa_utils,_debug -framework security_ocspd,_debug -framework security_cms,_debug -framework security_cryptkit,_debug -lstdc++ -framework CoreFoundation $(OTHER_LDFLAGS)"; - OTHER_LDFLAGS_nopic = "$(OPT_LDFLAGS) -framework security_codesigning -framework security_ssl -framework security_keychain -framework security_cssm -framework security_mds -framework security_apple_x509_tp -framework security_apple_x509_cl -framework security_apple_file_dl -framework security_apple_cspdl -framework security_apple_csp -framework security_sd_cspdl -framework security_filedb -framework security_cdsa_plugin -framework security_cdsa_client -framework security_authorization -framework securityd_client -framework security_cdsa_utilities -framework security_utilities -framework security_checkpw -framework security_authorization -framework security_pkcs12 -framework security_smime -framework security_manifest -framework security_asn1 -framework security_cdsa_utils -framework security_ocspd -framework security_cms -framework security_cryptkit -lstdc++ -framework CoreFoundation $(OTHER_LDFLAGS)"; - OTHER_LDFLAGS_normal = "$(OPT_LDFLAGS) -framework security_codesigning -framework security_ssl -framework security_keychain -framework security_cssm -framework security_mds -framework security_apple_x509_tp -framework security_apple_x509_cl -framework security_apple_file_dl -framework security_apple_cspdl -framework security_apple_csp -framework security_sd_cspdl -framework security_filedb -framework security_cdsa_plugin -framework security_cdsa_client -framework security_authorization -framework securityd_client -framework security_cdsa_utilities -framework security_utilities -framework security_checkpw -framework security_authorization -framework security_pkcs12 -framework security_smime -framework security_manifest -framework security_asn1 -framework security_cdsa_utils -framework security_ocspd -framework security_cms -framework security_cryptkit -lstdc++ -framework CoreFoundation $(OTHER_LDFLAGS)"; - OTHER_LDFLAGS_profile = "$(OPT_LDFLAGS) -pg -framework security_codesigning,_profile -framework security_ssl,_profile -framework security_keychain,_profile -framework security_cssm,_profile -framework security_mds,_profile -framework security_apple_x509_tp,_profile -framework security_apple_x509_cl,_profile -framework security_apple_file_dl,_profile -framework security_apple_cspdl,_profile -framework security_apple_csp,_profile -framework security_sd_cspdl,_profile -framework security_filedb,_profile -framework security_cdsa_plugin,_profile -framework security_cdsa_client,_profile -framework security_authorization,_profile -framework securityd_client,_profile -framework security_cdsa_utilities,_profile -framework security_utilities,_profile -framework security_checkpw,_profile -framework security_authorization,_profile -framework security_pkcs12,_profile -framework security_smime,_profile -framework security_manifest,_profile -framework security_asn1,_profile -framework security_cdsa_utils,_profile -framework security_ocspd,_profile -framework security_cms,_profile -framework security_cryptkit -lstdc++ -framework CoreFoundation $(OTHER_LDFLAGS)"; - PRODUCT_NAME = Security; - SECTORDER_FLAGS = ""; - STRIPFLAGS_FOR_GM = "-x"; - VERSIONING_SYSTEM = "apple-generic"; - WARNING_CFLAGS = ( - "-Wmost", - "-Wno-four-char-constants", - "-Wno-unknown-pragmas", - ); - WRAPPER_EXTENSION = framework; + PRODUCT_NAME = "$(TARGET_NAME)"; }; - name = "normal with debug"; + name = Release; }; - C23B0C8409A2987F00B7FCED /* Default */ = { + 18FE67FC1471A3AA00A2CBE3 /* Debug */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 181EA423146D4A2A00A6D320 /* debug.xcconfig */; buildSettings = { - BUILD_VARIANTS = ( - normal, - debug, - ); - CURRENT_PROJECT_VERSION = 55148.6; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 55148.6; - EXECUTABLE_PREFIX = ""; - EXECUTABLE_SUFFIX = ""; - EXPORTED_SYMBOLS_FILE = "${BUILT_PRODUCTS_DIR}/derived_src/Security.exp"; - FRAMEWORK_SEARCH_PATHS = ( - /usr/local/SecurityPieces/Components/Security, - /usr/local/SecurityPieces/Frameworks, - "\"$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks\"", - ); - FRAMEWORK_VERSION = A; - GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO; - INFOPLIST_FILE = "Info-Security.plist"; + CODE_SIGN_IDENTITY = ""; INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Frameworks"; - LD = "$(DEVELOPER_BIN_DIR)/g++"; - LIBRARY_SEARCH_PATHS = ""; - OPT_LDFLAGS = "-dead_strip"; - ORDER_FILE = "$(SRCROOT)/lib/Security.order"; - 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 = ( - "-framework", - security_comcryption, - "-L/usr/local/lib", - "-lantlr2c++", - "-lz", - "-lauto", - "-lobjc", - ); - OTHER_LDFLAGS_debug = "-framework security_codesigning,_debug -framework security_ssl,_debug -framework security_keychain,_debug -framework security_cssm,_debug -framework security_mds,_debug -framework security_apple_x509_tp,_debug -framework security_apple_x509_cl,_debug -framework security_apple_file_dl,_debug -framework security_apple_cspdl,_debug -framework security_apple_csp,_debug -framework security_sd_cspdl,_debug -framework security_filedb,_debug -framework security_cdsa_plugin,_debug -framework security_cdsa_client,_debug -framework security_authorization,_debug -framework securityd_client,_debug -framework security_cdsa_utilities,_debug -framework security_utilities,_debug -framework security_checkpw,_debug -framework security_authorization,_debug -framework security_pkcs12,_debug -framework security_smime,_debug -framework security_manifest,_debug -framework security_asn1,_debug -framework security_cdsa_utils,_debug -framework security_ocspd,_debug -framework security_cms,_debug -framework security_cryptkit,_debug -lstdc++ -framework CoreFoundation $(OTHER_LDFLAGS)"; - OTHER_LDFLAGS_nopic = "$(OPT_LDFLAGS) -framework security_codesigning -framework security_ssl -framework security_keychain -framework security_cssm -framework security_mds -framework security_apple_x509_tp -framework security_apple_x509_cl -framework security_apple_file_dl -framework security_apple_cspdl -framework security_apple_csp -framework security_sd_cspdl -framework security_filedb -framework security_cdsa_plugin -framework security_cdsa_client -framework security_authorization -framework securityd_client -framework security_cdsa_utilities -framework security_utilities -framework security_checkpw -framework security_authorization -framework security_pkcs12 -framework security_smime -framework security_manifest -framework security_asn1 -framework security_cdsa_utils -framework security_ocspd -framework security_cms -framework security_cryptkit -lstdc++ -framework CoreFoundation $(OTHER_LDFLAGS)"; - OTHER_LDFLAGS_normal = "$(OPT_LDFLAGS) -framework security_codesigning -framework security_ssl -framework security_keychain -framework security_cssm -framework security_mds -framework security_apple_x509_tp -framework security_apple_x509_cl -framework security_apple_file_dl -framework security_apple_cspdl -framework security_apple_csp -framework security_sd_cspdl -framework security_filedb -framework security_cdsa_plugin -framework security_cdsa_client -framework security_authorization -framework securityd_client -framework security_cdsa_utilities -framework security_utilities -framework security_checkpw -framework security_authorization -framework security_pkcs12 -framework security_smime -framework security_manifest -framework security_asn1 -framework security_cdsa_utils -framework security_ocspd -framework security_cms -framework security_cryptkit -lstdc++ -framework CoreFoundation $(OTHER_LDFLAGS)"; - OTHER_LDFLAGS_profile = "$(OPT_LDFLAGS) -pg -framework security_codesigning,_profile -framework security_ssl,_profile -framework security_keychain,_profile -framework security_cssm,_profile -framework security_mds,_profile -framework security_apple_x509_tp,_profile -framework security_apple_x509_cl,_profile -framework security_apple_file_dl,_profile -framework security_apple_cspdl,_profile -framework security_apple_csp,_profile -framework security_sd_cspdl,_profile -framework security_filedb,_profile -framework security_cdsa_plugin,_profile -framework security_cdsa_client,_profile -framework security_authorization,_profile -framework securityd_client,_profile -framework security_cdsa_utilities,_profile -framework security_utilities,_profile -framework security_checkpw,_profile -framework security_authorization,_profile -framework security_pkcs12,_profile -framework security_smime,_profile -framework security_manifest,_profile -framework security_asn1,_profile -framework security_cdsa_utils,_profile -framework security_ocspd,_profile -framework security_cms,_profile -framework security_cryptkit -lstdc++ -framework CoreFoundation $(OTHER_LDFLAGS)"; PRODUCT_NAME = Security; - SECTORDER_FLAGS = "-order_file_statistics"; - STRIPFLAGS_FOR_GM = "-x"; - VERSIONING_SYSTEM = "apple-generic"; - WARNING_CFLAGS = ( - "-Wmost", - "-Wno-four-char-constants", - "-Wno-unknown-pragmas", - ); - WRAPPER_EXTENSION = framework; - }; - name = Default; - }; - C23B0C8609A2987F00B7FCED /* Development */ = { - isa = XCBuildConfiguration; - buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; - BUILD_VARIANTS = debug; - CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)"; - CONFIGURATION_TEMP_DIR = "$(PROJECT_TEMP_DIR)"; - FRAMEWORK_SEARCH_PATHS = ( - /usr/local/SecurityPieces/Components/Security, - /usr/local/SecurityPieces/Frameworks, - ); - }; - name = Development; - }; - C23B0C8709A2987F00B7FCED /* Deployment */ = { - isa = XCBuildConfiguration; - buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; - CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)"; - CONFIGURATION_TEMP_DIR = "$(PROJECT_TEMP_DIR)"; - }; - name = Deployment; - }; - C23B0C8809A2987F00B7FCED /* Darwin */ = { - isa = XCBuildConfiguration; - buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; - CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)"; - CONFIGURATION_TEMP_DIR = "$(PROJECT_TEMP_DIR)"; }; - name = Darwin; + name = Debug; }; - C23B0C8909A2987F00B7FCED /* normal with debug */ = { + 18FE67FD1471A3AA00A2CBE3 /* Release */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 181EA425146D4A2A00A6D320 /* release.xcconfig */; buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; - CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)"; - CONFIGURATION_TEMP_DIR = "$(PROJECT_TEMP_DIR)"; - }; - name = "normal with debug"; - }; - C23B0C8A09A2987F00B7FCED /* Default */ = { - isa = XCBuildConfiguration; - buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; - CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)"; - CONFIGURATION_TEMP_DIR = "$(PROJECT_TEMP_DIR)"; + CODE_SIGN_IDENTITY = ""; + INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Frameworks"; + PRODUCT_NAME = Security; }; - name = Default; + name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ - C22463730B86212200626F1B /* Build configuration list for PBXNativeTarget "csparser" */ = { + 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 = ( - C22463740B86212200626F1B /* Development */, - C22463750B86212200626F1B /* Deployment */, - C22463760B86212200626F1B /* Darwin */, - C22463770B86212200626F1B /* normal with debug */, - C22463780B86212200626F1B /* Default */, + 18270EDE14CF282600B05E7F /* Debug */, + 18270EDF14CF282600B05E7F /* Release */, ); defaultConfigurationIsVisible = 0; - defaultConfigurationName = Default; + defaultConfigurationName = Release; }; - C22463800B86216400626F1B /* Build configuration list for PBXAggregateTarget "World" */ = { + 182BB572146F4DCB000BF1F3 /* Build configuration list for PBXNativeTarget "csparser" */ = { isa = XCConfigurationList; buildConfigurations = ( - C22463810B86216400626F1B /* Development */, - C22463820B86216400626F1B /* Deployment */, - C22463830B86216400626F1B /* Darwin */, - C22463840B86216400626F1B /* normal with debug */, - C22463850B86216400626F1B /* Default */, + 182BB573146F4DCB000BF1F3 /* Debug */, + 182BB574146F4DCB000BF1F3 /* Release */, ); defaultConfigurationIsVisible = 0; - defaultConfigurationName = Default; + defaultConfigurationName = Release; }; - C23B0C7309A2987F00B7FCED /* Build configuration list for PBXLegacyTarget "copy pieces" */ = { + 182BB599146FE295000BF1F3 /* Build configuration list for PBXAggregateTarget "World" */ = { isa = XCConfigurationList; buildConfigurations = ( - C23B0C7409A2987F00B7FCED /* Development */, - C23B0C7509A2987F00B7FCED /* Deployment */, - C23B0C7609A2987F00B7FCED /* Darwin */, - C23B0C7709A2987F00B7FCED /* normal with debug */, - C23B0C7809A2987F00B7FCED /* Default */, + 182BB59A146FE295000BF1F3 /* Debug */, + 182BB59B146FE295000BF1F3 /* Release */, ); defaultConfigurationIsVisible = 0; - defaultConfigurationName = Default; + defaultConfigurationName = Release; }; - C23B0C7909A2987F00B7FCED /* Build configuration list for PBXNativeTarget "generate" */ = { + 186F778914E59FB200434E1F /* Build configuration list for PBXAggregateTarget "Security_frameworks" */ = { isa = XCConfigurationList; buildConfigurations = ( - C23B0C7A09A2987F00B7FCED /* Development */, - C23B0C7B09A2987F00B7FCED /* Deployment */, - C23B0C7C09A2987F00B7FCED /* Darwin */, - C23B0C7D09A2987F00B7FCED /* normal with debug */, - C23B0C7E09A2987F00B7FCED /* Default */, + 186F778A14E59FB200434E1F /* Debug */, + 186F778B14E59FB200434E1F /* Release */, ); defaultConfigurationIsVisible = 0; - defaultConfigurationName = Default; + defaultConfigurationName = Release; }; - C23B0C7F09A2987F00B7FCED /* Build configuration list for PBXNativeTarget "Security" */ = { + 186F778D14E59FDA00434E1F /* Build configuration list for PBXAggregateTarget "Security_executables" */ = { isa = XCConfigurationList; buildConfigurations = ( - C23B0C8009A2987F00B7FCED /* Development */, - C23B0C8109A2987F00B7FCED /* Deployment */, - C23B0C8209A2987F00B7FCED /* Darwin */, - C23B0C8309A2987F00B7FCED /* normal with debug */, - C23B0C8409A2987F00B7FCED /* Default */, + 186F778E14E59FDA00434E1F /* Debug */, + 186F778F14E59FDA00434E1F /* Release */, ); defaultConfigurationIsVisible = 0; - defaultConfigurationName = Default; + defaultConfigurationName = Release; }; - C23B0C8509A2987F00B7FCED /* Build configuration list for PBXProject "Security" */ = { + 18FE67FB1471A3AA00A2CBE3 /* Build configuration list for PBXNativeTarget "copyHeaders" */ = { isa = XCConfigurationList; buildConfigurations = ( - C23B0C8609A2987F00B7FCED /* Development */, - C23B0C8709A2987F00B7FCED /* Deployment */, - C23B0C8809A2987F00B7FCED /* Darwin */, - C23B0C8909A2987F00B7FCED /* normal with debug */, - C23B0C8A09A2987F00B7FCED /* Default */, + 18FE67FC1471A3AA00A2CBE3 /* Debug */, + 18FE67FD1471A3AA00A2CBE3 /* Release */, ); defaultConfigurationIsVisible = 0; - defaultConfigurationName = Default; + defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; - rootObject = 0867D690FE84028FC02AAC07 /* Project object */; + rootObject = 18073841146D0D4E00F05C24 /* Project object */; } diff --git a/Security.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/Security.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 00000000..250c57cc --- /dev/null +++ b/Security.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded + + + diff --git a/Security.xcodeproj/xcshareddata/xcschemes/Security.xcscheme b/Security.xcodeproj/xcshareddata/xcschemes/Security.xcscheme new file mode 100644 index 00000000..8d48ee79 --- /dev/null +++ b/Security.xcodeproj/xcshareddata/xcschemes/Security.xcscheme @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Security.xcodeproj/xcshareddata/xcschemes/Security_executables.xcscheme b/Security.xcodeproj/xcshareddata/xcschemes/Security_executables.xcscheme new file mode 100644 index 00000000..92748dff --- /dev/null +++ b/Security.xcodeproj/xcshareddata/xcschemes/Security_executables.xcscheme @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Security.xcodeproj/xcshareddata/xcschemes/Security_frameworks.xcscheme b/Security.xcodeproj/xcshareddata/xcschemes/Security_frameworks.xcscheme new file mode 100644 index 00000000..d532de40 --- /dev/null +++ b/Security.xcodeproj/xcshareddata/xcschemes/Security_frameworks.xcscheme @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Security.xcodeproj/xcshareddata/xcschemes/World.xcscheme b/Security.xcodeproj/xcshareddata/xcschemes/World.xcscheme new file mode 100644 index 00000000..8102e9f1 --- /dev/null +++ b/Security.xcodeproj/xcshareddata/xcschemes/World.xcscheme @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Security.xcodeproj/xcshareddata/xcschemes/copyHeaders.xcscheme b/Security.xcodeproj/xcshareddata/xcschemes/copyHeaders.xcscheme new file mode 100644 index 00000000..adc69b37 --- /dev/null +++ b/Security.xcodeproj/xcshareddata/xcschemes/copyHeaders.xcscheme @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Security.xcodeproj/xcshareddata/xcschemes/secd.xcscheme b/Security.xcodeproj/xcshareddata/xcschemes/secd.xcscheme new file mode 100644 index 00000000..63a88abe --- /dev/null +++ b/Security.xcodeproj/xcshareddata/xcschemes/secd.xcscheme @@ -0,0 +1,85 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/config/base.xcconfig b/config/base.xcconfig new file mode 100644 index 00000000..7c1c312e --- /dev/null +++ b/config/base.xcconfig @@ -0,0 +1,8 @@ +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; diff --git a/config/debug.xcconfig b/config/debug.xcconfig new file mode 100644 index 00000000..937d1775 --- /dev/null +++ b/config/debug.xcconfig @@ -0,0 +1,3 @@ +GCC_OPTIMIZATION_LEVEL = 0 +GCC_PREPROCESSOR_DEFINITIONS = DEBUG=1 $(inherited) +COPY_PHASE_STRIP = NO diff --git a/config/lib.xcconfig b/config/lib.xcconfig new file mode 100644 index 00000000..1dec02cc --- /dev/null +++ b/config/lib.xcconfig @@ -0,0 +1,24 @@ +#include "base.xcconfig" + +PRODUCT_NAME = $(TARGET_NAME) +EXECUTABLE_PREFIX = + +CODE_SIGN_IDENTITY = + +HEADER_SEARCH_PATHS = $(PROJECT_DIR)/../include $(BUILT_PRODUCTS_DIR)/derived_src $(BUILT_PRODUCTS_DIR) $(PROJECT_DIR)/lib + +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 diff --git a/config/release.xcconfig b/config/release.xcconfig new file mode 100644 index 00000000..dc5f8761 --- /dev/null +++ b/config/release.xcconfig @@ -0,0 +1,3 @@ +GCC_PREPROCESSOR_DEFINITIONS = NDEBUG=1 $(inherited) +COPY_PHASE_STRIP = YES + diff --git a/config/security.xcconfig b/config/security.xcconfig new file mode 100644 index 00000000..72bd9207 --- /dev/null +++ b/config/security.xcconfig @@ -0,0 +1,24 @@ +#include "config/base.xcconfig" + +PRODUCT_NAME = $(TARGET_NAME) + +FRAMEWORK_VERSION = A + +DYLIB_COMPATIBILITY_VERSION = 1 +DYLIB_CURRENT_VERSION = $(CURRENT_PROJECT_VERSION) + +GCC_PRECOMPILE_PREFIX_HEADER = YES + +ALWAYS_SEARCH_USER_PATHS = NO + +//INSTALLHDRS_SCRIPT_PHASE = YES + +GCC_C_LANGUAGE_STANDARD = gnu99 + +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 diff --git a/include/security_agent_client b/include/security_agent_client new file mode 120000 index 00000000..c01356e3 --- /dev/null +++ b/include/security_agent_client @@ -0,0 +1 @@ +./libsecurity_agent/lib \ No newline at end of file diff --git a/include/security_asn1 b/include/security_asn1 new file mode 120000 index 00000000..09ef0802 --- /dev/null +++ b/include/security_asn1 @@ -0,0 +1 @@ +./libsecurity_asn1/lib \ No newline at end of file diff --git a/include/security_cdsa_client b/include/security_cdsa_client new file mode 120000 index 00000000..9737c610 --- /dev/null +++ b/include/security_cdsa_client @@ -0,0 +1 @@ +./libsecurity_cdsa_client/lib \ No newline at end of file diff --git a/include/security_cdsa_plugin b/include/security_cdsa_plugin new file mode 120000 index 00000000..2be156f8 --- /dev/null +++ b/include/security_cdsa_plugin @@ -0,0 +1 @@ +./libsecurity_cdsa_plugin/lib \ No newline at end of file diff --git a/include/security_cdsa_utilities b/include/security_cdsa_utilities new file mode 120000 index 00000000..2634481d --- /dev/null +++ b/include/security_cdsa_utilities @@ -0,0 +1 @@ +./libsecurity_cdsa_utilities/lib \ No newline at end of file diff --git a/include/security_cdsa_utils b/include/security_cdsa_utils new file mode 120000 index 00000000..f3e5247e --- /dev/null +++ b/include/security_cdsa_utils @@ -0,0 +1 @@ +./libsecurity_cdsa_utils/lib \ No newline at end of file diff --git a/include/security_codesigning b/include/security_codesigning new file mode 120000 index 00000000..7c67092b --- /dev/null +++ b/include/security_codesigning @@ -0,0 +1 @@ +./libsecurity_codesigning/lib \ No newline at end of file diff --git a/include/security_comcryption b/include/security_comcryption new file mode 120000 index 00000000..cbcdf214 --- /dev/null +++ b/include/security_comcryption @@ -0,0 +1 @@ +./libsecurity_comcryption/lib \ No newline at end of file diff --git a/include/security_cryptkit b/include/security_cryptkit new file mode 120000 index 00000000..609dcc3b --- /dev/null +++ b/include/security_cryptkit @@ -0,0 +1 @@ +./libsecurity_cryptkit/lib \ No newline at end of file diff --git a/include/security_filedb b/include/security_filedb new file mode 120000 index 00000000..99185cdc --- /dev/null +++ b/include/security_filedb @@ -0,0 +1 @@ +./libsecurity_filedb/lib \ No newline at end of file diff --git a/include/security_keychain b/include/security_keychain new file mode 120000 index 00000000..aac53b6d --- /dev/null +++ b/include/security_keychain @@ -0,0 +1 @@ +./libsecurity_keychain/lib \ No newline at end of file diff --git a/include/security_ocspd b/include/security_ocspd new file mode 120000 index 00000000..449ea98b --- /dev/null +++ b/include/security_ocspd @@ -0,0 +1 @@ +./libsecurity_ocspd/common \ No newline at end of file diff --git a/include/security_pkcs12 b/include/security_pkcs12 new file mode 120000 index 00000000..8fdcb01e --- /dev/null +++ b/include/security_pkcs12 @@ -0,0 +1 @@ +./libsecurity_pkcs12/lib \ No newline at end of file diff --git a/include/security_smime b/include/security_smime new file mode 120000 index 00000000..e1a40bad --- /dev/null +++ b/include/security_smime @@ -0,0 +1 @@ +./libsecurity_smime/lib \ No newline at end of file diff --git a/include/security_utilities b/include/security_utilities new file mode 120000 index 00000000..4d363d11 --- /dev/null +++ b/include/security_utilities @@ -0,0 +1 @@ +./libsecurity_utilities/lib \ No newline at end of file diff --git a/include/securityd_client b/include/securityd_client new file mode 120000 index 00000000..2edb676a --- /dev/null +++ b/include/securityd_client @@ -0,0 +1 @@ +./libsecurityd/lib \ No newline at end of file diff --git a/FDEPrefs.plist b/lib/FDEPrefs.plist similarity index 74% rename from FDEPrefs.plist rename to lib/FDEPrefs.plist index 31396258..42078fab 100644 --- a/FDEPrefs.plist +++ b/lib/FDEPrefs.plist @@ -2,8 +2,6 @@ - GETServerURL - https://fdelookup.corp.apple.com/fdeserver/lookupServlet POSTServerURL https://fdereg.apple.com/fdeserver/registrationServlet diff --git a/Info-Security.plist b/lib/Info-Security.plist similarity index 96% rename from Info-Security.plist rename to lib/Info-Security.plist index 999fc806..f8cf6e9a 100644 --- a/Info-Security.plist +++ b/lib/Info-Security.plist @@ -19,6 +19,6 @@ CFBundleSignature ???? CFBundleVersion - 55148.6 + 55163.44 diff --git a/intl/English.lproj/FDELocalizable.strings b/lib/en.lproj/FDELocalizable.strings similarity index 100% rename from intl/English.lproj/FDELocalizable.strings rename to lib/en.lproj/FDELocalizable.strings diff --git a/intl/English.lproj/InfoPlist.strings b/lib/en.lproj/InfoPlist.strings similarity index 100% rename from intl/English.lproj/InfoPlist.strings rename to lib/en.lproj/InfoPlist.strings diff --git a/plugins/csparser-Info.plist b/lib/plugins/csparser-Info.plist similarity index 96% rename from plugins/csparser-Info.plist rename to lib/plugins/csparser-Info.plist index 8cc529f0..0f0f8b44 100644 --- a/plugins/csparser-Info.plist +++ b/lib/plugins/csparser-Info.plist @@ -17,7 +17,7 @@ CFBundleSignature ???? CFBundleVersion - 55148.6 + 55163.44 CFBundleShortVersionString 3.0 diff --git a/plugins/csparser.cpp b/lib/plugins/csparser.cpp similarity index 100% rename from plugins/csparser.cpp rename to lib/plugins/csparser.cpp diff --git a/plugins/csparser.exp b/lib/plugins/csparser.exp similarity index 100% rename from plugins/csparser.exp rename to lib/plugins/csparser.exp diff --git a/lib/security.exp b/lib/security.exp index ed4325a0..d34e4db7 100644 --- a/lib/security.exp +++ b/lib/security.exp @@ -347,6 +347,7 @@ _kSecGuestAttributeMachPort _kSecGuestAttributePid _kSecRequirementKeyInfoPlist _kSecRequirementKeyEntitlements +_kSecRequirementKeyIdentifier _kSecCFErrorArchitecture _kSecCFErrorPath _kSecCFErrorPattern @@ -367,6 +368,7 @@ _SecTaskCopyValuesForEntitlements _SecAssessmentCreate _SecAssessmentCopyResult _SecAssessmentUpdate +_SecAssessmentCopyUpdate _SecAssessmentControl _kSecAssessmentContextKeyOperation _kSecAssessmentOperationTypeExecute @@ -378,12 +380,16 @@ _kSecAssessmentUpdateOperationAdd _kSecAssessmentUpdateOperationRemove _kSecAssessmentUpdateOperationEnable _kSecAssessmentUpdateOperationDisable +_kSecAssessmentUpdateOperationFind _kSecAssessmentUpdateKeyAuthorization _kSecAssessmentUpdateKeyAllow _kSecAssessmentUpdateKeyExpires _kSecAssessmentUpdateKeyLabel _kSecAssessmentUpdateKeyPriority _kSecAssessmentUpdateKeyRemarks +_kSecAssessmentUpdateKeyRow +_kSecAssessmentUpdateKeyCount +_kSecAssessmentUpdateKeyFound _kSecAssessmentAssessmentAuthority _kSecAssessmentAssessmentAuthorityOverride _kSecAssessmentAssessmentAuthorityRow @@ -391,6 +397,16 @@ _kSecAssessmentAssessmentFromCache _kSecAssessmentAssessmentOriginator _kSecAssessmentAssessmentSource _kSecAssessmentAssessmentVerdict +_kSecAssessmentRuleKeyID +_kSecAssessmentRuleKeyPriority +_kSecAssessmentRuleKeyAllow +_kSecAssessmentRuleKeyLabel +_kSecAssessmentRuleKeyRemarks +_kSecAssessmentRuleKeyRequirement +_kSecAssessmentRuleKeyType +_kSecAssessmentRuleKeyExpires +_kSecAssessmentRuleKeyDisabled +_kSecAssessmentRuleKeyBookmark # libsecurity_cssm ##################################################################################### @@ -1380,16 +1396,19 @@ _SecCertificateCopyPreferred _SecCertificateCopyPublicKey _SecCertificateCopySubjectSummary _SecCertificateCreateFromData +_SecCertificateCreateWithBytes _SecCertificateCreateWithData _SecCertificateFindByEmail _SecCertificateFindByIssuerAndSN _SecCertificateFindBySubjectKeyID _SecCertificateGetAlgorithmID _SecCertificateGetCLHandle +_SecCertificateGetBytePtr _SecCertificateGetCommonName _SecCertificateGetData _SecCertificateGetEmailAddress _SecCertificateGetIssuer +_SecCertificateGetLength _SecCertificateGetSubject _SecCertificateGetType _SecCertificateGetTypeID @@ -1455,6 +1474,7 @@ _kSecAttrPRFHmacAlgSHA384 _kSecAttrPRFHmacAlgSHA512 _kSecAttrSalt _kSecAttrRounds +_SecECKeyGetNamedCurve _SecItemExport _SecItemImport _SecKeyCreate @@ -1465,6 +1485,7 @@ _SecKeyEncrypt _SecKeyGenerate _SecKeyGeneratePair _SecKeyGetAlgorithmID +_SecKeyGetAlgorithmId _SecKeyGetBlockSize _SecKeyGetCSPHandle _SecKeyGetCSSMKey @@ -1474,6 +1495,8 @@ _SecKeyGetTypeID _SecKeyImportPair _SecKeyRawSign _SecKeyRawVerify +_SecKeySignDigest +_SecKeyVerifyDigest _SecKeyGenerateSymmetric _SecKeyCreateFromData _SecKeyGeneratePairAsync @@ -1852,6 +1875,8 @@ _SecSMIMEFindBulkAlgForRecipients ##################################################################################### _SSLAddDistinguishedName _SSLClose +_SSLContextGetTypeID +_SSLCreateContext _SSLDisposeContext _SSLGetAllowsAnyRoot _SSLGetAllowsExpiredCerts @@ -1876,6 +1901,8 @@ _SSLGetPeerID _SSLGetPeerSecTrust _SSLGetProtocolVersion _SSLGetProtocolVersionEnabled +_SSLGetProtocolVersionMax +_SSLGetProtocolVersionMin _SSLGetResumableSessionInfo _SSLGetRsaBlinding _SSLGetSessionOption @@ -1900,6 +1927,9 @@ _SSLSetCertificate _SSLGetCertificate _SSLSetClientSideAuthenticate _SSLSetConnection +_SSLSetDatagramHelloCookie +_SSLSetMaxDatagramRecordSize +_SSLGetMaxDatagramRecordSize _SSLSetDiffieHellmanParams _SSLSetEnableCertVerify _SSLSetEnabledCiphers @@ -1910,6 +1940,8 @@ _SSLSetPeerDomainName _SSLSetPeerID _SSLSetProtocolVersion _SSLSetProtocolVersionEnabled +_SSLSetProtocolVersionMax +_SSLSetProtocolVersionMin _SSLSetRsaBlinding _SSLSetTrustedRoots _SSLWrite @@ -1929,6 +1961,10 @@ _SSLSetECDSACurves _SSLGetNumberOfClientAuthTypes _SSLGetClientAuthTypes _SSLGetNegotiatedClientAuthType +_SSLGetNumberOfSignatureAlgorithms +_SSLGetSignatureAlgorithms +_SSLNewDatagramContext +_SSLGetDatagramWriteSize # libsecurity_transform ##################################################################################### @@ -1953,6 +1989,7 @@ _kSecDigestMD5 _kSecDigestSHA1 _kSecDigestSHA2 _kSecDigestHMACSHA1 +_kSecDigestHMACMD5 _kSecDigestHMACKeyAttribute _kSecDigestHMACSHA2 _SecExternalSourceTransformCreate diff --git a/libsecurity_apple_csp/Info-security_apple_csp.plist b/libsecurity_apple_csp/Info-security_apple_csp.plist new file mode 100644 index 00000000..0c67376e --- /dev/null +++ b/libsecurity_apple_csp/Info-security_apple_csp.plist @@ -0,0 +1,5 @@ + + + + + diff --git a/libsecurity_apple_csp/README b/libsecurity_apple_csp/README new file mode 100644 index 00000000..e207744a --- /dev/null +++ b/libsecurity_apple_csp/README @@ -0,0 +1,32 @@ + libsecurity_apple_csp Notes + +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 CSP (and hence Security.framework, 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. + +The algorithms avoided by selecting the Darwin build style are as follows: + +CSSM_ALGID_ASC + Apple Secure Compression, a symmetric encryption algorithm + which performs simultaneous encryption and compression. + +CSSM_ALGID_FEE +CSSM_ALGID_FEED +CSSM_ALGID_FEEDEXP +CSSM_ALGID_FEE_MD5 +CSSM_ALGID_FEE_SHA1 +CSSM_ALGID_SHA1WithECDSA +CSSM_ALGID_ECDSA + Asymmetric encryption using Apple's patented Fast Elliptic Encryption + algorithm. + \ No newline at end of file diff --git a/libsecurity_apple_csp/TODO b/libsecurity_apple_csp/TODO new file mode 100644 index 00000000..cbdab795 --- /dev/null +++ b/libsecurity_apple_csp/TODO @@ -0,0 +1 @@ +Things TODO in AppleCSPDL diff --git a/libsecurity_apple_csp/docs/libsecurity_apple_csp.plist b/libsecurity_apple_csp/docs/libsecurity_apple_csp.plist new file mode 100644 index 00000000..d1cc0fb2 --- /dev/null +++ b/libsecurity_apple_csp/docs/libsecurity_apple_csp.plist @@ -0,0 +1,42 @@ + + + + + + OpenSourceLicense + openssl + OpenSourceLicenseFile + libsecurity_apple_csp.txt + OpenSourceModifications + Extensive customization for OS X + OpenSourceProject + openssl + OpenSourceURL + http://www.openssl.org/source/openssl-0.9.6.tar.gz + OpenSourceVersion + openssl-0.9.6 + OpenSourceWebsiteURL + http://www.openssl.org/ + OpenSourceImportDate + 2000-01-01 + + + OpenSourceLicense + openssl + OpenSourceLicenseFile + libsecurity_apple_csp.txt + OpenSourceModifications + Extensive customization for OS X + OpenSourceProject + rijndael-alg-ref.c + OpenSourceURL + <No longer published> + OpenSourceVersion + Orignal AES Reference Implementation from NIST + OpenSourceWebsiteURL + http://csrc.nist.gov/CryptoToolkit/aes/ + OpenSourceImportDate + 2000-01-01 + + + diff --git a/libsecurity_apple_csp/docs/libsecurity_apple_csp.txt b/libsecurity_apple_csp/docs/libsecurity_apple_csp.txt new file mode 100644 index 00000000..c885273f --- /dev/null +++ b/libsecurity_apple_csp/docs/libsecurity_apple_csp.txt @@ -0,0 +1,60 @@ + Original SSLeay License + ----------------------- + +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + diff --git a/libsecurity_apple_csp/lib/AppleCSP.cpp b/libsecurity_apple_csp/lib/AppleCSP.cpp new file mode 100644 index 00000000..7fd55f16 --- /dev/null +++ b/libsecurity_apple_csp/lib/AppleCSP.cpp @@ -0,0 +1,661 @@ +/* + * 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. + */ + + +// +// AppleCSP.cpp - top-level plugin and session implementation +// +#include "AppleCSP.h" +#include "AppleCSPSession.h" +#include "AppleCSPUtils.h" +#include +#include "cspdebugging.h" +#include +#include +#ifdef BSAFE_CSP_ENABLE +#include "bsafecsp.h" +#include "bsafecspi.h" +#endif +#ifdef CRYPTKIT_CSP_ENABLE +#include "cryptkitcsp.h" +#include "FEEKeys.h" +#endif +#include +#ifdef ASC_CSP_ENABLE +#include "ascFactory.h" +#endif +#include +#include +#include +#include + +#include "YarrowConnection.h" + +// +// Make and break the plugin object +// +AppleCSPPlugin::AppleCSPPlugin() : + normAllocator(Allocator::standard(Allocator::normal)), + privAllocator(Allocator::standard(Allocator::sensitive)), + #ifdef BSAFE_CSP_ENABLE + bSafe4Factory(new BSafeFactory(&normAllocator, &privAllocator)), + #endif + #ifdef CRYPTKIT_CSP_ENABLE + cryptKitFactory(new CryptKitFactory(&normAllocator, &privAllocator)), + #endif + miscAlgFactory(new MiscAlgFactory(&normAllocator, &privAllocator)), + #ifdef ASC_CSP_ENABLE + ascAlgFactory(new AscAlgFactory(&normAllocator, &privAllocator)), + #endif + rsaDsaAlgFactory(new RSA_DSA_Factory(&normAllocator, &privAllocator)), + dhAlgFactory(new DH_Factory(&normAllocator, &privAllocator)) +{ + // misc. once-per-address-space cruft... +} + +AppleCSPPlugin::~AppleCSPPlugin() +{ + #ifdef BSAFE_CSP_ENABLE + delete bSafe4Factory; + #endif + #ifdef CRYPTKIT_CSP_ENABLE + delete cryptKitFactory; + #endif + delete miscAlgFactory; + #ifdef ASC_CSP_ENABLE + delete ascAlgFactory; + #endif + delete rsaDsaAlgFactory; + delete dhAlgFactory; +} + + +// +// Create a new plugin session, our way +// +PluginSession *AppleCSPPlugin::makeSession( + CSSM_MODULE_HANDLE handle, + const CSSM_VERSION &version, + uint32 subserviceId, + CSSM_SERVICE_TYPE subserviceType, + CSSM_ATTACH_FLAGS attachFlags, + const CSSM_UPCALLS &upcalls) +{ + switch (subserviceType) { + case CSSM_SERVICE_CSP: + return new AppleCSPSession(handle, + *this, + version, + subserviceId, + subserviceType, + attachFlags, + upcalls); + default: + CssmError::throwMe(CSSMERR_CSSM_INVALID_SERVICE_MASK); + return 0; // placebo + } +} + + +// +// Session constructor +// +AppleCSPSession::AppleCSPSession( + CSSM_MODULE_HANDLE handle, + AppleCSPPlugin &plug, + const CSSM_VERSION &version, + uint32 subserviceId, + CSSM_SERVICE_TYPE subserviceType, + CSSM_ATTACH_FLAGS attachFlags, + const CSSM_UPCALLS &upcalls) + : CSPFullPluginSession(handle, + plug, + version, + subserviceId, + subserviceType, + attachFlags, + upcalls), + #ifdef BSAFE_CSP_ENABLE + bSafe4Factory(*(dynamic_cast(plug.bSafe4Factory))), + #endif + #ifdef CRYPTKIT_CSP_ENABLE + cryptKitFactory(*(dynamic_cast(plug.cryptKitFactory))), + #endif + miscAlgFactory(*(dynamic_cast(plug.miscAlgFactory))), + #ifdef ASC_CSP_ENABLE + ascAlgFactory(*(dynamic_cast(plug.ascAlgFactory))), + #endif + rsaDsaAlgFactory(*(dynamic_cast(plug.rsaDsaAlgFactory))), + dhAlgFactory(*(dynamic_cast(plug.dhAlgFactory))), + normAllocator(*this), + privAllocator(plug.privAlloc()) +{ + // anything? +} + +AppleCSPSession::~AppleCSPSession() +{ + // anything? +} + +// +// Called at (CSSM) context create time. This is ignored; we do a full +// context setup later, at setupContext time. +// +CSPFullPluginSession::CSPContext * +AppleCSPSession::contextCreate( + CSSM_CC_HANDLE handle, + const Context &context) +{ + return NULL; +} + +// +// Called by CSPFullPluginSession when an op is actually commencing. +// Context can safely assumed to be fully formed and stable for the +// duration of the op; thus we wait until now to set up our +// CSPContext as appropriate to the op. +// +void AppleCSPSession::setupContext( + CSPContext * &cspCtx, + const Context &context, + bool encoding) +{ + /* + * Note we leave the decision as to whether it's OK to + * reuse a context to the individual factories. + */ + #ifdef BSAFE_CSP_ENABLE + /* Give BSAFE the firsrt shot if it's present */ + if (bSafe4Factory.setup(*this, cspCtx, context)) { + CASSERT(cspCtx != NULL); + return; + } + #endif + if (rsaDsaAlgFactory.setup(*this, cspCtx, context)) { + CASSERT(cspCtx != NULL); + return; + } + if (miscAlgFactory.setup(*this, cspCtx, context)) { + CASSERT(cspCtx != NULL); + return; + } + if (dhAlgFactory.setup(*this, cspCtx, context)) { + CASSERT(cspCtx != NULL); + return; + } + #ifdef CRYPTKIT_CSP_ENABLE + if (cryptKitFactory.setup(*this, cspCtx, context)) { + CASSERT(cspCtx != NULL); + return; + } + #endif + #ifdef ASC_CSP_ENABLE + if (ascAlgFactory.setup(*this, cspCtx, context)) { + CASSERT(cspCtx != NULL); + return; + } + #endif + if(setup(cspCtx, context)) { + CASSERT(cspCtx != NULL); + return; + } + dprintf0("AppleCSPSession::setupContext: invalid algorithm\n"); + CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM); +} + +/* + * Used for generating crypto contexts at this level. + * Analogous to AlgorithmFactory.setup(). + */ +bool AppleCSPSession::setup( + CSPFullPluginSession::CSPContext * &cspCtx, + const Context &context) +{ + if (cspCtx) { + return false; // not ours or already set + } + + switch(context.type()) { + case CSSM_ALGCLASS_RANDOMGEN: + switch (context.algorithm()) { + case CSSM_ALGID_APPLE_YARROW: + cspCtx = new YarrowContext(*this); + return true; + /* other random algs here */ + default: + return false; + } + /* other contexts here */ + default: + return false; + } + /* NOT REACHED */ + return false; + +} + +// +// Context for CSSM_ALGID_APPLE_YARROW. +// +YarrowContext::YarrowContext(AppleCSPSession &session) + : AppleCSPContext(session) +{ + // nothing for now +} + +YarrowContext::~YarrowContext() +{ + // nothing for now +} + +// +// Only job here is to snag the length and process the optional seed argument +// +void YarrowContext::init( + const Context &context, + bool encoding) +{ + /* stash requested length for use later in outputSize() */ + outSize = context.getInt(CSSM_ATTRIBUTE_OUTPUT_SIZE, + CSSMERR_CSP_INVALID_ATTR_OUTPUT_SIZE); + + /* optional seed */ + CssmCryptoData *cseed = context.get(CSSM_ATTRIBUTE_SEED); + if(cseed == NULL) { + /* we're done */ + return; + } + CssmData seed = (*cseed)(); + if((seed.Length == 0) || + (seed.Data == NULL)) { + CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_SEED); + } + session().addEntropy((size_t)seed.Length, seed.Data); +} + +void YarrowContext::final( + CssmData &out) +{ + session().getRandomBytes((size_t)out.Length, out.Data); +} + +/*** + *** Binary Key support. + ***/ + +// Given a CSSM_DATA, extract its KeyRef. +static KeyRef CssmDataToKeyRef( + const CSSM_DATA &data) +{ + if(data.Length != sizeof(KeyRef)) { + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_REFERENCE); + } + + uint8 *cp = data.Data + sizeof(KeyRef) - 1; + KeyRef keyRef = 0; + for(unsigned dex=0; dex sizeof(keyRef)) { + /* don't leave old raw key material lying around */ + memset(data.Data + sizeof(keyRef), 0, data.Length - sizeof(keyRef)); + } + else if(data.Length < sizeof(keyRef)) { + /* not enough space for even a keyRef, force realloc */ + allocator.free(data.Data); + data.Data = NULL; + data.Length = 0; + } + setUpData(data, sizeof(keyRef), allocator); + + uint8 *cp = data.Data; + for(unsigned i=0; i>= 8; + } +} + +// Look up a BinaryKey by its KeyRef. Returns NULL if not +// found. refKeyMapLock held on entry and exit. +BinaryKey *AppleCSPSession::lookupKeyRef( + KeyRef keyRef) +{ + const BinaryKey *binKey; + + // use safe version, don't create new entry if this key + // isn't there + keyMap::iterator it = refKeyMap.find(keyRef); + if(it == refKeyMap.end()) { + return NULL; + } + binKey = it->second; + assert(binKey == reinterpret_cast(keyRef)); + assert(binKey->mKeyRef == keyRef); + return const_cast(binKey); +} + +// add a BinaryKey to our refKeyMap. Sets up cssmKey +// as appropriate. +void AppleCSPSession::addRefKey( + BinaryKey &binKey, + CssmKey &cssmKey) +{ + // for now, KeyRef is just the address of the BinaryKey + KeyRef keyRef = reinterpret_cast(&binKey); + + binKey.mKeyRef = keyRef; + binKey.mKeyHeader = CssmKey::Header::overlay(cssmKey.KeyHeader); + { + StLock _(refKeyMapLock); + assert(lookupKeyRef(keyRef) == NULL); + refKeyMap[keyRef] = &binKey; + } + cssmKey.KeyHeader.BlobType = CSSM_KEYBLOB_REFERENCE; + cssmKey.KeyHeader.Format = CSSM_KEYBLOB_REF_FORMAT_INTEGER; + keyRefToCssmData(keyRef, cssmKey.KeyData, normAllocator); + secdebug("freeKey", "CSP addRefKey key %p keyData %p keyRef %p", + &cssmKey, cssmKey.KeyData.Data, &binKey); +} + +// Given a CssmKey in reference form, obtain the associated +// BinaryKey. Throws CSSMERR_CSP_INVALID_KEY_REFERENCE if +// key not found in session key map. +BinaryKey & AppleCSPSession::lookupRefKey( + const CssmKey &cssmKey) +{ + KeyRef keyRef; + BinaryKey *binKey; + + keyRef = CssmDataToKeyRef(cssmKey.KeyData); + { + StLock _(refKeyMapLock); + binKey = lookupKeyRef(keyRef); + } + if(binKey == NULL) { + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_REFERENCE); + } + assert(Guid::overlay(binKey->mKeyHeader.CspId) == plugin.myGuid()); + + /* + * Verify sensitive fields have not changed between when the BinaryKey was + * created/stored and when the caller passed in the ref key. + * Some fields were changed by addRefKey, so make a local copy.... + */ + CSSM_KEYHEADER localHdr = cssmKey.KeyHeader; + localHdr.BlobType = binKey->mKeyHeader.BlobType; + localHdr.Format = binKey->mKeyHeader.Format; + if(memcmp(&localHdr, &binKey->mKeyHeader, sizeof(CSSM_KEYHEADER))) { + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_REFERENCE); + } + return (*binKey); +} + +// CSPFullPluginSession declares & implements this. +// Note that we ignore the delete argument; since we don't +// store anything, freeing is the same as deleting. +void AppleCSPSession::FreeKey( + const AccessCredentials *AccessCred, + CssmKey &KeyPtr, + CSSM_BOOL Delete) +{ + + if((KeyPtr.blobType() == CSSM_KEYBLOB_REFERENCE) && + (KeyPtr.cspGuid() == plugin.myGuid())) { + // it's a ref key we generated - delete associated BinaryKey + KeyRef keyRef = CssmDataToKeyRef(KeyPtr.KeyData); + { + StLock _(refKeyMapLock); + BinaryKey *binKey = lookupKeyRef(keyRef); + if(binKey != NULL) { + secdebug("freeKey", "CSP FreeKey key %p keyData %p binKey %p", + &KeyPtr, KeyPtr.KeyData.Data, binKey); + try { + refKeyMap.erase(keyRef); + delete binKey; + } + catch (...) { + errorLog0("Error deleting/erasing known " + "ref key\n"); + } + } + else { + secdebug("freeKey", "CSP freeKey unknown key"); + } + } + } + CSPFullPluginSession::FreeKey(AccessCred, KeyPtr, Delete); +} + +/* Passthrough, used for key digest */ +void AppleCSPSession::PassThrough( + CSSM_CC_HANDLE CCHandle, + const Context &Context, + uint32 PassThroughId, + const void *InData, + void **OutData) +{ + *OutData = NULL; + + /* validate context */ + if(Context.type() != CSSM_ALGCLASS_NONE) { + CssmError::throwMe(CSSMERR_CSP_INVALID_CONTEXT); + } + + switch(PassThroughId) { + case CSSM_APPLECSP_KEYDIGEST: + { + CssmKey &key = Context.get( + CSSM_ATTRIBUTE_KEY, + CSSMERR_CSP_MISSING_ATTR_KEY); + + /* validate key as best we can */ + switch(key.keyClass()) { + case CSSM_KEYCLASS_PUBLIC_KEY: + case CSSM_KEYCLASS_PRIVATE_KEY: + case CSSM_KEYCLASS_SESSION_KEY: + break; + default: + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS); + } + + /* + * Ref key: obtain binary, ask it for blob + * Raw key: get info provider, ask it for the blob. This + * allows for an optimized path which avoids + * converting to a BinaryKey. + */ + CssmData blobToHash; + switch(key.blobType()) { + case CSSM_KEYBLOB_RAW: + { + CSPKeyInfoProvider *provider = infoProvider(key); + bool converted = + provider->getHashableBlob(privAllocator, blobToHash); + if(converted) { + /* took optimized case; proceed */ + delete provider; + break; + } + + /* convert to BinaryKey and ask it to do the work */ + BinaryKey *binKey; + CSSM_KEYATTR_FLAGS flags = 0; // not used + provider->CssmKeyToBinary(NULL, // no paramKey + flags, + &binKey); + binKey->mKeyHeader = + CssmKey::Header::overlay(key.KeyHeader); + CSSM_KEYBLOB_FORMAT rawFormat; + rawFormat = CSSM_KEYBLOB_RAW_FORMAT_DIGEST; + CSSM_KEYATTR_FLAGS attrFlags = 0; + binKey->generateKeyBlob(privAllocator, + blobToHash, + rawFormat, + *this, + NULL, + attrFlags); + delete binKey; + delete provider; + break; + } + case CSSM_KEYBLOB_REFERENCE: + { + BinaryKey &binKey = lookupRefKey(key); + CSSM_KEYBLOB_FORMAT rawFormat; + rawFormat = CSSM_KEYBLOB_RAW_FORMAT_DIGEST; + CSSM_KEYATTR_FLAGS attrFlags = 0; + binKey.generateKeyBlob(privAllocator, + blobToHash, + rawFormat, + *this, + NULL, + attrFlags); + } + break; + default: + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY); + } + + /* obtain sha1 hash of blobToHash */ + + CSSM_DATA_PTR outHash = NULL; + try { + outHash = + (CSSM_DATA_PTR)normAllocator.malloc(sizeof(CSSM_DATA)); + outHash->Data = + (uint8 *)normAllocator.malloc(SHA1_DIGEST_SIZE); + outHash->Length = SHA1_DIGEST_SIZE; + } + catch(...) { + freeCssmData(blobToHash, privAllocator); + throw; + } + cspGenSha1Hash(blobToHash.data(), blobToHash.length(), + outHash->Data); + freeCssmData(blobToHash, privAllocator); + *OutData = outHash; + return; + } + default: + CssmError::throwMe(CSSMERR_CSP_INVALID_PASSTHROUGH_ID); + } + /* NOT REACHED */ +} + +/* + * CSPSession version of QueryKeySizeInBits. + */ +void AppleCSPSession::getKeySize(const CssmKey &key, + CSSM_KEY_SIZE &size) +{ + CSPKeyInfoProvider *provider = infoProvider(key); + try { + provider->QueryKeySizeInBits(size); + } + catch(...) { + /* don't leak this on error */ + delete provider; + throw; + } + delete provider; +} + +void AppleCSPSession::getRandomBytes(size_t length, uint8 *cp) +{ + try { + cspGetRandomBytes(cp, (unsigned)length); + } + catch(...) { + errorLog0("CSP: YarrowClient failure\n"); + } +} + +void AppleCSPSession::addEntropy(size_t length, const uint8 *cp) +{ + try { + cspAddEntropy(cp, (unsigned)length); + } + catch(...) { + #if CSP_ALLOW_FEE_RNG + return; + #else + throw; + #endif + } +} + +/*** + *** CSPKeyInfoProvider support. + ***/ + +/* + * Find a CSPKeyInfoProvider subclass for the specified key. + */ +CSPKeyInfoProvider *AppleCSPSession::infoProvider( + const CssmKey &key) +{ + CSPKeyInfoProvider *provider = NULL; + + #ifdef BSAFE_CSP_ENABLE + /* Give BSAFE first shot, if it's here */ + provider = BSafe::BSafeKeyInfoProvider::provider(key, *this); + if(provider != NULL) { + return provider; + } + #endif + + provider = RSAKeyInfoProvider::provider(key, *this); + if(provider != NULL) { + return provider; + } + + provider = SymmetricKeyInfoProvider::provider(key, *this); + if(provider != NULL) { + return provider; + } + + #ifdef CRYPTKIT_CSP_ENABLE + provider = CryptKit::FEEKeyInfoProvider::provider(key, *this); + if(provider != NULL) { + return provider; + } + #endif + + provider = DSAKeyInfoProvider::provider(key, *this); + if(provider != NULL) { + return provider; + } + + provider = DHKeyInfoProvider::provider(key, *this); + if(provider != NULL) { + return provider; + } + + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY); +} + diff --git a/libsecurity_apple_csp/lib/AppleCSP.h b/libsecurity_apple_csp/lib/AppleCSP.h new file mode 100644 index 00000000..e8531a73 --- /dev/null +++ b/libsecurity_apple_csp/lib/AppleCSP.h @@ -0,0 +1,87 @@ +/* + * 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. + */ + + +// +// AppleCSP.h - top-level plugin and session classes +// +#ifndef _APPLE_CSP_H_ +#define _APPLE_CSP_H_ + +#include +#include +#include + +class AppleCSPSession; +class AppleCSPContext; + +/* + * AppleCSP-specific algorithm factory. + */ +class AppleCSPAlgorithmFactory { +public: + AppleCSPAlgorithmFactory() {}; + virtual ~AppleCSPAlgorithmFactory() { }; + + // set ctx and return true if you can handle this + virtual bool setup( + AppleCSPSession &session, + CSPFullPluginSession::CSPContext * &cspCtx, + const Context &context) = 0; + + /* probably other setup methods, e.g. by CSSM_ALGORITHMS instead of + * context */ +}; + +class AppleCSPPlugin : public CssmPlugin { + friend class AppleCSPSession; + friend class AppleCSPContext; + +public: + AppleCSPPlugin(); + ~AppleCSPPlugin(); + + PluginSession *makeSession(CSSM_MODULE_HANDLE handle, + const CSSM_VERSION &version, + uint32 subserviceId, + CSSM_SERVICE_TYPE subserviceType, + CSSM_ATTACH_FLAGS attachFlags, + const CSSM_UPCALLS &upcalls); + + Allocator &normAlloc() {return normAllocator; } + Allocator &privAlloc() {return privAllocator; } + +private: + Allocator &normAllocator; + Allocator &privAllocator; + #ifdef BSAFE_CSP_ENABLE + AppleCSPAlgorithmFactory *bSafe4Factory; // actually subclasses not visible + // in this header + #endif + #ifdef CRYPTKIT_CSP_ENABLE + AppleCSPAlgorithmFactory *cryptKitFactory; + #endif + AppleCSPAlgorithmFactory *miscAlgFactory; + #ifdef ASC_CSP_ENABLE + AppleCSPAlgorithmFactory *ascAlgFactory; + #endif + AppleCSPAlgorithmFactory *rsaDsaAlgFactory; + AppleCSPAlgorithmFactory *dhAlgFactory; +}; + + +#endif //_APPLE_CSP_H_ diff --git a/libsecurity_apple_csp/lib/AppleCSPBuiltin.cpp b/libsecurity_apple_csp/lib/AppleCSPBuiltin.cpp new file mode 100644 index 00000000..b7b5278a --- /dev/null +++ b/libsecurity_apple_csp/lib/AppleCSPBuiltin.cpp @@ -0,0 +1,32 @@ +/* + * 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 obtai +n + * 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. + */ + + +// +// Produce the "genuine plugin version" of the AppleCSP +// +#include + + +// +// Create the plugin object and generate the C layer hookup +// +static ModuleNexus plugin; + +#define SPINAME(s) s ## __apple_csp +#include diff --git a/libsecurity_apple_csp/lib/AppleCSPContext.cpp b/libsecurity_apple_csp/lib/AppleCSPContext.cpp new file mode 100644 index 00000000..f393e930 --- /dev/null +++ b/libsecurity_apple_csp/lib/AppleCSPContext.cpp @@ -0,0 +1,274 @@ +/* + * 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. + */ + + +// +// AppleCSPContext.cpp - CSP-wide contexts +// + +#include "AppleCSPContext.h" +#include "AppleCSPSession.h" +#include "AppleCSPUtils.h" + +/* + * Empty destructor (just to avoid out-of-line copies) + */ +AppleCSPContext::~AppleCSPContext() +{ } + +/* + * get symmetric key bits - context.key can be either ref or raw. + * A convenience routine typically used by subclass's init(). + */ +void AppleCSPContext::symmetricKeyBits( + const Context &context, + AppleCSPSession &session, + CSSM_ALGORITHMS requiredAlg, // throws if this doesn't match key alg + CSSM_KEYUSE intendedUse, // throws if key usage doesn't match this + uint8 *&keyBits, // RETURNED (not mallocd or copied) + CSSM_SIZE &keyLen) // RETURNED +{ + /* key must be present and it must be a session key matching caller's spec */ + CssmKey &key = + context.get(CSSM_ATTRIBUTE_KEY, CSSMERR_CSP_MISSING_ATTR_KEY); + if(key.keyClass() != CSSM_KEYCLASS_SESSION_KEY) { + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS); + } + if(key.algorithm() != requiredAlg) { + CssmError::throwMe(CSSMERR_CSP_ALGID_MISMATCH); + } + cspValidateIntendedKeyUsage(&key.KeyHeader, intendedUse); + cspVerifyKeyTimes(key.KeyHeader); + + /* extract raw bits one way or the other */ + switch(key.blobType()) { + case CSSM_KEYBLOB_RAW: + /* easy case, the bits are right there in the CssmKey */ + if(key.blobFormat() != CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING) { + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_FORMAT); + } + keyLen = key.length(); + keyBits = key.KeyData.Data; + break; + + case CSSM_KEYBLOB_REFERENCE: + { + /* do a lookup to get a binary key */ + BinaryKey &binKey = session.lookupRefKey(key); + /* fails if this is not a SymmetricBinaryKey */ + SymmetricBinaryKey *symBinKey = + dynamic_cast(&binKey); + if(symBinKey == NULL) { + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY); + } + keyLen = symBinKey->mKeyData.Length; + keyBits = symBinKey->mKeyData.Data; + break; + } + default: + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_FORMAT); + } + return; +} + +AppleKeyPairGenContext::~AppleKeyPairGenContext() +{ /* virtual */ } + +// Called from subclass after it allocates its BinaryKeys. +// Caller frees BinaryKeys if we throw any exception. +void AppleKeyPairGenContext::generate( + const Context &context, + AppleCSPSession &session, + CssmKey &pubKey, + BinaryKey *pubBinKey, + CssmKey &privKey, + BinaryKey *privBinKey) +{ + uint32 keySize; + cspKeyStorage privStorage; + cspKeyStorage pubStorage; + CssmKey::Header &pubHdr = pubKey.header(); + CssmKey::Header &privHdr = privKey.header(); + + // validate context and key header args + pubStorage = cspParseKeyAttr(CKT_Public, pubHdr.KeyAttr); + privStorage = cspParseKeyAttr(CKT_Private, privHdr.KeyAttr); + cspValidateKeyUsageBits(CKT_Public, pubHdr.KeyUsage); + cspValidateKeyUsageBits(CKT_Private, privHdr.KeyUsage); + + // have subclass generate the key pairs in the form of + // its native BinaryKeys + generate(context, *pubBinKey, *privBinKey, keySize); + + // FIXME - Any other header setup? + pubHdr.LogicalKeySizeInBits = + privHdr.LogicalKeySizeInBits = keySize; + pubHdr.KeyAttr &= ~KEY_ATTR_RETURN_MASK; + privHdr.KeyAttr &= ~KEY_ATTR_RETURN_MASK; + + // Handle key formatting. Delete the BinaryKeys if + // we're not creating ref keys, after safe completion of + // generateKeyBlob (which may throw, in which case the binary keys + // get deleted by our caller). + CSSM_KEYATTR_FLAGS attrFlags = 0; + switch(pubStorage) { + case CKS_Ref: + session.addRefKey(*pubBinKey, pubKey); + break; + case CKS_Data: + pubHdr.Format = requestedKeyFormat(context, pubKey); + pubBinKey->mKeyHeader = pubHdr; + pubBinKey->generateKeyBlob( + session.normAlloc(), // alloc in user space + CssmData::overlay(pubKey.KeyData), + pubHdr.Format, + session, + NULL, // no paramKey here! + attrFlags); + break; + case CKS_None: + break; + } + switch(privStorage) { + case CKS_Ref: + session.addRefKey(*privBinKey, privKey); + break; + case CKS_Data: + privHdr.Format = requestedKeyFormat(context, privKey); + privBinKey->mKeyHeader = privHdr; + privBinKey->generateKeyBlob( + session.normAlloc(), // alloc in user space + CssmData::overlay(privKey.KeyData), + privHdr.Format, + session, + NULL, + attrFlags); + break; + case CKS_None: + break; + } + if(pubStorage != CKS_Ref) { + delete pubBinKey; + } + if(privStorage != CKS_Ref) { + delete privBinKey; + } +} + +/* + * Called from subclass's generate method. Subclass is also a + * AppleCSPContext. + */ +void AppleSymmKeyGenContext::generateSymKey( + const Context &context, + AppleCSPSession &session, // for ref keys + CssmKey &cssmKey) // RETURNED +{ + /* there really is no legal way this should throw... */ + uint32 reqKeySize = context.getInt( + CSSM_ATTRIBUTE_KEY_LENGTH, + CSSMERR_CSP_MISSING_ATTR_KEY_LENGTH); + if((reqKeySize < minSizeInBits) || + (reqKeySize > maxSizeInBits)) { + CssmError::throwMe(CSSMERR_CSP_UNSUPPORTED_KEY_SIZE); + } + if(mustBeByteSized) { + if((reqKeySize & 0x7) != 0) { + CssmError::throwMe(CSSMERR_CSP_UNSUPPORTED_KEY_SIZE); + } + } + + // validate KeyAtrr and KeyUsage already present in header + cspKeyStorage keyStorage; + CssmKey::Header &hdr = cssmKey.header(); + + keyStorage = cspParseKeyAttr(CKT_Session, hdr.KeyAttr); + cspValidateKeyUsageBits(CKT_Session, hdr.KeyUsage); + hdr.KeyAttr &= ~KEY_ATTR_RETURN_MASK; + + hdr.LogicalKeySizeInBits = reqKeySize; + uint32 keySizeInBytes = (reqKeySize + 7) / 8; + SymmetricBinaryKey *binKey = NULL; + CssmData *keyData = NULL; + + switch(keyStorage) { + case CKS_None: + /* no way */ + CssmError::throwMe(CSSMERR_CSP_INVALID_KEYATTR_MASK); + case CKS_Ref: + /* cook up a symmetric binary key */ + binKey = new SymmetricBinaryKey(reqKeySize); + keyData = &binKey->mKeyData; + break; + case CKS_Data: + /* key bytes --> caller's cssmKey */ + keyData = &(CssmData::overlay(cssmKey.KeyData)); + setUpCssmData(*keyData, keySizeInBytes, + session.normAlloc()); + break; + } + + // in any case, fill key bytes with random data + session.getRandomBytes(keySizeInBytes, keyData->Data); + + if(keyStorage == CKS_Ref) { + session.addRefKey(*binKey, cssmKey); + } + else { + /* Raw data */ + hdr.BlobType = CSSM_KEYBLOB_RAW; + hdr.Format = CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING; + } + + // FIXME - any other header fields? +} + +// +// Symmetric Binary Key support +// +SymmetricBinaryKey::SymmetricBinaryKey( + unsigned keySizeInBits) : + mAllocator(Allocator::standard(Allocator::sensitive)) +{ + setUpCssmData(mKeyData, (keySizeInBits + 7) / 8, mAllocator); +} + +SymmetricBinaryKey::~SymmetricBinaryKey() +{ + freeCssmData(mKeyData, mAllocator); +} + +void SymmetricBinaryKey::generateKeyBlob( + Allocator &allocator, + CssmData &blob, + CSSM_KEYBLOB_FORMAT &format, // CSSM_KEYBLOB_RAW_FORMAT_PKCS1, etc. + AppleCSPSession &session, + const CssmKey *paramKey, /* optional, unused here */ + CSSM_KEYATTR_FLAGS &attrFlags) /* IN/OUT */ +{ + switch(format) { + case CSSM_KEYBLOB_RAW_FORMAT_NONE: // default + case CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING: // the one we can do + case CSSM_KEYBLOB_RAW_FORMAT_DIGEST: // same thing + break; + default: + CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_SYMMETRIC_KEY_FORMAT); + } + copyCssmData(mKeyData, blob, allocator); + format = CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING; +} + diff --git a/libsecurity_apple_csp/lib/AppleCSPContext.h b/libsecurity_apple_csp/lib/AppleCSPContext.h new file mode 100644 index 00000000..ad7b3739 --- /dev/null +++ b/libsecurity_apple_csp/lib/AppleCSPContext.h @@ -0,0 +1,181 @@ +/* + * 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. + */ + + +// +// AppleCSPContext.h - CSP-wide contexts +// +#ifndef _H_APPLE_CSP_CONTEXT +#define _H_APPLE_CSP_CONTEXT + +#include +#include "BinaryKey.h" + +// +// Parent class for all CSPContexts implemented in this CSP. +// Currently the only thing we add is a reference to our +// creator's session. +// +class AppleCSPSession; + +class AppleCSPContext : public CSPFullPluginSession::CSPContext +{ +public: + AppleCSPContext(AppleCSPSession &session) + : mSession(session) {} + + ~AppleCSPContext(); + + /* + * get symmetric key bits - context.key can be either ref or raw. + * A convenience routine typically used by symmetric contexts' + * init() routines. + */ + static void symmetricKeyBits( + const Context &context, + AppleCSPSession &session, + CSSM_ALGORITHMS requiredAlg, // throws if this doesn't match key alg + CSSM_KEYUSE intendedUse, // throws if key usage doesn't match this + uint8 *&keyBits, // RETURNED (not mallocd or copied) + CSSM_SIZE &keyLen); // RETURNED + +protected: + AppleCSPSession &session() { return mSession; } + +private: + AppleCSPSession &mSession; +}; + +// +// Context for CSSM_ALGID_APPLE_YARROW. +// +class YarrowContext : public AppleCSPContext +{ +public: + YarrowContext(AppleCSPSession &session); + virtual ~YarrowContext(); + virtual void init(const Context &context, bool encoding = true); + void final(CssmData &out); + size_t outputSize(bool final, size_t inSize) { return outSize; } + +private: + uint32 outSize; +}; + +// +// Classes which inherit from AppleCSPContext and which also perform +// key pair generation inherit from this class as well. +// +class AppleKeyPairGenContext { +public: + virtual ~AppleKeyPairGenContext(); + + // + // Subclass implements generate(const Context &, CssmKey &, + // CssmKey &). That method (called from CSPFullPluginSession) + // allocates two subclass-specific BinaryKeys and calls this + // method. This will eventually call down to generate(const Context &, + // BinaryKey &, BinaryKey &) and optionally to + // BinaryKey::generateKeyBlob. + // + void generate( + const Context &context, + AppleCSPSession &session, // for ref keys + CssmKey &pubKey, + BinaryKey *pubBinKey, + CssmKey &privKey, + BinaryKey *privBinKey); + +protected: + // Subclasses must implement this. It cooks up a key pair. + virtual void generate( + const Context &context, + BinaryKey &pubBinKey, // valid on successful return + BinaryKey &privBinKey, // ditto + uint32 &keySize) = 0; // ditto +}; + +// +// Classes which inherit from AppleCSPContext and which also perform +// symmetric key generation inherit from this class as well. +// +class AppleSymmKeyGenContext { +public: + // + // Subclass implements generate(const Context &, CssmKey &, + // CssmKey &). Note that the second CssmKey is a dummy + // argument. That method merely calls generateSymKey, allowing us + // to get to the associated AppleCSPSession if we need to + // store reference keys. We take care of all attribute and + // usage validation and of header formatting. Parameters for + // validation typlically specified in constructor via an + // algorithm factory. + // + AppleSymmKeyGenContext( + uint32 minSize, // in bits + uint32 maxSize, // ditto + bool byteSized) // true --> key size must + // be multiple of 8 bits + : minSizeInBits(minSize), + maxSizeInBits(maxSize), + mustBeByteSized(byteSized) {} + + void generateSymKey( + const Context &context, + AppleCSPSession &session, // for ref keys + CssmKey &cssmKey); // RETURNED + +private: + uint32 minSizeInBits; + uint32 maxSizeInBits; + bool mustBeByteSized; + +}; + +/* + * Generic symmetric key generation context, for algorithms whose + * requirements can be expressed in min/max key size and + * mustBeByteSized. Such algorithms just need create one of these + * from an algorithm factory. + */ +class AppleSymmKeyGenerator : public AppleCSPContext, private AppleSymmKeyGenContext { +public: + AppleSymmKeyGenerator( + AppleCSPSession &session, + uint32 minSize, // in bits + uint32 maxSize, // ditto + bool byteSized) : // true --> key size must + // be multiple of 8 bits + AppleCSPContext(session), + AppleSymmKeyGenContext(minSize, maxSize, byteSized) { } + + void init(const Context &context, bool encoding = true) { } + + /* this just passes the request up to AppleSymmKeyGenContext */ + void generate( + const Context &context, + CssmKey &symKey, + CssmKey &dummyKey) { + AppleSymmKeyGenContext::generateSymKey( + context, + session(), + symKey); + } + +}; + +#endif /* _H_APPLE_CSP_CONTEXT */ diff --git a/libsecurity_apple_csp/lib/AppleCSPKeys.cpp b/libsecurity_apple_csp/lib/AppleCSPKeys.cpp new file mode 100644 index 00000000..d1143ad1 --- /dev/null +++ b/libsecurity_apple_csp/lib/AppleCSPKeys.cpp @@ -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. + */ +/* + * AppleCSPKeys.cpp - Key support + */ + +#include "AppleCSPKeys.h" +#include "AppleCSPUtils.h" +/* + * CSPKeyInfoProvider for symmetric keys. + */ +CSPKeyInfoProvider *SymmetricKeyInfoProvider::provider( + const CssmKey &cssmKey, + AppleCSPSession &session) +{ + if(cssmKey.blobType() != CSSM_KEYBLOB_RAW) { + errorLog0("KeyInfoProvider deals only with RAW keys!\n"); + CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR); + } + if(cssmKey.keyClass() != CSSM_KEYCLASS_SESSION_KEY) { + /* that's all we need to know */ + return NULL; + } + return new SymmetricKeyInfoProvider(cssmKey, session); +} + +SymmetricKeyInfoProvider::SymmetricKeyInfoProvider( + const CssmKey &cssmKey, + AppleCSPSession &session) : + CSPKeyInfoProvider(cssmKey, session) +{ +} + +/* cook up a Binary key */ +void SymmetricKeyInfoProvider::CssmKeyToBinary( + CssmKey *paramKey, // ignored + CSSM_KEYATTR_FLAGS &attrFlags, // IN/OUT + BinaryKey **binKey) +{ + CASSERT(mKey.keyClass() == CSSM_KEYCLASS_SESSION_KEY); + SymmetricBinaryKey *symBinKey = new SymmetricBinaryKey( + mKey.KeyHeader.LogicalKeySizeInBits); + copyCssmData(mKey, + symBinKey->mKeyData, + symBinKey->mAllocator); + *binKey = symBinKey; +} + +/* obtain key size in bits */ +void SymmetricKeyInfoProvider::QueryKeySizeInBits( + CSSM_KEY_SIZE &keySize) +{ + /* FIXME - do we ever need to calculate RC2 effective size here? */ + keySize.LogicalKeySizeInBits = keySize.EffectiveKeySizeInBits = + mKey.length() * 8; +} + +/* + * Obtain blob suitable for hashing in CSSM_APPLECSP_KEYDIGEST + * passthrough. + */ +bool SymmetricKeyInfoProvider::getHashableBlob( + Allocator &allocator, + CssmData &blob) // blob to hash goes here +{ + /* + * This is trivial: the raw key is already in the "proper" format. + */ + assert(mKey.blobType() == CSSM_KEYBLOB_RAW); + const CssmData &keyBlob = CssmData::overlay(mKey.KeyData); + copyCssmData(keyBlob, blob, allocator); + return true; +} + diff --git a/libsecurity_apple_csp/lib/AppleCSPKeys.h b/libsecurity_apple_csp/lib/AppleCSPKeys.h new file mode 100644 index 00000000..2fdc407e --- /dev/null +++ b/libsecurity_apple_csp/lib/AppleCSPKeys.h @@ -0,0 +1,118 @@ +/* + * 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. + */ +/* + * AppleCSPKeys.h - Key support + */ + +#ifndef _APPLE_CSP_KEYS_H_ +#define _APPLE_CSP_KEYS_H_ + +#include "AppleCSPSession.h" + +/* + * Class to provide key-specific info. Each module dealing with keys + * implements one of these. It's sort of like a CSP-specific CSPContext + * without the Context object. AppleCSPSession finds one of these by + * querying module-specific subclasses, looking for one in which + * the constructor succeeds (which occurs when the specified key + * meets a subclass's specification). + */ +class CSPKeyInfoProvider +{ +protected: + CSPKeyInfoProvider( + const CssmKey &cssmKey, + AppleCSPSession &session) : + mKey(cssmKey), + mSession(session) { } +public: + /* + * This is the public way to construct - returns NULL if key is + * not handled. Static declaration per subclass. + * + * static CSPKeyInfoProvider *provider( + * const CssmKey &cssmKey, + *  AppleCSPSession &session); + */ + virtual ~CSPKeyInfoProvider() { } + + /* + * Cook up a Binary key. + * + * Incoming paramKey optionally contains a key from which + * additional algorithm parameters may be obtained to create + * a fully specified key in case the key provided to our + * constructor was a partial key. + * + * The attrFlags argument is a means for the info provider to + * inform the caller that the incoming key has additional + * attributes, currently CSSM_KEYATTR_PARTIAL. The provider + * ORs in bits as appropriate. + */ + virtual void CssmKeyToBinary( + CssmKey *paramKey, // optional + CSSM_KEYATTR_FLAGS &attrFlags, // IN/OUT + BinaryKey **binKey) = 0; // RETURNED + + /* obtain key size in bits */ + virtual void QueryKeySizeInBits( + CSSM_KEY_SIZE &keySize) = 0; // RETURNED + + /* + * Get blob appropriate for calculating key digest, if possible + * to do without generating a BinaryKey. Returns true if + * successful, falseif BinaryKey generation is required. + */ + virtual bool getHashableBlob( + Allocator &allocator, + CssmData &hashBlob) = 0; // blob to hash goes here + +protected: + const CssmKey &mKey; + AppleCSPSession &mSession; +}; + +/* + * CSPKeyInfoProvider for symmetric keys (handled directly by + * the session). + */ +class SymmetricKeyInfoProvider : public CSPKeyInfoProvider +{ +private: + SymmetricKeyInfoProvider( + const CssmKey &cssmKey, + AppleCSPSession &session); +public: + static CSPKeyInfoProvider *provider( + const CssmKey &cssmKey, + AppleCSPSession &session); + + ~SymmetricKeyInfoProvider() { } + void CssmKeyToBinary( + CssmKey *paramKey, // ignored + CSSM_KEYATTR_FLAGS &attrFlags, // IN/OUT + BinaryKey **binKey); // RETURNED + void QueryKeySizeInBits( + CSSM_KEY_SIZE &keySize); // RETURNED + bool getHashableBlob( + Allocator &allocator, + CssmData &hashBlob); +}; + +#endif /* _APPLE_CSP_KEYS_H_ */ + diff --git a/libsecurity_apple_csp/lib/AppleCSPPlugin.cpp b/libsecurity_apple_csp/lib/AppleCSPPlugin.cpp new file mode 100644 index 00000000..cc8d5414 --- /dev/null +++ b/libsecurity_apple_csp/lib/AppleCSPPlugin.cpp @@ -0,0 +1,31 @@ +/* + * 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 obtai +n + * 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. + */ + + +// +// Produce the "genuine plugin version" of the AppleCSP +// +#include + + +// +// Create the plugin object and generate the C layer hookup +// +ModuleNexus plugin; + +#include diff --git a/libsecurity_apple_csp/lib/AppleCSPSession.h b/libsecurity_apple_csp/lib/AppleCSPSession.h new file mode 100644 index 00000000..56ef2c14 --- /dev/null +++ b/libsecurity_apple_csp/lib/AppleCSPSession.h @@ -0,0 +1,238 @@ +/* + * 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. + */ + + +// +// AppleCSPSession.h - top-level session class +// +#ifndef _APPLE_CSP_SESSION_H_ +#define _APPLE_CSP_SESSION_H_ + +#include +#include +#include +#include +#include "BinaryKey.h" +#include "AppleCSPUtils.h" + +class CSPKeyInfoProvider; + +/* avoid unnecessary includes.... */ +class AppleCSPPlugin; +#ifdef BSAFE_CSP_ENABLE +class BSafeFactory; +#endif +#ifdef CRYPTKIT_CSP_ENABLE +class CryptKitFactory; +#endif +class MiscAlgFactory; +#ifdef ASC_CSP_ENABLE +class AscAlgFactory; +#endif +class RSA_DSA_Factory; +class DH_Factory; + +/* one per attach/detach */ +class AppleCSPSession : public CSPFullPluginSession { +public: + + AppleCSPSession( + CSSM_MODULE_HANDLE handle, + AppleCSPPlugin &plug, + const CSSM_VERSION &Version, + uint32 SubserviceID, + CSSM_SERVICE_TYPE SubServiceType, + CSSM_ATTACH_FLAGS AttachFlags, + const CSSM_UPCALLS &upcalls); + + ~AppleCSPSession(); + + CSPContext *contextCreate( + CSSM_CC_HANDLE handle, + const Context &context); + void setupContext( + CSPContext * &cspCtx, + const Context &context, + bool encoding); + + // Functions declared in CSPFullPluginSession which we override. + + // Free a key. If this is a reference key + // we generated, remove it from refKeyMap. + void FreeKey(const AccessCredentials *AccessCred, + CssmKey &KeyPtr, + CSSM_BOOL Delete); + + void UnwrapKey(CSSM_CC_HANDLE CCHandle, + const Context &Context, + const CssmKey *PublicKey, + const CssmKey &WrappedKey, + uint32 KeyUsage, + uint32 KeyAttr, + const CssmData *KeyLabel, + const CSSM_RESOURCE_CONTROL_CONTEXT *CredAndAclEntry, + CssmKey &UnwrappedKey, + CssmData &DescriptiveData, + CSSM_PRIVILEGE Privilege); + void WrapKey(CSSM_CC_HANDLE CCHandle, + const Context &Context, + const AccessCredentials &AccessCred, + const CssmKey &Key, + const CssmData *DescriptiveData, + CssmKey &WrappedKey, + CSSM_PRIVILEGE Privilege); + void DeriveKey(CSSM_CC_HANDLE CCHandle, + const Context &Context, + CssmData &Param, + uint32 KeyUsage, + uint32 KeyAttr, + const CssmData *KeyLabel, + const CSSM_RESOURCE_CONTROL_CONTEXT *CredAndAclEntry, + CssmKey &DerivedKey); + void PassThrough(CSSM_CC_HANDLE CCHandle, + const Context &Context, + uint32 PassThroughId, + const void *InData, + void **OutData); + void getKeySize(const CssmKey &key, + CSSM_KEY_SIZE &size); + + // add a BinaryKey to our refKeyMap. Sets up cssmKey + // as appropriate. + void addRefKey( + BinaryKey &binKey, + CssmKey &cssmKey); + + // Given a CssmKey in reference form, obtain the associated + // BinaryKey. + BinaryKey &lookupRefKey( + const CssmKey &cssmKey); + + // CSP's RNG. This redirects to Yarrow. + void getRandomBytes(size_t length, uint8 *cp); + void addEntropy(size_t length, const uint8 *cp); + + Allocator &normAlloc() { return normAllocator; } + Allocator &privAlloc() { return privAllocator; } + + #ifdef BSAFE_CSP_ENABLE + BSafeFactory &bSafe4Factory; + #endif + #ifdef CRYPTKIT_CSP_ENABLE + CryptKitFactory &cryptKitFactory; + #endif + MiscAlgFactory &miscAlgFactory; + #ifdef ASC_CSP_ENABLE + AscAlgFactory &ascAlgFactory; + #endif + RSA_DSA_Factory &rsaDsaAlgFactory; + DH_Factory &dhAlgFactory; + +private: + // storage of binary keys (which apps know as reference keys) + typedef std::map keyMap; + keyMap refKeyMap; + Mutex refKeyMapLock; + Allocator &normAllocator; + Allocator &privAllocator; + + BinaryKey *lookupKeyRef(KeyRef keyRef); + void DeriveKey_PBKDF2( + const Context &Context, + const CssmData &Param, + CSSM_DATA *keyData); + + void DeriveKey_PKCS5_V1_5( + const Context &context, + CSSM_ALGORITHMS algId, + const CssmData &Param, + CSSM_DATA *keyData); + + void DeriveKey_OpenSSH1( + const Context &context, + CSSM_ALGORITHMS algId, + const CssmData &Param, + CSSM_DATA *keyData); + + /* CMS wrap/unwrap, called out from standard wrap/unwrap */ + void WrapKeyCms( + CSSM_CC_HANDLE CCHandle, + const Context &Context, + const AccessCredentials &AccessCred, + const CssmKey &UnwrappedKey, + CssmData &rawBlob, + bool allocdRawBlob, // callee has to free rawBlob + const CssmData *DescriptiveData, + CssmKey &WrappedKey, + CSSM_PRIVILEGE Privilege); + + void UnwrapKeyCms( + CSSM_CC_HANDLE CCHandle, + const Context &Context, + const CssmKey &WrappedKey, + const CSSM_RESOURCE_CONTROL_CONTEXT *CredAndAclEntry, + CssmKey &UnwrappedKey, + CssmData &DescriptiveData, + CSSM_PRIVILEGE Privilege, + cspKeyStorage keyStorage); + + /* OpenSSHv1 wrap/unwrap, called out from standard wrap/unwrap */ + void WrapKeyOpenSSH1( + CSSM_CC_HANDLE CCHandle, + const Context &Context, + const AccessCredentials &AccessCred, + BinaryKey &unwrappedBinKey, + CssmData &rawBlob, + bool allocdRawBlob, // callee has to free rawBlob + const CssmData *DescriptiveData, + CssmKey &WrappedKey, + CSSM_PRIVILEGE Privilege); + + void UnwrapKeyOpenSSH1( + CSSM_CC_HANDLE CCHandle, + const Context &Context, + const CssmKey &WrappedKey, + const CSSM_RESOURCE_CONTROL_CONTEXT *CredAndAclEntry, + CssmKey &UnwrappedKey, + CssmData &DescriptiveData, + CSSM_PRIVILEGE Privilege, + cspKeyStorage keyStorage); + + /* + * Used for generating crypto contexts at this level. + * Analogous to AlgorithmFactory.setup(). + */ + bool setup( + CSPFullPluginSession::CSPContext * &cspCtx, + const Context &context); + + /* + * Find a CSPKeyInfoProvider subclass for the specified key. + */ + CSPKeyInfoProvider *infoProvider( + const CssmKey &key); + + void pkcs8InferKeyHeader( + CssmKey &key); + + void opensslInferKeyHeader( + CssmKey &key); + +}; /* AppleCSPSession */ + + +#endif //_APPLE_CSP_SESSION_H_ diff --git a/libsecurity_apple_csp/lib/AppleCSPUtils.cpp b/libsecurity_apple_csp/lib/AppleCSPUtils.cpp new file mode 100644 index 00000000..246bba25 --- /dev/null +++ b/libsecurity_apple_csp/lib/AppleCSPUtils.cpp @@ -0,0 +1,689 @@ +/* + * 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. + */ + + +// +// AppleCSPUtils.cpp - CSP-wide utility functions +// + +#include "AppleCSPUtils.h" +#include +#include +#include +#include +#include +#include +#include "RSA_DSA_keys.h" +#include + +/* + * Validate key attribute bits per specified key type. + * + * Used to check requested key attributes for new keys and for validating + * incoming existing keys. For checking key attributes for new keys, + * assumes that KEYATTR_RETURN_xxx bits have been checked elsewhere + * and stripped off before coming here. + */ +void cspValidateKeyAttr( + cspKeyType keyType, + uint32 keyAttr) +{ + uint32 sensitiveBit = (keyAttr & CSSM_KEYATTR_SENSITIVE) ? 1 : 0; + uint32 extractBit = (keyAttr & CSSM_KEYATTR_EXTRACTABLE) ? 1 : 0; + + /* first general CSP-wide checks */ + if(keyAttr & KEY_ATTR_RETURN_MASK) { + //errorLog0(" KEY_ATTR_RETURN bits set\n"); + CssmError::throwMe(CSSMERR_CSP_INVALID_KEYATTR_MASK); + } + if(keyAttr & CSSM_KEYATTR_PERMANENT) { + //errorLog0(" PERMANENT bit not supported\n"); + CssmError::throwMe(CSSMERR_CSP_UNSUPPORTED_KEYATTR_MASK); + } + if(keyAttr & CSSM_KEYATTR_PRIVATE) { + CssmError::throwMe(CSSMERR_CSP_UNSUPPORTED_KEYATTR_MASK); + } + /* Anything else? */ + + /* now check per keyType */ + switch(keyType) { + case CKT_Session: + break; + + case CKT_Public: + if(sensitiveBit || !extractBit) { + //errorLog0("Public keys must be extractable in the clear\n"); + CssmError::throwMe(CSSMERR_CSP_INVALID_KEYATTR_MASK); + } + break; + + case CKT_Private: + //if(!sensitiveBit) { + // errorLog0("Private keys must have KEYATTR_SENSITIVE\n"); + // CssmError::throwMe(CSSMERR_CSP_INVALID_KEYATTR_MASK); + //} + + /* + * One more restriction - EXTRACTABLE - caller must check since + * that involves KEYUSE bits. + */ + break; + default: + CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR); + } + return; +} + +/* + * Perform sanity check of incoming key attribute bits for a given + * key type, and return a cspKeyStorage value. + * + * Called from any routine which generates a new key. This specifically + * excludes WrapKey(). + */ +cspKeyStorage cspParseKeyAttr( + cspKeyType keyType, + uint32 keyAttr) +{ + uint32 sensitiveBit = (keyAttr & CSSM_KEYATTR_SENSITIVE) ? 1 : 0; + uint32 rtnDataBit = (keyAttr & CSSM_KEYATTR_RETURN_DATA) ? 1 : 0; + uint32 rtnRefBit = (keyAttr & CSSM_KEYATTR_RETURN_REF) ? 1 : 0; + uint32 extractBit = (keyAttr & CSSM_KEYATTR_EXTRACTABLE) ? 1 : 0; + + cspKeyStorage rtn; + + /* first general CDSA-wide checks */ + if(keyAttr & (CSSM_KEYATTR_ALWAYS_SENSITIVE | + CSSM_KEYATTR_NEVER_EXTRACTABLE)) { + //errorLog0("ALWAYS_SENSITIVE, NEVER_EXTRACTABLE illegal at SPI\n"); + CssmError::throwMe(CSSMERR_CSP_INVALID_KEYATTR_MASK); + } + switch(keyAttr & KEY_ATTR_RETURN_MASK) { + /* ensure only one bit is set */ + case CSSM_KEYATTR_RETURN_DATA: + rtn = CKS_Data; + break; + case CSSM_KEYATTR_RETURN_REF: + rtn = CKS_Ref; + break; + case CSSM_KEYATTR_RETURN_NONE: + rtn = CKS_None; + break; + case CSSM_KEYATTR_RETURN_DEFAULT: + /* CSP default */ + rtnRefBit = 1; + rtn = CKS_Ref; + break; + default: + //errorLog0("Multiple KEYATTR_RETURN bits set\n"); + CssmError::throwMe(CSSMERR_CSP_INVALID_KEYATTR_MASK); + } + + /* now CSP-wide checks for all key types */ + if(keyType != CKT_Session) { + /* session keys modifiable, no others are */ + if(keyAttr & CSSM_KEYATTR_MODIFIABLE) { + //errorLog0("CSSM_KEYATTR_MODIFIABLE not supported\n"); + CssmError::throwMe(CSSMERR_CSP_INVALID_KEYATTR_MASK); + } + } + if(rtnDataBit) { + if(!extractBit) { + //errorLog0("RETURN_DATA and !EXTRACTABLE not supported\n"); + CssmError::throwMe(CSSMERR_CSP_INVALID_KEYATTR_MASK); + } + if(sensitiveBit) { + //errorLog0("RETURN_DATA and SENSITIVE not supported\n"); + CssmError::throwMe(CSSMERR_CSP_INVALID_KEYATTR_MASK); + } + } + + /* now check per keyType. We're ust checking for things specific + * to KEYATTR_RETURN_xxx; cspValidateKeyAttr will check other fields. */ + #if 0 + // nothing for now + switch(keyType) { + case CKT_Session: + break; + + case MKT_Public: + break; + + case MKT_Private: + if(rtnDataBit) { + errorLog0("Private keys must be generated by ref\n"); + goto errorOut; + } + /* + * One more restriction - EXTRACTABLE - caller must check since + * that involves KEYUSE bits. + */ + break; + default: + CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR); + } + #endif // 0 + + /* validate other common static attributes */ + cspValidateKeyAttr(keyType, (keyAttr & ~KEY_ATTR_RETURN_MASK)); + return rtn; +} + + +/* used in cspValidateKeyUsageBits() */ +/* + * This is a vestige from OS9/ASA. In the real world there are in fact certs with + * keyUsage extensions which specify, e.g., verify and wrap. I think we'll just + * have to ignore the old exclusivity rules. + */ +#define IGNORE_KEYUSE_EXCLUSIVITY 1 +#if IGNORE_KEYUSE_EXCLUSIVITY +#define checkExclusiveUsage(ku, cb, ob, em) +#else +static void checkExclusiveUsage( + uint32 keyUsage, // requested usage word + uint32 checkBits, // if any of these are set + uint32 otherBits, // these are the only other bits which can be set + const char *errMsg) +{ + if(keyUsage & checkBits) { + if(keyUsage & ~otherBits) { + errorLog0((char *)errMsg); + CssmError::throwMe(CSSMERR_CSP_UNSUPPORTED_KEYUSAGE_MASK); + } + } +} +#endif /* IGNORE_KEYUSE_EXCLUSIVITY */ + +/* + * Validate key usage bits for specified key type. + */ +void cspValidateKeyUsageBits ( + cspKeyType keyType, + uint32 keyUsage) +{ + /* general restrictions */ + checkExclusiveUsage(keyUsage, + CSSM_KEYUSE_ANY, + CSSM_KEYUSE_ANY, + "CSSM_KEYUSE_ANY overload"); + checkExclusiveUsage(keyUsage, + CSSM_KEYUSE_DERIVE, + CSSM_KEYUSE_DERIVE, + "CSSM_KEYUSE_DERIVE overload\n"); + + /* brute force per key type. */ + switch(keyType) { + case CKT_Session: + checkExclusiveUsage(keyUsage, + CSSM_KEYUSE_ENCRYPT | CSSM_KEYUSE_DECRYPT, + CSSM_KEYUSE_ENCRYPT | CSSM_KEYUSE_DECRYPT, + "session key usage: encrypt/decrypt overload\n"); + checkExclusiveUsage(keyUsage, + CSSM_KEYUSE_SIGN | CSSM_KEYUSE_VERIFY | + CSSM_KEYUSE_SIGN_RECOVER | CSSM_KEYUSE_VERIFY_RECOVER, + CSSM_KEYUSE_SIGN | CSSM_KEYUSE_VERIFY | + CSSM_KEYUSE_SIGN_RECOVER | CSSM_KEYUSE_VERIFY_RECOVER, + "session key usage: sign/verify overload\n"); + checkExclusiveUsage(keyUsage, + CSSM_KEYUSE_WRAP | CSSM_KEYUSE_UNWRAP, + CSSM_KEYUSE_WRAP | CSSM_KEYUSE_UNWRAP, + "session key usage: wrap/unwrap overload\n"); + break; + + case CKT_Public: + checkExclusiveUsage(keyUsage, + CSSM_KEYUSE_ENCRYPT, + CSSM_KEYUSE_ENCRYPT, + "public key usage: encrypt overload\n"); + if(keyUsage & CSSM_KEYUSE_DECRYPT) { + errorLog0("public key usage: DECRYPT illegal\n"); + CssmError::throwMe(CSSMERR_CSP_UNSUPPORTED_KEYUSAGE_MASK); + } + if(keyUsage & (CSSM_KEYUSE_SIGN | CSSM_KEYUSE_SIGN_RECOVER)) { + errorLog0("public key usage: SIGN illegal\n"); + CssmError::throwMe(CSSMERR_CSP_UNSUPPORTED_KEYUSAGE_MASK); + } + checkExclusiveUsage(keyUsage, + CSSM_KEYUSE_VERIFY | CSSM_KEYUSE_VERIFY_RECOVER, + CSSM_KEYUSE_VERIFY | CSSM_KEYUSE_VERIFY_RECOVER, + "public key usage: verify overload\n"); + checkExclusiveUsage(keyUsage, + CSSM_KEYUSE_WRAP, + CSSM_KEYUSE_WRAP, + "public key usage: wrap overload\n"); + if(keyUsage & CSSM_KEYUSE_UNWRAP) { + errorLog0("public key usage: UNWRAP illegal\n"); + CssmError::throwMe(CSSMERR_CSP_UNSUPPORTED_KEYUSAGE_MASK); + } + break; + + case CKT_Private: + if(keyUsage & CSSM_KEYUSE_ENCRYPT) { + errorLog0("private key usage: ENCRYPT illegal\n"); + CssmError::throwMe(CSSMERR_CSP_UNSUPPORTED_KEYUSAGE_MASK); + } + checkExclusiveUsage(keyUsage, + CSSM_KEYUSE_DECRYPT, + CSSM_KEYUSE_DECRYPT, + "private key usage: decrypt overload\n"); + checkExclusiveUsage(keyUsage, + CSSM_KEYUSE_SIGN | CSSM_KEYUSE_SIGN_RECOVER, + CSSM_KEYUSE_SIGN | CSSM_KEYUSE_SIGN_RECOVER, + "private key usage: sign overload\n"); + if(keyUsage & (CSSM_KEYUSE_VERIFY | CSSM_KEYUSE_VERIFY_RECOVER)) { + errorLog0("private key usage: VERIFY illegal\n"); + CssmError::throwMe(CSSMERR_CSP_UNSUPPORTED_KEYUSAGE_MASK); + } + if(keyUsage & CSSM_KEYUSE_WRAP) { + errorLog0("private key usage: WRAP illegal\n"); + CssmError::throwMe(CSSMERR_CSP_UNSUPPORTED_KEYUSAGE_MASK); + } + checkExclusiveUsage(keyUsage, + CSSM_KEYUSE_UNWRAP, + CSSM_KEYUSE_UNWRAP, + "private key usage: unwrap overload\n"); + break; + default: + CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR); + } +} + +/* + * Validate existing key's usage bits against intended use. + */ + +/* + * For now, a key marked for KEYUSE_{WRAP|UNWRAP} can also be used for + * KEYUSE_{ENCRYPT|DECRYPT}. This is a temporary workaround for + * Radar 2716153. + */ +#define RELAXED_WRAP_USAGE 1 + +void cspValidateIntendedKeyUsage( + const CSSM_KEYHEADER *hdr, + CSSM_KEYUSE intendedUsage) +{ + uint32 keyUsage = hdr->KeyUsage; + cspKeyType keyType; + + /* first, the obvious */ + if(keyUsage & CSSM_KEYUSE_ANY) { + /* OK for now */ + return; + } + if(!(keyUsage & intendedUsage)) { + #if RELAXED_WRAP_USAGE + if(! ( ( (keyUsage & CSSM_KEYUSE_WRAP) && + (intendedUsage == CSSM_KEYUSE_ENCRYPT) + ) || + ( (keyUsage & CSSM_KEYUSE_UNWRAP) && + (intendedUsage == CSSM_KEYUSE_DECRYPT) + ) + ) ) + #endif + CssmError::throwMe(CSSMERR_CSP_KEY_USAGE_INCORRECT); + } + + /* now validate all of the key's usage bits - this is mainly to + * prevent and detect tampering */ + switch(hdr->KeyClass) { + case CSSM_KEYCLASS_SESSION_KEY: + keyType = CKT_Session; + break; + case CSSM_KEYCLASS_PUBLIC_KEY: + keyType = CKT_Public; + break; + case CSSM_KEYCLASS_PRIVATE_KEY: + keyType = CKT_Private; + break; + default: + CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR); + } + try { + cspValidateKeyUsageBits(keyType, keyUsage); + } + catch (...) { + /* override error.... */ + CssmError::throwMe(CSSMERR_CSP_KEY_USAGE_INCORRECT); + } +} + +/* + * Set up a key header. + */ +void setKeyHeader( + CSSM_KEYHEADER &hdr, + const Guid &myGuid, + CSSM_ALGORITHMS alg, + CSSM_KEYCLASS keyClass, + CSSM_KEYATTR_FLAGS attrs, + CSSM_KEYUSE use) +{ + memset(&hdr, 0, sizeof(CSSM_KEYHEADER)); + hdr.HeaderVersion = CSSM_KEYHEADER_VERSION; + hdr.CspId = myGuid; + hdr.AlgorithmId = alg; + hdr.KeyClass = keyClass; + hdr.KeyUsage = use; + hdr.KeyAttr = attrs; + + // defaults (change as needed) + hdr.WrapAlgorithmId = CSSM_ALGID_NONE; +} + +/* + * Ensure that indicated CssmData can handle 'length' bytes + * of data. Malloc the Data ptr if necessary. + */ +void setUpCssmData( + CssmData &data, + size_t length, + Allocator &allocator) +{ + /* FIXME - I'm sure Perry has more elegant ways of doing this, + * but I can't figure them out. */ + if(data.Length == 0) { + data.Data = (uint8 *)allocator.malloc(length); + } + else if(data.Length < length) { + CssmError::throwMe(CSSMERR_CSP_INVALID_DATA); + } + data.Length = length; +} + +void setUpData( + CSSM_DATA &data, + size_t length, + Allocator &allocator) +{ + setUpCssmData(CssmData::overlay(data), length, allocator); +} + +void freeCssmData( + CssmData &data, + Allocator &allocator) +{ + if(data.Data) { + allocator.free(data.Data); + data.Data = NULL; + } + data.Length = 0; +} + +void freeData( + CSSM_DATA *data, + Allocator &allocator, + bool freeStruct) // free the CSSM_DATA itself +{ + if(data == NULL) { + return; + } + if(data->Data) { + allocator.free(data->Data); + data->Data = NULL; + } + data->Length = 0; + if(freeStruct) { + allocator.free(data); + } +} + +/* + * Copy source to destination, mallocing destination if necessary. + */ +void copyCssmData( + const CssmData &src, + CssmData &dst, + Allocator &allocator) +{ + setUpCssmData(dst, src.Length, allocator); + memmove(dst.Data, src.Data, src.Length); +} + +void copyData( + const CSSM_DATA &src, + CSSM_DATA &dst, + Allocator &allocator) +{ + copyCssmData(CssmData::overlay(src), + CssmData::overlay(dst), + allocator); +} + +/* + * Compare two CSSM_DATAs, return CSSM_TRUE if identical. + */ +CSSM_BOOL cspCompareCssmData( + const CSSM_DATA *data1, + const CSSM_DATA *data2) +{ + if((data1 == NULL) || (data1->Data == NULL) || + (data2 == NULL) || (data2->Data == NULL) || + (data1->Length != data2->Length)) { + return CSSM_FALSE; + } + if(data1->Length != data2->Length) { + return CSSM_FALSE; + } + if(memcmp(data1->Data, data2->Data, data1->Length) == 0) { + return CSSM_TRUE; + } + else { + return CSSM_FALSE; + } +} + +/* + * This takes care of mallocing the KeyLabel field. + */ +void copyCssmHeader( + const CssmKey::Header &src, + CssmKey::Header &dst, + Allocator &allocator) +{ + dst = src; +} + +/* + * Given a wrapped key, infer its raw format for custom Apple unwrapping. + * This is a real kludge; it only works as long as each the key's + * default format is used to generate the blob to be wrapped. + */ +CSSM_KEYBLOB_FORMAT inferFormat( + const CssmKey &wrappedKey) +{ + switch(wrappedKey.keyClass()) { + case CSSM_KEYCLASS_SESSION_KEY: + return CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING; + case CSSM_KEYCLASS_PUBLIC_KEY: + switch(wrappedKey.algorithm()) { + case CSSM_ALGID_RSA: + return RSA_PUB_KEY_FORMAT; + case CSSM_ALGID_DSA: + return DSA_PUB_KEY_FORMAT; + #ifdef CRYPTKIT_CSP_ENABLE + case CSSM_ALGID_FEE: + return FEE_KEYBLOB_DEFAULT_FORMAT; + case CSSM_ALGID_ECDSA: + return CSSM_KEYBLOB_RAW_FORMAT_X509; + #endif + case CSSM_ALGID_DH: + return CSSM_KEYBLOB_RAW_FORMAT_PKCS3; + default: + /* punt */ + return CSSM_KEYBLOB_RAW_FORMAT_NONE; + } + case CSSM_KEYCLASS_PRIVATE_KEY: + switch(wrappedKey.algorithm()) { + case CSSM_ALGID_RSA: + return RSA_PRIV_KEY_FORMAT; + case CSSM_ALGID_DSA: + return DSA_PRIV_KEY_FORMAT; + #ifdef CRYPTKIT_CSP_ENABLE + case CSSM_ALGID_FEE: + return FEE_KEYBLOB_DEFAULT_FORMAT; + case CSSM_ALGID_ECDSA: + return CSSM_KEYBLOB_RAW_FORMAT_OPENSSL; + #endif + case CSSM_ALGID_DH: + return CSSM_KEYBLOB_RAW_FORMAT_PKCS3; + default: + /* punt */ + return CSSM_KEYBLOB_RAW_FORMAT_NONE; + } + default: + /* punt */ + return CSSM_KEYBLOB_RAW_FORMAT_NONE; + } +} + +/* + * Given a key and a Context, obtain the optional associated + * CSSM_ATTRIBUTE_{PUBLIC,PRIVATE,SYMMETRIC}_KEY_FORMAT attribute as a + * CSSM_KEYBLOB_FORMAT. + */ +CSSM_KEYBLOB_FORMAT requestedKeyFormat( + const Context &context, + const CssmKey &key) +{ + CSSM_ATTRIBUTE_TYPE attrType; + + switch(key.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: + return CSSM_KEYBLOB_RAW_FORMAT_NONE; + } + /* not present ==> 0 ==> CSSM_KEYBLOB_RAW_FORMAT_NONE */ + return context.getInt(attrType); +} + +/* one-shot SHA1 digest */ +void cspGenSha1Hash( + const void *inData, + size_t inDataLen, + void *out) // caller mallocs, digest goes here +{ + SHA1Object sha1; + + sha1.digestInit(); + sha1.digestUpdate(inData, inDataLen); + sha1.digestFinal(out); +} + +/* + * Convert a CSSM_DATE to a CssmUniformDate, or NULL if the CSSM_DATE + * is empty. + */ +static CssmUniformDate *cspGetUniformDate( + const CSSM_DATE &cdate) +{ + bool isZero = true; + unsigned char *cp = (unsigned char *)&cdate; + for(unsigned i=0; i *end) { + keyDateDebug("Invalid end date"); + err = CSSMERR_CSP_APPLE_INVALID_KEY_END_DATE; + } + else { + keyDateDebug("Valid end date"); + } + } + else { + keyDateDebug("Empty end date"); + } + } + if(now) { + delete now; + } + if(end) { + delete end; + } + if(start) { + delete start; + } + if(err) { + CssmError::throwMe(err); + } +} + diff --git a/libsecurity_apple_csp/lib/AppleCSPUtils.h b/libsecurity_apple_csp/lib/AppleCSPUtils.h new file mode 100644 index 00000000..2ddadac0 --- /dev/null +++ b/libsecurity_apple_csp/lib/AppleCSPUtils.h @@ -0,0 +1,184 @@ +/* + * 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. + */ + + +// +// AppleCSPUtils.h - CSP-wide utility functions +// + +#ifndef _H_APPLE_CSP_UTILS +#define _H_APPLE_CSP_UTILS + +#include "cspdebugging.h" +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Key type */ +typedef enum { + CKT_Session, + CKT_Private, + CKT_Public +} cspKeyType; + +/* Key storage type returned from cspParseKeyAttr() */ +typedef enum { + CKS_Ref, + CKS_Data, + CKS_None +} cspKeyStorage; + +#define KEY_ATTR_RETURN_MASK (CSSM_KEYATTR_RETURN_DATA | \ + CSSM_KEYATTR_RETURN_REF | \ + CSSM_KEYATTR_RETURN_NONE) + +/* + * Validate key attribute bits per specified key type. + * + * Used to check requested key attributes for new keys and for validating + * incoming existing keys. For checking key attributes for new keys, + * assumes that KEYATTR_RETURN_xxx bits have been checked elsewhere + * and stripped off before coming here. + */ +void cspValidateKeyAttr( + cspKeyType keyType, + uint32 keyAttr); + +/* + * Perform sanity check of incoming key attribute bits for a given + * key type, and return a malKeyStorage value. + * + * Called from any routine which generates a new key. This specifically + * excludes WrapKey(). + */ +cspKeyStorage cspParseKeyAttr( + cspKeyType keyType, + uint32 keyAttr); + +/* + * Validate key usage bits for specified key type. + */ +void cspValidateKeyUsageBits ( + cspKeyType keyType, + uint32 keyUsage); + +/* + * Validate existing key's usage bits against intended use. + */ +void cspValidateIntendedKeyUsage( + const CSSM_KEYHEADER *hdr, + CSSM_KEYUSE intendedUsage); + +/* + * Set up a key header. + */ +void setKeyHeader( + CSSM_KEYHEADER &hdr, + const Guid &myGuid, + CSSM_ALGORITHMS alg, + CSSM_KEYCLASS keyClass, + CSSM_KEYATTR_FLAGS attrs, + CSSM_KEYUSE use); + +/* + * Ensure that indicated CssmData can handle 'length' bytes + * of data. Malloc the Data ptr if necessary. + */ +void setUpCssmData( + CssmData &data, + size_t length, + Allocator &allocator); + +void setUpData( + CSSM_DATA &data, + size_t length, + Allocator &allocator); + +void freeCssmData( + CssmData &data, + Allocator &allocator); + +void freeData( + CSSM_DATA *data, + Allocator &allocator, + bool freeStruct); // free the CSSM_DATA itself + +/* + * Copy source to destination, mallocing destination if necessary. + */ +void copyCssmData( + const CssmData &src, + CssmData &dst, + Allocator &allocator); + +void copyData( + const CSSM_DATA &src, + CSSM_DATA &dst, + Allocator &allocator); + +/* + * Compare two CSSM_DATAs, return CSSM_TRUE if identical. + */ +CSSM_BOOL cspCompareCssmData( + const CSSM_DATA *data1, + const CSSM_DATA *data2); + +/* + * This takes care of mallocing the and KeyLabel field. + */ +void copyCssmHeader( + const CssmKey::Header &src, + CssmKey::Header &dst, + Allocator &allocator); + +/* + * Given a wrapped key, infer its raw format. + * This is a real kludge; it only works as long as each {algorithm, keyClass} + * maps to exactly one format. + */ +CSSM_KEYBLOB_FORMAT inferFormat( + const CssmKey &wrappedKey); + +/* + * Given a key and a Context, obtain the optional associated + * CSSM_ATTRIBUTE_{PUBLIC,PRIVATE,SYMMETRIC}_KEY_FORMAT attribute as a + * CSSM_KEYBLOB_FORMAT. + */ +CSSM_KEYBLOB_FORMAT requestedKeyFormat( + const Context &context, + const CssmKey &key); + +/* stateless function to calculate SHA-1 hash of a blob */ + +#define SHA1_DIGEST_SIZE 20 +void cspGenSha1Hash( + const void *inData, + size_t inDataLen, + void *out); // caller mallocs, digest goes here + +void cspVerifyKeyTimes( + const CSSM_KEYHEADER &hdr); + +#ifdef __cplusplus +} +#endif + +#endif // _H_APPLE_CSP_UTILS diff --git a/libsecurity_apple_csp/lib/BinaryKey.h b/libsecurity_apple_csp/lib/BinaryKey.h new file mode 100644 index 00000000..36055b9a --- /dev/null +++ b/libsecurity_apple_csp/lib/BinaryKey.h @@ -0,0 +1,124 @@ +/* + * 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. + */ + + +// +// BinaryKey.h - CSP-wide BinaryKey base class +// + +#ifndef _H_BINARY_KEY_ +#define _H_BINARY_KEY_ + +#include +#include + +// opaque key reference type +typedef CSSM_INTPTR KeyRef; + +class AppleCSPSession; + +/* + * unique blob type passed to generateKeyBlob() for key digest calculation + */ +#define CSSM_KEYBLOB_RAW_FORMAT_DIGEST \ + (CSSM_KEYBLOB_RAW_FORMAT_VENDOR_DEFINED + 0x12345) + + +// frame for Binary key; all modules (BSAFE, CryptKit) must subclass +// this and add a member whose type is the native raw key object. +// Subclasses must implement constructor, destructor, and generateKeyBlob(). +class BinaryKey +{ +public: + BinaryKey() : mKeyRef(0), mDescData(Allocator::standard()) { } + virtual ~BinaryKey() { mKeyRef = 0; } + + /* + * Generate raw key blob. + * The format argument is an in/out parameter and is optionally used + * to request a specific keyblob format for providers which can generate + * multipleÊformats. This value comes from an optional + * CSSM_ATTRIBUTE_{PUBLIC,PRIVATE,SYMMETRIC}_KEY_FORMAT attribute in the current + * context. If so such attribute is present, the default value + * CSSM_KEYBLOB_RAW_FORMAT_NONE is specified as the default input param. + * + * All BinaryKeys must handle the special case format + * CSSM_KEYBLOB_RAW_FORMAT_DIGEST, which creates a blob suitable for use + * in calcuating the digest of the key blob. + * + * The session and paramKey arguments facilitate the conversion of a partial + * BinaryKey to a fully formed raw key, i.e., a null wrap to get a fully formed + * raw key. The attrFlags aregument is used to indicate that this operation + * did in fact convert a partial binary key to a fully formed raw key + * (in which case the subclass clears the CSSM_KEYATTR_PARTIAL bit + * in attrFlags before returning). + */ + virtual void generateKeyBlob( + Allocator &allocator, + CssmData &blob, + CSSM_KEYBLOB_FORMAT &format, // in/out, CSSM_KEYBLOB_RAW_FORMAT_PKCS1, + // etc. + AppleCSPSession &session, + const CssmKey *paramKey, // optional + CSSM_KEYATTR_FLAGS &attrFlags) // IN/OUT + + { + CssmError::throwMe(CSSMERR_CSP_FUNCTION_NOT_IMPLEMENTED); + } + + CssmKey::Header mKeyHeader; + KeyRef mKeyRef; + const CssmData &descData() { return mDescData; } + void descData(const CssmData &inDescData) + { mDescData.copy(inDescData); } + +private: + /* optional DescriptiveData specified by app during WrapKey */ + CssmAutoData mDescData; +}; + +// Binary key representing a symmetric key. +class SymmetricBinaryKey : public BinaryKey +{ +public: + SymmetricBinaryKey( + unsigned keySizeInBits); + ~SymmetricBinaryKey(); + void generateKeyBlob( + Allocator &allocator, + CssmData &blob, + CSSM_KEYBLOB_FORMAT &format, /* CSSM_KEYBLOB_RAW_FORMAT_PKCS1, etc. */ + AppleCSPSession &session, + const CssmKey *paramKey, /* optional, unused here */ + CSSM_KEYATTR_FLAGS &attrFlags); /* IN/OUT */ + + CssmData mKeyData; + Allocator &mAllocator; +}; + +/* + * Stateless function to cook up a BinaryKey given a + * symmetric CssmKey in RAW format. Returns true on + * success, false if we can't deal with this type of key, + * throws exception on other runtime errors. + */ +bool symmetricCssmKeyToBinary( + const CssmKey &cssmKey, + BinaryKey **binKey); // RETURNED + +#endif // _H_BINARY_KEY_ + diff --git a/libsecurity_apple_csp/lib/BlockCryptor.cpp b/libsecurity_apple_csp/lib/BlockCryptor.cpp new file mode 100644 index 00000000..85d3bbbd --- /dev/null +++ b/libsecurity_apple_csp/lib/BlockCryptor.cpp @@ -0,0 +1,636 @@ +/* + * 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. + */ + + +/* + * BlockCryptor.cpp - common context for block-oriented encryption algorithms + * + * Created March 5 2001 by dmitch + */ + +#include "BlockCryptor.h" +#include "BinaryKey.h" +#include "AppleCSPSession.h" +#include +#include +#include +#include +#include + +#define BlockCryptDebug(args...) secdebug("blockCrypt", ## args) +#define bprintf(args...) secdebug("blockCryptBuf", ## args) +#define ioprintf(args...) secdebug("blockCryptIo", ## args) + +BlockCryptor::~BlockCryptor() +{ + if(mInBuf) { + memset(mInBuf, 0, mInBlockSize); + session().free(mInBuf); + mInBuf = NULL; + } + if(mChainBuf) { + memset(mChainBuf, 0, mInBlockSize); + session().free(mChainBuf); + mChainBuf = NULL; + } + mInBufSize = 0; +} + +/* + * Reusable setup functions called from subclass's init. + * This is the general purpose one.... + */ +void BlockCryptor::setup( + size_t blockSizeIn, // block size of input + size_t blockSizeOut, // block size of output + bool pkcsPad, // this class performs PKCS{5,7} padding + bool needsFinal, // needs final update with valid data + BC_Mode mode, // ECB, CBC + const CssmData *iv) // init vector, required for CBC + //Ê must be at least blockSizeIn bytes +{ + if(pkcsPad && needsFinal) { + BlockCryptDebug("BlockCryptor::setup pkcsPad && needsFinal"); + CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR); + } + mPkcsPadding = pkcsPad; + mMode = mode; + mNeedFinalData = needsFinal; + + /* set up inBuf, all configurations */ + if(mInBuf != NULL) { + /* only reuse if same size */ + if(mInBlockSize != blockSizeIn) { + session().free(mInBuf); + mInBuf = NULL; + } + } + if(mInBuf == NULL) { + mInBuf = (uint8 *)session().malloc(blockSizeIn); + } + + /* set up chain buf, decrypt/CBC only; skip if algorithm does its own chaining */ + if((mMode == BCM_CBC) && !encoding() && !mCbcCapable) { + if(mChainBuf != NULL) { + /* only reuse if same size */ + if(mInBlockSize != blockSizeIn) { + session().free(mChainBuf); + mChainBuf = NULL; + } + } + if(mChainBuf == NULL) { + mChainBuf = (uint8 *)session().malloc(blockSizeIn); + } + } + + /* IV iff CBC mode, and ensure IV is big enough */ + switch(mMode) { + case BCM_ECB: + if(iv != NULL) { + CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_INIT_VECTOR); + } + break; + case BCM_CBC: + if(iv == NULL) { + CssmError::throwMe(CSSMERR_CSP_MISSING_ATTR_INIT_VECTOR); + } + if(blockSizeIn != blockSizeOut) { + /* no can do, must be same block sizes */ + CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_MODE); + } + if(iv->Length < blockSizeIn) { + /* not enough IV */ + CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_INIT_VECTOR); + } + /* save IV as appropriate */ + if(!mCbcCapable) { + if(encoding()) { + memmove(mInBuf, iv->Data, blockSizeIn); + } + else { + assert(mChainBuf != NULL); + memmove(mChainBuf, iv->Data, blockSizeIn); + } + } + break; + } + + mInBlockSize = blockSizeIn; + mInBufSize = 0; + mOutBlockSize = blockSizeOut; + mOpStarted = false; +} + +/* + * This one is used by simple, well-behaved algorithms which don't do their own + * padding and which rely on us to do everything but one-block-at-a-time + * encrypt and decrypt. + */ +void BlockCryptor::setup( + size_t blockSize, // block size of input and output + const Context &context) +{ + bool padEnable = false; + bool chainEnable = false; + bool ivEnable = false; + CssmData *iv = NULL; + + /* + * Validate context + * IV optional per mode + * pad optional per mode + * Currently we ignore extraneous attributes (e.g., it's OK to pass in + * an IV if the mode doesn't specify it), mainly for simplifying test routines. + */ + CSSM_ENCRYPT_MODE cssmMode = context.getInt(CSSM_ATTRIBUTE_MODE); + + switch (cssmMode) { + /* no mode attr --> 0 == CSSM_ALGMODE_NONE, not currently supported */ + case CSSM_ALGMODE_CBCPadIV8: + padEnable = true; + ivEnable = true; + chainEnable = true; + break; + + case CSSM_ALGMODE_CBC_IV8: + ivEnable = true; + chainEnable = true; + break; + + case CSSM_ALGMODE_ECB: + break; + + case CSSM_ALGMODE_ECBPad: + padEnable = true; + break; + + default: + errorLog1("DESContext::init: illegal mode (%d)\n", (int)cssmMode); + CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_MODE); + } + + if(padEnable) { + /* validate padding type */ + uint32 padding = context.getInt(CSSM_ATTRIBUTE_PADDING); // 0 ==> PADDING_NONE + if(blockSize == 8) { + switch(padding) { + /* backwards compatibility - used to be PKCS1, should be PKCS5 or 7 */ + case CSSM_PADDING_PKCS7: + case CSSM_PADDING_PKCS5: + case CSSM_PADDING_PKCS1: //Êthis goes away soon + /* OK */ + break; + default: + CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_PADDING); + } + } + else { + switch(padding) { + case CSSM_PADDING_PKCS5: // this goes away soon + case CSSM_PADDING_PKCS7: + /* OK */ + break; + default: + CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_PADDING); + } + } + } + if(ivEnable) { + /* make sure there's an IV in the context of sufficient length */ + iv = context.get(CSSM_ATTRIBUTE_INIT_VECTOR); + if(iv == NULL) { + CssmError::throwMe(CSSMERR_CSP_MISSING_ATTR_INIT_VECTOR); + } + if(iv->Length < blockSize) { + CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_INIT_VECTOR); + } + } + setup(blockSize, + blockSize, + padEnable, + false, // needsFinal + chainEnable ? BCM_CBC : BCM_ECB, + iv); +} + +/* + * Update always leaves some data in mInBuf if: + * mNeedsFinalData is true, or + * decrypting and mPkcsPadding true. + * Also, we always process all of the input (except on error). + */ +void BlockCryptor::update( + void *inp, + size_t &inSize, // in/out + void *outp, + size_t &outSize) // in/out +{ + uint8 *uInp = (UInt8 *)inp; + uint8 *uOutp = (UInt8 *)outp; + size_t uInSize = inSize; // input bytes to go + size_t uOutSize = 0; // ouput bytes generated + size_t uOutLeft = outSize; // bytes remaining in outp + size_t toMove; + size_t actMoved; + unsigned i; + bool needLeftOver = mNeedFinalData || (!encoding() && mPkcsPadding); + bool doCbc = (mMode == BCM_CBC) && !mCbcCapable; + + assert(mInBuf != NULL); + mOpStarted = true; + + if(mInBufSize) { + /* attempt to fill mInBuf from inp */ + toMove = mInBlockSize - mInBufSize; + if(toMove > uInSize) { + toMove = uInSize; + } + if(encoding() && doCbc) { + /* xor into last cipherblock or IV */ + for(i=0; i mInBuf */ + if(leftOver) { + if(encoding() && doCbc) { + /* xor into last cipherblock or IV */ + for(i=0; i mOutBlockSize) { + BlockCryptDebug("BlockCryptor::final malformed ciphertext (1)"); + CssmError::throwMe(CSSM_ERRCODE_INVALID_DATA); + } + uint8 *padPtr = ptext + mOutBlockSize - padSize; + for(unsigned i=0; i= 1); + inSize = (wholeBlocks * mInBlockSize) - mInBufSize; + if(inSize == 0) { + /* i.e., we're holding a whole buffer */ + inSize++; + } + } + bprintf("--- BlockCryptor::inputSize inSize 0x%lx outSize 0x%lx mInBufSize 0x%lx", + inSize, outSize, mInBufSize); + return inSize; +} + +size_t BlockCryptor::outputSize( + bool final, + size_t inSize /*= 0*/) // output for given input size +{ + size_t rawBytes = inSize + mInBufSize; + // huh?Êdon't round this up! + //size_t rawBlocks = (rawBytes + mInBlockSize - 1) / mInBlockSize; + size_t rawBlocks = rawBytes / mInBlockSize; + + /* + * encrypting: always get one additional block on final() if we're padding + * or (we presume) the subclass is padding. Note that we + * truncated when calculating rawBlocks; to finish out on the + * final block, we (or our subclass) will either have to pad + * out the current partial block, or cook up a full pad block if + * mInBufSize is currently zero. Subclasses which pad some other + * way need to override this method. + * + * decrypting: outsize always <= insize + */ + if(encoding() && final && (mPkcsPadding || mNeedFinalData)) { + rawBlocks++; + } + + /* FIXME - optimize for needFinalData? (can squeak by with smaller outSize) */ + size_t rtn = rawBlocks * mOutBlockSize; + bprintf("--- BlockCryptor::outputSize inSize 0x%lx outSize 0x%lx final %d " + "inBufSize 0x%lx", inSize, rtn, final, mInBufSize); + return rtn; +} + + + diff --git a/libsecurity_apple_csp/lib/BlockCryptor.h b/libsecurity_apple_csp/lib/BlockCryptor.h new file mode 100644 index 00000000..1f101799 --- /dev/null +++ b/libsecurity_apple_csp/lib/BlockCryptor.h @@ -0,0 +1,190 @@ +/* + * 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. + */ + + +/* + * BlockCryptor.h - common context for block-oriented encryption algorithms + * + * Created March 5 2001 by dmitch + */ + +#ifndef _BLOCK_CRYPTOR_H_ +#define _BLOCK_CRYPTOR_H_ + +#include "AppleCSPContext.h" +#include + +/* + * Base class for AppleCSPContexts associated with BlockCryptObjects. + * The main purpose of this class is to abstract out the very common work + * of buffering incoming data (per CSSM-style update, ..., final) and + * doing single-block ops on the underlying encrypt/decrypt algorithm + * objects. Standard PKSC5 padding is handled here. All other chaining, + * padding, IV, et al, logic is handled by subclasses. + */ +class BlockCryptor : public AppleCSPContext +{ +public: + BlockCryptor( + AppleCSPSession &session) : + AppleCSPContext(session), + mOpStarted(false), + mCbcCapable(false), + mMultiBlockCapable(false), + mInBuf(NULL), + mChainBuf(NULL) { } + virtual ~BlockCryptor(); + + /* + * Note standard init(const Context &context, bool encoding) is totally + * subclass-specific. + * + * These are implemented here using the subclass's {en,de}cryptBlock functions. + * Note PKCS5 padding is implemented here if mPkcs5Padding is true. PKCS5 + * padding can only be accomplished if the result of decrypting + * cipherBlockSize() bytes of ciphertext yields exactly plainBlockSize() + * bytes of plaintext. (Sound odd? FEED does not meet that restriction...) + */ + void update( + void *inp, + size_t &inSize, // in/out + void *outp, + size_t &outSize); // in/out + + void final( + CssmData &out); + + /* + * Our implementation of these three query functions are only valid + * for algorithms for which encrypting one block of plaintext always + * yields exactly one block of ciphertext, and vice versa for decrypt. + * The block sizes for plaintext and ciphertext do NOT have to be the same. + * Subclasses (e.g. FEED) which do not meet this criterion will have to override. + */ + virtual size_t inputSize( + size_t outSize); // input for given output size + virtual size_t outputSize( + bool final = false, + size_t inSize = 0); // output for given input size + virtual void minimumProgress( + size_t &in, + size_t &out); // minimum progress chunks + +protected: + typedef enum { + BCM_ECB, // no chaining + BCM_CBC // requires inBlockSize == outBlockSize + } BC_Mode; + + /* accessors (see comments below re: the member variables) */ + bool pkcs5Padding() { return mPkcsPadding; } + bool needFinalData() { return mNeedFinalData; } + void *inBuf() { return mInBuf; } + size_t inBufSize() { return mInBufSize; } + void *chainBuf() { return mChainBuf; } + size_t inBlockSize() { return mInBlockSize; } + size_t outBlockSize() { return mOutBlockSize; } + BC_Mode mode() { return mMode; } + bool opStarted() { return mOpStarted; } + bool cbcCapable() { return mCbcCapable; } + void cbcCapable(bool c) { mCbcCapable = c; } + bool multiBlockCapable() { return mMultiBlockCapable; } + void multiBlockCapable(bool c) { mMultiBlockCapable = c; } + + /* + * Reusable setup functions called from subclass's init. + * This is the general purpose one.... + */ + void setup( + size_t blockSizeIn, // block size of input in bytes + size_t blockSizeOut, // block size of output in bytes + bool pkcsPad, // this class performs PKCS{5,7} padding + bool needsFinal, // needs final update with valid data + BC_Mode mode, // ECB, CBC + const CssmData *iv); // init vector, required for CBC + //Ê must be at least blockSizeIn bytes + + /* + * This one is used by simple, well-behaved algorithms which don't do their own + * padding and which rely on us to do everything but one-block-at-a-time + * encrypt and decrypt. + */ + void setup( + size_t blockSize, // block size of input and output + const Context &context); + + /*** + *** Routines to be implemented by subclass. + ***/ + + /* + virtual void init(const Context &context, bool encoding = true); + */ + + /* + * encrypt/decrypt exactly one block. Output buffers mallocd by caller. + * On encrypt, it may be acceptable for plainTextLen to be less than + * one plainBlockSize() if: + * -- final is true, and + * -- the subclass permits this. That is generally only true + * when the subclass implements some padding other than our + * standard PKCS5. + * + * The subclass throws CSSMERR_CSP_INPUT_LENGTH_ERROR if the above + * conditions are not met. + */ + virtual void encryptBlock( + const void *plainText, // length implied (one block) + size_t plainTextLen, + void *cipherText, + size_t &cipherTextLen, // in/out, subclass throws on overflow + bool final) = 0; + + /* + * Decrypt one block. Incoming cipherText length is ALWAYS cipherBlockSize(). + */ + virtual void decryptBlock( + const void *cipherText, // length implied (one cipher block) + size_t cipherTextLen, + void *plainText, + size_t &plainTextLen, // in/out, subclass throws on overflow + bool final) = 0; + +private: + bool mOpStarted; // for optional use by subclasses when + // resuing context after encrypt/decrypt + // ops occur + bool mCbcCapable; // when true, algorithm can do its own CBC + bool mMultiBlockCapable; // when true, algorithm can do multi-block ops + + /* these are all init'd via setup(), called from subclass-specific init */ + bool mPkcsPadding; // PKCS{5,7} padding enabled + bool mNeedFinalData; // subclass needs an update(final) with + // valid data; if true we always keep + // some data in mInBuf after an update. + // Mutually exclusive with mPkcsPadding. + uint8 *mInBuf; // for buffering input + size_t mInBufSize; // valid bytes in mInBuf + uint8 *mChainBuf; // for CBC, decrypting only + size_t mInBlockSize; // block size of input in bytes; also + // mallocd size of mInBuf + size_t mOutBlockSize; // block size of output in bytes + BC_Mode mMode; // ECB, CBC + +}; + +#endif /* _BLOCK_CRYPTOR_H_ */ diff --git a/libsecurity_apple_csp/lib/CryptKitSpace.h b/libsecurity_apple_csp/lib/CryptKitSpace.h new file mode 100755 index 00000000..ac546d7c --- /dev/null +++ b/libsecurity_apple_csp/lib/CryptKitSpace.h @@ -0,0 +1,37 @@ +/* + * 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. + */ + + +/* + * CryptKitSpace.h - bare-bones declaration of CryptKit namespace. + * + * Created by dmitch on Wed Feb 21 2001. + */ + +#ifdef CRYPTKIT_CSP_ENABLE + +#ifndef _CRYPT_KIT_SPACE_H_ +#define _CRYPT_KIT_SPACE_H_ + +/* first make sure it exists */ +namespace CryptKit { } + +/* then make4 it easy to use */ +using namespace CryptKit; + +#endif /* _CRYPT_KIT_SPACE_H_ */ +#endif /* CRYPTKIT_CSP_ENABLE */ diff --git a/libsecurity_apple_csp/lib/DH_csp.cpp b/libsecurity_apple_csp/lib/DH_csp.cpp new file mode 100644 index 00000000..7c2a903a --- /dev/null +++ b/libsecurity_apple_csp/lib/DH_csp.cpp @@ -0,0 +1,71 @@ +/* + * 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. + */ + + +/* + * DH_csp.cpp - Diffie-Hellman Algorithm factory + */ + +#include "DH_csp.h" +#include "DH_keys.h" +#include + +Allocator *DH_Factory::normAllocator; +Allocator *DH_Factory::privAllocator; + +DH_Factory::DH_Factory(Allocator *normAlloc, Allocator *privAlloc) +{ + setNormAllocator(normAlloc); + setPrivAllocator(privAlloc); + + /* NOTE WELL we assume that the RSA_DSA factory has already been instantitated, + * doing the basic init of openssl */ + + ERR_load_DH_strings(); +} + +DH_Factory::~DH_Factory() +{ +} + +bool DH_Factory::setup( + AppleCSPSession &session, + CSPFullPluginSession::CSPContext * &cspCtx, + const Context &context) +{ + switch(context.type()) { + case CSSM_ALGCLASS_KEYGEN: + switch(context.algorithm()) { + case CSSM_ALGID_DH: + if(cspCtx == NULL) { + cspCtx = new DHKeyPairGenContext(session, context); + } + return true; + default: + break; + } + break; + + default: + break; + } + /* not implemented here */ + return false; +} + + + diff --git a/libsecurity_apple_csp/lib/DH_csp.h b/libsecurity_apple_csp/lib/DH_csp.h new file mode 100644 index 00000000..1a73293b --- /dev/null +++ b/libsecurity_apple_csp/lib/DH_csp.h @@ -0,0 +1,53 @@ +/* + * 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. + */ + + +/* + * DH_csp.h - Diffie-Hellman Algorithm factory + */ + +#ifndef _DH_CSP_H_ +#define _DH_CSP_H_ + +#include +#include + +/* Can't include AppleCSPSession.h due to circular dependency */ +class AppleCSPSession; + +class DH_Factory : public AppleCSPAlgorithmFactory { +public: + DH_Factory(Allocator *normAlloc = NULL, Allocator *privAlloc = NULL); + ~DH_Factory(); + + bool setup( + AppleCSPSession &session, + CSPFullPluginSession::CSPContext * &cspCtx, + const Context &context); + + static void setNormAllocator(Allocator *alloc) + { assert(!normAllocator); normAllocator = alloc; } + static void setPrivAllocator(Allocator *alloc) + { assert(!privAllocator); privAllocator = alloc; } + + // memory allocators + static Allocator *normAllocator; + static Allocator *privAllocator; + +}; + +#endif /* _DH_CSP_H_ */ diff --git a/libsecurity_apple_csp/lib/DH_exchange.cpp b/libsecurity_apple_csp/lib/DH_exchange.cpp new file mode 100644 index 00000000..ae5f1eef --- /dev/null +++ b/libsecurity_apple_csp/lib/DH_exchange.cpp @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2000-2002 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. + */ + + +/* + * DH_exchange.cp - Diffie-Hellman key exchange + */ + +#include "DH_exchange.h" +#include +#include "DH_utils.h" +#include "DH_keys.h" +#include +#include + +void DeriveKey_DH ( + const Context &context, + const CssmData &Param, // other's public key. may be empty + CSSM_DATA *keyData, // mallocd by caller + // we fill in keyData->Length bytes + AppleCSPSession &session) +{ + bool mallocdPrivKey; + size_t privSize; + + /* private DH key from context - required */ + DH *privKey = contextToDhKey(context, session, CSSM_ATTRIBUTE_KEY, + CSSM_KEYCLASS_PRIVATE_KEY, CSSM_KEYUSE_DERIVE, mallocdPrivKey); + if(privKey == NULL) { + CssmError::throwMe(CSSMERR_CSP_MISSING_ATTR_KEY); + } + cspDhDebug("DeriveKey_DH, privKey %p", privKey); + privSize = DH_size(privKey); + if(privSize < keyData->Length) { + /* we've been asked for more bits than this key can generate */ + CssmError::throwMe(CSSMERR_CSP_UNSUPPORTED_KEY_SIZE); + } + + /* + * Public key ("their" key) can come from two places: + * -- in the context as a CSSM_ATTRIBUTE_PUBLIC_KEY. This is how + * public keys in X509 format must be used in this function + * -- in the incoming Param, the raw unformatted (PKCS3) form + */ + bool mallocdPubKey = false; + BIGNUM *pubKeyBn = NULL; + bool allocdPubKeyBn = false; + DH *pubKey = contextToDhKey(context, session, CSSM_ATTRIBUTE_PUBLIC_KEY, + CSSM_KEYCLASS_PUBLIC_KEY, CSSM_KEYUSE_DERIVE, mallocdPubKey); + if(pubKey != NULL) { + if(pubKey->pub_key == NULL) { + errorLog0("DeriveKey_DH: public key in context with no pub_key\n"); + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY); + } + pubKeyBn = pubKey->pub_key; + cspDhDebug("DeriveKey_DH, pubKey from context %p", pubKey); + } + else { + if((Param.Data == NULL) || (Param.Length == 0)) { + errorLog0("DeriveKey_DH: no pub_key, no Param\n"); + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY); + } + pubKeyBn = BN_bin2bn(Param.Data, Param.Length, NULL); + if(pubKeyBn == NULL) { + CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR); + } + allocdPubKeyBn = true; + cspDhDebug("DeriveKey_DH, no pubKey in context"); + } + unsigned char *buf = (unsigned char *)session.malloc(privSize); + int rtn = DH_compute_key(buf, pubKeyBn, privKey); + if(rtn > 0) { + /* + * FIXME : I have not found a specification describing *which* + * bytes of the value we just computed we are supposed to + * use as the actual key bytes. We use the M.S. bytes. + * + * Note that due to modulo arithmetic, we may have gotten fewer + * bytes than we asked for. If so, the caller will have + * to deal with that if they really need privSize bytes. + */ + assert((uint32)rtn <= privSize); + uint32 toMove = keyData->Length; + if((uint32)rtn < toMove) { + toMove = (uint32)rtn; + } + memmove(keyData->Data, buf, toMove); + keyData->Length = toMove; + } + if(mallocdPrivKey) { + DH_free(privKey); + } + if(mallocdPubKey) { + DH_free(pubKey); + } + if(allocdPubKeyBn) { + BN_free(pubKeyBn); + } + session.free(buf); + if(rtn <= 0) { + throwRsaDsa("DH_compute_key"); + } +} + diff --git a/libsecurity_apple_csp/lib/DH_exchange.h b/libsecurity_apple_csp/lib/DH_exchange.h new file mode 100644 index 00000000..7e408d8a --- /dev/null +++ b/libsecurity_apple_csp/lib/DH_exchange.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2000-2002 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. + */ + + +/* + * DH_exchange.h - Diffie-Hellman key exchange + */ + +#ifndef _DH_EXCHANGE_H_ +#define _DH_EXCHANGE_H_ + +#include + +void DeriveKey_DH ( + const Context &context, + const CssmData &Param, + CSSM_DATA *keyData, + AppleCSPSession &session); + +#endif /* _DH_EXCHANGE_H_ */ diff --git a/libsecurity_apple_csp/lib/DH_keys.cpp b/libsecurity_apple_csp/lib/DH_keys.cpp new file mode 100644 index 00000000..ab65f28e --- /dev/null +++ b/libsecurity_apple_csp/lib/DH_keys.cpp @@ -0,0 +1,533 @@ +/* + * Copyright (c) 2000-2002 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. + */ + + +/* + * DH_keys.cpp - Diffie-Hellman key pair support. + */ + +#include "DH_keys.h" +#include "DH_utils.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define dhKeyDebug(args...) secdebug("dhKey", ## args) + +/* + * FIXME - the CDSA Algorithm Guide claims that the incoming params argument + * for a GenerateAlgorithmParameters call is ignored for D-H. This means + * that there is no way for the caller to specify 'g' (typically 2, 3, or + * 5). This seems WAY bogus but we'll code to the spec for now, assuming + * a hard-coded default generator. + */ +#define DH_GENERATOR_DEFAULT DH_GENERATOR_2 + + +/*** + *** Diffie-Hellman-style BinaryKey + ***/ + +/* constructor with optional existing DSA key */ +DHBinaryKey::DHBinaryKey(DH *dhKey) + : mDhKey(dhKey) +{ +} + +DHBinaryKey::~DHBinaryKey() +{ + if(mDhKey) { + DH_free(mDhKey); + mDhKey = NULL; + } +} + +void DHBinaryKey::generateKeyBlob( + Allocator &allocator, + CssmData &blob, + CSSM_KEYBLOB_FORMAT &format, + AppleCSPSession &session, + const CssmKey *paramKey, /* optional, unused here */ + CSSM_KEYATTR_FLAGS &attrFlags) /* IN/OUT */ +{ + + switch(mKeyHeader.KeyClass) { + case CSSM_KEYCLASS_PUBLIC_KEY: + { + switch(format) { + case CSSM_KEYBLOB_RAW_FORMAT_NONE: + // take default + format = DH_PUB_KEY_FORMAT; + break; + case DH_PUB_KEY_FORMAT: + case CSSM_KEYBLOB_RAW_FORMAT_X509: + // proceed + break; + case CSSM_KEYBLOB_RAW_FORMAT_DIGEST: + /* use PKCS3 - caller won't care if we change this...right? */ + format = DH_PUB_KEY_FORMAT; + break; + default: + CssmError::throwMe(CSSMERR_CSP_UNSUPPORTED_KEY_FORMAT); + } + + assert(mDhKey != NULL); + CssmAutoData encodedKey(allocator); + CSSM_RETURN crtn = DHPublicKeyEncode(mDhKey, format, + encodedKey); + if(crtn) { + CssmError::throwMe(crtn); + } + blob = encodedKey.release(); + break; + } + case CSSM_KEYCLASS_PRIVATE_KEY: + { + switch(format) { + case CSSM_KEYBLOB_RAW_FORMAT_NONE: + // i.e., use default + format = DH_PRIV_KEY_FORMAT; + break; + case DH_PRIV_KEY_FORMAT: + case CSSM_KEYBLOB_RAW_FORMAT_PKCS8: + // proceed + break; + + case CSSM_KEYBLOB_RAW_FORMAT_DIGEST: + { + /* + * Use public blob; calculate it if we + * don't already have it. + */ + assert(mDhKey != NULL); + if(mDhKey->pub_key == NULL) { + int irtn = DH_generate_key(mDhKey); + if(!irtn) { + throwRsaDsa("DH_generate_key"); + } + } + assert(mDhKey->pub_key != NULL); + setUpData(blob, + BN_num_bytes(mDhKey->pub_key), + *DH_Factory::privAllocator); + BN_bn2bin(mDhKey->pub_key, blob); + format = DH_PUB_KEY_FORMAT; + return; + } + + default: + CssmError::throwMe(CSSMERR_CSP_UNSUPPORTED_KEY_FORMAT); + } + assert(mDhKey != NULL); + CssmAutoData encodedKey(allocator); + CSSM_RETURN crtn = DHPrivateKeyEncode(mDhKey, format, + encodedKey); + if(crtn) { + CssmError::throwMe(crtn); + } + blob = encodedKey.release(); + break; + } + default: + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS); + } +} + +/*** + *** Diffie-Hellman style AppleKeyPairGenContext + ***/ + +/* + * This one is specified in, and called from, CSPFullPluginSession. Our + * only job is to prepare two subclass-specific BinaryKeys and call up to + * AppleKeyPairGenContext. + */ +void DHKeyPairGenContext::generate( + const Context &context, + CssmKey &pubKey, + CssmKey &privKey) +{ + DHBinaryKey *pubBinKey = new DHBinaryKey(); + DHBinaryKey *privBinKey = new DHBinaryKey(); + + try { + AppleKeyPairGenContext::generate(context, + session(), + pubKey, + pubBinKey, + privKey, + privBinKey); + } + catch (...) { + delete pubBinKey; + delete privBinKey; + throw; + } +} + +/* + * This one is specified in, and called from, AppleKeyPairGenContext + */ +void DHKeyPairGenContext::generate( + const Context &context, + BinaryKey &pubBinKey, + BinaryKey &privBinKey, + uint32 &keyBits) +{ + /* + * These casts throw exceptions if the keys are of the + * wrong classes, which would be a major bogon, since we created + * the keys in the above generate() function. + */ + DHBinaryKey &rPubBinKey = + dynamic_cast(pubBinKey); + DHBinaryKey &rPrivBinKey = + dynamic_cast(privBinKey); + + /* + * Parameters from context: + * Key size in bits, required; + * {p,g,privKeyLength} from generateParams, optional + * NOTE: currently the openssl D-H imnplementation ignores the + * privKeyLength field. + */ + keyBits = context.getInt(CSSM_ATTRIBUTE_KEY_LENGTH, + CSSMERR_CSP_MISSING_ATTR_KEY_LENGTH); + CssmData *paramData = context.get(CSSM_ATTRIBUTE_ALG_PARAMS); + + NSS_DHParameterBlock algParamBlock; + NSS_DHParameter &algParams = algParamBlock.params; + uint32 privValueLen = 0; // only nonzero from externally generated + // params + SecNssCoder coder; // for temp allocs of decoded parameters + + if(paramData != NULL) { + /* this contains the DER encoding of a DHParameterBlock */ + CSSM_RETURN crtn; + crtn = DHParamBlockDecode(*paramData, algParamBlock, coder); + if(crtn) { + CssmError::throwMe(crtn); + } + + /* snag the optional private key length field */ + if(algParams.privateValueLength.Data) { + privValueLen = cssmDataToInt(algParams.privateValueLength); + } + + /* ensure caller's key size matches the incoming params */ + uint32 paramKeyBytes; + if(privValueLen) { + paramKeyBytes = (privValueLen + 7) / 8; + } + else { + paramKeyBytes = algParams.prime.Length; + /* trim off possible m.s. byte of zero */ + const unsigned char *uo = + (const unsigned char *)algParams.prime.Data; + if(*uo == 0) { + paramKeyBytes--; + } + } + uint32 reqBytes = (keyBits + 7) / 8; + if(paramKeyBytes != reqBytes) { + dhKeyDebug("DH key size mismatch (req %d param %d)", + (int)reqBytes, (int)paramKeyBytes); + CssmError::throwMe(CSSMERR_CSP_UNSUPPORTED_KEY_SIZE); + } + } + else { + /* no alg params specified; generate them now */ + dhKeyDebug("DH implicit alg param calculation"); + memset(&algParamBlock, 0, sizeof(algParamBlock)); + dhGenParams(keyBits, DH_GENERATOR_DEFAULT, 0, algParams, coder); + } + + /* create key, stuff params into it */ + rPrivBinKey.mDhKey = DH_new(); + if(rPrivBinKey.mDhKey == NULL) { + CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR); + } + DH *dhKey = rPrivBinKey.mDhKey; + dhKey->p = cssmDataToBn(algParams.prime); + dhKey->g = cssmDataToBn(algParams.base); + dhKey->length = privValueLen; + cspDhDebug("private DH binary key dhKey %p", dhKey); + + /* generate the key (both public and private capabilities) */ + int irtn = DH_generate_key(dhKey); + if(!irtn) { + throwRsaDsa("DH_generate_key"); + } + + /* public key is a subset */ + rPubBinKey.mDhKey = DH_new(); + if(rPubBinKey.mDhKey == NULL) { + CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR); + } + DH *pubDhKey = rPubBinKey.mDhKey; + pubDhKey->pub_key = BN_dup(dhKey->pub_key); + /* these params used for X509 style key blobs */ + pubDhKey->p = BN_dup(dhKey->p); + pubDhKey->g = BN_dup(dhKey->g); + cspDhDebug("public DH binary key pubDhKey %p", pubDhKey); +} + + + +/*** + *** Diffie-Hellman CSPKeyInfoProvider. + ***/ +DHKeyInfoProvider::DHKeyInfoProvider( + const CssmKey &cssmKey, + AppleCSPSession &session) : + CSPKeyInfoProvider(cssmKey, session) +{ +} + +CSPKeyInfoProvider *DHKeyInfoProvider::provider( + const CssmKey &cssmKey, + AppleCSPSession &session) +{ + switch(cssmKey.algorithm()) { + case CSSM_ALGID_DH: + break; + default: + CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM); + } + switch(cssmKey.keyClass()) { + case CSSM_KEYCLASS_PUBLIC_KEY: + case CSSM_KEYCLASS_PRIVATE_KEY: + break; + default: + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS); + } + /* OK, we'll handle this one */ + return new DHKeyInfoProvider(cssmKey, session); +} + +/* Given a raw key, cook up a Binary key */ +void DHKeyInfoProvider::CssmKeyToBinary( + CssmKey *paramKey, // optional, ignored here + CSSM_KEYATTR_FLAGS &attrFlags, // IN/OUT + BinaryKey **binKey) +{ + *binKey = NULL; + + assert(mKey.blobType() == CSSM_KEYBLOB_RAW); + switch(mKey.keyClass()) { + case CSSM_KEYCLASS_PUBLIC_KEY: + case CSSM_KEYCLASS_PRIVATE_KEY: + break; + default: + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS); + } + + /* first cook up an DH key, then drop that into a BinaryKey */ + DH *dhKey = rawCssmKeyToDh(mKey); + DHBinaryKey *dhBinKey = new DHBinaryKey(dhKey); + *binKey = dhBinKey; + cspDhDebug("CssmKeyToBinary dhKey %p", dhKey); +} + +/* + * Obtain key size in bits. + * FIXME - I doubt that this is, or can be, exactly accurate..... + */ +void DHKeyInfoProvider::QueryKeySizeInBits( + CSSM_KEY_SIZE &keySize) +{ + uint32 numBits = 0; + + if(mKey.blobType() != CSSM_KEYBLOB_RAW) { + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_FORMAT); + } + DH *dhKey = rawCssmKeyToDh(mKey); + + /* DH_size requires the p parameter, which some public keys don't have */ + if(dhKey->p != NULL) { + numBits = DH_size(dhKey) * 8; + } + else { + assert(dhKey->pub_key != NULL); + numBits = BN_num_bytes(dhKey->pub_key) * 8; + } + DH_free(dhKey); + keySize.LogicalKeySizeInBits = numBits; + keySize.EffectiveKeySizeInBits = numBits; +} + +/* + * Obtain blob suitable for hashing in CSSM_APPLECSP_KEYDIGEST + * passthrough. + */ +bool DHKeyInfoProvider::getHashableBlob( + Allocator &allocator, + CssmData &blob) // blob to hash goes here +{ + /* + * The optimized case, a raw key in the "proper" format already. + */ + assert(mKey.blobType() == CSSM_KEYBLOB_RAW); + bool useAsIs = false; + + switch(mKey.keyClass()) { + case CSSM_KEYCLASS_PUBLIC_KEY: + if(mKey.blobFormat() == CSSM_KEYBLOB_RAW_FORMAT_PKCS3) { + useAsIs = true; + } + break; + case CSSM_KEYCLASS_PRIVATE_KEY: + break; + default: + /* shouldn't be here */ + assert(0); + CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR); + } + if(useAsIs) { + const CssmData &keyBlob = CssmData::overlay(mKey.KeyData); + copyCssmData(keyBlob, blob, allocator); + return true; + } + + /* caller converts to binary and proceeds */ + return false; +} + +/* + * Generate keygen parameters, stash them in a context attr array for later use + * when actually generating the keys. + */ + +void DHKeyPairGenContext::generate( + const Context &context, + uint32 bitSize, + CssmData ¶ms, // RETURNED here, + uint32 &attrCount, // here, + Context::Attr * &attrs) // and here +{ + /* generate the params */ + NSS_DHParameterBlock algParamBlock; + SecNssCoder coder; + NSS_DHParameter &algParams = algParamBlock.params; + dhGenParams(bitSize, DH_GENERATOR_DEFAULT, 0, algParams, coder); + + /* drop in the required OID */ + algParamBlock.oid = CSSMOID_PKCS3; + + /* + * Here comes the fun part. + * We "return" the DER encoding of these generated params in two ways: + * 1. Copy out to app via the params argument, mallocing if Data ptr is NULL. + * The app must free this. + * 2. Cook up a 1-element Context::attr array containing one ALG_PARAM attr, + * a CSSM_DATA_PTR containing the DER encoding. We have to save a ptr to + * this attr array and free it, the CSSM_DATA it points to, and the DER + * encoding *that* points to, in our destructor. + * + * First, DER encode. + */ + CssmAutoData aDerData(session()); + PRErrorCode perr; + perr = SecNssEncodeItemOdata(&algParamBlock, kSecAsn1DHParameterBlockTemplate, + aDerData); + if(perr) { + /* only known error... */ + CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR); + } + + /* copy/release that into a mallocd CSSM_DATA. */ + CSSM_DATA_PTR derData = (CSSM_DATA_PTR)session().malloc(sizeof(CSSM_DATA)); + *derData = aDerData.release(); + + /* stuff that into a one-element Attr array which we keep after returning */ + freeGenAttrs(); + mGenAttrs = (Context::Attr *)session().malloc(sizeof(Context::Attr)); + mGenAttrs->AttributeType = CSSM_ATTRIBUTE_ALG_PARAMS; + mGenAttrs->AttributeLength = sizeof(CSSM_DATA); + mGenAttrs->Attribute.Data = derData; + + /* and "return" this stuff */ + copyCssmData(CssmData::overlay(*derData), params, session()); + attrCount = 1; + attrs = mGenAttrs; +} + +/* free mGenAttrs and its referents if present */ +void DHKeyPairGenContext::freeGenAttrs() +{ + if(mGenAttrs == NULL) { + return; + } + if(mGenAttrs->Attribute.Data) { + if(mGenAttrs->Attribute.Data->Data) { + session().free(mGenAttrs->Attribute.Data->Data); + } + session().free(mGenAttrs->Attribute.Data); + } + session().free(mGenAttrs); +} + +/* + * Generate DSA algorithm parameters returning result + * into DHParameter.{prime,base,privateValueLength]. + * This is called from both GenerateParameters and from + * KeyPairGenerate (if no GenerateParameters has yet been called). + * + * FIXME - privateValueLength not implemented in openssl, not here + * either for now. + */ + +void DHKeyPairGenContext::dhGenParams( + uint32 keySizeInBits, + unsigned g, // probably should be BIGNUM + int privValueLength, // optional + NSS_DHParameter &algParams, + SecNssCoder &coder) // temp contents of algParams + // mallocd here +{ + /* validate key size */ + if((keySizeInBits < DH_MIN_KEY_SIZE) || + (keySizeInBits > DH_MAX_KEY_SIZE)) { + CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_KEY_LENGTH); + } + + /* create an openssl-style DH key with minimal setup */ + DH *dhKey = DH_generate_parameters(keySizeInBits, g, NULL, NULL); + if(dhKey == NULL) { + throwRsaDsa("DSA_generate_parameters"); + } + + /* stuff dhKey->{p,g,length}] into a caller's NSS_DHParameter */ + bnToCssmData(dhKey->p, algParams.prime, coder); + bnToCssmData(dhKey->g, algParams.base, coder); + CSSM_DATA &privValData = algParams.privateValueLength; + if(privValueLength) { + intToCssmData(privValueLength, privValData, coder); + } + else { + privValData.Data = NULL; + privValData.Length = 0; + } + DH_free(dhKey); +} + diff --git a/libsecurity_apple_csp/lib/DH_keys.h b/libsecurity_apple_csp/lib/DH_keys.h new file mode 100644 index 00000000..c75d403f --- /dev/null +++ b/libsecurity_apple_csp/lib/DH_keys.h @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2000-2002 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. + */ + + +/* + * DH_keys.h - Diffie-Hellman key pair support + */ + +#ifndef _DH_KEYS_H_ +#define _DH_KEYS_H_ + +#include +#include +#include "AppleCSPKeys.h" +#include +#include +#include +#include +#include +#include + +#define DH_PUB_KEY_FORMAT CSSM_KEYBLOB_RAW_FORMAT_PKCS3 +#define DH_PRIV_KEY_FORMAT CSSM_KEYBLOB_RAW_FORMAT_PKCS3 + +#define DH_MIN_KEY_SIZE 512 /* FIXME */ +#define DH_MAX_KEY_SIZE 2048 + +#define cspDhDebug(args...) secdebug("dhDebug", ## args) + +/* + * Diffie-Hellman version of a BinaryKey. + */ +class DHBinaryKey : public BinaryKey { +public: + DHBinaryKey(DH *dhKey = NULL); + ~DHBinaryKey(); + void generateKeyBlob( + Allocator &allocator, + CssmData &blob, + CSSM_KEYBLOB_FORMAT &format, + AppleCSPSession &session, + const CssmKey *paramKey, /* optional, unused here */ + CSSM_KEYATTR_FLAGS &attrFlags); /* IN/OUT */ + + /* + * This may contain a fully-capable private key, or a public + * key with as little as the pub_key field set. + */ + DH *mDhKey; +}; + +class DHKeyPairGenContext : + public AppleCSPContext, private AppleKeyPairGenContext { +public: + DHKeyPairGenContext( + AppleCSPSession &session, + const Context &) : + AppleCSPContext(session), + mGenAttrs(NULL) {} + + ~DHKeyPairGenContext() { freeGenAttrs(); } + + // no init functionality, but we need to implement it + void init( + const Context &, + bool) { } + + // this one is specified in, and called from, CSPFullPluginSession + void generate( + const Context &context, + CssmKey &pubKey, + CssmKey &privKey); + + // this one is specified in, and called from, AppleKeyPairGenContext + void generate( + const Context &context, + BinaryKey &pubBinKey, + BinaryKey &privBinKey, + uint32 &keySize); + + // specified in, and called from, CSPFullPluginSessionÊ- generate parameters + void generate( + const Context &context, + uint32 bitSize, + CssmData ¶ms, + uint32 &attrCount, + Context::Attr * &attrs); + + /* + * Necessary to handle and deflect "context changed" notification which occurs + * after the strange return from "generate parameters", when the plugin adds + * the "returned" values to the Context. + */ + bool changed(const Context &context) { return true; } + + void dhGenParams( + uint32 keySizeInBits, + unsigned g, // probably should be BIGNUM + int privValueLength, // optional + NSS_DHParameter &algParams, + SecNssCoder &coder); // for temp contents of algParams + +private: + /* gross hack to store attributes "returned" from GenParams */ + Context::Attr *mGenAttrs; + void freeGenAttrs(); +}; /* DHKeyPairGenContext */ + +/* + * CSPKeyInfoProvider for Diffie-Hellman keys + */ +class DHKeyInfoProvider : public CSPKeyInfoProvider +{ +private: + DHKeyInfoProvider( + const CssmKey &cssmKey, + AppleCSPSession &session); +public: + static CSPKeyInfoProvider *provider( + const CssmKey &cssmKey, + AppleCSPSession &session); + + ~DHKeyInfoProvider() { } + void CssmKeyToBinary( + CssmKey *paramKey, // optional, ignored here + CSSM_KEYATTR_FLAGS &attrFlags, // IN/OUT + BinaryKey **binKey); // RETURNED + void QueryKeySizeInBits( + CSSM_KEY_SIZE &keySize); // RETURNED + bool getHashableBlob( + Allocator &allocator, + CssmData &hashBlob); +}; + +#endif /* _DH_KEYS_H_ */ diff --git a/libsecurity_apple_csp/lib/DH_utils.cpp b/libsecurity_apple_csp/lib/DH_utils.cpp new file mode 100644 index 00000000..98096261 --- /dev/null +++ b/libsecurity_apple_csp/lib/DH_utils.cpp @@ -0,0 +1,185 @@ +/* + * 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. + */ + + +/* + * DH_utils.cpp + */ + +#include "DH_utils.h" +#include "DH_keys.h" +#include +#include +#include +#include +#include +#include +#include + +#define dhMiscDebug(args...) secdebug("dhMisc", ## args) + +/* + * Given a Context: + * -- obtain CSSM key with specified attr (there must only be one) + * -- validate keyClass per caller's specification + * -- validate keyUsage + * -- convert to DH *, allocating the DH key if necessary + */ +DH *contextToDhKey( + const Context &context, + AppleCSPSession &session, + CSSM_ATTRIBUTE_TYPE attr, // CSSM_ATTRIBUTE_KEY for private key + // CSSM_ATTRIBUTE_PUBLIC_KEY for public key + CSSM_KEYCLASS keyClass, // CSSM_KEYCLASS_{PUBLIC,PRIVATE}_KEY + CSSM_KEYUSE usage, // CSSM_KEYUSE_ENCRYPT, CSSM_KEYUSE_SIGN, etc. + bool &mallocdKey) // RETURNED +{ + CssmKey *cssmKey = context.get(attr); + if(cssmKey == NULL) { + return NULL; + } + const CSSM_KEYHEADER &hdr = cssmKey->KeyHeader; + if(hdr.AlgorithmId != CSSM_ALGID_DH) { + CssmError::throwMe(CSSMERR_CSP_ALGID_MISMATCH); + } + if(hdr.KeyClass != keyClass) { + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS); + } + cspValidateIntendedKeyUsage(&hdr, usage); + cspVerifyKeyTimes(hdr); + return cssmKeyToDh(*cssmKey, session, mallocdKey); +} + +/* + * Convert a CssmKey to an DH * key. May result in the + * creation of a new DH (when cssmKey is a raw key); allocdKey is true + * in that case in which case the caller generally has to free the allocd key). + */ +DH *cssmKeyToDh( + const CssmKey &cssmKey, + AppleCSPSession &session, + bool &allocdKey) // RETURNED +{ + DH *dhKey = NULL; + allocdKey = false; + + const CSSM_KEYHEADER *hdr = &cssmKey.KeyHeader; + if(hdr->AlgorithmId != CSSM_ALGID_DH) { + // someone else's key (should never happen) + CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM); + } + switch(hdr->BlobType) { + case CSSM_KEYBLOB_RAW: + dhKey = rawCssmKeyToDh(cssmKey); + cspDhDebug("cssmKeyToDh, raw, dhKey %p", dhKey); + allocdKey = true; + break; + case CSSM_KEYBLOB_REFERENCE: + { + BinaryKey &binKey = session.lookupRefKey(cssmKey); + DHBinaryKey *dhBinKey = dynamic_cast(&binKey); + /* this cast failing means that this is some other + * kind of binary key */ + if(dhBinKey == NULL) { + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY); + } + assert(dhBinKey->mDhKey != NULL); + dhKey = dhBinKey->mDhKey; + cspDhDebug("cssmKeyToDh, ref, dhKey %p", dhKey); + break; + } + default: + CssmError::throwMe(CSSMERR_CSP_KEY_BLOB_TYPE_INCORRECT); + } + return dhKey; +} + +/* + * Convert a raw CssmKey to a newly alloc'd DH key. + */ +DH *rawCssmKeyToDh( + const CssmKey &cssmKey) +{ + const CSSM_KEYHEADER *hdr = &cssmKey.KeyHeader; + bool isPub = false; + + if(hdr->AlgorithmId != CSSM_ALGID_DH) { + // someone else's key (should never happen) + CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM); + } + assert(hdr->BlobType == CSSM_KEYBLOB_RAW); + /* validate and figure out what we're dealing with */ + switch(hdr->KeyClass) { + case CSSM_KEYCLASS_PUBLIC_KEY: + switch(hdr->Format) { + case CSSM_KEYBLOB_RAW_FORMAT_PKCS3: + case CSSM_KEYBLOB_RAW_FORMAT_X509: + break; + /* openssh real soon now */ + case CSSM_KEYBLOB_RAW_FORMAT_OPENSSH: + default: + CssmError::throwMe( + CSSMERR_CSP_INVALID_ATTR_PUBLIC_KEY_FORMAT); + } + isPub = true; + break; + case CSSM_KEYCLASS_PRIVATE_KEY: + switch(hdr->Format) { + case CSSM_KEYBLOB_RAW_FORMAT_PKCS3: // default + case CSSM_KEYBLOB_RAW_FORMAT_PKCS8: // SMIME style + break; + /* openssh real soon now */ + case CSSM_KEYBLOB_RAW_FORMAT_OPENSSH: + default: + CssmError::throwMe( + CSSMERR_CSP_INVALID_ATTR_PRIVATE_KEY_FORMAT); + } + isPub = false; + break; + default: + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS); + } + + CSSM_RETURN crtn; + + DH *dhKey = DH_new(); + if(dhKey == NULL) { + crtn = CSSMERR_CSP_MEMORY_ERROR; + } + else + { + if(isPub) { + crtn = DHPublicKeyDecode(dhKey, hdr->Format, + cssmKey.KeyData.Data, cssmKey.KeyData.Length); + } + else { + crtn = DHPrivateKeyDecode(dhKey, hdr->Format, + cssmKey.KeyData.Data, cssmKey.KeyData.Length); + } + } + + if(crtn) { + if (dhKey != NULL) { + DH_free(dhKey); + } + + CssmError::throwMe(crtn); + } + cspDhDebug("rawCssmKeyToDh, dhKey %p", dhKey); + return dhKey; +} + diff --git a/libsecurity_apple_csp/lib/DH_utils.h b/libsecurity_apple_csp/lib/DH_utils.h new file mode 100644 index 00000000..4bf45f24 --- /dev/null +++ b/libsecurity_apple_csp/lib/DH_utils.h @@ -0,0 +1,75 @@ +/* + * 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. + */ + + +/* + * DH_utils.h + */ +#ifndef _DH_UTILS_H_ +#define _DH_UTILS_H_ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +void throwDh( + const char *op); + +/* + * Given a Context: + * -- obtain CSSM key (there must only be one) + * -- validate keyClass - MUST be private! (DH public keys are never found + * in contexts.) + * -- validate keyUsage + * -- convert to DH *, allocating the DH key if necessary + */ +DH *contextToDhKey( + const Context &context, + AppleCSPSession &session, + CSSM_ATTRIBUTE_TYPE attr, // CSSM_ATTRIBUTE_KEY for normal private key + // CSSM_ATTRIBUTE_PUBLIC_KEY for public key + CSSM_KEYCLASS keyClass, // CSSM_KEYCLASS_{PUBLIC,PRIVATE}_KEY + CSSM_KEYUSE usage, // CSSM_KEYUSE_ENCRYPT, + // CSSM_KEYUSE_SIGN, etc. + bool &mallocdKey); // RETURNED + +/* + * Convert a CssmKey to an DH * key. May result in the creation of a new + * DH (when cssmKey is a raw key); allocdKey is true in that case + * in which case the caller generally has to free the allocd key). + */ +DH *cssmKeyToDh( + const CssmKey &cssmKey, + AppleCSPSession &session, + bool &allocdKey); // RETURNED + +/* + * Convert a raw CssmKey to a newly alloc'd DH *. + */ +DH *rawCssmKeyToDh( + const CssmKey &cssmKey); + + +#ifdef __cplusplus +} +#endif + +#endif /*_DH_UTILS_H_ */ diff --git a/libsecurity_apple_csp/lib/DigestContext.cpp b/libsecurity_apple_csp/lib/DigestContext.cpp new file mode 100644 index 00000000..395d3d61 --- /dev/null +++ b/libsecurity_apple_csp/lib/DigestContext.cpp @@ -0,0 +1,58 @@ +/* + * 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. + */ + + +// +// DigestContext.cpp +// +#include "DigestContext.h" +#include + +/* + * Just field the expected/required calls from CSPFullPluginSession, + * and dispatch them to mDigest. + */ +void DigestContext::init(const Context &context, bool) +{ + mDigest.digestInit(); +} + +void DigestContext::update(const CssmData &data) +{ + mDigest.digestUpdate((const uint8 *)data.data(), data.length()); +} + +void DigestContext::final(CssmData &data) +{ + data.length(mDigest.digestSizeInBytes()); + mDigest.digestFinal((uint8 *)data.data()); +} + +CSPFullPluginSession::CSPContext *DigestContext::clone(Allocator &) +{ + /* first clone the low-level digest object */ + DigestObject *newDigest = mDigest.digestClone(); + + /* now construct a new context */ + return new DigestContext(session(), *newDigest); +} + +size_t DigestContext::outputSize(bool, size_t) +{ + return mDigest.digestSizeInBytes(); +} + diff --git a/libsecurity_apple_csp/lib/DigestContext.h b/libsecurity_apple_csp/lib/DigestContext.h new file mode 100644 index 00000000..5053315b --- /dev/null +++ b/libsecurity_apple_csp/lib/DigestContext.h @@ -0,0 +1,51 @@ +/* + * 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. + */ + + +// +// DigestContext.h +// + +#ifndef _DIGEST_CONTEXT_H_ +#define _DIGEST_CONTEXT_H_ + +#include +#include "AppleCSPContext.h" + +/* + * This is just a shim to give AppleCSPContext functionality to a + * DigestObject subclass (a reference to which is passed to our constructor). + */ +class DigestContext : public AppleCSPContext { +public: + DigestContext( + AppleCSPSession &session, + DigestObject &digest) : + AppleCSPContext(session), mDigest(digest) { } + ~DigestContext() { delete &mDigest; } + + void init(const Context &context, bool); + void update(const CssmData &data); + void final(CssmData &data); + CSPFullPluginSession::CSPContext *clone(Allocator &); // clone internal state + size_t outputSize(bool, size_t); + +private: + DigestObject &mDigest; +}; + +#endif /* _CRYPTKIT_DIGEST_CONTEXT_H_ */ diff --git a/libsecurity_apple_csp/lib/FEEAsymmetricContext.cpp b/libsecurity_apple_csp/lib/FEEAsymmetricContext.cpp new file mode 100644 index 00000000..60c5df6b --- /dev/null +++ b/libsecurity_apple_csp/lib/FEEAsymmetricContext.cpp @@ -0,0 +1,604 @@ +/* + * 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. + */ + + +/* + * FEEAsymmetricContext.cpp - CSPContexts for FEE asymmetric encryption + * + * Created March 8 2001 by dmitch. + */ + +#ifdef CRYPTKIT_CSP_ENABLE + +#include "FEEAsymmetricContext.h" +#include "FEECSPUtils.h" +#include +#include + +/* validate context for FEED and FEEDExp - no unexpected attributes allowed */ +static void validateFeedContext( + const Context &context) +{ + /* Note we cannot distinguish between zero and "not there" */ + uint32 blockSize = context.getInt(CSSM_ATTRIBUTE_BLOCK_SIZE); + if(blockSize != 0) { + CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_BLOCK_SIZE); + } + CSSM_ENCRYPT_MODE cssmMode = context.getInt(CSSM_ATTRIBUTE_MODE); + if(cssmMode != 0) { + CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_MODE); + } + #if 0 + /* we allow this for CMS wrapping */ + CssmData *iv = context.get(CSSM_ATTRIBUTE_INIT_VECTOR); + if(iv != NULL) { + CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_INIT_VECTOR); + } + #endif + CSSM_PADDING padding = context.getInt(CSSM_ATTRIBUTE_PADDING); + if(padding != 0) { + CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_PADDING); + } +} + +/*** + *** FEED - 1:1 FEED - encrypt n bytes of plaintext, get (roughly) n bytes + *** of ciphertext. Ciphertext is smaller than with FEED, but this is slower. + ***/ +CryptKit::FEEDContext::~FEEDContext() +{ + if(mFeeFeed) { + feeFEEDFree(mFeeFeed); + mFeeFeed = NULL; + } + if(mPrivKey && mAllocdPrivKey) { + feePubKeyFree(mPrivKey); + } + if(mPubKey && mAllocdPubKey) { + feePubKeyFree(mPubKey); + } + mPrivKey = NULL; + mPubKey = NULL; + mInitFlag = false; +} + +// called by CSPFullPluginSession; reusable +void CryptKit::FEEDContext::init( + const Context &context, + bool encoding) +{ + if(mInitFlag && !opStarted()) { + /* reusing - e.g. query followed by encrypt */ + return; + } + + /* + * Fetch FEE keys from context. This is an unusual algorithm - it requires + * two keys, one public and one private. The public key MUST be stored in + * the context with attribute type CSSM_ATTRIBUTE_PUBLIC_KEY, and the private + * key with CSSM_ATTRIBUTE_KEY. + * + * For now, we require CSSM_KEYUSE_ANY for FEE keys used for this algorithm. + * Otherwise we'd have to allow both KEYUSE_ENCRYPT and KEYUSE_DECRYPT for + * both keys, and that would require some algorithm-specific hack in + * cspValidateKeyUsageBits() which I really don't want to do. + */ + if(mPrivKey == NULL) { + assert(!opStarted()); + mPrivKey = contextToFeeKey(context, + session(), + CSSM_ATTRIBUTE_KEY, + CSSM_KEYCLASS_PRIVATE_KEY, + CSSM_KEYUSE_ANY, + mAllocdPrivKey); + } + else { + assert(opStarted()); + } + if(mPubKey == NULL) { + assert(!opStarted()); + mPubKey = contextToFeeKey(context, + session(), + CSSM_ATTRIBUTE_PUBLIC_KEY, + CSSM_KEYCLASS_PUBLIC_KEY, + CSSM_KEYUSE_ANY, + mAllocdPubKey); + } + else { + assert(opStarted()); + } + + /* validate context - no other attributes allowed */ + validateFeedContext(context); + + if(mFeeFeed != NULL) { + /* not reusable */ + assert(opStarted()); + feeFEEDFree(mFeeFeed); + mFeeFeed = NULL; + } + + /* OK, looks good. Cook up a feeFEED object. */ + mFeeFeed = feeFEEDNewWithPubKey(mPrivKey, + mPubKey, + encoding ? 1 : 0, + feeRandCallback, + &session()); + if(mFeeFeed == NULL) { + CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_KEY); + } + + /* finally, have BlockCryptor set up its stuff. */ + unsigned plainBlockSize = feeFEEDPlainBlockSize(mFeeFeed); + unsigned cipherBlockSize = feeFEEDCipherBlockSize(mFeeFeed); + setup(encoding ? plainBlockSize : cipherBlockSize, // blockSizeIn + encoding ? cipherBlockSize : plainBlockSize, // blockSizeOut + false, // pkcsPad + true, // needsFinal + BCM_ECB, + NULL); // IV + mInitFlag = true; +} + +// called by BlockCryptor +void CryptKit::FEEDContext::encryptBlock( + const void *plainText, // length implied (one block) + size_t plainTextLen, + void *cipherText, + size_t &cipherTextLen, // in/out, throws on overflow + bool final) +{ + feeReturn frtn; + unsigned actMoved; + + assert(mFeeFeed != NULL); + frtn = feeFEEDEncryptBlock(mFeeFeed, + (unsigned char *)plainText, + plainTextLen, + (unsigned char *)cipherText, + &actMoved, + final ? 1 : 0); + if(frtn) { + throwCryptKit(frtn, "feeFEEDEncryptBlock"); + } + if(actMoved > cipherTextLen) { + /* Overflow already occurred! */ + CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR); + } + cipherTextLen = actMoved; +} + +void CryptKit::FEEDContext::decryptBlock( + const void *cipherText, // length implied (one cipher block) + size_t cipherTextLen, + void *plainText, + size_t &plainTextLen, // in/out, throws on overflow + bool final) +{ + feeReturn frtn; + unsigned actMoved; + + assert(mFeeFeed != NULL); + frtn = feeFEEDDecryptBlock(mFeeFeed, + (unsigned char *)cipherText, + inBlockSize(), + (unsigned char *)plainText, + &actMoved, + final ? 1 : 0); + if(frtn) { + throwCryptKit(frtn, "feeFEEDDecryptBlock"); + } + if(actMoved > plainTextLen) { + /* Overflow already occurred! */ + CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR); + } + plainTextLen = actMoved; +} + +/* + * Additional query size support, necessary because we don't conform to + * BlockCryptor's standard one-to-one block scheme + */ + +#define BUFFER_DEBUG 0 +#if BUFFER_DEBUG +#define bprintf(s) printf s +#else +#define bprintf(s) +#endif + +size_t CryptKit::FEEDContext::inputSize( + size_t outSize) // input for given output size +{ + /* + * We've been assured that this is NOT called for the final() op... + */ + unsigned inSize; + if(encoding()) { + inSize = feeFEEDPlainTextSize(mFeeFeed, outSize, 0); + } + else { + inSize = feeFEEDCipherTextSize(mFeeFeed, outSize, 0); + } + + /* account for possible pending buffered input */ + if(inSize >= inBufSize()) { + inSize -= inBufSize(); + } + + /* round up to next block size, then lop off one...anything from + * blockSize*n to (blockSize*n)-1 has same effect */ + unsigned inBlocks = ((inSize + inBlockSize()) / inBlockSize()); + inSize = (inBlocks * inBlockSize()) - 1; + bprintf(("--- FEEDContext::inputSize inSize 0x%x outSize 0x%x\n", + inSize, outSize)); + return inSize; +} + +size_t CryptKit::FEEDContext::outputSize( + bool final, + size_t inSize) // output for given input size +{ + size_t rtn; + if(encoding()) { + rtn = feeFEEDCipherTextSize(mFeeFeed, inSize + inBufSize(), final ? 1 : 0); + } + else { + rtn = feeFEEDPlainTextSize(mFeeFeed, inSize + inBufSize(), final ? 1 : 0); + } + bprintf(("--- FEEDContext::outputSize inSize 0x%x outSize 0x%x final %d\n", + inSize, rtn, final)); + return rtn; +} + +void CryptKit::FEEDContext::minimumProgress( + size_t &in, + size_t &out) // minimum progress chunks +{ + if(encoding()) { + /* + * -- in := one block plaintext + * -- out := current cipher size for one block plaintext + */ + in = inBlockSize(); + out = feeFEEDCipherBufSize(mFeeFeed, 0); + } + else { + /* + * -- in := current cipher size for one block plaintext + * -- out := one block plaintext + */ + in = feeFEEDCipherBufSize(mFeeFeed, 0); + out = outBlockSize(); + } + + /* + * Either case - input adjusted for pending. Note inBufSize can be up to one + * input block size, leaving the temp result zero here.... + */ + assert(in >= inBufSize()); + in -= inBufSize(); + + /* if it is zero, bump it up so caller can make something happen */ + if(in == 0) { + in++; + } + bprintf(("--- FEEDContext::minProgres inSize 0x%x outSize 0x%x\n", + in, out)); +} + +/*** + *** FEEDExp - 2:1 FEED - encrypt n bytes of plaintext, get (roughly) 2n bytes + *** of ciphertext. Ciphertext is larger than with FEED, but this is faster. + ***/ +CryptKit::FEEDExpContext::~FEEDExpContext() +{ + if(mFeeFeedExp) { + feeFEEDExpFree(mFeeFeedExp); + mFeeFeedExp = NULL; + } + if(mFeeKey && mAllocdFeeKey) { + feePubKeyFree(mFeeKey); + } + mFeeKey = NULL; + mInitFlag = false; +} + +// called by CSPFullPluginSession; reusable +void CryptKit::FEEDExpContext::init( + const Context &context, + bool encoding) +{ + if(mInitFlag && !opStarted()) { + /* reusing - e.g. query followed by encrypt */ + return; + } + + /* fetch FEE key from context */ + CSSM_KEYCLASS keyClass; + CSSM_KEYUSE keyUse; + + if(encoding) { + /* encrypting to public key */ + keyClass = CSSM_KEYCLASS_PUBLIC_KEY; + keyUse = CSSM_KEYUSE_ENCRYPT; + } + else { + /* decrypting with private key */ + keyClass = CSSM_KEYCLASS_PRIVATE_KEY; + keyUse = CSSM_KEYUSE_DECRYPT; + } + if(mFeeKey == NULL) { + assert(!opStarted()); + mFeeKey = contextToFeeKey(context, + session(), + CSSM_ATTRIBUTE_KEY, + keyClass, + keyUse, + mAllocdFeeKey); + } + else { + assert(opStarted()); + } + + /* validate context - no other attributes allowed */ + validateFeedContext(context); + + /* OK, looks good. Cook up a feeFEEDExp object. */ + if(mFeeFeedExp != NULL) { + /* not reusable */ + assert(opStarted()); + feeFEEDExpFree(mFeeFeedExp); + mFeeFeedExp = NULL; + } + mFeeFeedExp = feeFEEDExpNewWithPubKey(mFeeKey, + feeRandCallback, + &session()); + if(mFeeFeedExp == NULL) { + CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_KEY); + } + + /* finally, have BlockCryptor set up its stuff. */ + unsigned plainBlockSize = feeFEEDExpPlainBlockSize(mFeeFeedExp); + unsigned cipherBlockSize = feeFEEDExpCipherBlockSize(mFeeFeedExp); + setup(encoding ? plainBlockSize : cipherBlockSize, // blockSizeIn + encoding ? cipherBlockSize : plainBlockSize, // blockSizeOut + false, // pkcs5Pad + true, // needsFinal + BCM_ECB, + NULL); // IV + mInitFlag = true; +} + +// called by BlockCryptor +void CryptKit::FEEDExpContext::encryptBlock( + const void *plainText, // length implied (one block) + size_t plainTextLen, + void *cipherText, + size_t &cipherTextLen, // in/out, throws on overflow + bool final) +{ + feeReturn frtn; + unsigned actMoved; + + assert(mFeeFeedExp != NULL); + frtn = feeFEEDExpEncryptBlock(mFeeFeedExp, + (unsigned char *)plainText, + plainTextLen, + (unsigned char *)cipherText, + &actMoved, + final ? 1 : 0); + if(frtn) { + throwCryptKit(frtn, "feeFEEDExpEncryptBlock"); + } + if(actMoved > cipherTextLen) { + /* Overflow already occurred! */ + CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR); + } + cipherTextLen = actMoved; +} + +void CryptKit::FEEDExpContext::decryptBlock( + const void *cipherText, // length implied (one cipher block) + size_t cipherTextLen, + void *plainText, + size_t &plainTextLen, // in/out, throws on overflow + bool final) +{ + feeReturn frtn; + unsigned actMoved; + + assert(mFeeFeedExp != NULL); + frtn = feeFEEDExpDecryptBlock(mFeeFeedExp, + (unsigned char *)cipherText, + inBlockSize(), + (unsigned char *)plainText, + &actMoved, + final ? 1 : 0); + if(frtn) { + throwCryptKit(frtn, "feeFEEDExpDecryptBlock"); + } + if(actMoved > plainTextLen) { + /* Overflow already occurred! */ + CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR); + } + plainTextLen = actMoved; +} + +/* convert uint32 to big-endian 4 bytes */ +static void int32ToBytes( + uint32_t i, + unsigned char *b) +{ + for(int dex=3; dex>=0; dex--) { + b[dex] = i; + i >>= 8; + } +} + +/* + * X9.63 key derivation with optional SharedInfo passed as + * context attribute CSSM_ATTRIBUTE_SALT. + */ +static feeReturn ecdhKdf( + const Context &context, + const unsigned char *Z, /* shared secret, i.e., output of ECDH */ + unsigned ZLen, + CSSM_DATA *K) /* output RETURNED in K->Data, length K->Length bytes */ +{ + /* SharedInfo via salt, from context, optional */ + const unsigned char *sharedInfo = NULL; + CSSM_SIZE sharedInfoLen = 0; + + CssmData *salt = context.get(CSSM_ATTRIBUTE_SALT); + if(salt != NULL) { + sharedInfo = (const unsigned char *)salt->Data; + sharedInfoLen = salt->Length; + } + + unsigned char *outp = K->Data; + CSSM_SIZE bytesToGo = K->Length; + CC_SHA1_CTX sha1; + uint32_t counter = 1; + uint8 counterBytes[4]; + unsigned char digOut[CC_SHA1_DIGEST_LENGTH]; + + do { + /* K[i] = Hash(Z || Counter || SharedInfo) */ + CC_SHA1_Init(&sha1); + CC_SHA1_Update(&sha1, Z, ZLen); + int32ToBytes(counter, counterBytes); + CC_SHA1_Update(&sha1, counterBytes, 4); + if(sharedInfoLen) { + CC_SHA1_Update(&sha1, sharedInfo, sharedInfoLen); + } + CC_SHA1_Final(digOut, &sha1); + + /* digest --> output */ + unsigned toMove = CC_SHA1_DIGEST_LENGTH; + if(toMove > bytesToGo) { + toMove = bytesToGo; + } + memmove(outp, digOut, toMove); + + counter++; + outp += toMove; + bytesToGo -= toMove; + + } while(bytesToGo); + + return FR_Success; +} + +/* + * Elliptic curve Diffie-Hellman key exchange. The public key is + * specified in one of two ways - a raw X9.62 format public key + * string in Param, or a CSSM_KEY in the Context. + * Requested size, in keyData->Length, must be the same size as + * the keys' modulus. Data is returned in keyData->Data, which is + * allocated by the caller. + * Optionally performs X9.63 key derivation if algId == + * CSSM_ALGID_ECDH_X963_KDF, with the optional SharedInfo passed + * as optional context attribute CSSM_ATTRIBUTE_SALT. + */ +void CryptKit::DeriveKey_ECDH ( + const Context &context, + CSSM_ALGORITHMS algId, + const CssmData &Param, // other's public key. may be empty + CSSM_DATA *keyData, // mallocd by caller + // we fill in keyData->Length bytes + AppleCSPSession &session) +{ + bool mallocdPrivKey; + size_t privSize; + + /* private ECDH key from context - required */ + feePubKey privKey = contextToFeeKey(context, session, CSSM_ATTRIBUTE_KEY, + CSSM_KEYCLASS_PRIVATE_KEY, CSSM_KEYUSE_DERIVE, mallocdPrivKey); + if(privKey == NULL) { + CssmError::throwMe(CSSMERR_CSP_MISSING_ATTR_KEY); + } + privSize = (feePubKeyBitsize(privKey) + 7) / 8; + if((algId == CSSM_ALGID_ECDH) & (privSize != keyData->Length)) { + /* exact match required here */ + CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR); + } + + /* + * Public key ("their" key) can come from two places: + * -- in the context as a CSSM_ATTRIBUTE_PUBLIC_KEY. This is how + * public keys in X509 format must be used in this function. + * -- in the incoming Param, the raw unformatted (ANSI X9.62) form + */ + bool mallocdPubKey = false; + feePubKey pubKey = NULL; + if(Param.Data == NULL) { + /* this throws if no key present */ + pubKey = contextToFeeKey(context, session, CSSM_ATTRIBUTE_PUBLIC_KEY, + CSSM_KEYCLASS_PUBLIC_KEY, CSSM_KEYUSE_DERIVE, mallocdPubKey); + } + if((pubKey == NULL) && (Param.Data == NULL)) { + errorLog0("DeriveKey_ECDH: no pub_key\n"); + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY); + } + unsigned char *output = NULL; + unsigned outputLen = 0; + feeReturn frtn = feePubKeyECDH(privKey, pubKey, + (const unsigned char *)Param.Data, (unsigned)Param.Length, + &output, &outputLen); + if(frtn) { + goto errOut; + } + switch(algId) { + case CSSM_ALGID_ECDH: + /* + * Raw ECDH - requested length must match the generated size + * exactly. If so, return the result unmodified. + */ + if(outputLen != keyData->Length) { + errorLog0("DeriveKey_ECDH: length mismatch\n"); + frtn = FR_Internal; + break; + } + memmove(keyData->Data, output, outputLen); + break; + case CSSM_ALGID_ECDH_X963_KDF: + /* Further processing... */ + frtn = ecdhKdf(context, output, outputLen, keyData); + break; + default: + /* shouldn't be here */ + frtn = FR_Internal; + break; + } + +errOut: + if(mallocdPrivKey) { + feePubKeyFree(privKey); + } + if(mallocdPubKey) { + feePubKeyFree(pubKey); + } + if(output != NULL) { + ffree(output); + } + if(frtn) { + throwCryptKit(frtn, NULL); + } +} + +#endif /* CRYPTKIT_CSP_ENABLE */ diff --git a/libsecurity_apple_csp/lib/FEEAsymmetricContext.h b/libsecurity_apple_csp/lib/FEEAsymmetricContext.h new file mode 100644 index 00000000..6546cb51 --- /dev/null +++ b/libsecurity_apple_csp/lib/FEEAsymmetricContext.h @@ -0,0 +1,146 @@ +/* + * 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. + */ + + +/* + * FEEAsymmetricContext.h - CSPContexts for FEE asymmetric encryption + * + * Created March 8 2001 by dmitch. + */ + +#ifdef CRYPTKIT_CSP_ENABLE + +#ifndef _FEE_ASYMMETRIC_CONTEXT_H_ +#define _FEE_ASYMMETRIC_CONTEXT_H_ + +#include +#include "AppleCSP.h" +#include "AppleCSPContext.h" +#include "AppleCSPSession.h" +#include "BlockCryptor.h" +#include +#include + +namespace CryptKit { + +class FEEDContext : public BlockCryptor { +public: + FEEDContext(AppleCSPSession &session) : + BlockCryptor(session), + mFeeFeed(NULL), + mPrivKey(NULL), + mPubKey(NULL), + mInitFlag(false) { } + ~FEEDContext(); + + /* called by CSPFullPluginSession */ + void init(const Context &context, bool encoding = true); + + /* called by BlockCryptor */ + void encryptBlock( + const void *plainText, // length implied (one block) + size_t plainTextLen, + void *cipherText, + size_t &cipherTextLen, // in/out, throws on overflow + bool final); + void decryptBlock( + const void *cipherText, // length implied (one cipher block) + size_t cipherTextLen, + void *plainText, + size_t &plainTextLen, // in/out, throws on overflow + bool final); + + /* + * Additional query size support, necessary because we don't conform to + * BlockCryptor's standard one-to-one block scheme + */ + 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: + feeFEED mFeeFeed; + feePubKey mPrivKey; + bool mAllocdPrivKey; + feePubKey mPubKey; + bool mAllocdPubKey; + bool mInitFlag; // allows easy reuse +}; /* FEEDContext */ + + +class FEEDExpContext : public BlockCryptor { +public: + FEEDExpContext(AppleCSPSession &session) : + BlockCryptor(session), + mFeeFeedExp(NULL), + mFeeKey(NULL), + mInitFlag(false) { } + + ~FEEDExpContext(); + + /* called by CSPFullPluginSession */ + void init(const Context &context, bool encoding = true); + + /* called by BlockCryptor */ + void encryptBlock( + const void *plainText, // length implied (one block) + size_t plainTextLen, + void *cipherText, + size_t &cipherTextLen, // in/out, throws on overflow + bool final); + void decryptBlock( + const void *cipherText, // length implied (one cipher block) + size_t cipherTextLen, + void *plainText, + size_t &plainTextLen, // in/out, throws on overflow + bool final); + +private: + feeFEEDExp mFeeFeedExp; + feePubKey mFeeKey; + bool mAllocdFeeKey; + bool mInitFlag; // allows easy reuse +}; /* FEEDExpContext */ + +/* + * Elliptic curve Diffie-Hellman key exchange. The public key is + * specified in one of two ways - a raw X9.62 format public key + * string in Param, or a CSSM_KEY in the Context. + * Requested size, in keyData->Length, must be the same size as + * the keys' modulus. Data is returned in keyData->Data, which is + * allocated by the caller. + * Optionally performs X9.63 key derivation if algId == + * CSSM_ALGID_ECDH_X963_KDF, with the optional SharedInfo passed + * as optional context attribute CSSM_ATTRIBUTE_SALT. + */ +extern void DeriveKey_ECDH ( + const Context &context, + CSSM_ALGORITHMS algId, + const CssmData &Param, + CSSM_DATA *keyData, + AppleCSPSession &session); + +} /* namespace CryptKit */ + +#endif /* _FEE_ASYMMETRIC_CONTEXT_H_ */ +#endif /* CRYPTKIT_CSP_ENABLE */ diff --git a/libsecurity_apple_csp/lib/FEECSPUtils.cpp b/libsecurity_apple_csp/lib/FEECSPUtils.cpp new file mode 100644 index 00000000..f20bff62 --- /dev/null +++ b/libsecurity_apple_csp/lib/FEECSPUtils.cpp @@ -0,0 +1,353 @@ +/* + * 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. + */ + + +/* + * FEECSPUtils.h - Misc. utility function for FEE/CryptKit CSP. + * + * Created 2/20/2001 by dmitch. + */ + +#ifdef CRYPTKIT_CSP_ENABLE + +#include +#include +#include "FEECSPUtils.h" +#include "FEEKeys.h" +#include +#include + +#define feeMiscDebug(args...) secdebug("feeMisc", ## args) + +/* Given a FEE error, throw appropriate CssmError */ +void CryptKit::throwCryptKit( + feeReturn frtn, + const char *op) /* optional */ +{ + if(op) { + Security::Syslog::error("Apple CSP %s: %s", op, feeReturnString(frtn)); + } + switch(frtn) { + case FR_Success: + return; + case FR_BadPubKey: + case FR_BadPubKeyString: + case FR_IncompatibleKey: + case FR_BadKeyBlob: + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY); + case FR_IllegalDepth: + CssmError::throwMe(CSSMERR_CSP_UNSUPPORTED_KEY_SIZE); + case FR_BadSignatureFormat: /* signature corrupted */ + CssmError::throwMe(CSSMERR_CSP_INVALID_SIGNATURE); + case FR_InvalidSignature: /* signature intact, but not valid */ + CssmError::throwMe(CSSMERR_CSP_VERIFY_FAILED); + case FR_IllegalArg: /* illegal argument */ + CssmError::throwMe(CSSMERR_CSP_INVALID_CONTEXT); + case FR_BadCipherText: /* malformed ciphertext */ + case FR_BadEnc64: /* bad enc64() format */ + CssmError::throwMe(CSSMERR_CSP_INVALID_DATA); + case FR_Unimplemented: /* unimplemented function */ + CssmError::throwMe(CSSMERR_CSP_FUNCTION_NOT_IMPLEMENTED); + case FR_Memory: /* unimplemented function */ + CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR); + case FR_ShortPrivData: + CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_SEED); + case FR_IllegalCurve: /* e.g., ECDSA with Montgomery curve */ + CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_KEY); + + /* I don't think we should ever see these no matter what the + * caller throws at us */ + case FR_WrongSignatureType: /* ElGamal vs. ECDSA */ + case FR_BadUsageName: /* bad usageName */ + case FR_BadCipherFile: + case FR_Internal: /* internal library error */ + CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR); + } +} + +/* + * Given a Context: + * -- obtain CSSM key of specified CSSM_ATTRIBUTE_TYPE + * -- validate keyClass + * -- validate keyUsage + * -- convert to feePubKey, allocating the feePubKey if necessary + * + * Returned key can be of algorithm CSSM_ALGID_ECDSA or CSSM_ALGID_FEE; + * caller has to verify proper algorithm for operation. + */ +feePubKey CryptKit::contextToFeeKey( + const Context &context, + AppleCSPSession &session, + CSSM_ATTRIBUTE_TYPE attrType, // CSSM_ATTRIBUTE_KEY, CSSM_ATTRIBUTE_PUBLIC_KEY + CSSM_KEYCLASS keyClass, // CSSM_KEYCLASS_{PUBLIC,PRIVATE}_KEY + CSSM_KEYUSE usage, // CSSM_KEYUSE_ENCRYPT, CSSM_KEYUSE_SIGN, etc. + bool &mallocdKey) // RETURNED +{ + CssmKey &cssmKey = + context.get(attrType, CSSMERR_CSP_MISSING_ATTR_KEY); + const CSSM_KEYHEADER &hdr = cssmKey.KeyHeader; + switch(hdr.AlgorithmId) { + case CSSM_ALGID_FEE: + case CSSM_ALGID_ECDSA: + break; + default: + CssmError::throwMe(CSSMERR_CSP_ALGID_MISMATCH); + } + if(hdr.KeyClass != keyClass) { + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS); + } + cspValidateIntendedKeyUsage(&hdr, usage); + cspVerifyKeyTimes(hdr); + return cssmKeyToFee(cssmKey, session, mallocdKey); +} + +/* + * Convert a CssmKey to a feePubKey. May result in the creation of a new + * feePubKey (when cssmKey is a raw key); allocdKey is true in that case + * in which case the caller generally has to free the allocd key). + */ +feePubKey CryptKit::cssmKeyToFee( + const CssmKey &cssmKey, + AppleCSPSession &session, + bool &allocdKey) // RETURNED +{ + feePubKey feeKey = NULL; + allocdKey = false; + + const CSSM_KEYHEADER *hdr = &cssmKey.KeyHeader; + switch(hdr->AlgorithmId) { + case CSSM_ALGID_FEE: + case CSSM_ALGID_ECDSA: + break; + default: + // someone else's key (should never happen) + CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM); + } + switch(hdr->BlobType) { + case CSSM_KEYBLOB_RAW: + feeKey = rawCssmKeyToFee(cssmKey); + allocdKey = true; + break; + case CSSM_KEYBLOB_REFERENCE: + { + BinaryKey &binKey = session.lookupRefKey(cssmKey); + FEEBinaryKey *feeBinKey = dynamic_cast(&binKey); + /* this cast failing means that this is some other + * kind of binary key */ + if(feeBinKey == NULL) { + feeMiscDebug("CryptKit::cssmKeyToFee: wrong BinaryKey subclass\n"); + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY); + } + assert(feeBinKey->feeKey() != NULL); + feeKey = feeBinKey->feeKey(); + break; + } + default: + CssmError::throwMe(CSSMERR_CSP_KEY_BLOB_TYPE_INCORRECT); + } + return feeKey; +} + +/* + * Convert a raw CssmKey to a newly alloc'd feePubKey. + */ +feePubKey CryptKit::rawCssmKeyToFee( + const CssmKey &cssmKey) +{ + const CSSM_KEYHEADER *hdr = &cssmKey.KeyHeader; + assert(hdr->BlobType == CSSM_KEYBLOB_RAW); + + switch(hdr->AlgorithmId) { + case CSSM_ALGID_FEE: + case CSSM_ALGID_ECDSA: + break; + default: + // someone else's key (should never happen) + CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM); + } + + switch(hdr->KeyClass) { + case CSSM_KEYCLASS_PUBLIC_KEY: + case CSSM_KEYCLASS_PRIVATE_KEY: + break; + default: + // someone else's key + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS); + } + + feePubKey feeKey = feePubKeyAlloc(); + if(feeKey == NULL) { + CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR); + } + + feeReturn frtn = FR_IllegalArg; + bool badFormat = false; + + /* + * The actual key init depends on key type and incoming format + */ + switch(hdr->AlgorithmId) { + case CSSM_ALGID_FEE: + switch(hdr->KeyClass) { + case CSSM_KEYCLASS_PUBLIC_KEY: + switch(hdr->Format) { + case FEE_KEYBLOB_DEFAULT_FORMAT: + /* FEE, public key, default: custom DER */ + frtn = feePubKeyInitFromDERPubBlob(feeKey, + cssmKey.KeyData.Data, + cssmKey.KeyData.Length); + break; + case CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING: + /* FEE, public key, native byte stream */ + frtn = feePubKeyInitFromPubBlob(feeKey, + cssmKey.KeyData.Data, + cssmKey.KeyData.Length); + break; + default: + badFormat = true; + break; + } + break; + case CSSM_KEYCLASS_PRIVATE_KEY: + switch(hdr->Format) { + case FEE_KEYBLOB_DEFAULT_FORMAT: + /* FEE, private key, default: custom DER */ + frtn = feePubKeyInitFromDERPrivBlob(feeKey, + cssmKey.KeyData.Data, + cssmKey.KeyData.Length); + break; + case CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING: + /* FEE, private key, native byte stream */ + frtn = feePubKeyInitFromPrivBlob(feeKey, + cssmKey.KeyData.Data, + cssmKey.KeyData.Length); + break; + default: + badFormat = true; + break; + } + break; + default: + /* not reached, we already checked */ + break; + } + /* end of case ALGID_FEE */ + break; + + case CSSM_ALGID_ECDSA: + switch(hdr->KeyClass) { + case CSSM_KEYCLASS_PUBLIC_KEY: + switch(hdr->Format) { + case CSSM_KEYBLOB_RAW_FORMAT_NONE: + case CSSM_KEYBLOB_RAW_FORMAT_X509: + /* ECDSA, public key, default: X509 */ + frtn = feePubKeyInitFromX509Blob(feeKey, + cssmKey.KeyData.Data, + cssmKey.KeyData.Length); + break; + + case CSSM_KEYBLOB_RAW_FORMAT_OPENSSL: + /* + * An oddity here: we can parse this incoming key, but + * it contains both private and public parts. We throw + * out the private component here. + */ + frtn = feePubKeyInitFromOpenSSLBlob(feeKey, + 1, /* pubOnly */ + cssmKey.KeyData.Data, + cssmKey.KeyData.Length); + break; + /* + * NOTE: we cannot *import* a key in raw X9.62 format. + * We'd need to know the curve, i.e., the feeDepth. + * I suppose we could infer that from the blob length but + * a better way would be to have a new context attribute + * specifying which curve. + * For now, imported raw keys have to be in X509 format. + */ + case CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING: + default: + badFormat = true; + break; + } + break; + case CSSM_KEYCLASS_PRIVATE_KEY: + switch(hdr->Format) { + case CSSM_KEYBLOB_RAW_FORMAT_PKCS8: + /* ECDSA, private key, PKCS8 */ + frtn = feePubKeyInitFromPKCS8Blob(feeKey, + cssmKey.KeyData.Data, + cssmKey.KeyData.Length); + break; + + case CSSM_KEYBLOB_RAW_FORMAT_NONE: + case CSSM_KEYBLOB_RAW_FORMAT_OPENSSL: + /* ECDSA, private, default: OpenSSL */ + /* see comment above re: OpenSSL public/private keys */ + frtn = feePubKeyInitFromOpenSSLBlob(feeKey, + 0, /* pubOnly */ + cssmKey.KeyData.Data, + cssmKey.KeyData.Length); + break; + /* see comment above about X9.62 format public key blobs */ + case CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING: + default: + badFormat = true; + break; + } + break; + default: + /* not reached, we already checked */ + break; + } + /* end of case CSSM_ALGID_ECDSA */ + break; + } + if(badFormat) { + CssmError::throwMe(hdr->KeyClass == CSSM_KEYCLASS_PRIVATE_KEY ? + CSSMERR_CSP_INVALID_ATTR_PRIVATE_KEY_FORMAT : + CSSMERR_CSP_INVALID_ATTR_PUBLIC_KEY_FORMAT); + } + if(frtn) { + feePubKeyFree(feeKey); + throwCryptKit(frtn, "feePubKeyInitFromKeyBlob"); + } + return feeKey; +} + +/* + * Glue function which allows C code to use AppleCSPSession + * as an RNG. A ptr to this function gets passed down to + * CryptKit C functions as a feeRandFcn. + */ +feeReturn CryptKit::feeRandCallback( + void *ref, // actually an AppleCSPSession * + unsigned char *bytes, // must be alloc'd by caller + unsigned numBytes) +{ + AppleCSPSession *session = + reinterpret_cast(ref); + try { + session->getRandomBytes(numBytes, bytes); + } + catch(...) { + return FR_Internal; + } + return FR_Success; +} + +#endif /* CRYPTKIT_CSP_ENABLE */ diff --git a/libsecurity_apple_csp/lib/FEECSPUtils.h b/libsecurity_apple_csp/lib/FEECSPUtils.h new file mode 100644 index 00000000..986d29ce --- /dev/null +++ b/libsecurity_apple_csp/lib/FEECSPUtils.h @@ -0,0 +1,92 @@ +/* + * 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. + */ + + +/* + * FEECSPUtils.h - Misc. utility function for FEE/CryptKit CSP. + * + * Created 2/20/2001 by dmitch. + */ + +#ifdef CRYPTKIT_CSP_ENABLE + +#ifndef _FEE_CSP_UTILS_H_ +#define _FEE_CSP_UTILS_H_ + +#include "AppleCSPSession.h" +#include +#include + +/* + * Default FEE keyblob format, indicating DER-encoding. + * FEE keys can optionally be generated by requesting + * CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING, indicating native FEE key blobs. + */ +#define FEE_KEYBLOB_DEFAULT_FORMAT CSSM_KEYBLOB_RAW_FORMAT_NONE + +namespace CryptKit { + +/* Given a FEE error, throw appropriate CssmError */ +void throwCryptKit( + feeReturn frtn, + const char *op); /* optional */ + +/* + * Given a Context: + * -- obtain CSSM key of specified CSSM_ATTRIBUTE_TYPE + * -- validate keyClass + * -- validate keyUsage + * -- convert to feePubKey, allocating the feePubKey if necessary + */ +feePubKey contextToFeeKey( + const Context &context, + AppleCSPSession &session, + CSSM_ATTRIBUTE_TYPE attrType, // CSSM_ATTRIBUTE_KEY, CSSM_ATTRIBUTE_PUBLIC_KEY + CSSM_KEYCLASS keyClass, // CSSM_KEYCLASS_{PUBLIC,PRIVATE}_KEY + CSSM_KEYUSE usage, // CSSM_KEYUSE_ENCRYPT, CSSM_KEYUSE_SIGN, etc. + bool &mallocdKey); // RETURNED + +/* + * Convert a CssmKey to a feePubKey. May result in the creation of a new + * feePubKey (when cssmKey is a raw key); allocdKey is true in that case + * in which case the caller generally has to free the allocd key). + */ +feePubKey cssmKeyToFee( + const CssmKey &cssmKey, + AppleCSPSession &session, + bool &allocdKey); // RETURNED + +/* + * Convert a raw CssmKey to a newly alloc'd feePubKey. + */ +feePubKey rawCssmKeyToFee( + const CssmKey &cssmKey); + +/* + * Glue function which allows C code to use AppleCSPSession + * as an RNG. A ptr to this function gets passed down to + * CryptKit C functions as a feeRandFcn. + */ +feeReturn feeRandCallback( + void *ref, // actually an AppleCSPSession * + unsigned char *bytes, // must be alloc'd by caller + unsigned numBytes); + +} /* namespace CryptKit */ + +#endif /* _FEE_CSP_UTILS_H_ */ +#endif /* CRYPTKIT_CSP_ENABLE */ diff --git a/libsecurity_apple_csp/lib/FEEKeys.cpp b/libsecurity_apple_csp/lib/FEEKeys.cpp new file mode 100644 index 00000000..90220ba0 --- /dev/null +++ b/libsecurity_apple_csp/lib/FEEKeys.cpp @@ -0,0 +1,454 @@ +/* + * 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. + */ + + +/* + * FEEKeys.cpp - FEE-related asymmetric key pair classes. + * + * Created 2/21/2001 by dmitch. + */ + +#ifdef CRYPTKIT_CSP_ENABLE + +#include "FEEKeys.h" +#include "FEECSPUtils.h" +#include "CryptKitSpace.h" +#include +#include +#include +#include "AppleCSPSession.h" +#include "AppleCSPUtils.h" +#include +#include + +#define feeKeyDebug(args...) secdebug("feeKey", ## args) + +/*** + *** FEE-style BinaryKey + ***/ + +/* constructor with optional existing feePubKey */ +CryptKit::FEEBinaryKey::FEEBinaryKey(feePubKey feeKey) + : mFeeKey(feeKey) +{ + if(mFeeKey == NULL) { + mFeeKey = feePubKeyAlloc(); + if(mFeeKey == NULL) { + CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR); + } + } +} + +CryptKit::FEEBinaryKey::~FEEBinaryKey() +{ + if(mFeeKey) { + feePubKeyFree(mFeeKey); + mFeeKey = NULL; + } +} + +void CryptKit::FEEBinaryKey::generateKeyBlob( + Allocator &allocator, + CssmData &blob, + CSSM_KEYBLOB_FORMAT &format, + AppleCSPSession &session, + const CssmKey *paramKey, /* optional, unused here */ + CSSM_KEYATTR_FLAGS &attrFlags) /* IN/OUT */ +{ + unsigned char *keyBlob; + unsigned len; + feeReturn frtn = FR_Internal; + bool freeTheKey = false; + feePubKey keyToEncode = mFeeKey; + + assert(mFeeKey != NULL); + if((format == CSSM_KEYBLOB_RAW_FORMAT_DIGEST) && + (mKeyHeader.KeyClass == CSSM_KEYCLASS_PRIVATE_KEY)) { + /* key digest calculation; special case for private keys: cook + * up the associated public key and encode that */ + keyToEncode = feePubKeyAlloc(); + if(keyToEncode == NULL) { + CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR); + } + frtn = feePubKeyInitPubKeyFromPriv(mFeeKey, keyToEncode); + if(frtn) { + feePubKeyFree(keyToEncode); + throwCryptKit(frtn, "feePubKeyInitPubKeyFromPriv"); + } + freeTheKey = true; + } + + bool badFormat = false; + int isPrivate = feePubKeyIsPrivate(keyToEncode); + + switch(mKeyHeader.AlgorithmId) { + case CSSM_ALGID_FEE: + if(isPrivate) { + /* FEE private key */ + switch(format) { + case CSSM_KEYBLOB_RAW_FORMAT_DIGEST: + format = CSSM_KEYBLOB_RAW_FORMAT_NONE; + /* and drop thru */ + case CSSM_KEYBLOB_RAW_FORMAT_NONE: + frtn = feePubKeyCreateDERPrivBlob(keyToEncode, &keyBlob, &len); + break; + case CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING: + frtn = feePubKeyCreatePrivBlob(keyToEncode, &keyBlob, &len); + break; + default: + badFormat = true; + break; + } + } + else { + /* FEE Public key */ + switch(format) { + case CSSM_KEYBLOB_RAW_FORMAT_DIGEST: + format = CSSM_KEYBLOB_RAW_FORMAT_NONE; + /* and drop thru */ + case CSSM_KEYBLOB_RAW_FORMAT_NONE: + frtn = feePubKeyCreateDERPubBlob(keyToEncode, &keyBlob, &len); + break; + case CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING: + frtn = feePubKeyCreatePubBlob(keyToEncode, &keyBlob, &len); + break; + default: + badFormat = true; + break; + } + } + /* end of base ALGID_FEE */ + break; + + case CSSM_ALGID_ECDSA: + if(isPrivate) { + /* ECDSA/ECDH private key */ + switch(format) { + case CSSM_KEYBLOB_RAW_FORMAT_PKCS8: + /* ECDSA private key: PKCS8 */ + frtn = feePubKeyCreatePKCS8Blob(keyToEncode, &keyBlob, &len); + break; + case CSSM_KEYBLOB_RAW_FORMAT_NONE: + /* set to default format, drop thru */ + format = CSSM_KEYBLOB_RAW_FORMAT_OPENSSL; + case CSSM_KEYBLOB_RAW_FORMAT_OPENSSL: + /* ECDSA private key, SEC1/OpenSSL format */ + frtn = feePubKeyCreateOpenSSLBlob(keyToEncode, &keyBlob, &len); + break; + case CSSM_KEYBLOB_RAW_FORMAT_DIGEST: + format = CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING; + /* and drop thru */ + case CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING: + /* raw private key bytes */ + frtn = feeCreateECDSAPrivBlob(keyToEncode, &keyBlob, &len); + break; + default: + badFormat = true; + break; + } + } + else { + /* + * ECDSA public key. + * Note there is no OpenSSL case here, that format is only generated for + * private keys. + */ + switch(format) { + case CSSM_KEYBLOB_RAW_FORMAT_NONE: + /* set to default format, drop thru */ + format = CSSM_KEYBLOB_RAW_FORMAT_X509; + case CSSM_KEYBLOB_RAW_FORMAT_X509: + /* ECDSA, public key, default: X509 */ + frtn = feePubKeyCreateX509Blob(keyToEncode, &keyBlob, &len); + break; + case CSSM_KEYBLOB_RAW_FORMAT_DIGEST: + format = CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING; + /* and drop thru */ + case CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING: + /* raw x|y string */ + frtn = feeCreateECDSAPubBlob(keyToEncode, &keyBlob, &len); + break; + default: + badFormat = true; + break; + } + } + /* end of case CSSM_ALGID_ECDSA */ + break; + default: + /* not reached */ + break; + } + + if(badFormat) { + CssmError::throwMe(isPrivate ? + CSSMERR_CSP_INVALID_ATTR_PRIVATE_KEY_FORMAT : + CSSMERR_CSP_INVALID_ATTR_PUBLIC_KEY_FORMAT); + } + if(frtn) { + throwCryptKit(frtn, "feePubKeyCreate*Blob"); + } + setUpCssmData(blob, len, allocator); + memmove(blob.data(), keyBlob, len); + blob.length(len); + ffree(keyBlob); + if(freeTheKey) { + /* free the temp pub key we created here */ + feePubKeyFree(keyToEncode); + } +} + +/*** + *** FEE-style AppleKeyPairGenContext + ***/ + +/* + * This one is specified in, and called from, CSPFullPluginSession. Our + * only job is to prepare two subclass-specific BinaryKeys and call up to + * AppleKeyPairGenContext. + */ +void CryptKit::FEEKeyPairGenContext::generate( + const Context &context, + CssmKey &pubKey, + CssmKey &privKey) +{ + FEEBinaryKey *pubBinKey = new FEEBinaryKey(); + FEEBinaryKey *privBinKey = new FEEBinaryKey(); + + try { + AppleKeyPairGenContext::generate(context, + session(), + pubKey, + pubBinKey, + privKey, + privBinKey); + } + catch (...) { + delete pubBinKey; + delete privBinKey; + throw; + } + +} + +// this one is specified in, and called from, AppleKeyPairGenContext +void CryptKit::FEEKeyPairGenContext::generate( + const Context &context, + BinaryKey &pubBinKey, + BinaryKey &privBinKey, + uint32 &keyBits) +{ + /* + * These casts throw exceptions if the keys are of the + * wrong classes, which would be a major bogon, since we created + * the keys in the above generate() function. + */ + FEEBinaryKey &fPubBinKey = + dynamic_cast(pubBinKey); + FEEBinaryKey &fPrivBinKey = + dynamic_cast(privBinKey); + + /* + * Two parameters from context. Key size in bits is required; + * seed is optional. If not present, we cook up random private data. + */ + keyBits = context.getInt(CSSM_ATTRIBUTE_KEY_LENGTH, + CSSMERR_CSP_MISSING_ATTR_KEY_LENGTH); + CssmCryptoData *cseed = context.get(CSSM_ATTRIBUTE_SEED); + CssmData *seed; + bool haveSeed; + CssmAutoData aSeed(session()); // malloc on demand + if(cseed) { + /* caller specified seed */ + haveSeed = true; + seed = &cseed->param(); + } + else { + /* generate random seed */ + haveSeed = false; + unsigned keyBytes = ((keyBits + 7) / 8) + 1; + aSeed.malloc(keyBytes); + session().getRandomBytes(keyBytes, aSeed); + seed = &aSeed.get(); + } + + CSSM_ALGORITHMS algId = context.algorithm(); + + /* Curve and prime types - optional */ + feePrimeType primeType = FPT_Default; + uint32 uPrimeType = context.getInt(CSSM_ATTRIBUTE_FEE_PRIME_TYPE); + switch(uPrimeType) { + case CSSM_FEE_PRIME_TYPE_DEFAULT: + break; + case CSSM_FEE_PRIME_TYPE_MERSENNE: + primeType = FPT_Mersenne; + break; + case CSSM_FEE_PRIME_TYPE_FEE: + primeType = FPT_FEE; + break; + case CSSM_FEE_PRIME_TYPE_GENERAL: + primeType = FPT_General; + break; + default: + /* FIXME - maybe we should be more specific */ + CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_ALG_PARAMS); + } + feeCurveType curveType = FCT_Default; + switch(algId) { + case CSSM_ALGID_ECDSA: + /* no options */ + curveType = FCT_ANSI; + break; + default: + { + uint32 uCurveType = context.getInt(CSSM_ATTRIBUTE_FEE_CURVE_TYPE); + switch(uCurveType) { + case CSSM_FEE_CURVE_TYPE_DEFAULT: + break; + case CSSM_FEE_CURVE_TYPE_MONTGOMERY: + curveType = FCT_Montgomery; + break; + case CSSM_FEE_CURVE_TYPE_WEIERSTRASS: + curveType = FCT_Weierstrass; + break; + case CSSM_FEE_CURVE_TYPE_ANSI_X9_62: + curveType = FCT_ANSI; + break; + default: + /* FIXME - maybe we should be more specific */ + CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_ALG_PARAMS); + } + break; + } + } + feeReturn frtn = feePubKeyInitFromPrivDataKeyBits( + fPrivBinKey.feeKey(), + (unsigned char *)seed->data(), + seed->length(), + keyBits, + primeType, + curveType, + /* + * our random seed: trust it + * caller's seed: hash it + */ + haveSeed ? 1 : 0); + if(frtn) { + throwCryptKit(frtn, "feePubKeyInitFromPrivDataKeyBits"); + } + frtn = feePubKeyInitPubKeyFromPriv(fPrivBinKey.feeKey(), + fPubBinKey.feeKey()); + if(frtn) { + throwCryptKit(frtn, "feePubKeyInitPubKeyFromPriv"); + } +} + + +/*** + *** FEE-style CSPKeyInfoProvider. + ***/ +CryptKit::FEEKeyInfoProvider::FEEKeyInfoProvider( + const CssmKey &cssmKey, + AppleCSPSession &session) : + CSPKeyInfoProvider(cssmKey, session) +{ +} +CSPKeyInfoProvider *FEEKeyInfoProvider::provider( + const CssmKey &cssmKey, + AppleCSPSession &session) +{ + switch(cssmKey.algorithm()) { + case CSSM_ALGID_FEE: + case CSSM_ALGID_ECDSA: + break; + default: + return NULL; + } + switch(cssmKey.keyClass()) { + case CSSM_KEYCLASS_PUBLIC_KEY: + case CSSM_KEYCLASS_PRIVATE_KEY: + /* FIXME - verify proper CSSM_KEYBLOB_RAW_FORMAT_xx */ + break; + default: + return NULL; + } + /* OK, we'll handle this one */ + return new FEEKeyInfoProvider(cssmKey, session); +} + +/* Given a raw key, cook up a Binary key */ +void CryptKit::FEEKeyInfoProvider::CssmKeyToBinary( + CssmKey *paramKey, // optional, ignored + CSSM_KEYATTR_FLAGS &attrFlags, // IN/OUT + BinaryKey **binKey) +{ + *binKey = NULL; + feePubKey feeKey = NULL; + + /* first cook up a feePubKey, then drop that into a BinaryKey */ + feeKey = rawCssmKeyToFee(mKey); + FEEBinaryKey *feeBinKey = new FEEBinaryKey(feeKey); + *binKey = feeBinKey; +} + +/* + * Obtain key size in bits. + * Currently only raw public keys are dealt with (they're the ones + * which come from certs, the only current use for this function). + * Note that if we need to handle ref keys, we'll need a session ref... + */ +void CryptKit::FEEKeyInfoProvider::QueryKeySizeInBits( + CSSM_KEY_SIZE &keySize) +{ + feePubKey feeKey = NULL; + + if(mKey.blobType() != CSSM_KEYBLOB_RAW) { + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_FORMAT); + } + feeKey = rawCssmKeyToFee(mKey); + keySize.LogicalKeySizeInBits = feePubKeyBitsize(feeKey); + keySize.EffectiveKeySizeInBits = keySize.LogicalKeySizeInBits; + feePubKeyFree(feeKey); +} + +/* + * Obtain blob suitable for hashing in CSSM_APPLECSP_KEYDIGEST + * passthrough. + */ +bool CryptKit::FEEKeyInfoProvider::getHashableBlob( + Allocator &allocator, + CssmData &blob) // blob to hash goes here +{ + /* + * The optimized case, a raw key in the "proper" format already. + * Currently this is: + * FEE public key in default/NONE form (which happens to be DER) + */ + assert(mKey.blobType() == CSSM_KEYBLOB_RAW); + if((mKey.algorithm() == CSSM_ALGID_FEE) && + (mKey.blobFormat() == CSSM_KEYBLOB_RAW_FORMAT_NONE) && + (mKey.keyClass() == CSSM_KEYCLASS_PUBLIC_KEY)) { + const CssmData &keyBlob = CssmData::overlay(mKey.KeyData); + copyCssmData(keyBlob, blob, allocator); + return true; + } + + /* caller converts to binary and proceeds */ + return false; +} + +#endif /* CRYPTKIT_CSP_ENABLE */ diff --git a/libsecurity_apple_csp/lib/FEEKeys.h b/libsecurity_apple_csp/lib/FEEKeys.h new file mode 100644 index 00000000..cf757076 --- /dev/null +++ b/libsecurity_apple_csp/lib/FEEKeys.h @@ -0,0 +1,117 @@ +/* + * 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. + */ + + +/* + * FEEKeys.h - FEE-related asymmetric key pair classes. + * + * Created 2/21/2001 by dmitch. + */ + +#ifdef CRYPTKIT_CSP_ENABLE + +#ifndef _FEE_KEYS_H_ +#define _FEE_KEYS_H_ + +#include "AppleCSPContext.h" +#include "AppleCSPSession.h" +#include "AppleCSPKeys.h" +#include "cryptkitcsp.h" +#include + +namespace CryptKit { + +/* + * FEE/ECDSA version of a BinaryKey. + */ +class FEEBinaryKey : public BinaryKey { +public: + FEEBinaryKey(feePubKey feeKey = NULL); + ~FEEBinaryKey(); + void generateKeyBlob( + Allocator &allocator, + CssmData &blob, + CSSM_KEYBLOB_FORMAT &format, + AppleCSPSession &session, + const CssmKey *paramKey, /* optional, unused here */ + CSSM_KEYATTR_FLAGS &attrFlags); /* IN/OUT */ + + feePubKey feeKey() { return mFeeKey; } +private: + feePubKey mFeeKey; +}; + +class FEEKeyPairGenContext : + public AppleCSPContext, private AppleKeyPairGenContext { +public: + FEEKeyPairGenContext( + AppleCSPSession &session, + const Context &) : + AppleCSPContext(session) {} + + ~FEEKeyPairGenContext() { } + + /* no init functionality, but we need to implement it */ + void init( + const Context &, + bool) { } + + // this one is specified in, and called from, CSPFullPluginSession + void generate( + const Context &context, + CssmKey &pubKey, + CssmKey &privKey); + + // this one is specified in, and called from, AppleKeyPairGenContext + void generate( + const Context &context, + BinaryKey &pubBinKey, + BinaryKey &privBinKey, + uint32 &keySize); + +}; /* KeyPairGenContext */ + +/* + * CSPKeyInfoProvider for FEE and ECDSA keys + */ +class FEEKeyInfoProvider : public CSPKeyInfoProvider +{ +private: + FEEKeyInfoProvider( + const CssmKey &cssmKey, + AppleCSPSession &session); +public: + static CSPKeyInfoProvider *provider( + const CssmKey &cssmKey, + AppleCSPSession &session); + + ~FEEKeyInfoProvider() { } + void CssmKeyToBinary( + CssmKey *paramKey, // optional, ignored here + CSSM_KEYATTR_FLAGS &attrFlags, // IN/OUT + BinaryKey **binKey); // RETURNED + void QueryKeySizeInBits( + CSSM_KEY_SIZE &keySize); // RETURNED + bool getHashableBlob( + Allocator &allocator, + CssmData &hashBlob); +}; + +} /* namespace CryptKit */ + +#endif /* _FEE_KEYS_H_ */ +#endif /* CRYPTKIT_CSP_ENABLE */ diff --git a/libsecurity_apple_csp/lib/FEESignatureObject.cpp b/libsecurity_apple_csp/lib/FEESignatureObject.cpp new file mode 100644 index 00000000..12bdfecd --- /dev/null +++ b/libsecurity_apple_csp/lib/FEESignatureObject.cpp @@ -0,0 +1,242 @@ +/* + * 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. + */ + + +/* + * FEESignatureObject.cpp - implementations of FEE-style raw sign/verify classes + * + * Created 2/20/2001 by dmitch. + */ + +#ifdef CRYPTKIT_CSP_ENABLE + +#include "FEESignatureObject.h" +#include +#include +#include +#include +#include +#include + +#define feeSigObjDebug(args...) secdebug("feeSig", ##args) + +CryptKit::FEESigner::~FEESigner() +{ + if(mWeMallocdFeeKey) { + assert(mFeeKey != NULL); + feePubKeyFree(mFeeKey); + } +} + +/* + * obtain key from context, validate, convert to native FEE key + */ +void CryptKit::FEESigner::keyFromContext( + const Context &context) +{ + if(initFlag() && (mFeeKey != NULL)) { + /* reusing context, OK */ + return; + } + + CSSM_KEYCLASS keyClass; + CSSM_KEYUSE keyUse; + if(isSigning()) { + /* signing with private key */ + keyClass = CSSM_KEYCLASS_PRIVATE_KEY; + keyUse = CSSM_KEYUSE_SIGN; + } + else { + /* verifying with public key */ + keyClass = CSSM_KEYCLASS_PUBLIC_KEY; + keyUse = CSSM_KEYUSE_VERIFY; + } + if(mFeeKey == NULL) { + mFeeKey = contextToFeeKey(context, + mSession, + CSSM_ATTRIBUTE_KEY, + keyClass, + keyUse, + mWeMallocdFeeKey); + } +} + +/* reusable init */ +void CryptKit::FEESigner::signerInit( + const Context &context, + bool isSigning) +{ + setIsSigning(isSigning); + keyFromContext(context); + setInitFlag(true); +} + +/* + * Note that, unlike the implementation in security_cryptkit/feePublicKey.c, we ignore + * the Pm which used to be used as salt for the digest. That made staged verification + * impossible and I do not believe it increased security. + */ +void CryptKit::FEERawSigner::sign( + const void *data, + size_t dataLen, + void *sig, + size_t *sigLen) /* IN/OUT */ +{ + feeSig fsig; + feeReturn frtn; + unsigned char *feeSig; + unsigned feeSigLen; + + if(mFeeKey == NULL) { + throwCryptKit(FR_BadPubKey, "FEERawSigner::sign (no key)"); + } + fsig = feeSigNewWithKey(mFeeKey, mRandFcn, mRandRef); + if(fsig == NULL) { + throwCryptKit(FR_BadPubKey, "FEERawSigner::sign"); + } + frtn = feeSigSign(fsig, + (unsigned char *)data, + dataLen, + mFeeKey); + if(frtn == FR_Success) { + frtn = feeSigData(fsig, &feeSig, &feeSigLen); + } + feeSigFree(fsig); + if(frtn) { + throwCryptKit(frtn, "FEERawSigner::sign"); + } + + /* copy out to caller and ffree */ + if(*sigLen < feeSigLen) { + feeSigObjDebug("FEERawSigner sign overflow\n"); + ffree(feeSig); + CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR); + } + memmove(sig, feeSig, feeSigLen); + *sigLen = feeSigLen; + ffree(feeSig); +} + +void CryptKit::FEERawSigner::verify( + const void *data, + size_t dataLen, + const void *sig, + size_t sigLen) +{ + feeSig fsig; + feeReturn frtn; + + if(mFeeKey == NULL) { + throwCryptKit(FR_BadPubKey, "FEERawSigner::verify (no key)"); + } + frtn = feeSigParse((unsigned char *)sig, sigLen, &fsig); + if(frtn) { + throwCryptKit(frtn, "feeSigParse"); + } + frtn = feeSigVerify(fsig, + (unsigned char *)data, + dataLen, + mFeeKey); + feeSigFree(fsig); + if(frtn) { + throwCryptKit(frtn, NULL); + } +} + +size_t CryptKit::FEERawSigner::maxSigSize() +{ + unsigned rtn; + feeReturn frtn; + + frtn = feeSigSize(mFeeKey, &rtn); + if(frtn) { + throwCryptKit(frtn, "feeSigSize"); + } + return rtn; +} + +/* ECDSA - this is really easy. */ + +void CryptKit::FEEECDSASigner::sign( + const void *data, + size_t dataLen, + void *sig, + size_t *sigLen) /* IN/OUT */ +{ + unsigned char *feeSig; + unsigned feeSigLen; + feeReturn frtn; + + if(mFeeKey == NULL) { + throwCryptKit(FR_BadPubKey, "FEERawSigner::sign (no key)"); + } + frtn = feeECDSASign(mFeeKey, + (unsigned char *)data, // data to be signed + dataLen, // in bytes + mRandFcn, + mRandRef, + &feeSig, + &feeSigLen); + if(frtn) { + throwCryptKit(frtn, "feeECDSASign"); + } + /* copy out to caller and ffree */ + if(*sigLen < feeSigLen) { + feeSigObjDebug("feeECDSASign overflow\n"); + ffree(feeSig); + CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR); + } + memmove(sig, feeSig, feeSigLen); + *sigLen = feeSigLen; + ffree(feeSig); + +} + +void CryptKit::FEEECDSASigner::verify( + const void *data, + size_t dataLen, + const void *sig, + size_t sigLen) +{ + feeReturn frtn; + + if(mFeeKey == NULL) { + throwCryptKit(FR_BadPubKey, "FEERawSigner::verify (no key)"); + } + frtn = feeECDSAVerify((unsigned char *)sig, + sigLen, + (unsigned char *)data, + dataLen, + mFeeKey); + if(frtn) { + throwCryptKit(frtn, NULL); + } +} + +size_t CryptKit::FEEECDSASigner::maxSigSize() +{ + unsigned rtn; + feeReturn frtn; + + frtn = feeECDSASigSize(mFeeKey, &rtn); + if(frtn) { + throwCryptKit(frtn, "feeECDSASigSize"); + } + return rtn; +} + +#endif /* CRYPTKIT_CSP_ENABLE */ diff --git a/libsecurity_apple_csp/lib/FEESignatureObject.h b/libsecurity_apple_csp/lib/FEESignatureObject.h new file mode 100644 index 00000000..8b7f8f6c --- /dev/null +++ b/libsecurity_apple_csp/lib/FEESignatureObject.h @@ -0,0 +1,147 @@ +/* + * 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. + */ + + +/* + * FEESignatureObject.h - FEE-based raw sign/verify classes + */ + +#ifdef CRYPTKIT_CSP_ENABLE + +#ifndef _FEE_SIGNATURE_OBJECT_H_ +#define _FEE_SIGNATURE_OBJECT_H_ + +#include +#include +#include +#include "FEECSPUtils.h" +#include "CryptKitSpace.h" +#include +#include + +namespace CryptKit { + +/* + * Common raw FEE sign/verify class. + */ +class FEESigner : public RawSigner { +public: + FEESigner( + feeRandFcn randFcn, + void *randRef, + AppleCSPSession &session, + Allocator &alloc) : + RawSigner(alloc, CSSM_ALGID_NONE), + mFeeKey(NULL), + mWeMallocdFeeKey(false), + mRandFcn(randFcn), + mRandRef(randRef), + mSession(session) { } + + virtual ~FEESigner(); + + /* reusable init */ + void signerInit( + const Context &context, + bool isSigning); + + /* + * obtain key from context, validate, convert to native FEE key + */ + void keyFromContext( + const Context &context); + +protected: + feePubKey mFeeKey; + bool mWeMallocdFeeKey; + feeRandFcn mRandFcn; + void *mRandRef; + AppleCSPSession &mSession; +}; + +/* + * And two implementations. + * + * Native FEE signature, ElGamal style. + */ +class FEERawSigner : public FEESigner +{ +public: + FEERawSigner( + feeRandFcn randFcn, + void *randRef, + AppleCSPSession &session, + Allocator &alloc) : + FEESigner(randFcn, randRef, session, alloc) { }; + + ~FEERawSigner() { } + + /* sign */ + void sign( + const void *data, + size_t dataLen, + void *sig, + size_t *sigLen); /* IN/OUT */ + + /* verify */ + void verify( + const void *data, + size_t dataLen, + const void *sig, + size_t sigLen); + + /* works for both, but only used for signing */ + size_t maxSigSize(); +}; + +/* + * FEE signature, ECDSA style. + */ +class FEEECDSASigner : public FEESigner +{ +public: + FEEECDSASigner( + feeRandFcn randFcn, + void *randRef, + AppleCSPSession &session, + Allocator &alloc) : + FEESigner(randFcn, randRef, session, alloc) { }; + + ~FEEECDSASigner() { } + + /* sign */ + void sign( + const void *data, + size_t dataLen, + void *sig, + size_t *sigLen); /* IN/OUT */ + + /* verify */ + void verify( + const void *data, + size_t dataLen, + const void *sig, + size_t sigLen); + + /* works for both, but only used for signing */ + size_t maxSigSize(); +}; + +} /* namespace CryptKit */ + +#endif /* _FEE_SIGNATURE_OBJECT_H_ */ +#endif /* CRYPTKIT_CSP_ENABLE */ diff --git a/libsecurity_apple_csp/lib/HMACSHA1.c b/libsecurity_apple_csp/lib/HMACSHA1.c new file mode 100644 index 00000000..10dd203b --- /dev/null +++ b/libsecurity_apple_csp/lib/HMACSHA1.c @@ -0,0 +1,37 @@ +/* + * 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: HMACSHA1.c + Contains: Apple Data Security Services HMACSHA1 function definition. + Copyright: (C) 1999 by Apple Computer, Inc., all rights reserved + Written by: Michael Brouwer +*/ +#include "HMACSHA1.h" +#include +#include "cspdebugging.h" + +void +hmacsha1 (const void *keyPtr, uint32 keyLen, + const void *textPtr, uint32 textLen, + void *resultPtr) +{ + CCHmac(kCCHmacAlgSHA1, keyPtr, keyLen, + textPtr, textLen, resultPtr); +} + diff --git a/libsecurity_apple_csp/lib/HMACSHA1.h b/libsecurity_apple_csp/lib/HMACSHA1.h new file mode 100644 index 00000000..7cd95e75 --- /dev/null +++ b/libsecurity_apple_csp/lib/HMACSHA1.h @@ -0,0 +1,51 @@ +/* + * 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: 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 +*/ +#ifndef __HMACSHA1__ +#define __HMACSHA1__ + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define kHMACSHA1DigestSize CC_SHA1_DIGEST_LENGTH +#define kHMACMD5DigestSize CC_MD5_DIGEST_LENGTH + +/* This function create an HMACSHA1 digest of kHMACSHA1DigestSizestSize bytes + * and outputs it to resultPtr. See RFC 2104 for details. */ +void +hmacsha1 (const void *keyPtr, uint32 keyLen, + const void *textPtr, uint32 textLen, + void *resultPtr); + +#ifdef __cplusplus +} +#endif + +#endif /* __HMACSHA1__ */ diff --git a/libsecurity_apple_csp/lib/MD2Object.cpp b/libsecurity_apple_csp/lib/MD2Object.cpp new file mode 100644 index 00000000..b2b2aee1 --- /dev/null +++ b/libsecurity_apple_csp/lib/MD2Object.cpp @@ -0,0 +1,61 @@ +/* + * 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. + */ + +/* + * MD2Object.cpp + */ +#include "MD2Object.h" +#include +#include + +void MD2Object::digestInit() +{ + setIsDone(false); + CC_MD2_Init(&mCtx); +} + +void MD2Object::digestUpdate( + const void *data, + size_t len) +{ + if(isDone()) { + throw std::runtime_error("MD2 digestUpdate after final"); + } + CC_MD2_Update(&mCtx, (unsigned char *)data, len); +} + +void MD2Object::digestFinal( + void *digest) +{ + if(isDone()) { + throw std::runtime_error("MD2 digestFinal after final"); + } + CC_MD2_Final((unsigned char *)digest, &mCtx); + setIsDone(true); +} + +/* use default memberwise init */ +DigestObject *MD2Object::digestClone() const +{ + return new MD2Object(*this); +} + +CSSM_SIZE MD2Object::digestSizeInBytes() const +{ + return CC_MD2_DIGEST_LENGTH; +} + diff --git a/libsecurity_apple_csp/lib/MD2Object.h b/libsecurity_apple_csp/lib/MD2Object.h new file mode 100644 index 00000000..8c5caa72 --- /dev/null +++ b/libsecurity_apple_csp/lib/MD2Object.h @@ -0,0 +1,47 @@ +/* + * 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. + */ + + +/* + * MD2Object.h - MD2 digest object + */ + +#ifndef _MD2_OBJECT_H_ +#define _MD2_OBJECT_H_ + +#include +#include +#include + +class MD2Object : public DigestObject +{ +public: + MD2Object() { } + virtual ~MD2Object() { }; + virtual void digestInit(); + virtual void digestUpdate( + const void *data, + size_t len); + virtual void digestFinal( + void *digest); + virtual DigestObject *digestClone() const; + virtual CSSM_SIZE digestSizeInBytes() const; +private: + CC_MD2_CTX mCtx; +}; + +#endif /* _MD2_OBJECT_H_ */ diff --git a/libsecurity_apple_csp/lib/MacContext.cpp b/libsecurity_apple_csp/lib/MacContext.cpp new file mode 100644 index 00000000..91353fd7 --- /dev/null +++ b/libsecurity_apple_csp/lib/MacContext.cpp @@ -0,0 +1,176 @@ +/* + * 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. + */ + +/* + * MacContext.cpp - AppleCSPContext for HMACSHA1 + */ + +#include "MacContext.h" +#include +#include +#include /* for digest sizes */ +#ifdef CRYPTKIT_CSP_ENABLE +#include +#endif /* CRYPTKIT_CSP_ENABLE */ + +MacContext::~MacContext() +{ + memset(&hmacCtx, 0, sizeof(hmacCtx)); +} + +/* called out from CSPFullPluginSession.... + * both generate and verify */ +void MacContext::init(const Context &context, bool isSigning) +{ + CCHmacAlgorithm ccAlg; + + /* obtain key from context */ + CSSM_SIZE keyLen; + uint8 *keyData = NULL; + + symmetricKeyBits(context, session(), mAlg, + isSigning ? CSSM_KEYUSE_SIGN : CSSM_KEYUSE_VERIFY, + keyData, keyLen); + uint32 minKey = 0; + switch(mAlg) { + case CSSM_ALGID_SHA1HMAC: + minKey = HMAC_SHA_MIN_KEY_SIZE; + mDigestSize = CC_SHA1_DIGEST_LENGTH; + ccAlg = kCCHmacAlgSHA1; + break; + case CSSM_ALGID_MD5HMAC: + minKey = HMAC_MD5_MIN_KEY_SIZE; + mDigestSize = CC_MD5_DIGEST_LENGTH; + ccAlg = kCCHmacAlgMD5; + break; + default: + assert(0); // factory should not have called us + CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM); + } + if((keyLen < minKey) || (keyLen > HMAC_MAX_KEY_SIZE)) { + CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_KEY); + } + CCHmacInit(&hmacCtx, ccAlg, keyData, keyLen); +} + +void MacContext::update(const CssmData &data) +{ + CCHmacUpdate(&hmacCtx, data.data(), data.length()); +} + +/* generate only */ +void MacContext::final(CssmData &out) +{ + if(out.length() < mDigestSize) { + CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR); + } + CCHmacFinal(&hmacCtx, out.data()); + out.Length = mDigestSize; +} + +/* verify only */ +#define MAX_DIGEST_SIZE CC_SHA1_DIGEST_LENGTH + +void MacContext::final(const CssmData &in) +{ + unsigned char mac[MAX_DIGEST_SIZE]; + + CCHmacFinal(&hmacCtx, mac); + if(memcmp(mac, in.data(), mDigestSize)) { + CssmError::throwMe(CSSMERR_CSP_VERIFY_FAILED); + } +} + +size_t MacContext::outputSize(bool final, size_t inSize) +{ + return mDigestSize; +} + +#ifdef CRYPTKIT_CSP_ENABLE + +MacLegacyContext::~MacLegacyContext() +{ + if(mHmac) { + hmacLegacyFree(mHmac); + mHmac = NULL; + } +} + +/* called out from CSPFullPluginSession.... + * both generate and verify: */ +void MacLegacyContext::init(const Context &context, bool isSigning) +{ + if(mHmac == NULL) { + mHmac = hmacLegacyAlloc(); + if(mHmac == NULL) { + CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR); + } + } + + /* obtain key from context */ + CSSM_SIZE keyLen; + uint8 *keyData = NULL; + + /* FIXME - this may require a different key alg */ + symmetricKeyBits(context, session(), CSSM_ALGID_SHA1HMAC, + isSigning ? CSSM_KEYUSE_SIGN : CSSM_KEYUSE_VERIFY, + keyData, keyLen); + if((keyLen < HMAC_SHA_MIN_KEY_SIZE) || (keyLen > HMAC_MAX_KEY_SIZE)) { + CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_KEY); + } + + OSStatus ortn = hmacLegacyInit(mHmac, keyData, keyLen); + if(ortn) { + MacOSError::throwMe(ortn); + } +} + +void MacLegacyContext::update(const CssmData &data) +{ + OSStatus ortn = hmacLegacyUpdate(mHmac, + data.data(), + data.length()); + if(ortn) { + MacOSError::throwMe(ortn); + } +} + +/* generate only */ +void MacLegacyContext::final(CssmData &out) +{ + if(out.length() < kHMACSHA1DigestSize) { + CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR); + } + hmacLegacyFinal(mHmac, out.data()); +} + +/* verify only */ +void MacLegacyContext::final(const CssmData &in) +{ + unsigned char mac[kHMACSHA1DigestSize]; + hmacLegacyFinal(mHmac, mac); + if(memcmp(mac, in.data(), kHMACSHA1DigestSize)) { + CssmError::throwMe(CSSMERR_CSP_VERIFY_FAILED); + } +} + +size_t MacLegacyContext::outputSize(bool final, size_t inSize) +{ + return kHMACSHA1DigestSize; +} + +#endif /* CRYPTKIT_CSP_ENABLE */ diff --git a/libsecurity_apple_csp/lib/MacContext.h b/libsecurity_apple_csp/lib/MacContext.h new file mode 100644 index 00000000..62d69fca --- /dev/null +++ b/libsecurity_apple_csp/lib/MacContext.h @@ -0,0 +1,99 @@ +/* + * 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. + */ + +/* + * MacContext.h - AppleCSPContext for HMAC{SHA1,MD5} + */ + +#ifndef _MAC_CONTEXT_H_ +#define _MAC_CONTEXT_H_ + +#include +#include + +/* + * TLS Export Ciphers require HMAC calculation with a secret key + * size of 0 bytes. We'd really like to enforce a minimum key size equal + * the digest size, per RFC 2104, but TLS precludes that. + */ +#define HMAC_MIN_KEY_SIZE 0 +#define HMAC_SHA_MIN_KEY_SIZE HMAC_MIN_KEY_SIZE +#define HMAC_MD5_MIN_KEY_SIZE HMAC_MIN_KEY_SIZE +#define HMAC_MAX_KEY_SIZE 2048 + +class MacContext : public AppleCSPContext { +public: + MacContext( + AppleCSPSession &session, + CSSM_ALGORITHMS alg) : + AppleCSPContext(session), + mAlg(alg), + mDigestSize(0) { } + ~MacContext(); + + /* called out from CSPFullPluginSession.... + * both generate and verify: */ + void init(const Context &context, bool isSigning); + void update(const CssmData &data); + + /* generate only */ + void final(CssmData &out); + + /* verify only */ + void final(const CssmData &in); + + size_t outputSize(bool final, size_t inSize); + +private: + CCHmacContext hmacCtx; + CSSM_ALGORITHMS mAlg; + uint32 mDigestSize; +}; + +#ifdef CRYPTKIT_CSP_ENABLE +#include + +/* This version is bug-for-bug compatible with a legacy implementation */ + +class MacLegacyContext : public AppleCSPContext { +public: + MacLegacyContext( + AppleCSPSession &session, + CSSM_ALGORITHMS alg) : + AppleCSPContext(session), mHmac(NULL) { } + ~MacLegacyContext(); + + /* called out from CSPFullPluginSession.... + * both generate and verify: */ + void init(const Context &context, bool isSigning); + void update(const CssmData &data); + + /* generate only */ + void final(CssmData &out); + + /* verify only */ + void final(const CssmData &in); + + size_t outputSize(bool final, size_t inSize); + +private: + hmacLegacyContextRef mHmac; +}; + +#endif /* CRYPTKIT_CSP_ENABLE */ + +#endif /* _MAC_CONTEXT_H_ */ diff --git a/libsecurity_apple_csp/lib/NullCryptor.h b/libsecurity_apple_csp/lib/NullCryptor.h new file mode 100644 index 00000000..0fde61cd --- /dev/null +++ b/libsecurity_apple_csp/lib/NullCryptor.h @@ -0,0 +1,89 @@ +/* + * 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. + */ + + +/* + * NullCryptor.h - null symmetric encryptor for measurement only + * Written by Doug Mitchell 12/17/2001 + */ +#ifndef _NULL_CRYPTOR_H_ +#define _NULL_CRYPTOR_H_ + +/* + * DO NOT DEFINE THIS SYMBOL TRUE FOR CODE CHECKED IN TO CVS + */ +#define NULL_CRYPT_ENABLE 0 + +#if NULL_CRYPT_ENABLE + +#include +#include "AppleCSP.h" +#include "AppleCSPContext.h" +#include "AppleCSPSession.h" +#include "BlockCryptor.h" + +#define NULL_CRYPT_BLOCK_SIZE 16 + +class NullCryptor : public BlockCryptor { +public: + NullCryptor(AppleCSPSession &session) : + BlockCryptor(session), + mInitFlag(false) { } + ~NullCryptor() { } + + // called by CSPFullPluginSession + void init(const Context &context, bool encoding = true) + { + if(mInitFlag && !opStarted()) { + return; + } + /* Just have BlockCryptor do its setup */ + setup(NULL_CRYPT_BLOCK_SIZE, context); + mInitFlag = true; + } + + // called by BlockCryptor + void encryptBlock( + const void *plainText, // length implied (one block) + size_t plainTextLen, + void *cipherText, + size_t &cipherTextLen, // in/out, throws on overflow + bool final) + { + memmove(cipherText, plainText, NULL_CRYPT_BLOCK_SIZE); + cipherTextLen = NULL_CRYPT_BLOCK_SIZE; + } + + void decryptBlock( + const void *cipherText, // length implied (one cipher block) + size_t cipherTextLen, + void *plainText, + size_t &plainTextLen, // in/out, throws on overflow + bool final) + { + memmove(plainText, cipherText, NULL_CRYPT_BLOCK_SIZE); + plainTextLen = NULL_CRYPT_BLOCK_SIZE; + } + +private: + bool mInitFlag; // for easy reuse + +}; /* NullCryptor */ + +#endif /* NULL_CRYPT_ENABLE */ + +#endif //_NULL_CRYPTOR_H_ diff --git a/libsecurity_apple_csp/lib/RSA_DSA_csp.cpp b/libsecurity_apple_csp/lib/RSA_DSA_csp.cpp new file mode 100644 index 00000000..723e2294 --- /dev/null +++ b/libsecurity_apple_csp/lib/RSA_DSA_csp.cpp @@ -0,0 +1,234 @@ +/* + * 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. + */ + + +/* + * RSA_DSA_csp.cpp - Algorithm factory for RSA/DSA + */ + +#include "RSA_DSA_csp.h" +#include "RSA_DSA_signature.h" /* raw signer */ +#include /* raw digest */ +#include +#include +#include "RSA_DSA_keys.h" +#include "RSA_asymmetric.h" +#include +#include +#include + +#define OPENSSL_DSA_ENABLE 1 + +Allocator *RSA_DSA_Factory::normAllocator; +Allocator *RSA_DSA_Factory::privAllocator; + +/* normally found in crypto.h, which has way too much useless cruft....move these to + * a local header.... */ +extern "C" { +extern int CRYPTO_set_mem_functions( + void *(*m)(size_t), + void *(*r)(void *,size_t), + void (*f)(void *)); +int CRYPTO_set_locked_mem_functions( + void *(*m)(size_t), + void (*free_func)(void *)); +} + +/* + * openssl-style memory allocator callbacks + */ +static void *osMalloc(size_t size) +{ + return RSA_DSA_Factory::privAllocator->malloc(size); +} +static void osFree(void *data) +{ + RSA_DSA_Factory::privAllocator->free(data); +} +static void *osRealloc(void *oldPtr, size_t newSize) +{ + return RSA_DSA_Factory::privAllocator->realloc(oldPtr, newSize); +} + +RSA_DSA_Factory::RSA_DSA_Factory(Allocator *normAlloc, Allocator *privAlloc) +{ + setNormAllocator(normAlloc); + setPrivAllocator(privAlloc); + /* once-per-address space */ + CRYPTO_set_mem_functions(osMalloc, osRealloc, osFree); + CRYPTO_set_locked_mem_functions(osMalloc, osFree); + /* these should go in a lib somewhere */ + ERR_load_RSA_strings(); + ERR_load_BN_strings(); + ERR_load_DSA_strings(); +} + +RSA_DSA_Factory::~RSA_DSA_Factory() +{ + // TBD terminateCryptKit(); +} + +bool RSA_DSA_Factory::setup( + AppleCSPSession &session, + CSPFullPluginSession::CSPContext * &cspCtx, + const Context &context) +{ + switch(context.type()) { + case CSSM_ALGCLASS_SIGNATURE: + switch(context.algorithm()) { + case CSSM_ALGID_SHA1WithRSA: + if(cspCtx == NULL) { + cspCtx = new SignatureContext(session, + *(new SHA1Object()), + *(new RSASigner(*privAllocator, + session, + CSSM_ALGID_SHA1))); + } + return true; + case CSSM_ALGID_MD5WithRSA: + if(cspCtx == NULL) { + cspCtx = new SignatureContext(session, + *(new MD5Object()), + *(new RSASigner(*privAllocator, + session, + CSSM_ALGID_MD5))); + } + return true; + case CSSM_ALGID_MD2WithRSA: + if(cspCtx == NULL) { + cspCtx = new SignatureContext(session, + *(new MD2Object()), + *(new RSASigner(*privAllocator, + session, + CSSM_ALGID_MD2))); + } + return true; + #if OPENSSL_DSA_ENABLE + case CSSM_ALGID_SHA1WithDSA: + if(cspCtx == NULL) { + cspCtx = new SignatureContext(session, + *(new SHA1Object()), + *(new DSASigner(*privAllocator, + session, + CSSM_ALGID_SHA1))); + } + return true; + case CSSM_ALGID_DSA: + if(cspCtx == NULL) { + cspCtx = new SignatureContext(session, + *(new NullDigest()), + *(new DSASigner(*privAllocator, + session, + // set later via setDigestAlgorithm but not used by DSA + CSSM_ALGID_NONE))); + } + return true; + #endif + case CSSM_ALGID_RSA: + if(cspCtx == NULL) { + cspCtx = new SignatureContext(session, + *(new NullDigest()), + *(new RSASigner(*privAllocator, + session, + // set later via setDigestAlgorithm + CSSM_ALGID_NONE))); + } + return true; + case CSSM_ALGID_SHA256WithRSA: + if(cspCtx == NULL) { + cspCtx = new SignatureContext(session, + *(new SHA256Object()), + *(new RSASigner(*privAllocator, + session, + CSSM_ALGID_SHA256))); + } + return true; + case CSSM_ALGID_SHA224WithRSA: + if(cspCtx == NULL) { + cspCtx = new SignatureContext(session, + *(new SHA224Object()), + *(new RSASigner(*privAllocator, + session, + CSSM_ALGID_SHA224))); + } + return true; + case CSSM_ALGID_SHA384WithRSA: + if(cspCtx == NULL) { + cspCtx = new SignatureContext(session, + *(new SHA384Object()), + *(new RSASigner(*privAllocator, + session, + CSSM_ALGID_SHA384))); + } + return true; + case CSSM_ALGID_SHA512WithRSA: + if(cspCtx == NULL) { + cspCtx = new SignatureContext(session, + *(new SHA512Object()), + *(new RSASigner(*privAllocator, + session, + CSSM_ALGID_SHA512))); + } + return true; + default: + break; + } + break; + + case CSSM_ALGCLASS_KEYGEN: + switch(context.algorithm()) { + case CSSM_ALGID_RSA: + case CSSM_ALGMODE_PKCS1_EME_OAEP: + if(cspCtx == NULL) { + cspCtx = new RSAKeyPairGenContext(session, context); + } + return true; + #if OPENSSL_DSA_ENABLE + case CSSM_ALGID_DSA: + if(cspCtx == NULL) { + cspCtx = new DSAKeyPairGenContext(session, context); + } + return true; + #endif + default: + break; + } + break; + + case CSSM_ALGCLASS_ASYMMETRIC: + switch(context.algorithm()) { + case CSSM_ALGID_RSA: + case CSSM_ALGMODE_PKCS1_EME_OAEP: + if(cspCtx == NULL) { + cspCtx = new RSA_CryptContext(session); + } + return true; + default: + break; + } + break; + + /* more here - symmetric, etc. */ + default: + break; + } + /* not implemented here */ + return false; +} + + + diff --git a/libsecurity_apple_csp/lib/RSA_DSA_csp.h b/libsecurity_apple_csp/lib/RSA_DSA_csp.h new file mode 100644 index 00000000..b4e7b05c --- /dev/null +++ b/libsecurity_apple_csp/lib/RSA_DSA_csp.h @@ -0,0 +1,53 @@ +/* + * 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. + */ + + +/* + * RSA_DSA_csp.h - Algorithm factory for RSA/DSA + */ + +#ifndef _RSA_DSA_CSP_H_ +#define _RSA_DSA_CSP_H_ + +#include +#include + +/* Can't include AppleCSPSession.h due to circular dependency */ +class AppleCSPSession; + +class RSA_DSA_Factory : public AppleCSPAlgorithmFactory { +public: + RSA_DSA_Factory(Allocator *normAlloc = NULL, Allocator *privAlloc = NULL); + ~RSA_DSA_Factory(); + + bool setup( + AppleCSPSession &session, + CSPFullPluginSession::CSPContext * &cspCtx, + const Context &context); + + static void setNormAllocator(Allocator *alloc) + { assert(!normAllocator); normAllocator = alloc; } + static void setPrivAllocator(Allocator *alloc) + { assert(!privAllocator); privAllocator = alloc; } + + // memory allocators + static Allocator *normAllocator; + static Allocator *privAllocator; + +}; + +#endif /* _RSA_DSA_CSP_H_ */ diff --git a/libsecurity_apple_csp/lib/RSA_DSA_keys.cpp b/libsecurity_apple_csp/lib/RSA_DSA_keys.cpp new file mode 100644 index 00000000..7b9deb5f --- /dev/null +++ b/libsecurity_apple_csp/lib/RSA_DSA_keys.cpp @@ -0,0 +1,829 @@ +/* + * 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. + */ + + +/* + * RSA_DSA_Keys.cpp - RSA, DSA related asymmetric key pair classes. + */ + +#include "RSA_DSA_keys.h" +#include +#include +#include +#include +#include +#include +#include +#include "RSA_DSA_utils.h" +#include +#include + +#define RSA_PUB_EXPONENT 0x10001 /* recommended by RSA */ + +#define rsaKeyDebug(args...) secdebug("rsaKey", ## args) + + +/*** + *** RSA-style BinaryKey + ***/ + +/* constructor with optional existing RSA key */ +/* FIXME how to transmit OAEP params? */ +RSABinaryKey::RSABinaryKey(RSA *rsaKey) + : mRsaKey(rsaKey), + mOaep(false), + mLabel(Allocator::standard()) +{ +} + +RSABinaryKey::~RSABinaryKey() +{ + if(mRsaKey) { + RSA_free(mRsaKey); + mRsaKey = NULL; + } +} + +void RSABinaryKey::setOaep( + const CSSM_DATA &label) +{ + mLabel.copy(label); + mOaep = true; +} + +void RSABinaryKey::generateKeyBlob( + Allocator &allocator, + CssmData &blob, + CSSM_KEYBLOB_FORMAT &format, /* IN/OUT */ + AppleCSPSession &session, + const CssmKey *paramKey, /* optional, unused here */ + CSSM_KEYATTR_FLAGS &attrFlags) /* IN/OUT */ +{ + bool isPub; + CSSM_RETURN crtn; + + /* FIXME get label from context here for OAEP */ + + /* + * Here, the incoming default of CSSM_KEYBLOB_RAW_FORMAT_NONE + * is translated to our AppleCSP-custom defaults. App can override. + */ + switch(mKeyHeader.KeyClass) { + case CSSM_KEYCLASS_PUBLIC_KEY: + isPub = true; + switch(format) { + case CSSM_KEYBLOB_RAW_FORMAT_NONE: + format = RSA_PUB_KEY_FORMAT; // default + break; + case CSSM_KEYBLOB_RAW_FORMAT_DIGEST: + if(mOaep) { + /* have to take digest of the whole thing including label */ + format = CSSM_KEYBLOB_RAW_FORMAT_X509; + } + else { + /* calculate digest on PKCS1 blob */ + format = CSSM_KEYBLOB_RAW_FORMAT_PKCS1; + } + break; + case CSSM_KEYBLOB_RAW_FORMAT_PKCS1: + case CSSM_KEYBLOB_RAW_FORMAT_X509: + case CSSM_KEYBLOB_RAW_FORMAT_OPENSSH: + case CSSM_KEYBLOB_RAW_FORMAT_OPENSSH2: + break; + default: + CssmError::throwMe(CSSMERR_CSP_UNSUPPORTED_KEY_FORMAT); + } + break; + case CSSM_KEYCLASS_PRIVATE_KEY: + isPub = false; + switch(format) { + case CSSM_KEYBLOB_RAW_FORMAT_NONE: // default + format = RSA_PRIV_KEY_FORMAT; + break; + case CSSM_KEYBLOB_RAW_FORMAT_DIGEST: + if(mOaep) { + /* have to take digest of the whole thing including label */ + format = CSSM_KEYBLOB_RAW_FORMAT_X509; + } + else { + /* calculate digest on PKCS1 blob */ + format = CSSM_KEYBLOB_RAW_FORMAT_PKCS1; + } + isPub = true; + break; + case CSSM_KEYBLOB_RAW_FORMAT_PKCS1: + case CSSM_KEYBLOB_RAW_FORMAT_PKCS8: + case CSSM_KEYBLOB_RAW_FORMAT_OPENSSH: + break; + default: + CssmError::throwMe(CSSMERR_CSP_UNSUPPORTED_KEY_FORMAT); + } + break; + default: + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS); + } + + CssmAutoData encodedKey(allocator); + if(mOaep) { + CSSM_DATA label = mLabel; + if(isPub) { + crtn = RSAOAEPPublicKeyEncode(mRsaKey, &label, encodedKey); + } + else { + crtn = RSAOAEPPrivateKeyEncode(mRsaKey, &label, encodedKey); + } + } + else { + if(isPub) { + crtn = RSAPublicKeyEncode(mRsaKey, format, descData(), encodedKey); + } + else { + crtn = RSAPrivateKeyEncode(mRsaKey, format, descData(), encodedKey); + } + } + if(crtn) { + CssmError::throwMe(crtn); + } + blob = encodedKey.release(); +} + +/*** + *** RSA-style AppleKeyPairGenContext + ***/ + +/* + * This one is specified in, and called from, CSPFullPluginSession. Our + * only job is to prepare two subclass-specific BinaryKeys and call up to + * AppleKeyPairGenContext. + */ +void RSAKeyPairGenContext::generate( + const Context &context, + CssmKey &pubKey, + CssmKey &privKey) +{ + RSABinaryKey *pubBinKey = new RSABinaryKey(); + RSABinaryKey *privBinKey = new RSABinaryKey(); + + try { + AppleKeyPairGenContext::generate(context, + session(), + pubKey, + pubBinKey, + privKey, + privBinKey); + } + catch (...) { + delete pubBinKey; + delete privBinKey; + throw; + } + +} + +// this one is specified in, and called from, AppleKeyPairGenContext +void RSAKeyPairGenContext::generate( + const Context &context, + BinaryKey &pubBinKey, + BinaryKey &privBinKey, + uint32 &keyBits) +{ + /* + * These casts throw exceptions if the keys are of the + * wrong classes, which would be a major bogon, since we created + * the keys in the above generate() function. + */ + RSABinaryKey &rPubBinKey = + dynamic_cast(pubBinKey); + RSABinaryKey &rPrivBinKey = + dynamic_cast(privBinKey); + + /* + * One parameter from context: Key size in bits is required. + * FIXME - get public exponent from context? + */ + keyBits = context.getInt(CSSM_ATTRIBUTE_KEY_LENGTH, + CSSMERR_CSP_MISSING_ATTR_KEY_LENGTH); + if(keyBits > rsaMaxKeySize()) { + CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_KEY_LENGTH); + } + + /* generate the private key */ + rPrivBinKey.mRsaKey = RSA_generate_key(keyBits, + RSA_PUB_EXPONENT, + NULL, // no callback + NULL); + if(rPrivBinKey.mRsaKey == NULL) { + rsaKeyDebug("RSA_generate_key returned NULL"); + CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR); // ??? + } + + /* public key is subset of private key */ + rPubBinKey.mRsaKey = RSA_new(); + if(rPrivBinKey.mRsaKey == NULL) { + CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR); + } + RSA *pub = rPubBinKey.mRsaKey; + RSA *priv = rPrivBinKey.mRsaKey; + pub->n = BN_dup(priv->n); + pub->e = BN_dup(priv->e); + if((pub->n == NULL) || (pub->e == NULL)) { + CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR); + } +} + + +/*** + *** RSA-style CSPKeyInfoProvider. + ***/ +RSAKeyInfoProvider::RSAKeyInfoProvider( + const CssmKey &cssmKey, + AppleCSPSession &session) : + CSPKeyInfoProvider(cssmKey, session) +{ +} + +CSPKeyInfoProvider *RSAKeyInfoProvider::provider( + const CssmKey &cssmKey, + AppleCSPSession &session) +{ + switch(cssmKey.algorithm()) { + case CSSM_ALGID_RSA: + case CSSM_ALGMODE_PKCS1_EME_OAEP: + break; + default: + return NULL; + } + switch(cssmKey.keyClass()) { + case CSSM_KEYCLASS_PUBLIC_KEY: + case CSSM_KEYCLASS_PRIVATE_KEY: + break; + default: + return NULL; + } + /* OK, we'll handle this one */ + return new RSAKeyInfoProvider(cssmKey, session); +} + +/* Given a raw key, cook up a Binary key */ +void RSAKeyInfoProvider::CssmKeyToBinary( + CssmKey *paramKey, // ignored + CSSM_KEYATTR_FLAGS &attrFlags, // IN/OUT, unused here + BinaryKey **binKey) +{ + *binKey = NULL; + RSA *rsaKey = NULL; + CSSM_DATA label = {0, NULL}; + + /* first cook up an RSA key */ + rsaKey = rawCssmKeyToRsa(mKey, label); + + /* now drop that into a BinaryKey */ + RSABinaryKey *rsaBinKey = new RSABinaryKey(rsaKey); + *binKey = rsaBinKey; + if(label.Data) { + rsaBinKey->setOaep(label); + free(label.Data); + } +} + +/* + * Obtain key size in bits. + */ +void RSAKeyInfoProvider::QueryKeySizeInBits( + CSSM_KEY_SIZE &keySize) +{ + RSA *rsaKey = NULL; + CSSM_DATA label = {0, NULL}; + + if(mKey.blobType() != CSSM_KEYBLOB_RAW) { + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_FORMAT); + } + rsaKey = rawCssmKeyToRsa(mKey, label); + keySize.LogicalKeySizeInBits = RSA_size(rsaKey) * 8; + keySize.EffectiveKeySizeInBits = keySize.LogicalKeySizeInBits; + RSA_free(rsaKey); + if(label.Data) { + free(label.Data); + } +} + +/* + * Obtain blob suitable for hashing in CSSM_APPLECSP_KEYDIGEST + * passthrough. + */ +bool RSAKeyInfoProvider::getHashableBlob( + Allocator &allocator, + CssmData &blob) // blob to hash goes here +{ + /* + * The optimized case, a raw key in the "proper" format already. + * Only public keys in PKCS1 format fit this bill. + */ + assert(mKey.blobType() == CSSM_KEYBLOB_RAW); + bool useAsIs = false; + + switch(mKey.keyClass()) { + case CSSM_KEYCLASS_PUBLIC_KEY: + if(mKey.blobFormat() == CSSM_KEYBLOB_RAW_FORMAT_PKCS1) { + useAsIs = true; + } + break; + case CSSM_KEYCLASS_PRIVATE_KEY: + break; + default: + /* shouldn't be here */ + assert(0); + CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR); + } + if(useAsIs) { + const CssmData &keyBlob = CssmData::overlay(mKey.KeyData); + copyCssmData(keyBlob, blob, allocator); + return true; + } + + /* caller converts to binary and proceeds */ + return false; +} + +/*** + *** DSA key support + ***/ + + +/*** + *** DSA-style BinaryKey + ***/ + +/* constructor with optional existing DSA key */ +DSABinaryKey::DSABinaryKey(DSA *dsaKey) + : mDsaKey(dsaKey) +{ +} + +DSABinaryKey::~DSABinaryKey() +{ + if(mDsaKey) { + DSA_free(mDsaKey); + mDsaKey = NULL; + } +} + +void DSABinaryKey::generateKeyBlob( + Allocator &allocator, + CssmData &blob, + CSSM_KEYBLOB_FORMAT &format, + AppleCSPSession &session, + const CssmKey *paramKey, /* optional */ + CSSM_KEYATTR_FLAGS &attrFlags) /* IN/OUT */ +{ + bool isPub; + CSSM_RETURN crtn; + + /* + * Here, the incoming default of CSSM_KEYBLOB_RAW_FORMAT_NONE + * is translated to our AppleCSP-custom defaults. App can override. + */ + switch(mKeyHeader.KeyClass) { + case CSSM_KEYCLASS_PUBLIC_KEY: + isPub = true; + switch(format) { + case CSSM_KEYBLOB_RAW_FORMAT_NONE: + format = DSA_PUB_KEY_FORMAT; // default + break; + case CSSM_KEYBLOB_RAW_FORMAT_FIPS186: + case CSSM_KEYBLOB_RAW_FORMAT_X509: + case CSSM_KEYBLOB_RAW_FORMAT_DIGEST: + case CSSM_KEYBLOB_RAW_FORMAT_OPENSSH2: + break; + default: + CssmError::throwMe(CSSMERR_CSP_UNSUPPORTED_KEY_FORMAT); + } + break; + case CSSM_KEYCLASS_PRIVATE_KEY: + isPub = false; + switch(format) { + case CSSM_KEYBLOB_RAW_FORMAT_NONE: + format = DSA_PRIV_KEY_FORMAT; // default + break; + case CSSM_KEYBLOB_RAW_FORMAT_DIGEST: + /* + * This is calculated on the public key, which + * is not always part of a DSA private key's encoding... + * so first calculate the public key. + */ + dsaKeyPrivToPub(mDsaKey); + isPub = true; + break; + case CSSM_KEYBLOB_RAW_FORMAT_FIPS186: + case CSSM_KEYBLOB_RAW_FORMAT_PKCS8: + case CSSM_KEYBLOB_RAW_FORMAT_OPENSSL: + break; + default: + CssmError::throwMe(CSSMERR_CSP_UNSUPPORTED_KEY_FORMAT); + } + break; + default: + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS); + } + + /* possible conversion from partial binary key to fully + * formed blob */ + DSA *dsaToEncode = mDsaKey; + DSA *dsaUpgrade = NULL; + if(isPub && + (mDsaKey->p == NULL) && + (paramKey != NULL)) { + /* + * Don't modify BinaryKey; make a copy. + */ + dsaUpgrade = DSA_new(); + if(dsaUpgrade == NULL) { + CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR); + } + dsaUpgrade->pub_key = BN_dup(mDsaKey->pub_key); + crtn = dsaGetParamsFromKey(dsaUpgrade, *paramKey, session); + if(crtn) { + DSA_free(dsaUpgrade); + CssmError::throwMe(crtn); + } + + /* success - switch keys and inform caller of attr change */ + dsaToEncode = dsaUpgrade; + attrFlags &= ~CSSM_KEYATTR_PARTIAL; + } + + /* + * DSA private keys originating from BSAFE form - e.g., DSA private + * keys wrapped in a keychain (which have format FIPS186 by default) + * have no public key component. Generate the public key if we don't + * have one. + */ + if(!isPub && (dsaToEncode->pub_key == NULL)) { + dsaKeyPrivToPub(dsaToEncode); + } + + CssmAutoData encodedKey(allocator); + if(isPub) { + crtn = DSAPublicKeyEncode(dsaToEncode, format, descData(), encodedKey); + } + else { + crtn = DSAPrivateKeyEncode(dsaToEncode, format, descData(), encodedKey); + } + if(dsaUpgrade != NULL) { + /* temp key, get rid of it */ + DSA_free(dsaUpgrade); + } + if(crtn) { + CssmError::throwMe(crtn); + } + blob = encodedKey.release(); +} + +/*** + *** DSA-style AppleKeyPairGenContext + ***/ + +/* + * This one is specified in, and called from, CSPFullPluginSession. Our + * only job is to prepare two subclass-specific BinaryKeys and call up to + * AppleKeyPairGenContext. + */ +void DSAKeyPairGenContext::generate( + const Context &context, + CssmKey &pubKey, + CssmKey &privKey) +{ + DSABinaryKey *pubBinKey = new DSABinaryKey(); + DSABinaryKey *privBinKey = new DSABinaryKey(); + + try { + AppleKeyPairGenContext::generate(context, + session(), + pubKey, + pubBinKey, + privKey, + privBinKey); + } + catch (...) { + delete pubBinKey; + delete privBinKey; + throw; + } + +} + +/* + * This one is specified in, and called from, AppleKeyPairGenContext + */ +void DSAKeyPairGenContext::generate( + const Context &context, + BinaryKey &pubBinKey, + BinaryKey &privBinKey, + uint32 &keyBits) +{ + /* + * These casts throw exceptions if the keys are of the + * wrong classes, which would be a major bogon, since we created + * the keys in the above generate() function. + */ + DSABinaryKey &rPubBinKey = + dynamic_cast(pubBinKey); + DSABinaryKey &rPrivBinKey = + dynamic_cast(privBinKey); + + /* + * Parameters from context: + * Key size in bits, required; + * {p,q,g} from generateParams, optional + */ + keyBits = context.getInt(CSSM_ATTRIBUTE_KEY_LENGTH, + CSSMERR_CSP_MISSING_ATTR_KEY_LENGTH); + if(keyBits > DSA_MAX_KEY_SIZE) { + CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_KEY_LENGTH); + } + CssmData *paramData = context.get(CSSM_ATTRIBUTE_ALG_PARAMS); + + NSS_DSAAlgParams algParams; + SecNssCoder coder; // generated algParams mallocd from here + if(paramData != NULL) { + /* this contains the DER encoding of a NSS_DSAAlgParams */ + CSSM_RETURN crtn = DSADecodeAlgParams(algParams, paramData->Data, + paramData->Length, coder); + if(crtn) { + CssmError::throwMe(crtn); + } + } + else { + /* no alg params specified; generate them now using null (random) seed */ + dsaGenParams(keyBits, NULL, 0, algParams, coder); + } + + /* create key, stuff params into it */ + rPrivBinKey.mDsaKey = DSA_new(); + if(rPrivBinKey.mDsaKey == NULL) { + CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR); + } + DSA *dsaKey = rPrivBinKey.mDsaKey; + dsaKey->p = cssmDataToBn(algParams.p); + dsaKey->q = cssmDataToBn(algParams.q); + dsaKey->g = cssmDataToBn(algParams.g); + + /* generate the key (both public and private capabilities) */ + int irtn = DSA_generate_key(dsaKey); + if(!irtn) { + throwRsaDsa("DSA_generate_key"); + } + + /* public key is subset of private key */ + rPubBinKey.mDsaKey = DSA_new(); + if(rPrivBinKey.mDsaKey == NULL) { + CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR); + } + DSA *pub = rPubBinKey.mDsaKey; + DSA *priv = rPrivBinKey.mDsaKey; + pub->p = BN_dup(priv->p); + pub->q = BN_dup(priv->q); + pub->g = BN_dup(priv->g); + pub->pub_key = BN_dup(priv->pub_key); + if((pub->p == NULL) || (pub->q == NULL) || (pub->g == NULL) || + (pub->pub_key == NULL)) { + CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR); + } +} + +/* + * Generate keygen parameters, stash them in a context attr array for later use + * when actually generating the keys. + */ +void DSAKeyPairGenContext::generate( + const Context &context, + uint32 bitSize, + CssmData ¶ms, + uint32 &attrCount, + Context::Attr * &attrs) +{ + void *seed = NULL; + unsigned seedLen = 0; + + /* optional seed from context */ + CssmData *seedData = context.get(CSSM_ATTRIBUTE_SEED); + if(seedData) { + seed = seedData->data(); + seedLen = seedData->length(); + } + + /* generate the params, temp alloc from SecNssCoder */ + NSS_DSAAlgParams algParams; + SecNssCoder coder; + dsaGenParams(bitSize, seed, seedLen, algParams, coder); + + /* + * Here comes the fun part. + * We "return" the DER encoding of these generated params in two ways: + * 1. Copy out to app via the params argument, mallocing if Data ptr is NULL. + * The app must free this. + * 2. Cook up a 1-element Context::attr array containing one ALG_PARAM attr, + * a CSSM_DATA_PTR containing the DER encoding. We have to save a ptr to + * this attr array and free it, the CSSM_DATA it points to, and the DER + * encoding *that* points to, in our destructor. + * + * First, DER encode. + */ + CssmAutoData aDerData(session()); + DSAEncodeAlgParams(algParams, aDerData); + + /* copy/release that into a mallocd CSSM_DATA. */ + CSSM_DATA_PTR derData = (CSSM_DATA_PTR)session().malloc(sizeof(CSSM_DATA)); + *derData = aDerData.release(); + + /* stuff that into a one-element Attr array which we keep after returning */ + freeGenAttrs(); + mGenAttrs = (Context::Attr *)session().malloc(sizeof(Context::Attr)); + mGenAttrs->AttributeType = CSSM_ATTRIBUTE_ALG_PARAMS; + mGenAttrs->AttributeLength = sizeof(CSSM_DATA); + mGenAttrs->Attribute.Data = derData; + + /* and "return" this stuff */ + copyCssmData(CssmData::overlay(*derData), params, session()); + attrCount = 1; + attrs = mGenAttrs; +} + +/* free mGenAttrs and its referents if present */ +void DSAKeyPairGenContext::freeGenAttrs() +{ + if(mGenAttrs == NULL) { + return; + } + if(mGenAttrs->Attribute.Data) { + if(mGenAttrs->Attribute.Data->Data) { + session().free(mGenAttrs->Attribute.Data->Data); + } + session().free(mGenAttrs->Attribute.Data); + } + session().free(mGenAttrs); +} + +/* + * Generate DSA algorithm parameters from optional seed input, returning result + * into NSS_DSAAlgParamss.[pqg]. This is called from both GenerateParameters and from + * KeyPairGenerate (if no GenerateParameters has yet been called). + */ +void DSAKeyPairGenContext::dsaGenParams( + uint32 keySizeInBits, + const void *inSeed, // optional + unsigned inSeedLen, + NSS_DSAAlgParams &algParams, + SecNssCoder &coder) // contents of algParams mallocd from here +{ + unsigned char seedBuf[SHA1_DIGEST_SIZE]; + void *seedPtr; + + /* validate key size */ + if((keySizeInBits < DSA_MIN_KEY_SIZE) || + (keySizeInBits > DSA_MAX_KEY_SIZE) || + (keySizeInBits & DSA_KEY_BITS_MASK)) { + CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_KEY_LENGTH); + } + + /* seed from one of three sources */ + if(inSeed == NULL) { + /* 20 random seed bytes */ + session().getRandomBytes(SHA1_DIGEST_SIZE, seedBuf); + seedPtr = seedBuf; + } + else if(inSeedLen == SHA1_DIGEST_SIZE) { + /* perfect */ + seedPtr = (void *)inSeed; + } + else { + /* hash caller's seed */ + cspGenSha1Hash(inSeed, inSeedLen, seedBuf); + seedPtr = seedBuf; + } + + DSA *dsaKey = DSA_generate_parameters(keySizeInBits, + (unsigned char *)seedPtr, + SHA1_DIGEST_SIZE, + NULL, // counter_ret + NULL, // h_ret + NULL, + NULL); + if(dsaKey == NULL) { + throwRsaDsa("DSA_generate_parameters"); + } + + /* stuff dsaKey->[pqg] into a caller's NSS_DSAAlgParams */ + bnToCssmData(dsaKey->p, algParams.p, coder); + bnToCssmData(dsaKey->q, algParams.q, coder); + bnToCssmData(dsaKey->g, algParams.g, coder); + + DSA_free(dsaKey); +} + +/*** + *** DSA-style CSPKeyInfoProvider. + ***/ +DSAKeyInfoProvider::DSAKeyInfoProvider( + const CssmKey &cssmKey, + AppleCSPSession &session) : + CSPKeyInfoProvider(cssmKey, session) +{ + +} +CSPKeyInfoProvider *DSAKeyInfoProvider::provider( + const CssmKey &cssmKey, + AppleCSPSession &session) +{ + switch(cssmKey.algorithm()) { + case CSSM_ALGID_DSA: + break; + default: + return NULL; + } + switch(cssmKey.keyClass()) { + case CSSM_KEYCLASS_PUBLIC_KEY: + case CSSM_KEYCLASS_PRIVATE_KEY: + break; + default: + return NULL; + } + /* OK, we'll handle this one */ + return new DSAKeyInfoProvider(cssmKey, session); +} + +/* Given a raw key, cook up a Binary key */ +void DSAKeyInfoProvider::CssmKeyToBinary( + CssmKey *paramKey, // optional + CSSM_KEYATTR_FLAGS &attrFlags, // IN/OUT + BinaryKey **binKey) +{ + *binKey = NULL; + DSA *dsaKey = NULL; + + /* first cook up an DSA key, then drop that into a BinaryKey */ + dsaKey = rawCssmKeyToDsa(mKey, mSession, paramKey); + if(dsaKey->p == NULL) { + attrFlags |= CSSM_KEYATTR_PARTIAL; + } + else { + attrFlags &= ~CSSM_KEYATTR_PARTIAL; + } + DSABinaryKey *dsaBinKey = new DSABinaryKey(dsaKey); + *binKey = dsaBinKey; +} + +/* + * Obtain key size in bits. + */ +void DSAKeyInfoProvider::QueryKeySizeInBits( + CSSM_KEY_SIZE &keySize) +{ + DSA *dsaKey = NULL; + + if(mKey.blobType() != CSSM_KEYBLOB_RAW) { + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_FORMAT); + } + dsaKey = rawCssmKeyToDsa(mKey, + mSession, + NULL); // no param key allowed here + if(dsaKey->p != NULL) { + /* normal fully-formed key */ + keySize.LogicalKeySizeInBits = BN_num_bits(dsaKey->p); + keySize.EffectiveKeySizeInBits = keySize.LogicalKeySizeInBits; + DSA_free(dsaKey); + } + else { + /* partial key, get an approximation from pub_key */ + keySize.LogicalKeySizeInBits = BN_num_bits(dsaKey->pub_key); + DSA_free(dsaKey); + /* and indicate this anomaly like so */ + CssmError::throwMe(CSSMERR_CSP_APPLE_PUBLIC_KEY_INCOMPLETE); + } +} + +/* + * Obtain blob suitable for hashing in CSSM_APPLECSP_KEYDIGEST + * passthrough. + */ +bool DSAKeyInfoProvider::getHashableBlob( + Allocator &allocator, + CssmData &blob) // blob to hash goes here +{ + /* No optimized case for DSA keys */ + return false; +} diff --git a/libsecurity_apple_csp/lib/RSA_DSA_keys.h b/libsecurity_apple_csp/lib/RSA_DSA_keys.h new file mode 100644 index 00000000..8bc2cb15 --- /dev/null +++ b/libsecurity_apple_csp/lib/RSA_DSA_keys.h @@ -0,0 +1,241 @@ +/* + * 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. + */ + + +/* + * RSA_DSA_keys.h - key pair support for RSA/DSA + */ + +#ifndef _RSA_DSA_KEYS_H_ +#define _RSA_DSA_KEYS_H_ + +#include +#include +#include +#include "AppleCSPKeys.h" +#include +#include +#include +#include +#include + +#define RSA_PUB_KEY_FORMAT CSSM_KEYBLOB_RAW_FORMAT_PKCS1 +#define RSA_PRIV_KEY_FORMAT CSSM_KEYBLOB_RAW_FORMAT_PKCS8 + +#define DSA_PUB_KEY_FORMAT CSSM_KEYBLOB_RAW_FORMAT_X509 +#define DSA_PRIV_KEY_FORMAT CSSM_KEYBLOB_RAW_FORMAT_FIPS186 + +#define DSA_MIN_KEY_SIZE 512 +#define DSA_MAX_KEY_SIZE 4096 +#define DSA_KEY_BITS_MASK (64 - 1) /* these bits must be zero */ + /* i.e., aligned to 64 bits */ + +#define RSA_MAX_KEY_SIZE 4096 +#define RSA_MAX_PUB_EXPONENT_SIZE 64 + +/* Those max RSA sizes can be overridden with these system preferences */ +#define kRSAKeySizePrefsDomain "com.apple.crypto" +#define kRSAMaxKeySizePref CFSTR("RSAMaxKeySize") +#define kRSAMaxPublicExponentPref CFSTR("RSAMaxPublicExponent") + +/* + * RSA version of a BinaryKey. + */ +class RSABinaryKey : public BinaryKey { +public: + RSABinaryKey(RSA *rsaKey = NULL); + ~RSABinaryKey(); + void generateKeyBlob( + Allocator &allocator, + CssmData &blob, + CSSM_KEYBLOB_FORMAT &format, + AppleCSPSession &session, + const CssmKey *paramKey, /* optional, unused here */ + CSSM_KEYATTR_FLAGS &attrFlags); /* IN/OUT */ + + RSA *mRsaKey; + + bool isOaep() { return mOaep; } + const CSSM_DATA &label() { return mLabel; } + void setOaep( + const CSSM_DATA &label); +private: + /* + * optional fields for OEAP keys + * (mKeyHeader.AlgorithmId == CSSM_ALGMODE_PKCS1_EME_OAEP) + */ + bool mOaep; + CssmAutoData mLabel; +}; + +class RSAKeyPairGenContext : + public AppleCSPContext, private AppleKeyPairGenContext { +public: + RSAKeyPairGenContext( + AppleCSPSession &session, + const Context &) : + AppleCSPContext(session) {} + + ~RSAKeyPairGenContext() { } + + /* no init functionality, but we need to implement it */ + void init( + const Context &, + bool) { } + + // this one is specified in, and called from, CSPFullPluginSession + void generate( + const Context &context, + CssmKey &pubKey, + CssmKey &privKey); + + // this one is specified in, and called from, AppleKeyPairGenContext + void generate( + const Context &context, + BinaryKey &pubBinKey, + BinaryKey &privBinKey, + uint32 &keySize); + +}; /* KeyPairGenContext */ + +/* + * CSPKeyInfoProvider for RSA keys + */ +class RSAKeyInfoProvider : public CSPKeyInfoProvider +{ +private: + RSAKeyInfoProvider( + const CssmKey &cssmKey, + AppleCSPSession &session); +public: + static CSPKeyInfoProvider *provider( + const CssmKey &cssmKey, + AppleCSPSession &session); + + ~RSAKeyInfoProvider() { } + void CssmKeyToBinary( + CssmKey *paramKey, // optional + CSSM_KEYATTR_FLAGS &attrFlags, // IN/OUT + BinaryKey **binKey); // RETURNED + void QueryKeySizeInBits( + CSSM_KEY_SIZE &keySize); // RETURNED + bool getHashableBlob( + Allocator &allocator, + CssmData &hashBlob); +}; + +/* + * DSA version of a BinaryKey. + */ +class DSABinaryKey : public BinaryKey { +public: + DSABinaryKey(DSA *dsaKey = NULL); + ~DSABinaryKey(); + void generateKeyBlob( + Allocator &allocator, + CssmData &blob, + CSSM_KEYBLOB_FORMAT &format, + AppleCSPSession &session, + const CssmKey *paramKey, /* optional */ + CSSM_KEYATTR_FLAGS &attrFlags); /* IN/OUT */ + + DSA *mDsaKey; +}; + +class DSAKeyPairGenContext : + public AppleCSPContext, private AppleKeyPairGenContext { +public: + DSAKeyPairGenContext( + AppleCSPSession &session, + const Context &) : + AppleCSPContext(session), mGenAttrs(NULL) {} + + ~DSAKeyPairGenContext() { freeGenAttrs(); } + + /* no init functionality, but we need to implement it */ + void init( + const Context &, + bool) { } + + // this one is specified in, and called from, CSPFullPluginSession + void generate( + const Context &context, + CssmKey &pubKey, + CssmKey &privKey); + + // this one is specified in, and called from, AppleKeyPairGenContext + void generate( + const Context &context, + BinaryKey &pubBinKey, + BinaryKey &privBinKey, + uint32 &keySize); + + // specified in, and called from, CSPFullPluginSessionÊ- generate parameters + void generate( + const Context &context, + uint32 bitSize, + CssmData ¶ms, + uint32 &attrCount, + Context::Attr * &attrs); + + /* + * Necessary to handle and deflect "context changed" notification which occurs + * after the strange return from "generate parameters", when the plugin adds + * the "returned" values to the Context. + */ + bool changed(const Context &context) { return true; } + + void dsaGenParams( + uint32 keySizeInBits, + const void *inSeed, // optional + unsigned inSeedLen, + NSS_DSAAlgParams &algParams, + SecNssCoder &coder); + +private: + /* gross hack to store attributes "returned" from GenParams */ + Context::Attr *mGenAttrs; + void freeGenAttrs(); +}; /* KeyPairGenContext */ + +/* + * CSPKeyInfoProvider for DSA keys + */ +class DSAKeyInfoProvider : public CSPKeyInfoProvider +{ +private: + DSAKeyInfoProvider( + const CssmKey &cssmKey, + AppleCSPSession &session); +public: + static CSPKeyInfoProvider *provider( + const CssmKey &cssmKey, + AppleCSPSession &session); + + ~DSAKeyInfoProvider() { } + void CssmKeyToBinary( + CssmKey *paramKey, // optional + CSSM_KEYATTR_FLAGS &attrFlags, // IN/OUT + BinaryKey **binKey); // RETURNED + void QueryKeySizeInBits( + CSSM_KEY_SIZE &keySize); // RETURNED + bool getHashableBlob( + Allocator &allocator, + CssmData &hashBlob); +}; + +#endif /* _RSA_DSA_KEYS_H_ */ diff --git a/libsecurity_apple_csp/lib/RSA_DSA_signature.cpp b/libsecurity_apple_csp/lib/RSA_DSA_signature.cpp new file mode 100644 index 00000000..d28a61df --- /dev/null +++ b/libsecurity_apple_csp/lib/RSA_DSA_signature.cpp @@ -0,0 +1,394 @@ +/* + * 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. + */ + + +/* + * RSA_DSA_signature.cpp - openssl-based signature classes. + */ + +#include "RSA_DSA_signature.h" +#include "RSA_DSA_utils.h" +#include +#include +#include +#include +#include +#include + +#define rsaSigDebug(args...) secdebug("rsaSig", ## args) + +static ModuleNexus gMutex; + +RSASigner::~RSASigner() +{ + StLock _(gMutex()); + if(mWeMallocdRsaKey) { + assert(mRsaKey != NULL); + RSA_free(mRsaKey); + mRsaKey = NULL; + mWeMallocdRsaKey = false; + } +} + +/* reusable init */ +void RSASigner::signerInit( + const Context &context, + bool isSigning) +{ + StLock _(gMutex()); + + setIsSigning(isSigning); + keyFromContext(context); + + /* optional padding attribute */ + uint32 padding; + bool padPresent = context.getInt(CSSM_ATTRIBUTE_PADDING, padding); + if(padPresent) { + /* padding specified in context, convert to openssl style */ + switch(padding) { + case CSSM_PADDING_NONE: + mPadding = RSA_NO_PADDING; + break; + case CSSM_PADDING_PKCS1: + mPadding = RSA_PKCS1_PADDING; + break; + default: + CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_PADDING); + } + } + + /* optional blinding attribute */ + uint32 blinding = context.getInt(CSSM_ATTRIBUTE_RSA_BLINDING); + if(blinding) { + if(RSA_blinding_on(mRsaKey, NULL) <= 0) { + /* actually no legit failures */ + CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR); + } + } + else { + RSA_blinding_off(mRsaKey); + } + + setInitFlag(true); +} + +/* sign */ +void RSASigner::sign( + const void *data, + size_t dataLen, + void *sig, + size_t *sigLen) /* IN/OUT */ +{ + StLock _(gMutex()); + + if(mRsaKey == NULL) { + CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR); + } + + /* get encoded digest info */ + CssmAutoData encodedInfo(alloc()); + int irtn = generateDigestInfo(data, + dataLen, + digestAlg(), + encodedInfo, + RSA_size(mRsaKey)); + if(irtn) { + rsaSigDebug("***digestInfo error\n"); + throwOpensslErr(irtn); + } + + /* signature := encrypted digest info */ + irtn = RSA_private_encrypt(encodedInfo.length(), + (unsigned char *)encodedInfo.data(), + (unsigned char *)sig, + mRsaKey, + mPadding); + if(irtn < 0) { + throwRsaDsa("RSA_private_encrypt"); + } + if((unsigned)irtn > *sigLen) { + rsaSigDebug("RSA_private_encrypt: sig overflow"); + CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR); + } + *sigLen = (unsigned)irtn; +} + +/* verify */ +void RSASigner::verify( + const void *data, + size_t dataLen, + const void *sig, + size_t sigLen) +{ + StLock _(gMutex()); + + const char *op = NULL; + bool throwSigVerify = false; + + if(mRsaKey == NULL) { + CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR); + } + + /* get encoded digest info */ + CssmAutoData encodedInfo(alloc()); + int irtn = generateDigestInfo(data, + dataLen, + digestAlg(), + encodedInfo, + RSA_size(mRsaKey)); + if(irtn) { + rsaSigDebug("***digestInfo error\n"); + CssmError::throwMe(/* FIXME */CSSMERR_CSP_INTERNAL_ERROR); + } + + /* malloc decrypted signature */ + unsigned char *decryptSig = + (unsigned char *)alloc().malloc(RSA_size(mRsaKey)); + unsigned decryptSigLen; + + /* signature should be encrypted digest info; decrypt the signature */ + irtn = RSA_public_decrypt(sigLen, + (unsigned char *)sig, + decryptSig, + mRsaKey, + mPadding); + if(irtn < 0) { + op = "RSA_public_decrypt"; + throwSigVerify = true; + goto abort; + } + decryptSigLen = (unsigned)irtn; + if(decryptSigLen != encodedInfo.length()) { + rsaSigDebug("***Decrypted signature length error (exp %ld, got %d)\n", + encodedInfo.length(), decryptSigLen); + throwSigVerify = true; + op = "RSA Sig length check"; + goto abort; + } + if(memcmp(decryptSig, encodedInfo.data(), decryptSigLen)) { + rsaSigDebug("***Signature miscompare\n"); + throwSigVerify = true; + op = "RSA Sig miscompare"; + goto abort; + } + else { + irtn = 0; + } +abort: + if(decryptSig != NULL) { + alloc().free(decryptSig); + } + if(throwSigVerify) { + clearOpensslErrors(); + CssmError::throwMe(CSSMERR_CSP_VERIFY_FAILED); + } +} + +/* works for both, but only used for signing */ +size_t RSASigner::maxSigSize() +{ + StLock _(gMutex()); + if(mRsaKey == NULL) { + return 0; + } + return RSA_size(mRsaKey); +} + +/* + * obtain key from context, validate, convert to native RSA key + */ +void RSASigner::keyFromContext( + const Context &context) +{ + if(initFlag() && (mRsaKey != NULL)) { + /* reusing context, OK */ + return; + } + + CSSM_KEYCLASS keyClass; + CSSM_KEYUSE keyUse; + if(isSigning()) { + /* signing with private key */ + keyClass = CSSM_KEYCLASS_PRIVATE_KEY; + keyUse = CSSM_KEYUSE_SIGN; + } + else { + /* verifying with public key */ + keyClass = CSSM_KEYCLASS_PUBLIC_KEY; + keyUse = CSSM_KEYUSE_VERIFY; + } + if(mRsaKey == NULL) { + CSSM_DATA label = {0, NULL}; + mRsaKey = contextToRsaKey(context, + mSession, + keyClass, + keyUse, + mWeMallocdRsaKey, + label); + /* cannot have label param for signing */ + assert(label.Data == NULL); + } +} + +DSASigner::~DSASigner() +{ + if(mWeMallocdDsaKey) { + assert(mDsaKey != NULL); + DSA_free(mDsaKey); + mDsaKey = NULL; + mWeMallocdDsaKey = false; + } +} + +/* reusable init */ +void DSASigner::signerInit( + const Context &context, + bool isSigning) +{ + setIsSigning(isSigning); + keyFromContext(context); + setInitFlag(true); +} + +/* sign */ +void DSASigner::sign( + const void *data, + size_t dataLen, + void *sig, + size_t *sigLen) /* IN/OUT */ +{ + if(mDsaKey == NULL) { + CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR); + } + if(mDsaKey->priv_key == NULL) { + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS); + } + + /* get signature in internal format */ + DSA_SIG *dsaSig = DSA_do_sign((unsigned char *)data, dataLen, mDsaKey); + if(dsaSig == NULL) { + throwRsaDsa("DSA_do_sign"); + } + + /* DER encode the signature */ + CssmAutoData encodedSig(alloc()); + int irtn = DSASigEncode(dsaSig, encodedSig); + if(irtn) { + throwRsaDsa("DSASigEncode"); + } + if(encodedSig.length() > *sigLen) { + throwRsaDsa("DSA sign overflow"); + } + memmove(sig, encodedSig.data(), encodedSig.length()); + *sigLen = encodedSig.length(); + DSA_SIG_free(dsaSig); +} + +/* verify */ +void DSASigner::verify( + const void *data, + size_t dataLen, + const void *sig, + size_t sigLen) +{ + bool throwSigVerify = false; + DSA_SIG *dsaSig = NULL; + CSSM_RETURN crtn = CSSM_OK; + int irtn; + + if(mDsaKey == NULL) { + CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR); + } + if(mDsaKey->pub_key == NULL) { + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS); + } + + /* incoming sig is DER encoded....decode into internal format */ + dsaSig = DSA_SIG_new(); + crtn = DSASigDecode(dsaSig, sig, sigLen); + if(crtn) { + goto abort; + } + + irtn = DSA_do_verify((unsigned char *)data, dataLen, dsaSig, mDsaKey); + if(irtn != 1) { + throwSigVerify = true; + } + +abort: + if(dsaSig != NULL) { + DSA_SIG_free(dsaSig); + } + if(throwSigVerify) { + clearOpensslErrors(); + CssmError::throwMe(CSSMERR_CSP_VERIFY_FAILED); + } + else if(crtn) { + CssmError::throwMe(crtn); + } +} + +/* + * Works for both, but only used for signing. + * DSA sig is a sequence of two 160-bit integers. + */ +size_t DSASigner::maxSigSize() +{ + if(mDsaKey == NULL) { + return 0; + } + size_t outSize; + size_t sizeOfOneInt; + + sizeOfOneInt = (160 / 8) + // the raw contents + 1 + // possible leading zero + 2; // tag + length (assume DER, not BER) + outSize = (2 * sizeOfOneInt) + 5; + return outSize; +} + +/* + * obtain key from context, validate, convert to native DSA key + */ +void DSASigner::keyFromContext( + const Context &context) +{ + if(initFlag() && (mDsaKey != NULL)) { + /* reusing context, OK */ + return; + } + + CSSM_KEYCLASS keyClass; + CSSM_KEYUSE keyUse; + if(isSigning()) { + /* signing with private key */ + keyClass = CSSM_KEYCLASS_PRIVATE_KEY; + keyUse = CSSM_KEYUSE_SIGN; + } + else { + /* verifying with public key */ + keyClass = CSSM_KEYCLASS_PUBLIC_KEY; + keyUse = CSSM_KEYUSE_VERIFY; + } + if(mDsaKey == NULL) { + mDsaKey = contextToDsaKey(context, + mSession, + keyClass, + keyUse, + mWeMallocdDsaKey); + } +} diff --git a/libsecurity_apple_csp/lib/RSA_DSA_signature.h b/libsecurity_apple_csp/lib/RSA_DSA_signature.h new file mode 100644 index 00000000..c0fdbdd7 --- /dev/null +++ b/libsecurity_apple_csp/lib/RSA_DSA_signature.h @@ -0,0 +1,135 @@ +/* + * 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. + */ + + +/* + * RSA_DSA_signature.h - openssl-based signature classes. + */ + +#ifndef _RSA_DSA_SIGNATURE_H_ +#define _RSA_DSA_SIGNATURE_H_ + +#include +#include +#include +#include +#include + +#define RSA_SIG_PADDING_DEFAULT RSA_PKCS1_PADDING + +class RSASigner : public RawSigner { +public: + RSASigner( + Allocator &alloc, + AppleCSPSession &session, + CSSM_ALGORITHMS digestAlg) : + RawSigner(alloc, digestAlg), + mRsaKey(NULL), + mWeMallocdRsaKey(false), + mSession(session), + mPadding(RSA_SIG_PADDING_DEFAULT) { } + + ~RSASigner(); + + /* reusable init */ + void signerInit( + const Context &context, + bool isSigning); + + + /* sign */ + void sign( + const void *data, + size_t dataLen, + void *sig, + size_t *sigLen); /* IN/OUT */ + + /* verify */ + void verify( + const void *data, + size_t dataLen, + const void *sig, + size_t sigLen); + + /* works for both, but only used for signing */ + size_t maxSigSize(); + +private: + + /* + * obtain key from context, validate, convert to RSA key + */ + void keyFromContext( + const Context &context); + + RSA *mRsaKey; + bool mWeMallocdRsaKey; + AppleCSPSession &mSession; + int mPadding; // RSA_NO_PADDING, RSA_PKCS1_PADDING +}; + +class DSASigner : public RawSigner { +public: + DSASigner( + Allocator &alloc, + AppleCSPSession &session, + CSSM_ALGORITHMS digestAlg) : + RawSigner(alloc, digestAlg), + mDsaKey(NULL), + mWeMallocdDsaKey(false), + mSession(session) { } + + ~DSASigner(); + + /* reusable init */ + void signerInit( + const Context &context, + bool isSigning); + + + /* sign */ + void sign( + const void *data, + size_t dataLen, + void *sig, + size_t *sigLen); /* IN/OUT */ + + /* verify */ + void verify( + const void *data, + size_t dataLen, + const void *sig, + size_t sigLen); + + /* works for both, but only used for signing */ + size_t maxSigSize(); + +private: + + /* + * obtain key from context, validate, convert to DSA key + */ + void keyFromContext( + const Context &context); + + DSA *mDsaKey; + bool mWeMallocdDsaKey; + AppleCSPSession &mSession; +}; + + +#endif /* _RSA_DSA_SIGNATURE_H_ */ diff --git a/libsecurity_apple_csp/lib/RSA_DSA_utils.cpp b/libsecurity_apple_csp/lib/RSA_DSA_utils.cpp new file mode 100644 index 00000000..f85ecfa9 --- /dev/null +++ b/libsecurity_apple_csp/lib/RSA_DSA_utils.cpp @@ -0,0 +1,623 @@ +/* + * 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. + */ + + +/* + * RSA_DSA_utils.cpp + */ + +#include "RSA_DSA_utils.h" +#include "RSA_DSA_keys.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define rsaMiscDebug(args...) secdebug("rsaMisc", ## args) + +/* + * Obtain and cache max key sizes. System preferences only consulted + * at most once per process. + */ + +/* + * Do dictionary lookup, convert possible CFNumber to uint32. + * Does not alter val if valid number is not found. + */ +static void rsaLookupVal( + Dictionary &prefs, + CFStringRef key, + uint32 &val) +{ + CFNumberRef cfVal = (CFNumberRef)prefs.getValue(key); + if(cfVal == NULL) { + return; + } + if(CFGetTypeID(cfVal) != CFNumberGetTypeID()) { + return; + } + + /* ensure the number is positive, not relying on gcc 64-bit arithmetic */ + SInt32 s32 = 0; + CFNumberRef cfLimit = CFNumberCreate(NULL, kCFNumberSInt32Type, &s32); + CFComparisonResult result = CFNumberCompare(cfVal, cfLimit, NULL); + CFRelease(cfLimit); + if(result == kCFCompareLessThan) { + /* negative value in preference */ + return; + } + + /* ensure the number fits in 31 bits (the useful size of a SInt32 for us) */ + s32 = 0x7fffffff; + cfLimit = CFNumberCreate(NULL, kCFNumberSInt32Type, &s32); + result = CFNumberCompare(cfVal, cfLimit, NULL); + CFRelease(cfLimit); + if(result == kCFCompareGreaterThan) { + /* too large; discard it */ + return; + } + SInt64 s64; + if(!CFNumberGetValue(cfVal, kCFNumberSInt64Type, &s64)) { + /* impossible, right? We already range checked */ + return; + } + val = (uint32)s64; +} + +struct RSAKeySizes { + uint32 maxKeySize; + uint32 maxPubExponentSize; + RSAKeySizes(); +}; + +/* one-time only prefs lookup */ +RSAKeySizes::RSAKeySizes() +{ + /* set defaults, these might get overridden */ + maxKeySize = RSA_MAX_KEY_SIZE; + maxPubExponentSize = RSA_MAX_PUB_EXPONENT_SIZE; + + /* now see if there are prefs set for either of these */ + Dictionary* d = Dictionary::CreateDictionary(kRSAKeySizePrefsDomain, Dictionary::US_System, true); + if (!d) + { + return; + } + + if (d->dict()) + { + auto_ptrapd(d); + rsaLookupVal(*apd, kRSAMaxKeySizePref, maxKeySize); + rsaLookupVal(*apd, kRSAMaxPublicExponentPref, maxPubExponentSize); + } + else + { + delete d; + } +} + +static ModuleNexus rsaKeySizes; + +/* + * Public functions to obtain the currently configured max sizes of + * RSA key and public exponent. + */ +uint32 rsaMaxKeySize() +{ + return rsaKeySizes().maxKeySize; +} + +uint32 rsaMaxPubExponentSize() +{ + return rsaKeySizes().maxPubExponentSize; +} + +/* + * Given a Context: + * -- obtain CSSM key (there must only be one) + * -- validate keyClass + * -- validate keyUsage + * -- convert to RSA *, allocating the RSA key if necessary + */ +RSA *contextToRsaKey( + const Context &context, + AppleCSPSession &session, + CSSM_KEYCLASS keyClass, // CSSM_KEYCLASS_{PUBLIC,PRIVATE}_KEY + CSSM_KEYUSE usage, // CSSM_KEYUSE_ENCRYPT, CSSM_KEYUSE_SIGN, etc. + bool &mallocdKey, // RETURNED + CSSM_DATA &label) // mallocd and RETURNED for OAEP +{ + CssmKey &cssmKey = + context.get(CSSM_ATTRIBUTE_KEY, CSSMERR_CSP_MISSING_ATTR_KEY); + const CSSM_KEYHEADER &hdr = cssmKey.KeyHeader; + if(hdr.AlgorithmId != CSSM_ALGID_RSA) { + CssmError::throwMe(CSSMERR_CSP_ALGID_MISMATCH); + } + if(hdr.KeyClass != keyClass) { + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS); + } + cspValidateIntendedKeyUsage(&hdr, usage); + cspVerifyKeyTimes(hdr); + return cssmKeyToRsa(cssmKey, session, mallocdKey, label); +} +/* + * Convert a CssmKey to an RSA * key. May result in the creation of a new + * RSA (when cssmKey is a raw key); allocdKey is true in that case + * in which case the caller generally has to free the allocd key). + */ +RSA *cssmKeyToRsa( + const CssmKey &cssmKey, + AppleCSPSession &session, + bool &allocdKey, // RETURNED + CSSM_DATA &label) // mallocd and RETURNED for OAEP +{ + RSA *rsaKey = NULL; + allocdKey = false; + + const CSSM_KEYHEADER *hdr = &cssmKey.KeyHeader; + if(hdr->AlgorithmId != CSSM_ALGID_RSA) { + // someone else's key (should never happen) + CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM); + } + switch(hdr->BlobType) { + case CSSM_KEYBLOB_RAW: + rsaKey = rawCssmKeyToRsa(cssmKey, label); + allocdKey = true; + break; + case CSSM_KEYBLOB_REFERENCE: + { + BinaryKey &binKey = session.lookupRefKey(cssmKey); + RSABinaryKey *rsaBinKey = dynamic_cast(&binKey); + /* this cast failing means that this is some other + * kind of binary key */ + if(rsaBinKey == NULL) { + rsaMiscDebug("cssmKeyToRsa: wrong BinaryKey subclass\n"); + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY); + } + assert(rsaBinKey->mRsaKey != NULL); + rsaKey = rsaBinKey->mRsaKey; + break; + } + default: + CssmError::throwMe(CSSMERR_CSP_KEY_BLOB_TYPE_INCORRECT); + } + return rsaKey; +} + +/* + * Convert a raw CssmKey to a newly alloc'd RSA key. + */ +RSA *rawCssmKeyToRsa( + const CssmKey &cssmKey, + CSSM_DATA &label) // mallocd and RETURNED for OAEP keys +{ + const CSSM_KEYHEADER *hdr = &cssmKey.KeyHeader; + bool isPub; + bool isOaep = false; + + assert(hdr->BlobType == CSSM_KEYBLOB_RAW); + + switch(hdr->AlgorithmId) { + case CSSM_ALGID_RSA: + break; + case CSSM_ALGMODE_PKCS1_EME_OAEP: + isOaep = true; + break; + default: + // someone else's key (should never happen) + CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM); + } + + /* validate and figure out what we're dealing with */ + switch(hdr->KeyClass) { + case CSSM_KEYCLASS_PUBLIC_KEY: + switch(hdr->Format) { + case CSSM_KEYBLOB_RAW_FORMAT_PKCS1: + case CSSM_KEYBLOB_RAW_FORMAT_X509: + case CSSM_KEYBLOB_RAW_FORMAT_OPENSSH: + case CSSM_KEYBLOB_RAW_FORMAT_OPENSSH2: + break; + default: + CssmError::throwMe( + CSSMERR_CSP_INVALID_ATTR_PUBLIC_KEY_FORMAT); + } + if(isOaep && (hdr->Format != CSSM_KEYBLOB_RAW_FORMAT_X509)) { + CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_PUBLIC_KEY_FORMAT); + } + isPub = true; + break; + case CSSM_KEYCLASS_PRIVATE_KEY: + switch(hdr->Format) { + case CSSM_KEYBLOB_RAW_FORMAT_PKCS8: // default + case CSSM_KEYBLOB_RAW_FORMAT_PKCS1: // openssl style + case CSSM_KEYBLOB_RAW_FORMAT_OPENSSH: + break; + default: + CssmError::throwMe( + CSSMERR_CSP_INVALID_ATTR_PRIVATE_KEY_FORMAT); + } + if(isOaep && (hdr->Format != CSSM_KEYBLOB_RAW_FORMAT_PKCS8)) { + CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_PRIVATE_KEY_FORMAT); + } + isPub = false; + break; + default: + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS); + } + + RSA *rsaKey = RSA_new(); + if(rsaKey == NULL) { + CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR); + } + CSSM_RETURN crtn; + if(isOaep) { + if(isPub) { + crtn = RSAOAEPPublicKeyDecode(rsaKey, + cssmKey.KeyData.Data, cssmKey.KeyData.Length, + &label); + } + else { + crtn = RSAOAEPPrivateKeyDecode(rsaKey, + cssmKey.KeyData.Data, cssmKey.KeyData.Length, + &label); + } + } + else { + if(isPub) { + crtn = RSAPublicKeyDecode(rsaKey, hdr->Format, + cssmKey.KeyData.Data, cssmKey.KeyData.Length); + } + else { + crtn = RSAPrivateKeyDecode(rsaKey, hdr->Format, + cssmKey.KeyData.Data, cssmKey.KeyData.Length); + } + } + if(crtn) { + RSA_free(rsaKey); + CssmError::throwMe(crtn); + } + + /* enforce max key size and max public exponent size */ + bool badKey = false; + uint32 keySize = RSA_size(rsaKey) * 8; + if(keySize > rsaMaxKeySize()) { + rsaMiscDebug("rawCssmKeyToRsa: key size exceeded"); + badKey = true; + } + else { + keySize = BN_num_bytes(rsaKey->e) * 8; + if(keySize > rsaMaxPubExponentSize()) { + badKey = true; + rsaMiscDebug("rawCssmKeyToRsa: pub exponent size exceeded"); + } + } + if(badKey) { + RSA_free(rsaKey); + CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_KEY_LENGTH); + } + return rsaKey; +} + +/* + * Given a partially formed DSA public key (with no p, q, or g) and a + * CssmKey representing a supposedly fully-formed DSA key, populate + * the public key's p, g, and q with values from the fully formed key. + */ +CSSM_RETURN dsaGetParamsFromKey( + DSA *partialKey, + const CssmKey ¶mKey, + AppleCSPSession &session) +{ + bool allocdKey; + DSA *dsaParamKey = cssmKeyToDsa(paramKey, session, allocdKey); + if(dsaParamKey == NULL) { + errorLog0("dsaGetParamsFromKey: bad paramKey\n"); + return CSSMERR_CSP_APPLE_PUBLIC_KEY_INCOMPLETE; + } + CSSM_RETURN crtn = CSSM_OK; + + /* require fully formed other key of course... */ + if((dsaParamKey->p == NULL) || + (dsaParamKey->q == NULL) || + (dsaParamKey->g == NULL)) { + errorLog0("dsaGetParamsFromKey: incomplete paramKey\n"); + crtn = CSSMERR_CSP_APPLE_PUBLIC_KEY_INCOMPLETE; + goto abort; + } + rsaMiscDebug("dsaGetParamsFromKey: partialKey %p paramKey %p", + partialKey, dsaParamKey); + + partialKey->q = BN_dup(dsaParamKey->q); + partialKey->p = BN_dup(dsaParamKey->p); + partialKey->g = BN_dup(dsaParamKey->g); + +abort: + if(allocdKey) { + DSA_free(dsaParamKey); + } + return crtn; +} + +/* + * Given a Context: + * -- obtain CSSM key (there must only be one) + * -- validate keyClass + * -- validate keyUsage + * -- convert to DSA *, allocating the DSA key if necessary + */ +DSA *contextToDsaKey( + const Context &context, + AppleCSPSession &session, + CSSM_KEYCLASS keyClass, // CSSM_KEYCLASS_{PUBLIC,PRIVATE}_KEY + CSSM_KEYUSE usage, // CSSM_KEYUSE_ENCRYPT, CSSM_KEYUSE_SIGN, etc. + bool &mallocdKey) // RETURNED +{ + CssmKey &cssmKey = + context.get(CSSM_ATTRIBUTE_KEY, CSSMERR_CSP_MISSING_ATTR_KEY); + const CSSM_KEYHEADER &hdr = cssmKey.KeyHeader; + if(hdr.AlgorithmId != CSSM_ALGID_DSA) { + CssmError::throwMe(CSSMERR_CSP_ALGID_MISMATCH); + } + if(hdr.KeyClass != keyClass) { + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS); + } + cspValidateIntendedKeyUsage(&hdr, usage); + cspVerifyKeyTimes(hdr); + DSA *rtnDsa = cssmKeyToDsa(cssmKey, session, mallocdKey); + if((keyClass == CSSM_KEYCLASS_PUBLIC_KEY) && + (rtnDsa->p == NULL)) { + /* + * Special case: this specific key is only partially formed; + * it's missing the DSA parameters p, g, and q. To proceed with this + * key, the caller must pass in another fully formned DSA public key + * in raw form in the context. If it's there we use those parameters. + */ + rsaMiscDebug("contextToDsaKey; partial DSA key %p", rtnDsa); + CssmKey *paramKey = context.get(CSSM_ATTRIBUTE_PARAM_KEY); + if(paramKey == NULL) { + rsaMiscDebug("contextToDsaKey: missing DSA params, no pub key in " + "context"); + if(mallocdKey) { + DSA_free(rtnDsa); + mallocdKey = false; + } + CssmError::throwMe(CSSMERR_CSP_APPLE_PUBLIC_KEY_INCOMPLETE); + } + + /* + * If this is a ref key, we have to cook up a new DSA key to + * avoid modifying the existing key. If we started with a raw key, + * we can modify it directly since the underlying DSA key has + * a lifetime only as long as this context (and since the context + * contains the parameter-bearing key, the params are valid + * as long as the DSA key). + */ + if(!mallocdKey) { + DSA *existKey = rtnDsa; + rtnDsa = DSA_new(); + if(rtnDsa == NULL) { + CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR); + } + rtnDsa->pub_key = BN_dup(existKey->pub_key); + rsaMiscDebug("contextToDsaKey; temp partial copy %p", rtnDsa); + mallocdKey = true; + } + + /* + * Add params from paramKey into rtnDsa + */ + CSSM_RETURN crtn = dsaGetParamsFromKey(rtnDsa, *paramKey, session); + if(crtn) { + if(mallocdKey) { + DSA_free(rtnDsa); + mallocdKey = false; + } + CssmError::throwMe(crtn); + } + } + return rtnDsa; +} + +/* + * Convert a CssmKey to an DSA * key. May result in the creation of a new + * DSA (when cssmKey is a raw key); allocdKey is true in that case + * in which case the caller generally has to free the allocd key). + */ +DSA *cssmKeyToDsa( + const CssmKey &cssmKey, + AppleCSPSession &session, + bool &allocdKey) // RETURNED +{ + DSA *dsaKey = NULL; + allocdKey = false; + + const CSSM_KEYHEADER *hdr = &cssmKey.KeyHeader; + if(hdr->AlgorithmId != CSSM_ALGID_DSA) { + // someone else's key (should never happen) + CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM); + } + switch(hdr->BlobType) { + case CSSM_KEYBLOB_RAW: + dsaKey = rawCssmKeyToDsa(cssmKey, session, NULL); + allocdKey = true; + break; + case CSSM_KEYBLOB_REFERENCE: + { + BinaryKey &binKey = session.lookupRefKey(cssmKey); + DSABinaryKey *dsaBinKey = dynamic_cast(&binKey); + /* this cast failing means that this is some other + * kind of binary key */ + if(dsaBinKey == NULL) { + rsaMiscDebug("cssmKeyToDsa: wrong BinaryKey subclass\n"); + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY); + } + assert(dsaBinKey->mDsaKey != NULL); + dsaKey = dsaBinKey->mDsaKey; + break; + } + default: + CssmError::throwMe(CSSMERR_CSP_KEY_BLOB_TYPE_INCORRECT); + } + return dsaKey; +} + +/* + * Convert a raw CssmKey to a newly alloc'd DSA key. + */ +DSA *rawCssmKeyToDsa( + const CssmKey &cssmKey, + AppleCSPSession &session, + const CssmKey *paramKey) // optional +{ + const CSSM_KEYHEADER *hdr = &cssmKey.KeyHeader; + bool isPub; + + assert(hdr->BlobType == CSSM_KEYBLOB_RAW); + + if(hdr->AlgorithmId != CSSM_ALGID_DSA) { + // someone else's key (should never happen) + CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM); + } + /* validate and figure out what we're dealing with */ + switch(hdr->KeyClass) { + case CSSM_KEYCLASS_PUBLIC_KEY: + switch(hdr->Format) { + case CSSM_KEYBLOB_RAW_FORMAT_FIPS186: + case CSSM_KEYBLOB_RAW_FORMAT_X509: + case CSSM_KEYBLOB_RAW_FORMAT_OPENSSH2: + break; + default: + CssmError::throwMe( + CSSMERR_CSP_INVALID_ATTR_PUBLIC_KEY_FORMAT); + } + isPub = true; + break; + case CSSM_KEYCLASS_PRIVATE_KEY: + switch(hdr->Format) { + case CSSM_KEYBLOB_RAW_FORMAT_FIPS186: // default + case CSSM_KEYBLOB_RAW_FORMAT_OPENSSL: // openssl style + case CSSM_KEYBLOB_RAW_FORMAT_PKCS8: // SMIME style + break; + /* openssh real soon now */ + case CSSM_KEYBLOB_RAW_FORMAT_OPENSSH: + default: + CssmError::throwMe( + CSSMERR_CSP_INVALID_ATTR_PRIVATE_KEY_FORMAT); + } + isPub = false; + break; + default: + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS); + } + + CSSM_RETURN crtn; + DSA *dsaKey = DSA_new(); + + if (dsaKey == NULL) { + crtn = CSSMERR_CSP_MEMORY_ERROR; + } + else { + if(dsaKey == NULL) { + CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR); + } + if(isPub) { + crtn = DSAPublicKeyDecode(dsaKey, hdr->Format, + cssmKey.KeyData.Data, + cssmKey.KeyData.Length); + } + else { + crtn = DSAPrivateKeyDecode(dsaKey, hdr->Format, + cssmKey.KeyData.Data, + cssmKey.KeyData.Length); + } + } + + if(crtn) { + if (dsaKey != NULL) { + DSA_free(dsaKey); + } + + CssmError::throwMe(crtn); + } + /* + * Add in optional external parameters if this is not fully formed. + * This path is only taken from DSAKeyInfoProvider::CssmKeyToBinary, + * e.g., when doing a NULL unwrap of a partially formed DSA public + * key with the "complete the key with these params" option. + */ + if(isPub && (dsaKey->p == NULL) && (paramKey != NULL)) { + rsaMiscDebug("rawCssmKeyToDsa; updating dsaKey %p", dsaKey); + crtn = dsaGetParamsFromKey(dsaKey, *paramKey, session); + if(crtn) { + DSA_free(dsaKey); + CssmError::throwMe(crtn); + } + } + + if(dsaKey->p != NULL) { + /* avoid use of provided DSA key which exceeds the max size */ + uint32 keySize = BN_num_bits(dsaKey->p); + if(keySize > DSA_MAX_KEY_SIZE) { + DSA_free(dsaKey); + CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_KEY_LENGTH); + } + } + return dsaKey; +} + +/* + * Given a DSA private key, calculate its public component if it + * doesn't already exist. Used for calculating the key digest of + * an incoming raw private key. + */ +void dsaKeyPrivToPub( + DSA *dsaKey) +{ + assert(dsaKey != NULL); + assert(dsaKey->priv_key != NULL); + + if(dsaKey->pub_key != NULL) { + return; + } + + /* logic copied from DSA_generate_key() */ + dsaKey->pub_key = BN_new(); + if(dsaKey->pub_key == NULL) { + CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR); + } + BN_CTX *ctx = BN_CTX_new(); + if (ctx == NULL) { + CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR); + } + int rtn = BN_mod_exp(dsaKey->pub_key, + dsaKey->g, + dsaKey->priv_key, + dsaKey->p, + ctx); + BN_CTX_free(ctx); + if(rtn == 0) { + CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR); + } +} diff --git a/libsecurity_apple_csp/lib/RSA_DSA_utils.h b/libsecurity_apple_csp/lib/RSA_DSA_utils.h new file mode 100644 index 00000000..fecfd88d --- /dev/null +++ b/libsecurity_apple_csp/lib/RSA_DSA_utils.h @@ -0,0 +1,124 @@ +/* + * 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. + */ + + +/* + * RSA_DSA_utils.h + */ +#ifndef _RSA_DSA_UTILS_H_ +#define _RSA_DSA_UTILS_H_ + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +uint32 rsaMaxKeySize(); +uint32 rsaMaxPubExponentSize(); + +/* + * Given a Context: + * -- obtain CSSM key (there must only be one) + * -- validate keyClass + * -- validate keyUsage + * -- convert to RSA *, allocating the RSA key if necessary + */ +RSA *contextToRsaKey( + const Context &context, + AppleCSPSession &session, + CSSM_KEYCLASS keyClass, // CSSM_KEYCLASS_{PUBLIC,PRIVATE}_KEY + CSSM_KEYUSE usage, // CSSM_KEYUSE_ENCRYPT, CSSM_KEYUSE_SIGN, etc. + bool &mallocdKey, // RETURNED + CSSM_DATA &label); // mallocd and RETURNED for OAEP + +/* + * Convert a CssmKey to an RSA * key. May result in the creation of a new + * RSA (when cssmKey is a raw key); allocdKey is true in that case + * in which case the caller generally has to free the allocd key). + */ +RSA *cssmKeyToRsa( + const CssmKey &cssmKey, + AppleCSPSession &session, + bool &allocdKey, // RETURNED + CSSM_DATA &label); // mallocd and RETURNED for OAEP + +/* + * Convert a raw CssmKey to a newly alloc'd RSA *. + */ +RSA *rawCssmKeyToRsa( + const CssmKey &cssmKey, + CSSM_DATA &label); // mallocd and RETURNED for OAEP keys + +/* + * Given a partially formed DSA public key (with no p, q, or g) and a + * CssmKey representing a supposedly fully-formed DSA key, populate + * the public key's p, g, and q with values from the fully formed key. + */ +CSSM_RETURN dsaGetParamsFromKey( + DSA *partialKey, + const CssmKey ¶mKey, + AppleCSPSession &session); + +/* + * Given a Context: + * -- obtain CSSM key (there must only be one) + * -- validate keyClass + * -- validate keyUsage + * -- convert to DSA *, allocating the DSA key if necessary + */ +DSA *contextToDsaKey( + const Context &context, + AppleCSPSession &session, + CSSM_KEYCLASS keyClass, // CSSM_KEYCLASS_{PUBLIC,PRIVATE}_KEY + CSSM_KEYUSE usage, // CSSM_KEYUSE_ENCRYPT, CSSM_KEYUSE_SIGN, etc. + bool &mallocdKey); // RETURNED + +/* + * Convert a CssmKey to an DSA * key. May result in the creation of a new + * DSA (when cssmKey is a raw key); allocdKey is true in that case + * in which case the caller generally has to free the allocd key). + */ +DSA *cssmKeyToDsa( + const CssmKey &cssmKey, + AppleCSPSession &session, + bool &allocdKey); // RETURNED + +/* + * Convert a raw CssmKey to a newly alloc'd DSA *. + */ +DSA *rawCssmKeyToDsa( + const CssmKey &cssmKey, + AppleCSPSession &session, + const CssmKey *paramKey); // optional + +/* + * Given a DSA private key, calculate its public component if it + * doesn't already exist. Used for calculating the key digest of + * an incoming raw private key. + */ +void dsaKeyPrivToPub( + DSA *dsaKey); + +#ifdef __cplusplus +} +#endif + +#endif /*_RSA_DSA_UTILS_H_ */ diff --git a/libsecurity_apple_csp/lib/RSA_asymmetric.cpp b/libsecurity_apple_csp/lib/RSA_asymmetric.cpp new file mode 100644 index 00000000..03167b96 --- /dev/null +++ b/libsecurity_apple_csp/lib/RSA_asymmetric.cpp @@ -0,0 +1,224 @@ +/* + * 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. + */ + + +/* + * RSA_asymmetric.cpp - CSPContext for RSA asymmetric encryption + */ + +#include "RSA_asymmetric.h" +#include "RSA_DSA_utils.h" +#include +#include + +#define rsaCryptDebug(args...) secdebug("rsaCrypt", ## args) +#define rbprintf(args...) secdebug("rsaBuf", ## args) + +static ModuleNexus gMutex; + +RSA_CryptContext::~RSA_CryptContext() +{ + StLock _(gMutex()); + if(mAllocdRsaKey) { + assert(mRsaKey != NULL); + RSA_free(mRsaKey); + mRsaKey = NULL; + mAllocdRsaKey = false; + } +} + +/* called by CSPFullPluginSession */ +void RSA_CryptContext::init(const Context &context, bool encoding /*= true*/) +{ + StLock _(gMutex()); + + if(mInitFlag && !opStarted()) { + /* reusing - e.g. query followed by encrypt */ + return; + } + + /* optional mode to use alternate key class (e.g., decrypt with public key) */ + CSSM_KEYCLASS keyClass; + switch (context.getInt(CSSM_ATTRIBUTE_MODE)) { + case CSSM_ALGMODE_PUBLIC_KEY: + keyClass = CSSM_KEYCLASS_PUBLIC_KEY; + break; + case CSSM_ALGMODE_PRIVATE_KEY: + keyClass = CSSM_KEYCLASS_PRIVATE_KEY; + break; + case CSSM_ALGMODE_NONE: + /* default, not present in context: infer from op type */ + keyClass = encoding ? CSSM_KEYCLASS_PUBLIC_KEY : CSSM_KEYCLASS_PRIVATE_KEY; + break; + default: + CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_MODE); + } + + /* fetch key from context */ + if(mRsaKey == NULL) { + assert(!opStarted()); + CSSM_DATA label = {0, NULL}; + mRsaKey = contextToRsaKey(context, + session(), + keyClass, + encoding ? CSSM_KEYUSE_ENCRYPT : CSSM_KEYUSE_DECRYPT, + mAllocdRsaKey, + label); + if(label.Data) { + mLabel.copy(label); + mOaep = true; + free(label.Data); + } + } + else { + assert(opStarted()); + } + + unsigned cipherBlockSize = RSA_size(mRsaKey); + unsigned plainBlockSize; + + /* padding - not present means value zero, CSSM_PADDING_NONE */ + uint32 padding = context.getInt(CSSM_ATTRIBUTE_PADDING); + switch(padding) { + case CSSM_PADDING_NONE: + mPadding = RSA_NO_PADDING; + plainBlockSize = cipherBlockSize; + break; + case CSSM_PADDING_PKCS1: + mPadding = RSA_PKCS1_PADDING; + plainBlockSize = cipherBlockSize - 11; + break; + case CSSM_PADDING_APPLE_SSLv2: + rsaCryptDebug("RSA_CryptContext::init using CSSM_PADDING_APPLE_SSLv2"); + mPadding = RSA_SSLV23_PADDING; + plainBlockSize = cipherBlockSize - 11; + break; + default: + rsaCryptDebug("RSA_CryptContext::init bad padding (0x%x)", + (unsigned)padding); + CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_PADDING); + } + + /* optional blinding attribute */ + uint32 blinding = context.getInt(CSSM_ATTRIBUTE_RSA_BLINDING); + if(blinding) { + if(RSA_blinding_on(mRsaKey, NULL) <= 0) { + /* actually no legit failures */ + CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR); + } + } + else { + RSA_blinding_off(mRsaKey); + } + + /* finally, have BlockCryptor set up its stuff. */ + setup(encoding ? plainBlockSize : cipherBlockSize, // blockSizeIn + encoding ? cipherBlockSize : plainBlockSize, // blockSizeOut + false, // pkcs5Pad + false, // needsFinal + BCM_ECB, + NULL); // IV + mInitFlag = true; + +} +/* called by BlockCryptor */ +void RSA_CryptContext::encryptBlock( + const void *plainText, // length implied (one block) + size_t plainTextLen, + void *cipherText, + size_t &cipherTextLen, // in/out, throws on overflow + bool final) +{ + StLock _(gMutex()); + + int irtn; + + /* FIXME do OAEP encoding here */ + if(mRsaKey->d == NULL) { + irtn = RSA_public_encrypt(plainTextLen, + (unsigned char *)plainText, + (unsigned char *)cipherText, + mRsaKey, + mPadding); + } + else { + irtn = RSA_private_encrypt(plainTextLen, + (unsigned char *)plainText, + (unsigned char *)cipherText, + mRsaKey, + mPadding); + } + if(irtn < 0) { + throwRsaDsa("RSA_public_encrypt"); + } + else if((unsigned)irtn > cipherTextLen) { + rsaCryptDebug("RSA_public_encrypt overflow"); + CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR); + } + cipherTextLen = (size_t)irtn; +} + +void RSA_CryptContext::decryptBlock( + const void *cipherText, // length implied (one cipher block) + size_t cipherTextLen, + void *plainText, + size_t &plainTextLen, // in/out, throws on overflow + bool final) +{ + StLock _(gMutex()); + + int irtn; + + rsaCryptDebug("decryptBlock padding %d", mPadding); + /* FIXME do OAEP encoding here */ + if(mRsaKey->d == NULL) { + irtn = RSA_public_decrypt(inBlockSize(), + (unsigned char *)cipherText, + (unsigned char *)plainText, + mRsaKey, + mPadding); + } + else { + irtn = RSA_private_decrypt(inBlockSize(), + (unsigned char *)cipherText, + (unsigned char *)plainText, + mRsaKey, + mPadding); + } + if(irtn < 0) { + rsaCryptDebug("decryptBlock err"); + throwRsaDsa("RSA_private_decrypt"); + } + else if((unsigned)irtn > plainTextLen) { + rsaCryptDebug("RSA_private_decrypt overflow"); + CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR); + } + plainTextLen = (size_t)irtn; +} + +size_t RSA_CryptContext::outputSize( + bool final, // ignored + size_t inSize /*= 0*/) // output for given input size +{ + StLock _(gMutex()); + + uint32 rawBytes = inSize + inBufSize(); + uint32 rawBlocks = (rawBytes + inBlockSize() - 1) / inBlockSize(); + rbprintf("--- RSA_CryptContext::outputSize inSize 0x%lx outSize 0x%lx mInBufSize 0x%lx", + inSize, rawBlocks * outBlockSize(), inBufSize()); + return rawBlocks * outBlockSize(); +} diff --git a/libsecurity_apple_csp/lib/RSA_asymmetric.h b/libsecurity_apple_csp/lib/RSA_asymmetric.h new file mode 100644 index 00000000..eb387c26 --- /dev/null +++ b/libsecurity_apple_csp/lib/RSA_asymmetric.h @@ -0,0 +1,86 @@ +/* + * 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. + */ + + +/* + * RSA_asymmetric.h - CSPContext for RSA asymmetric encryption + */ + +#ifndef _RSA_ASYMMETRIC_H_ +#define _RSA_ASYMMETRIC_H_ + +#include +#include +#include +#include +#include +#include + +#define RSA_ASYM_PADDING_DEFAULT RSA_PKCS1_PADDING + +class RSA_CryptContext : public BlockCryptor { +public: + RSA_CryptContext(AppleCSPSession &session) : + BlockCryptor(session), + mRsaKey(NULL), + mAllocdRsaKey(false), + mInitFlag(false), + mPadding(RSA_ASYM_PADDING_DEFAULT), + mOaep(false), + mLabel(Allocator::standard()) { } + + ~RSA_CryptContext(); + + /* called by CSPFullPluginSession */ + void init(const Context &context, bool encoding = true); + + /* called by BlockCryptor */ + void encryptBlock( + const void *plainText, // length implied (one block) + size_t plainTextLen, + void *cipherText, + size_t &cipherTextLen, // in/out, throws on overflow + bool final); + void decryptBlock( + const void *cipherText, // length implied (one cipher block) + size_t cipherTextLen, + void *plainText, + size_t &plainTextLen, // in/out, throws on overflow + bool final); + + size_t outputSize( + bool final, // ignored + size_t inSize = 0); // output for given input size + +private: + RSA *mRsaKey; + bool mAllocdRsaKey; + bool mInitFlag; // allows easy reuse + int mPadding; // RSA_NO_PADDING, RSA_PKCS1_PADDING, + // RSA_SSLV23_PADDING + + /* + * optional fields for OEAP keys + * (mKeyHeader.AlgorithmId == CSSM_ALGMODE_PKCS1_EME_OAEP) + */ + bool mOaep; + CssmAutoData mLabel; + +}; /* RSA_CryptContext */ + + +#endif // _RSA_ASYMMETRIC_H_ diff --git a/libsecurity_apple_csp/lib/RawSigner.h b/libsecurity_apple_csp/lib/RawSigner.h new file mode 100644 index 00000000..b72d8d66 --- /dev/null +++ b/libsecurity_apple_csp/lib/RawSigner.h @@ -0,0 +1,95 @@ +/* + * 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. + */ + + +/* + * RawSigner.h - low-level virtual sign/verify object (no digest) + */ + +#ifndef _RAW_SIGNER_H_ +#define _RAW_SIGNER_H_ + +#include +#include +#include + +class RawSigner { +public: + RawSigner( + Allocator &alloc, + CSSM_ALGORITHMS digestAlg) : + mInitFlag(false), + mIsSigning(false), + mDigestAlg(digestAlg), + mAlloc(alloc) { } + virtual ~RawSigner() { } + + /* + * The use of our mDigestAlg variable is pretty crufty. For some algs, it's + * known and specified at construction time (e.g., CSSM_ALGID_MD5WithRSA). + * For some algs, it's set by CSPFullPluginSession via + * CSPContext::setDigestAlgorithm during raw sign/verify. + */ + void setDigestAlg(CSSM_ALGORITHMS alg) + { mDigestAlg = alg; } + + /* + * The remaining functions must be implemented by subclass. + */ + + /* reusable init */ + virtual void signerInit( + const Context &context, + bool isSigning) = 0; + + /* sign */ + virtual void sign( + const void *data, + size_t dataLen, + void *sig, + size_t *sigLen) = 0; /* IN/OUT */ + + /* verify */ + virtual void verify( + const void *data, + size_t dataLen, + const void *sig, + size_t sigLen) = 0; + + /* works for both, but only used for signing */ + virtual size_t maxSigSize() = 0; + +protected: + bool mInitFlag; // true after init + bool mOpStarted; // true after update + bool mIsSigning; + CSSM_ALGORITHMS mDigestAlg; // for raw sign/verify + Allocator &mAlloc; + + bool initFlag() { return mInitFlag; } + void setInitFlag(bool flag) { mInitFlag = flag; } + bool opStarted() { return mOpStarted; } + void setOpStarted(bool flag) { mOpStarted = flag; } + bool isSigning() { return mIsSigning; } + void setIsSigning(bool signing) + { mIsSigning = signing; } + CSSM_ALGORITHMS digestAlg() { return mDigestAlg; } + Allocator &alloc() { return mAlloc; } +}; + + +#endif /* _RAW_SIGNER_H_ */ diff --git a/libsecurity_apple_csp/lib/SHA1_MD5_Object.cpp b/libsecurity_apple_csp/lib/SHA1_MD5_Object.cpp new file mode 100644 index 00000000..6cef3342 --- /dev/null +++ b/libsecurity_apple_csp/lib/SHA1_MD5_Object.cpp @@ -0,0 +1,108 @@ +/* + * 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@ + */ + + +/* + * DigestObject.cpp - generic C++ implementations of SHA1 and MD5. + * + * Created 2/19/2001 by dmitch. + */ + +#include "SHA1_MD5_Object.h" +#include +#include + +/*** + *** MD5 + ***/ +void MD5Object::digestInit() +{ + mIsDone = false; + CC_MD5_Init(&mCtx); +} + +void MD5Object::digestUpdate( + const void *data, + size_t len) +{ + if(mIsDone) { + throw std::runtime_error("MD5 digestUpdate after final"); + } + CC_MD5_Update(&mCtx, data, len); +} + +void MD5Object::digestFinal( + void *digest) +{ + if(mIsDone) { + throw std::runtime_error("MD5 digestFinal after final"); + } + CC_MD5_Final((unsigned char *)digest, &mCtx); + mIsDone = true; +} + +/* use default memberwise init */ +DigestObject *MD5Object::digestClone() const +{ + return new MD5Object(*this); +} + +size_t MD5Object::digestSizeInBytes() const +{ + return CC_MD5_DIGEST_LENGTH; +} + +/*** + *** SHA1 + ***/ +void SHA1Object::digestInit() +{ + mIsDone = false; + CC_SHA1_Init(&mCtx); +} + +void SHA1Object::digestUpdate( + const void *data, + size_t len) +{ + CC_SHA1_Update(&mCtx, (const unsigned char *)data, len); +} + +void SHA1Object::digestFinal( + void *digest) +{ + CC_SHA1_Final((unsigned char *)digest, &mCtx); + mIsDone = true; +} + +/* use default memberwise init */ +DigestObject *SHA1Object::digestClone() const +{ + return new SHA1Object(*this); +} + +size_t SHA1Object::digestSizeInBytes() const +{ + return CC_SHA1_DIGEST_LENGTH; +} + diff --git a/libsecurity_apple_csp/lib/SHA1_MD5_Object.h b/libsecurity_apple_csp/lib/SHA1_MD5_Object.h new file mode 100644 index 00000000..d66f9f08 --- /dev/null +++ b/libsecurity_apple_csp/lib/SHA1_MD5_Object.h @@ -0,0 +1,71 @@ +/* + * 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@ + */ + + +/* + * SHA1_MD5_Object.h - SHA1, MD5 digest objects + * + * Created 2/19/2001 by dmitch. + */ + +#ifndef _SHA1_MD5_OBJECT_H_ +#define _SHA1_MD5_OBJECT_H_ + +#include +#include + +class SHA1Object : public DigestObject +{ +public: + SHA1Object() { } + virtual ~SHA1Object() { }; + virtual void digestInit(); + virtual void digestUpdate( + const void *data, + size_t len); + virtual void digestFinal( + void *digest); + virtual DigestObject *digestClone() const; + virtual size_t digestSizeInBytes() const; +private: + CC_SHA1_CTX mCtx; +}; + +class MD5Object : public DigestObject +{ +public: + MD5Object() { } + virtual ~MD5Object() { } + virtual void digestInit(); + virtual void digestUpdate( + const void *data, + size_t len); + virtual void digestFinal( + void *digest); + virtual DigestObject *digestClone() const; + virtual size_t digestSizeInBytes() const; +private: + CC_MD5_CTX mCtx; +}; + +#endif /* _SHA1_MD5_OBJECT_H_ */ diff --git a/libsecurity_apple_csp/lib/SHA2_Object.cpp b/libsecurity_apple_csp/lib/SHA2_Object.cpp new file mode 100644 index 00000000..77e7edd3 --- /dev/null +++ b/libsecurity_apple_csp/lib/SHA2_Object.cpp @@ -0,0 +1,170 @@ +/* + * 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@ + */ + + +/* + * SHA2_Object.cpp - SHA2 digest objects + * Created 8/12/2004 by dmitch. + * Created 2/19/2001 by dmitch. + */ + +#include "SHA2_Object.h" +#include +#include + +/*** + *** SHA224 + ***/ +void SHA224Object::digestInit() +{ + mIsDone = false; + CC_SHA224_Init(&mCtx); +} + +void SHA224Object::digestUpdate( + const void *data, + size_t len) +{ + CC_SHA224_Update(&mCtx, (const unsigned char *)data, len); +} + +void SHA224Object::digestFinal( + void *digest) +{ + CC_SHA224_Final((unsigned char *)digest, &mCtx); + mIsDone = true; +} + +/* use default memberwise init */ +DigestObject *SHA224Object::digestClone() const +{ + return new SHA224Object(*this); +} + +size_t SHA224Object::digestSizeInBytes() const +{ + return CC_SHA224_DIGEST_LENGTH; +} + +/*** + *** SHA256 + ***/ +void SHA256Object::digestInit() +{ + mIsDone = false; + CC_SHA256_Init(&mCtx); +} + +void SHA256Object::digestUpdate( + const void *data, + size_t len) +{ + CC_SHA256_Update(&mCtx, (const unsigned char *)data, len); +} + +void SHA256Object::digestFinal( + void *digest) +{ + CC_SHA256_Final((unsigned char *)digest, &mCtx); + mIsDone = true; +} + +/* use default memberwise init */ +DigestObject *SHA256Object::digestClone() const +{ + return new SHA256Object(*this); +} + +size_t SHA256Object::digestSizeInBytes() const +{ + return CC_SHA256_DIGEST_LENGTH; +} + +/*** + *** SHA384 + ***/ +void SHA384Object::digestInit() +{ + mIsDone = false; + CC_SHA384_Init(&mCtx); +} + +void SHA384Object::digestUpdate( + const void *data, + size_t len) +{ + CC_SHA384_Update(&mCtx, (const unsigned char *)data, len); +} + +void SHA384Object::digestFinal( + void *digest) +{ + CC_SHA384_Final((unsigned char *)digest, &mCtx); + mIsDone = true; +} + +/* use default memberwise init */ +DigestObject *SHA384Object::digestClone() const +{ + return new SHA384Object(*this); +} + +size_t SHA384Object::digestSizeInBytes() const +{ + return CC_SHA384_DIGEST_LENGTH; +} + +/*** + *** SHA512 + ***/ +void SHA512Object::digestInit() +{ + mIsDone = false; + CC_SHA512_Init(&mCtx); +} + +void SHA512Object::digestUpdate( + const void *data, + size_t len) +{ + CC_SHA512_Update(&mCtx, (const unsigned char *)data, len); +} + +void SHA512Object::digestFinal( + void *digest) +{ + CC_SHA512_Final((unsigned char *)digest, &mCtx); + mIsDone = true; +} + +/* use default memberwise init */ +DigestObject *SHA512Object::digestClone() const +{ + return new SHA512Object(*this); +} + +size_t SHA512Object::digestSizeInBytes() const +{ + return CC_SHA512_DIGEST_LENGTH; +} + diff --git a/libsecurity_apple_csp/lib/SHA2_Object.h b/libsecurity_apple_csp/lib/SHA2_Object.h new file mode 100644 index 00000000..68bba6b0 --- /dev/null +++ b/libsecurity_apple_csp/lib/SHA2_Object.h @@ -0,0 +1,105 @@ +/* + * 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@ + */ + + +/* + * SHA2_Object.h - SHA2 digest objects + * + * Created 8/12/2004 by dmitch. + */ + +#ifndef _SHA2_OBJECT_H_ +#define _SHA2_OBJECT_H_ + +#include +#include + +class SHA224Object : public DigestObject +{ +public: + SHA224Object() { } + virtual ~SHA224Object() { }; + virtual void digestInit(); + virtual void digestUpdate( + const void *data, + size_t len); + virtual void digestFinal( + void *digest); + virtual DigestObject *digestClone() const; + virtual size_t digestSizeInBytes() const; +private: + CC_SHA256_CTX mCtx; +}; + +class SHA256Object : public DigestObject +{ +public: + SHA256Object() { } + virtual ~SHA256Object() { }; + virtual void digestInit(); + virtual void digestUpdate( + const void *data, + size_t len); + virtual void digestFinal( + void *digest); + virtual DigestObject *digestClone() const; + virtual size_t digestSizeInBytes() const; +private: + CC_SHA256_CTX mCtx; +}; + +class SHA384Object : public DigestObject +{ +public: + SHA384Object() { } + virtual ~SHA384Object() { }; + virtual void digestInit(); + virtual void digestUpdate( + const void *data, + size_t len); + virtual void digestFinal( + void *digest); + virtual DigestObject *digestClone() const; + virtual size_t digestSizeInBytes() const; +private: + CC_SHA512_CTX mCtx; +}; + +class SHA512Object : public DigestObject +{ +public: + SHA512Object() { } + virtual ~SHA512Object() { }; + virtual void digestInit(); + virtual void digestUpdate( + const void *data, + size_t len); + virtual void digestFinal( + void *digest); + virtual DigestObject *digestClone() const; + virtual size_t digestSizeInBytes() const; +private: + CC_SHA512_CTX mCtx; +}; + +#endif /* _SHA2_OBJECT_H_ */ diff --git a/libsecurity_apple_csp/lib/SignatureContext.cpp b/libsecurity_apple_csp/lib/SignatureContext.cpp new file mode 100644 index 00000000..f7085c7d --- /dev/null +++ b/libsecurity_apple_csp/lib/SignatureContext.cpp @@ -0,0 +1,127 @@ +/* + * 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. + */ + + +/* + * SignatureContext.h - AppleCSPContext sublass for generic sign/verify + */ + +#include "SignatureContext.h" +#include "AppleCSPUtils.h" +#include "AppleCSPSession.h" +#include + +#include + +#define cspSigDebug(args...) secdebug("cspSig", ## args) + +SignatureContext::~SignatureContext() +{ + delete &mDigest; + delete &mSigner; + mInitFlag = false; +} + +/* both sign & verify */ +void SignatureContext::init( + const Context &context, + bool isSigning) +{ + mDigest.digestInit(); + mSigner.signerInit(context, isSigning); + mInitFlag = true; +} + +/* both sign & verify */ +void SignatureContext::update( + const CssmData &data) +{ + mDigest.digestUpdate(data.Data, data.Length); +} + +/* sign only */ +void SignatureContext::final( + CssmData &out) +{ + void *digest; + size_t digestLen; + void *sig = out.data(); + size_t sigLen = out.length(); + + /* first obtain the digest */ + digestLen = mDigest.digestSizeInBytes(); + digest = session().malloc(digestLen); + mDigest.digestFinal(digest); + + /* now sign */ + try { + mSigner.sign(digest, + digestLen, + sig, + &sigLen); + } + catch(...) { + session().free(digest); + throw; + } + session().free(digest); + if(out.length() < sigLen) { + cspSigDebug("SignatureContext: mallocd sig too small!"); + CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR); + } + out.length(sigLen); +} + +/* verify only */ +void SignatureContext::final( + const CssmData &in) +{ + void *digest; + size_t digestLen; + + /* first obtain the digest */ + digestLen = mDigest.digestSizeInBytes(); + digest = session().malloc(digestLen); + mDigest.digestFinal(digest); + + /* now verify */ + try { + mSigner.verify(digest, + digestLen, + in.Data, + in.Length); + } + catch(...) { + session().free(digest); + throw; + } + session().free(digest); +} + +size_t SignatureContext::outputSize( + bool final, + size_t inSize) +{ + return mSigner.maxSigSize(); +} + +/* for raw sign/verify - optionally called after init */ +void SignatureContext::setDigestAlgorithm( + CSSM_ALGORITHMS digestAlg) +{ + mSigner.setDigestAlg(digestAlg); +} diff --git a/libsecurity_apple_csp/lib/SignatureContext.h b/libsecurity_apple_csp/lib/SignatureContext.h new file mode 100644 index 00000000..da365a93 --- /dev/null +++ b/libsecurity_apple_csp/lib/SignatureContext.h @@ -0,0 +1,83 @@ +/* + * 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. + */ + + +/* + * SignatureContext.h - AppleCSPContext subclass for generic sign/verify + * + * This class performs all of the sign/verify operations in the CSP. The general + * scheme is that an instance of this class has references to one DigestObject + * and one RawSigner. Sign and Verify "updates" go to the DigestObject. The "final" + * operation consists of obtaining the final digest from the DigestObject and + * performing a sign or verify on that data via the RawSigner. + * + * This class knows nothing about any of the algorithms involved; all sign and + * verify operations follow this same scheme. Various modules' AlgorithmFactories + * construct one of these objects by providing the appropriate DigestObject and + * RawSigner. + * + * The seemingly special case of "raw RSA sign", in which the app calculates the + * digest separately from the sign operation, is handled via the NullDigest object. + */ + +#ifndef _SIGNATURE_CONTEXT_H_ +#define _SIGNATURE_CONTEXT_H_ + +#include +#include +#include + +class SignatureContext : public AppleCSPContext { +public: + SignatureContext( + AppleCSPSession &session, + DigestObject &digest, + RawSigner &signer) : + AppleCSPContext(session), + mDigest(digest), + mSigner(signer), + mInitFlag(false), + mOpStarted(false) { } + + ~SignatureContext(); + + /* called out from CSPFullPluginSession.... + * both sign & verify: */ + void init(const Context &context, bool isSigning); + void update(const CssmData &data); + + /* sign only */ + void final(CssmData &out); + + /* verify only */ + void final(const CssmData &in); + + size_t outputSize(bool final, size_t inSize); + + /* for raw sign/verify - optionally called after init */ + virtual void setDigestAlgorithm(CSSM_ALGORITHMS digestAlg); + + +private: + DigestObject &mDigest; + RawSigner &mSigner; + bool mInitFlag; // true after init + bool mOpStarted; // true after update +}; + + +#endif /* _SIGNATURE_CONTEXT_H_ */ diff --git a/libsecurity_apple_csp/lib/YarrowConnection.cpp b/libsecurity_apple_csp/lib/YarrowConnection.cpp new file mode 100644 index 00000000..064e1b71 --- /dev/null +++ b/libsecurity_apple_csp/lib/YarrowConnection.cpp @@ -0,0 +1,48 @@ +/* + * 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. + */ + + +/* + * YarrowConnection.cpp - single, process-wide, thread-safe Yarrow client + */ +#include "YarrowConnection.h" +#include +#include +#include + +/* instantiated by C++ runtime at library load/init time */ +class YarrowConnection : public DevRandomGenerator { +public: + YarrowConnection() : DevRandomGenerator(getuid() == 0), writable(getuid() == 0) { } + const bool writable; +}; + +/* the single global thing */ +static ModuleNexus yarrowConnection; + + +/* and the exported functions */ +void cspGetRandomBytes(void *buf, unsigned len) +{ + yarrowConnection().random(buf, len); +} + +void cspAddEntropy(const void *buf, unsigned len) +{ + if (yarrowConnection().writable) + yarrowConnection().addEntropy(buf, len); +} diff --git a/libsecurity_apple_csp/lib/YarrowConnection.h b/libsecurity_apple_csp/lib/YarrowConnection.h new file mode 100644 index 00000000..a5521df9 --- /dev/null +++ b/libsecurity_apple_csp/lib/YarrowConnection.h @@ -0,0 +1,46 @@ +/* + * 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. + */ + + +/* + * YarrowConnection.h - single, process-wide, thread-safe Yarrow client + */ + +#ifndef _YARROW_CONNECTION_H_ +#define _YARROW_CONNECTION_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Both functions a CssmError::throwMe(CSSMERR_CSP_FUNCTION_FAILED) on failure. + * + * "Give me some random data". Caller mallocs the data. + */ +extern void cspGetRandomBytes(void *buf, unsigned len); + +/* + * Add some entropy to the pool. + */ +extern void cspAddEntropy(const void *buf, unsigned len); + +#ifdef __cplusplus +} +#endif + +#endif /* _YARROW_CONNECTION_H_ */ diff --git a/libsecurity_apple_csp/lib/aesCommon.h b/libsecurity_apple_csp/lib/aesCommon.h new file mode 100644 index 00000000..6e3480f6 --- /dev/null +++ b/libsecurity_apple_csp/lib/aesCommon.h @@ -0,0 +1,42 @@ +/* + * 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. + */ + + +// +// aesCommon.h - common AES/Rijndael constants +// +#ifndef _H_AES_COMMON_ +#define _H_AES_COMMON_ + +#define MIN_AES_KEY_BITS 128 +#define MID_AES_KEY_BITS 192 +#define MAX_AES_KEY_BITS 256 + +#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) +#define DEFAULT_AES_BLOCK_BYTES MIN_AES_BLOCK_BYTES + +/* + * When true, the Gladman AES implementation is present and is used + * for all 128-bit block configurations. + */ +#define GLADMAN_AES_128_ENABLE 1 + +#endif /* _H_AES_COMMON_ */ diff --git a/libsecurity_apple_csp/lib/aescsp.cpp b/libsecurity_apple_csp/lib/aescsp.cpp new file mode 100644 index 00000000..9f068b3a --- /dev/null +++ b/libsecurity_apple_csp/lib/aescsp.cpp @@ -0,0 +1,243 @@ +/* + * 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. + */ + + +/* + * aescsp.cpp - glue between BlockCryptor and AES implementation + * Written by Doug Mitchell 10/3/2000 + */ + +#include "aescspi.h" +#include "rijndaelApi.h" +#include "rijndael-alg-ref.h" +#include "cspdebugging.h" + +#define DEFAULT_BLOCK_SIZE (MIN_AES_BLOCK_BITS / 8) + +/* + * AES symmetric key generation. + * This algorithm has key size restrictions which don't fit with the + * standard AppleSymmKeyGenContext model so we have to do some addditional + * checking. + */ +void AESKeyGenContext::generate( + const Context &context, + CssmKey &symKey, + CssmKey &dummyKey) +{ + uint32 reqKeySize = context.getInt( + CSSM_ATTRIBUTE_KEY_LENGTH, + CSSMERR_CSP_MISSING_ATTR_KEY_LENGTH); + switch(reqKeySize) { + case MIN_AES_KEY_BITS: + case MID_AES_KEY_BITS: + case MAX_AES_KEY_BITS: + break; + default: + CssmError::throwMe(CSSMERR_CSP_UNSUPPORTED_KEY_SIZE); + } + AppleSymmKeyGenContext::generateSymKey( + context, + session(), + symKey); +} + +/* + * AES encrypt/decrypt. + */ +AESContext::~AESContext() +{ + deleteKey(); + memset(mRawKey, 0, MAX_AES_KEY_BITS / 8); + mInitFlag = false; +} + +void AESContext::aesError( + int artn, + const char *errStr) +{ + CSSM_RETURN crtn; + errorLog2("AESContext: %s : %d\n", errStr, artn); + switch(artn) { + case BAD_KEY_INSTANCE: + default: + crtn = CSSMERR_CSP_INTERNAL_ERROR; + break; + case BAD_KEY_MAT: + crtn = CSSMERR_CSP_INVALID_KEY; + break; + } + CssmError::throwMe(crtn); +} + +void AESContext::deleteKey() +{ + if(mAesKey) { + memset(mAesKey, 0, sizeof(keyInstance)); + session().free(mAesKey); + mAesKey = NULL; + } +} + +/* + * Standard CSPContext init, called from CSPFullPluginSession::init(). + * Reusable, e.g., query followed by en/decrypt. Even reusable after context + * changed (i.e., new IV in Encrypted File System). + */ +void AESContext::init( + const Context &context, + bool encrypting) +{ + if(mInitFlag && !opStarted()) { + return; + } + + CSSM_SIZE keyLen; + uint8 *keyData = NULL; + unsigned lastBlockSize = mBlockSize; // may be 0 (first time thru) + bool sameKeyAndBlockSizes = false; + + /* obtain key from context */ + symmetricKeyBits(context, session(), CSSM_ALGID_AES, + encrypting ? CSSM_KEYUSE_ENCRYPT : CSSM_KEYUSE_DECRYPT, + keyData, keyLen); + + switch(keyLen) { + case MIN_AES_KEY_BITS / 8: + case MID_AES_KEY_BITS / 8: + case MAX_AES_KEY_BITS / 8: + break; + default: + CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_KEY); + } + + /* + * Validate context + * block size is optional + */ + mBlockSize = context.getInt(CSSM_ATTRIBUTE_BLOCK_SIZE); + if(mBlockSize == 0) { + mBlockSize = DEFAULT_BLOCK_SIZE; + } + + + /* + * Delete existing key if key size or block size changed + */ + if((lastBlockSize == mBlockSize) && (mRawKeySize == keyLen)) { + sameKeyAndBlockSizes = true; + } + if((mAesKey != NULL) && !sameKeyAndBlockSizes) { + deleteKey(); + } + + int opt128 = 0; +#if !GLADMAN_AES_128_ENABLE + if((mBlockSize == (MIN_AES_BLOCK_BITS/8)) && + (keyLen == (MIN_AES_KEY_BITS/8)) && + doAES128) { + opt128 = 1; + } +#endif /* !GLADMAN_AES_128_ENABLE */ + + /* create new key if needed */ + if(mAesKey == NULL) { + mAesKey = (keyInstance *)session().malloc(sizeof(keyInstance)); + } + + /* init key only if key size, block size, or key bits have changed */ + if(!sameKeyAndBlockSizes || memcmp(mRawKey, keyData, mRawKeySize)) { + int artn = makeKey((keyInstance *)mAesKey, + keyLen * 8, + mBlockSize * 8, + (word8 *)keyData, + opt128); + if(artn < 0) { + aesError(artn, "makeKey"); + } + + /* save this raw key data */ + memmove(mRawKey, keyData, mRawKeySize); + mRawKeySize = keyLen; + } + +#if !GLADMAN_AES_128_ENABLE + if(opt128) { + /* optimized path */ + mEncryptFcn = rijndaelBlockEncrypt128; + mDecryptFcn = rijndaelBlockDecrypt128; + } + else { + /* common standard path */ + mEncryptFcn = rijndaelBlockEncrypt; + mDecryptFcn = rijndaelBlockDecrypt; + } +#else + /* common standard path */ + mEncryptFcn = rijndaelBlockEncrypt; + mDecryptFcn = rijndaelBlockDecrypt; +#endif /* !GLADMAN_AES_128_ENABLE */ + + /* Finally, have BlockCryptor do its setup */ + setup(mBlockSize, context); + mInitFlag = true; +} + +/* + * Functions called by BlockCryptor + */ +void AESContext::encryptBlock( + const void *plainText, // length implied (one block) + size_t plainTextLen, + void *cipherText, + size_t &cipherTextLen, // in/out, throws on overflow + bool final) // ignored +{ + if(plainTextLen != mBlockSize) { + CssmError::throwMe(CSSMERR_CSP_INPUT_LENGTH_ERROR); + } + if(cipherTextLen < mBlockSize) { + CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR); + } + int artn = mEncryptFcn(mAesKey, + (word8 *)plainText, + (word8 *)cipherText); + if(artn < 0) { + aesError(artn, "rijndaelBlockEncrypt"); + } + cipherTextLen = mBlockSize; +} + +void AESContext::decryptBlock( + const void *cipherText, // length implied (one cipher block) + size_t cipherTextLen, + void *plainText, + size_t &plainTextLen, // in/out, throws on overflow + bool final) // ignored +{ + if(plainTextLen < mBlockSize) { + CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR); + } + int artn = mDecryptFcn(mAesKey, + (word8 *)cipherText, + (word8 *)plainText); + if(artn < 0) { + aesError(artn, "rijndaelBlockDecrypt"); + } + plainTextLen = mBlockSize; +} + diff --git a/libsecurity_apple_csp/lib/aescspi.h b/libsecurity_apple_csp/lib/aescspi.h new file mode 100644 index 00000000..368db4b1 --- /dev/null +++ b/libsecurity_apple_csp/lib/aescspi.h @@ -0,0 +1,102 @@ +/* + * 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. + */ + + +// +// aescspi.h - AES context class +// +#ifndef _H_AESCSPI +#define _H_AESCSPI + +#include +#include "AppleCSP.h" +#include "AppleCSPContext.h" +#include "AppleCSPSession.h" +#include "BlockCryptor.h" +#include "rijndaelApi.h" + +/* Symmetric encryption context */ +class AESContext : public BlockCryptor { +public: + AESContext(AppleCSPSession &session) : + BlockCryptor(session), + mAesKey(NULL), + mBlockSize(0), + mInitFlag(false), + mRawKeySize(0) { } + ~AESContext(); + + // called by CSPFullPluginSession + void init(const Context &context, bool encoding = true); + + // As an optimization, we allow reuse of a modified context. The main thing + // we avoid is a redundant key scheduling. We save the current raw keys bits + // in mRawKey and compare on re-init. + bool changed(const Context &context) { return true; } + + // called by BlockCryptor + void encryptBlock( + const void *plainText, // length implied (one block) + size_t plainTextLen, + void *cipherText, + size_t &cipherTextLen, // in/out, throws on overflow + bool final); + void decryptBlock( + const void *cipherText, // length implied (one cipher block) + size_t cipherTextLen, + void *plainText, + size_t &plainTextLen, // in/out, throws on overflow + bool final); + +private: + void aesError( + int artn, + const char *errStr); + void deleteKey(); + + keyInstance *mAesKey; // keyInstance or keyInstance128 + unsigned mBlockSize; // in BYTES + bool mInitFlag; // for easy reuse + aesCryptFcn mEncryptFcn; + aesCryptFcn mDecryptFcn; + + /* raw key bits saved here and checked on re-init to avoid extra key schedule */ + uint8 mRawKey[MAX_AES_KEY_BITS / 8]; + uint32 mRawKeySize; +}; /* AESContext */ + +// symmetric key generation context +class AESKeyGenContext : public AppleCSPContext, private AppleSymmKeyGenContext { +public: + AESKeyGenContext( + AppleCSPSession &session) : + AppleCSPContext(session), + AppleSymmKeyGenContext( + MIN_AES_KEY_BITS, + MAX_AES_KEY_BITS, + true) { } + + void init(const Context &context, bool encoding = true) { } + + void generate( + const Context &context, + CssmKey &symKey, + CssmKey &dummyKey); + +}; + +#endif //_H_AESCSPI diff --git a/libsecurity_apple_csp/lib/algmaker.cpp b/libsecurity_apple_csp/lib/algmaker.cpp new file mode 100644 index 00000000..5b7e558b --- /dev/null +++ b/libsecurity_apple_csp/lib/algmaker.cpp @@ -0,0 +1,333 @@ +/* + * 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. + */ + +#ifdef BSAFE_CSP_ENABLE + + +// +// algmaker - algorithm factory for BSafe 4 +// +#include "bsafecspi.h" +#include "bsafecsp.h" +#include "AppleCSPSession.h" + +// +// BSafe's Chooser table. +// These are references to all *BSafe algorithms* we use (and thus must link in) +// +const B_ALGORITHM_METHOD * const BSafe::bsChooser[] = { + // 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 +}; + + +// +// Makers +// +template +class Maker0 : public BSafe::MakerBase { +public: + Ctx *make(AppleCSPSession &session, const Context &context) const + { return new Ctx(session, context); } +}; + +template +class Maker1 : public BSafe::MakerBase { + Arg arg; +public: + Maker1(Arg a) : arg(a) { } + Ctx *make(AppleCSPSession &session, const Context &context) const + { return new Ctx(session, context, arg); } +}; + +template +class Maker2 : public BSafe::MakerBase { + Arg1 arg1; Arg2 arg2; +public: + Maker2(Arg1 a1, Arg2 a2) : arg1(a1), arg2(a2) { } + Ctx *make(AppleCSPSession &session, const Context &context) const + { return new Ctx(session, context, arg1, arg2); } +}; + +template +class Maker3 : public BSafe::MakerBase { + Arg1 arg1; Arg2 arg2; Arg3 arg3; +public: + Maker3(Arg1 a1, Arg2 a2, Arg3 a3) : + arg1(a1), arg2(a2), arg3(a3) { } + Ctx *make(AppleCSPSession &session, const Context &context) const + { return new Ctx(session, context, arg1, arg2, arg3); } +}; + + +bug_const BSafe::MakerTable BSafe::algorithms[] = { + // signing algorithms + // constructor args: BSafe algorithm, signature size + { + CSSM_ALGID_SHA1WithDSA, + CSSM_ALGCLASS_SIGNATURE, + new Maker2 + (AI_DSAWithSHA1, 48) // max size of 48 bytes + }, + { + CSSM_ALGID_SHA1WithRSA, + CSSM_ALGCLASS_SIGNATURE, + new Maker2 + (AI_SHA1WithRSAEncryption, 0) // size = RSA key size + }, + + { + CSSM_ALGID_MD5WithRSA, + CSSM_ALGCLASS_SIGNATURE, + new Maker2 + (AI_MD5WithRSAEncryption, 0) // size = RSA key size + }, + + { + CSSM_ALGID_MD2WithRSA, + CSSM_ALGCLASS_SIGNATURE, + new Maker2 + (AI_MD2WithRSAEncryption, 0) // size = RSA key size + }, + + // MAC algorithms + // constructor args: BSafe algorithm, signature size + { + CSSM_ALGID_SHA1HMAC, + CSSM_ALGCLASS_MAC, + new Maker2 + (AI_SHA1, 20) + }, + + // symmetric key generation + // constructor args: min/max key size in bits, mustBeByteSized + { + CSSM_ALGID_RC2, + CSSM_ALGCLASS_KEYGEN, + new Maker3 + (1*8, 128*8, true) + }, + { + CSSM_ALGID_RC4, + CSSM_ALGCLASS_KEYGEN, + new Maker3 + (1*8, 256*8, true) + }, + { + CSSM_ALGID_RC5, + CSSM_ALGCLASS_KEYGEN, + new Maker3 + (1*8, 255*8, true) + }, + { + CSSM_ALGID_DES, + CSSM_ALGCLASS_KEYGEN, + new Maker3 + (64, 64, true) + }, + { + CSSM_ALGID_DESX, + CSSM_ALGCLASS_KEYGEN, + new Maker3 + (192, 192, true) + }, + { + CSSM_ALGID_3DES_3KEY, + CSSM_ALGCLASS_KEYGEN, + new Maker3 + (192, 192, true) + }, + { + CSSM_ALGID_SHA1HMAC, + CSSM_ALGCLASS_KEYGEN, + new Maker3 + (160, 2048, true) + }, + + // symmetric encryption algorithms + // constructor arg: block size (1 ==> stream cipher) + { + CSSM_ALGID_DES, + CSSM_ALGCLASS_SYMMETRIC, + new Maker1(8) + }, + { + CSSM_ALGID_DESX, + CSSM_ALGCLASS_SYMMETRIC, + new Maker1(8) + }, + { + CSSM_ALGID_3DES_3KEY_EDE, + CSSM_ALGCLASS_SYMMETRIC, + new Maker1(8) + }, + { + CSSM_ALGID_RC2, + CSSM_ALGCLASS_SYMMETRIC, + new Maker1(8) + }, + { + CSSM_ALGID_RC4, + CSSM_ALGCLASS_SYMMETRIC, + new Maker1(1) + }, + { + CSSM_ALGID_RC5, + CSSM_ALGCLASS_SYMMETRIC, + new Maker1(8) + }, + + // asymmetric encryption algorithms + { + CSSM_ALGID_RSA, + CSSM_ALGCLASS_ASYMMETRIC, + new Maker0() + }, + { + CSSM_ALGID_DSA, + CSSM_ALGCLASS_ASYMMETRIC, + new Maker0() + }, + + // key pair generate algorithms + { + CSSM_ALGID_RSA, + CSSM_ALGCLASS_KEYGEN, + new Maker0() + }, + { + CSSM_ALGID_DSA, + CSSM_ALGCLASS_KEYGEN, + new Maker0() + }, + + // pseudo-random number generators + { + CSSM_ALGID_MD5Random, + CSSM_ALGCLASS_RANDOMGEN, + new Maker1(AI_MD5Random) + }, + { + CSSM_ALGID_SHARandom, + CSSM_ALGCLASS_RANDOMGEN, + new Maker1(AI_SHA1Random) + }, +}; + +const unsigned int BSafe::algorithmCount = sizeof(algorithms) / sizeof(algorithms[0]); + + +// +// BSafeFactory hookup +// +void BSafeFactory::setNormAllocator(Allocator *alloc) +{ + BSafe::setNormAllocator(alloc); +} +void BSafeFactory::setPrivAllocator(Allocator *alloc) +{ + BSafe::setPrivAllocator(alloc); +} + +bool BSafeFactory::setup( + AppleCSPSession &session, + CSPFullPluginSession::CSPContext * &cspCtx, + const Context &context) +{ + return BSafe::setup(session, cspCtx, context); +} + + +// +// Algorithm setup +// +bool BSafe::setup( + AppleCSPSession &session, + CSPFullPluginSession::CSPContext * &cspCtx, + const Context &context) +{ + for (const BSafe::MakerTable *alg = algorithms; + alg < algorithms + algorithmCount; + alg++) { + if ((alg->algorithmId == context.algorithm()) && + (alg->algClass == context.type())) { + if(cspCtx != NULL) { + /* we allow reuse */ + return true; + } + // make new context + cspCtx = alg->maker->make(session, context); + return true; + } + } + /* not ours */ + return false; +} +#endif /* BSAFE_CSP_ENABLE */ diff --git a/libsecurity_apple_csp/lib/ascContext.cpp b/libsecurity_apple_csp/lib/ascContext.cpp new file mode 100644 index 00000000..f0a45b17 --- /dev/null +++ b/libsecurity_apple_csp/lib/ascContext.cpp @@ -0,0 +1,373 @@ +/* + * ascContext.cpp - glue between BlockCrytpor and ComCryption (a.k.a. Apple + * Secure Compression). + * Written by Doug Mitchell 4/4/2001 + */ + +#ifdef ASC_CSP_ENABLE + +#include "ascContext.h" +#include "ascFactory.h" +#include +#include +#include + +#define abprintf(args...) secdebug("ascBuf", ## args) /* buffer sizes */ +#define aioprintf(args...) secdebug("ascIo", ## args) /* all I/O */ + +static Allocator *ascAllocator; + +/* + * Comcryption-style memory allocator callbacks + */ +static void *ccMalloc(unsigned size) +{ + return ascAllocator->malloc(size); +} +static void ccFree(void *data) +{ + ascAllocator->free(data); +} + +/* Given a ComCryption error, throw appropriate CssmError */ +static void throwComcrypt( + comcryptReturn crtn, + const char *op) /* optional */ +{ + CSSM_RETURN cerr = CSSM_OK; + const char *errStr = "Bad Error String"; + + switch(crtn) { + case CCR_SUCCESS: + errStr = "CCR_SUCCESS"; + break; + case CCR_OUTBUFFER_TOO_SMALL: + errStr = "CCR_OUTBUFFER_TOO_SMALL"; + cerr = CSSMERR_CSP_OUTPUT_LENGTH_ERROR; + break; + case CCR_MEMORY_ERROR: + errStr = "CCR_MEMORY_ERROR"; + cerr = CSSMERR_CSP_MEMORY_ERROR; + break; + case CCR_WRONG_VERSION: + errStr = "CCR_WRONG_VERSION"; + cerr = CSSMERR_CSP_INVALID_DATA; + break; + case CCR_BAD_CIPHERTEXT: + errStr = "CCR_BAD_CIPHERTEXT"; + cerr = CSSMERR_CSP_INVALID_DATA; + break; + case CCR_INTERNAL: + default: + errStr = "CCR_INTERNAL"; + cerr = CSSMERR_CSP_INTERNAL_ERROR; + break; + } + if(op) { + Security::Syslog::error("Apple CSP %s: %s", op, errStr); + } + if(cerr) { + CssmError::throwMe(cerr); + } +} + +/* + * Algorithm factory. + */ + +AscAlgFactory::AscAlgFactory( + Allocator *normAlloc, + Allocator *privAlloc) +{ + /* once-per-address-space init */ + ascAllocator = privAlloc; + comMallocRegister(ccMalloc, ccFree); +} + +bool AscAlgFactory::setup( + AppleCSPSession &session, + CSPFullPluginSession::CSPContext * &cspCtx, + const Context &context) +{ + if(context.algorithm() != CSSM_ALGID_ASC) { + return false; + } + if(cspCtx != NULL) { + /* reusing one of ours; OK */ + return true; + } + switch(context.type()) { + case CSSM_ALGCLASS_KEYGEN: + cspCtx = new AppleSymmKeyGenerator(session, + 8, + COMCRYPT_MAX_KEYLENGTH * 8, + true); // must be byte size + return true; + case CSSM_ALGCLASS_SYMMETRIC: + cspCtx = new ASCContext(session); + return true; + default: + break; + } + /* not ours */ + return false; +} + +ASCContext::~ASCContext() +{ + if(mCcObj != NULL) { + comcryptObjFree(mCcObj); + } +} + +/* + * Standard CSPContext init, called from CSPFullPluginSession::init(). + * Reusable, e.g., query followed by en/decrypt. + */ +void ASCContext::init( + const Context &context, + bool encrypting) +{ + CSSM_SIZE keyLen; + uint8 *keyData = NULL; + comcryptReturn crtn; + + /* obtain key from context */ + symmetricKeyBits(context, session(), CSSM_ALGID_ASC, + encrypting ? CSSM_KEYUSE_ENCRYPT : CSSM_KEYUSE_DECRYPT, + keyData, keyLen); + if((keyLen < 1) || (keyLen > COMCRYPT_MAX_KEYLENGTH)) { + CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_KEY); + } + mDecryptBufValid = false; + + /* optional optimization attribute */ + comcryptOptimize optimize = CCO_DEFAULT; + uint32 opt = context.getInt(CSSM_ATTRIBUTE_ASC_OPTIMIZATION); + switch(opt) { + case CSSM_ASC_OPTIMIZE_DEFAULT: + optimize = CCO_DEFAULT; + break; + case CSSM_ASC_OPTIMIZE_SIZE: + optimize = CCO_SIZE; + break; + case CSSM_ASC_OPTIMIZE_SECURITY: + optimize = CCO_SECURITY; + break; + case CSSM_ASC_OPTIMIZE_TIME: + optimize = CCO_TIME; + break; + case CSSM_ASC_OPTIMIZE_TIME_SIZE: + optimize = CCO_TIME_SIZE; + break; + case CSSM_ASC_OPTIMIZE_ASCII: + optimize = CCO_ASCII; + break; + default: + CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_ALG_PARAMS); + } + + /* All other context attributes ignored */ + /* init the low-level state */ + if(mCcObj == NULL) { + /* note we allow for context reuse */ + mCcObj = comcryptAlloc(); + if(mCcObj == NULL) { + CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR); + } + } + + crtn = comcryptInit(mCcObj, keyData, keyLen, optimize); + if(crtn) { + throwComcrypt(crtn, "comcryptInit"); + } +} + +/* + * All of these functions are called by CSPFullPluginSession. + */ +void ASCContext::update( + void *inp, + size_t &inSize, // in/out + void *outp, + size_t &outSize) // in/out +{ + comcryptReturn crtn; + unsigned outLen; + unsigned char *inText = (unsigned char *)inp; + unsigned char *outText = (unsigned char *)outp; + + if(encoding()) { + outLen = outSize; + crtn = comcryptData(mCcObj, + inText, + inSize, + outText, + &outLen, + CCE_MORE_TO_COME); // not used on encrypt + if(crtn) { + throwComcrypt(crtn, "comcryptData"); + } + } + else { + /* + * Deal with 1-byte buffer hack. First decrypt the existing buffer... + */ + if(inSize == 0) { + CssmError::throwMe(CSSMERR_CSP_INPUT_LENGTH_ERROR); + } + unsigned thisOutLen; + unsigned partialOutLen = 0; + if(mDecryptBufValid) { + thisOutLen = outSize; + crtn = deComcryptData(mCcObj, + &mDecryptBuf, + 1, + outText, + &thisOutLen, + CCE_MORE_TO_COME); + mDecryptBufValid = false; + if(crtn) { + throwComcrypt(crtn, "deComcryptData (1)"); + } + partialOutLen = thisOutLen; + outText += thisOutLen; + } + + /* + * Now decrypt remaining, less one byte (which is stored in the + * buffer). + */ + thisOutLen = outSize - partialOutLen; + crtn = deComcryptData(mCcObj, + inText, + inSize - 1, + outText, + &thisOutLen, + CCE_MORE_TO_COME); + if(crtn) { + throwComcrypt(crtn, "deComcryptData (2)"); + } + outLen = partialOutLen + thisOutLen; + mDecryptBuf = inText[inSize - 1]; + mDecryptBufValid = true; + } + outSize = outLen; + aioprintf("=== ASC::update encrypt %d inSize %ld outSize %ld", + encoding() ? 1 : 0, inSize, outSize); +} + +void ASCContext::final( + CssmData &out) +{ + if(encoding()) { + out.length(0); + } + else { + /* decrypt buffer hack */ + if(!mDecryptBufValid) { + CssmError::throwMe(CSSMERR_CSP_INPUT_LENGTH_ERROR); + } + comcryptReturn crtn; + unsigned outLen = out.Length; + crtn = deComcryptData(mCcObj, + &mDecryptBuf, + 1, + (unsigned char *)out.Data, + &outLen, + CCE_END_OF_STREAM); + mDecryptBufValid = false; + if(crtn) { + throwComcrypt(crtn, "deComcryptData (3)"); + } + out.length(outLen); + } + aioprintf("=== ASC::final encrypt %d outSize %ld", + encoding() ? 1 : 0, out.Length); +} + +size_t ASCContext::inputSize( + size_t outSize) // input for given output size +{ + size_t rtn = comcryptMaxInBufSize(mCcObj, + outSize, + encoding() ? CCOP_COMCRYPT : CCOP_DECOMCRYPT); + abprintf("--- ASCContext::inputSize inSize %ld outSize %ld", + rtn, outSize); + return rtn; +} + +/* + * ComCryption's buffer size calculation really does not lend itself to the + * requirements here. For example, there is no guarantee that + * inputSize(outputSize(x)) == x. We're just going to fudge it and make + * apps (or CSPFullPluginSession) alloc plenty more than they need. + */ +#define ASC_OUTSIZE_FUDGE 1 +#define ASC_OUTSIZE_FUDGE_FACTOR 1.2 + +size_t ASCContext::outputSize( + bool final, + size_t inSize) // output for given input size +{ + unsigned effectiveInSize = inSize; + size_t rtn; + if(encoding()) { + rtn = comcryptMaxOutBufSize(mCcObj, + effectiveInSize, + CCOP_COMCRYPT, + final); + #if ASC_OUTSIZE_FUDGE + float newOutSize = rtn; + newOutSize *= ASC_OUTSIZE_FUDGE_FACTOR; + rtn = static_cast(newOutSize); + #endif /* ASC_OUTSIZE_FUDGE */ + } + else { + if(final) { + if(mDecryptBufValid) { + effectiveInSize++; + } + } + else if(inSize && !mDecryptBufValid) { + /* not final and nothing buffered yet - lop off one */ + effectiveInSize--; + } + rtn = comcryptMaxOutBufSize(mCcObj, + effectiveInSize, + CCOP_DECOMCRYPT, + final); + } + abprintf("--- ASCContext::outputSize inSize %ld outSize %ld final %d ", + inSize, rtn, final); + return rtn; +} + +void ASCContext::minimumProgress( + size_t &in, + size_t &out) // minimum progress chunks +{ + if(encoding()) { + in = 1; + out = comcryptMaxOutBufSize(mCcObj, + 1, + CCOP_COMCRYPT, + 0); + } + else { + if(mDecryptBufValid) { + /* use "everything" */ + in = 1; + } + else { + in = 0; + } + out = comcryptMaxOutBufSize(mCcObj, + in, + CCOP_DECOMCRYPT, + 0); + } + abprintf("--- ASCContext::minProgres in %ld out %ld", in, out); +} + +#endif /* ASC_CSP_ENABLE */ diff --git a/libsecurity_apple_csp/lib/ascContext.h b/libsecurity_apple_csp/lib/ascContext.h new file mode 100644 index 00000000..bea6d24a --- /dev/null +++ b/libsecurity_apple_csp/lib/ascContext.h @@ -0,0 +1,61 @@ +/* + * 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 +#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 new file mode 100644 index 00000000..afe7d148 --- /dev/null +++ b/libsecurity_apple_csp/lib/ascFactory.h @@ -0,0 +1,34 @@ +// +// 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/bfContext.cpp b/libsecurity_apple_csp/lib/bfContext.cpp new file mode 100644 index 00000000..3180e407 --- /dev/null +++ b/libsecurity_apple_csp/lib/bfContext.cpp @@ -0,0 +1,120 @@ +/* + * 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. + */ + + +/* + * bfContext.cpp - glue between BlockCrytpor and ssleay Blowfish + * implementation + * Written by Doug Mitchell 4/23/2003 + */ + +#include "bfContext.h" + +BlowfishContext::~BlowfishContext() +{ + deleteKey(); +} + +void BlowfishContext::deleteKey() +{ + memset(&mBfKey, 0, sizeof(mBfKey)); + mInitFlag = false; +} + +/* + * Standard CSPContext init, called from CSPFullPluginSession::init(). + * Reusable, e.g., query followed by en/decrypt. + */ +void BlowfishContext::init( + const Context &context, + bool encrypting) +{ + if(mInitFlag && !opStarted()) { + return; + } + + CSSM_SIZE keyLen; + uint8 *keyData = NULL; + bool sameKeySize = false; + + /* obtain key from context */ + symmetricKeyBits(context, session(), CSSM_ALGID_BLOWFISH, + encrypting ? CSSM_KEYUSE_ENCRYPT : CSSM_KEYUSE_DECRYPT, + keyData, keyLen); + if((keyLen < BF_MIN_KEY_SIZE_BYTES) || (keyLen > BF_MAX_KEY_SIZE_BYTES)) { + CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_KEY); + } + + /* + * Delete existing key if key size changed + */ + if(mRawKeySize == keyLen) { + sameKeySize = true; + } + else { + deleteKey(); + } + + /* init key only if key size or key bits have changed */ + if(!sameKeySize || memcmp(mRawKey, keyData, mRawKeySize)) { + BF_set_key(&mBfKey, keyLen, keyData); + + /* save this raw key data */ + memmove(mRawKey, keyData, keyLen); + mRawKeySize = keyLen; + } + + /* Finally, have BlockCryptor do its setup */ + setup(BF_BLOCK, context); + mInitFlag = true; +} + +/* + * Functions called by BlockCryptor + */ +void BlowfishContext::encryptBlock( + const void *plainText, // length implied (one block) + size_t plainTextLen, + void *cipherText, + size_t &cipherTextLen, // in/out, throws on overflow + bool final) // ignored +{ + if(plainTextLen != BF_BLOCK) { + CssmError::throwMe(CSSMERR_CSP_INPUT_LENGTH_ERROR); + } + if(cipherTextLen < BF_BLOCK) { + CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR); + } + BF_ecb_encrypt((const unsigned char *)plainText, (unsigned char *)cipherText, + &mBfKey, BF_ENCRYPT); + cipherTextLen = BF_BLOCK; +} + +void BlowfishContext::decryptBlock( + const void *cipherText, // length implied (one block) + size_t cipherTextLen, + void *plainText, + size_t &plainTextLen, // in/out, throws on overflow + bool final) // ignored +{ + if(plainTextLen < BF_BLOCK) { + CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR); + } + BF_ecb_encrypt((const unsigned char *)cipherText, (unsigned char *)plainText, + &mBfKey, BF_DECRYPT); + plainTextLen = BF_BLOCK; +} diff --git a/libsecurity_apple_csp/lib/bfContext.h b/libsecurity_apple_csp/lib/bfContext.h new file mode 100644 index 00000000..d148760d --- /dev/null +++ b/libsecurity_apple_csp/lib/bfContext.h @@ -0,0 +1,81 @@ +/* + * 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. + */ + + +/* + * bfContext.h - glue between BlockCrytpor and ssleay Blowfish + * implementation + * Written by Doug Mitchell 4/23/2003 + */ + +#ifndef _BF_CONTEXT_H_ +#define _BF_CONTEXT_H_ + +#include "AppleCSPContext.h" +#include "BlockCryptor.h" +#include +#include + +class BlowfishContext : public BlockCryptor { +public: + BlowfishContext(AppleCSPSession &session) : + BlockCryptor(session), + mInitFlag(false), + mRawKeySize(0) { } + ~BlowfishContext(); + + // called by CSPFullPluginSession + void init(const Context &context, bool encoding = true); + + // As an optimization, we allow reuse of a modified context. + // The main thing we avoid is a redundant key scheduling. We + // save the current raw keys bits in mRawKey and compare on + // re-init. + bool changed(const Context &context) { return true; } + + // called by BlockCryptor + void encryptBlock( + const void *plainText, // length implied (one block) + size_t plainTextLen, + void *cipherText, + size_t &cipherTextLen, // in/out, throws on overflow + bool final); + void decryptBlock( + const void *cipherText, // length implied (one cipher block) + size_t cipherTextLen, + void *plainText, + size_t &plainTextLen, // in/out, throws on overflow + bool final); + +private: + void deleteKey(); + + /* scheduled key */ + BF_KEY mBfKey; + bool mInitFlag; // for easy reuse + + /* + * Raw key bits saved here and checked on re-init to avoid + * extra key schedule + */ + uint8 mRawKey[BF_MAX_KEY_SIZE_BYTES]; + uint32 mRawKeySize; + + +}; /* BlowfishContext */ + +#endif //_BF_CONTEXT_H_ diff --git a/libsecurity_apple_csp/lib/boxes-ref.c b/libsecurity_apple_csp/lib/boxes-ref.c new file mode 100644 index 00000000..ddc63573 --- /dev/null +++ b/libsecurity_apple_csp/lib/boxes-ref.c @@ -0,0 +1,228 @@ +/* + * 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 "boxes-ref.h" + +#if !AES_MUL_BY_LOOKUP +const unsigned char 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, +}; + +const unsigned char 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, +}; +#endif /* AES_MUL_BY_LOOKUP */ + +const unsigned char 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, +}; + +const unsigned char 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, +}; + +const unsigned char iG[4][4] = { +{ 0x0e, 0x09, 0x0d, 0x0b }, +{ 0x0b, 0x0e, 0x09, 0x0d }, +{ 0x0d, 0x0b, 0x0e, 0x09 }, +{ 0x09, 0x0d, 0x0b, 0x0e } +}; + +const unsigned long 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, }; + +#if AES_MUL_BY_LOOKUP + +/* + * Lookup tables for mul(). Only 6 multiplicands are used when calling this + * function so we just have a table for each one. + */ +const word8 mulBy0x02[256] = { + 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, + 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, + 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, + 96, 98, 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124, 126, + 128, 130, 132, 134, 136, 138, 140, 142, 144, 146, 148, 150, 152, 154, 156, 158, + 160, 162, 164, 166, 168, 170, 172, 174, 176, 178, 180, 182, 184, 186, 188, 190, + 192, 194, 196, 198, 200, 202, 204, 206, 208, 210, 212, 214, 216, 218, 220, 222, + 224, 226, 228, 230, 232, 234, 236, 238, 240, 242, 244, 246, 248, 250, 252, 254, + 27, 25, 31, 29, 19, 17, 23, 21, 11, 9, 15, 13, 3, 1, 7, 5, + 59, 57, 63, 61, 51, 49, 55, 53, 43, 41, 47, 45, 35, 33, 39, 37, + 91, 89, 95, 93, 83, 81, 87, 85, 75, 73, 79, 77, 67, 65, 71, 69, + 123, 121, 127, 125, 115, 113, 119, 117, 107, 105, 111, 109, 99, 97, 103, 101, + 155, 153, 159, 157, 147, 145, 151, 149, 139, 137, 143, 141, 131, 129, 135, 133, + 187, 185, 191, 189, 179, 177, 183, 181, 171, 169, 175, 173, 163, 161, 167, 165, + 219, 217, 223, 221, 211, 209, 215, 213, 203, 201, 207, 205, 195, 193, 199, 197, + 251, 249, 255, 253, 243, 241, 247, 245, 235, 233, 239, 237, 227, 225, 231, 229, + }; + +const word8 mulBy0x03[256] = { + 0, 3, 6, 5, 12, 15, 10, 9, 24, 27, 30, 29, 20, 23, 18, 17, + 48, 51, 54, 53, 60, 63, 58, 57, 40, 43, 46, 45, 36, 39, 34, 33, + 96, 99, 102, 101, 108, 111, 106, 105, 120, 123, 126, 125, 116, 119, 114, 113, + 80, 83, 86, 85, 92, 95, 90, 89, 72, 75, 78, 77, 68, 71, 66, 65, + 192, 195, 198, 197, 204, 207, 202, 201, 216, 219, 222, 221, 212, 215, 210, 209, + 240, 243, 246, 245, 252, 255, 250, 249, 232, 235, 238, 237, 228, 231, 226, 225, + 160, 163, 166, 165, 172, 175, 170, 169, 184, 187, 190, 189, 180, 183, 178, 177, + 144, 147, 150, 149, 156, 159, 154, 153, 136, 139, 142, 141, 132, 135, 130, 129, + 155, 152, 157, 158, 151, 148, 145, 146, 131, 128, 133, 134, 143, 140, 137, 138, + 171, 168, 173, 174, 167, 164, 161, 162, 179, 176, 181, 182, 191, 188, 185, 186, + 251, 248, 253, 254, 247, 244, 241, 242, 227, 224, 229, 230, 239, 236, 233, 234, + 203, 200, 205, 206, 199, 196, 193, 194, 211, 208, 213, 214, 223, 220, 217, 218, + 91, 88, 93, 94, 87, 84, 81, 82, 67, 64, 69, 70, 79, 76, 73, 74, + 107, 104, 109, 110, 103, 100, 97, 98, 115, 112, 117, 118, 127, 124, 121, 122, + 59, 56, 61, 62, 55, 52, 49, 50, 35, 32, 37, 38, 47, 44, 41, 42, + 11, 8, 13, 14, 7, 4, 1, 2, 19, 16, 21, 22, 31, 28, 25, 26, + }; + +const word8 mulBy0x0e[256] = { + 0, 14, 28, 18, 56, 54, 36, 42, 112, 126, 108, 98, 72, 70, 84, 90, + 224, 238, 252, 242, 216, 214, 196, 202, 144, 158, 140, 130, 168, 166, 180, 186, + 219, 213, 199, 201, 227, 237, 255, 241, 171, 165, 183, 185, 147, 157, 143, 129, + 59, 53, 39, 41, 3, 13, 31, 17, 75, 69, 87, 89, 115, 125, 111, 97, + 173, 163, 177, 191, 149, 155, 137, 135, 221, 211, 193, 207, 229, 235, 249, 247, + 77, 67, 81, 95, 117, 123, 105, 103, 61, 51, 33, 47, 5, 11, 25, 23, + 118, 120, 106, 100, 78, 64, 82, 92, 6, 8, 26, 20, 62, 48, 34, 44, + 150, 152, 138, 132, 174, 160, 178, 188, 230, 232, 250, 244, 222, 208, 194, 204, + 65, 79, 93, 83, 121, 119, 101, 107, 49, 63, 45, 35, 9, 7, 21, 27, + 161, 175, 189, 179, 153, 151, 133, 139, 209, 223, 205, 195, 233, 231, 245, 251, + 154, 148, 134, 136, 162, 172, 190, 176, 234, 228, 246, 248, 210, 220, 206, 192, + 122, 116, 102, 104, 66, 76, 94, 80, 10, 4, 22, 24, 50, 60, 46, 32, + 236, 226, 240, 254, 212, 218, 200, 198, 156, 146, 128, 142, 164, 170, 184, 182, + 12, 2, 16, 30, 52, 58, 40, 38, 124, 114, 96, 110, 68, 74, 88, 86, + 55, 57, 43, 37, 15, 1, 19, 29, 71, 73, 91, 85, 127, 113, 99, 109, + 215, 217, 203, 197, 239, 225, 243, 253, 167, 169, 187, 181, 159, 145, 131, 141, + }; + +const word8 mulBy0x0b[256] = { + 0, 11, 22, 29, 44, 39, 58, 49, 88, 83, 78, 69, 116, 127, 98, 105, + 176, 187, 166, 173, 156, 151, 138, 129, 232, 227, 254, 245, 196, 207, 210, 217, + 123, 112, 109, 102, 87, 92, 65, 74, 35, 40, 53, 62, 15, 4, 25, 18, + 203, 192, 221, 214, 231, 236, 241, 250, 147, 152, 133, 142, 191, 180, 169, 162, + 246, 253, 224, 235, 218, 209, 204, 199, 174, 165, 184, 179, 130, 137, 148, 159, + 70, 77, 80, 91, 106, 97, 124, 119, 30, 21, 8, 3, 50, 57, 36, 47, + 141, 134, 155, 144, 161, 170, 183, 188, 213, 222, 195, 200, 249, 242, 239, 228, + 61, 54, 43, 32, 17, 26, 7, 12, 101, 110, 115, 120, 73, 66, 95, 84, + 247, 252, 225, 234, 219, 208, 205, 198, 175, 164, 185, 178, 131, 136, 149, 158, + 71, 76, 81, 90, 107, 96, 125, 118, 31, 20, 9, 2, 51, 56, 37, 46, + 140, 135, 154, 145, 160, 171, 182, 189, 212, 223, 194, 201, 248, 243, 238, 229, + 60, 55, 42, 33, 16, 27, 6, 13, 100, 111, 114, 121, 72, 67, 94, 85, + 1, 10, 23, 28, 45, 38, 59, 48, 89, 82, 79, 68, 117, 126, 99, 104, + 177, 186, 167, 172, 157, 150, 139, 128, 233, 226, 255, 244, 197, 206, 211, 216, + 122, 113, 108, 103, 86, 93, 64, 75, 34, 41, 52, 63, 14, 5, 24, 19, + 202, 193, 220, 215, 230, 237, 240, 251, 146, 153, 132, 143, 190, 181, 168, 163, + }; + +const word8 mulBy0x0d[256] = { + 0, 13, 26, 23, 52, 57, 46, 35, 104, 101, 114, 127, 92, 81, 70, 75, + 208, 221, 202, 199, 228, 233, 254, 243, 184, 181, 162, 175, 140, 129, 150, 155, + 187, 182, 161, 172, 143, 130, 149, 152, 211, 222, 201, 196, 231, 234, 253, 240, + 107, 102, 113, 124, 95, 82, 69, 72, 3, 14, 25, 20, 55, 58, 45, 32, + 109, 96, 119, 122, 89, 84, 67, 78, 5, 8, 31, 18, 49, 60, 43, 38, + 189, 176, 167, 170, 137, 132, 147, 158, 213, 216, 207, 194, 225, 236, 251, 246, + 214, 219, 204, 193, 226, 239, 248, 245, 190, 179, 164, 169, 138, 135, 144, 157, + 6, 11, 28, 17, 50, 63, 40, 37, 110, 99, 116, 121, 90, 87, 64, 77, + 218, 215, 192, 205, 238, 227, 244, 249, 178, 191, 168, 165, 134, 139, 156, 145, + 10, 7, 16, 29, 62, 51, 36, 41, 98, 111, 120, 117, 86, 91, 76, 65, + 97, 108, 123, 118, 85, 88, 79, 66, 9, 4, 19, 30, 61, 48, 39, 42, + 177, 188, 171, 166, 133, 136, 159, 146, 217, 212, 195, 206, 237, 224, 247, 250, + 183, 186, 173, 160, 131, 142, 153, 148, 223, 210, 197, 200, 235, 230, 241, 252, + 103, 106, 125, 112, 83, 94, 73, 68, 15, 2, 21, 24, 59, 54, 33, 44, + 12, 1, 22, 27, 56, 53, 34, 47, 100, 105, 126, 115, 80, 93, 74, 71, + 220, 209, 198, 203, 232, 229, 242, 255, 180, 185, 174, 163, 128, 141, 154, 151, + }; + +const word8 mulBy0x09[256] = { + 0, 9, 18, 27, 36, 45, 54, 63, 72, 65, 90, 83, 108, 101, 126, 119, + 144, 153, 130, 139, 180, 189, 166, 175, 216, 209, 202, 195, 252, 245, 238, 231, + 59, 50, 41, 32, 31, 22, 13, 4, 115, 122, 97, 104, 87, 94, 69, 76, + 171, 162, 185, 176, 143, 134, 157, 148, 227, 234, 241, 248, 199, 206, 213, 220, + 118, 127, 100, 109, 82, 91, 64, 73, 62, 55, 44, 37, 26, 19, 8, 1, + 230, 239, 244, 253, 194, 203, 208, 217, 174, 167, 188, 181, 138, 131, 152, 145, + 77, 68, 95, 86, 105, 96, 123, 114, 5, 12, 23, 30, 33, 40, 51, 58, + 221, 212, 207, 198, 249, 240, 235, 226, 149, 156, 135, 142, 177, 184, 163, 170, + 236, 229, 254, 247, 200, 193, 218, 211, 164, 173, 182, 191, 128, 137, 146, 155, + 124, 117, 110, 103, 88, 81, 74, 67, 52, 61, 38, 47, 16, 25, 2, 11, + 215, 222, 197, 204, 243, 250, 225, 232, 159, 150, 141, 132, 187, 178, 169, 160, + 71, 78, 85, 92, 99, 106, 113, 120, 15, 6, 29, 20, 43, 34, 57, 48, + 154, 147, 136, 129, 190, 183, 172, 165, 210, 219, 192, 201, 246, 255, 228, 237, + 10, 3, 24, 17, 46, 39, 60, 53, 66, 75, 80, 89, 102, 111, 116, 125, + 161, 168, 179, 186, 133, 140, 151, 158, 233, 224, 251, 242, 205, 196, 223, 214, + 49, 56, 35, 42, 21, 28, 7, 14, 121, 112, 107, 98, 93, 84, 79, 70, + }; + +#endif /* AES_MUL_BY_LOOKUP */ diff --git a/libsecurity_apple_csp/lib/boxes-ref.h b/libsecurity_apple_csp/lib/boxes-ref.h new file mode 100644 index 00000000..ca261820 --- /dev/null +++ b/libsecurity_apple_csp/lib/boxes-ref.h @@ -0,0 +1,51 @@ +/* + * 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/bsafeAsymmetric.cpp b/libsecurity_apple_csp/lib/bsafeAsymmetric.cpp new file mode 100644 index 00000000..7cffdd25 --- /dev/null +++ b/libsecurity_apple_csp/lib/bsafeAsymmetric.cpp @@ -0,0 +1,87 @@ +/* + * 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. + */ + +#ifdef BSAFE_CSP_ENABLE + + +// +// bsafeAsymmetric.cpp - asymmetric encrypt/decrypt +// +#include "bsafecspi.h" + +#include // debug + +// +// Public key {en,de}cryption (currently RSA only) +// +// FIXME: +// We really should match the key algorithm to the en/decrypt +// algorithm. Also: verify key usage bits. +void BSafe::PublicKeyCipherContext::init(const Context &context, bool encrypting) +{ + assert(context.algorithm() == CSSM_ALGID_RSA); + + if (reusing(encrypting)) + return; // all set to go + + switch (context.getInt(CSSM_ATTRIBUTE_MODE)) { + case CSSM_ALGMODE_PUBLIC_KEY: + setAlgorithm(AI_PKCS_RSAPublic); + break; + case CSSM_ALGMODE_PRIVATE_KEY: + setAlgorithm(AI_PKCS_RSAPrivate); + break; + case CSSM_ALGMODE_NONE: + { + /* + * None specified (getInt returns zero in that case) - + * infer from key type + */ + CssmKey &key = context.get( + CSSM_ATTRIBUTE_KEY, CSSMERR_CSP_MISSING_ATTR_KEY); + B_INFO_TYPE bAlgType; + switch (key.keyClass()) { + case CSSM_KEYCLASS_PUBLIC_KEY: + bAlgType = AI_PKCS_RSAPublic; + break; + case CSSM_KEYCLASS_PRIVATE_KEY: + bAlgType = AI_PKCS_RSAPrivate; + break; + default: + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS); + } + setAlgorithm(bAlgType); + break; + } + default: + CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_MODE); + } + + // put it all together + setKeyFromContext(context); // set BSafe key + setRandom(); // some PK cryption algs need random input + cipherInit(); // common cipher init + //@@@ calculate output buffer size +} + +// we assume asymmetric crypto algorithms are one-shot output non-repeating + +size_t BSafe::PublicKeyCipherContext::inputSize(size_t outSize) +{ + return 0xFFFFFFFF; // perhaps not the biggest size_t, but big enough... +} +#endif /* BSAFE_CSP_ENABLE */ diff --git a/libsecurity_apple_csp/lib/bsafeContext.cpp b/libsecurity_apple_csp/lib/bsafeContext.cpp new file mode 100644 index 00000000..a58f2afd --- /dev/null +++ b/libsecurity_apple_csp/lib/bsafeContext.cpp @@ -0,0 +1,448 @@ +/* + * 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. + */ + +#ifdef BSAFE_CSP_ENABLE + + +// +// bsafeContext.cpp - implementation of class BSafe::BSafeContext +// and some of its subclasses +// + +#include "bsafecspi.h" +#include "bsafePKCS1.h" +#include +#include +#include +#include "cspdebugging.h" + +#define DATA(cData) POINTER(cData.data()), cData.length() + +A_SURRENDER_CTX * const BSafe::BSafeContext::bsSurrender = NULL; + + +// +// Construct an algorithm object +// +BSafe::BSafeContext::BSafeContext(AppleCSPSession &session) + : AppleCSPContext(session) +{ + bsAlgorithm = NULL; + bsKey = NULL; + bsBinKey = NULL; + bsRandom = NULL; + initialized = false; + opStarted = false; +#ifdef SAFER + inUpdate = NULL; + inOutUpdate = NULL; + inFinal = NULL; + outFinal = NULL; + outFinalR = NULL; +#endif //SAFER +} + +BSafe::BSafeContext::~BSafeContext() +{ + reset(); +} + +void BSafe::BSafeContext::reset() +{ + B_DestroyAlgorithmObject(&bsAlgorithm); + B_DestroyAlgorithmObject(&bsRandom); + destroyBsKey(); +} + +/* + * Clear key state. We only destroy bsKey if we don't have a + * BinaryKey. + */ +void BSafe::BSafeContext::destroyBsKey() +{ + if(bsBinKey == NULL) { + B_DestroyKeyObject(&bsKey); + } + else { + // bsKey gets destroyed when bsBinKey gets deleted + bsBinKey = NULL; + bsKey = NULL; + } +} + +void BSafe::check(int status, bool isKeyOp) +{ + if(status == 0) { + return; + } + dprintf1("BSAFE Error %d\n", status); + switch (status) { + case BE_ALLOC: + throw std::bad_alloc(); + case BE_SIGNATURE: + CssmError::throwMe(CSSMERR_CSP_VERIFY_FAILED); + case BE_OUTPUT_LEN: + CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR); + case BE_INPUT_LEN: + CssmError::throwMe(CSSMERR_CSP_INPUT_LENGTH_ERROR); + case BE_EXPONENT_EVEN: + case BE_EXPONENT_LEN: + case BE_EXPONENT_ONE: + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY); + case BE_DATA: + case BE_INPUT_DATA: + if(isKeyOp) { + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY); + } + else { + CssmError::throwMe(CSSMERR_CSP_INVALID_DATA); + } + case BE_MODULUS_LEN: + case BE_OVER_32K: + case BE_INPUT_COUNT: + case BE_CANCEL: + //@@@ later... + default: + //@@@ translate BSafe errors intelligently + CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR); + } +} + + +void BSafe::BSafeContext::setAlgorithm( + B_INFO_TYPE bAlgType, + const void *info) +{ + B_DestroyAlgorithmObject(&bsAlgorithm); // clear any old BSafe algorithm + check(B_CreateAlgorithmObject(&bsAlgorithm)); + check(B_SetAlgorithmInfo(bsAlgorithm, bAlgType, POINTER(info))); +} + +/* safely create bsKey */ +void BSafe::BSafeContext::createBsKey() +{ + /* reset to initial key state - some keys can't be reused */ + destroyBsKey(); + check(B_CreateKeyObject(&bsKey)); +} + +/* form of *info varies per bKeyInfo */ +void BSafe::BSafeContext::setKeyAtom( + B_INFO_TYPE bKeyInfo, + const void *info) +{ + /* debug only */ + if((bKeyInfo == KI_RSAPublicBER) || (bKeyInfo == KI_RSAPublic)) { + printf("Aargh! Unhandled KI_RSAPublic!\n"); + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY); + } + assert(bKeyInfo != KI_RSAPublicBER); // handled elsewhere for now + assert(bKeyInfo != KI_RSAPublic); // handled elsewhere for now + createBsKey(); + check(B_SetKeyInfo(bsKey, bKeyInfo, POINTER(info)), true); +} + +// +// Set outSize for RSA keys. +// +void BSafe::BSafeContext::setRsaOutSize( + bool isPubKey) +{ + assert(bsKey != NULL); + + A_RSA_KEY *keyInfo; + if(isPubKey) { + keyInfo = getKey(bsKey, KI_RSAPublic); + } + else { + keyInfo = getKey(bsKey, KI_RSAPrivate); + } + mOutSize = (B_IntegerBits(keyInfo->modulus.data, + keyInfo->modulus.len) + 7) / 8; +} + +// +// Handle various forms of reference key. Symmetric +// keys are stored as SymmetricBinaryKey, with raw key bytes +// in keyData. Our asymmetric keys are stored as BSafeBinaryKeys, +// with an embedded ready-to-use B_KEY_OBJ. +// +void BSafe::BSafeContext::setRefKey(CssmKey &key) +{ + bool isPubKey = false; + + switch(key.keyClass()) { + case CSSM_KEYCLASS_SESSION_KEY: + { + assert(key.blobFormat() == + CSSM_KEYBLOB_REF_FORMAT_INTEGER); + + BinaryKey &binKey = session().lookupRefKey(key); + // fails if this is not a SymmetricBinaryKey + SymmetricBinaryKey *symBinKey = + dynamic_cast(&binKey); + if(symBinKey == NULL) { + errorLog0("BSafe::setRefKey(1): wrong BinaryKey subclass\n"); + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY); + } + setKeyFromCssmData(KI_Item, symBinKey->mKeyData); + return; + } + case CSSM_KEYCLASS_PUBLIC_KEY: + isPubKey = true; // and fall thru + case CSSM_KEYCLASS_PRIVATE_KEY: + { + BinaryKey &binKey = session().lookupRefKey(key); + destroyBsKey(); + bsBinKey = dynamic_cast(&binKey); + /* this cast failing means that this is some other + * kind of binary key */ + if(bsBinKey == NULL) { + errorLog0("BSafe::setRefKey(2): wrong BinaryKey subclass\n"); + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY); + } + assert(bsBinKey->bsKey() != NULL); + bsKey = bsBinKey->bsKey(); + if(key.algorithm() == CSSM_ALGID_RSA) { + setRsaOutSize(isPubKey); + } + return; + } + default: + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS); + } +} + +void BSafe::BSafeContext::setKeyFromContext( + const Context &context, + bool required) +{ + CssmKey &key = + context.get(CSSM_ATTRIBUTE_KEY, CSSMERR_CSP_MISSING_ATTR_KEY); + + switch(key.blobType()) { + case CSSM_KEYBLOB_REFERENCE: + setRefKey(key); + return; + case CSSM_KEYBLOB_RAW: + break; // to main routine + default: + CssmError::throwMe(CSSMERR_CSP_KEY_BLOB_TYPE_INCORRECT); + } + + bool isPubKey; + switch (key.keyClass()) { + case CSSM_KEYCLASS_SESSION_KEY: + /* symmetric, one format supported for all algs */ + switch (key.blobFormat()) { + case CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING: + setKeyFromCssmKey(KI_Item, key); + return; + default: + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_FORMAT); + } + case CSSM_KEYCLASS_PUBLIC_KEY: + isPubKey = true; + break; + case CSSM_KEYCLASS_PRIVATE_KEY: + isPubKey = false; + break; + default: + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS); + } + + /* We know it's an asymmetric key; get some info */ + B_INFO_TYPE infoType; + CSSM_KEYBLOB_FORMAT expectedFormat; + + if(!bsafeAlgToInfoType(key.algorithm(), + isPubKey, + infoType, + expectedFormat)) { + /* unknown alg! */ + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY); + } + + /* + * Correct format? + * NOTE: if we end up supporting multiple incoming key formats, they'll + * have to be handled here. + */ + if(expectedFormat != key.blobFormat()) { + errorLog1("setKeyFromContext: invalid blob format (%d)\n", + (int)key.blobFormat()); + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_FORMAT); + } + + /* + * Most formats can be handled directly by BSAFE. Handle the special cases + * requiring additional processing here. + */ + switch(expectedFormat) { + case CSSM_KEYBLOB_RAW_FORMAT_PKCS1: + /* RSA public keys */ + createBsKey(); + BS_setKeyPkcs1(CssmData::overlay(key.KeyData), bsKey); + break; + default: + setKeyFromCssmKey(infoType, key); + break; + } + + /* + * One more thing - set mOutSize for RSA keys + */ + if(key.algorithm() == CSSM_ALGID_RSA) { + setRsaOutSize(isPubKey); + } +} + +#define BSAFE_RANDSIZE 32 + +void BSafe::BSafeContext::setRandom() +{ + if (bsRandom == NULL) { + check(B_CreateAlgorithmObject(&bsRandom)); + check(B_SetAlgorithmInfo(bsRandom, AI_X962Random_V0, NULL_PTR)); + check(B_RandomInit(bsRandom, chooser(), bsSurrender)); + uint8 seed[BSAFE_RANDSIZE]; + session().getRandomBytes(BSAFE_RANDSIZE, seed); + check(B_RandomUpdate(bsRandom, seed, sizeof(seed), bsSurrender)); + } +} + + +// +// Operational methods of BSafeContext +// +void BSafe::BSafeContext::init(const Context &, bool) +{ + // some algorithms don't need init(), because all is done in the context constructor +} + +// update for input-only block/stream algorithms +void BSafe::BSafeContext::update(const CssmData &data) +{ + opStarted = true; + check(inUpdate(bsAlgorithm, POINTER(data.data()), data.length(), bsSurrender)); +} + +// update for input/output block/stream algorithms +void BSafe::BSafeContext::update(void *inp, size_t &inSize, void *outp, size_t &outSize) +{ + unsigned int length; + opStarted = true; + check(inOutUpdate(bsAlgorithm, POINTER(outp), &length, outSize, + POINTER(inp), inSize, bsRandom, bsSurrender)); + // always eat all input (inSize unchanged) + outSize = length; + + // let the algorithm manager track I/O sizes, if needed + trackUpdate(inSize, outSize); +} + +// output-generating final call +void BSafe::BSafeContext::final(CssmData &out) +{ + unsigned int length; + if (outFinal) { + check(outFinal(bsAlgorithm, + POINTER(out.data()), + &length, + out.length(), + bsSurrender)); + } + else { + check(outFinalR(bsAlgorithm, + POINTER(out.data()), + &length, + out.length(), + bsRandom, + bsSurrender)); + } + out.length(length); + initialized = false; +} + +// verifying final call (takes additional input) +void BSafe::BSafeContext::final(const CssmData &in) +{ + int status; + + /* note sig verify errors can show up as lots of BSAFE statuses; + * munge them all into the appropriate error */ + if (inFinal) { + status = inFinal(bsAlgorithm, + POINTER(in.data()), + in.length(), + bsSurrender); + } + else { + status = inFinalR(bsAlgorithm, + POINTER(in.data()), + in.length(), + bsRandom, + bsSurrender); + } + if(status != 0) { + if((mType == CSSM_ALGCLASS_SIGNATURE) && (mDirection == false)) { + /* yep, sig verify error */ + CssmError::throwMe(CSSMERR_CSP_VERIFY_FAILED); + } + /* other error, use standard trap */ + check(status); + } + initialized = false; +} + +size_t BSafe::BSafeContext::outputSize(bool final, size_t inSize) +{ + // this default implementation only makes sense for single-output end-loaded algorithms + return final ? mOutSize : 0; +} + +void BSafe::BSafeContext::trackUpdate(size_t, size_t) +{ /* do nothing */ } + +// +// Common features of CipherContexts. +// +void BSafe::CipherContext::cipherInit() +{ + // set handlers + if (encoding) { + inOutUpdate = B_EncryptUpdate; + outFinalR = B_EncryptFinal; + } else { + inOutUpdate = B_DecryptUpdate; + outFinalR = B_DecryptFinal; + } + outFinal = NULL; + + // init the algorithm + check((encoding ? B_EncryptInit : B_DecryptInit) + (bsAlgorithm, bsKey, chooser(), bsSurrender)); + + // buffers start empty + pending = 0; + + // state is now valid + initialized = true; + opStarted = false; +} +#endif /* BSAFE_CSP_ENABLE */ + diff --git a/libsecurity_apple_csp/lib/bsafeKeyGen.cpp b/libsecurity_apple_csp/lib/bsafeKeyGen.cpp new file mode 100644 index 00000000..8e76232d --- /dev/null +++ b/libsecurity_apple_csp/lib/bsafeKeyGen.cpp @@ -0,0 +1,461 @@ +/* + * 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. + */ + +#ifdef BSAFE_CSP_ENABLE + + +// +// bsafeKeyGen.cpp - key generation routines +// +#include "bsafecspi.h" +#include "bsafePKCS1.h" +#include "cspdebugging.h" + +/* + * Stateless, private function to map a CSSM alg and pub/priv state + * to B_INFO_TYPE and format. Returns true on success, false on + * "I don't understand this algorithm". + */ +bool BSafe::bsafeAlgToInfoType( + CSSM_ALGORITHMS alg, + bool isPublic, + B_INFO_TYPE &infoType, // RETURNED + CSSM_KEYBLOB_FORMAT &format) // RETURNED +{ + switch(alg) { + case CSSM_ALGID_RSA: + if(isPublic) { + infoType = RSA_PUB_KEYINFO_TYPE; + format = CSSM_KEYBLOB_RAW_FORMAT_PKCS1; + } + else { + infoType = RSA_PRIV_KEYINFO_TYPE; + format = CSSM_KEYBLOB_RAW_FORMAT_PKCS8; + } + return true; + case CSSM_ALGID_DSA: + format = CSSM_KEYBLOB_RAW_FORMAT_FIPS186; + if(isPublic) { + infoType = DSA_PUB_KEYINFO_TYPE; + } + else { + infoType = DSA_PRIV_KEYINFO_TYPE; + } + return true; + default: + return false; + } +} + + +BSafe::BSafeBinaryKey::BSafeBinaryKey( + bool isPub, + uint32 Alg) + : mIsPublic(isPub), + mAlg(Alg) +{ + BSafe::check(B_CreateKeyObject(&mBsKey), true); +} + +BSafe::BSafeBinaryKey::~BSafeBinaryKey() +{ + B_DestroyKeyObject(&mBsKey); +} + +void BSafe::BSafeBinaryKey::generateKeyBlob( + Allocator &allocator, + CssmData &blob, + CSSM_KEYBLOB_FORMAT &format, // input val ignored for now + AppleCSPSession &session, + const CssmKey *paramKey, // optional, unused here + CSSM_KEYATTR_FLAGS &attrFlags) // IN/OUT +{ + assert(mBsKey != NULL); + + B_INFO_TYPE bsType; + if(!bsafeAlgToInfoType(mAlg, mIsPublic, bsType, format)) { + CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR); + } + if(format == CSSM_KEYBLOB_RAW_FORMAT_PKCS1) { + /* special case, encode the PKCS1 format blob */ + CssmRemoteData rData( + Allocator::standard(Allocator::sensitive), blob); + BS_GetKeyPkcs1(mBsKey, rData); + rData.release(); + } + else { + BSafeItem *info; + BSafe::check( + B_GetKeyInfo((POINTER *)&info, mBsKey, bsType), true); + blob = info->copy(allocator); + } +} + +// +// This is called from CSPFullPluginSession +// +void BSafe::BSafeKeyPairGenContext::generate( + const Context &context, + CssmKey &pubKey, + CssmKey &privKey) +{ + BSafeBinaryKey *pubBinKey = new BSafeBinaryKey(true, + context.algorithm()); + BSafeBinaryKey *privBinKey = new BSafeBinaryKey(false, + context.algorithm()); + + try { + AppleKeyPairGenContext::generate(context, + session(), + pubKey, + pubBinKey, + privKey, + privBinKey); + } + catch (...) { + delete pubBinKey; + delete privBinKey; + throw; + } +} + +// +// Called from AppleKeyPairGenContext +// +void BSafe::BSafeKeyPairGenContext::generate( + const Context &context, + BinaryKey &pubBinKey, // valid on successful return + BinaryKey &privBinKey, // ditto + uint32 &keySize) // ditto +{ + /* these casts throw exceptions if the keys are of the + * wrong classes, which is a major bogon, since we created + * the keys in the above generate() function */ + BSafeBinaryKey &bsPubBinKey = + dynamic_cast(pubBinKey); + BSafeBinaryKey &bsPrivBinKey = + dynamic_cast(privBinKey); + + if (!initialized) { + setupAlgorithm(context, keySize); + check(B_GenerateInit(bsAlgorithm, chooser(), bsSurrender), true); + initialized = true; + } + + setRandom(); + check(B_GenerateKeypair(bsAlgorithm, + bsPubBinKey.bsKey(), + bsPrivBinKey.bsKey(), + bsRandom, + bsSurrender), true); +} + +void BSafe::BSafeKeyPairGenContext::setupAlgorithm( + const Context &context, + uint32 &keySize) +{ + switch(context.algorithm()) { + case CSSM_ALGID_RSA: + { + A_RSA_KEY_GEN_PARAMS genParams; + keySize = genParams.modulusBits = + context.getInt(CSSM_ATTRIBUTE_KEY_LENGTH, + CSSMERR_CSP_INVALID_ATTR_KEY_LENGTH); + if (CssmData *params = + context.get(CSSM_ATTRIBUTE_ALG_PARAMS)) { + genParams.publicExponent = BSafeItem(*params); + } else { + static unsigned char exponent[] = { 1, 0, 1 }; + genParams.publicExponent = BSafeItem(exponent, sizeof(exponent)); + } + /* + * For test purposes, we avoid the 'strong' key generate + * algorithm if a CSSM_ALGMODE_CUSTOM mode atrtribute + * is present in the context. This is not published and + * not supported in the real world. + */ + uint32 mode = context.getInt(CSSM_ATTRIBUTE_MODE); + if(mode == CSSM_ALGMODE_CUSTOM) { + setAlgorithm(AI_RSAKeyGen, &genParams); + } + else { + setAlgorithm(AI_RSAStrongKeyGen, &genParams); + } + } + break; + case CSSM_ALGID_DSA: + { + A_DSA_PARAMS genParams; + genParams.prime = + BSafeItem(context.get( + CSSM_ATTRIBUTE_PRIME, + CSSMERR_CSP_MISSING_ATTR_ALG_PARAMS)); + genParams.subPrime = + BSafeItem(context.get( + CSSM_ATTRIBUTE_SUBPRIME, + CSSMERR_CSP_MISSING_ATTR_ALG_PARAMS)); + genParams.base = + BSafeItem(context.get( + CSSM_ATTRIBUTE_BASE, + CSSMERR_CSP_MISSING_ATTR_ALG_PARAMS)); + setAlgorithm(AI_DSAKeyGen, &genParams); + keySize = B_IntegerBits(genParams.prime.data, genParams.prime.len); + } + break; + default: + CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR); + } +} + +// +// DSA Parameter Generation +// +void BSafe::BSafeKeyPairGenContext::generate( + const Context &context, + uint32 bitSize, + CssmData ¶ms, + uint32 &attrCount, + Context::Attr * &attrs) +{ + assert(context.algorithm() == CSSM_ALGID_DSA); + + B_ALGORITHM_OBJ genAlg = NULL; + B_ALGORITHM_OBJ result = NULL; + + try { + check(B_CreateAlgorithmObject(&genAlg)); + + B_DSA_PARAM_GEN_PARAMS genParams; + genParams.primeBits = bitSize; + check(B_SetAlgorithmInfo(genAlg, AI_DSAParamGen, POINTER(&genParams))); + setRandom(); + check(B_GenerateInit(genAlg, chooser(), bsSurrender), true); + check(B_CreateAlgorithmObject(&result)); + check(B_GenerateParameters(genAlg, result, bsRandom, bsSurrender)); + + // get parameters out of algorithm object + A_DSA_PARAMS *kParams = NULL; + check(B_GetAlgorithmInfo((POINTER *)&kParams, result, AI_DSAKeyGen), true); + + // shred them into context attribute form + attrs = normAllocator->alloc(3); + attrs[0] = Context::Attr(CSSM_ATTRIBUTE_PRIME, + *BSafeItem(kParams->prime).copyp(*normAllocator)); + attrs[1] = Context::Attr(CSSM_ATTRIBUTE_SUBPRIME, + *BSafeItem(kParams->subPrime).copyp(*normAllocator)); + attrs[2] = Context::Attr(CSSM_ATTRIBUTE_BASE, + *BSafeItem(kParams->base).copyp(*normAllocator)); + attrCount = 3; + + // clean up + B_DestroyAlgorithmObject(&result); + B_DestroyAlgorithmObject(&genAlg); + } catch (...) { + // clean up + B_DestroyAlgorithmObject(&result); + B_DestroyAlgorithmObject(&genAlg); + throw; + } +} + +/* + * CSPKeyInfoProvider for asymmetric BSAFE keys. + */ +BSafe::BSafeKeyInfoProvider::BSafeKeyInfoProvider( + const CssmKey &cssmKey, + AppleCSPSession &session) : + CSPKeyInfoProvider(cssmKey, session) +{ +} + +CSPKeyInfoProvider *BSafe::BSafeKeyInfoProvider::provider( + const CssmKey &cssmKey, + AppleCSPSession &session) +{ + switch(cssmKey.keyClass()) { + case CSSM_KEYCLASS_PUBLIC_KEY: + case CSSM_KEYCLASS_PRIVATE_KEY: + break; + default: + return NULL; + } + switch(mKey.algorithm()) { + case CSSM_ALGID_RSA: + case CSSM_ALGID_DSA: + break; + default: + return NULL; + } + /* OK, we'll handle this one */ + return new BSafeKeyInfoProvider(cssmKey, session); +} + +/* cook up a Binary key */ +void BSafe::BSafeKeyInfoProvider::CssmKeyToBinary( + CssmKey *paramKey, // optional, ignored + CSSM_KEYATTR_FLAGS &attrFlags, // IN/OUT + BinaryKey **binKey) +{ + *binKey = NULL; + + const CSSM_KEYHEADER *hdr = &mKey.KeyHeader; + assert(hdr->BlobType == CSSM_KEYBLOB_RAW); + + B_INFO_TYPE bsType; + CSSM_KEYBLOB_FORMAT format; + bool isPub; + + switch(hdr->KeyClass) { + case CSSM_KEYCLASS_PUBLIC_KEY: + isPub = true; + break; + case CSSM_KEYCLASS_PRIVATE_KEY: + isPub = false; + break; + default: + // someone else's key + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS); + } + if(!bsafeAlgToInfoType(hdr->AlgorithmId, isPub, bsType, format)) { + // someone else's key + CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM); + } + if(hdr->Format != format) { + dprintf0("BSafe::cssmKeyToBinary: format mismatch\n"); + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_FORMAT); + } + + BSafeBinaryKey *bsBinKey = new BSafeBinaryKey(isPub, + hdr->AlgorithmId); + + // set up key material as appropriate + if(format == CSSM_KEYBLOB_RAW_FORMAT_PKCS1) { + /* special case, decode the PKCS1 format blob */ + BS_setKeyPkcs1(mKey, bsBinKey->bsKey()); + } + else { + /* normal case, use key blob as is */ + BSafeItem item(mKey.KeyData); + BSafe::check( + B_SetKeyInfo(bsBinKey->bsKey(), bsType, POINTER(&item)), true); + } + *binKey = bsBinKey; +} + +/* + * Obtain key size in bits. + */ +void BSafe::BSafeKeyInfoProvider::QueryKeySizeInBits( + CSSM_KEY_SIZE &keySize) +{ + if(mKey.blobType() != CSSM_KEYBLOB_RAW) { + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_FORMAT); + } + + /* cook up BSAFE key */ + B_KEY_OBJ bKey; + A_RSA_KEY *rsaKeyInfo = NULL; + A_DSA_PUBLIC_KEY *dsaPubKeyInfo = NULL; + A_DSA_PRIVATE_KEY *dsaPrivKeyInfo = NULL; + ITEM *sizeItem = NULL; + BSafe::check(B_CreateKeyObject(&bKey), true); + B_INFO_TYPE infoType; + + switch(mKey.algorithm()) { + case CSSM_ALGID_RSA: + switch(mKey.keyClass()) { + case CSSM_KEYCLASS_PUBLIC_KEY: + if(mKey.blobFormat() != + CSSM_KEYBLOB_RAW_FORMAT_PKCS1) { + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_FORMAT); + } + + /* convert from PKCS1 blob to raw key */ + BS_setKeyPkcs1(mKey, bKey); + infoType = KI_RSAPublic; + /* break to common RSA code */ + break; + case CSSM_KEYCLASS_PRIVATE_KEY: + { + if(mKey.blobFormat() != + CSSM_KEYBLOB_RAW_FORMAT_PKCS8) { + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_FORMAT); + } + + /* convert from PKCS8 blob to raw key */ + BSafeItem item(mKey.KeyData); + BSafe::check( + B_SetKeyInfo(bKey, KI_PKCS_RSAPrivateBER, + POINTER(&item)), true); + infoType = KI_RSAPrivate; + break; + } + default: + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS); + } + rsaKeyInfo = getKey(bKey, infoType); + sizeItem = &rsaKeyInfo->modulus; + break; + + case CSSM_ALGID_DSA: + /* untested as of 9/11/00 */ + if(mKey.blobFormat() != + CSSM_KEYBLOB_RAW_FORMAT_FIPS186) { + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_FORMAT); + } + switch(mKey.keyClass()) { + case CSSM_KEYCLASS_PUBLIC_KEY: + { + BSafeItem item(mKey.KeyData); + BSafe::check(B_SetKeyInfo(bKey, + DSA_PUB_KEYINFO_TYPE, + (POINTER)&item), true); + + /* get the key bits */ + dsaPubKeyInfo = getKey(bKey, + KI_DSAPublic); + sizeItem = &dsaPubKeyInfo->params.prime; + break; + } + case CSSM_KEYCLASS_PRIVATE_KEY: + { + BSafeItem item(mKey.KeyData); + BSafe::check(B_SetKeyInfo(bKey, + DSA_PRIV_KEYINFO_TYPE, + (POINTER)&item), true); + + /* get the key bits */ + dsaPrivKeyInfo = getKey(bKey, + KI_DSAPrivate); + sizeItem = &dsaPrivKeyInfo->params.prime; + break; + } + default: + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS); + } + break; + default: + CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR); + } + uint32 iSize = B_IntegerBits(sizeItem->data, sizeItem->len); + keySize.LogicalKeySizeInBits = iSize; + keySize.EffectiveKeySizeInBits = iSize; + B_DestroyKeyObject(&bKey); +} + +#endif /* BSAFE_CSP_ENABLE */ + diff --git a/libsecurity_apple_csp/lib/bsafePKCS1.cpp b/libsecurity_apple_csp/lib/bsafePKCS1.cpp new file mode 100644 index 00000000..1c7e0196 --- /dev/null +++ b/libsecurity_apple_csp/lib/bsafePKCS1.cpp @@ -0,0 +1,137 @@ +/* + * 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. + */ + +#ifdef BSAFE_CSP_ENABLE + + +/* + * bsafePKCS1.cpp - support for PKCS1 format RSA public key blobs, which for some + * reason, BSAFE doesn't know about. + */ + +#include "bsafePKCS1.h" +#include "bsafecspi.h" +#include "cspdebugging.h" +#include "bsobjects.h" +#include /* for RSAPublicKey */ +#include +#include + +/* + * Simple conversion between BSAFE ITEM and snacc BigIntegerStr + */ +static void BS_ItemToSnaccBigInt( + const ITEM &item, + BigIntegerStr &snaccInt) +{ + snaccInt.Set(reinterpret_cast(item.data), item.len); +} + +/* + * This one doesn't do a malloc - the ITEM is only valid as long as + * snaccInt is! + */ +static void BS_snaccBigIntToItem( + BigIntegerStr &snaccInt, // not const - we're passing a ptr + ITEM &item) +{ + char *cp = snaccInt; + item.data = reinterpret_cast(cp); + item.len = snaccInt.Len(); +} + +/* + * Given a PKCS1-formatted key blob, decode the blob into components and do + * a B_SetKeyInfo on the specified BSAFE key. + */ +void BS_setKeyPkcs1( + const CssmData &pkcs1Blob, + B_KEY_OBJ bsKey) +{ + /* DER-decode the blob */ + RSAPublicKey snaccPubKey; + + try { + SC_decodeAsnObj(pkcs1Blob, snaccPubKey); + } + catch(const CssmError &cerror) { + CSSM_RETURN crtn = cerror.cssmError(); + + errorLog1("BS_setKeyPkcs1: SC_decodeAsnObj returned %s\n", + cssmErrorString(crtn).c_str()); + switch(crtn) { + case CSSMERR_CSSM_MEMORY_ERROR: + crtn = CSSMERR_CSP_MEMORY_ERROR; + break; + case CSSMERR_CSSM_INVALID_INPUT_POINTER: + crtn = CSSMERR_CSP_INVALID_KEY; + default: + break; + } + CssmError::throwMe(crtn); + } + + /* + * Convert BigIntegerStr modulus, publicExponent into + * ITEMS in an A_RSA_KEY. + */ + A_RSA_KEY rsaKey; + BS_snaccBigIntToItem(snaccPubKey.modulus, rsaKey.modulus); + BS_snaccBigIntToItem(snaccPubKey.publicExponent, rsaKey.exponent); + + BSafe::check( + B_SetKeyInfo(bsKey, KI_RSAPublic, POINTER(&rsaKey)), true); +} + +/* + * Obtain public key blob info, PKCS1 format. + */ +void BS_GetKeyPkcs1( + const B_KEY_OBJ bsKey, + CssmOwnedData &pkcs1Blob) +{ + /* get modulus/exponent info from BSAFE */ + A_RSA_KEY *rsaKey; + BSafe::check( + B_GetKeyInfo((POINTER *)&rsaKey, bsKey, KI_RSAPublic), true); + + /* Cook up a snacc-style RSAPublic key */ + RSAPublicKey snaccPubKey; + BS_ItemToSnaccBigInt(rsaKey->modulus, snaccPubKey.modulus); + BS_ItemToSnaccBigInt(rsaKey->exponent, snaccPubKey.publicExponent); + + /* estimate max size, BER-encode */ + size_t maxSize = 2 * (rsaKey->modulus.len + rsaKey->exponent.len); + try { + SC_encodeAsnObj(snaccPubKey, pkcs1Blob, maxSize); + } + catch(const CssmError &cerror) { + CSSM_RETURN crtn = cerror.cssmError(); + + errorLog1("BS_GetKeyPkcs1: SC_encodeAsnObj returned %s\n", + cssmErrorString(crtn).c_str()); + switch(crtn) { + case CSSMERR_CSSM_MEMORY_ERROR: + crtn = CSSMERR_CSP_MEMORY_ERROR; + break; + default: + break; + } + CssmError::throwMe(crtn); + } +} +#endif /* BSAFE_CSP_ENABLE */ diff --git a/libsecurity_apple_csp/lib/bsafePKCS1.h b/libsecurity_apple_csp/lib/bsafePKCS1.h new file mode 100644 index 00000000..9a10f80e --- /dev/null +++ b/libsecurity_apple_csp/lib/bsafePKCS1.h @@ -0,0 +1,73 @@ +/* + * 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. + */ + +#ifdef BSAFE_CSP_ENABLE + + +/* + * bsafePKCS1.h - support for PKCS1 format RSA public key blobs, which for some + * reason, BSAFE doesn't know about. + */ + +#ifndef _BSAFE_PKCS1_H_ +#define _BSAFE_PKCS1_H_ + +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* DER-decode any AsnType object */ +CSSM_RETURN CL_decodeAsnObj( + const CssmData &derEncoded, + AsnType &asnObj); + +/* DER-encode any AsnType object. */ +CSSM_RETURN CL_encodeAsnObj( + AsnType &asnObj, + CssmOwnedData &derEncoded, + size_t maxEncodedSize); + +/* + * Given a PKCS1-formatted key blob, decode the blob into components and do + * a B_SetKeyInfo on the specified BSAFE key. + */ +void BS_setKeyPkcs1( + const CssmData &pkcs1Blob, + B_KEY_OBJ bsKey); + +/* + * Obtain public key blob info, PKCS1 format. + */ +void BS_GetKeyPkcs1( + const B_KEY_OBJ bsKey, + CssmOwnedData &pkcs1Blob); + +#ifdef __cplusplus +} +#endif + +#endif /* _BSAFE_PKCS1_H_ */ + +#endif /* BSAFE_CSP_ENABLE */ + diff --git a/libsecurity_apple_csp/lib/bsafeSymmetric.cpp b/libsecurity_apple_csp/lib/bsafeSymmetric.cpp new file mode 100644 index 00000000..5d7280ef --- /dev/null +++ b/libsecurity_apple_csp/lib/bsafeSymmetric.cpp @@ -0,0 +1,289 @@ +/* + * 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. + */ + +#ifdef BSAFE_CSP_ENABLE + + +// +// bsafeSymmetric.cpp - symmetric encryption contexts and algorithms +// +#include "bsafecspi.h" +#include + +#define bbprintf(args...) secdebug("BSafeBuf", ## args) + +#define VERBOSE_DEBUG 0 +#if VERBOSE_DEBUG +static void dumpBuf( + char *title, + const CSSM_DATA *d, + uint32 maxLen) +{ + unsigned i; + uint32 len; + + if(title) { + printf("%s: ", title); + } + if(d == NULL) { + printf("NO DATA\n"); + return; + } + printf("Total Length: %d\n ", d->Length); + len = maxLen; + if(d->Length < len) { + len = d->Length; + } + for(i=0; iData[i]); + if((i % 16) == 15) { + printf("\n "); + } + } + printf("\n"); +} +#else +#define dumpBuf(t, d, m) +#endif /* VERBOSE_DEBUG */ + +void BSafe::SymmetricKeyGenContext::generate( + const Context &context, + CssmKey &symKey, + CssmKey &dummyKey) +{ + AppleSymmKeyGenContext::generateSymKey( + context, + session(), + symKey); +} + +// FIXME: +// We really should match the key algorithm to the en/decrypt +// algorithm. Also: verify key usage bits. +void BSafe::BlockCipherContext::init( + const Context &context, + bool encrypting) +{ + bool hasIV = false; + bool requirePad = false; + + if (reusing(encrypting)) + return; // all set to go + + cssmAlg = context.algorithm(); + switch(cssmAlg) { + // most are handled below; break here to special cases + case CSSM_ALGID_RC4: + RC4init(context); + return; + case CSSM_ALGID_DES: + case CSSM_ALGID_DESX: + case CSSM_ALGID_3DES_3KEY_EDE: + case CSSM_ALGID_RC5: + case CSSM_ALGID_RC2: + break; + + /* others here... */ + default: + // Should never have gotten this far + assert(0); + CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM); + } + + + // these variables are used in the switch below and need to + // live until after setAlgorithm() + BSafeItem iv; + B_BLK_CIPHER_W_FEEDBACK_PARAMS spec; + A_RC5_PARAMS rc5Params; + A_RC2_PARAMS rc2Params; + + // crypto algorithm + spec.encryptionParams = NULL_PTR; // default, may change + switch (cssmAlg) { + case CSSM_ALGID_DES: + spec.encryptionMethodName = POINTER("des"); + break; + case CSSM_ALGID_DESX: + spec.encryptionMethodName = POINTER("desx"); + break; + case CSSM_ALGID_3DES_3KEY_EDE: + spec.encryptionMethodName = POINTER("des_ede"); + break; + case CSSM_ALGID_RC5: + spec.encryptionMethodName = POINTER("rc5"); + spec.encryptionParams = POINTER(&rc5Params); + rc5Params.version = 0x10; + // FIXME - get this from context attr + rc5Params.rounds = 1; + rc5Params.wordSizeInBits = 32; + break; + case CSSM_ALGID_RC2: + { + spec.encryptionMethodName = POINTER("rc2"); + spec.encryptionParams = POINTER(&rc2Params); + // effective key size in bits - either from Context, + // or the key + uint32 bits = context.getInt(CSSM_ATTRIBUTE_EFFECTIVE_BITS); + if(bits == 0) { + // OK, try the key + CssmKey &key = context.get(CSSM_ATTRIBUTE_KEY, + CSSMERR_CSP_MISSING_ATTR_KEY); + bits = key.KeyHeader.LogicalKeySizeInBits; + } + rc2Params.effectiveKeyBits = bits; + break; + } + } + + // feedback mode + cssmMode = context.getInt(CSSM_ATTRIBUTE_MODE); + switch (cssmMode) { + /* no mode attr --> 0 == CSSM_ALGMODE_NONE, not currently supported */ + case CSSM_ALGMODE_CBCPadIV8: + requirePad = true; + // and fall thru + case CSSM_ALGMODE_CBC_IV8: + { + iv = context.get(CSSM_ATTRIBUTE_INIT_VECTOR, + CSSMERR_CSP_MISSING_ATTR_INIT_VECTOR); + spec.feedbackMethodName = POINTER("cbc"); + spec.feedbackParams = POINTER(&iv); + hasIV = true; + break; + } + case CSSM_ALGMODE_OFB_IV8: { + iv = context.get(CSSM_ATTRIBUTE_INIT_VECTOR, + CSSMERR_CSP_MISSING_ATTR_INIT_VECTOR); + spec.feedbackMethodName = POINTER("ofb"); + spec.feedbackParams = POINTER(&iv); + hasIV = true; + break; + } + case CSSM_ALGMODE_ECB: { + spec.feedbackMethodName = POINTER("ecb"); + spec.feedbackParams = POINTER(&blockSize); + break; + } + default: + errorLog1("BSafe symmetric init: illegal mode (%d)\n", (int)cssmMode); + CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_MODE); + } + + // padding + spec.paddingParams = NULL_PTR; + /* no padding attr --> 0 == PADDING_NONE */ + padEnable = false; + uint32 cssmPadding = context.getInt(CSSM_ATTRIBUTE_PADDING); + if(requirePad) { + switch(cssmPadding) { + case CSSM_PADDING_PKCS1: // for backwards compatibility + case CSSM_PADDING_PKCS5: + case CSSM_PADDING_PKCS7: + spec.paddingMethodName = POINTER("pad"); + padEnable = true; + break; + default: + CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_PADDING); + } + } + else { + if(cssmPadding != CSSM_PADDING_NONE) { + CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_PADDING); + } + else { + spec.paddingMethodName = POINTER("nopad"); + } + } + + // put it all together + setAlgorithm(AI_FeedbackCipher, &spec); // set BSafe algorithm + setKeyFromContext(context); // set BSafe key + cipherInit(); // common cryption init +} + +void BSafe::BlockCipherContext::RC4init( + const Context &context) +{ + setAlgorithm(AI_RC4, NULL); // set BSafe algorithm + setKeyFromContext(context); // set BSafe key + padEnable = false; + cipherInit(); // common cryption init +} + +void BSafe::BlockCipherContext::trackUpdate(size_t inSize, size_t outSize) +{ + size_t newPending = pending + inSize; + pending = newPending % blockSize; + + /* + * Most of the time, the max size buffered by BSAFE is + * blockSize - 1 bytes. When decrypting and padding is enabled, + * BSAFE buffers up to a full block. + */ + if(!mDirection && //Êdecrypting + padEnable && // padding + (pending == 0) && // mod result was 0 + (newPending > 0)) { // but nonzero total + /* BSAFE is holding a whole block in its buffer */ + pending = blockSize; + } + bbprintf("===trackUpdte: %s; inSize=%d newPending=%d pending=%d", + (mDirection ? "encrypt" : "decrypt"), + inSize, newPending, pending); +} + +size_t BSafe::BlockCipherContext::inputSize(size_t outSize) +{ + // if we have an 'outSize' output buffer, how many input bytes may we feed in? + size_t wholeBlocks = outSize / blockSize; + return wholeBlocks * blockSize - pending + (blockSize - 1); +} + +size_t BSafe::BlockCipherContext::outputSize(bool final, size_t inSize) +{ + // how much output buffer will we need for 'size' input bytes? + + size_t totalToGo = inSize + pending; + // total to go, rounded up to next block + size_t numBlocks = (totalToGo + blockSize - 1) / blockSize; + size_t outSize; + + /* + * encrypting: may get one additional block on final() if padding + * decrypting: outsize always <= insize + */ + if(mDirection && // encrypting + final && // last time + padEnable && // padding enabled + ((totalToGo % blockSize) == 0)) { // even ptext len + numBlocks++; // extra pad block + } + outSize = numBlocks * blockSize; + bbprintf("===outputSize: %s; final=%d inSize=%d pending=%d outSize=%d", + (mDirection ? "encrypt" : "decrypt"), + final, inSize, pending, outSize); + return outSize; +} + +void BSafe::BlockCipherContext::minimumProgress(size_t &inSize, size_t &outSize) +{ + // eat up buffer, proceed one full block + inSize = blockSize - pending; + outSize = blockSize; +} +#endif /* BSAFE_CSP_ENABLE */ diff --git a/libsecurity_apple_csp/lib/bsafecsp.h b/libsecurity_apple_csp/lib/bsafecsp.h new file mode 100644 index 00000000..cfe21a59 --- /dev/null +++ b/libsecurity_apple_csp/lib/bsafecsp.h @@ -0,0 +1,58 @@ +/* + * 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. + */ + +#ifdef BSAFE_CSP_ENABLE + + +// +// bsafecsp - top C++ implementation layer for BSafe 4 +// +#ifndef _H_BSAFECSP +#define _H_BSAFECSP + +#include +#include "AppleCSP.h" + +/* Can't include AppleCSPSession.h due to circular dependency */ +class AppleCSPSession; + +// no longer a subclass of AlgorithmFactory due to +// differing setup() methods +class BSafeFactory : public AppleCSPAlgorithmFactory { +public: + + BSafeFactory( + Allocator *normAlloc = NULL, + Allocator *privAlloc = NULL) + { + setNormAllocator(normAlloc); + setPrivAllocator(privAlloc); + } + ~BSafeFactory() { } + + bool setup( + AppleCSPSession &session, + CSPFullPluginSession::CSPContext * &cspCtx, + const Context &context); + + static void setNormAllocator(Allocator *alloc); + static void setPrivAllocator(Allocator *alloc); + +}; + +#endif //_H_BSAFECSP +#endif /* BSAFE_CSP_ENABLE */ diff --git a/libsecurity_apple_csp/lib/bsafecspi.h b/libsecurity_apple_csp/lib/bsafecspi.h new file mode 100644 index 00000000..9c649d7e --- /dev/null +++ b/libsecurity_apple_csp/lib/bsafecspi.h @@ -0,0 +1,463 @@ +/* + * 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. + */ + +#ifdef BSAFE_CSP_ENABLE + + +// +// bsafecspi - implementation layer for C++ BSafe 4 interface +// +#ifndef _H_BSAFECSPI +#define _H_BSAFECSPI + +#include +#include "bsobjects.h" +#include "AppleCSPContext.h" +#include "AppleCSPSession.h" +#include +#include + +// +// The BSafe class is more of a namespace than anything else. +// Just think of it as the "static binder" for BSafe's objects. +// Note that we keep a global, static allocator. We have to; BSafe +// doesn't have any state management at that level. +// +class BSafe { + class BSafeContext; friend class BSafeContext; + class BSafeFactory; friend class BSafeFactory; + +public: + static void setNormAllocator(Allocator *alloc) + { assert(!normAllocator); normAllocator = alloc; } + static void setPrivAllocator(Allocator *alloc) + { assert(!privAllocator); privAllocator = alloc; } + + static bool setup( + AppleCSPSession &session, + CSPFullPluginSession::CSPContext * &cspCtx, + const Context &context); + +private: + // BSafe's memory allocators + static Allocator *normAllocator; + static Allocator *privAllocator; + friend POINTER T_malloc(unsigned int); + friend void T_free(POINTER); + friend POINTER T_realloc(POINTER, unsigned int); + + static const B_ALGORITHM_METHOD * const bsChooser[]; + +private: + // BSafe-specific BinaryKey class. + class BSafeBinaryKey : public BinaryKey { + + public: + BSafeBinaryKey( + bool isPub, + uint32 alg); // CSSM_ALGID_{RSA,DSA} + ~BSafeBinaryKey(); + void generateKeyBlob( + Allocator &allocator, + CssmData &blob, + CSSM_KEYBLOB_FORMAT &format, + AppleCSPSession &session, + const CssmKey *paramKey, /* optional, unused here */ + CSSM_KEYATTR_FLAGS &attrFlags); /* IN/OUT */ + + bool isPublic() { return mIsPublic; } + uint32 alg() { return mAlg; } + B_KEY_OBJ bsKey() { return mBsKey; } + + private: + bool mIsPublic; + uint32 mAlg; // CSSM_ALGID_{RSA,DSA} + B_KEY_OBJ mBsKey; + }; + +private: + // + // The BSafeContext class is the parent of all BSafe-used CSPContext objects. + // It implements the CSPContext operation functions (init, update, ...) in terms + // of pointer-to-member fields set by its subclasses. This may not be pretty, but + // it avoids every subclass having to re-implement all CSPContext operations. + // Beyond that, we implement a raftload of utility methods for our children. + // + class BSafeContext : public AppleCSPContext { + friend class BSafe; + public: + BSafeContext(AppleCSPSession &session); + virtual ~BSafeContext(); + + // called by CSPFullPluginSession + void init(const Context &context, bool encoding = true); + void update(const CssmData &data); + void update(void *inp, size_t &inSize, void *outp, size_t &outSize); + void final(CssmData &out); + void final(const CssmData &in); + size_t outputSize(bool final, size_t inSize); + + protected: + // install a BSafe algorithm into bsAlgorithm + void setAlgorithm(B_INFO_TYPE bAlgType, const void *info = NULL); + + // safely create bsKey + void createBsKey(); + + // set bsKey. The different versions are equivalent + void setKeyAtom(B_INFO_TYPE bKeyInfo, const void *info); + void setKeyFromItem(B_INFO_TYPE bKeyInfo, const BSafeItem &item) + { setKeyAtom(bKeyInfo, &item); } + void setKeyFromCssmKey(B_INFO_TYPE bKeyInfo, const CssmKey &key) + { BSafeItem item(key.KeyData); setKeyAtom(bKeyInfo, &item); } + void setKeyFromCssmData(B_INFO_TYPE bKeyInfo, const CssmData &keyData) + { BSafeItem item(keyData); setKeyAtom(bKeyInfo, &item); } + void setKeyFromContext(const Context &context, bool required = true); + + void setRefKey(CssmKey &key); + void setRsaOutSize(bool isPubKey); + + // create mRandom to be a suitable random-generator BSafe object (if it isn't yet) + void setRandom(); + + // trackUpdate is called during crypto-output. Hook it to keep track of data flow + virtual void trackUpdate(size_t in, size_t out); + + // destroy bsAlgorithm and bsKey so we can start over making them + void reset(); + + // clear key state + void destroyBsKey(); + + // determine if we can reuse the current bsAlgorithm + bool reusing(bool encode = true) + { + if (initialized && !opStarted && + (encode == encoding)) return true; + encoding = encode; + return false; + } + + public: + // + // These pointers-to-member are called by the BSafeContext operations + // (update, final). They must be set by a subclasses's init() method. + // Not all members are used by all types of operations - check the + // source when in doubt. + // + int (*inUpdate)(B_ALGORITHM_OBJ, POINTER, unsigned int, A_SURRENDER_CTX *); + int (*inOutUpdate)(B_ALGORITHM_OBJ, POINTER, unsigned int *, unsigned int, + POINTER, unsigned int, B_ALGORITHM_OBJ, A_SURRENDER_CTX *); + int (*inFinal)(B_ALGORITHM_OBJ, POINTER, unsigned int, A_SURRENDER_CTX *); + int (*inFinalR)(B_ALGORITHM_OBJ, POINTER, unsigned int, + B_ALGORITHM_OBJ, A_SURRENDER_CTX *); + int (*outFinalR)(B_ALGORITHM_OBJ, POINTER, unsigned int *, unsigned int, + B_ALGORITHM_OBJ, A_SURRENDER_CTX *); + int (*outFinal)(B_ALGORITHM_OBJ, POINTER, unsigned int *, unsigned int, + A_SURRENDER_CTX *); + + protected: + + // un-consted bsChooser for BSafe's consumption. BSafe's Bad + static B_ALGORITHM_METHOD **chooser() + { return const_cast(bsChooser); } + + // a placeholder for a surrender context. Not currently used + // @@@ should perhaps test for pthread cancel? --> thread abstraction + static A_SURRENDER_CTX * const bsSurrender; + + protected: + B_ALGORITHM_OBJ bsAlgorithm; // BSafe algorithm object or NULL + B_ALGORITHM_OBJ bsRandom; // PRNG algorithm + bool encoding; // encoding direction + bool initialized; // method init() has completed + bool opStarted; // method update() has been called + // generally means that we can't reuse + // the current bsAlgorithm + // + // We have a binKey only if the caller passed in a reference + // key. In that case we avoid deleting bsKey - which is a copy + // of binKey.bsKey - because a BinaryKey is persistent + // relative to this context. + // + BSafeBinaryKey *bsBinKey; + B_KEY_OBJ bsKey; // BSafe key object or NULL + + size_t mOutSize; // simple output size, if applicable + }; /* BSafeContext */ + + // contexts for BSafe digest operations + class DigestContext : public BSafeContext { + public: + // do all work in constructor. We have no directions; thus default init() works fine + DigestContext( + AppleCSPSession &session, + const Context &, + B_INFO_TYPE bAlgInfo, + size_t sz); + }; + + // common context features for BSafe cipher operations (both symmetric and asymmetric) + class CipherContext : public BSafeContext { + public: + CipherContext( + AppleCSPSession &session) : + BSafeContext(session), + pending(0) {} + + protected: + size_t pending; // bytes not eaten still pending (staged only) + public: + void cipherInit(); // common init code (must be called from init()) + }; + + // contexts for block cipher operations using symmetric algorithms + class BlockCipherContext : public CipherContext { + size_t blockSize; + uint32 cssmAlg; + uint32 cssmMode; + bool padEnable; + public: + BlockCipherContext( + AppleCSPSession &session, + const Context &, + size_t sz) : + CipherContext(session), + blockSize(sz) { } + void init(const Context &context, bool encrypting); + size_t inputSize(size_t outSize); + size_t outputSize(bool final, size_t inSize); + void minimumProgress(size_t &in, size_t &out); + void trackUpdate(size_t in, size_t out); + private: + // special case for RC4 + void RC4init(const Context &context); + }; + + // context for generating public/private key pairs + class BSafeKeyPairGenContext : public BSafeContext, + private AppleKeyPairGenContext { + public: + BSafeKeyPairGenContext( + AppleCSPSession &session, + const Context &) : + BSafeContext(session) {} + + // generate alg params, not handled by PublicKeyGenerateContext + // For DSA only. + void generate( + const Context &context, + uint32 bitSize, + CssmData ¶ms, + uint32 &attrCount, + Context::Attr * &attrs); + + // this one is specified in CSPFullPluginSession + void generate( + const Context &context, + CssmKey &pubKey, + CssmKey &privKey); + + // this one in AppleKeyPairGenContext + void generate( + const Context &context, + BinaryKey &pubBinKey, + BinaryKey &privBinKey, + uint32 &keySize); + + private: + void setupAlgorithm( + const Context &context, + uint32 &keySize); + + }; /* BSafeKeyPairGenContext */ + + // public key cipher operations + class PublicKeyCipherContext : public CipherContext { + public: + PublicKeyCipherContext( + AppleCSPSession &session, + const Context &) : + CipherContext(session) { } + void init(const Context &context, bool encrypting); + size_t inputSize(size_t outSize); // unlimited + }; + + // contexts for BSafe signing/verifying operations + class SigningContext : public BSafeContext { + B_INFO_TYPE algorithm; + public: + SigningContext( + AppleCSPSession &session, + const Context &, + B_INFO_TYPE bAlg, + size_t sz) : + BSafeContext(session), + algorithm(bAlg) { mOutSize = sz; } + void init(const Context &context, bool signing); + }; + + // contexts for BSafe MAC generation and verification + class MacContext : public BSafeContext { + B_INFO_TYPE algorithm; + public: + MacContext( + AppleCSPSession &session, + const Context &, + B_INFO_TYPE bAlg, + size_t sz) : + BSafeContext(session), + algorithm(bAlg) { mOutSize = sz; } + void init(const Context &context, bool signing); + void final(const CssmData &in); + }; + + // contexts for BSafe's random number generation + class RandomContext : public BSafeContext { + B_INFO_TYPE algorithm; + public: + RandomContext( + AppleCSPSession &session, + const Context &, + B_INFO_TYPE alg) : + BSafeContext(session), + algorithm(alg) { } + void init(const Context &context, bool); + void final(CssmData &data); + }; + + // symmetric key generation context + class SymmetricKeyGenContext : public BSafeContext, + private AppleSymmKeyGenContext { + public: + SymmetricKeyGenContext( + AppleCSPSession &session, + const Context &ctx, + uint32 minSizeInBits, + uint32 maxSizeInBits, + bool mustBeByteSized) : + BSafeContext(session), + AppleSymmKeyGenContext( + minSizeInBits, + maxSizeInBits, + mustBeByteSized) { } + + void generate( + const Context &context, + CssmKey &symKey, + CssmKey &dummyKey); + + }; + +public: + /* + * Stateless, private function to map a CSSM alg and pub/priv state + * to B_INFO_TYPE and format. Returns true on success, false on + * "I don't understand this algorithm". + */ + static bool bsafeAlgToInfoType( + CSSM_ALGORITHMS alg, + bool isPublic, + B_INFO_TYPE &infoType, // RETURNED + CSSM_KEYBLOB_FORMAT &format); // RETURNED + + /* check result of a BSafe call and throw on error */ + static void check(int status, bool isKeyOp = false); + + /* moved here from BSafeContext - now works on any key */ + template + static KI_Type *getKey(B_KEY_OBJ bKey, B_INFO_TYPE type) + { + POINTER p; + check(B_GetKeyInfo(&p, bKey, type), true); + return reinterpret_cast(p); + } + + + // + // The context generation table - see algmaker.cpp. + // +public: + // Base class for Maker classes + class MakerBase { + public: + virtual ~MakerBase() { } + virtual BSafeContext *make( + AppleCSPSession &session, + const Context &context) const = 0; + }; + + // One entry in Maker table + struct MakerTable { + CSSM_ALGORITHMS algorithmId; + CSSM_CONTEXT_TYPE algClass; + const MakerBase *maker; + ~MakerTable() { delete maker; } + }; + +private: + static bug_const MakerTable algorithms[]; + static const unsigned int algorithmCount; + + /* + * CSPKeyInfoProvider for BSafe keys + */ + class BSafeKeyInfoProvider : public CSPKeyInfoProvider + { +private: + BSafeKeyInfoProvider( + const CssmKey &cssmKey, + AppleCSPSession &session); + public: + static CSPKeyInfoProvider *provider( + const CssmKey &cssmKey, + AppleCSPSession &session); + ~BSafeKeyInfoProvider() { } + void CssmKeyToBinary( + CssmKey *paramKey, // optional + CSSM_KEYATTR_FLAGS &attrFlags, // IN/OUT + BinaryKey **binKey); // RETURNED + void QueryKeySizeInBits( + CSSM_KEY_SIZE &keySize); // RETURNED + }; + +}; /* BSAFE namespace */ + +/* + * BSAFE Key Info types. + */ +#define BLOB_IS_PUB_KEY_INFO 0 + +#if BLOB_IS_PUB_KEY_INFO + +/* X beta values */ +#define RSA_PUB_KEYINFO_TYPE KI_RSAPublicBER +#define RSA_PRIV_KEYINFO_TYPE KI_PKCS_RSAPrivateBER +#define DSA_PUB_KEYINFO_TYPE KI_DSAPublicBER +#define DSA_PRIV_KEYINFO_TYPE KI_DSAPrivateBER + +#else /* BLOB_IS_PUB_KEY_INFO */ + +#define RSA_PUB_KEYINFO_TYPE KI_RSAPublic +#define RSA_PRIV_KEYINFO_TYPE KI_PKCS_RSAPrivateBER +#define DSA_PUB_KEYINFO_TYPE KI_DSAPublicBER +#define DSA_PRIV_KEYINFO_TYPE KI_DSAPrivateBER + +#endif + +#endif //_H_BSAFECSP +#endif /* BSAFE_CSP_ENABLE */ diff --git a/libsecurity_apple_csp/lib/bsobjects.h b/libsecurity_apple_csp/lib/bsobjects.h new file mode 100644 index 00000000..4b8ad096 --- /dev/null +++ b/libsecurity_apple_csp/lib/bsobjects.h @@ -0,0 +1,64 @@ +/* + * 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. + */ + +#ifdef BSAFE_CSP_ENABLE + + +// +// bsobjects - C++ adaptations of popular BSafe 4 object types +// +#ifndef _H_BSOBJECTS +#define _H_BSOBJECTS + +#include +#include +#include +#include + +// +// A PodWrapper for BSafe's ITEM objects +// +class BSafeItem : public PodWrapper { +public: + BSafeItem() { ((ITEM *)this)->data = NULL; len = 0; } + BSafeItem(void *addr, size_t sz) + { ((ITEM *)this)->data = (unsigned char *)addr; len = sz; } + BSafeItem(const CSSM_DATA &cData) + { ((ITEM *)this)->data = cData.Data; len = cData.Length; } + BSafeItem(const ITEM &cData) + { *(ITEM *)this = cData; } + + void operator = (const CssmData &cData) + { ((ITEM *)this)->data = (unsigned char *)cData.data(); len = cData.length(); } + + void *data() const { return ((ITEM *)this)->data; } + size_t length() const { return len; } + + template + T copy(Allocator &alloc) + { return T(memcpy(alloc.malloc(length()), data(), length()), length()); } + + template + T *copyp(Allocator &alloc) + { return new(alloc) T(copy(alloc)); } + + void *operator new (size_t size, Allocator &alloc) + { return alloc.malloc(size); } +}; + +#endif //_H_BSOBJECTS +#endif /* BSAFE_CSP_ENABLE */ diff --git a/libsecurity_apple_csp/lib/castContext.cpp b/libsecurity_apple_csp/lib/castContext.cpp new file mode 100644 index 00000000..dcf76aba --- /dev/null +++ b/libsecurity_apple_csp/lib/castContext.cpp @@ -0,0 +1,133 @@ +/* + * 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. + */ + + +/* + * castContext.cpp - glue between BlockCrytpor and CommonCrypto CAST128 (CAST5) + * implementation + * + */ + +#include "castContext.h" + +CastContext::CastContext(AppleCSPSession &session) : + BlockCryptor(session), + mInitFlag(false), + mCastKey(NULL), + mRawKeySize(0) +{ +} + + + +CastContext::~CastContext() +{ + deleteKey(); +} + +void CastContext::deleteKey() +{ + if (mCastKey != NULL) { + CCCryptorRelease(mCastKey); + } + mCastKey = NULL; + mInitFlag = false; +} + +/* + * Standard CSPContext init, called from CSPFullPluginSession::init(). + * Reusable, e.g., query followed by en/decrypt. + */ +void CastContext::init( + const Context &context, + bool encrypting) +{ + if(mInitFlag && !opStarted()) { + return; + } + + CSSM_SIZE keyLen; + uint8 *keyData = NULL; + bool sameKeySize = false; + + /* obtain key from context */ + symmetricKeyBits(context, session(), CSSM_ALGID_CAST, + encrypting ? CSSM_KEYUSE_ENCRYPT : CSSM_KEYUSE_DECRYPT, + keyData, keyLen); + if((keyLen < kCCKeySizeMinCAST) || (keyLen > kCCKeySizeMaxCAST)) { + CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_KEY); + } + + /* + * Delete existing key if key size changed + */ + if(mRawKeySize == keyLen) { + sameKeySize = true; + } + else { + deleteKey(); + } + + /* init key only if key size or key bits have changed */ + if(!sameKeySize || memcmp(mRawKey, keyData, mRawKeySize)) { + (void) CCCryptorCreateWithMode(0, kCCModeECB, kCCAlgorithmCAST, ccDefaultPadding, NULL, keyData, keyLen, NULL, 0, 0, 0, &mCastKey); + + /* save this raw key data */ + memmove(mRawKey, keyData, keyLen); + mRawKeySize = keyLen; + } + + /* Finally, have BlockCryptor do its setup */ + setup(kCCBlockSizeCAST, context); + mInitFlag = true; +} + +/* + * Functions called by BlockCryptor + */ +void CastContext::encryptBlock( + const void *plainText, // length implied (one block) + size_t plainTextLen, + void *cipherText, + size_t &cipherTextLen, // in/out, throws on overflow + bool final) // ignored +{ + if(plainTextLen != kCCBlockSizeCAST) { + CssmError::throwMe(CSSMERR_CSP_INPUT_LENGTH_ERROR); + } + if(cipherTextLen < kCCBlockSizeCAST) { + CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR); + } + (void) CCCryptorEncryptDataBlock(mCastKey, NULL, plainText, kCCBlockSizeCAST, cipherText); + + cipherTextLen = kCCBlockSizeCAST; +} + +void CastContext::decryptBlock( + const void *cipherText, // length implied (one block) + size_t cipherTextLen, + void *plainText, + size_t &plainTextLen, // in/out, throws on overflow + bool final) // ignored +{ + if(plainTextLen < kCCBlockSizeCAST) { + CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR); + } + (void) CCCryptorDecryptDataBlock(mCastKey, NULL, cipherText, kCCBlockSizeCAST, plainText); + + plainTextLen = kCCBlockSizeCAST; +} diff --git a/libsecurity_apple_csp/lib/castContext.h b/libsecurity_apple_csp/lib/castContext.h new file mode 100644 index 00000000..122fb5dd --- /dev/null +++ b/libsecurity_apple_csp/lib/castContext.h @@ -0,0 +1,93 @@ +/* + * 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. + */ + + +/* + * 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: + * + * In order to avoid confusion when variable keysize operation is + * used, the name CAST-128 is to be considered synonymous with the + * name CAST5; this allows a keysize to be appended without ambiguity. + * Thus, for example, CAST-128 with a 40-bit key is to be referred to + * as CAST5-40; where a 128-bit key is explicitly intended, the + * name CAST5-128 should be used. + * + * This module implements a variable key length, from 40 bits to 128 bits, + * and can thus be said to implement both CAST-128 and CAST5. + */ + +#ifndef _CAST_CONTEXT_H_ +#define _CAST_CONTEXT_H_ + +#include "AppleCSPContext.h" +#include "BlockCryptor.h" +#include +#include +#include "/usr/local/include/CommonCrypto/CommonCryptorSPI.h" + +class CastContext : public BlockCryptor { +public: + CastContext(AppleCSPSession &session); + virtual ~CastContext(); + + // called by CSPFullPluginSession + void init(const Context &context, bool encoding = true); + + // As an optimization, we allow reuse of a modified context. + // The main thing we avoid is a redundant key scheduling. We + // save the current raw keys bits in mRawKey and compare on + // re-init. + bool changed(const Context &context) { return true; } + + // called by BlockCryptor + void encryptBlock( + const void *plainText, // length implied (one block) + size_t plainTextLen, + void *cipherText, + size_t &cipherTextLen, // in/out, throws on overflow + bool final); + void decryptBlock( + const void *cipherText, // length implied (one cipher block) + size_t cipherTextLen, + void *plainText, + size_t &plainTextLen, // in/out, throws on overflow + bool final); + +private: + void deleteKey(); + + /* scheduled key */ + CCCryptorRef mCastKey; + + bool mInitFlag; // for easy reuse + + /* + * Raw key bits saved here and checked on re-init to avoid + * extra key schedule + */ + uint8 mRawKey[kCCKeySizeMaxCAST]; + uint32 mRawKeySize; + + +}; /* CastContext */ + +#endif //_CAST_CONTEXT_H_ diff --git a/libsecurity_apple_csp/lib/cryptkitcsp.cpp b/libsecurity_apple_csp/lib/cryptkitcsp.cpp new file mode 100644 index 00000000..300d0d30 --- /dev/null +++ b/libsecurity_apple_csp/lib/cryptkitcsp.cpp @@ -0,0 +1,218 @@ +/* + * 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. + */ + + +// +// cryptkitcsp - top C++ implementation layer for CryptKit +// + +#ifdef CRYPTKIT_CSP_ENABLE + +#include "cryptkitcsp.h" +#include "FEESignatureObject.h" /* raw signer */ +#include +#include "FEEKeys.h" +#include "FEEAsymmetricContext.h" +#include +#include +#include +#include +#include +#include + +Allocator *CryptKitFactory::normAllocator; +Allocator *CryptKitFactory::privAllocator; + +/* + * CryptKit-style memory allocator callbacks + */ +static void *ckMalloc(unsigned size) +{ + return CryptKitFactory::privAllocator->malloc(size); +} +static void ckFree(void *data) +{ + CryptKitFactory::privAllocator->free(data); +} +static void *ckRealloc(void *oldPtr, unsigned newSize) +{ + return CryptKitFactory::privAllocator->realloc(oldPtr, newSize); +} + +// +// Manage the CryptKit algorithm factory +// + +CryptKitFactory::CryptKitFactory(Allocator *normAlloc, Allocator *privAlloc) +{ + setNormAllocator(normAlloc); + setPrivAllocator(privAlloc); + /* once-per-address space */ + initCryptKit(); + fallocRegister(ckMalloc, ckFree, ckRealloc); +} + +CryptKitFactory::~CryptKitFactory() +{ + terminateCryptKit(); +} + +bool CryptKitFactory::setup( + AppleCSPSession &session, + CSPFullPluginSession::CSPContext * &cspCtx, + const Context &context) +{ + switch(context.type()) { + case CSSM_ALGCLASS_SIGNATURE: + switch(context.algorithm()) { + case CSSM_ALGID_FEE_MD5: + if(cspCtx == NULL) { + cspCtx = new SignatureContext(session, + *(new MD5Object()), + *(new FEERawSigner(feeRandCallback, + &session, + session, + *privAllocator))); + } + return true; + case CSSM_ALGID_FEE_SHA1: + if(cspCtx == NULL) { + cspCtx = new SignatureContext(session, + *(new SHA1Object()), + *(new FEERawSigner(feeRandCallback, + &session, + session, + *privAllocator))); + } + return true; + case CSSM_ALGID_SHA1WithECDSA: + if(cspCtx == NULL) { + cspCtx = new SignatureContext(session, + *(new SHA1Object()), + *(new FEEECDSASigner(feeRandCallback, + &session, + session, + *privAllocator))); + } + return true; + case CSSM_ALGID_SHA224WithECDSA: + if(cspCtx == NULL) { + cspCtx = new SignatureContext(session, + *(new SHA224Object()), + *(new FEEECDSASigner(feeRandCallback, + &session, + session, + *privAllocator))); + } + return true; + case CSSM_ALGID_SHA256WithECDSA: + if(cspCtx == NULL) { + cspCtx = new SignatureContext(session, + *(new SHA256Object()), + *(new FEEECDSASigner(feeRandCallback, + &session, + session, + *privAllocator))); + } + return true; + case CSSM_ALGID_SHA384WithECDSA: + if(cspCtx == NULL) { + cspCtx = new SignatureContext(session, + *(new SHA384Object()), + *(new FEEECDSASigner(feeRandCallback, + &session, + session, + *privAllocator))); + } + return true; + case CSSM_ALGID_SHA512WithECDSA: + if(cspCtx == NULL) { + cspCtx = new SignatureContext(session, + *(new SHA512Object()), + *(new FEEECDSASigner(feeRandCallback, + &session, + session, + *privAllocator))); + } + return true; + + case CSSM_ALGID_FEE: + if(cspCtx == NULL) { + cspCtx = new SignatureContext(session, + *(new NullDigest()), + *(new FEERawSigner(feeRandCallback, + &session, + session, + *privAllocator))); + } + return true; + case CSSM_ALGID_ECDSA: + if(cspCtx == NULL) { + cspCtx = new SignatureContext(session, + *(new NullDigest()), + *(new FEEECDSASigner(feeRandCallback, + &session, + session, + *privAllocator))); + } + return true; + default: + break; + } + break; + + case CSSM_ALGCLASS_KEYGEN: + switch(context.algorithm()) { + case CSSM_ALGID_FEE: + case CSSM_ALGID_ECDSA: + if(cspCtx == NULL) { + cspCtx = new CryptKit::FEEKeyPairGenContext(session, context); + } + return true; + default: + break; + } + break; + + case CSSM_ALGCLASS_ASYMMETRIC: + switch(context.algorithm()) { + case CSSM_ALGID_FEEDEXP: + if(cspCtx == NULL) { + cspCtx = new CryptKit::FEEDExpContext(session); + } + return true; + case CSSM_ALGID_FEED: + if(cspCtx == NULL) { + cspCtx = new CryptKit::FEEDContext(session); + } + return true; + default: + break; + } + break; + + /* more here - symmetric, etc. */ + default: + break; + } + /* not implemented here */ + return false; +} + +#endif /* CRYPTKIT_CSP_ENABLE */ + + diff --git a/libsecurity_apple_csp/lib/cryptkitcsp.h b/libsecurity_apple_csp/lib/cryptkitcsp.h new file mode 100644 index 00000000..1494a8d4 --- /dev/null +++ b/libsecurity_apple_csp/lib/cryptkitcsp.h @@ -0,0 +1,59 @@ +/* + * 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. + */ + + +// +// cryptkitcsp.h - AlgorithmFactory for CryptKit CSP +// + +#ifdef CRYPTKIT_CSP_ENABLE + +#ifndef _H_CRYPTKITCSPLIB +#define _H_CRYPTKITCSPLIB + +#include +#include "AppleCSP.h" + +/* Can't include AppleCSPSession.h due to circular dependency */ +class AppleCSPSession; + +class CryptKitFactory : public AppleCSPAlgorithmFactory { +public: + CryptKitFactory(Allocator *normAlloc = NULL, Allocator *privAlloc = NULL); + ~CryptKitFactory(); + + bool setup( + AppleCSPSession &session, + CSPFullPluginSession::CSPContext * &cspCtx, + const Context &context); + + static void setNormAllocator(Allocator *alloc) + { assert(!normAllocator); normAllocator = alloc; } + static void setPrivAllocator(Allocator *alloc) + { assert(!privAllocator); privAllocator = alloc; } + + // memory allocators + static Allocator *normAllocator; + static Allocator *privAllocator; + +}; + +/* convenience for clients.... */ +#include "CryptKitSpace.h" + +#endif //_H_CRYPTKITCSPLIB +#endif /* CRYPTKIT_CSP_ENABLE */ diff --git a/libsecurity_apple_csp/lib/cspdebugging.c b/libsecurity_apple_csp/lib/cspdebugging.c new file mode 100644 index 00000000..bac414c5 --- /dev/null +++ b/libsecurity_apple_csp/lib/cspdebugging.c @@ -0,0 +1,83 @@ +/* + * 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: cspdebugging.c + + Contains: Debugging support. + + Written by: Doug Mitchell + + Copyright: (c) 1998 by Apple Computer, Inc., all rights reserved. + + Change History (most recent first): + + 03/10/98 dpm Created. + +*/ + +#include "cspdebugging.h" + +#if !LOG_VIA_PRINTF + +#include +#include +#include + +/* common log macros */ + +/* this one needs a writable string */ +static void logCom(unsigned char *str) { + c2pstr((char *)str); + DebugStr(str); +} + +/* remaining ones can take constant strings */ +void dblog0(char *str) { + Str255 outStr; + strcpy((char *)outStr, str); + logCom(outStr); +} + +void dblog1(char *str, void *arg1) { + Str255 outStr; + sprintf((char *)outStr, str, arg1); + logCom(outStr); +} + +void dblog2(char *str, void * arg1, void * arg2) { + Str255 outStr; + sprintf((char *)outStr, str, arg1, arg2); + logCom(outStr); +} + +void dblog3(char *str, void * arg1, void * arg2, void * arg3) { + Str255 outStr; + sprintf((char *)outStr, str, arg1, arg2, arg3); + logCom(outStr); +} + +void dblog4(char *str, void * arg1, void * arg2, void * arg3, void * arg4) { + Str255 outStr; + sprintf((char *)outStr, str, arg1, arg2, arg3, arg4); + logCom(outStr); +} + +#endif /* !LOG_VIA_PRINTF */ + +//int foobarSymbol; diff --git a/libsecurity_apple_csp/lib/cspdebugging.h b/libsecurity_apple_csp/lib/cspdebugging.h new file mode 100644 index 00000000..01e7e0dc --- /dev/null +++ b/libsecurity_apple_csp/lib/cspdebugging.h @@ -0,0 +1,161 @@ +/* + * 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: cspdebugging.h + + Contains: Debugging macros. + + Written by: Doug Mitchell + + Copyright: (c) 1998 by Apple Computer, Inc., all rights reserved. + + Change History (most recent first): + + 06/02/98 dpm Added DEBUG_THREAD_YIELD. + 03/10/98 dpm Created. + +*/ + +#ifndef _CSPDEBUGGING_H_ +#define _CSPDEBUGGING_H_ + +#ifdef NDEBUG +#define DEBUG_ENABLE 0 +#define ERROR_LOG_ENABLE 0 +#else +#define DEBUG_ENABLE 1 +#define ERROR_LOG_ENABLE 1 +#endif + +/* any other way? */ +#define LOG_VIA_PRINTF 1 + +#if DEBUG_ENABLE || ERROR_LOG_ENABLE + +#include +#include + +#if !LOG_VIA_PRINTF + +#error Hey, figure out a debug mechanism + +#include +#include +#include + +/* common log macros */ + +/* remaining ones can take constant strings */ + +#ifdef __cplusplus +extern "C" { +#endif + +extern void dblog0(char *str); +extern void dblog1(char *str, void * arg1); +extern void dblog2(char *str, void * arg1, void * arg2); +extern void dblog3(char *str, void * arg1, void * arg2, void * arg3); +extern void dblog4(char *str, void * arg1, void * arg2, void * arg3, void * arg4); + +#ifdef __cplusplus +} +#endif + + +#else /* LOG_VIA_PRINTF */ + +#define dblog0(str) printf(str) +#define dblog1(str, arg1) printf(str, arg1) +#define dblog2(str, arg1, arg2) printf(str, arg1, arg2) +#define dblog3(str, arg1, arg2, arg3) printf(str, arg1, arg2, arg3) +#define dblog4(str, arg1, arg2, arg3, arg4) printf(str, arg1, arg2, arg3, arg4) + +#endif /* LOG_VIA_PRINTF */ + +#else /* log macros disabled */ + +#define dblog0(str) +#define dblog1(str, arg1) +#define dblog2(str, arg1, arg2) +#define dblog3(str, arg1, arg2, arg3) +#define dblog4(str, arg1, arg2, arg3, arg4) + +#endif /* DEBUG_ENABLE || ERROR_LOG_ENABLE */ + +#if DEBUG_ENABLE + +#define dprintf0(str) dblog0(str) +#define dprintf1(str, arg1) dblog1(str, arg1) +#define dprintf2(str, arg1, arg2) dblog2(str, arg1, arg2) +#define dprintf3(str, arg1, arg2, arg3) dblog3(str, arg1, arg2, arg3) +#define dprintf4(str, arg1, arg2, arg3, arg4) dblog4(str, arg1, arg2, arg3, arg4) + +#ifdef __cplusplus +extern "C" { +#endif + +static inline void _panic(const char *str) +{ + printf("%s\n", str); + exit(1); +} + +#ifdef __cplusplus +} +#endif + +#define CASSERT(expression) \ + ((expression) ? (void)0 : \ + (dprintf1 ("Assertion failed: " #expression \ + ", file " __FILE__ ", line %d.\n", __LINE__), \ + _panic("Assertion Failure"))) + +#else /* DEBUG_ENABLE */ + +#define dprintf0(str) +#define dprintf1(str, arg1) +#define dprintf2(str, arg1, arg2) +#define dprintf3(str, arg1, arg2, arg3) +#define dprintf4(str, arg1, arg2, arg3, arg4) + +#define CASSERT(expression) + +#endif /* DEBUG_ENABLE */ + +/* + * Error logging. This may well be platform dependent. + */ +#if ERROR_LOG_ENABLE +#define errorLog0(str) dblog0(str); +#define errorLog1(str, arg1) dblog1(str, arg1) +#define errorLog2(str, arg1, arg2) dblog2(str, arg1, arg2) +#define errorLog3(str, arg1, arg2, arg3) dblog3(str, arg1, arg2, arg3) +#define errorLog4(str, arg1, arg2, arg3, arg4) dblog4(str, arg1, arg2, arg3, arg4) + +#else /* ERROR_LOG_ENABLE */ + +#define errorLog0(str) +#define errorLog1(str, arg1) +#define errorLog2(str, arg1, arg2) +#define errorLog3(str, arg1, arg2, arg3) +#define errorLog4(str, arg1, arg2, arg3, arg4) + +#endif /* ERROR_LOG_ENABLE */ + +#endif /* _CSPDEBUGGING_H_ */ diff --git a/libsecurity_apple_csp/lib/cssmplugin.exp b/libsecurity_apple_csp/lib/cssmplugin.exp new file mode 100644 index 00000000..f5046fbf --- /dev/null +++ b/libsecurity_apple_csp/lib/cssmplugin.exp @@ -0,0 +1,4 @@ +_CSSM_SPI_ModuleLoad +_CSSM_SPI_ModuleAttach +_CSSM_SPI_ModuleDetach +_CSSM_SPI_ModuleUnload diff --git a/libsecurity_apple_csp/lib/deriveKey.cpp b/libsecurity_apple_csp/lib/deriveKey.cpp new file mode 100644 index 00000000..6229c270 --- /dev/null +++ b/libsecurity_apple_csp/lib/deriveKey.cpp @@ -0,0 +1,436 @@ +/* + * 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: deriveKey.cpp + + Contains: CSSM_DeriveKey functions + + Copyright: (C) 2000 by Apple Computer, Inc., all rights reserved + + Written by: Doug Mitchell +*/ + +#include +#include +#include +#include +#include "AppleCSPSession.h" +#include "AppleCSPUtils.h" +#include "AppleCSPContext.h" +#include "cspdebugging.h" +#include +#include +#include "FEEAsymmetricContext.h" + +/* minimum legal values */ +#define PBKDF2_MIN_SALT 8 /* bytes */ +#define PBKDF2_MIN_ITER_CNT 1000 /* iteration count */ + +#define ALLOW_ZERO_PASSWORD 1 + +void AppleCSPSession::DeriveKey_PBKDF2( + const Context &context, + const CssmData &Param, + CSSM_DATA *keyData) +{ + /* validate algorithm-specific arguments */ + + /* Param must point to a CSSM_PKCS5_PBKDF2_PARAMS */ + if(Param.Length != sizeof(CSSM_PKCS5_PBKDF2_PARAMS)) { + errorLog0("DeriveKey_PBKDF2: Param wrong size\n"); + CssmError::throwMe(CSSMERR_CSP_INVALID_INPUT_POINTER); + } + const CSSM_PKCS5_PBKDF2_PARAMS *pbkdf2Params = + reinterpret_cast(Param.Data); + if(pbkdf2Params == NULL) { + errorLog0("DeriveKey_PBKDF2: null Param.Data\n"); + CssmError::throwMe(CSSMERR_CSP_INVALID_DATA); + } + + /* Get passphrase from either baseKey or from CSSM_PKCS5_PBKDF2_PARAMS */ + CssmKey *passKey = context.get(CSSM_ATTRIBUTE_KEY); + CSSM_SIZE passphraseLen = 0; + uint8 *passphrase = NULL; + if(passKey != NULL) { + AppleCSPContext::symmetricKeyBits(context, *this, + CSSM_ALGID_SECURE_PASSPHRASE, CSSM_KEYUSE_DERIVE, + passphrase, passphraseLen); + } + else { + passphraseLen = pbkdf2Params->Passphrase.Length; + passphrase = pbkdf2Params->Passphrase.Data; + } + + #if !ALLOW_ZERO_PASSWORD + /* passphrase required */ + if(passphrase == NULL) { + errorLog0("DeriveKey_PBKDF2: null Passphrase\n"); + CssmError::throwMe(CSSMERR_CSP_INVALID_DATA); + } + if(passphraseLen == 0) { + /* FIXME - enforce minimum length? */ + errorLog0("DeriveKey_PBKDF2: zero length passphrase\n"); + CssmError::throwMe(CSSMERR_CSP_INVALID_INPUT_POINTER); + } + #endif /* ALLOW_ZERO_PASSWORD */ + + if(pbkdf2Params->PseudoRandomFunction != + CSSM_PKCS5_PBKDF2_PRF_HMAC_SHA1) { + errorLog0("DeriveKey_PBKDF2: invalid PRF\n"); + CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM); + } + + /* salt, from context, required */ + CssmData salt = context.get(CSSM_ATTRIBUTE_SALT, + CSSMERR_CSP_MISSING_ATTR_SALT); + if((salt.Data == NULL) || (salt.Length < PBKDF2_MIN_SALT)){ + CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_SALT); + } + + /* iteration count, from context, required */ + uint32 iterCount = context.getInt(CSSM_ATTRIBUTE_ITERATION_COUNT, + CSSMERR_CSP_MISSING_ATTR_ITERATION_COUNT); + if(iterCount < PBKDF2_MIN_ITER_CNT) { + CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_ITERATION_COUNT); + } + + /* + * allocate a temp buffer, length + * = MAX (hLen, saltLen + 4) + 2 * hLen + * = MAX (kSHA1DigestSize, saltLen + 4) + 2 * kSHA1DigestSize + */ + uint32 tempLen = salt.Length + 4; + if(tempLen < kSHA1DigestSize) { + tempLen = kSHA1DigestSize; + } + tempLen += (2 * kSHA1DigestSize); + CSSM_DATA tempData = {0, NULL}; + setUpData(tempData, tempLen, privAllocator); + + /* go */ + pbkdf2 (hmacsha1, + kSHA1DigestSize, + passphrase, passphraseLen, + salt.Data, salt.Length, + iterCount, + keyData->Data, keyData->Length, + tempData.Data); + freeData(&tempData, privAllocator, false); +} + +/* + * PKCS5 v1.5 key derivation. Also used for traditional openssl key + * derivation, which is mighty similar to PKCS5 v1.5, with the addition + * of the ability to generate more than (keysize + ivsize) bytes. + */ +void AppleCSPSession::DeriveKey_PKCS5_V1_5( + const Context &context, + CSSM_ALGORITHMS algId, + const CssmData &Param, // IV optional, mallocd by app to indicate + // size + CSSM_DATA *keyData) // mallocd by caller to indicate size +{ + CSSM_DATA pwd = {0, NULL}; + + /* password from either Seed.Param or from base key */ + CssmCryptoData *cryptData = + context.get(CSSM_ATTRIBUTE_SEED); + if((cryptData != NULL) && (cryptData->Param.Length != 0)) { + pwd = cryptData->Param; + } + else { + /* Get secure passphrase from base key */ + CssmKey *passKey = context.get(CSSM_ATTRIBUTE_KEY); + if (passKey != NULL) { + AppleCSPContext::symmetricKeyBits(context, *this, + CSSM_ALGID_SECURE_PASSPHRASE, CSSM_KEYUSE_DERIVE, + pwd.Data, pwd.Length); + } + } + + if(pwd.Data == NULL) { + errorLog0("DeriveKey_PKCS5_V1_5: null Passphrase\n"); + CssmError::throwMe(CSSMERR_CSP_INVALID_DATA); + } + if(pwd.Length == 0) { + errorLog0("DeriveKey_PKCS5_V1_5: zero length passphrase\n"); + CssmError::throwMe(CSSMERR_CSP_INVALID_INPUT_POINTER); + } + + CSSM_ALGORITHMS hashAlg; + unsigned digestLen; + bool opensslAlg = false; + switch(algId) { + case CSSM_ALGID_PKCS5_PBKDF1_MD5: + hashAlg = CSSM_ALGID_MD5; + digestLen = kMD5DigestSize; + break; + case CSSM_ALGID_PKCS5_PBKDF1_MD2: + hashAlg = CSSM_ALGID_MD2; + digestLen = kMD2DigestSize; + break; + case CSSM_ALGID_PKCS5_PBKDF1_SHA1: + hashAlg = CSSM_ALGID_SHA1; + digestLen = kSHA1DigestSize; + break; + case CSSM_ALGID_PBE_OPENSSL_MD5: + hashAlg = CSSM_ALGID_MD5; + digestLen = kMD5DigestSize; + opensslAlg = true; + break; + default: + /* should not have been called */ + assert(0); + CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM); + } + + /* IV optional */ + CSSM_DATA iv = Param; + + /* total requested length can't exceed digest size for struct PKCS5 v1.5*/ + if(!opensslAlg && ((keyData->Length + iv.Length) > digestLen)) { + errorLog0("DeriveKey_PKCS5_V1_5: requested length larger than digest\n"); + CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_KEY_LENGTH); + } + + /* salt, from context, required */ + CssmData salt = context.get(CSSM_ATTRIBUTE_SALT, + CSSMERR_CSP_MISSING_ATTR_SALT); + if(salt.Data == NULL) { + CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_SALT); + } + + /* iteration count, from context, required */ + uint32 iterCount = context.getInt(CSSM_ATTRIBUTE_ITERATION_COUNT, + CSSMERR_CSP_MISSING_ATTR_ITERATION_COUNT); + + /* + * Apply the underlying hash function Hash for c iterations to + * the concatenation of the password P and the salt S, then + * extract the first dkLen octets to produce a derived key DK: + * + * T1 = Hash (P || S) , + * T2 = Hash (T1) , + * ... + * Tc = Hash (Tc-1) , + * DK = Tc<0..dkLen-1> . + */ + DigestCtx ctx; + uint8 *keyDataP = keyData->Data; + uint32 keyBytesToGo = keyData->Length; + uint8 *ivDataP = iv.Data; + uint32 ivBytesToGo = iv.Length; + bool looping = false; // true for additional bytes for openssl + unsigned char digestOut[kMaxDigestSize]; + + for(;;) { + /* this loop guaranteed to only run once if !opensslAlg */ + DigestCtxInit(&ctx, hashAlg); + + if(looping) { + /* openssl addition: re-digest the digest here */ + DigestCtxUpdate(&ctx, digestOut, digestLen); + } + + /* digest password then salt */ + DigestCtxUpdate(&ctx, pwd.Data, pwd.Length); + DigestCtxUpdate(&ctx, salt.Data, salt.Length); + + DigestCtxFinal(&ctx, digestOut); + + /* now iterCount-1 more iterations */ + for(unsigned dex=1; dex bytesAvail) ? bytesAvail : keyBytesToGo; + memmove(keyDataP, digestOut, toMove); + uint8 *remainder = digestOut + toMove; + bytesAvail -= toMove; + keyDataP += toMove; + keyBytesToGo -= toMove; + + /* then optionally some to IV */ + if(ivBytesToGo && bytesAvail) { + toMove = (ivBytesToGo > bytesAvail) ? bytesAvail : ivBytesToGo; + memmove(ivDataP, remainder, toMove); + ivDataP += toMove; + ivBytesToGo -= toMove; + } + if((keyBytesToGo == 0) && (ivBytesToGo == 0)) { + /* guaranteed true for PKCS5 v1.5 */ + break; + } + + assert(opensslAlg == true); + looping = true; + } + DigestCtxFree(&ctx); +} + +/* + * Member function initially declared for CSPAbstractPluginSession; + * we're overriding the null version in CSPFullPluginSession. + * + * We'll generate any type of key (for now). + */ +void AppleCSPSession::DeriveKey( + CSSM_CC_HANDLE CCHandle, + const Context &context, + CssmData &Param, + uint32 KeyUsage, + uint32 KeyAttr, + const CssmData *KeyLabel, + const CSSM_RESOURCE_CONTROL_CONTEXT *CredAndAclEntry, + CssmKey &DerivedKey) +{ + /* validate input args, common to all algorithms */ + switch(context.algorithm()) { + case CSSM_ALGID_PKCS5_PBKDF2: + case CSSM_ALGID_DH: + case CSSM_ALGID_PKCS12_PBE_ENCR: + case CSSM_ALGID_PKCS12_PBE_MAC: + case CSSM_ALGID_PKCS5_PBKDF1_MD5: + case CSSM_ALGID_PKCS5_PBKDF1_MD2: + case CSSM_ALGID_PKCS5_PBKDF1_SHA1: + case CSSM_ALGID_PBE_OPENSSL_MD5: + case CSSM_ALGID_OPENSSH1: + #if CRYPTKIT_CSP_ENABLE + case CSSM_ALGID_ECDH: + case CSSM_ALGID_ECDH_X963_KDF: + #endif + break; + /* maybe more here, later */ + default: + CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM); + } + DerivedKey.KeyData.Data = NULL; + DerivedKey.KeyData.Length = 0; + cspKeyStorage keyStorage = cspParseKeyAttr(CKT_Session, KeyAttr); + cspValidateKeyUsageBits(CKT_Session, KeyUsage); + + /* outgoing key type, required (though any algorithm is OK) */ + uint32 keyType = context.getInt(CSSM_ATTRIBUTE_KEY_TYPE, + CSSMERR_CSP_MISSING_ATTR_KEY_TYPE); + + /* outgoing key size, required - any nonzero value is OK */ + uint32 reqKeySize = context.getInt( + CSSM_ATTRIBUTE_KEY_LENGTH, + CSSMERR_CSP_MISSING_ATTR_KEY_LENGTH); + + /* cook up a place to put the key data */ + uint32 keySizeInBytes = (reqKeySize + 7) / 8; + SymmetricBinaryKey *binKey = NULL; + CSSM_DATA_PTR keyData = NULL; + + switch(keyStorage) { + case CKS_None: + /* no way */ + CssmError::throwMe(CSSMERR_CSP_INVALID_KEYATTR_MASK); + case CKS_Ref: + /* cook up a symmetric binary key */ + binKey = new SymmetricBinaryKey(reqKeySize); + keyData = &binKey->mKeyData; + break; + case CKS_Data: + /* key bytes --> caller's cssmKey */ + keyData = &DerivedKey.KeyData; + setUpData(*keyData, keySizeInBytes, + normAllocator); + break; + } + + /* break off to algorithm-specific code, whose job it is + * to fill in keyData->Data with keyData->Length bytes */ + switch(context.algorithm()) { + case CSSM_ALGID_PKCS5_PBKDF2: + DeriveKey_PBKDF2(context, + Param, + keyData); + break; + case CSSM_ALGID_DH: + DeriveKey_DH(context, + Param, + keyData, + *this); + break; + case CSSM_ALGID_PKCS12_PBE_ENCR: + case CSSM_ALGID_PKCS12_PBE_MAC: + DeriveKey_PKCS12(context, + *this, + Param, + keyData); + break; + case CSSM_ALGID_PKCS5_PBKDF1_MD5: + case CSSM_ALGID_PKCS5_PBKDF1_MD2: + case CSSM_ALGID_PKCS5_PBKDF1_SHA1: + case CSSM_ALGID_PBE_OPENSSL_MD5: + DeriveKey_PKCS5_V1_5(context, + context.algorithm(), + Param, + keyData); + break; + case CSSM_ALGID_OPENSSH1: + DeriveKey_OpenSSH1(context, + context.algorithm(), + Param, + keyData); + break; + #if CRYPTKIT_CSP_ENABLE + case CSSM_ALGID_ECDH: + case CSSM_ALGID_ECDH_X963_KDF: + CryptKit::DeriveKey_ECDH(context, + context.algorithm(), + Param, + keyData, + *this); + break; + #endif + /* maybe more here, later */ + default: + assert(0); + } + + /* set up outgoing header */ + KeyAttr &= ~KEY_ATTR_RETURN_MASK; + CSSM_KEYHEADER &hdr = DerivedKey.KeyHeader; + setKeyHeader(hdr, + plugin.myGuid(), + keyType, + CSSM_KEYCLASS_SESSION_KEY, + KeyAttr, + KeyUsage); + /* handle derived size < requested size, legal for Diffie-Hellman */ + hdr.LogicalKeySizeInBits = keyData->Length * 8; + + if(keyStorage == CKS_Ref) { + /* store and convert to ref key */ + addRefKey(*binKey, DerivedKey); + } + else { + /* Raw data */ + hdr.BlobType = CSSM_KEYBLOB_RAW; + hdr.Format = CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING; + } +} + diff --git a/libsecurity_apple_csp/lib/desContext.cpp b/libsecurity_apple_csp/lib/desContext.cpp new file mode 100644 index 00000000..6b546d29 --- /dev/null +++ b/libsecurity_apple_csp/lib/desContext.cpp @@ -0,0 +1,197 @@ +/* + * 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. + */ + + +/* + * desContext.cpp - glue between BlockCrytpor and DES implementation + * Written by Doug Mitchell 3/28/2001 + */ + +#include "desContext.h" +#include +#include +#include + +#define DESDebug(args...) secdebug("desContext", ## args) + +/* + * DES encrypt/decrypt. + */ +DESContext::DESContext(AppleCSPSession &session) : BlockCryptor(session), DesInst(NULL) +{ +} + +DESContext::~DESContext() +{ + if (DesInst != NULL) { + CCCryptorRelease(DesInst); + } + + DesInst = NULL; +} + +/* + * Standard CSPContext init, called from CSPFullPluginSession::init(). + * Reusable, e.g., query followed by en/decrypt. + */ +void DESContext::init( + const Context &context, + bool encrypting) +{ + CSSM_SIZE keyLen; + uint8 *keyData = NULL; + + /* obtain key from context */ + symmetricKeyBits(context, session(), CSSM_ALGID_DES, + encrypting ? CSSM_KEYUSE_ENCRYPT : CSSM_KEYUSE_DECRYPT, + keyData, keyLen); + if(keyLen != (DES_KEY_SIZE_BITS_EXTERNAL / 8)) { + CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_KEY); + } + + if (DesInst != NULL) + { + CCCryptorRelease(DesInst); + } + + (void) CCCryptorCreateWithMode(0, kCCModeECB, kCCAlgorithmDES, ccDefaultPadding, NULL, keyData, kCCKeySizeDES, NULL, 0, 0, 0, &DesInst); + + /* Finally, have BlockCryptor do its setup */ + setup(DES_BLOCK_SIZE_BYTES, context); +} + +/* + * Functions called by BlockCryptor + * DES does encrypt/decrypt in place + */ +void DESContext::encryptBlock( + const void *plainText, // length implied (one block) + size_t plainTextLen, + void *cipherText, + size_t &cipherTextLen, // in/out, throws on overflow + bool final) // ignored +{ + if(plainTextLen != DES_BLOCK_SIZE_BYTES) { + CssmError::throwMe(CSSMERR_CSP_INPUT_LENGTH_ERROR); + } + if(cipherTextLen < DES_BLOCK_SIZE_BYTES) { + CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR); + } + (void) CCCryptorEncryptDataBlock(DesInst, NULL, plainText, DES_BLOCK_SIZE_BYTES, cipherText); + cipherTextLen = DES_BLOCK_SIZE_BYTES; +} + +void DESContext::decryptBlock( + const void *cipherText, // length implied (one block) + size_t cipherTextLen, + void *plainText, + size_t &plainTextLen, // in/out, throws on overflow + bool final) // ignored +{ + if(plainTextLen < DES_BLOCK_SIZE_BYTES) { + CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR); + } + if(plainText != cipherText) { + /* little optimization for callers who want to decrypt in place */ + memmove(plainText, cipherText, DES_BLOCK_SIZE_BYTES); + } + (void) CCCryptorDecryptDataBlock(DesInst, NULL, cipherText, DES_BLOCK_SIZE_BYTES, plainText); + plainTextLen = DES_BLOCK_SIZE_BYTES; +} + +/*** + *** Triple-DES - EDE, 24-bit key only + ***/ + +DES3Context::DES3Context(AppleCSPSession &session) : BlockCryptor(session), DesInst(NULL) +{ +} + + + +DES3Context::~DES3Context() +{ + if (DesInst != NULL) { + CCCryptorRelease(DesInst); + } + + DesInst = NULL; +} + +/* + * Standard CSPContext init, called from CSPFullPluginSession::init(). + * Reusable, e.g., query followed by en/decrypt. + */ +void DES3Context::init( + const Context &context, + bool encrypting) +{ + CSSM_SIZE keyLen; + uint8 *keyData = NULL; + + /* obtain key from context */ + symmetricKeyBits(context, session(), CSSM_ALGID_3DES_3KEY_EDE, + encrypting ? CSSM_KEYUSE_ENCRYPT : CSSM_KEYUSE_DECRYPT, + keyData, keyLen); + if(keyLen != DES3_KEY_SIZE_BYTES) { + CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_KEY); + } + + if (DesInst != NULL) { + CCCryptorRelease(DesInst); + } + + (void) CCCryptorCreateWithMode(0, kCCModeECB, kCCAlgorithm3DES, ccDefaultPadding, NULL, keyData, kCCKeySize3DES, NULL, 0, 0, 0, &DesInst); + + /* Finally, have BlockCryptor do its setup */ + setup(DES3_BLOCK_SIZE_BYTES, context); +} + +/* + * Functions called by BlockCryptor + * DES does encrypt/decrypt in place + */ +void DES3Context::encryptBlock( + const void *plainText, // length implied (one block) + size_t plainTextLen, + void *cipherText, + size_t &cipherTextLen, // in/out, throws on overflow + bool final) // ignored +{ + if(plainTextLen != DES3_BLOCK_SIZE_BYTES) { + CssmError::throwMe(CSSMERR_CSP_INPUT_LENGTH_ERROR); + } + if(cipherTextLen < DES3_BLOCK_SIZE_BYTES) { + CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR); + } + (void) CCCryptorEncryptDataBlock(DesInst, NULL, plainText, DES3_BLOCK_SIZE_BYTES, cipherText); + cipherTextLen = DES3_BLOCK_SIZE_BYTES; +} + +void DES3Context::decryptBlock( + const void *cipherText, // length implied (one block) + size_t cipherTextLen, + void *plainText, + size_t &plainTextLen, // in/out, throws on overflow + bool final) // ignored +{ + if(plainTextLen < DES3_BLOCK_SIZE_BYTES) { + CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR); + } + (void) CCCryptorDecryptDataBlock(DesInst, NULL, cipherText, DES3_BLOCK_SIZE_BYTES, plainText); + plainTextLen = DES3_BLOCK_SIZE_BYTES; +} diff --git a/libsecurity_apple_csp/lib/desContext.h b/libsecurity_apple_csp/lib/desContext.h new file mode 100644 index 00000000..55158ab4 --- /dev/null +++ b/libsecurity_apple_csp/lib/desContext.h @@ -0,0 +1,95 @@ +/* + * 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. + */ + + +/* + * desContext.h - glue between BlockCrytpor and DES/3DES implementations + * Written by Doug Mitchell 3/28/2001 + */ +#ifndef _DES_CONTEXT_H_ +#define _DES_CONTEXT_H_ + +#include +#include "AppleCSP.h" +#include "AppleCSPContext.h" +#include "AppleCSPSession.h" +#include "BlockCryptor.h" +#include +#include "/usr/local/include/CommonCrypto/CommonCryptorSPI.h" + +#define DES_KEY_SIZE_BITS_EXTERNAL (kCCKeySizeDES * 8) +#define DES_BLOCK_SIZE_BYTES kCCBlockSizeDES + +/* DES Symmetric encryption context */ +class DESContext : public BlockCryptor { +public: + DESContext(AppleCSPSession &session); + virtual ~DESContext(); + + // called by CSPFullPluginSession + void init(const Context &context, bool encoding = true); + + // called by BlockCryptor + void encryptBlock( + const void *plainText, // length implied (one block) + size_t plainTextLen, + void *cipherText, + size_t &cipherTextLen, // in/out, throws on overflow + bool final); + void decryptBlock( + const void *cipherText, // length implied (one cipher block) + size_t cipherTextLen, + void *plainText, + size_t &plainTextLen, // in/out, throws on overflow + bool final); + +private: + CCCryptorRef DesInst; +}; /* DESContext */ + +/* Triple-DES (EDE, 24 byte key) Symmetric encryption context */ + +#define DES3_KEY_SIZE_BYTES (3 * (DES_KEY_SIZE_BITS_EXTERNAL / 8)) +#define DES3_BLOCK_SIZE_BYTES kCCBlockSize3DES + +class DES3Context : public BlockCryptor { +public: + DES3Context(AppleCSPSession &session); + ~DES3Context(); + + // called by CSPFullPluginSession + void init(const Context &context, bool encoding = true); + + // called by BlockCryptor + void encryptBlock( + const void *plainText, // length implied (one block) + size_t plainTextLen, + void *cipherText, + size_t &cipherTextLen, // in/out, throws on overflow + bool final); + void decryptBlock( + const void *cipherText, // length implied (one cipher block) + size_t cipherTextLen, + void *plainText, + size_t &plainTextLen, // in/out, throws on overflow + bool final); + +private: + CCCryptorRef DesInst; +}; /* DES3Context */ + +#endif //_DES_CONTEXT_H_ diff --git a/libsecurity_apple_csp/lib/gladmanContext.cpp b/libsecurity_apple_csp/lib/gladmanContext.cpp new file mode 100644 index 00000000..e08d927e --- /dev/null +++ b/libsecurity_apple_csp/lib/gladmanContext.cpp @@ -0,0 +1,173 @@ +/* + * 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. + */ + + +/* + * gladmanContext.cpp - glue between BlockCryptor and Gladman AES implementation + * Written by Doug Mitchell 12/12/2001 + */ + +#include "gladmanContext.h" +#include "cspdebugging.h" +#include + +/* + * AES encrypt/decrypt. + */ +GAESContext::GAESContext(AppleCSPSession &session) : + BlockCryptor(session), + mAesKey(NULL), + mInitFlag(false), + mRawKeySize(0), + mWasEncrypting(false) +{ + cbcCapable(false); + multiBlockCapable(false); +} + +GAESContext::~GAESContext() +{ + if(mAesKey) { + CCCryptorFinal(mAesKey,NULL,0,NULL); + CCCryptorRelease(mAesKey); + mAesKey = NULL; + } + + deleteKey(); + memset(mRawKey, 0, MAX_AES_KEY_BITS / 8); + mInitFlag = false; +} + +void GAESContext::deleteKey() +{ + mRawKeySize = 0; +} + +/* + * Standard CSPContext init, called from CSPFullPluginSession::init(). + * Reusable, e.g., query followed by en/decrypt. Even reusable after context + * changed (i.e., new IV in Encrypted File System). + */ +void GAESContext::init( + const Context &context, + bool encrypting) +{ + if(mInitFlag && !opStarted()) { + return; + } + + CSSM_SIZE keyLen; + uint8 *keyData = NULL; + bool sameKeySize = false; + + /* obtain key from context */ + symmetricKeyBits(context, session(), CSSM_ALGID_AES, + encrypting ? CSSM_KEYUSE_ENCRYPT : CSSM_KEYUSE_DECRYPT, + keyData, keyLen); + + switch(keyLen) { + case kCCKeySizeAES128: + case kCCKeySizeAES192: + case kCCKeySizeAES256: + break; + default: + CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_KEY); + } + + /* + * Delete existing key if key size changed + */ + if(mRawKeySize == keyLen) { + sameKeySize = true; + } + else { + deleteKey(); + } + + /* + * Init key only if key size or key bits have changed, or + * we're doing a different operation than the previous key + * was scheduled for. + */ + if(!sameKeySize || (mWasEncrypting != encrypting) || + memcmp(mRawKey, keyData, mRawKeySize)) { + (void) CCCryptorCreateWithMode(0, kCCModeECB, kCCAlgorithmAES128, ccDefaultPadding, NULL, keyData, keyLen, NULL, 0, 0, 0, &mAesKey); + + /* save this raw key data */ + memmove(mRawKey, keyData, keyLen); + mRawKeySize = keyLen; + mWasEncrypting = encrypting; + } + + /* we handle CBC, and hence the IV, ourselves */ + CSSM_ENCRYPT_MODE cssmMode = context.getInt(CSSM_ATTRIBUTE_MODE); + switch (cssmMode) { + /* no mode attr --> 0 == CSSM_ALGMODE_NONE, not currently supported */ + case CSSM_ALGMODE_CBCPadIV8: + case CSSM_ALGMODE_CBC_IV8: + { + CssmData *iv = context.get(CSSM_ATTRIBUTE_INIT_VECTOR); + if(iv == NULL) { + CssmError::throwMe(CSSMERR_CSP_MISSING_ATTR_INIT_VECTOR); + } + if(iv->Length != kCCBlockSizeAES128) { + CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_INIT_VECTOR); + } + } + break; + default: + break; + } + + /* Finally, have BlockCryptor do its setup */ + setup(GLADMAN_BLOCK_SIZE_BYTES, context); + mInitFlag = true; +} + +/* + * Functions called by BlockCryptor + * FIXME make this multi-block capabl3e + */ +void GAESContext::encryptBlock( + const void *plainText, // length implied (one block) + size_t plainTextLen, + void *cipherText, + size_t &cipherTextLen, // in/out, throws on overflow + bool final) // ignored +{ + if(cipherTextLen < plainTextLen) { + CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR); + } + (void) CCCryptorEncryptDataBlock(mAesKey, NULL, plainText, plainTextLen, cipherText); + + cipherTextLen = plainTextLen; +} + +void GAESContext::decryptBlock( + const void *cipherText, // length implied (one cipher block) + size_t cipherTextLen, + void *plainText, + size_t &plainTextLen, // in/out, throws on overflow + bool final) // ignored +{ + if(plainTextLen < cipherTextLen) { + CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR); + } + (void) CCCryptorDecryptDataBlock(mAesKey, NULL, cipherText, cipherTextLen, plainText); + plainTextLen = cipherTextLen; +} + diff --git a/libsecurity_apple_csp/lib/gladmanContext.h b/libsecurity_apple_csp/lib/gladmanContext.h new file mode 100644 index 00000000..48a9ba68 --- /dev/null +++ b/libsecurity_apple_csp/lib/gladmanContext.h @@ -0,0 +1,82 @@ +/* + * 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. + */ + + +// +// gladmanContext.h - Gladman AES context class +// +#ifndef _H_GLADMAN_CONTEXT +#define _H_GLADMAN_CONTEXT + +#include +#include "AppleCSP.h" +#include "AppleCSPContext.h" +#include "AppleCSPSession.h" +#include "BlockCryptor.h" +#include +#include "/usr/local/include/CommonCrypto/CommonCryptorSPI.h" +#include "aesCommon.h" + +#define GLADMAN_BLOCK_SIZE_BYTES DEFAULT_AES_BLOCK_BYTES + +/* Symmetric encryption context */ +class GAESContext : public BlockCryptor { +public: + GAESContext(AppleCSPSession &session); + virtual ~GAESContext(); + + // called by CSPFullPluginSession + void init(const Context &context, bool encoding = true); + + // As an optimization, we allow reuse of a modified context. The main thing + // we avoid is a redundant key scheduling. We save the current raw keys bits + // in mRawKey and compare on re-init. + bool changed(const Context &context) { return true; } + + // called by BlockCryptor + void encryptBlock( + const void *plainText, // length implied (one block) + size_t plainTextLen, + void *cipherText, + size_t &cipherTextLen, // in/out, throws on overflow + bool final); + void decryptBlock( + const void *cipherText, // length implied (one cipher block) + size_t cipherTextLen, + void *plainText, + size_t &plainTextLen, // in/out, throws on overflow + bool final); + +private: + void deleteKey(); + + /* scheduled key */ + CCCryptorRef mAesKey; + bool mInitFlag; // for easy reuse + + /* + * Raw key bits saved here and checked on re-init to avoid extra key + * schedule on re-init. We also have to do a new key schedule if + * changing between encrypting and decrypting since the key schedules + * differ for the two. + */ + uint8 mRawKey[MAX_AES_KEY_BITS / 8]; + uint32 mRawKeySize; + bool mWasEncrypting; +}; /* AESContext */ + +#endif //_H_GLADMAN_CONTEXT diff --git a/libsecurity_apple_csp/lib/memory.cpp b/libsecurity_apple_csp/lib/memory.cpp new file mode 100644 index 00000000..9de47bec --- /dev/null +++ b/libsecurity_apple_csp/lib/memory.cpp @@ -0,0 +1,53 @@ +/* + * 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. + */ + +#ifdef BSAFE_CSP_ENABLE + + +// +// memory - memory functions for BSafe +// +#include +#include +#include "bsafecspi.h" + + +// declared in bsafecspi.h.... +Allocator *BSafe::normAllocator; +Allocator *BSafe::privAllocator; + +// We use the private allocator for all BSAFE-alalocated memory. +// Memory allocated my BSAFE should never be visible by apps. + +POINTER CALL_CONV T_malloc (unsigned int size) +{ + return reinterpret_cast(BSafe::privAllocator->malloc(size)); +} + +POINTER CALL_CONV T_realloc (POINTER p, unsigned int size) +{ + POINTER result; + if ((result = (POINTER)BSafe::privAllocator->realloc(p, size)) == NULL_PTR) + free (p); + return (result); +} + +void CALL_CONV T_free (POINTER p) +{ + BSafe::privAllocator->free(p); +} +#endif /* BSAFE_CSP_ENABLE */ diff --git a/libsecurity_apple_csp/lib/miscAlgFactory.cpp b/libsecurity_apple_csp/lib/miscAlgFactory.cpp new file mode 100644 index 00000000..9ce82235 --- /dev/null +++ b/libsecurity_apple_csp/lib/miscAlgFactory.cpp @@ -0,0 +1,375 @@ +/* + * 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. + */ + + +// +// miscAlgFactory.h - miscellaneous algorithm factory +// Written by Doug Mitchell 3/28/2001 +// + +#include "miscAlgFactory.h" +#include +#include +#include "desContext.h" +#include "rc2Context.h" +#include "rc4Context.h" +#include "rc5Context.h" +#include "MacContext.h" +#include "DigestContext.h" +#include "SHA1_MD5_Object.h" /* raw digest */ +#include "SHA2_Object.h" +#include "MD2Object.h" +#include "NullCryptor.h" +#include "bfContext.h" +#include "castContext.h" +#include + +/* + * These #defines are mainly to facilitate measuring the performance of our own + * implementation vs. the ones in BSafe. This factory gets called first; if + * we disable e.g. DES here the BSAFE version will be used. + */ +#ifdef BSAFE_CSP_ENABLE + +#define MAF_DES_ENABLE 0 +#define MAF_DES3_ENABLE 0 +#define MAF_RC2_ENABLE 0 +#define MAF_RC4_ENABLE 0 +#define MAF_RC5_ENABLE 0 +#define MAF_MAC_ENABLE 0 + +#else /* !BSAFE_CSP_ENABLE, normal case */ + +#define MAF_DES_ENABLE 1 +#define MAF_DES3_ENABLE 1 +#define MAF_RC2_ENABLE 1 +#define MAF_RC4_ENABLE 1 +#define MAF_RC5_ENABLE 1 +#define MAF_MAC_ENABLE 1 + +#endif /* BSAFE_CSP_ENABLE */ + +#if (!MAF_DES_ENABLE || !MAF_DES3_ENABLE || !MAF_RC2_ENABLE || !MAF_RC4_ENABLE || \ + !MAF_RC5_ENABLE || !MAF_MAC_ENABLE) +#warning Internal DES/RC2/RC4/RC5/Mac implementation disabled! +#endif + +bool MiscAlgFactory::setup( + AppleCSPSession &session, + CSPFullPluginSession::CSPContext * &cspCtx, + const Context &context) +{ + CSSM_CONTEXT_TYPE ctype = context.type(); + CSSM_ALGORITHMS alg = context.algorithm(); + + switch(ctype) { + case CSSM_ALGCLASS_SYMMETRIC: + switch(alg) { + case CSSM_ALGID_AES: + if(cspCtx == NULL) { + /* + * Get optional block size to determine correct implementation + */ + uint32 blockSize = context.getInt(CSSM_ATTRIBUTE_BLOCK_SIZE); + if(blockSize == 0) { + blockSize = GLADMAN_BLOCK_SIZE_BYTES; + } + if(GLADMAN_AES_128_ENABLE && + (blockSize == GLADMAN_BLOCK_SIZE_BYTES)) { + cspCtx = new GAESContext(session); + } + else { + cspCtx = new AESContext(session); + } + } + return true; + + #if MAF_DES_ENABLE + case CSSM_ALGID_DES: + if(cspCtx == NULL) { + cspCtx = new DESContext(session); + } + return true; + #endif /* MAF_DES_ENABLE */ + + #if MAF_DES3_ENABLE + /* + * TripleDES: for some reason, cssmtype.h defines different symbols + * for CSSM_ALGID_3DES_3KEY (key gen) and CSSM_ALGID_3DES_3KEY_EDE + * (an encrypt alg with mode), but they define to the same value. + */ + case CSSM_ALGID_3DES_3KEY_EDE: + if(cspCtx == NULL) { + cspCtx = new DES3Context(session); + } + return true; + #endif + + #if MAF_RC2_ENABLE + case CSSM_ALGID_RC2: + if(cspCtx == NULL) { + cspCtx = new RC2Context(session); + } + return true; + #endif + + #if MAF_RC4_ENABLE + case CSSM_ALGID_RC4: + if(cspCtx == NULL) { + cspCtx = new RC4Context(session); + } + return true; + #endif + + #if MAF_RC5_ENABLE + case CSSM_ALGID_RC5: + if(cspCtx == NULL) { + cspCtx = new RC5Context(session); + } + return true; + #endif + + case CSSM_ALGID_BLOWFISH: + if(cspCtx == NULL) { + cspCtx = new BlowfishContext(session); + } + return true; + + case CSSM_ALGID_CAST: + case CSSM_ALGID_CAST5: + if(cspCtx == NULL) { + cspCtx = new CastContext(session); + } + return true; + + #if NULL_CRYPT_ENABLE + case CSSM_ALGID_NONE: + if(cspCtx == NULL) { + cspCtx = new NullCryptor(session); + } + return true; + #endif /* NULL_CRYPT_ENABLE */ + + default: + break; // not our symmetric alg + } // switch alg for symmetric + break; // from case CSSM_ALGCLASS_SYMMETRIC + + /* digest algorithms always enabled here */ + case CSSM_ALGCLASS_DIGEST: + switch(alg) { + case CSSM_ALGID_SHA1: + if(cspCtx == NULL) { + /* reuse is OK */ + cspCtx = new DigestContext(session, + *(new SHA1Object)); + } + return true; + case CSSM_ALGID_MD5: + if(cspCtx == NULL) { + /* reuse is OK */ + cspCtx = new DigestContext(session, + *(new MD5Object)); + } + return true; + case CSSM_ALGID_MD2: + if(cspCtx == NULL) { + /* reuse is OK */ + cspCtx = new DigestContext(session, + *(new MD2Object)); + } + return true; + case CSSM_ALGID_SHA224: + if(cspCtx == NULL) { + /* reuse is OK */ + cspCtx = new DigestContext(session, + *(new SHA224Object)); + } + return true; + case CSSM_ALGID_SHA256: + if(cspCtx == NULL) { + /* reuse is OK */ + cspCtx = new DigestContext(session, + *(new SHA256Object)); + } + return true; + case CSSM_ALGID_SHA384: + if(cspCtx == NULL) { + /* reuse is OK */ + cspCtx = new DigestContext(session, + *(new SHA384Object)); + } + return true; + case CSSM_ALGID_SHA512: + if(cspCtx == NULL) { + /* reuse is OK */ + cspCtx = new DigestContext(session, + *(new SHA512Object)); + } + return true; + default: + break; // not our digest alg + } // switch digest alg + break; // from case CSSM_ALGCLASS_DIGEST + + case CSSM_ALGCLASS_KEYGEN: + switch(alg) { + case CSSM_ALGID_AES: + if(cspCtx == NULL) { + cspCtx = new AESKeyGenContext(session); + } + return true; + + #if MAF_DES_ENABLE + case CSSM_ALGID_DES: + if(cspCtx == NULL) { + cspCtx = new AppleSymmKeyGenerator(session, + DES_KEY_SIZE_BITS_EXTERNAL, + DES_KEY_SIZE_BITS_EXTERNAL, + true); // must be byte size + } + return true; + #endif /* MAF_DES_ENABLE */ + + #if MAF_DES3_ENABLE + case CSSM_ALGID_3DES_3KEY_EDE: + if(cspCtx == NULL) { + cspCtx = new AppleSymmKeyGenerator(session, + DES3_KEY_SIZE_BYTES * 8, + DES3_KEY_SIZE_BYTES * 8, + true); // must be byte size + } + return true; + #endif + + #if MAF_RC2_ENABLE + case CSSM_ALGID_RC2: + if(cspCtx == NULL) { + cspCtx = new AppleSymmKeyGenerator(session, + RC2_MIN_KEY_SIZE_BYTES * 8, + RC2_MAX_KEY_SIZE_BYTES * 8, + true); // must be byte size + } + return true; + #endif + + #if MAF_RC4_ENABLE + case CSSM_ALGID_RC4: + if(cspCtx == NULL) { + cspCtx = new AppleSymmKeyGenerator(session, + kCCKeySizeMinRC4 * 8, + kCCKeySizeMaxRC4 * 8, + true); // must be byte size + } + return true; + #endif + + #if MAF_RC5_ENABLE + case CSSM_ALGID_RC5: + if(cspCtx == NULL) { + cspCtx = new AppleSymmKeyGenerator(session, + RC5_MIN_KEY_SIZE_BYTES * 8, + RC5_MAX_KEY_SIZE_BYTES * 8, + true); // must be byte size + } + return true; + #endif + + case CSSM_ALGID_BLOWFISH: + if(cspCtx == NULL) { + cspCtx = new AppleSymmKeyGenerator(session, + BF_MIN_KEY_SIZE_BYTES * 8, + BF_MAX_KEY_SIZE_BYTES * 8, + true); // must be byte size + } + return true; + + /* Note we require keys to be ALGID_CAST, not ALGID_CAST5 */ + case CSSM_ALGID_CAST: + if(cspCtx == NULL) { + cspCtx = new AppleSymmKeyGenerator(session, + kCCKeySizeMinCAST * 8, + kCCKeySizeMaxCAST * 8, + true); // must be byte size + } + return true; + + #if MAF_MAC_ENABLE + case CSSM_ALGID_SHA1HMAC: + if(cspCtx == NULL) { + cspCtx = new AppleSymmKeyGenerator(session, + HMAC_SHA_MIN_KEY_SIZE * 8, + HMAC_MAX_KEY_SIZE * 8, + true); // must be byte size + } + return true; + case CSSM_ALGID_MD5HMAC: + if(cspCtx == NULL) { + cspCtx = new AppleSymmKeyGenerator(session, + HMAC_MD5_MIN_KEY_SIZE * 8, + HMAC_MAX_KEY_SIZE * 8, + true); // must be byte size + } + return true; + #endif + + #if NULL_CRYPT_ENABLE + case CSSM_ALGID_NONE: + if(cspCtx == NULL) { + cspCtx = new AppleSymmKeyGenerator(session, + NULL_CRYPT_BLOCK_SIZE * 8, + NULL_CRYPT_BLOCK_SIZE * 8, + true); // must be byte size + } + return true; + #endif /* NULL_CRYPT_ENABLE */ + + default: + break; // not our keygen alg + } // switch alg for keygen + break; // from case CSSM_ALGCLASS_KEYGEN + + case CSSM_ALGCLASS_MAC: + switch(alg) { + #if MAF_MAC_ENABLE + case CSSM_ALGID_SHA1HMAC: + case CSSM_ALGID_MD5HMAC: + if(cspCtx == NULL) { + cspCtx = new MacContext(session, alg); + } + return true; + #endif + #if CRYPTKIT_CSP_ENABLE + case CSSM_ALGID_SHA1HMAC_LEGACY: + if(cspCtx == NULL) { + cspCtx = new MacLegacyContext(session, alg); + } + return true; + #endif + default: + /* not our mac alg */ + break; + } + break; + + default: + break; // not our context type + } // switch context type + + /* not ours */ + return false; +} diff --git a/libsecurity_apple_csp/lib/miscAlgFactory.h b/libsecurity_apple_csp/lib/miscAlgFactory.h new file mode 100644 index 00000000..6a0eec7a --- /dev/null +++ b/libsecurity_apple_csp/lib/miscAlgFactory.h @@ -0,0 +1,47 @@ +/* + * 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. + */ + + +// +// miscAlgFactory.h - miscellaneous algorithm factory +// Written by Doug Mitchell 3/28/2001 +// +#ifndef _MISC_ALG_FACTORY_H_ +#define _MISC_ALG_FACTORY_H_ + +#include +#include "AppleCSP.h" + +class AppleCSPSession; + +class MiscAlgFactory : public AppleCSPAlgorithmFactory { +public: + + MiscAlgFactory( + Allocator *normAlloc = NULL, + Allocator *privAlloc = NULL) + { } + ~MiscAlgFactory() { } + + bool setup( + AppleCSPSession &session, + CSPFullPluginSession::CSPContext * &cspCtx, + const Context &context); + +}; + +#endif //_MISC_ALG_FACTORY_H_ diff --git a/libsecurity_apple_csp/lib/miscalgorithms.cpp b/libsecurity_apple_csp/lib/miscalgorithms.cpp new file mode 100644 index 00000000..4934cf22 --- /dev/null +++ b/libsecurity_apple_csp/lib/miscalgorithms.cpp @@ -0,0 +1,152 @@ +/* + * 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. + */ + +#ifdef BSAFE_CSP_ENABLE + +// +// miscalgorithms - miscellaneous BSafe context creators and managers +// +#include "bsafecspi.h" + +#include // debug + + +// +// Digest algorithms. +// NOTE: There is no init() method, since BSafe digest algorithms re-initialize +// automatically and there is no directional difference. +// +BSafe::DigestContext::DigestContext( + AppleCSPSession &session, + const Context &, + B_INFO_TYPE bAlgInfo, + size_t sz) + : BSafeContext(session) +{ + mOutSize = sz; + inUpdate = B_DigestUpdate; + outFinal = B_DigestFinal; + setAlgorithm(bAlgInfo); + check(B_DigestInit(bsAlgorithm, bsKey, chooser(), bsSurrender)); + initialized = true; +} + + +// +// Signing/Verifying algorithms +// +// FIXME: +// We really should match the key algorithm to the sign/vfy +// algorithm. Also: verify key usage bits. +void BSafe::SigningContext::init( + const Context &context, + bool signing) +{ + if (reusing(signing)) + return; // all set to go + + setAlgorithm(algorithm, NULL); + setKeyFromContext(context); // may set outSize for some keys + + if (signing) { + check(B_SignInit(bsAlgorithm, bsKey, chooser(), bsSurrender)); + setRandom(); // needed by some signing algorithms + inUpdate = B_SignUpdate; + outFinalR = B_SignFinal; + outFinal = NULL; + } else { + check(B_VerifyInit(bsAlgorithm, bsKey, chooser(), bsSurrender)); + inUpdate = B_VerifyUpdate; + inFinalR = B_VerifyFinal; + inFinal = NULL; + } +} + + +// +// MAC algorithms. +// Note that BSafe treats MACs as digest algorithms - it has no MAC algorithm +// class. Thus, verifying consists of "digesting" followed by comparing the result. +// +// FIXME : what kind of key do we expect here? For now, any old +// symmetric key will work... +// +void BSafe::MacContext::init( + const Context &context, + bool signing) +{ + if (reusing(signing)) + return; // all set to go + + B_DIGEST_SPECIFIER digestSpec; + digestSpec.digestInfoType = algorithm; + digestSpec.digestInfoParams = NULL; + + setAlgorithm(AI_HMAC, &digestSpec); + setKeyFromContext(context); + check(B_DigestInit(bsAlgorithm, bsKey, chooser(), bsSurrender)); + + if (signing) { + inUpdate = B_DigestUpdate; + outFinal = B_DigestFinal; + } else { + inUpdate = B_DigestUpdate; + // need not set xxFinal - we override final(). + } +} + +void BSafe::MacContext::final(const CssmData &in) +{ + // we need to perform a DigestFinal step into a temp buffer and compare to 'in' + void *digest = normAllocator->malloc(in.length()); + unsigned int length; + check(B_DigestFinal(bsAlgorithm, POINTER(digest), &length, in.length(), bsSurrender)); + bool verified = length == in.length() && !memcmp(digest, in.data(), in.length()); + normAllocator->free(digest); + initialized = false; + if (!verified) + CssmError::throwMe(CSSMERR_CSP_VERIFY_FAILED); +} + + +// +// Random-number generation algorithms. +// Note that we don't use bsRandom, since that's our internal fixed "best to use" method, +// not the one the user asked for. +// NOTE: We freeze the output size at init(). +// +void BSafe::RandomContext::init(const Context &context, bool) +{ + reset(); // throw away, we need to re-seed anyway + setAlgorithm(algorithm, NULL); // MD5 generator mode (RSA proprietary) + check(B_RandomInit(bsAlgorithm, chooser(), bsSurrender)); + + // set/freeze output size + mOutSize = context.getInt(CSSM_ATTRIBUTE_OUTPUT_SIZE, CSSMERR_CSP_MISSING_ATTR_OUTPUT_SIZE); + + // seed the PRNG (if specified) + if (const CssmCryptoData *seed = context.get(CSSM_ATTRIBUTE_SEED)) { + const CssmData &seedValue = (*seed)(); + check(B_RandomUpdate(bsAlgorithm, POINTER(seedValue.data()), seedValue.length(), bsSurrender)); + } +} + +void BSafe::RandomContext::final(CssmData &data) +{ + check(B_GenerateRandomBytes(bsAlgorithm, POINTER(data.data()), mOutSize, bsSurrender)); +} +#endif /* BSAFE_CSP_ENABLE */ diff --git a/libsecurity_apple_csp/lib/opensshCoding.cpp b/libsecurity_apple_csp/lib/opensshCoding.cpp new file mode 100644 index 00000000..15bc177e --- /dev/null +++ b/libsecurity_apple_csp/lib/opensshCoding.cpp @@ -0,0 +1,683 @@ +/* + * 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@ + */ + + +/* + * opensshCoding.cpp - Encoding and decoding of OpenSSH format public keys. + * + * Created 8/29/2006 by dmitch. + */ + +#include "opensshCoding.h" +#include +#include +#include +#include + +#define SSH2_RSA_HEADER "ssh-rsa" +#define SSH2_DSA_HEADER "ssh-dss" + +#ifndef NDEBUG +#include +#define dprintf(s...) printf(s) +#else +#define dprintf(...) +#endif + +#pragma mark --- commmon code --- + +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)); +} + + +/* 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; +} + +/* write BIGNUM, OpenSSH v2 format (with a 4-byte byte count) */ +static CSSM_RETURN appendBigNum2( + CFMutableDataRef cfOut, + const BIGNUM *bn) +{ + if(bn == NULL) { + dprintf("appendBigNum2: NULL bn"); + return CSSMERR_CSP_INTERNAL_ERROR; + } + if (BN_is_zero(bn)) { + appendUint32(cfOut, 0); + return 0; + } + if(bn->neg) { + dprintf("appendBigNum2: negative numbers not supported\n"); + return CSSMERR_CSP_INTERNAL_ERROR; + } + 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 CSSMERR_CSP_INTERNAL_ERROR; + } + 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 CSSM_OK; +} + +/* 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-1 decimal (public key) version */ +static CSSM_RETURN appendBigNumDec( + CFMutableDataRef cfOut, + const BIGNUM *bn) +{ + char *buf = BN_bn2dec(bn); + if(buf == NULL) { + dprintf("appendBigNumDec: BN_bn2dec() error"); + return CSSMERR_CSP_INTERNAL_ERROR; + } + CFDataAppendBytes(cfOut, (const UInt8 *)buf, strlen(buf)); + Free(buf); + return CSSM_OK; +} + +/* 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; +} + + +/* + * Decode components from an SSHv2 public key. + * Also verifies the leading header, e.g. "ssh-rsa". + * The returned decodedBlob is algorithm-specific. + */ +static CSSM_RETURN 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 +{ + unsigned len = strlen(header); + *decodedBlob = NULL; + + /* ID string plus at least one space */ + if(keyLen < (len + 1)) { + dprintf("parseSSH2PubKey: short record(1)\n"); + return CSSMERR_CSP_INVALID_KEY; + } + + if(memcmp(header, key, len)) { + dprintf("parseSSH2PubKey: bad header (1)\n"); + return CSSMERR_CSP_INVALID_KEY; + } + key += len; + if(*key++ != ' ') { + dprintf("parseSSH2PubKey: bad header (2)\n"); + return CSSMERR_CSP_INVALID_KEY; + } + keyLen -= (len + 1); + + /* key points to first whitespace after header */ + skipWhite(key, keyLen); + if(keyLen == 0) { + dprintf("parseSSH2PubKey: short key\n"); + return CSSMERR_CSP_INVALID_KEY; + } + + /* 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 CSSMERR_CSP_INVALID_KEY; + } + + /* skip remainder; it's comment */ + + return CSSM_OK; +} + + +#pragma mark -- RSA OpenSSHv1 --- + +CSSM_RETURN RSAPublicKeyEncodeOpenSSH1( + RSA *rsa, + const CssmData &descData, + CssmOwnedData &encodedKey) +{ + CFMutableDataRef cfOut = CFDataCreateMutable(NULL, 0); + CSSM_RETURN ourRtn = CSSM_OK; + + /* + * Format is + * num_bits in decimal + * + * e, bignum in decimal + * + * n, bignum in decimal + * + * optional comment + * newline + */ + 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(ourRtn = appendBigNumDec(cfOut, rsa->e)) { + goto errOut; + } + CFDataAppendBytes(cfOut, &c, 1); + if(ourRtn = appendBigNumDec(cfOut, rsa->n)) { + goto errOut; + } + + if(descData.Length) { + /* optional comment */ + CFDataAppendBytes(cfOut, &c, 1); + CFDataAppendBytes(cfOut, (UInt8 *)descData.Data, descData.Length); + } + + c = '\n'; + CFDataAppendBytes(cfOut, &c, 1); + encodedKey.copy(CFDataGetBytePtr(cfOut), CFDataGetLength(cfOut)); +errOut: + CFRelease(cfOut); + return ourRtn; +} + +CSSM_RETURN RSAPublicKeyDecodeOpenSSH1( + RSA *rsa, + void *p, + size_t length) +{ + const unsigned char *cp = (const unsigned char *)p; + unsigned remLen = length; + + 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("RSAPublicKeyDecodeOpenSSH1: short key (1)\n"); + return CSSMERR_CSP_INVALID_KEY; + } + skipWhite(cp, remLen); + if(remLen == 0) { + dprintf("RSAPublicKeyDecodeOpenSSH1: short key (2)\n"); + return CSSMERR_CSP_INVALID_KEY; + } + + /* + * cp points to start of e + */ + const unsigned char *ep = findNextWhite(cp, remLen); + if(remLen == 0) { + dprintf("RSAPublicKeyDecodeOpenSSH1: short key (3)\n"); + return CSSMERR_CSP_INVALID_KEY; + } + unsigned len = ep - cp; + rsa->e = parseDecimalBn(cp, len); + if(rsa->e == NULL) { + return CSSMERR_CSP_INVALID_KEY; + } + cp += len; + + skipWhite(cp, remLen); + if(remLen == 0) { + dprintf("RSAPublicKeyDecodeOpenSSH1: 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 CSSMERR_CSP_INVALID_KEY; + } + + /* remainder is comment, we ignore */ + return CSSM_OK; + +} + +CSSM_RETURN RSAPrivateKeyEncodeOpenSSH1( + RSA *rsa, + const CssmData &descData, + CssmOwnedData &encodedKey) +{ + CFDataRef cfOut; + CSSM_RETURN ourRtn; + + ourRtn = encodeOpenSSHv1PrivKey(rsa, descData.Data, descData.Length, NULL, &cfOut); + if(ourRtn) { + return ourRtn; + } + encodedKey.copy(CFDataGetBytePtr(cfOut), CFDataGetLength(cfOut)); + CFRelease(cfOut); + return CSSM_OK; +} + +extern CSSM_RETURN RSAPrivateKeyDecodeOpenSSH1( + RSA *openKey, + void *p, + size_t length) +{ + return decodeOpenSSHv1PrivKey((const unsigned char *)p, length, + openKey, NULL, NULL, NULL); +} + +#pragma mark -- RSA OpenSSHv2 --- + +CSSM_RETURN RSAPublicKeyEncodeOpenSSH2( + RSA *rsa, + const CssmData &descData, + CssmOwnedData &encodedKey) +{ + 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); + CSSM_RETURN ourRtn = CSSM_OK; + appendString(cfOut, SSH2_RSA_HEADER, strlen(SSH2_RSA_HEADER)); + if(ourRtn = appendBigNum2(cfOut, rsa->e)) { + goto errOut; + } + if(ourRtn = appendBigNum2(cfOut, rsa->n)) { + 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); + + if(descData.Length) { + /* optional comment */ + CFDataAppendBytes(cfOut, &c, 1); + CFDataAppendBytes(cfOut, (UInt8 *)descData.Data, descData.Length); + } + + /* finish it with a newline */ + c = '\n'; + CFDataAppendBytes(cfOut, &c, 1); + + encodedKey.copy(CFDataGetBytePtr(cfOut), CFDataGetLength(cfOut)); +errOut: + CFRelease(cfOut); + if(b64) { + free(b64); + } + return ourRtn; +} + +CSSM_RETURN RSAPublicKeyDecodeOpenSSH2( + RSA *rsa, + void *p, + size_t length) +{ + const unsigned char *key = (const unsigned char *)p; + unsigned keyLen = length; + CSSM_RETURN ourRtn; + + /* + * Verify header + * get base64-decoded blob + */ + unsigned char *decodedBlob = NULL; + unsigned decodedBlobLen = 0; + if(ourRtn = parseSSH2PubKey(key, keyLen, SSH2_RSA_HEADER, &decodedBlob, &decodedBlobLen)) { + return ourRtn; + } + /* subsequent errors to errOut: */ + + /* + * The inner base64-decoded blob, consisting of + * ssh-rsa + * e + * n + */ + uint32_t decLen; + unsigned len; + + key = decodedBlob; + keyLen = decodedBlobLen; + if(keyLen < 12) { + /* three length fields at least */ + dprintf("RSAPublicKeyDecodeOpenSSH2: short record(2)\n"); + ourRtn = -1; + goto errOut; + } + decLen = readUint32(key, keyLen); + len = strlen(SSH2_RSA_HEADER); + if(decLen != len) { + dprintf("RSAPublicKeyDecodeOpenSSH2: bad header (2)\n"); + ourRtn = CSSMERR_CSP_INVALID_KEY; + goto errOut; + } + if(memcmp(SSH2_RSA_HEADER, key, len)) { + dprintf("RSAPublicKeyDecodeOpenSSH2: bad header (1)\n"); + return CSSMERR_CSP_INVALID_KEY; + } + key += len; + keyLen -= len; + + rsa->e = readBigNum2(key, keyLen); + if(rsa->e == NULL) { + ourRtn = CSSMERR_CSP_INVALID_KEY; + goto errOut; + } + rsa->n = readBigNum2(key, keyLen); + if(rsa->n == NULL) { + ourRtn = CSSMERR_CSP_INVALID_KEY; + goto errOut; + } + +errOut: + free(decodedBlob); + return ourRtn; +} + +#pragma mark -- DSA OpenSSHv2 --- + +CSSM_RETURN DSAPublicKeyEncodeOpenSSH2( + DSA *dsa, + const CssmData &descData, + CssmOwnedData &encodedKey) +{ + 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)); + if(ourRtn = appendBigNum2(cfOut, dsa->p)) { + goto errOut; + } + if(ourRtn = appendBigNum2(cfOut, dsa->q)) { + goto errOut; + } + if(ourRtn = appendBigNum2(cfOut, dsa->g)) { + goto errOut; + } + if(ourRtn = appendBigNum2(cfOut, dsa->pub_key)) { + 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); + + if(descData.Length) { + /* optional comment */ + CFDataAppendBytes(cfOut, &c, 1); + CFDataAppendBytes(cfOut, (UInt8 *)descData.Data, descData.Length); + } + + /* finish it with a newline */ + c = '\n'; + CFDataAppendBytes(cfOut, &c, 1); + + encodedKey.copy(CFDataGetBytePtr(cfOut), CFDataGetLength(cfOut)); + +errOut: + CFRelease(cfOut); + if(b64) { + free(b64); + } + return ourRtn; +} + +CSSM_RETURN DSAPublicKeyDecodeOpenSSH2( + DSA *dsa, + void *p, + size_t length) +{ + const unsigned char *key = (const unsigned char *)p; + unsigned keyLen = length; + CSSM_RETURN ourRtn; + + /* + * Verify header + * get base64-decoded blob + */ + unsigned char *decodedBlob = NULL; + unsigned decodedBlobLen = 0; + if(ourRtn = parseSSH2PubKey(key, keyLen, SSH2_DSA_HEADER, &decodedBlob, &decodedBlobLen)) { + return ourRtn; + } + /* subsequent errors to errOut: */ + + /* + * The inner base64-decoded blob, consisting of + * ssh-dss + * p + * q + * g + * pub_key + */ + uint32_t decLen; + unsigned len; + + key = decodedBlob; + keyLen = decodedBlobLen; + if(keyLen < 20) { + /* five length fields at least */ + dprintf("DSAPublicKeyDecodeOpenSSH2: short record(2)\n"); + ourRtn = CSSMERR_CSP_INVALID_KEY; + goto errOut; + } + decLen = readUint32(key, keyLen); + len = strlen(SSH2_DSA_HEADER); + if(decLen != len) { + dprintf("DSAPublicKeyDecodeOpenSSH2: bad header (2)\n"); + ourRtn = CSSMERR_CSP_INVALID_KEY; + goto errOut; + } + if(memcmp(SSH2_DSA_HEADER, key, len)) { + dprintf("DSAPublicKeyDecodeOpenSSH2: bad header (1)\n"); + return CSSMERR_CSP_INVALID_KEY; + } + key += len; + keyLen -= len; + + dsa->p = readBigNum2(key, keyLen); + if(dsa->p == NULL) { + ourRtn = CSSMERR_CSP_INVALID_KEY; + goto errOut; + } + dsa->q = readBigNum2(key, keyLen); + if(dsa->q == NULL) { + ourRtn = CSSMERR_CSP_INVALID_KEY; + goto errOut; + } + dsa->g = readBigNum2(key, keyLen); + if(dsa->g == NULL) { + ourRtn = CSSMERR_CSP_INVALID_KEY; + goto errOut; + } + dsa->pub_key = readBigNum2(key, keyLen); + if(dsa->pub_key == NULL) { + ourRtn = CSSMERR_CSP_INVALID_KEY; + goto errOut; + } + +errOut: + free(decodedBlob); + return ourRtn; + +} + diff --git a/libsecurity_apple_csp/lib/opensshCoding.h b/libsecurity_apple_csp/lib/opensshCoding.h new file mode 100644 index 00000000..61d4f76c --- /dev/null +++ b/libsecurity_apple_csp/lib/opensshCoding.h @@ -0,0 +1,112 @@ +/* + * 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@ + */ + +/* + * opensshCoding.h - Encoding and decoding of OpenSSH format public keys. + * + * Created 8/29/2006 by dmitch. + */ + +#ifndef _OPENSSH_CODING_H_ +#define _OPENSSH_CODING_H_ + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +void appendUint32( + CFMutableDataRef cfOut, + uint32_t ui); +uint32_t readUint32( + const unsigned char *&cp, // IN/OUT + unsigned &len); // IN/OUT + +extern CSSM_RETURN RSAPublicKeyEncodeOpenSSH1( + RSA *openKey, + const CssmData &descData, + CssmOwnedData &encodedKey); + +extern CSSM_RETURN RSAPublicKeyDecodeOpenSSH1( + RSA *openKey, + void *p, + size_t length); + +extern CSSM_RETURN RSAPrivateKeyEncodeOpenSSH1( + RSA *openKey, + const CssmData &descData, + CssmOwnedData &encodedKey); + +extern CSSM_RETURN RSAPrivateKeyDecodeOpenSSH1( + RSA *openKey, + void *p, + size_t length); + +extern CSSM_RETURN RSAPublicKeyEncodeOpenSSH2( + RSA *openKey, + const CssmData &descData, + CssmOwnedData &encodedKey); + +extern CSSM_RETURN RSAPublicKeyDecodeOpenSSH2( + RSA *openKey, + void *p, + size_t length); + +extern CSSM_RETURN DSAPublicKeyEncodeOpenSSH2( + DSA *openKey, + const CssmData &descData, + CssmOwnedData &encodedKey); + +extern CSSM_RETURN DSAPublicKeyDecodeOpenSSH2( + DSA *openKey, + void *p, + size_t length); + +/* In opensshWrap.cpp */ + +/* Encode OpenSSHv1 private key, with or without encryption */ +extern CSSM_RETURN encodeOpenSSHv1PrivKey( + RSA *r, + const uint8 *comment, /* optional */ + unsigned commentLen, + const uint8 *encryptKey, /* optional; if present, it's 16 bytes of MD5(password) */ + CFDataRef *encodedKey); /* RETURNED */ + +extern CSSM_RETURN decodeOpenSSHv1PrivKey( + const unsigned char *encodedKey, + unsigned encodedKeyLen, + RSA *r, + const uint8 *decryptKey, /* optional; if present, it's 16 bytes of MD5(password) */ + uint8 **comment, /* mallocd and RETURNED */ + unsigned *commentLen); /* RETURNED */ + +#ifdef __cplusplus +} +#endif + +#endif /* _OPENSSH_CODING_H_ */ diff --git a/libsecurity_apple_csp/lib/opensshWrap.cpp b/libsecurity_apple_csp/lib/opensshWrap.cpp new file mode 100644 index 00000000..9338d52b --- /dev/null +++ b/libsecurity_apple_csp/lib/opensshWrap.cpp @@ -0,0 +1,728 @@ +/* + * 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@ + */ + +/* + * opensshCoding.h - Encoding and decoding of OpenSSH format public keys. + * + * Created 8/29/2006 by dmitch. + */ + +#include "AppleCSPSession.h" +#include "AppleCSPContext.h" +#include "AppleCSPUtils.h" +#include "AppleCSPKeys.h" +#include "RSA_DSA_Keys.h" +#include "opensshCoding.h" +#include "cspdebugging.h" +#include +#include +#include +#include +#include + +static const char *authfile_id_string = "SSH PRIVATE KEY FILE FORMAT 1.1\n"; + +/* default comment on encode if app doesn't provide DescriptiveData */ +#define OPENSSH1_COMMENT "Encoded by Mac OS X Security.framework" + +/* 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 + +#pragma mark --- utilities --- + +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)); +} + +static uint16_t readUint16( + const unsigned char *&cp, // IN/OUT + unsigned &len) // IN/OUT +{ + uint16_t r = *cp++; + r <<= 8; + r |= *cp++; + len -= 2; + return r; +} + +/* Write BIGNUM, OpenSSH-1 version */ +static CSSM_RETURN 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) { + errorLog0("appendBigNum: BN_bn2bin() screwup\n"); + return CSSMERR_CSP_INTERNAL_ERROR; + } + CFDataAppendBytes(cfOut, (UInt8 *)outBytes, numBytes); + return CSSM_OK; +} + +/* Read BIGNUM, OpenSSH-1 version */ +static BIGNUM *readBigNum( + const unsigned char *&cp, // IN/OUT + unsigned &remLen) // IN/OUT +{ + if(remLen < sizeof(uint16_t)) { + errorLog0("readBigNum: short record(1)\n"); + return NULL; + } + uint16_t numBits = readUint16(cp, remLen); + unsigned bytes = (numBits + 7) / 8; + if(remLen < bytes) { + errorLog0("readBigNum: short record(2)\n"); + return NULL; + } + BIGNUM *bn = BN_bin2bn(cp, bytes, NULL); + if(bn == NULL) { + errorLog0("readBigNum: BN_bin2bn error\n"); + return NULL; + } + cp += bytes; + remLen -= bytes; + return bn; +} + +/* + * Calculate d mod{p-1,q-1} + * Used when decoding OpenSSH-1 private RSA key. + */ +static CSSM_RETURN rsa_generate_additional_parameters(RSA *rsa) +{ + BIGNUM *aux; + BN_CTX *ctx; + + if((rsa->dmq1 = BN_new()) == NULL) { + errorLog0("rsa_generate_additional_parameters: BN_new failed"); + return CSSMERR_CSP_INTERNAL_ERROR; + } + if((rsa->dmp1 = BN_new()) == NULL) { + errorLog0("rsa_generate_additional_parameters: BN_new failed"); + return CSSMERR_CSP_INTERNAL_ERROR; + } + if ((aux = BN_new()) == NULL) { + errorLog0("rsa_generate_additional_parameters: BN_new failed"); + return CSSMERR_CSP_INTERNAL_ERROR; + } + if ((ctx = BN_CTX_new()) == NULL) { + errorLog0("rsa_generate_additional_parameters: BN_CTX_new failed"); + BN_clear_free(aux); + return CSSMERR_CSP_INTERNAL_ERROR; + } + + 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 CSSM_OK; +} + +#pragma mark --- encrypt/decrypt --- + +/* + * Encrypt/decrypt the secret portion of an OpenSSHv1 format RSA private key. + */ +static CSSM_RETURN ssh1DES3Crypt( + unsigned char cipher, + bool doEncrypt, + const unsigned char *inText, + unsigned inTextLen, + const uint8 *key, // MD5(password) + CSSM_SIZE keyLen, + 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 CSSM_OK; + default: + /* who knows how we're going to figure these out */ + errorLog1("***ssh1DES3Crypt: Unsupported cipher (%u)\n", cipher); + return CSSMERR_CSP_INVALID_KEY; + } + + if(keyLen != CC_MD5_DIGEST_LENGTH) { + errorLog0("ssh1DES3Crypt: bad key length\n"); + return CSSMERR_CSP_INVALID_KEY; + } + + /* three keys from that, like so: */ + unsigned char k1[kCCKeySizeDES]; + unsigned char k2[kCCKeySizeDES]; + unsigned char k3[kCCKeySizeDES]; + memmove(k1, key, kCCKeySizeDES); + memmove(k2, key + kCCKeySizeDES, kCCKeySizeDES); + memmove(k3, key, 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) { + /* should never happen */ + errorLog1("***ssh1DES3Crypt: CCCrypt()(1) returned %u\n", (unsigned)cstat); + return CSSMERR_CSP_INTERNAL_ERROR; + } + cstat = CCCrypt(op2, kCCAlgorithmDES, + 0, // no padding - SSH does that itself + k2, kCCKeySizeDES, + NULL, // IV + outText, moved, + outText, inTextLen, &moved); + if(cstat) { + errorLog1("***ssh1DES3Crypt: CCCrypt()(2) returned %u\n", (unsigned)cstat); + return CSSMERR_CSP_INTERNAL_ERROR; + } + cstat = CCCrypt(op1_3, kCCAlgorithmDES, + 0, // no padding - SSH does that itself + k3, kCCKeySizeDES, + NULL, // IV + outText, moved, + outText, inTextLen, &moved); + if(cstat) { + errorLog1("***ssh1DES3Crypt: CCCrypt()(3) returned %u\n", (unsigned)cstat); + return CSSMERR_CSP_INTERNAL_ERROR; + } + + *outTextLen = moved; + return CSSM_OK; +} + +#pragma mark --- DeriveKey --- + +/* + * Key derivation for OpenSSH1 private key wrap/unwrap. + * This is pretty trivial, it's just an MD5() operation. The main + * purpose for doing this in a DeriveKey operation is to enable the + * use of either Secure Passphrases, obtained by securityd/SecurityAgent, + * or app-specified data. + */ +void AppleCSPSession::DeriveKey_OpenSSH1( + const Context &context, + CSSM_ALGORITHMS algId, + const CssmData &Param, // IV optional, mallocd by app to indicate + // size + CSSM_DATA *keyData) // mallocd by caller to indicate size - must be + // size of MD5 digest! +{ + CSSM_DATA pwd = {0, NULL}; + + if(keyData->Length != CC_MD5_DIGEST_LENGTH) { + errorLog0("DeriveKey_OpenSSH1: invalid key length\n"); + CssmError::throwMe(CSSMERR_CSP_UNSUPPORTED_KEY_SIZE); + } + + /* password from either Seed.Param or from base key */ + CssmCryptoData *cryptData = + context.get(CSSM_ATTRIBUTE_SEED); + if((cryptData != NULL) && (cryptData->Param.Length != 0)) { + pwd = cryptData->Param; + } + else { + /* Get secure passphrase from base key */ + CssmKey *passKey = context.get(CSSM_ATTRIBUTE_KEY); + if (passKey != NULL) { + AppleCSPContext::symmetricKeyBits(context, *this, + CSSM_ALGID_SECURE_PASSPHRASE, CSSM_KEYUSE_DERIVE, + pwd.Data, pwd.Length); + } + } + + if(pwd.Data == NULL) { + errorLog0("DeriveKey_PKCS5_V1_5: null Passphrase\n"); + CssmError::throwMe(CSSMERR_CSP_INVALID_DATA); + } + if(pwd.Length == 0) { + errorLog0("DeriveKey_PKCS5_V1_5: zero length passphrase\n"); + CssmError::throwMe(CSSMERR_CSP_INVALID_INPUT_POINTER); + } + + /* here it is */ + CC_MD5(pwd.Data, pwd.Length, keyData->Data); + +} + +#pragma mark --- Encode/Wrap OpenSSHv1 private key --- + +/* + * Encode OpenSSHv1 private key, with or without encryption. + * This used for generating key blobs of format CSSM_KEYBLOB_RAW_FORMAT_OPENSSH + * as well as wrapping keys in format CSSM_KEYBLOB_WRAPPED_FORMAT_OPENSSH1. + */ +CSSM_RETURN encodeOpenSSHv1PrivKey( + RSA *rsa, + const uint8 *comment, /* optional */ + unsigned commentLen, + const uint8 *encryptKey, /* optional; if present, it's 16 bytes of MD5(password) */ + CFDataRef *encodedKey) /* RETURNED */ +{ + CFMutableDataRef cfOut = CFDataCreateMutable(NULL, 0); + CSSM_RETURN ourRtn = CSSM_OK; + + /* ID string including NULL */ + CFDataAppendBytes(cfOut, (const UInt8 *)authfile_id_string, strlen(authfile_id_string) + 1); + + /* one byte cipher */ + UInt8 cipherSpec = encryptKey ? SSH_CIPHER_3DES : SSH_CIPHER_NONE; + 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. + * The format appears to require this, or else we wouldn't know + * when we've got to the ciphertext on decode. + */ + if((comment == NULL) || (commentLen == 0)) { + comment = (const UInt8 *)OPENSSH1_COMMENT; + commentLen = strlen(OPENSSH1_COMMENT); + } + appendUint32(cfOut, commentLen); + CFDataAppendBytes(cfOut, comment, commentLen); + + /* + * 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); + + /* pad to block boundary */ + unsigned ptextLen = CFDataGetLength(ptext); + unsigned padding = 0; + unsigned rem = ptextLen & 0x7; + if(rem) { + padding = 8 - rem; + } + UInt8 padByte = 0; + for(unsigned dex=0; dex(unwrappedBinKey); + RSA *rsa = rPubBinKey.mRsaKey; + CASSERT(rsa != NULL); + + /* + * Get the raw password bits from the wrapping key. + * Our caller verified that the context has a symmetric key; this call + * ensures that the key is of algorithm CSSM_ALGID_OPENSSH1. + * Key length 0 means no encryption. + */ + CSSM_SIZE wrappingKeyLen = 0; + uint8 *wrappingKey = NULL; + + AppleCSPContext::symmetricKeyBits(context, *this, + CSSM_ALGID_OPENSSH1, CSSM_KEYUSE_WRAP, + wrappingKey, wrappingKeyLen); + if(wrappingKeyLen != CC_MD5_DIGEST_LENGTH) { + errorLog0("AppleCSPSession::WrapKeyOpenSSH1: bad wrapping key length\n"); + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY); + } + + CFDataRef cfOut = NULL; + + /* + * Optional comment string from DescriptiveData. + */ + const UInt8 *comment = NULL; + unsigned commentLen = 0; + if((DescriptiveData != NULL) && (DescriptiveData->Length != 0)) { + comment = (const UInt8 *)DescriptiveData->Data; + commentLen = DescriptiveData->Length; + } + + /* generate the encrypted blob */ + CSSM_RETURN crtn = encodeOpenSSHv1PrivKey(rsa, comment, commentLen, wrappingKey, &cfOut); + if(crtn) { + CssmError::throwMe(crtn); + } + + /* allocate key data in session's memory space */ + unsigned len = CFDataGetLength(cfOut); + setUpData(WrappedKey.KeyData, len, normAllocator); + memmove(WrappedKey.KeyData.Data, CFDataGetBytePtr(cfOut), len); + CFRelease(cfOut); + + /* outgoing header */ + WrappedKey.KeyHeader.BlobType = CSSM_KEYBLOB_WRAPPED; + // OK to be zero or not present + WrappedKey.KeyHeader.WrapMode = CSSM_ALGMODE_NONE; + WrappedKey.KeyHeader.Format = CSSM_KEYBLOB_WRAPPED_FORMAT_OPENSSH1; +} + +#pragma mark --- Decode/Unwrap OpenSSHv1 private key --- + +/* + * Decode OpenSSHv1 private, optionally decrypting the secret portion. + * This used for decoding key blobs of format CSSM_KEYBLOB_RAW_FORMAT_OPENSSH + * as well as unwrapping keys in format CSSM_KEYBLOB_WRAPPED_FORMAT_OPENSSH1. + */ +CSSM_RETURN decodeOpenSSHv1PrivKey( + const unsigned char *encodedKey, + unsigned encodedKeyLen, + RSA *rsa, + const uint8 *decryptKey, /* optional; if present, it's 16 bytes of MD5(password) */ + uint8 **comment, /* optional, mallocd and RETURNED */ + unsigned *commentLen) /* RETURNED */ +{ + unsigned len = strlen(authfile_id_string); + const unsigned char *cp = encodedKey; + unsigned remLen = encodedKeyLen; + CSSM_RETURN ourRtn = CSSM_OK; + + /* length: ID string, NULL, Cipher, 4-byte spare */ + if(remLen < (len + 6)) { + errorLog0("decodeOpenSSHv1PrivKey: short record(1)\n"); + return CSSMERR_CSP_INVALID_KEY; + } + + /* ID string plus a NULL */ + if(memcmp(authfile_id_string, cp, len)) { + errorLog0("decodeOpenSSHv1PrivKey: bad header\n"); + return CSSMERR_CSP_INVALID_KEY; + } + cp += (len + 1); + remLen -= (len + 1); + + /* cipher */ + unsigned char cipherSpec = *cp; + switch(cipherSpec) { + case SSH_CIPHER_NONE: + if(decryptKey != NULL) { + errorLog0("decodeOpenSSHv1PrivKey: Attempt to decrypt plaintext key\n"); + return CSSMERR_CSP_INVALID_KEY; + } + break; + case SSH_CIPHER_3DES: + if(decryptKey == NULL) { + errorLog0("decodeOpenSSHv1PrivKey: Encrypted key with no decryptKey\n"); + return CSSMERR_CSP_INVALID_KEY; + } + break; + default: + /* I hope we don't see any other values here */ + errorLog1("decodeOpenSSHv1PrivKey: unknown cipherSpec (%u)\n", cipherSpec); + return CSSMERR_CSP_INVALID_KEY; + } + + /* skip cipher, spares */ + cp += 5; + remLen -= 5; + + /* + * Clear text public key: + * uint32 bits + * bignum n + * bignum e + */ + if(remLen < sizeof(uint32_t)) { + errorLog0("decodeOpenSSHv1PrivKey: bad len(1)\n"); + return CSSMERR_CSP_INVALID_KEY; + } + /* skip over bits */ + readUint32(cp, remLen); + rsa->n = readBigNum(cp, remLen); + if(rsa->n == NULL) { + errorLog0("decodeOpenSSHv1PrivKey: error decoding n\n"); + return CSSMERR_CSP_INVALID_KEY; + } + rsa->e = readBigNum(cp, remLen); + if(rsa->e == NULL) { + errorLog0("decodeOpenSSHv1PrivKey: error decoding e\n"); + return CSSMERR_CSP_INVALID_KEY; + } + + /* comment string: 4-byte length and the string w/o NULL */ + if(remLen < sizeof(uint32_t)) { + errorLog0("decodeOpenSSHv1PrivKey: bad len(2)\n"); + return CSSMERR_CSP_INVALID_KEY; + } + uint32_t commLen = readUint32(cp, remLen); + if(commLen > remLen) { + errorLog0("decodeOpenSSHv1PrivKey: bad len(3)\n"); + return CSSMERR_CSP_INVALID_KEY; + } + if(comment) { + *comment = (uint8 *)malloc(commLen); + *commentLen = commLen; + memcpy(*comment, cp, commLen); + } + + cp += commLen; + remLen -= commLen; + + /* everything that remains is ciphertext */ + unsigned char *ptext = (unsigned char *)malloc(remLen); + unsigned ptextLen = 0; + ourRtn = ssh1DES3Crypt(cipherSpec, false, cp, remLen, + decryptKey, decryptKey ? CC_MD5_DIGEST_LENGTH : 0, + ptext, &ptextLen); + if(ourRtn) { + errorLog0("UnwrapKeyOpenSSH1: decrypt error\n"); + ourRtn = CSSMERR_CSP_INVALID_KEY; + goto errOut; + } + + /* 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) { + errorLog0("UnwrapKeyOpenSSH1: bad len(4)\n"); + ourRtn = CSSMERR_CSP_INVALID_KEY; + goto errOut; + } + if((cp[0] != cp[2]) || (cp[1] != cp[3])) { + /* decrypt fail */ + errorLog0("UnwrapKeyOpenSSH1: check byte error\n"); + ourRtn = CSSMERR_CSP_INVALID_KEY; + goto errOut; + } + cp += 4; + remLen -= 4; + + /* remainder comprises private portion of RSA key */ + rsa->d = readBigNum(cp, remLen); + if(rsa->d == NULL) { + errorLog0("UnwrapKeyOpenSSH1: error decoding d\n"); + ourRtn = CSSMERR_CSP_INVALID_KEY; + goto errOut; + } + rsa->iqmp = readBigNum(cp, remLen); + if(rsa->iqmp == NULL) { + errorLog0("UnwrapKeyOpenSSH1: error decoding iqmp\n"); + ourRtn = CSSMERR_CSP_INVALID_KEY; + goto errOut; + } + rsa->q = readBigNum(cp, remLen); + if(rsa->q == NULL) { + errorLog0("UnwrapKeyOpenSSH1: error decoding q\n"); + ourRtn = CSSMERR_CSP_INVALID_KEY; + goto errOut; + } + rsa->p = readBigNum(cp, remLen); + if(rsa->p == NULL) { + errorLog0("UnwrapKeyOpenSSH1: error decoding p\n"); + ourRtn = CSSMERR_CSP_INVALID_KEY; + goto errOut; + } + + /* calculate d mod{p-1,q-1} */ + ourRtn = rsa_generate_additional_parameters(rsa); + +errOut: + if(ptext) { + memset(ptext, 0, ptextLen); + free(ptext); + } + return ourRtn; +} + +void AppleCSPSession::UnwrapKeyOpenSSH1( + CSSM_CC_HANDLE CCHandle, + const Context &context, + const CssmKey &WrappedKey, + const CSSM_RESOURCE_CONTROL_CONTEXT *CredAndAclEntry, + CssmKey &UnwrappedKey, + CssmData &DescriptiveData, + CSSM_PRIVILEGE Privilege, + cspKeyStorage keyStorage) +{ + /* + * Get the raw password bits from the unwrapping key. + * Our caller verified that the context has a symmetric key; this call + * ensures that the key is of algorithm CSSM_ALGID_OPENSSH1. + */ + CSSM_SIZE unwrapKeyLen = 0; + uint8 *unwrapKey = NULL; + + AppleCSPContext::symmetricKeyBits(context, *this, + CSSM_ALGID_OPENSSH1, CSSM_KEYUSE_UNWRAP, + unwrapKey, unwrapKeyLen); + if((unwrapKey == NULL) || (unwrapKeyLen != CC_MD5_DIGEST_LENGTH)) { + errorLog0("AppleCSPSession::UnwrapKeyOpenSSH1: bad unwrapping key length\n"); + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY); + } + + RSA *rsa = RSA_new(); + CSSM_RETURN ourRtn = CSSM_OK; + unsigned char *comment = NULL; + unsigned commentLen = 0; + RSABinaryKey *binKey = NULL; + + ourRtn = decodeOpenSSHv1PrivKey((const unsigned char *)WrappedKey.KeyData.Data, + WrappedKey.KeyData.Length, + rsa, unwrapKey, &comment, &commentLen); + if(ourRtn) { + goto errOut; + } + if(comment) { + setUpCssmData(DescriptiveData, commentLen, normAllocator); + memcpy(DescriptiveData.Data, comment, commentLen); + } + + /* + * Our caller ensured that we're only generating a reference key, + * which we do like so: + */ + binKey = new RSABinaryKey(rsa); + addRefKey(*binKey, UnwrappedKey); + +errOut: + if(ourRtn) { + if(rsa) { + RSA_free(rsa); + } + CssmError::throwMe(ourRtn); + } +} diff --git a/libsecurity_apple_csp/lib/pbkdDigest.cpp b/libsecurity_apple_csp/lib/pbkdDigest.cpp new file mode 100644 index 00000000..06dbea05 --- /dev/null +++ b/libsecurity_apple_csp/lib/pbkdDigest.cpp @@ -0,0 +1,84 @@ +/* + * 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 new file mode 100644 index 00000000..28421fc2 --- /dev/null +++ b/libsecurity_apple_csp/lib/pbkdDigest.h @@ -0,0 +1,83 @@ +/* + * 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 new file mode 100644 index 00000000..55057b32 --- /dev/null +++ b/libsecurity_apple_csp/lib/pbkdf2.c @@ -0,0 +1,100 @@ +/* + * 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 new file mode 100644 index 00000000..377b303f --- /dev/null +++ b/libsecurity_apple_csp/lib/pbkdf2.h @@ -0,0 +1,79 @@ +/* + * 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/pkcs12Derive.cpp b/libsecurity_apple_csp/lib/pkcs12Derive.cpp new file mode 100644 index 00000000..5fe8d649 --- /dev/null +++ b/libsecurity_apple_csp/lib/pkcs12Derive.cpp @@ -0,0 +1,447 @@ +/* + * 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. + */ +/* + * pkcs12Derive.cpp - PKCS12 PBE routine + * + * Created 2/28/03 by Doug Mitchell. + */ + +#include +#include +#include + +#include "pkcs12Derive.h" +#include "AppleCSPUtils.h" +#include "AppleCSPContext.h" + +#include +#include +#include +#include +#include + +#include + +/* specify which flavor of bits to generate */ +typedef enum { + PBE_ID_Key = 1, + PBE_ID_IV = 2, + PBE_ID_MAC = 3 +} P12_PBE_ID; + +/* + * Create a "string" (in the loose p12 notation) of specified length + * from the concatention of copies of the specified input string. + */ +static unsigned char *p12StrCat( + const unsigned char *inStr, + unsigned inStrLen, + SecNssCoder &coder, + unsigned outLen, + unsigned char *outStr = NULL) // if not present, we malloc +{ + if(outStr == NULL) { + outStr = (unsigned char *)coder.malloc(outLen); + } + unsigned toMove = outLen; + unsigned char *outp = outStr; + while(toMove) { + unsigned thisMove = inStrLen; + if(thisMove > toMove) { + thisMove = toMove; + } + memmove(outp, inStr, thisMove); + toMove -= thisMove; + outp += thisMove; + } + return outStr; +} + +/* + * PBE generator per PKCS12 v.1 section B.2. + */ +static CSSM_RETURN p12PbeGen( + const CSSM_DATA &pwd, // unicode, double null terminated + const uint8 *salt, + unsigned saltLen, + unsigned iterCount, + P12_PBE_ID pbeId, + CSSM_ALGORITHMS hashAlg, // MS5 or SHA1 only + SecNssCoder &coder, // for temp allocs + /* result goes here, mallocd by caller */ + uint8 *outbuf, + unsigned outbufLen) +{ + CSSM_RETURN ourRtn = CSSM_OK; + unsigned unipassLen = pwd.Length; + unsigned char *unipass = pwd.Data; + int irtn; + + /* + * all variables of the form p12_ represent from the + * PKCS12 spec. E.g., p12_u is u, the length of the digest output. + * Only difference here is: all of our sizes are in BYTES, not + * bits. + */ + unsigned p12_r = iterCount; + unsigned p12_n = outbufLen; + + unsigned p12_u; // hash output size + unsigned p12_v; // hash block size + unsigned char *p12_P = NULL; // catted passwords + unsigned char *p12_S = NULL; // catted salts + + switch(hashAlg) { + case CSSM_ALGID_MD5: + p12_u = kMD5DigestSize; + p12_v = kMD5BlockSize; + break; + case CSSM_ALGID_SHA1: + p12_u = kSHA1DigestSize; + p12_v = kSHA1BlockSize; + break; + default: + return CSSMERR_CSP_INVALID_ALGORITHM; + } + + /* + * 1. Construct a string, D (the diversifier), by + * concatenating v/8 copies of ID. + */ + unsigned char *p12_D = NULL; // diversifier + p12_D = (unsigned char *)coder.malloc(p12_v); + for(unsigned dex=0; dex p12_v) { + BN_bn2bin (Ij, p12_B); + memcpy (p12_I + j, p12_B + 1, p12_v); + /* If less than v bytes pad with zeroes */ + } else if (Ijlen < p12_v) { + memset(p12_I + j, 0, p12_v - Ijlen); + BN_bn2bin(Ij, p12_I + j + p12_v - Ijlen); + } else BN_bn2bin (Ij, p12_I + j); + } + } + + if(ourRtn == CSSM_OK) { + /* + * 7. Concatenate A[1], A[2], ..., A[c] together to form a + * pseudo-random bit string, A. + * + * 8. Use the first n bits of A as the output of this entire + * process. + */ + memmove(outbuf, p12_A, outbufLen); + } + + /* clear all these strings */ + if(p12_D) { + memset(p12_D, 0, p12_v); + } + if(p12_S) { + memset(p12_S, 0, p12_Slen); + } + if(p12_P) { + memset(p12_P, 0, p12_Plen); + } + if(p12_I) { + memset(p12_I, 0, p12_Slen + p12_Plen); + } + if(p12_A) { + memset(p12_A, 0, p12_c * p12_u); + } + if(p12_B) { + memset(p12_B, 0, p12_v); + } + if(hashHand) { + DigestCtxFree(hashHand); + } + BN_free(Bpl1); + BN_free(Ij); + return ourRtn; +} + +/* + * Public P12 derive key function, called out from + * AppleCSPSession::DeriveKey() + * + * On input: + * --------- + * Context parameters: + * Salt + * Iteration Count + * CSSM_CRYPTO_DATA.Param - Unicode passphrase, double-NULL terminated + * Algorithm - CSSM_ALGID_PKCS12_PBE_{ENCR,MAC} + * Passed explicitly from DeriveKey(): + * CSSM_DATA Param - IN/OUT - optional IV - caller mallocs space to + * tell us to generate an IV. The param itself is not + * optional; the presence or absence of allocated data in it + * is our IV indicator (present/absent as well as size) + * KeyData - mallocd by caller, we fill in keyData->Length bytes + */ +void DeriveKey_PKCS12 ( + const Context &context, + AppleCSPSession &session, + const CssmData &Param, // other's public key + CSSM_DATA *keyData) // mallocd by caller + // we fill in keyData->Length bytes +{ + SecNssCoder tmpCoder; + + /* + * According to the spec, both passphrase and salt are optional. + * Get them from context if they're present. In practical terms + * the user really should supply a passphrase either in the + * seed attribute (as a Unicode passphrase) or as the BaseKey + * as a CSSM_ALGID_SECURE_PASSPHRASE key). + */ + CSSM_DATA pwd = {0, NULL}; + CSSM_DATA appPwd = {0, NULL}; + CssmCryptoData *cryptData = + context.get(CSSM_ATTRIBUTE_SEED); + if((cryptData != NULL) && (cryptData->Param.Length != 0)) { + appPwd = cryptData->Param; + } + else { + /* Get pwd from base key */ + CssmKey *passKey = context.get(CSSM_ATTRIBUTE_KEY); + if (passKey != NULL) { + AppleCSPContext::symmetricKeyBits(context, session, + CSSM_ALGID_SECURE_PASSPHRASE, CSSM_KEYUSE_DERIVE, + appPwd.Data, appPwd.Length); + } + } + if(appPwd.Data) { + /* + * The incoming passphrase is a UTF8 encoded enternal representation + * of a CFString. Convert to CFString and obtain the unicode characters + * from the string. + */ + CFDataRef cfData = CFDataCreate(NULL, appPwd.Data, appPwd.Length); + CFStringRef cfStr = CFStringCreateFromExternalRepresentation(NULL, + cfData, kCFStringEncodingUTF8); + if (cfData) + CFRelease(cfData); + if(cfStr == NULL) { + CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_SEED); + } + + /* convert unicode to chars with an extra double-NULL */ + unsigned len = CFStringGetLength(cfStr); + tmpCoder.allocItem(pwd, sizeof(UniChar) * (len + 1)); + unsigned char *cp = pwd.Data; + UniChar uc = 0; + for(unsigned dex=0; dex> 8; + *cp++ = uc & 0xff; + } + /* CFString tends to include a NULL at the end; add it if it's not there */ + if(uc == 0) { + if(pwd.Length < 2) { + CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_SEED); + } + pwd.Length -= 2; + } + else { + *cp++ = 0; + *cp++ = 0; + } + if (cfStr) + CFRelease(cfStr); + } + + /* salt from context */ + uint32 saltLen = 0; + uint8 *salt = NULL; + CssmData *csalt = context.get(CSSM_ATTRIBUTE_SALT); + if(csalt) { + salt = csalt->Data; + saltLen = csalt->Length; + } + + /* + * Iteration count, from context, required. + * The spec's ASN1 definition says this is optional with a default + * of one but that's a BER encode/decode issue. Here we require + * a nonzero value. + */ + uint32 iterCount = context.getInt(CSSM_ATTRIBUTE_ITERATION_COUNT, + CSSMERR_CSP_MISSING_ATTR_ITERATION_COUNT); + if(iterCount == 0) { + CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_ITERATION_COUNT); + } + + /* + * Algorithm determines which of {PBE_ID_Key,PBE_ID_MAC} we now + * generate. We'll also do an optional PBE_ID_IV later. + */ + P12_PBE_ID pbeId = PBE_ID_Key; + switch(context.algorithm()) { + case CSSM_ALGID_PKCS12_PBE_ENCR: + pbeId = PBE_ID_Key; + break; + case CSSM_ALGID_PKCS12_PBE_MAC: + pbeId = PBE_ID_MAC; + break; + default: + /* really should not be here */ + assert(0); + CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR); + } + + /* Go */ + CSSM_RETURN crtn = p12PbeGen(pwd, + salt, saltLen, + iterCount, + pbeId, + CSSM_ALGID_SHA1, // all we support for now + tmpCoder, + keyData->Data, + keyData->Length); + if(crtn) { + CssmError::throwMe(crtn); + } + + /* + * Optional IV - makes no sense if we just did PBE_ID_MAC, but why + * bother restricting? + */ + if(Param.Data) { + crtn = p12PbeGen(pwd, + salt, saltLen, + iterCount, + PBE_ID_IV, + CSSM_ALGID_SHA1, // all we support for now + tmpCoder, + Param.Data, + Param.Length); + if(crtn) { + CssmError::throwMe(crtn); + } + } +} + diff --git a/libsecurity_apple_csp/lib/pkcs12Derive.h b/libsecurity_apple_csp/lib/pkcs12Derive.h new file mode 100644 index 00000000..893cc0ba --- /dev/null +++ b/libsecurity_apple_csp/lib/pkcs12Derive.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. + */ + +/* + * pkcs12Derive.cpp - PKCS12 PBE routine + * + * Created 2/28/03 by Doug Mitchell. + */ + +#ifndef _PKCS12_DERIVE_H_ +#define _PKCS12_DERIVE_H_ + +#include +#include +#include "AppleCSPSession.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void DeriveKey_PKCS12 ( + const Context &context, + AppleCSPSession &session, + const CssmData &Param, // other's public key + CSSM_DATA *keyData); // mallocd by caller + // we fill in keyData->Length bytes + +#ifdef __cplusplus +} +#endif + +#endif /* _PKCS12_DERIVE_H_ */ + diff --git a/libsecurity_apple_csp/lib/pkcs8.cpp b/libsecurity_apple_csp/lib/pkcs8.cpp new file mode 100644 index 00000000..d0dc5b8e --- /dev/null +++ b/libsecurity_apple_csp/lib/pkcs8.cpp @@ -0,0 +1,211 @@ +/* + * 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. + */ + + +// +// pkcs8.cpp - PKCS8 key wrap/unwrap support. +// + + +#include "pkcs8.h" +#include "AppleCSPUtils.h" +#include "AppleCSPKeys.h" +#include +#include +#include +#include "AppleCSPSession.h" +#include + +/* + * Given a key in PKCS8 format, fill in the following + * header fields: + * + * CSSM_KEYBLOB_FORMAT Format + * CSSM_ALGORITHMS AlgorithmId + * uint32 LogicalKeySizeInBits + */ +void AppleCSPSession::pkcs8InferKeyHeader( + CssmKey &key) +{ + /* + * Incoming key blob is a PrivateKeyInfo. Take it apart + * to get its algorithm info, from which we infer other + * fields. + */ + NSS_PrivateKeyInfo privKeyInfo; + SecNssCoder coder; + CSSM_DATA &keyData = key.KeyData; + + memset(&privKeyInfo, 0, sizeof(privKeyInfo)); + if(coder.decodeItem(keyData, kSecAsn1PrivateKeyInfoTemplate, + &privKeyInfo)) { + errorLog0("pkcs8InferKeyHeader decode error\n"); + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY); + } + + CSSM_KEYHEADER &hdr = key.KeyHeader; + if(!cssmOidToAlg(&privKeyInfo.algorithm.algorithm, + &hdr.AlgorithmId)) { + errorLog0("pkcs8InferKeyHeader unknown algorithm\n"); + CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM); + } + + switch(hdr.AlgorithmId) { + case CSSM_ALGID_RSA: + case CSSM_ALGID_ECDSA: + hdr.Format = CSSM_KEYBLOB_RAW_FORMAT_PKCS8; + break; + case CSSM_ALGID_DSA: + /* + * Try openssl style first, though our default when + * wrapping is FIPS186 + */ + hdr.Format = CSSM_KEYBLOB_RAW_FORMAT_PKCS8; + break; + default: + /* punt */ + hdr.Format = CSSM_KEYBLOB_RAW_FORMAT_NONE; + break; + } + + /* + * Find someone who knows about this key and ask them the + * key size. infoProvider() throws if no provider found. + */ + CSSM_KEY_SIZE keySize; + try { + auto_ptr provider(infoProvider(key)); + provider->QueryKeySizeInBits(keySize); + } + catch(const CssmError &cerror) { + /* + * Special case: DSA private keys keys can be in two forms - FIPS186 + * (for legacy implementations) and PKCS8 (for openssl). We're wired to + * *generate* FIPS186 blobs by default in pkcs8RawKeyFormat(), but to + * decode openssl-generated DSA private keys in wrapped FIPS186 format + * we have to try both. + */ + if((cerror.error == CSSMERR_CSP_INVALID_KEY) && + (hdr.AlgorithmId == CSSM_ALGID_DSA)) { + hdr.Format = CSSM_KEYBLOB_RAW_FORMAT_FIPS186; + try { + auto_ptr provider(infoProvider(key)); + provider->QueryKeySizeInBits(keySize); + } + catch(...) { + /* out of luck */ + throw; + } + } + else { + /* other error, give up */ + throw; + } + } + catch(...) { + /* other (non-CSSM) error, give up */ + throw; + } + hdr.LogicalKeySizeInBits = keySize.LogicalKeySizeInBits; +} + +/* + * When doing a PKCS8 wrap operation on a reference key, this + * is used to infer the blob type to obtain before the encryption. + * App can override this with a + * CSSM_ATTRIBUTE_{PRIVATE,PUBLIC,SESSION}_KEY_FORMAT + * context attribute. + */ +CSSM_KEYBLOB_FORMAT pkcs8RawKeyFormat( + CSSM_ALGORITHMS keyAlg) +{ + switch(keyAlg) { + case CSSM_ALGID_RSA: + case CSSM_ALGID_ECDSA: + return CSSM_KEYBLOB_RAW_FORMAT_PKCS8; + case CSSM_ALGID_DSA: + return CSSM_KEYBLOB_RAW_FORMAT_FIPS186; + default: + /* punt */ + return CSSM_KEYBLOB_RAW_FORMAT_NONE; + } +} + +/* + * When doing a OPENSSL style wrap operation on a reference key, this + * is used to infer the blob type to obtain before the encryption. + * App can override this with a + * CSSM_ATTRIBUTE_{PRIVATE,PUBLIC,SESSION}_KEY_FORMAT + * context attribute. + */ +CSSM_KEYBLOB_FORMAT opensslRawKeyFormat( + CSSM_ALGORITHMS keyAlg) +{ + switch(keyAlg) { + case CSSM_ALGID_RSA: + return CSSM_KEYBLOB_RAW_FORMAT_PKCS1; + case CSSM_ALGID_DSA: + return CSSM_KEYBLOB_RAW_FORMAT_OPENSSL; + case CSSM_ALGID_ECDSA: + return CSSM_KEYBLOB_RAW_FORMAT_PKCS8; + default: + /* punt */ + return CSSM_KEYBLOB_RAW_FORMAT_NONE; + } +} + +/* + * Given a key in some kind of openssl format (just subsequent to decryption + * during an unwrap), fill in the following header fields: + * + * CSSM_KEYBLOB_FORMAT Format + * uint32 LogicalKeySizeInBits + */ +void AppleCSPSession::opensslInferKeyHeader( + CssmKey &key) +{ + CSSM_KEYHEADER &hdr = key.KeyHeader; + switch(hdr.AlgorithmId) { + case CSSM_ALGID_RSA: + hdr.Format = CSSM_KEYBLOB_RAW_FORMAT_PKCS1; + break; + case CSSM_ALGID_DSA: + hdr.Format = CSSM_KEYBLOB_RAW_FORMAT_OPENSSL; + break; + case CSSM_ALGID_ECDSA: + hdr.Format = CSSM_KEYBLOB_RAW_FORMAT_PKCS8; + break; + default: + /* punt */ + hdr.Format = CSSM_KEYBLOB_RAW_FORMAT_NONE; + return; + } + + /* now figure out the key size by finding a provider for this key */ + CSSM_KEY_SIZE keySize; + try { + auto_ptr provider(infoProvider(key)); + provider->QueryKeySizeInBits(keySize); + } + catch(...) { + /* no recovery possible */ + throw; + } + hdr.LogicalKeySizeInBits = keySize.LogicalKeySizeInBits; + return; +} + diff --git a/libsecurity_apple_csp/lib/pkcs8.h b/libsecurity_apple_csp/lib/pkcs8.h new file mode 100644 index 00000000..d7e5810e --- /dev/null +++ b/libsecurity_apple_csp/lib/pkcs8.h @@ -0,0 +1,44 @@ +/* + * 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. + */ + +// +// pkcs8.cpp - PKCS8 key wrap/unwrap support. +// + +#ifndef _PKCS_8_H_ +#define _PKCS_8_H_ + +#include +#include +#include "AppleCSPSession.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +CSSM_KEYBLOB_FORMAT pkcs8RawKeyFormat( + CSSM_ALGORITHMS keyAlg); + +CSSM_KEYBLOB_FORMAT opensslRawKeyFormat( + CSSM_ALGORITHMS keyAlg); + +#ifdef __cplusplus +} +#endif + +#endif /* _PKCS_7_8_H_ */ diff --git a/libsecurity_apple_csp/lib/rc2Context.cpp b/libsecurity_apple_csp/lib/rc2Context.cpp new file mode 100644 index 00000000..e258b51f --- /dev/null +++ b/libsecurity_apple_csp/lib/rc2Context.cpp @@ -0,0 +1,127 @@ +/* + * 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. + */ + + +/* + * rc2Context.cpp - glue between BlockCrytpor and ssleay RC2 implementation + * Written by Doug Mitchell 04/03/2001 + */ + +#include +#include +#include "rc2Context.h" + +RC2Context::~RC2Context() +{ + memset(&rc2Key, 0, sizeof(RC2_KEY)); +} + +/* + * Standard CSPContext init, called from CSPFullPluginSession::init(). + * Reusable, e.g., query followed by en/decrypt. + */ +void RC2Context::init( + const Context &context, + bool encrypting) +{ + CSSM_SIZE keyLen; + uint8 *keyData = NULL; + uint32 effectiveBits; + + /* obtain key from context */ + symmetricKeyBits(context, session(), CSSM_ALGID_RC2, + encrypting ? CSSM_KEYUSE_ENCRYPT : CSSM_KEYUSE_DECRYPT, + keyData, keyLen); + if((keyLen < RC2_MIN_KEY_SIZE_BYTES) || (keyLen > RC2_MAX_KEY_SIZE_BYTES)) { + CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_KEY); + } + + /* + * Optional effective key size in bits - either from Context, + * or the key + */ + effectiveBits = context.getInt(CSSM_ATTRIBUTE_EFFECTIVE_BITS); + if(effectiveBits == 0) { + CssmKey &key = context.get(CSSM_ATTRIBUTE_KEY, + CSSMERR_CSP_MISSING_ATTR_KEY); + effectiveBits = key.KeyHeader.LogicalKeySizeInBits; + } + + /* init the low-level state */ + RC2_set_key(&rc2Key, keyLen, keyData, effectiveBits); + + /* Finally, have BlockCryptor do its setup */ + setup(RC2_BLOCK_SIZE_BYTES, context); +} + +/* + * Functions called by BlockCryptor + */ +void RC2Context::encryptBlock( + const void *plainText, // length implied (one block) + size_t plainTextLen, + void *cipherText, + size_t &cipherTextLen, // in/out, throws on overflow + bool final) // ignored +{ + if(plainTextLen != RC2_BLOCK_SIZE_BYTES) { + CssmError::throwMe(CSSMERR_CSP_INPUT_LENGTH_ERROR); + } + if(cipherTextLen < RC2_BLOCK_SIZE_BYTES) { + CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR); + } + + /* + * Low-level code operates on array of unsigned 32-bit integers + */ + RC2_INT d[2]; + RC2_INT l; + const unsigned char *pt = (const unsigned char *)plainText; + c2l(pt, l); d[0]=l; + c2l(pt, l); d[1]=l; + RC2_encrypt(d, &rc2Key); + unsigned char *ct = (unsigned char *)cipherText; + l=d[0]; l2c(l, ct); + l=d[1]; l2c(l, ct); + cipherTextLen = RC2_BLOCK_SIZE_BYTES; +} + +void RC2Context::decryptBlock( + const void *cipherText, // length implied (one block) + size_t cipherTextLen, + void *plainText, + size_t &plainTextLen, // in/out, throws on overflow + bool final) // ignored +{ + if(plainTextLen < RC2_BLOCK_SIZE_BYTES) { + CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR); + } + /* + * Low-level code operates on array of unsigned 32-bit integers + */ + RC2_INT d[2]; + RC2_INT l; + const unsigned char *ct = (const unsigned char *)cipherText; + c2l(ct, l); d[0]=l; + c2l(ct, l); d[1]=l; + RC2_decrypt(d, &rc2Key); + unsigned char *pt = (unsigned char *)plainText; + l=d[0]; l2c(l, pt); + l=d[1]; l2c(l, pt); + plainTextLen = RC2_BLOCK_SIZE_BYTES; +} + diff --git a/libsecurity_apple_csp/lib/rc2Context.h b/libsecurity_apple_csp/lib/rc2Context.h new file mode 100644 index 00000000..b71c710a --- /dev/null +++ b/libsecurity_apple_csp/lib/rc2Context.h @@ -0,0 +1,58 @@ +/* + * 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. + */ + + +/* + * rc2Context.h - glue between BlockCrytpor and ssleay RC2 implementation + * Written by Doug Mitchell 4/3/2001 + */ +#ifndef _RC2_CONTEXT_H_ +#define _RC2_CONTEXT_H_ + +#include +#include + +/* RC2 Symmetric encryption context */ +class RC2Context : public BlockCryptor { +public: + RC2Context(AppleCSPSession &session) : + BlockCryptor(session) { } + ~RC2Context(); + + // called by CSPFullPluginSession + void init(const Context &context, bool encoding = true); + + // called by BlockCryptor + void encryptBlock( + const void *plainText, // length implied (one block) + size_t plainTextLen, + void *cipherText, + size_t &cipherTextLen, // in/out, throws on overflow + bool final); + void decryptBlock( + const void *cipherText, // length implied (one cipher block) + size_t cipherTextLen, + void *plainText, + size_t &plainTextLen, // in/out, throws on overflow + bool final); + +private: + RC2_KEY rc2Key; + +}; /* RC2Context */ + +#endif //_RC2_CONTEXT_H_ diff --git a/libsecurity_apple_csp/lib/rc4Context.cpp b/libsecurity_apple_csp/lib/rc4Context.cpp new file mode 100644 index 00000000..29ee478d --- /dev/null +++ b/libsecurity_apple_csp/lib/rc4Context.cpp @@ -0,0 +1,97 @@ +/* + * 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. + */ + + +/* + * rc4Context.cpp - glue between AppleCSPContext and ssleay RC4 implementation + * Written by Doug Mitchell 04/03/2001 + */ + +#include "rc4Context.h" + +RC4Context::~RC4Context() +{ + if (rc4Key != NULL) { + CCCryptorRelease(rc4Key); + } + rc4Key = NULL; +} + +/* + * Standard CSPContext init, called from CSPFullPluginSession::init(). + * Reusable, e.g., query followed by en/decrypt. + */ +void RC4Context::init( + const Context &context, + bool encrypting) +{ + CSSM_SIZE keyLen; + uint8 *keyData = NULL; + + /* obtain key from context */ + symmetricKeyBits(context, session(), CSSM_ALGID_RC4, + encrypting ? CSSM_KEYUSE_ENCRYPT : CSSM_KEYUSE_DECRYPT, + keyData, keyLen); + if((keyLen < kCCKeySizeMinRC4) || (keyLen > kCCKeySizeMaxRC4)) { + CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_KEY); + } + + /* All other context attributes ignored */ + /* init the low-level state */ + (void) CCCryptorCreateWithMode(0, kCCModeRC4, kCCAlgorithmRC4, ccDefaultPadding, NULL, keyData, keyLen, NULL, 0, 0, 0, &rc4Key); + +} + +/* + * All of these functions are called by CSPFullPluginSession. + */ +void RC4Context::update( + void *inp, + size_t &inSize, // in/out + void *outp, + size_t &outSize) // in/out +{ + (void) CCCryptorUpdate(rc4Key, inp, inSize, outp, inSize, &outSize); +} + +/* remainding functions are trivial for any stream cipher */ +void RC4Context::final( + CssmData &out) +{ + out.length(0); +} + +size_t RC4Context::inputSize( + size_t outSize) // input for given output size +{ + return outSize; +} + +size_t RC4Context::outputSize( + bool final /*= false*/, + size_t inSize /*= 0*/) // output for given input size +{ + return inSize; +} + +void RC4Context::minimumProgress( + size_t &in, + size_t &out) // minimum progress chunks +{ + in = 1; + out = 1; +} diff --git a/libsecurity_apple_csp/lib/rc4Context.h b/libsecurity_apple_csp/lib/rc4Context.h new file mode 100644 index 00000000..e3aeb905 --- /dev/null +++ b/libsecurity_apple_csp/lib/rc4Context.h @@ -0,0 +1,63 @@ +/* + * 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. + */ + + +/* + * rc4Context.h - glue between BlockCrytpor and ssleay RC4 implementation + * Written by Doug Mitchell 4/3/2001 + */ +#ifndef _RC4_CONTEXT_H_ +#define _RC4_CONTEXT_H_ + +#include "AppleCSPContext.h" +#include +#include +#include "/usr/local/include/CommonCrypto/CommonCryptorSPI.h" + +class RC4Context : public AppleCSPContext { +public: + RC4Context(AppleCSPSession &session) : + AppleCSPContext(session) { } + virtual ~RC4Context(); + + // 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: + CCCryptorRef rc4Key; + +}; /* RC4Context */ + +#endif //_RC4_CONTEXT_H_ diff --git a/libsecurity_apple_csp/lib/rc5Context.cpp b/libsecurity_apple_csp/lib/rc5Context.cpp new file mode 100644 index 00000000..24dfac0f --- /dev/null +++ b/libsecurity_apple_csp/lib/rc5Context.cpp @@ -0,0 +1,125 @@ +/* + * 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. + */ + + +/* + * rc5Context.cpp - glue between BlockCrytpor and ssleay RC5 implementation + * Written by Doug Mitchell 04/03/2001 + */ + +#include +#include +#include "rc5Context.h" + +RC5Context::~RC5Context() +{ + memset(&rc5Key, 0, sizeof(RC5_32_KEY)); +} + +/* + * Standard CSPContext init, called from CSPFullPluginSession::init(). + * Reusable, e.g., query followed by en/decrypt. + */ +void RC5Context::init( + const Context &context, + bool encrypting) +{ + CSSM_SIZE keyLen; + uint8 *keyData = NULL; + uint32 rounds = RC5_16_ROUNDS; + + /* obtain key from context */ + symmetricKeyBits(context, session(), CSSM_ALGID_RC5, + encrypting ? CSSM_KEYUSE_ENCRYPT : CSSM_KEYUSE_DECRYPT, + keyData, keyLen); + if((keyLen < RC5_MIN_KEY_SIZE_BYTES) || (keyLen > RC5_MAX_KEY_SIZE_BYTES)) { + CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_KEY); + } + + /* + * Optional rounds + */ + rounds = context.getInt(CSSM_ATTRIBUTE_ROUNDS); + if(rounds == 0) { + /* default */ + rounds = RC5_16_ROUNDS; + } + + /* init the low-level state */ + RC5_32_set_key(&rc5Key, keyLen, keyData, rounds); + + /* Finally, have BlockCryptor do its setup */ + setup(RC5_BLOCK_SIZE_BYTES, context); +} + +/* + * Functions called by BlockCryptor + */ +void RC5Context::encryptBlock( + const void *plainText, // length implied (one block) + size_t plainTextLen, + void *cipherText, + size_t &cipherTextLen, // in/out, throws on overflow + bool final) // ignored +{ + if(plainTextLen != RC5_BLOCK_SIZE_BYTES) { + CssmError::throwMe(CSSMERR_CSP_INPUT_LENGTH_ERROR); + } + if(cipherTextLen < RC5_BLOCK_SIZE_BYTES) { + CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR); + } + + /* + * Low-level code operates on array of unsigned 32-bit integers + */ + RC5_32_INT d[2]; + RC5_32_INT l; + const unsigned char *pt = (const unsigned char *)plainText; + c2l(pt, l); d[0]=l; + c2l(pt, l); d[1]=l; + RC5_32_encrypt(d, &rc5Key); + unsigned char *ct = (unsigned char *)cipherText; + l=d[0]; l2c(l, ct); + l=d[1]; l2c(l, ct); + cipherTextLen = RC5_BLOCK_SIZE_BYTES; +} + +void RC5Context::decryptBlock( + const void *cipherText, // length implied (one block) + size_t cipherTextLen, + void *plainText, + size_t &plainTextLen, // in/out, throws on overflow + bool final) // ignored +{ + if(plainTextLen < RC5_BLOCK_SIZE_BYTES) { + CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR); + } + /* + * Low-level code operates on array of unsigned 32-bit integers + */ + RC5_32_INT d[2]; + RC5_32_INT l; + const unsigned char *ct = (const unsigned char *)cipherText; + c2l(ct, l); d[0]=l; + c2l(ct, l); d[1]=l; + RC5_32_decrypt(d, &rc5Key); + unsigned char *pt = (unsigned char *)plainText; + l=d[0]; l2c(l, pt); + l=d[1]; l2c(l, pt); + plainTextLen = RC5_BLOCK_SIZE_BYTES; +} + diff --git a/libsecurity_apple_csp/lib/rc5Context.h b/libsecurity_apple_csp/lib/rc5Context.h new file mode 100644 index 00000000..423dca51 --- /dev/null +++ b/libsecurity_apple_csp/lib/rc5Context.h @@ -0,0 +1,57 @@ +/* + * 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. + */ + + +/* + * rc5Context.h - glue between BlockCrytpor and ssleay RC5 implementation + * Written by Doug Mitchell 4/3/2001 + */ +#ifndef _RC5_CONTEXT_H_ +#define _RC5_CONTEXT_H_ + +#include +#include + +class RC5Context : public BlockCryptor { +public: + RC5Context(AppleCSPSession &session) : + BlockCryptor(session) { } + ~RC5Context(); + + // called by CSPFullPluginSession + void init(const Context &context, bool encoding = true); + + // called by BlockCryptor + void encryptBlock( + const void *plainText, // length implied (one block) + size_t plainTextLen, + void *cipherText, + size_t &cipherTextLen, // in/out, throws on overflow + bool final); + void decryptBlock( + const void *cipherText, // length implied (one cipher block) + size_t cipherTextLen, + void *plainText, + size_t &plainTextLen, // in/out, throws on overflow + bool final); + +private: + RC5_32_KEY rc5Key; + +}; /* RC5Context */ + +#endif //_RC2_CONTEXT_H_ diff --git a/libsecurity_apple_csp/lib/rijndael-alg-ref.c b/libsecurity_apple_csp/lib/rijndael-alg-ref.c new file mode 100644 index 00000000..2a350914 --- /dev/null +++ b/libsecurity_apple_csp/lib/rijndael-alg-ref.c @@ -0,0 +1,615 @@ +/* + * 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 */ + +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]; +} + +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]; + } +} + +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]] ; +} + +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]; + } +} + +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 new file mode 100644 index 00000000..9b78ad0c --- /dev/null +++ b/libsecurity_apple_csp/lib/rijndael-alg-ref.h @@ -0,0 +1,82 @@ +/* + * 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 new file mode 100644 index 00000000..67e84235 --- /dev/null +++ b/libsecurity_apple_csp/lib/rijndaelApi.c @@ -0,0 +1,276 @@ +/* + * 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 new file mode 100644 index 00000000..38e79001 --- /dev/null +++ b/libsecurity_apple_csp/lib/rijndaelApi.h @@ -0,0 +1,119 @@ +/* + * 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/lib/vRijndael-alg-ref.c b/libsecurity_apple_csp/lib/vRijndael-alg-ref.c new file mode 100644 index 00000000..f5afda69 --- /dev/null +++ b/libsecurity_apple_csp/lib/vRijndael-alg-ref.c @@ -0,0 +1,684 @@ +/* + * 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. + */ + + +/* + * vRijndael-alg-ref.c + * + * Created by Robert A. Murley on Mon Jan 22 2001. + * Copyright (c) 2001 Apple Computer, Inc. All rights reserved. + * + */ + +#include "rijndaelApi.h" +#include "rijndael-alg-ref.h" +#include "boxes-ref.h" +#include + +/* debugger seems to have trouble with this code... */ +#define VAES_DEBUG 1 +#if VAES_DEBUG +#include +#define vdprintf(s) printf s +#else +#define vdprintf(s) +#endif + +#define SC ((BC - 4) >> 1) + +#if defined(__ppc__) && defined(ALTIVEC_ENABLE) + +typedef union { + unsigned char s[4][8]; + unsigned long l[8]; + vector unsigned char v[2]; +} doubleVec; + +typedef union { + unsigned long s[4]; + vector unsigned long v; +} vecLong; + +static 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 } + } +}; + +int vRijndaelKeySched ( vector unsigned char vk[2], int keyBits, int blockBits, + unsigned char 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; + doubleVec tk; + register vector unsigned char v1, v2, mask; + + 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 */ + } + + tk.v[0] = vk[0]; + tk.v[1] = vk[1]; + + 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.s[i][j]; + + while (t < (ROUNDS+1)*BC) { /* while not enough round key material calculated */ + /* calculate new values */ + for(i = 0; i < 4; i++) + tk.s[i][0] ^= *((word8 *)S + tk.s[(i+1)%4][KC-1]); + tk.s[0][0] ^= rcon[rconpointer++]; + + if (KC != 8) { + /* xor bytes 1-7 of each row with previous byte */ + mask = (vector unsigned char) ( 0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff ); + for ( i = 0; i < 2; i++ ) { + v1 = vec_sld( tk.v[i], tk.v[i], 15 ); + v2 = vec_and( v1, mask ); + tk.v[i] = vec_xor( tk.v[i], v2 ); + } + } + else { + /* xor bytes 1-3 of each row with previous byte */ + mask = (vector unsigned char) ( 0, 0xff, 0xff, 0xff, 0, 0, 0, 0, 0, 0xff, 0xff, 0xff, 0, 0, 0, 0 ); + for ( i = 0; i < 2; i++ ) { + v1 = vec_sld( tk.v[i], tk.v[i], 15 ); + v2 = vec_and( v1, mask ); + tk.v[i] = vec_xor( tk.v[i], v2 ); + for(j = 0; j < 4; j++) tk.s[i][KC/2] ^= *((word8 *)S + tk.s[i][KC/2 - 1]); + /* xor bytes 5-7 of each row with previous byte */ + mask = vec_sld( mask, mask, 4 ); + v2 = vec_and( v1, mask ); + tk.v[i] = vec_xor( tk.v[i], v2 ); + mask = vec_sld( mask, mask, 4 ); + } + } + /* 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.s[i][j]; + } + return 0; +} + + +void vMakeKey(BYTE *keyMaterial, keyInstance *key) +{ + register vector unsigned char v1, v2, v3, mask; + vector unsigned char vk[2]; + + /* load and align input */ + v1 = vec_ld( 0, (vector unsigned char *) keyMaterial ); + v2 = vec_ld( 16, (vector unsigned char *) keyMaterial ); + if ( (long) keyMaterial & 0x0fL ) + { // this is required if keyMaterial is not on a 16-byte boundary + v3 = vec_ld( 32, (vector unsigned char *) keyMaterial ); + mask = vec_lvsl( 0, keyMaterial ); + v1 = vec_perm( v1, v2, mask ); + v2 = vec_perm( v2, v3, mask ); + } + + /* parse input stream into rectangular array */ + vk[0] = vec_perm( v1, v2, (vector unsigned char) ( 0, 4, 8, 12, 16, 20, 24, 28, 1, 5, 9, 13, 17, 21, 25, 29 ) ); + vk[1] = vec_perm( v1, v2, (vector unsigned char) ( 2, 6, 10, 14, 18, 22, 26, 30, 3, 7, 11, 15, 19, 23, 27, 31 ) ); + vRijndaelKeySched (vk, key->keyLen, key->blockLen, key->keySched); + memset( (char *) vk, 0, 4 * MAXKC); +} + + +/* This routine does 16 simultaneous lookups in a 256-byte table. */ +vector unsigned char rimskyKorsakov ( vector unsigned char v, vector unsigned char * table ) +{ + register vector unsigned char upperBits000, upperBits001, upperBits010, upperBits011, + upperBits100, upperBits101, upperBits110, upperBits111, + lookupBit00, lookupBit01, lookupBit10, lookupBit11, + lookupBit0, lookupBit1, lookup, + maskForBit6, maskForBit7, maskForBit8, seven; + register vector unsigned char *tabeven, *tabodd; + + seven = vec_splat_u8 ( 7 ); + tabeven = table++; + tabodd = table; + +// Each variable contains the correct values for the corresponding bits 6, 7 and 8. + upperBits000 = vec_perm ( *tabeven, *tabodd, v ); + tabeven += 2; tabodd += 2; + upperBits001 = vec_perm ( *tabeven, *tabodd, v ); + tabeven += 2; tabodd += 2; + upperBits010 = vec_perm ( *tabeven, *tabodd, v ); + tabeven += 2; tabodd += 2; + upperBits011 = vec_perm ( *tabeven, *tabodd, v ); + tabeven += 2; tabodd += 2; + upperBits100 = vec_perm ( *tabeven, *tabodd, v ); + tabeven += 2; tabodd += 2; + upperBits101 = vec_perm ( *tabeven, *tabodd, v ); + tabeven += 2; tabodd += 2; + upperBits110 = vec_perm ( *tabeven, *tabodd, v ); + tabeven += 2; tabodd += 2; + upperBits111 = vec_perm ( *tabeven, *tabodd, v ); + +// Here we extract all the correct values for bit 6. + maskForBit6 = vec_sl ( v, vec_splat_u8 ( 2 ) ); + maskForBit6 = vec_sra ( maskForBit6, seven ); + lookupBit00 = vec_sel ( upperBits000, upperBits001, maskForBit6 ); + lookupBit01 = vec_sel ( upperBits010, upperBits011, maskForBit6 ); + lookupBit10 = vec_sel ( upperBits100, upperBits101, maskForBit6 ); + lookupBit11 = vec_sel ( upperBits110, upperBits111, maskForBit6 ); + +// Then we get the correct values for bit 7. + maskForBit7 = vec_sl ( v, vec_splat_u8 ( 1 ) ); + maskForBit7 = vec_sra ( maskForBit7, seven ); + lookupBit0 = vec_sel ( lookupBit00, lookupBit01, maskForBit7 ); + lookupBit1 = vec_sel ( lookupBit10, lookupBit11, maskForBit7 ); + +// Finally, the entire correct result vector. + maskForBit8 = vec_sra ( v, seven ); + + lookup = vec_sel ( lookupBit0, lookupBit1, maskForBit8 ); + + return lookup; +} + +vector unsigned char vmul(vector unsigned char a, vector unsigned char b) +{ + register vector unsigned char x, y, zero; + register vector unsigned short xh, yh, zhi, zlo, two54, two55; + + zero = vec_splat_u8( 0 ); + two55 = vec_splat_u16( -1 ); + two55 = (vector unsigned short) vec_mergeh( zero, (vector unsigned char) two55 ); + two54 = vec_sub( two55, vec_splat_u16( 1 ) ); + + x = rimskyKorsakov( a, (vector unsigned char *)Logtable ); // Logtable[a] + y = rimskyKorsakov( b, (vector unsigned char *)Logtable ); // Logtable[b] + + // Convert upper 8 bytes to shorts for addition ond modulo + xh = (vector unsigned short) vec_mergeh( zero, x ); + yh = (vector unsigned short) vec_mergeh( zero, y ); + xh = vec_add( xh, yh ); // xh = Logtable[a] + Logtable[b] + yh = vec_sub( xh, two55 ); + zhi = vec_sel( xh, yh, vec_cmpgt( xh, two54 ) ); // xh%255 + + // Convert lower 8 bytes to shorts for addition ond modulo + xh = (vector unsigned short) vec_mergel( zero, x ); + yh = (vector unsigned short) vec_mergel( zero, y ); + xh = vec_add( xh, yh ); + yh = vec_sub( xh, two55 ); + zlo = vec_sel( xh, yh, vec_cmpgt( xh, two54 ) ); + + x = vec_pack( zhi, zlo ); // recombine into single byte vector + x = rimskyKorsakov( x, (vector unsigned char *)Alogtable ); // Alogtable[x] + x = vec_sel( x, zero, vec_cmpeq( a, zero ) ); // check a = 0 + x = vec_sel( x, zero, vec_cmpeq( b, zero ) ); // check b = 0 + return x; +} + +void vKeyAddition(vector unsigned char v[2], vector unsigned char rk[2]) +{ + v[0] = vec_xor( v[0], rk[0] ); // first vector contains rows 0 and 1 + v[1] = vec_xor( v[1], rk[1] ); // second vector contains rows 2 and 3 +} + + +void vShiftRow(vector unsigned char v[2], word8 d, word8 BC) +{ + vecLong sh; + register vector unsigned char mask, mask1, t; + register vector bool char c; + register int i, j; + + sh.s[0] = 0; + for (i = 1; i < 4; i++) + sh.s[i] = shifts[SC][i][d] % BC; // contains the number of elements to shift each row + + // each vector contains two BC-byte long rows + j = 0; + for ( i = 0; i < 2; i++ ) { + mask = vec_lvsl( 0, (int *) sh.s[j++]); // mask for even row + mask1 = vec_lvsl( 0, (int *) sh.s[j++]); // mask for odd row + if (BC == 4) { + mask = vec_sld( mask, mask1, 8 ); // combined rotation mask for both rows + mask = vec_and( mask, vec_splat_u8( 3 ) ); + } else if (BC == 6) { + mask = vec_sld( mask, mask, 8 ); + mask = vec_sld( mask, mask1, 8 ); // combined rotation mask for both rows + t = vec_sub( mask, vec_splat_u8( 6 ) ); + c = vec_cmpgt( mask, vec_splat_u8( 5 ) ); + mask = vec_sel( mask, t, c ); + } else { + mask = vec_sld( mask, mask1, 8 ); // combined rotation mask for both rows + mask = vec_and( mask, vec_splat_u8( 7 ) ); + } + mask1 = vec_sld( vec_splat_u8( 0 ), vec_splat_u8( 8 ), 8 ); + mask = vec_add( mask, mask1 ); + v[i] = vec_perm( v[i], v[i], mask ); // rotate each row as required + } +} + +void vSubstitution( vector unsigned char v[2], vector unsigned char box[16] ) +{ + v[0] = rimskyKorsakov( v[0], box ); // first vector contains rows 0 and 1 + v[1] = rimskyKorsakov( v[1], box ); // second vector contains rows 2 and 3 +} + +void vMixColumn(vector unsigned char v[2]) +{ + // vector 0 contains row 0 in bytes 0-7 and row 1 in bytes 8-f + // vector 1 contains row 2 in bytes 0-7 and row 3 in bytes 8-f + + register vector unsigned char a0, a1, a2, a3, b0, b1, b2, b3; + register vector unsigned char two, three; + + two = vec_splat_u8( 2 ); + three = vec_splat_u8( 3 ); + + a1 = vec_sld( v[0], v[1], 8 ); // equivalent to a[i+1] % 4 + b1 = vec_sld( v[1], v[0], 8 ); + a2 = vec_sld( a1, b1, 8 ); // equivalent to a[i+2] % 4 + b2 = vec_sld( b1, a1, 8 ); + a3 = vec_sld( a2, b2, 8 ); // equivalent to a[i+3] % 4 + b3 = vec_sld( b2, a2, 8 ); + + // Calculations for rows 0 and 1 + a0 = vmul( two, v[0] ); // mul(2,a[i][j]) + a0 = vec_xor( a0, vmul( three, a1 ) ); // ^ mul(3,a[(i + 1) % 4][j]) + a0 = vec_xor( a0, a2 ); // ^ a[(i + 2) % 4][j] + v[0] = vec_xor( a0, a3 ); // ^ a[(i + 3) % 4][j] + + // Calculations for rows 2 and 3 + b0 = vmul( two, v[1] ); + b0 = vec_xor( b0, vmul( three, b1 ) ); + b0 = vec_xor( b0, b2 ); + v[1] = vec_xor( b0, b3 ); +} + +void vInvMixColumn(vector unsigned char v[2]) +{ + // vector 0 contains row 0 in bytes 0-7 and row 1 in bytes 8-f + // vector 1 contains row 2 in bytes 0-7 and row 3 in bytes 8-f + + register vector unsigned char a0, a1, a2, a3, b0, b1, b2, b3; + register vector unsigned char nine, eleven, thirteen, fourteen;; + + nine = vec_splat_u8( 0x9 ); + eleven = vec_splat_u8( 0xb ); + thirteen = vec_splat_u8( 0xd ); + fourteen = vec_splat_u8( 0xe ); + + a1 = vec_sld( v[0], v[1], 8 ); // equivalent to a[i+1] % 4 + b1 = vec_sld( v[1], v[0], 8 ); + a2 = vec_sld( a1, b1, 8 ); // equivalent to a[i+2] % 4 + b2 = vec_sld( b1, a1, 8 ); + a3 = vec_sld( a2, b2, 8 ); // equivalent to a[i+3] % 4 + b3 = vec_sld( b2, a2, 8 ); + + // Calculations for rows 0 and 1 + a0 = vmul( fourteen, v[0] ); // mul(0xe,a[i][j]) + a0 = vec_xor( a0, vmul( eleven, a1 ) ); // ^ mul(0xb,a[(i + 1) % 4][j]) + a0 = vec_xor( a0, vmul( thirteen, a2 ) ); // ^ mul(0xd,a[(i + 2) % 4][j]) + v[0] = vec_xor( a0, vmul( nine, a3 ) ); // ^ mul(0x9,a[(i + 3) % 4][j]) + + // Calculations for rows 2 and 3 + b0 = vmul( fourteen, v[1] ); + b0 = vec_xor( b0, vmul( eleven, b1 ) ); + b0 = vec_xor( b0, vmul( thirteen, b2 ) ); + v[1] = vec_xor( b0, vmul( nine, b3 ) ); +} + +int vRijndaelEncrypt (vector unsigned char a[2], int keyBits, int blockBits, vector unsigned char rk[MAXROUNDS+1][2]) +{ + /* 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 */ + } + + vKeyAddition( a, rk[0] ); + for(r = 1; r < ROUNDS; r++) { + vSubstitution( a, (vector unsigned char *)S); + vShiftRow( a, 0, BC); + vMixColumn( a ); + vKeyAddition( a, rk[r] ); + } + vSubstitution( a, (vector unsigned char *)S); + vShiftRow( a, 0, BC); + vKeyAddition( a, rk[ROUNDS] ); + + return 0; +} + +int vRijndaelDecrypt (vector unsigned char a[2], int keyBits, int blockBits, vector unsigned char rk[MAXROUNDS+1][2]) +{ + 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 */ + } + + vKeyAddition( a, rk[ROUNDS] ); + vSubstitution( a, (vector unsigned char *)Si); + vShiftRow( a, 1, BC); + for(r = ROUNDS-1; r > 0; r--) { + vKeyAddition( a, rk[r] ); + vInvMixColumn( a ); + vSubstitution( a, (vector unsigned char *)Si); + vShiftRow( a, 1, BC); + } + vKeyAddition( a, rk[0] ); + + return 0; +} + +#if 0 +/* Murley's code, to be deleted */ +void vBlockEncrypt(cipherInstance *cipher, keyInstance *key, BYTE *input, int inputLen, BYTE *outBuffer) +{ + register vector unsigned char v1, v2, v3, v4, mask; + register vector bool char cmp; + + /* load and align input */ + v1 = vec_ld( 0, (vector unsigned char *) input ); + v2 = vec_ld( 16, (vector unsigned char *) input ); + if ( (long) input & 0x0fL ) + { // this is required if input is not on a 16-byte boundary + v3 = vec_ld( 32, (vector unsigned char *) input ); + mask = vec_lvsl( 0, input ); + v1 = vec_perm( v1, v2, mask ); + v2 = vec_perm( v2, v3, mask ); + } + + /* parse input stream into rectangular array */ + v3 = vec_perm( v1, v2, (vector unsigned char) ( 0, 4, 8, 12, 16, 20, 24, 28, 1, 5, 9, 13, 17, 21, 25, 29 ) ); + v4 = vec_perm( v1, v2, (vector unsigned char) ( 2, 6, 10, 14, 18, 22, 26, 30, 3, 7, 11, 15, 19, 23, 27, 31 ) ); + + /* store into cipher structure */ + if (cipher->mode == MODE_CBC) { + v3 = vec_xor( v3, *((vector unsigned char *) cipher->chainBlock ) ); + v4 = vec_xor( v4, *((vector unsigned char *) cipher->chainBlock + 1 ) ); + } + vec_st( v3, 0, (vector unsigned char *) cipher->chainBlock ); + vec_st( v4, 16, (vector unsigned char *) cipher->chainBlock ); + + vRijndaelEncrypt((vector unsigned char *) cipher->chainBlock, key->keyLen, cipher->blockLen, (vector unsigned char *) key->keySched); + + v1 = vec_ld( 0, (vector unsigned char *) cipher->chainBlock ); + v2 = vec_ld( 16, (vector unsigned char *) cipher->chainBlock ); + + /* parse rectangular array into output ciphertext bytes */ + v3 = vec_perm( v1, v2, (vector unsigned char) ( 0, 8, 16, 24, 1, 9, 17, 25, 2, 10, 18, 26, 3, 11, 19, 27 ) ); + v4 = vec_perm( v1, v2, (vector unsigned char) ( 4, 12, 20, 28, 5, 13, 21, 29, 6, 14, 22, 30, 7, 15, 23, 31 ) ); + + if ( (long) outBuffer & 0x0fL ) + { + /* store output data into a non-aligned buffer */ + mask = vec_lvsr( 0, outBuffer ); + cmp = vec_cmpgt( mask, vec_splat_u8( 0x0f ) ); + v1 = vec_perm( v3, v3, mask ); + v2 = vec_perm( v4, v4, mask ); + v3 = vec_ld( 0, (vector unsigned char *) outBuffer ); + v4 = vec_sel( v3, v1, cmp ); + vec_st( v4, 0, (vector unsigned char *) outBuffer ); + v1 = vec_sel( v1, v2, cmp ); + vec_st( v1, 16, (vector unsigned char *) outBuffer ); + v3 = vec_ld( 32, (vector unsigned char *) outBuffer ); + v2 = vec_sel( v2, v3, cmp ); + vec_st( v2, 32, (vector unsigned char *) outBuffer ); + } else { + // store output data into an aligned buffer + vec_st( v3, 0, (vector unsigned char *) outBuffer ); + vec_st( v4, 16, (vector unsigned char *) outBuffer ); + } + return; +} + +void vBlockDecrypt(cipherInstance *cipher, keyInstance *key, BYTE *input, int inputLen, BYTE *outBuffer) +{ + // for vector machines + register vector unsigned char v1, v2, v3, v4, mask; + register vector bool char cmp; + vector unsigned char block[2], cblock[2]; + + /* load and align input */ + v1 = vec_ld( 0, (vector unsigned char *) input ); + v2 = vec_ld( 16, (vector unsigned char *) input ); + if ( (long) input & 0x0fL ) + { // this is required if input is not on a 16-byte boundary + v3 = vec_ld( 32, (vector unsigned char *) input ); + mask = vec_lvsl( 0, input ); + v1 = vec_perm( v1, v2, mask ); + v2 = vec_perm( v2, v3, mask ); + } + + /* parse input stream into rectangular array */ + v3 = vec_perm( v1, v2, (vector unsigned char) ( 0, 4, 8, 12, 16, 20, 24, 28, 1, 5, 9, 13, 17, 21, 25, 29 ) ); + v4 = vec_perm( v1, v2, (vector unsigned char) ( 2, 6, 10, 14, 18, 22, 26, 30, 3, 7, 11, 15, 19, 23, 27, 31 ) ); + block[0] = v3; + block[1] = v4; + + /* save a copy of incoming ciphertext for later chain */ + if (cipher->mode == MODE_CBC) { + cblock[0] = v3; + cblock[1] = v4; + } + + vRijndaelDecrypt ((vector unsigned char *) block, key->keyLen, cipher->blockLen, (vector unsigned char *) key->keySched); + + v1 = block[0]; + v2 = block[1]; + + /* exor with last ciphertext */ + if (cipher->mode == MODE_CBC) { + v1 = vec_xor( v1, *((vector unsigned char *) cipher->chainBlock) ); + v2 = vec_xor( v2, *((vector unsigned char *) cipher->chainBlock + 1) ); + vec_st( cblock[0], 0, (vector unsigned char *) cipher->chainBlock ); + vec_st( cblock[1], 16, (vector unsigned char *) cipher->chainBlock ); + } + + /* parse rectangular array into output ciphertext bytes */ + v3 = vec_perm( v1, v2, (vector unsigned char) ( 0, 8, 16, 24, 1, 9, 17, 25, 2, 10, 18, 26, 3, 11, 19, 27 ) ); + v4 = vec_perm( v1, v2, (vector unsigned char) ( 4, 12, 20, 28, 5, 13, 21, 29, 6, 14, 22, 30, 7, 15, 23, 31 ) ); + + if ( (long) outBuffer & 0x0fL ) + { /* store output data into a non-aligned buffer */ + mask = vec_lvsr( 0, outBuffer ); + cmp = vec_cmpgt( mask, vec_splat_u8( 0x0f ) ); + v1 = vec_perm( v3, v3, mask ); + v2 = vec_perm( v4, v4, mask ); + v3 = vec_ld( 0, (vector unsigned char *) outBuffer ); + v4 = vec_sel( v3, v1, cmp ); + vec_st( v4, 0, (vector unsigned char *) outBuffer ); + v1 = vec_sel( v1, v2, cmp ); + vec_st( v1, 16, (vector unsigned char *) outBuffer ); + v3 = vec_ld( 32, (vector unsigned char *) outBuffer ); + v2 = vec_sel( v2, v3, cmp ); + vec_st( v2, 32, (vector unsigned char *) outBuffer ); + } else { + // store output data into an aligned buffer + vec_st( v3, 0, (vector unsigned char *) outBuffer ); + vec_st( v4, 16, (vector unsigned char *) outBuffer ); + } +} +#endif /* Murley's code, to be deleted */ + +/* + * dmitch addenda 4/11/2001: 128-bit only encrypt/decrypt with no CBC + */ +void vBlockEncrypt128( + keyInstance *key, + BYTE *input, + BYTE *outBuffer) +{ + vector unsigned char block[2]; + register vector unsigned char v1, v2; + + if ( (long) input & 0x0fL ) { + BYTE localBuf[16]; + vdprintf(("vBlockEncrypt128: unaligned input\n")); + /* manually re-align - the compiler is supposed to 16-byte align this for us */ + if((unsigned)localBuf & 0xf) { + vdprintf(("vBlockEncrypt128: unaligned localBuf!\n")); + } + memmove(localBuf, input, 16); + v1 = vec_ld(0, (vector unsigned char *)localBuf); + } + else { + vdprintf(("vBlockEncrypt128: aligned input\n")); + v1 = vec_ld( 0, (vector unsigned char *) input ); + } + + /* parse input stream into rectangular array */ + /* FIXME - do we need to zero v2 (or something)? */ + block[0] = vec_perm(v1, v2, + (vector unsigned char) ( 0, 4, 8, 12, 16, 20, 24, 28, 1, + 5, 9, 13, 17, 21, 25, 29 ) ); + block[1] = vec_perm( v1, v2, + (vector unsigned char) ( 2, 6, 10, 14, 18, 22, 26, 30, 3, + 7, 11, 15, 19, 23, 27, 31 ) ); + + vRijndaelEncrypt(block, key->keyLen, 128, (vector unsigned char *) key->keySched); + + /* parse rectangular array into output ciphertext bytes */ + v1 = vec_perm(block[0], block[1], + (vector unsigned char) ( 0, 8, 16, 24, 1, 9, 17, 25, 2, + 10, 18, 26, 3, 11, 19, 27 ) ); + v2 = vec_perm(block[0], block[1], + (vector unsigned char) ( 4, 12, 20, 28, 5, 13, 21, 29, 6, + 14, 22, 30, 7, 15, 23, 31 ) ); + + if ( (long) outBuffer & 0x0fL ) + { + /* store output data into a non-aligned buffer */ + BYTE localBuf[16]; + vec_st(v1, 0, (vector unsigned char *) localBuf ); + memmove(outBuffer, localBuf, 16); + } else { + /* store output data into an aligned buffer */ + vec_st( v1, 0, (vector unsigned char *) outBuffer ); + } + return; +} + +void vBlockDecrypt128( + keyInstance *key, + BYTE *input, + BYTE *outBuffer) +{ + vector unsigned char block[2]; + register vector unsigned char v1, v2; + + if ( (long) input & 0x0fL ) { + /* manually re-align - the compiler is supposed to 16-byte align this for us */ + BYTE localBuf[16]; + vdprintf(("vBlockDecrypt128: unaligned input\n")); + if((unsigned)localBuf & 0xf) { + vdprintf(("vBlockDecrypt128: unaligned localBuf!\n")); + } + memmove(localBuf, input, 16); + v1 = vec_ld(0, (vector unsigned char *)localBuf); + } + else { + vdprintf(("vBlockDecrypt128: aligned input\n")); + v1 = vec_ld( 0, (vector unsigned char *) input ); + } + + /* parse input stream into rectangular array */ + /* FIXME - do we need to zero v2 (or something)? */ + block[0] = vec_perm(v1, v2, + (vector unsigned char) ( 0, 4, 8, 12, 16, 20, 24, 28, 1, + 5, 9, 13, 17, 21, 25, 29 ) ); + block[1] = vec_perm( v1, v2, + (vector unsigned char) ( 2, 6, 10, 14, 18, 22, 26, 30, 3, + 7, 11, 15, 19, 23, 27, 31 ) ); + + vRijndaelDecrypt(block, key->keyLen, 128, (vector unsigned char *) key->keySched); + + /* parse rectangular array into output ciphertext bytes */ + v1 = vec_perm(block[0], block[1], + (vector unsigned char) ( 0, 8, 16, 24, 1, 9, 17, 25, 2, + 10, 18, 26, 3, 11, 19, 27 ) ); + v2 = vec_perm(block[0], block[1], + (vector unsigned char) ( 4, 12, 20, 28, 5, 13, 21, 29, 6, + 14, 22, 30, 7, 15, 23, 31 ) ); + + if ( (long) outBuffer & 0x0fL ) { + /* store output data into a non-aligned buffer */ + BYTE localBuf[16]; + vec_st(v1, 0, (vector unsigned char *) localBuf ); + memmove(outBuffer, localBuf, 16); + } else { + /* store output data into an aligned buffer */ + vec_st( v1, 0, (vector unsigned char *) outBuffer ); + } + return; +} + +#endif /* defined(__ppc__) && defined(ALTIVEC_ENABLE) */ diff --git a/libsecurity_apple_csp/lib/wrapKey.cpp b/libsecurity_apple_csp/lib/wrapKey.cpp new file mode 100644 index 00000000..2d84b2ce --- /dev/null +++ b/libsecurity_apple_csp/lib/wrapKey.cpp @@ -0,0 +1,742 @@ +/* + * 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. + */ + + +// +// wrapKey.cpp - wrap/unwrap key functions for AppleCSPSession +// + +/* + * Currently the Security Server wraps public keys when they're stored, so we have + * to allow this. We might not want to do this in the real world. + */ +#define ALLOW_PUB_KEY_WRAP 1 + +#include "AppleCSPSession.h" +#include "AppleCSPUtils.h" +#include "AppleCSPKeys.h" +#include "pkcs8.h" +#include "cspdebugging.h" + +/* + * Wrap key function. Used for two things: + * + * -- Encrypt and encode a private or session key for export to + * a foreign system or program. Any type of keys may be used + * for the unwrapped key and the wrapping (encrypting) key, + * as long as this CSP understands those keys. The context + * must be of class ALGCLASS_SYMMETRIC or ALGCLASS_ASYMMETRIC, + * matching the wrapping key. + * + * In the absence of an explicit CSSM_ATTRIBUTE_WRAPPED_KEY_FORMAT + * attribute, private keys will be PKCS8 wrapped; session keys will be + * PKCS7 wrapped. Both input keys may be in raw or reference + * format. Wrapped key will have BlobType CSSM_KEYBLOB_WRAPPED. + * + * -- Convert a reference key to a RAW key (with no encrypting). + * This is called a NULL wrap; no wrapping key need be present in + * the context, but the context must be of class + * ALGCLASS_SYMMETRIC and algorithm ALGID_NONE. + * + * There are serious inconsistencies in the specification of wrap + * algorithms to be used in the various CDSA specs (c914.pdf, + * CSP Behavior spec) and between those specs and the PKCS standards + * PKCS7, PKCS8, RFC2630). Here is what this module implements: + * + * On a wrap key op, the caller can add a CSSM_ATTRIBUTE_WRAPPED_KEY_FORMAT + * attribute to the context to specify the wrapping algorithm to be used. + * If it's there, that's what we use if appropriate for the incoming key + * types. Otherwise we figure out a reasonable default from the incoming + * key types. The wrapped key always has the appropriate KeyHeader.Format + * field set indicating how it was wrapped. Defaults are shows below. + * + * The format CSSM_KEYBLOB_WRAPPED_FORMAT_APPLE_CUSTOM is used to indicate + * a modified CMS-style wrapping which is similar to that specified in + * RFC2630, with some modification. + * + * Default wrapping if none specified based on ther unwrapped key as + * follows: + * + * UnwrappedKey Wrap format + * ------------ ----------- + * Symmetric PKCS7 + * Public APPLE_CUSTOM + * FEE private APPLE_CUSTOM + * Other private PKCS8 + */ + +void AppleCSPSession::WrapKey( + CSSM_CC_HANDLE CCHandle, + const Context &Context, + const AccessCredentials &AccessCred, + const CssmKey &UnwrappedKey, + const CssmData *DescriptiveData, + CssmKey &WrappedKey, + CSSM_PRIVILEGE Privilege) +{ + CssmKey::Header &wrappedHdr = WrappedKey.header(); + bool isNullWrap = false; + CssmKey *wrappingKey = NULL; + CSSM_KEYBLOB_FORMAT wrapFormat; + + switch(UnwrappedKey.keyClass()) { + case CSSM_KEYCLASS_PUBLIC_KEY: + case CSSM_KEYCLASS_PRIVATE_KEY: + case CSSM_KEYCLASS_SESSION_KEY: + break; + default: + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS); + } + + /* wrapping key only required for non-NULL wrap */ + wrappingKey = Context.get(CSSM_ATTRIBUTE_KEY); + if(wrappingKey == NULL) { + if((Context.algorithm() == CSSM_ALGID_NONE) && + (Context.type() == CSSM_ALGCLASS_SYMMETRIC)) { + // NULL wrap, OK + isNullWrap = true; + } + else { + errorLog0("WrapKey: missing wrapping key\n"); + CssmError::throwMe(CSSMERR_CSP_MISSING_ATTR_KEY); + } + } + + /* + * Validate misc. params as best we can + */ + if(isNullWrap) { + wrapFormat = CSSM_KEYBLOB_WRAPPED_FORMAT_NONE; + } + else { + /* + * Can only wrap session and private keys. + */ + #if !ALLOW_PUB_KEY_WRAP + if(UnwrappedKey.keyClass() == CSSM_KEYCLASS_PUBLIC_KEY) { + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS); + } + #endif /* ALLOW_PUB_KEY_WRAP */ + cspValidateIntendedKeyUsage(&wrappingKey->KeyHeader, CSSM_KEYUSE_WRAP); + cspVerifyKeyTimes(wrappingKey->KeyHeader); + + /* + * make sure wrapping key type matches context + */ + CSSM_CONTEXT_TYPE wrapType; + switch(wrappingKey->KeyHeader.KeyClass) { + case CSSM_KEYCLASS_PUBLIC_KEY: + case CSSM_KEYCLASS_PRIVATE_KEY: + wrapType = CSSM_ALGCLASS_ASYMMETRIC; + break; + case CSSM_KEYCLASS_SESSION_KEY: + wrapType = CSSM_ALGCLASS_SYMMETRIC; + break; + default: + errorLog0("WrapKey: bad class of wrappingKey\n"); + CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_KEY); + } + if(wrapType != Context.type()) { + errorLog0("WrapKey: mismatch wrappingKey/contextType\n"); + CssmError::throwMe(CSSMERR_CSP_INVALID_CONTEXT); + } + if(Context.algorithm() == CSSM_ALGID_NONE) { + errorLog0("WrapKey: null wrap alg, non-null key\n"); + CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM); + } + + /* + * Get optional wrap format, set default per incoming keys + * Note: no such atrribute ==> 0 ==> FORMAT_NONE, which we + * take to mean "use the default". + */ + wrapFormat = Context.getInt(CSSM_ATTRIBUTE_WRAPPED_KEY_FORMAT); + if(wrapFormat == CSSM_KEYBLOB_WRAPPED_FORMAT_NONE) { + /* figure out a default based on unwrapped key */ + switch(UnwrappedKey.keyClass()) { + case CSSM_KEYCLASS_SESSION_KEY: + wrapFormat = CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS7; + break; + case CSSM_KEYCLASS_PUBLIC_KEY: + wrapFormat = CSSM_KEYBLOB_WRAPPED_FORMAT_APPLE_CUSTOM; + break; + case CSSM_KEYCLASS_PRIVATE_KEY: + switch(UnwrappedKey.algorithm()) { + case CSSM_ALGID_FEE: + wrapFormat = CSSM_KEYBLOB_WRAPPED_FORMAT_APPLE_CUSTOM; + break; + default: + wrapFormat = CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS8; + break; + } + break; + default: + /* NOT REACHED - checked above */ + break; + } + } /* no format present or FORMAT_NONE */ + } + + /* make sure we have a valid format here */ + switch(wrapFormat) { + case CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS7: + if(UnwrappedKey.keyClass() != CSSM_KEYCLASS_SESSION_KEY) { + /* this wrapping style only for symmetric keys */ + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS); + } + break; + case CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS8: + case CSSM_KEYBLOB_WRAPPED_FORMAT_OPENSSL: + if(UnwrappedKey.keyClass() != CSSM_KEYCLASS_PRIVATE_KEY) { + /* these wrapping styles only for private keys */ + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS); + } + break; + case CSSM_KEYBLOB_WRAPPED_FORMAT_APPLE_CUSTOM: + /* no restrictions (well AES can't be the wrap alg but that will + * be caught later */ + break; + case CSSM_KEYBLOB_WRAPPED_FORMAT_OPENSSH1: + /* RSA private key, reference format, only */ + if(UnwrappedKey.keyClass() != CSSM_KEYCLASS_PRIVATE_KEY) { + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS); + } + if(UnwrappedKey.algorithm() != CSSM_ALGID_RSA) { + CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM); + } + if(UnwrappedKey.blobType() != CSSM_KEYBLOB_REFERENCE) { + CssmError::throwMe(CSSMERR_CSP_KEY_BLOB_TYPE_INCORRECT); + } + break; + case CSSM_KEYBLOB_WRAPPED_FORMAT_NONE: + if(isNullWrap) { + /* only time this is OK */ + break; + } + /* else fall thru */ + default: + dprintf1("KeyWrap: invalid wrapFormat (%d)\n", (int)wrapFormat); + CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_WRAPPED_KEY_FORMAT); + } + /* get the blob to be wrappped */ + CssmData rawBlob; + bool allocdRawBlob = false; + CSSM_KEYBLOB_FORMAT rawFormat; + + /* + * Outgoing same as incoming unless a partial key is completed during + * generateKeyBlob() + */ + const CssmKey::Header &unwrappedHdr = UnwrappedKey.header(); + CSSM_KEYATTR_FLAGS unwrappedKeyAttrFlags = unwrappedHdr.KeyAttr; + + switch(UnwrappedKey.blobType()) { + case CSSM_KEYBLOB_RAW: + /* + * Trivial case - we already have the blob. + * This op - wrapping a raw key - is not supported for the + * CSSM_KEYBLOB_WRAPPED_FORMAT_OPENSSH1 format since that doesn't + * operate on a key blob. + */ + rawBlob = CssmData::overlay(UnwrappedKey.KeyData); + rawFormat = UnwrappedKey.blobFormat(); + break; + case CSSM_KEYBLOB_REFERENCE: + /* get binary key, then get blob from it */ + { + BinaryKey &binKey = lookupRefKey(UnwrappedKey); + + /* + * Subsequent tests for extractability: don't trust the + * caller's header; use the one in the BinaryKey. + */ + CSSM_KEYATTR_FLAGS keyAttr = binKey.mKeyHeader.KeyAttr; + if(!(keyAttr & CSSM_KEYATTR_EXTRACTABLE)) { + /* this key not extractable in any form */ + CssmError::throwMe(CSSMERR_CSP_INVALID_KEYATTR_MASK); + } + + /* + * CSSM_KEYBLOB_WRAPPED_FORMAT_OPENSSH1: we're ready to roll; + * all we need is the reference key. + */ + if(wrapFormat == CSSM_KEYBLOB_WRAPPED_FORMAT_OPENSSH1) { + break; + } + + /* + * Null wrap - prevent caller from obtaining + * clear bits if CSSM_KEYATTR_SENSITIVE + */ + if(isNullWrap && (keyAttr & CSSM_KEYATTR_SENSITIVE)) { + CssmError::throwMe(CSSMERR_CSP_INVALID_KEYATTR_MASK); + } + + /* + * Special case for PKCS8 and openssl: need to get blob of a specific + * algorithm-dependent format. Caller can override our + * preference with a + * CSSM_ATTRIBUTE_{PRIVATE,PUBLIC,SESSION}_KEY_FORMAT + * context attribute. + */ + rawFormat = requestedKeyFormat(Context, UnwrappedKey); + if(rawFormat == CSSM_KEYBLOB_RAW_FORMAT_NONE) { + CSSM_ALGORITHMS keyAlg = binKey.mKeyHeader.AlgorithmId; + switch(wrapFormat) { + case CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS8: + rawFormat = pkcs8RawKeyFormat(keyAlg); + break; + case CSSM_KEYBLOB_WRAPPED_FORMAT_OPENSSL: + rawFormat = opensslRawKeyFormat(keyAlg); + break; + default: + /* punt and take default for key type */ + break; + } + } + + /* + * DescriptiveData for encoding, currently only used for + * SSH1 keys. + */ + if((DescriptiveData != NULL) && (DescriptiveData->Length != 0)) { + binKey.descData(*DescriptiveData); + } + + /* optional parameter-bearing key */ + CssmKey *paramKey = Context.get(CSSM_ATTRIBUTE_PARAM_KEY); + binKey.generateKeyBlob(privAllocator, + rawBlob, + rawFormat, + *this, + paramKey, + unwrappedKeyAttrFlags); + } + allocdRawBlob = true; // remember - we need to free + break; + + default: + errorLog0("WrapKey: bad unwrappedKey BlobType\n"); + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY); + } + + /* + * Prepare outgoing header. + */ + setKeyHeader(wrappedHdr, + plugin.myGuid(), + unwrappedHdr.algorithm(), // same as incoming + unwrappedHdr.keyClass(), // same as incoming + unwrappedKeyAttrFlags, + unwrappedHdr.KeyUsage); + wrappedHdr.LogicalKeySizeInBits = unwrappedHdr.LogicalKeySizeInBits; + wrappedHdr.WrapAlgorithmId = Context.algorithm(); // true for null + // and non-Null + wrappedHdr.StartDate = unwrappedHdr.StartDate; + wrappedHdr.EndDate = unwrappedHdr.EndDate; + wrappedHdr.Format = wrapFormat; + if(isNullWrap) { + wrappedHdr.BlobType = CSSM_KEYBLOB_RAW; + } + else { + wrappedHdr.BlobType = CSSM_KEYBLOB_WRAPPED; + } + + /* + * special cases - break out here for Apple Custom and OpenSSHv1 + */ + if(!isNullWrap) { + switch(wrapFormat) { + case CSSM_KEYBLOB_WRAPPED_FORMAT_APPLE_CUSTOM: + try { + WrapKeyCms(CCHandle, + Context, + AccessCred, + UnwrappedKey, + rawBlob, + allocdRawBlob, + DescriptiveData, + WrappedKey, + Privilege); + } + catch(...) { + if(allocdRawBlob) { + freeCssmData(rawBlob, privAllocator); + } + throw; + } + if(allocdRawBlob) { + freeCssmData(rawBlob, privAllocator); + } + return; + case CSSM_KEYBLOB_WRAPPED_FORMAT_OPENSSH1: + { + /* + * 1. We don't have to worry about allocdRawBlob since this + * operation only works on reference keys and we did not + * obtain the raw blob from the BinaryKey. + * 2. This is a redundant lookupRefKey, I know, but since + * that returns a reference, it would just be too messy to have + * the previous call be in the same scope as this. + */ + BinaryKey &binKey = lookupRefKey(UnwrappedKey); + WrapKeyOpenSSH1(CCHandle, + Context, + AccessCred, + binKey, + rawBlob, + allocdRawBlob, + DescriptiveData, + WrappedKey, + Privilege); + return; + } + default: + /* proceed to encrypt blob */ + break; + } + } /* !isNullWrap */ + + + /* + * Generate wrapped blob. Careful, we need to conditionally free + * rawBlob on error. + */ + CssmData encryptedBlob; + CssmData remData; + WrappedKey.KeyData.Data = NULL; // ignore possible incoming KeyData + WrappedKey.KeyData.Length = 0; + + try { + if(isNullWrap) { + /* copy raw blob to caller's wrappedKey */ + copyCssmData(rawBlob, + CssmData::overlay(WrappedKey.KeyData), + normAllocator); + wrappedHdr.Format = rawFormat; + } + else { + /* encrypt rawBlob using caller's context, then encode to + * WrappedKey.KeyData */ + CSSM_SIZE bytesEncrypted; + EncryptData(CCHandle, + Context, + &rawBlob, // ClearBufs[] + 1, // ClearBufCount + &encryptedBlob, // CipherBufs[], + 1, // CipherBufCount, + bytesEncrypted, + remData, + Privilege); + + // I'm not 100% sure about this.... + assert(remData.Length == 0); + encryptedBlob.Length = bytesEncrypted; + WrappedKey.KeyData = encryptedBlob; + wrappedHdr.BlobType = CSSM_KEYBLOB_WRAPPED; + // OK to be zero or not present + wrappedHdr.WrapMode = Context.getInt( + CSSM_ATTRIBUTE_MODE); + } + } + catch (...) { + errorLog0("WrapKey: EncryptData() threw exception\n"); + if(allocdRawBlob) { + freeCssmData(rawBlob, privAllocator); + } + freeCssmData(remData,normAllocator); + throw; + } + if(allocdRawBlob) { + freeCssmData(rawBlob, privAllocator); + } + freeCssmData(remData, normAllocator); +} + +/* + * Unwrap key function. Used for: + * + * -- Given key of BlobType CSSM_KEYBLOB_WRAPPED, decode and decrypt + * it, yielding a key in either raw or reference format. Unwrapping + * key may be either raw or reference. The context must match + * the unwrapping key (ALGCLASS_SYMMETRIC or ALGCLASS_ASYMMETRIC). + * + * Private keys are assumed to be PKCS8 encoded; session keys + * are assumed to be PKCS7 encoded. + * + * -- Convert a Raw key to a reference key (with no decrypting). + * This is called a NULL unwrap; no unwrapping key need be present in + * the context, but the context must be of class + * ALGCLASS_SYMMETRIC and algorithm ALGID_NONE. + */ +void AppleCSPSession::UnwrapKey( + CSSM_CC_HANDLE CCHandle, + const Context &Context, + const CssmKey *PublicKey, + const CssmKey &WrappedKey, + uint32 KeyUsage, + uint32 KeyAttr, + const CssmData *KeyLabel, + const CSSM_RESOURCE_CONTROL_CONTEXT *CredAndAclEntry, + CssmKey &UnwrappedKey, + CssmData &DescriptiveData, + CSSM_PRIVILEGE Privilege) +{ + bool isNullUnwrap = false; + CssmKey *unwrappingKey = NULL; + cspKeyType keyType; // CKT_Public, etc. + CSSM_KEYBLOB_FORMAT wrapFormat = WrappedKey.blobFormat(); + + /* obtain unwrapping key if present */ + unwrappingKey = Context.get(CSSM_ATTRIBUTE_KEY); + if(unwrappingKey == NULL) { + if((Context.algorithm() == CSSM_ALGID_NONE) && + (Context.type() == CSSM_ALGCLASS_SYMMETRIC)) { + // NULL unwrap, OK + isNullUnwrap = true; + } + else { + errorLog0("UnwrapKey: missing wrapping key\n"); + CssmError::throwMe(CSSMERR_CSP_MISSING_ATTR_KEY); + } + } + + /* + * validate unwrappingKey + */ + if(!isNullUnwrap) { + /* make sure unwrapping key type matches context */ + CSSM_CONTEXT_TYPE unwrapType; + switch(unwrappingKey->KeyHeader.KeyClass) { + case CSSM_KEYCLASS_PUBLIC_KEY: + case CSSM_KEYCLASS_PRIVATE_KEY: + unwrapType = CSSM_ALGCLASS_ASYMMETRIC; + break; + case CSSM_KEYCLASS_SESSION_KEY: + unwrapType = CSSM_ALGCLASS_SYMMETRIC; + break; + default: + errorLog0("UnwrapKey: bad class of wrappingKey\n"); + CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_KEY); + } + if(unwrapType != Context.type()) { + errorLog0("UnwrapKey: mismatch unwrappingKey/contextType\n"); + CssmError::throwMe(CSSMERR_CSP_INVALID_CONTEXT); + } + if(Context.algorithm() == CSSM_ALGID_NONE) { + errorLog0("UnwrapKey: null wrap alg, non-null key\n"); + CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM); + } + cspValidateIntendedKeyUsage(&unwrappingKey->KeyHeader, CSSM_KEYUSE_UNWRAP); + cspVerifyKeyTimes(unwrappingKey->KeyHeader); + } + + /* validate WrappedKey */ + switch(WrappedKey.keyClass()) { + case CSSM_KEYCLASS_PUBLIC_KEY: + #if !ALLOW_PUB_KEY_WRAP + if(!isNullUnwrap) { + errorLog0("UnwrapKey: unwrap of public key illegal\n"); + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS); + } + #endif /* ALLOW_PUB_KEY_WRAP */ + keyType = CKT_Public; + break; + case CSSM_KEYCLASS_PRIVATE_KEY: + keyType = CKT_Private; + break; + case CSSM_KEYCLASS_SESSION_KEY: + keyType = CKT_Session; + break; + default: + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS); + } + if(isNullUnwrap) { + if(WrappedKey.blobType() != CSSM_KEYBLOB_RAW) { + errorLog0("UnwrapKey: expected raw blobType\n"); + CssmError::throwMe(CSSMERR_CSP_KEY_BLOB_TYPE_INCORRECT); + } + } + else { + if(WrappedKey.blobType() != CSSM_KEYBLOB_WRAPPED) { + errorLog0("UnwrapKey: expected wrapped blobType\n"); + CssmError::throwMe(CSSMERR_CSP_KEY_BLOB_TYPE_INCORRECT); + } + } + + /* validate requested storage and usage */ + cspKeyStorage keyStorage = cspParseKeyAttr(keyType, KeyAttr); + switch(keyStorage) { + case CKS_Ref: + case CKS_Data: + break; // OK + default: + CssmError::throwMe(CSSMERR_CSP_INVALID_KEYATTR_MASK); + } + cspValidateKeyUsageBits(keyType, KeyUsage); + + /* prepare outgoing header */ + CssmKey::Header &unwrappedHdr = UnwrappedKey.header(); + const CssmKey::Header &wrappedHdr = WrappedKey.header(); + setKeyHeader(unwrappedHdr, + plugin.myGuid(), + wrappedHdr.algorithm(), // same as incoming + wrappedHdr.keyClass(), // same as incoming + KeyAttr & ~KEY_ATTR_RETURN_MASK, + KeyUsage); + unwrappedHdr.LogicalKeySizeInBits = wrappedHdr.LogicalKeySizeInBits; + unwrappedHdr.StartDate = wrappedHdr.StartDate; + unwrappedHdr.EndDate = wrappedHdr.EndDate; + UnwrappedKey.KeyData.Data = NULL; // ignore possible incoming KeyData + UnwrappedKey.KeyData.Length = 0; + + /* validate wrappedKey format */ + if(!isNullUnwrap) { + switch(wrapFormat) { + case CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS7: + if(WrappedKey.keyClass() != CSSM_KEYCLASS_SESSION_KEY) { + /* this unwrapping style only for symmetric keys */ + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS); + } + break; + case CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS8: + case CSSM_KEYBLOB_WRAPPED_FORMAT_OPENSSL: + if(WrappedKey.keyClass() != CSSM_KEYCLASS_PRIVATE_KEY) { + /* these unwrapping styles only for private keys */ + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS); + } + break; + case CSSM_KEYBLOB_WRAPPED_FORMAT_APPLE_CUSTOM: + UnwrapKeyCms(CCHandle, + Context, + WrappedKey, + CredAndAclEntry, + UnwrappedKey, + DescriptiveData, + Privilege, + keyStorage); + return; + case CSSM_KEYBLOB_WRAPPED_FORMAT_OPENSSH1: + /* RSA private key, unwrap to ref key only */ + if(WrappedKey.keyClass() != CSSM_KEYCLASS_PRIVATE_KEY) { + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS); + } + if(WrappedKey.algorithm() != CSSM_ALGID_RSA) { + CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM); + } + if(keyStorage != CKS_Ref) { + errorLog0("UNwrapKey: OPENSSH1 only wraps to reference key\n"); + CssmError::throwMe(CSSMERR_CSP_KEY_BLOB_TYPE_INCORRECT); + } + UnwrapKeyOpenSSH1(CCHandle, + Context, + WrappedKey, + CredAndAclEntry, + UnwrappedKey, + DescriptiveData, + Privilege, + keyStorage); + return; + default: + CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_WRAPPED_KEY_FORMAT); + } + } + + /* Get key blob, decoding and decrypting if necessary */ + CssmData decodedBlob; + CssmData remData; + try { + if(isNullUnwrap) { + /* simple copy of raw blob */ + copyData(WrappedKey.KeyData, + UnwrappedKey.KeyData, + normAllocator); + unwrappedHdr.BlobType = CSSM_KEYBLOB_RAW; + unwrappedHdr.Format = wrapFormat; + } + else { + decodedBlob = CssmData::overlay(WrappedKey.KeyData); + CSSM_SIZE bytesDecrypted; + CssmData *unwrapData = + CssmData::overlay(&UnwrappedKey.KeyData); + + DecryptData(CCHandle, + Context, + &decodedBlob, // CipherBufs[], + 1, // CipherBufCount, + unwrapData, // ClearBufs[] + 1, // ClearBufCount + bytesDecrypted, + remData, + Privilege); + + // I'm not 100% sure about this.... + assert(remData.Length == 0); + UnwrappedKey.KeyData.Length = bytesDecrypted; + unwrappedHdr.BlobType = CSSM_KEYBLOB_RAW; + + /* + * Figure out various header fields from resulting blob + */ + switch(wrapFormat) { + case CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS7: + unwrappedHdr.Format = + CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING; + if(unwrappedHdr.LogicalKeySizeInBits == 0) { + unwrappedHdr.LogicalKeySizeInBits = + bytesDecrypted * 8; + } + /* app has to infer/know algorithm */ + break; + case CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS8: + pkcs8InferKeyHeader(UnwrappedKey); + break; + case CSSM_KEYBLOB_WRAPPED_FORMAT_OPENSSL: + /* + * App told us key algorithm (in WrappedKey). + * Infer format and key size. + */ + opensslInferKeyHeader(UnwrappedKey); + break; + } + } + } + catch (...) { + errorLog0("UnwrapKey: DecryptData() threw exception\n"); + freeCssmData(remData, normAllocator); + throw; + } + freeCssmData(remData, normAllocator); + + /* + * One more thing: cook up a BinaryKey if caller wants a + * reference key. + */ + if(keyStorage == CKS_Ref) { + /* + * We have a key in raw format; convert to BinaryKey. + */ + BinaryKey *binKey = NULL; + CSPKeyInfoProvider *provider = infoProvider(UnwrappedKey); + /* optional parameter-bearing key */ + CssmKey *paramKey = Context.get(CSSM_ATTRIBUTE_PARAM_KEY); + provider->CssmKeyToBinary(paramKey, UnwrappedKey.KeyHeader.KeyAttr, &binKey); + addRefKey(*binKey, UnwrappedKey); + delete provider; + } +} + diff --git a/libsecurity_apple_csp/lib/wrapKeyCms.cpp b/libsecurity_apple_csp/lib/wrapKeyCms.cpp new file mode 100644 index 00000000..b35ac45e --- /dev/null +++ b/libsecurity_apple_csp/lib/wrapKeyCms.cpp @@ -0,0 +1,468 @@ +/* + * 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. + */ + + +// +// wrapKeyCms.cpp - wrap/unwrap key, CMS format +// + +#include "AppleCSPSession.h" +#include "AppleCSPUtils.h" +#include "AppleCSPKeys.h" +#include "cspdebugging.h" + +/* + * + * Here is the algorithm implemented in this module: + * + * Note that DEK is the wrapping key, + * + * 1. PRIVATE_KEY_BYTES is the private data to be wrapped. It consists of the + * following concatenation: + * + * 4-byte length of Descriptive Data, big-endian | + * Descriptive Data | + * rawBlob.Data bytes + * + * 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 octets 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. + * + * TEMP4 is wrappedKey.KeyData. + */ + +/* true: cook up second CCHandle via a new HandleObject + * false - OK to reuse a CCHandle */ +#define USE_SECOND_CCHAND 0 + +/* false : make copy of incoming context before changing IV + * true : resuse OK */ +#define REUSE_CONTEXT 1 + +/* lots'o'printfs in lieu of a debugger which works */ +#define VERBOSE_DEBUG 0 + +static const uint8 magicCmsIv[] = + { 0x4a, 0xdd, 0xa2, 0x2c, 0x79, 0xe8, 0x21, 0x05 }; + +#if VERBOSE_DEBUG +static void dumpBuf( + char *title, + const CSSM_DATA *d, + uint32 maxLen) +{ + unsigned i; + uint32 len; + + if(title) { + printf("%s: ", title); + } + if(d == NULL) { + printf("NO DATA\n"); + return; + } + printf("Total Length: %d\n ", d->Length); + len = maxLen; + if(d->Length < len) { + len = d->Length; + } + for(i=0; iData[i]); + if((i % 16) == 15) { + printf("\n "); + } + } + printf("\n"); +} +#else +#define dumpBuf(t, d, m) +#endif /* VERBOSE_DEBUG */ + + +/* serialize/deserialize uint32, big-endian. */ +static void serializeUint32(uint32 i, uint8 *buf) +{ + *buf++ = (uint8)(i >> 24); + *buf++ = (uint8)(i >> 16); + *buf++ = (uint8)(i >> 8); + *buf = (uint8)i; +} + +static uint32 deserializeUint32(const uint8 *buf) { + uint32 result; + + result = ((uint32)buf[0] << 24) | + ((uint32)buf[1] << 16) | + ((uint32)buf[2] << 8) | + (uint32)buf[3]; + return result; +} + +void AppleCSPSession::WrapKeyCms( + CSSM_CC_HANDLE CCHandle, + const Context &context, + const AccessCredentials &AccessCred, + const CssmKey &UnwrappedKey, + CssmData &rawBlob, + bool allocdRawBlob, // callee has to free rawBlob + const CssmData *DescriptiveData, + CssmKey &WrappedKey, + CSSM_PRIVILEGE Privilege) +{ + uint32 ddLen; + CssmData PRIVATE_KEY_BYTES; + #if !REUSE_CONTEXT + Context secondCtx(context.ContextType, context.AlgorithmType); + secondCtx.copyFrom(context, privAllocator); + #endif /* REUSE_CONTEXT */ + + /* + * 1. PRIVATE_KEY_BYTES is the private data to be wrapped. It consists of the + * following concatenation: + * + * 4-byte length of Descriptive Data, big-endian | + * Descriptive Data | + * rawBlob.Data bytes + */ + dumpBuf("wrap rawBlob", &rawBlob, 24); + dumpBuf("wrap DescriptiveData", DescriptiveData, 24); + + if(DescriptiveData == NULL) { + ddLen = 0; + } + else { + ddLen = DescriptiveData->Length; + } + uint32 pkbLen = 4 + ddLen + rawBlob.Length; + setUpCssmData(PRIVATE_KEY_BYTES, pkbLen, privAllocator); + uint8 *cp = PRIVATE_KEY_BYTES.Data; + serializeUint32(ddLen, cp); + cp += 4; + if(ddLen != 0) { + memcpy(cp, DescriptiveData->Data, ddLen); + cp += ddLen; + } + memcpy(cp, rawBlob.Data, rawBlob.Length); + dumpBuf("wrap PRIVATE_KEY_BYTES", &PRIVATE_KEY_BYTES, 48); + + /* 2. Encrypt PRIVATE_KEY_BYTES using DEK (3DES) and IV in CBC mode with + * PKCS1 padding. Call the ciphertext TEMP1 + * + * We'll just use the caller's context for this. Maybe we should + * validate mode, padding, IV? + */ + CssmData TEMP1; + CSSM_SIZE bytesEncrypted; + CssmData remData; + EncryptData(CCHandle, + context, + &PRIVATE_KEY_BYTES, // ClearBufs[] + 1, // ClearBufCount + &TEMP1, // CipherBufs[], + 1, // CipherBufCount, + bytesEncrypted, + remData, + Privilege); + + // I'm not 100% sure about this.... + assert(remData.Length == 0); + TEMP1.Length = bytesEncrypted; + dumpBuf("wrap TEMP1", &TEMP1, 48); + + /* + * 3. Let TEMP2 = IV || TEMP1. + */ + CssmData TEMP2; + CssmData &IV = context.get(CSSM_ATTRIBUTE_INIT_VECTOR, + CSSMERR_CSP_MISSING_ATTR_INIT_VECTOR); + setUpCssmData(TEMP2, IV.Length + TEMP1.Length, privAllocator); + memcpy(TEMP2.Data, IV.Data, IV.Length); + memcpy(TEMP2.Data + IV.Length, TEMP1.Data, TEMP1.Length); + dumpBuf("wrap TEMP2", &TEMP2, 56); + + + /* + * 4. Reverse the order of the octets in TEMP2 call the result + * TEMP3. + */ + CssmData TEMP3; + setUpCssmData(TEMP3, TEMP2.Length, privAllocator); + uint8 *cp2 = TEMP2.Data + TEMP2.Length - 1; + cp = TEMP3.Data; + for(uint32 i=0; i + * actually is in the context and not a copy! + */ + #if REUSE_CONTEXT + CssmData &IV2 = context.get(CSSM_ATTRIBUTE_INIT_VECTOR, + CSSMERR_CSP_MISSING_ATTR_INIT_VECTOR); + #else + CssmData &IV2 = secondCtx.get(CSSM_ATTRIBUTE_INIT_VECTOR, + CSSMERR_CSP_MISSING_ATTR_INIT_VECTOR); + #endif /* REUSE_CONTEXT */ + + uint8 *savedIV = IV2.Data; + uint32 savedIVLen = IV2.Length; + IV2.Data = (uint8 *)magicCmsIv; + IV2.Length = 8; + CssmData &outBlob = CssmData::overlay(WrappedKey.KeyData); + outBlob.Length = 0; + outBlob.Data = NULL; + try { + EncryptData(CCHandle, + #if REUSE_CONTEXT + context, + #else + secondCtx, + #endif /* REUSE_CONTEXT */ + + &TEMP3, // ClearBufs[] + 1, // ClearBufCount + &outBlob, // CipherBufs[], + 1, // CipherBufCount, + bytesEncrypted, + remData, + Privilege); + } + catch (...) { + IV2.Data = savedIV; + IV2.Length = savedIVLen; + throw; // and leak + } + IV2.Data = savedIV; + IV2.Length = savedIVLen; + + // I'm not 100% sure about this.... + assert(remData.Length == 0); + outBlob.Length = bytesEncrypted; + dumpBuf("wrap outBlob", &outBlob, 64); + + /* outgoing header */ + WrappedKey.KeyHeader.BlobType = CSSM_KEYBLOB_WRAPPED; + // OK to be zero or not present + WrappedKey.KeyHeader.WrapMode = context.getInt(CSSM_ATTRIBUTE_MODE); + WrappedKey.KeyHeader.Format = CSSM_KEYBLOB_WRAPPED_FORMAT_APPLE_CUSTOM; + + /* free resources */ + freeCssmData(PRIVATE_KEY_BYTES, privAllocator); + freeCssmData(TEMP1, normAllocator); // alloc via encrypt + freeCssmData(TEMP2, privAllocator); + freeCssmData(TEMP3, privAllocator); + if(allocdRawBlob) { + /* our caller mallocd this when dereferencing a ref key */ + freeCssmData(rawBlob, privAllocator); + } +} + +/* note we expect an IV present in the context though we don't use it + * FIXME - we should figure out how to add this attribute at this level + */ + +/* safety trap - don't try to malloc anything bigger than this - we get + * sizes from the processed bit stream.... */ +#define MAX_MALLOC_SIZE 0x10000 + +void AppleCSPSession::UnwrapKeyCms( + CSSM_CC_HANDLE CCHandle, + const Context &Context, + const CssmKey &WrappedKey, + const CSSM_RESOURCE_CONTROL_CONTEXT *CredAndAclEntry, + CssmKey &UnwrappedKey, + CssmData &DescriptiveData, + CSSM_PRIVILEGE Privilege, + cspKeyStorage keyStorage) +{ + /* + * In reverse order, the steps from wrap... + * + * 5. Encrypt TEMP3 using DEK with an IV of 0x4adda22c79e82105 in CBC mode + * with PKCS1 padding call the result TEMP4. + * + * TEMP4 is wrappedKey.KeyData. + */ + const CssmData &wrappedBlob = CssmData::overlay(WrappedKey.KeyData); + dumpBuf("unwrap inBlob", &wrappedBlob, 64); + CssmData &IV1 = Context.get(CSSM_ATTRIBUTE_INIT_VECTOR, + CSSMERR_CSP_MISSING_ATTR_INIT_VECTOR); + uint8 *savedIV = IV1.Data; + uint32 savedIvLen = IV1.Length; + IV1.Data = (uint8 *)magicCmsIv; + IV1.Length = 8; + CssmData TEMP3; + CSSM_SIZE bytesDecrypted; + CssmData remData; + + try { + DecryptData(CCHandle, + Context, + &wrappedBlob, // CipherBufs[], + 1, // CipherBufCount, + &TEMP3, // ClearBufs[] + 1, // ClearBufCount + bytesDecrypted, + remData, + Privilege); + } + catch(...) { + IV1.Data = savedIV; + IV1.Length = savedIvLen; + throw; + } + IV1.Data = savedIV; + IV1.Length = savedIvLen; + // I'm not 100% sure about this.... + assert(remData.Length == 0); + TEMP3.Length = bytesDecrypted; + dumpBuf("unwrap TEMP3", &TEMP3, 64); + + /* + * 4. Reverse the order of the octets in TEMP2 call the result + * TEMP3. + * + * i.e., TEMP2 := reverse(TEMP3) + */ + CssmData TEMP2; + setUpCssmData(TEMP2, TEMP3.Length, privAllocator); + uint8 *src = TEMP3.Data + TEMP3.Length - 1; + uint8 *dst = TEMP2.Data; + for(uint32 i=0; i MAX_MALLOC_SIZE) { + dprintf0("UnwrapKeyCms: preposterous ddLen in PRIVATE_KEY_BYTES\n"); + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY); + } + setUpCssmData(DescriptiveData, ddLen, normAllocator); + memcpy(DescriptiveData.Data, cp1, ddLen); + cp1 += ddLen; + uint32 outBlobLen = PRIVATE_KEY_BYTES.Length - ddLen - 4; + if(ddLen > MAX_MALLOC_SIZE) { + dprintf0("UnwrapKeyCms: preposterous outBlobLen in PRIVATE_KEY_BYTES\n"); + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY); + } + CssmData &outBlob = CssmData::overlay(UnwrappedKey.KeyData); + setUpCssmData(outBlob, outBlobLen, normAllocator); + memcpy(outBlob.Data, cp1, outBlobLen); + + /* set up outgoing header */ + UnwrappedKey.KeyHeader.BlobType = CSSM_KEYBLOB_RAW; + UnwrappedKey.KeyHeader.Format = inferFormat(UnwrappedKey); + + /* + * Cook up a BinaryKey if caller wants a reference key. + */ + if(keyStorage == CKS_Ref) { + BinaryKey *binKey = NULL; + CSPKeyInfoProvider *provider = infoProvider(UnwrappedKey); + /* optional parameter-bearing key */ + CssmKey *paramKey = Context.get(CSSM_ATTRIBUTE_PARAM_KEY); + provider->CssmKeyToBinary(paramKey, UnwrappedKey.KeyHeader.KeyAttr, &binKey); + addRefKey(*binKey, UnwrappedKey); + delete provider; + } + /* free resources */ + freeCssmData(PRIVATE_KEY_BYTES, normAllocator); // alloc via decrypt + freeCssmData(TEMP1, privAllocator); + freeCssmData(IV2, privAllocator); + freeCssmData(TEMP2, privAllocator); + freeCssmData(TEMP3, normAllocator); // via decrypt + +} + diff --git a/libsecurity_apple_csp/libsecurity_apple_csp.xcodeproj/project.pbxproj b/libsecurity_apple_csp/libsecurity_apple_csp.xcodeproj/project.pbxproj new file mode 100644 index 00000000..8db494d8 --- /dev/null +++ b/libsecurity_apple_csp/libsecurity_apple_csp.xcodeproj/project.pbxproj @@ -0,0 +1,1460 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXAggregateTarget section */ + 0539107D0A37721E00B9E848 /* Copy Open Source Docs */ = { + isa = PBXAggregateTarget; + buildConfigurationList = 053910860A37725A00B9E848 /* Build configuration list for PBXAggregateTarget "Copy Open Source Docs" */; + buildPhases = ( + 0539107C0A37721E00B9E848 /* CopyFiles */, + 053910850A37725A00B9E848 /* CopyFiles */, + ); + dependencies = ( + ); + name = "Copy Open Source Docs"; + productName = "Copy Open Source Docs"; + }; +/* End PBXAggregateTarget section */ + +/* Begin PBXBuildFile section */ + 053910830A37725A00B9E848 /* libsecurity_apple_csp.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = 053910810A37725A00B9E848 /* libsecurity_apple_csp.plist */; }; + 0539108B0A37726600B9E848 /* libsecurity_apple_csp.txt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 053910820A37725A00B9E848 /* libsecurity_apple_csp.txt */; }; + 053ABEFF0AA4C94900CA6DC3 /* opensshCoding.h in Headers */ = {isa = PBXBuildFile; fileRef = 053ABEFD0AA4C94900CA6DC3 /* opensshCoding.h */; }; + 053ABF000AA4C94900CA6DC3 /* opensshCoding.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 053ABEFE0AA4C94900CA6DC3 /* opensshCoding.cpp */; }; + 053ABF620AA4F3EB00CA6DC3 /* opensshWrap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 053ABF600AA4F3EB00CA6DC3 /* opensshWrap.cpp */; }; + 05622BAC06CC352100784EED /* SHA2_Object.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 05622BAA06CC352100784EED /* SHA2_Object.cpp */; }; + 05622BAD06CC352100784EED /* SHA2_Object.h in Headers */ = {isa = PBXBuildFile; fileRef = 05622BAB06CC352100784EED /* SHA2_Object.h */; }; + 05BFEE0E09E1D71800F3D7E0 /* HMACSHA1.c in Sources */ = {isa = PBXBuildFile; fileRef = 05BFEE0C09E1D71800F3D7E0 /* HMACSHA1.c */; }; + 05BFEE0F09E1D71800F3D7E0 /* HMACSHA1.h in Headers */ = {isa = PBXBuildFile; fileRef = 05BFEE0D09E1D71800F3D7E0 /* HMACSHA1.h */; }; + C2196B3A053B5905005808D4 /* AppleCSPBuiltin.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2196B39053B5905005808D4 /* AppleCSPBuiltin.cpp */; }; + C280AE6F0534BBD900F7E802 /* bf_ecb.c in Sources */ = {isa = PBXBuildFile; fileRef = C280ADE80534BBD900F7E802 /* bf_ecb.c */; }; + C280AE700534BBD900F7E802 /* bf_enc.c in Sources */ = {isa = PBXBuildFile; fileRef = C280ADE90534BBD900F7E802 /* bf_enc.c */; }; + C280AE710534BBD900F7E802 /* bf_locl.h in Headers */ = {isa = PBXBuildFile; fileRef = C280ADEA0534BBD900F7E802 /* bf_locl.h */; }; + C280AE720534BBD900F7E802 /* bf_pi.h in Headers */ = {isa = PBXBuildFile; fileRef = C280ADEB0534BBD900F7E802 /* bf_pi.h */; }; + C280AE730534BBD900F7E802 /* bf_skey.c in Sources */ = {isa = PBXBuildFile; fileRef = C280ADEC0534BBD900F7E802 /* bf_skey.c */; }; + C280AE740534BBD900F7E802 /* bio_lib.c in Sources */ = {isa = PBXBuildFile; fileRef = C280ADF00534BBD900F7E802 /* bio_lib.c */; }; + C280AE750534BBD900F7E802 /* bss_file.c in Sources */ = {isa = PBXBuildFile; fileRef = C280ADF10534BBD900F7E802 /* bss_file.c */; }; + C280AE760534BBD900F7E802 /* bn_add.c in Sources */ = {isa = PBXBuildFile; fileRef = C280ADF30534BBD900F7E802 /* bn_add.c */; }; + C280AE770534BBD900F7E802 /* bn_asm.c in Sources */ = {isa = PBXBuildFile; fileRef = C280ADF40534BBD900F7E802 /* bn_asm.c */; }; + C280AE780534BBD900F7E802 /* bn_blind.c in Sources */ = {isa = PBXBuildFile; fileRef = C280ADF50534BBD900F7E802 /* bn_blind.c */; }; + C280AE790534BBD900F7E802 /* bn_ctx.c in Sources */ = {isa = PBXBuildFile; fileRef = C280ADF60534BBD900F7E802 /* bn_ctx.c */; }; + C280AE7A0534BBD900F7E802 /* bn_div.c in Sources */ = {isa = PBXBuildFile; fileRef = C280ADF70534BBD900F7E802 /* bn_div.c */; }; + C280AE7B0534BBD900F7E802 /* bn_err.c in Sources */ = {isa = PBXBuildFile; fileRef = C280ADF80534BBD900F7E802 /* bn_err.c */; }; + C280AE7C0534BBD900F7E802 /* bn_exp.c in Sources */ = {isa = PBXBuildFile; fileRef = C280ADF90534BBD900F7E802 /* bn_exp.c */; }; + C280AE7D0534BBD900F7E802 /* bn_exp2.c in Sources */ = {isa = PBXBuildFile; fileRef = C280ADFA0534BBD900F7E802 /* bn_exp2.c */; }; + C280AE7E0534BBD900F7E802 /* bn_gcd.c in Sources */ = {isa = PBXBuildFile; fileRef = C280ADFB0534BBD900F7E802 /* bn_gcd.c */; }; + C280AE7F0534BBD900F7E802 /* bn_lcl.h in Headers */ = {isa = PBXBuildFile; fileRef = C280ADFC0534BBD900F7E802 /* bn_lcl.h */; }; + C280AE800534BBD900F7E802 /* bn_lib.c in Sources */ = {isa = PBXBuildFile; fileRef = C280ADFD0534BBD900F7E802 /* bn_lib.c */; }; + C280AE810534BBD900F7E802 /* bn_mont.c in Sources */ = {isa = PBXBuildFile; fileRef = C280ADFE0534BBD900F7E802 /* bn_mont.c */; }; + C280AE820534BBD900F7E802 /* bn_mpi.c in Sources */ = {isa = PBXBuildFile; fileRef = C280ADFF0534BBD900F7E802 /* bn_mpi.c */; }; + C280AE830534BBD900F7E802 /* bn_mul.c in Sources */ = {isa = PBXBuildFile; fileRef = C280AE000534BBD900F7E802 /* bn_mul.c */; }; + C280AE840534BBD900F7E802 /* bn_prime.c in Sources */ = {isa = PBXBuildFile; fileRef = C280AE010534BBD900F7E802 /* bn_prime.c */; }; + C280AE850534BBD900F7E802 /* bn_prime.h in Headers */ = {isa = PBXBuildFile; fileRef = C280AE020534BBD900F7E802 /* bn_prime.h */; }; + C280AE860534BBD900F7E802 /* bn_print.c in Sources */ = {isa = PBXBuildFile; fileRef = C280AE030534BBD900F7E802 /* bn_print.c */; }; + C280AE870534BBD900F7E802 /* bn_rand.c in Sources */ = {isa = PBXBuildFile; fileRef = C280AE040534BBD900F7E802 /* bn_rand.c */; }; + C280AE880534BBD900F7E802 /* bn_recp.c in Sources */ = {isa = PBXBuildFile; fileRef = C280AE050534BBD900F7E802 /* bn_recp.c */; }; + C280AE890534BBD900F7E802 /* bn_shift.c in Sources */ = {isa = PBXBuildFile; fileRef = C280AE060534BBD900F7E802 /* bn_shift.c */; }; + C280AE8A0534BBD900F7E802 /* bn_sqr.c in Sources */ = {isa = PBXBuildFile; fileRef = C280AE070534BBD900F7E802 /* bn_sqr.c */; }; + C280AE8B0534BBD900F7E802 /* bn_word.c in Sources */ = {isa = PBXBuildFile; fileRef = C280AE080534BBD900F7E802 /* bn_word.c */; }; + C280AE930534BBD900F7E802 /* buf_err.c in Sources */ = {isa = PBXBuildFile; fileRef = C280AE110534BBD900F7E802 /* buf_err.c */; }; + C280AE940534BBD900F7E802 /* buffer.c in Sources */ = {isa = PBXBuildFile; fileRef = C280AE120534BBD900F7E802 /* buffer.c */; }; + C280AE9A0534BBD900F7E802 /* cryptlib.c in Sources */ = {isa = PBXBuildFile; fileRef = C280AE190534BBD900F7E802 /* cryptlib.c */; }; + C280AE9B0534BBD900F7E802 /* cryptlib.h in Headers */ = {isa = PBXBuildFile; fileRef = C280AE1A0534BBD900F7E802 /* cryptlib.h */; }; + C280AE9C0534BBD900F7E802 /* dh_check.c in Sources */ = {isa = PBXBuildFile; fileRef = C280AE1C0534BBD900F7E802 /* dh_check.c */; }; + C280AE9D0534BBD900F7E802 /* dh_err.c in Sources */ = {isa = PBXBuildFile; fileRef = C280AE1D0534BBD900F7E802 /* dh_err.c */; }; + C280AE9E0534BBD900F7E802 /* dh_gen.c in Sources */ = {isa = PBXBuildFile; fileRef = C280AE1E0534BBD900F7E802 /* dh_gen.c */; }; + C280AE9F0534BBD900F7E802 /* dh_key.c in Sources */ = {isa = PBXBuildFile; fileRef = C280AE1F0534BBD900F7E802 /* dh_key.c */; }; + C280AEA00534BBD900F7E802 /* dh_lib.c in Sources */ = {isa = PBXBuildFile; fileRef = C280AE200534BBD900F7E802 /* dh_lib.c */; }; + C280AEA10534BBD900F7E802 /* dsa_asn1.c in Sources */ = {isa = PBXBuildFile; fileRef = C280AE220534BBD900F7E802 /* dsa_asn1.c */; }; + C280AEA20534BBD900F7E802 /* dsa_err.c in Sources */ = {isa = PBXBuildFile; fileRef = C280AE230534BBD900F7E802 /* dsa_err.c */; }; + C280AEA30534BBD900F7E802 /* dsa_gen.c in Sources */ = {isa = PBXBuildFile; fileRef = C280AE240534BBD900F7E802 /* dsa_gen.c */; }; + C280AEA40534BBD900F7E802 /* dsa_key.c in Sources */ = {isa = PBXBuildFile; fileRef = C280AE250534BBD900F7E802 /* dsa_key.c */; }; + C280AEA50534BBD900F7E802 /* dsa_lib.c in Sources */ = {isa = PBXBuildFile; fileRef = C280AE260534BBD900F7E802 /* dsa_lib.c */; }; + C280AEA60534BBD900F7E802 /* dsa_ossl.c in Sources */ = {isa = PBXBuildFile; fileRef = C280AE270534BBD900F7E802 /* dsa_ossl.c */; }; + C280AEA70534BBD900F7E802 /* dsa_sign.c in Sources */ = {isa = PBXBuildFile; fileRef = C280AE280534BBD900F7E802 /* dsa_sign.c */; }; + C280AEA80534BBD900F7E802 /* dsa_vrf.c in Sources */ = {isa = PBXBuildFile; fileRef = C280AE290534BBD900F7E802 /* dsa_vrf.c */; }; + C280AEA90534BBD900F7E802 /* err.c in Sources */ = {isa = PBXBuildFile; fileRef = C280AE2B0534BBD900F7E802 /* err.c */; }; + C280AEAA0534BBD900F7E802 /* err_prn.c in Sources */ = {isa = PBXBuildFile; fileRef = C280AE2C0534BBD900F7E802 /* err_prn.c */; }; + C280AEAB0534BBD900F7E802 /* ex_data.c in Sources */ = {isa = PBXBuildFile; fileRef = C280AE2D0534BBD900F7E802 /* ex_data.c */; }; + C280AEAC0534BBD900F7E802 /* lhash.c in Sources */ = {isa = PBXBuildFile; fileRef = C280AE2F0534BBD900F7E802 /* lhash.c */; }; + C280AEAD0534BBD900F7E802 /* mem.c in Sources */ = {isa = PBXBuildFile; fileRef = C280AE310534BBD900F7E802 /* mem.c */; }; + C280AEAF0534BBD900F7E802 /* rc2_cbc.c in Sources */ = {isa = PBXBuildFile; fileRef = C280AE340534BBD900F7E802 /* rc2_cbc.c */; }; + C280AEB00534BBD900F7E802 /* rc2_locl.h in Headers */ = {isa = PBXBuildFile; fileRef = C280AE350534BBD900F7E802 /* rc2_locl.h */; }; + C280AEB10534BBD900F7E802 /* rc2_skey.c in Sources */ = {isa = PBXBuildFile; fileRef = C280AE360534BBD900F7E802 /* rc2_skey.c */; }; + C280AEB40534BBD900F7E802 /* rc5_enc.c in Sources */ = {isa = PBXBuildFile; fileRef = C280AE390534BBD900F7E802 /* rc5_enc.c */; }; + C280AEB50534BBD900F7E802 /* rc5_locl.h in Headers */ = {isa = PBXBuildFile; fileRef = C280AE3A0534BBD900F7E802 /* rc5_locl.h */; }; + C280AEB60534BBD900F7E802 /* rc5_skey.c in Sources */ = {isa = PBXBuildFile; fileRef = C280AE3B0534BBD900F7E802 /* rc5_skey.c */; }; + C280AEB70534BBD900F7E802 /* asn1.h in Headers */ = {isa = PBXBuildFile; fileRef = C280AE3D0534BBD900F7E802 /* asn1.h */; }; + C280AEB80534BBD900F7E802 /* bio.h in Headers */ = {isa = PBXBuildFile; fileRef = C280AE3E0534BBD900F7E802 /* bio.h */; }; + C280AEB90534BBD900F7E802 /* blowfish.h in Headers */ = {isa = PBXBuildFile; fileRef = C280AE3F0534BBD900F7E802 /* blowfish.h */; }; + C280AEBA0534BBD900F7E802 /* bn.h in Headers */ = {isa = PBXBuildFile; fileRef = C280AE400534BBD900F7E802 /* bn.h */; }; + C280AEBB0534BBD900F7E802 /* buffer.h in Headers */ = {isa = PBXBuildFile; fileRef = C280AE410534BBD900F7E802 /* buffer.h */; }; + C280AEBC0534BBD900F7E802 /* cast.h in Headers */ = {isa = PBXBuildFile; fileRef = C280AE420534BBD900F7E802 /* cast.h */; }; + C280AEBD0534BBD900F7E802 /* crypto.h in Headers */ = {isa = PBXBuildFile; fileRef = C280AE430534BBD900F7E802 /* crypto.h */; }; + C280AEBE0534BBD900F7E802 /* dh.h in Headers */ = {isa = PBXBuildFile; fileRef = C280AE440534BBD900F7E802 /* dh.h */; }; + C280AEBF0534BBD900F7E802 /* dsa.h in Headers */ = {isa = PBXBuildFile; fileRef = C280AE450534BBD900F7E802 /* dsa.h */; }; + C280AEC00534BBD900F7E802 /* e_os.h in Headers */ = {isa = PBXBuildFile; fileRef = C280AE460534BBD900F7E802 /* e_os.h */; }; + C280AEC10534BBD900F7E802 /* e_os2.h in Headers */ = {isa = PBXBuildFile; fileRef = C280AE470534BBD900F7E802 /* e_os2.h */; }; + C280AEC20534BBD900F7E802 /* err.h in Headers */ = {isa = PBXBuildFile; fileRef = C280AE480534BBD900F7E802 /* err.h */; }; + C280AEC30534BBD900F7E802 /* evp.h in Headers */ = {isa = PBXBuildFile; fileRef = C280AE490534BBD900F7E802 /* evp.h */; }; + C280AEC40534BBD900F7E802 /* lhash.h in Headers */ = {isa = PBXBuildFile; fileRef = C280AE4A0534BBD900F7E802 /* lhash.h */; }; + C280AEC60534BBD900F7E802 /* objects.h in Headers */ = {isa = PBXBuildFile; fileRef = C280AE4C0534BBD900F7E802 /* objects.h */; }; + C280AEC70534BBD900F7E802 /* openssl_pkcs7.h in Headers */ = {isa = PBXBuildFile; fileRef = C280AE4D0534BBD900F7E802 /* openssl_pkcs7.h */; }; + C280AEC80534BBD900F7E802 /* opensslconf.h in Headers */ = {isa = PBXBuildFile; fileRef = C280AE4E0534BBD900F7E802 /* opensslconf.h */; }; + C280AEC90534BBD900F7E802 /* opensslv.h in Headers */ = {isa = PBXBuildFile; fileRef = C280AE4F0534BBD900F7E802 /* opensslv.h */; }; + C280AECA0534BBD900F7E802 /* rand.h in Headers */ = {isa = PBXBuildFile; fileRef = C280AE500534BBD900F7E802 /* rand.h */; }; + C280AECB0534BBD900F7E802 /* rc2.h in Headers */ = {isa = PBXBuildFile; fileRef = C280AE510534BBD900F7E802 /* rc2.h */; }; + C280AECD0534BBD900F7E802 /* rc5.h in Headers */ = {isa = PBXBuildFile; fileRef = C280AE530534BBD900F7E802 /* rc5.h */; }; + C280AECE0534BBD900F7E802 /* rsa.h in Headers */ = {isa = PBXBuildFile; fileRef = C280AE540534BBD900F7E802 /* rsa.h */; }; + C280AECF0534BBD900F7E802 /* safestack.h in Headers */ = {isa = PBXBuildFile; fileRef = C280AE550534BBD900F7E802 /* safestack.h */; }; + C280AED10534BBD900F7E802 /* stack.h in Headers */ = {isa = PBXBuildFile; fileRef = C280AE570534BBD900F7E802 /* stack.h */; }; + C280AED20534BBD900F7E802 /* x509.h in Headers */ = {isa = PBXBuildFile; fileRef = C280AE580534BBD900F7E802 /* x509.h */; }; + C280AED30534BBD900F7E802 /* x509_vfy.h in Headers */ = {isa = PBXBuildFile; fileRef = C280AE590534BBD900F7E802 /* x509_vfy.h */; }; + C280AED40534BBD900F7E802 /* opensslAsn1.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C280AE5B0534BBD900F7E802 /* opensslAsn1.cpp */; }; + C280AED50534BBD900F7E802 /* opensslAsn1.h in Headers */ = {isa = PBXBuildFile; fileRef = C280AE5C0534BBD900F7E802 /* opensslAsn1.h */; }; + C280AED60534BBD900F7E802 /* opensslUtils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C280AE5D0534BBD900F7E802 /* opensslUtils.cpp */; }; + C280AED70534BBD900F7E802 /* opensslUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = C280AE5E0534BBD900F7E802 /* opensslUtils.h */; }; + C280AEDA0534BBD900F7E802 /* rsa_chk.c in Sources */ = {isa = PBXBuildFile; fileRef = C280AE620534BBD900F7E802 /* rsa_chk.c */; }; + C280AEDB0534BBD900F7E802 /* rsa_eay.c in Sources */ = {isa = PBXBuildFile; fileRef = C280AE630534BBD900F7E802 /* rsa_eay.c */; }; + C280AEDC0534BBD900F7E802 /* rsa_err.c in Sources */ = {isa = PBXBuildFile; fileRef = C280AE640534BBD900F7E802 /* rsa_err.c */; }; + C280AEDD0534BBD900F7E802 /* rsa_gen.c in Sources */ = {isa = PBXBuildFile; fileRef = C280AE650534BBD900F7E802 /* rsa_gen.c */; }; + C280AEDE0534BBD900F7E802 /* rsa_lib.c in Sources */ = {isa = PBXBuildFile; fileRef = C280AE660534BBD900F7E802 /* rsa_lib.c */; }; + C280AEDF0534BBD900F7E802 /* rsa_none.c in Sources */ = {isa = PBXBuildFile; fileRef = C280AE670534BBD900F7E802 /* rsa_none.c */; }; + C280AEE00534BBD900F7E802 /* rsa_null.c in Sources */ = {isa = PBXBuildFile; fileRef = C280AE680534BBD900F7E802 /* rsa_null.c */; }; + C280AEE10534BBD900F7E802 /* rsa_pk1.c in Sources */ = {isa = PBXBuildFile; fileRef = C280AE690534BBD900F7E802 /* rsa_pk1.c */; }; + C280AEE20534BBD900F7E802 /* rsa_saos.c in Sources */ = {isa = PBXBuildFile; fileRef = C280AE6A0534BBD900F7E802 /* rsa_saos.c */; }; + C280AEE30534BBD900F7E802 /* rsa_sign.c in Sources */ = {isa = PBXBuildFile; fileRef = C280AE6B0534BBD900F7E802 /* rsa_sign.c */; }; + C280AEE40534BBD900F7E802 /* rsa_ssl.c in Sources */ = {isa = PBXBuildFile; fileRef = C280AE6C0534BBD900F7E802 /* rsa_ssl.c */; }; + C280AEE50534BBD900F7E802 /* stack.c in Sources */ = {isa = PBXBuildFile; fileRef = C280AE6E0534BBD900F7E802 /* stack.c */; }; + C284377C053488AC000AE0FC /* aesCommon.h in Headers */ = {isa = PBXBuildFile; fileRef = C28436FD053488AB000AE0FC /* aesCommon.h */; }; + C284377D053488AC000AE0FC /* aescsp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C28436FE053488AB000AE0FC /* aescsp.cpp */; }; + C284377E053488AC000AE0FC /* aescspi.h in Headers */ = {isa = PBXBuildFile; fileRef = C28436FF053488AB000AE0FC /* aescspi.h */; }; + C284377F053488AC000AE0FC /* algmaker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2843700053488AB000AE0FC /* algmaker.cpp */; }; + C2843780053488AC000AE0FC /* AppleCSP.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2843701053488AB000AE0FC /* AppleCSP.cpp */; }; + C2843781053488AC000AE0FC /* AppleCSP.h in Headers */ = {isa = PBXBuildFile; fileRef = C2843702053488AB000AE0FC /* AppleCSP.h */; }; + C2843782053488AC000AE0FC /* AppleCSPContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2843703053488AB000AE0FC /* AppleCSPContext.cpp */; }; + C2843783053488AC000AE0FC /* AppleCSPContext.h in Headers */ = {isa = PBXBuildFile; fileRef = C2843704053488AB000AE0FC /* AppleCSPContext.h */; }; + C2843784053488AC000AE0FC /* AppleCSPKeys.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2843705053488AB000AE0FC /* AppleCSPKeys.cpp */; }; + C2843785053488AC000AE0FC /* AppleCSPKeys.h in Headers */ = {isa = PBXBuildFile; fileRef = C2843706053488AB000AE0FC /* AppleCSPKeys.h */; }; + C2843787053488AC000AE0FC /* AppleCSPSession.h in Headers */ = {isa = PBXBuildFile; fileRef = C2843708053488AB000AE0FC /* AppleCSPSession.h */; }; + C2843788053488AC000AE0FC /* AppleCSPUtils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2843709053488AB000AE0FC /* AppleCSPUtils.cpp */; }; + C2843789053488AC000AE0FC /* AppleCSPUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = C284370A053488AB000AE0FC /* AppleCSPUtils.h */; }; + C284378A053488AC000AE0FC /* ascContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C284370B053488AB000AE0FC /* ascContext.cpp */; }; + C284378B053488AC000AE0FC /* ascContext.h in Headers */ = {isa = PBXBuildFile; fileRef = C284370C053488AB000AE0FC /* ascContext.h */; }; + C284378C053488AC000AE0FC /* ascFactory.h in Headers */ = {isa = PBXBuildFile; fileRef = C284370D053488AB000AE0FC /* ascFactory.h */; }; + C284378D053488AC000AE0FC /* bfContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C284370E053488AB000AE0FC /* bfContext.cpp */; }; + C284378E053488AC000AE0FC /* bfContext.h in Headers */ = {isa = PBXBuildFile; fileRef = C284370F053488AB000AE0FC /* bfContext.h */; }; + C284378F053488AC000AE0FC /* BinaryKey.h in Headers */ = {isa = PBXBuildFile; fileRef = C2843710053488AB000AE0FC /* BinaryKey.h */; }; + C2843790053488AC000AE0FC /* BlockCryptor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2843711053488AB000AE0FC /* BlockCryptor.cpp */; }; + C2843791053488AC000AE0FC /* BlockCryptor.h in Headers */ = {isa = PBXBuildFile; fileRef = C2843712053488AB000AE0FC /* BlockCryptor.h */; }; + C2843792053488AC000AE0FC /* boxes-ref.c in Sources */ = {isa = PBXBuildFile; fileRef = C2843713053488AB000AE0FC /* boxes-ref.c */; }; + C2843793053488AC000AE0FC /* boxes-ref.h in Headers */ = {isa = PBXBuildFile; fileRef = C2843714053488AB000AE0FC /* boxes-ref.h */; }; + C2843794053488AC000AE0FC /* bsafeAsymmetric.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2843715053488AB000AE0FC /* bsafeAsymmetric.cpp */; }; + C2843795053488AC000AE0FC /* bsafeContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2843716053488AB000AE0FC /* bsafeContext.cpp */; }; + C2843796053488AC000AE0FC /* bsafecsp.h in Headers */ = {isa = PBXBuildFile; fileRef = C2843717053488AB000AE0FC /* bsafecsp.h */; }; + C2843797053488AC000AE0FC /* bsafecspi.h in Headers */ = {isa = PBXBuildFile; fileRef = C2843718053488AB000AE0FC /* bsafecspi.h */; }; + C2843798053488AC000AE0FC /* bsafeKeyGen.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2843719053488AB000AE0FC /* bsafeKeyGen.cpp */; }; + C2843799053488AC000AE0FC /* bsafePKCS1.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C284371A053488AB000AE0FC /* bsafePKCS1.cpp */; }; + C284379A053488AC000AE0FC /* bsafePKCS1.h in Headers */ = {isa = PBXBuildFile; fileRef = C284371B053488AB000AE0FC /* bsafePKCS1.h */; }; + C284379B053488AC000AE0FC /* bsafeSymmetric.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C284371C053488AB000AE0FC /* bsafeSymmetric.cpp */; }; + C284379C053488AC000AE0FC /* bsobjects.h in Headers */ = {isa = PBXBuildFile; fileRef = C284371D053488AB000AE0FC /* bsobjects.h */; }; + C284379D053488AC000AE0FC /* castContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C284371E053488AB000AE0FC /* castContext.cpp */; }; + C284379E053488AC000AE0FC /* castContext.h in Headers */ = {isa = PBXBuildFile; fileRef = C284371F053488AB000AE0FC /* castContext.h */; }; + C28437A1053488AC000AE0FC /* cryptkitcsp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2843722053488AB000AE0FC /* cryptkitcsp.cpp */; }; + C28437A2053488AC000AE0FC /* cryptkitcsp.h in Headers */ = {isa = PBXBuildFile; fileRef = C2843723053488AB000AE0FC /* cryptkitcsp.h */; }; + C28437A4053488AC000AE0FC /* CryptKitSpace.h in Headers */ = {isa = PBXBuildFile; fileRef = C2843725053488AB000AE0FC /* CryptKitSpace.h */; }; + C28437A5053488AC000AE0FC /* cspdebugging.c in Sources */ = {isa = PBXBuildFile; fileRef = C2843726053488AB000AE0FC /* cspdebugging.c */; }; + C28437A6053488AC000AE0FC /* cspdebugging.h in Headers */ = {isa = PBXBuildFile; fileRef = C2843727053488AB000AE0FC /* cspdebugging.h */; }; + C28437A8053488AC000AE0FC /* deriveKey.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2843729053488AB000AE0FC /* deriveKey.cpp */; }; + C28437AB053488AC000AE0FC /* desContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C284372C053488AB000AE0FC /* desContext.cpp */; }; + C28437AC053488AC000AE0FC /* desContext.h in Headers */ = {isa = PBXBuildFile; fileRef = C284372D053488AB000AE0FC /* desContext.h */; }; + C28437AD053488AC000AE0FC /* DH_csp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C284372E053488AB000AE0FC /* DH_csp.cpp */; }; + C28437AE053488AC000AE0FC /* DH_csp.h in Headers */ = {isa = PBXBuildFile; fileRef = C284372F053488AB000AE0FC /* DH_csp.h */; }; + C28437AF053488AC000AE0FC /* DH_exchange.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2843730053488AB000AE0FC /* DH_exchange.cpp */; }; + C28437B0053488AC000AE0FC /* DH_exchange.h in Headers */ = {isa = PBXBuildFile; fileRef = C2843731053488AB000AE0FC /* DH_exchange.h */; }; + C28437B1053488AC000AE0FC /* DH_keys.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2843732053488AB000AE0FC /* DH_keys.cpp */; }; + C28437B2053488AC000AE0FC /* DH_keys.h in Headers */ = {isa = PBXBuildFile; fileRef = C2843733053488AB000AE0FC /* DH_keys.h */; }; + C28437B3053488AC000AE0FC /* DH_utils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2843734053488AB000AE0FC /* DH_utils.cpp */; }; + C28437B4053488AC000AE0FC /* DH_utils.h in Headers */ = {isa = PBXBuildFile; fileRef = C2843735053488AB000AE0FC /* DH_utils.h */; }; + C28437B5053488AC000AE0FC /* DigestContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2843736053488AB000AE0FC /* DigestContext.cpp */; }; + C28437B6053488AC000AE0FC /* DigestContext.h in Headers */ = {isa = PBXBuildFile; fileRef = C2843737053488AB000AE0FC /* DigestContext.h */; }; + C28437B7053488AC000AE0FC /* FEEAsymmetricContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2843738053488AB000AE0FC /* FEEAsymmetricContext.cpp */; }; + C28437B8053488AC000AE0FC /* FEEAsymmetricContext.h in Headers */ = {isa = PBXBuildFile; fileRef = C2843739053488AB000AE0FC /* FEEAsymmetricContext.h */; }; + C28437B9053488AC000AE0FC /* FEECSPUtils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C284373A053488AB000AE0FC /* FEECSPUtils.cpp */; }; + C28437BA053488AC000AE0FC /* FEECSPUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = C284373B053488AB000AE0FC /* FEECSPUtils.h */; }; + C28437BB053488AC000AE0FC /* FEEKeys.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C284373C053488AB000AE0FC /* FEEKeys.cpp */; }; + C28437BC053488AC000AE0FC /* FEEKeys.h in Headers */ = {isa = PBXBuildFile; fileRef = C284373D053488AB000AE0FC /* FEEKeys.h */; }; + C28437BD053488AC000AE0FC /* FEESignatureObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C284373E053488AB000AE0FC /* FEESignatureObject.cpp */; }; + C28437BE053488AC000AE0FC /* FEESignatureObject.h in Headers */ = {isa = PBXBuildFile; fileRef = C284373F053488AB000AE0FC /* FEESignatureObject.h */; }; + C28437BF053488AC000AE0FC /* gladmanContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2843740053488AB000AE0FC /* gladmanContext.cpp */; }; + C28437C0053488AC000AE0FC /* gladmanContext.h in Headers */ = {isa = PBXBuildFile; fileRef = C2843741053488AB000AE0FC /* gladmanContext.h */; }; + C28437C3053488AC000AE0FC /* MacContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2843744053488AB000AE0FC /* MacContext.cpp */; }; + C28437C4053488AC000AE0FC /* MacContext.h in Headers */ = {isa = PBXBuildFile; fileRef = C2843745053488AB000AE0FC /* MacContext.h */; }; + C28437C5053488AC000AE0FC /* MD2Object.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2843746053488AB000AE0FC /* MD2Object.cpp */; }; + C28437C6053488AC000AE0FC /* MD2Object.h in Headers */ = {isa = PBXBuildFile; fileRef = C2843747053488AB000AE0FC /* MD2Object.h */; }; + C28437C9053488AC000AE0FC /* memory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C284374A053488AB000AE0FC /* memory.cpp */; }; + C28437CA053488AC000AE0FC /* miscAlgFactory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C284374B053488AB000AE0FC /* miscAlgFactory.cpp */; }; + C28437CB053488AC000AE0FC /* miscAlgFactory.h in Headers */ = {isa = PBXBuildFile; fileRef = C284374C053488AB000AE0FC /* miscAlgFactory.h */; }; + C28437CC053488AC000AE0FC /* miscalgorithms.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C284374D053488AB000AE0FC /* miscalgorithms.cpp */; }; + C28437CD053488AC000AE0FC /* NullCryptor.h in Headers */ = {isa = PBXBuildFile; fileRef = C284374E053488AC000AE0FC /* NullCryptor.h */; }; + C28437CE053488AC000AE0FC /* pbkdDigest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C284374F053488AC000AE0FC /* pbkdDigest.cpp */; }; + C28437CF053488AC000AE0FC /* pbkdDigest.h in Headers */ = {isa = PBXBuildFile; fileRef = C2843750053488AC000AE0FC /* pbkdDigest.h */; }; + C28437D0053488AC000AE0FC /* pbkdf2.c in Sources */ = {isa = PBXBuildFile; fileRef = C2843751053488AC000AE0FC /* pbkdf2.c */; }; + C28437D1053488AC000AE0FC /* pbkdf2.h in Headers */ = {isa = PBXBuildFile; fileRef = C2843752053488AC000AE0FC /* pbkdf2.h */; }; + C28437D2053488AC000AE0FC /* pkcs12Derive.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2843753053488AC000AE0FC /* pkcs12Derive.cpp */; }; + C28437D3053488AC000AE0FC /* pkcs12Derive.h in Headers */ = {isa = PBXBuildFile; fileRef = C2843754053488AC000AE0FC /* pkcs12Derive.h */; }; + C28437D4053488AC000AE0FC /* pkcs8.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2843755053488AC000AE0FC /* pkcs8.cpp */; }; + C28437D5053488AC000AE0FC /* pkcs8.h in Headers */ = {isa = PBXBuildFile; fileRef = C2843756053488AC000AE0FC /* pkcs8.h */; }; + C28437D7053488AC000AE0FC /* RawSigner.h in Headers */ = {isa = PBXBuildFile; fileRef = C2843758053488AC000AE0FC /* RawSigner.h */; }; + C28437D8053488AC000AE0FC /* rc2Context.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2843759053488AC000AE0FC /* rc2Context.cpp */; }; + C28437D9053488AC000AE0FC /* rc2Context.h in Headers */ = {isa = PBXBuildFile; fileRef = C284375A053488AC000AE0FC /* rc2Context.h */; }; + C28437DA053488AC000AE0FC /* rc4Context.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C284375B053488AC000AE0FC /* rc4Context.cpp */; }; + C28437DB053488AC000AE0FC /* rc4Context.h in Headers */ = {isa = PBXBuildFile; fileRef = C284375C053488AC000AE0FC /* rc4Context.h */; }; + C28437DC053488AC000AE0FC /* rc5Context.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C284375D053488AC000AE0FC /* rc5Context.cpp */; }; + C28437DD053488AC000AE0FC /* rc5Context.h in Headers */ = {isa = PBXBuildFile; fileRef = C284375E053488AC000AE0FC /* rc5Context.h */; }; + C28437DE053488AC000AE0FC /* rijndael-alg-ref.c in Sources */ = {isa = PBXBuildFile; fileRef = C284375F053488AC000AE0FC /* rijndael-alg-ref.c */; }; + C28437DF053488AC000AE0FC /* rijndael-alg-ref.h in Headers */ = {isa = PBXBuildFile; fileRef = C2843760053488AC000AE0FC /* rijndael-alg-ref.h */; }; + C28437E0053488AC000AE0FC /* rijndaelApi.c in Sources */ = {isa = PBXBuildFile; fileRef = C2843761053488AC000AE0FC /* rijndaelApi.c */; }; + C28437E1053488AC000AE0FC /* rijndaelApi.h in Headers */ = {isa = PBXBuildFile; fileRef = C2843762053488AC000AE0FC /* rijndaelApi.h */; }; + C28437E4053488AC000AE0FC /* RSA_asymmetric.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2843765053488AC000AE0FC /* RSA_asymmetric.cpp */; }; + C28437E5053488AC000AE0FC /* RSA_asymmetric.h in Headers */ = {isa = PBXBuildFile; fileRef = C2843766053488AC000AE0FC /* RSA_asymmetric.h */; }; + C28437E6053488AC000AE0FC /* RSA_DSA_csp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2843767053488AC000AE0FC /* RSA_DSA_csp.cpp */; }; + C28437E7053488AC000AE0FC /* RSA_DSA_csp.h in Headers */ = {isa = PBXBuildFile; fileRef = C2843768053488AC000AE0FC /* RSA_DSA_csp.h */; }; + C28437E8053488AC000AE0FC /* RSA_DSA_keys.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2843769053488AC000AE0FC /* RSA_DSA_keys.cpp */; }; + C28437E9053488AC000AE0FC /* RSA_DSA_keys.h in Headers */ = {isa = PBXBuildFile; fileRef = C284376A053488AC000AE0FC /* RSA_DSA_keys.h */; }; + C28437EA053488AC000AE0FC /* RSA_DSA_signature.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C284376B053488AC000AE0FC /* RSA_DSA_signature.cpp */; }; + C28437EB053488AC000AE0FC /* RSA_DSA_signature.h in Headers */ = {isa = PBXBuildFile; fileRef = C284376C053488AC000AE0FC /* RSA_DSA_signature.h */; }; + C28437EC053488AC000AE0FC /* RSA_DSA_utils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C284376D053488AC000AE0FC /* RSA_DSA_utils.cpp */; }; + C28437ED053488AC000AE0FC /* RSA_DSA_utils.h in Headers */ = {isa = PBXBuildFile; fileRef = C284376E053488AC000AE0FC /* RSA_DSA_utils.h */; }; + C28437F0053488AC000AE0FC /* SHA1_MD5_Object.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2843771053488AC000AE0FC /* SHA1_MD5_Object.cpp */; }; + C28437F1053488AC000AE0FC /* SHA1_MD5_Object.h in Headers */ = {isa = PBXBuildFile; fileRef = C2843772053488AC000AE0FC /* SHA1_MD5_Object.h */; }; + C28437F4053488AC000AE0FC /* SignatureContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2843775053488AC000AE0FC /* SignatureContext.cpp */; }; + C28437F5053488AC000AE0FC /* SignatureContext.h in Headers */ = {isa = PBXBuildFile; fileRef = C2843776053488AC000AE0FC /* SignatureContext.h */; }; + C28437F6053488AC000AE0FC /* vRijndael-alg-ref.c in Sources */ = {isa = PBXBuildFile; fileRef = C2843777053488AC000AE0FC /* vRijndael-alg-ref.c */; }; + C28437F7053488AC000AE0FC /* wrapKey.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2843778053488AC000AE0FC /* wrapKey.cpp */; }; + C28437F8053488AC000AE0FC /* wrapKeyCms.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2843779053488AC000AE0FC /* wrapKeyCms.cpp */; }; + C28437F9053488AC000AE0FC /* YarrowConnection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C284377A053488AC000AE0FC /* YarrowConnection.cpp */; }; + C28437FA053488AC000AE0FC /* YarrowConnection.h in Headers */ = {isa = PBXBuildFile; fileRef = C284377B053488AC000AE0FC /* YarrowConnection.h */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 0539107F0A37724600B9E848 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4CA1FEAB052A3C3800F22E42 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 0539107D0A37721E00B9E848; + remoteInfo = "Copy Open Source Docs"; + }; + 182BB344146F10ED000BF1F3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 18446090146DFBC800B12992 /* libsecurity_cdsa_plugin.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = C2C38A530535EDE600D7421F; + remoteInfo = libsecurity_cdsa_plugin_generate; + }; + 18446095146DFBC900B12992 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 18446090146DFBC800B12992 /* libsecurity_cdsa_plugin.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 4CA1FEBE052A3C8100F22E42; + remoteInfo = libsecurity_cdsa_plugin; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 0539107C0A37721E00B9E848 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = /usr/local/OpenSourceVersions/; + dstSubfolderSpec = 0; + files = ( + 053910830A37725A00B9E848 /* libsecurity_apple_csp.plist in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 1; + }; + 053910850A37725A00B9E848 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = /usr/local/OpenSourceLicenses/; + dstSubfolderSpec = 0; + files = ( + 0539108B0A37726600B9E848 /* libsecurity_apple_csp.txt in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 1; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 053910810A37725A00B9E848 /* libsecurity_apple_csp.plist */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.plist.xml; path = libsecurity_apple_csp.plist; sourceTree = ""; }; + 053910820A37725A00B9E848 /* libsecurity_apple_csp.txt */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = libsecurity_apple_csp.txt; sourceTree = ""; }; + 053ABEFD0AA4C94900CA6DC3 /* opensshCoding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = opensshCoding.h; sourceTree = ""; }; + 053ABEFE0AA4C94900CA6DC3 /* opensshCoding.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = opensshCoding.cpp; sourceTree = ""; }; + 053ABF600AA4F3EB00CA6DC3 /* opensshWrap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = opensshWrap.cpp; sourceTree = ""; }; + 05622BAA06CC352100784EED /* SHA2_Object.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SHA2_Object.cpp; sourceTree = ""; }; + 05622BAB06CC352100784EED /* SHA2_Object.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SHA2_Object.h; sourceTree = ""; }; + 05BFEE0C09E1D71800F3D7E0 /* HMACSHA1.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = HMACSHA1.c; sourceTree = ""; }; + 05BFEE0D09E1D71800F3D7E0 /* HMACSHA1.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = HMACSHA1.h; sourceTree = ""; }; + 18446065146DE98E00B12992 /* base.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = base.xcconfig; sourceTree = ""; }; + 18446066146DE98E00B12992 /* debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = debug.xcconfig; sourceTree = ""; }; + 18446067146DE98E00B12992 /* lib.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = lib.xcconfig; sourceTree = ""; }; + 18446068146DE98E00B12992 /* release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = release.xcconfig; sourceTree = ""; }; + 18446090146DFBC800B12992 /* libsecurity_cdsa_plugin.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libsecurity_cdsa_plugin.xcodeproj; path = ../libsecurity_cdsa_plugin/libsecurity_cdsa_plugin.xcodeproj; sourceTree = ""; }; + 4094B0DC057EA70300B44BCC /* csp_capabilities.mdsinfo */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.xml; path = csp_capabilities.mdsinfo; sourceTree = ""; }; + 4094B0DD057EA70300B44BCC /* csp_capabilities_common.mds */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.xml; path = csp_capabilities_common.mds; sourceTree = ""; }; + 4094B0DE057EA70300B44BCC /* csp_common.mdsinfo */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.xml; path = csp_common.mdsinfo; sourceTree = ""; }; + 4094B0DF057EA70300B44BCC /* csp_primary.mdsinfo */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.xml; path = csp_primary.mdsinfo; sourceTree = ""; }; + 4CA1FEBE052A3C8100F22E42 /* libsecurity_apple_csp.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libsecurity_apple_csp.a; sourceTree = BUILT_PRODUCTS_DIR; }; + C2196B39053B5905005808D4 /* AppleCSPBuiltin.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = AppleCSPBuiltin.cpp; sourceTree = ""; }; + C280ADE80534BBD900F7E802 /* bf_ecb.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = bf_ecb.c; sourceTree = ""; }; + C280ADE90534BBD900F7E802 /* bf_enc.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = bf_enc.c; sourceTree = ""; }; + C280ADEA0534BBD900F7E802 /* bf_locl.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = bf_locl.h; sourceTree = ""; }; + C280ADEB0534BBD900F7E802 /* bf_pi.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = bf_pi.h; sourceTree = ""; }; + C280ADEC0534BBD900F7E802 /* bf_skey.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = bf_skey.c; sourceTree = ""; }; + C280ADED0534BBD900F7E802 /* COPYRIGHT */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = COPYRIGHT; sourceTree = ""; }; + C280ADEE0534BBD900F7E802 /* README */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = README; sourceTree = ""; }; + C280ADF00534BBD900F7E802 /* bio_lib.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = bio_lib.c; sourceTree = ""; }; + C280ADF10534BBD900F7E802 /* bss_file.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = bss_file.c; sourceTree = ""; }; + C280ADF30534BBD900F7E802 /* bn_add.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = bn_add.c; sourceTree = ""; }; + C280ADF40534BBD900F7E802 /* bn_asm.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = bn_asm.c; sourceTree = ""; }; + C280ADF50534BBD900F7E802 /* bn_blind.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = bn_blind.c; sourceTree = ""; }; + C280ADF60534BBD900F7E802 /* bn_ctx.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = bn_ctx.c; sourceTree = ""; }; + C280ADF70534BBD900F7E802 /* bn_div.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = bn_div.c; sourceTree = ""; }; + C280ADF80534BBD900F7E802 /* bn_err.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = bn_err.c; sourceTree = ""; }; + C280ADF90534BBD900F7E802 /* bn_exp.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = bn_exp.c; sourceTree = ""; }; + C280ADFA0534BBD900F7E802 /* bn_exp2.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = bn_exp2.c; sourceTree = ""; }; + C280ADFB0534BBD900F7E802 /* bn_gcd.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = bn_gcd.c; sourceTree = ""; }; + C280ADFC0534BBD900F7E802 /* bn_lcl.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = bn_lcl.h; sourceTree = ""; }; + C280ADFD0534BBD900F7E802 /* bn_lib.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = bn_lib.c; sourceTree = ""; }; + C280ADFE0534BBD900F7E802 /* bn_mont.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = bn_mont.c; sourceTree = ""; }; + C280ADFF0534BBD900F7E802 /* bn_mpi.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = bn_mpi.c; sourceTree = ""; }; + C280AE000534BBD900F7E802 /* bn_mul.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = bn_mul.c; sourceTree = ""; }; + C280AE010534BBD900F7E802 /* bn_prime.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = bn_prime.c; sourceTree = ""; }; + C280AE020534BBD900F7E802 /* bn_prime.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = bn_prime.h; sourceTree = ""; }; + C280AE030534BBD900F7E802 /* bn_print.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = bn_print.c; sourceTree = ""; }; + C280AE040534BBD900F7E802 /* bn_rand.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = bn_rand.c; sourceTree = ""; }; + C280AE050534BBD900F7E802 /* bn_recp.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = bn_recp.c; sourceTree = ""; }; + C280AE060534BBD900F7E802 /* bn_shift.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = bn_shift.c; sourceTree = ""; }; + C280AE070534BBD900F7E802 /* bn_sqr.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = bn_sqr.c; sourceTree = ""; }; + C280AE080534BBD900F7E802 /* bn_word.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = bn_word.c; sourceTree = ""; }; + C280AE090534BBD900F7E802 /* bnspeed.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = bnspeed.c; sourceTree = ""; }; + C280AE0A0534BBD900F7E802 /* bntest.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = bntest.c; sourceTree = ""; }; + C280AE0B0534BBD900F7E802 /* divtest.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = divtest.c; sourceTree = ""; }; + C280AE0C0534BBD900F7E802 /* exp.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = exp.c; sourceTree = ""; }; + C280AE0D0534BBD900F7E802 /* expspeed.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = expspeed.c; sourceTree = ""; }; + C280AE0E0534BBD900F7E802 /* exptest.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = exptest.c; sourceTree = ""; }; + C280AE0F0534BBD900F7E802 /* vms-helper.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = "vms-helper.c"; sourceTree = ""; }; + C280AE110534BBD900F7E802 /* buf_err.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = buf_err.c; sourceTree = ""; }; + C280AE120534BBD900F7E802 /* buffer.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = buffer.c; sourceTree = ""; }; + C280AE190534BBD900F7E802 /* cryptlib.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = cryptlib.c; sourceTree = ""; }; + C280AE1A0534BBD900F7E802 /* cryptlib.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cryptlib.h; sourceTree = ""; }; + C280AE1C0534BBD900F7E802 /* dh_check.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = dh_check.c; sourceTree = ""; }; + C280AE1D0534BBD900F7E802 /* dh_err.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = dh_err.c; sourceTree = ""; }; + C280AE1E0534BBD900F7E802 /* dh_gen.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = dh_gen.c; sourceTree = ""; }; + C280AE1F0534BBD900F7E802 /* dh_key.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = dh_key.c; sourceTree = ""; }; + C280AE200534BBD900F7E802 /* dh_lib.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = dh_lib.c; sourceTree = ""; }; + C280AE220534BBD900F7E802 /* dsa_asn1.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = dsa_asn1.c; sourceTree = ""; }; + C280AE230534BBD900F7E802 /* dsa_err.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = dsa_err.c; sourceTree = ""; }; + C280AE240534BBD900F7E802 /* dsa_gen.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = dsa_gen.c; sourceTree = ""; }; + C280AE250534BBD900F7E802 /* dsa_key.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = dsa_key.c; sourceTree = ""; }; + C280AE260534BBD900F7E802 /* dsa_lib.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = dsa_lib.c; sourceTree = ""; }; + C280AE270534BBD900F7E802 /* dsa_ossl.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = dsa_ossl.c; sourceTree = ""; }; + C280AE280534BBD900F7E802 /* dsa_sign.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = dsa_sign.c; sourceTree = ""; }; + C280AE290534BBD900F7E802 /* dsa_vrf.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = dsa_vrf.c; sourceTree = ""; }; + C280AE2B0534BBD900F7E802 /* err.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = err.c; sourceTree = ""; }; + C280AE2C0534BBD900F7E802 /* err_prn.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = err_prn.c; sourceTree = ""; }; + C280AE2D0534BBD900F7E802 /* ex_data.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = ex_data.c; sourceTree = ""; }; + C280AE2F0534BBD900F7E802 /* lhash.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = lhash.c; sourceTree = ""; }; + C280AE300534BBD900F7E802 /* LICENSE */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = LICENSE; sourceTree = ""; }; + C280AE310534BBD900F7E802 /* mem.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = mem.c; sourceTree = ""; }; + C280AE340534BBD900F7E802 /* rc2_cbc.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = rc2_cbc.c; sourceTree = ""; }; + C280AE350534BBD900F7E802 /* rc2_locl.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = rc2_locl.h; sourceTree = ""; }; + C280AE360534BBD900F7E802 /* rc2_skey.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = rc2_skey.c; sourceTree = ""; }; + C280AE390534BBD900F7E802 /* rc5_enc.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = rc5_enc.c; sourceTree = ""; }; + C280AE3A0534BBD900F7E802 /* rc5_locl.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = rc5_locl.h; sourceTree = ""; }; + C280AE3B0534BBD900F7E802 /* rc5_skey.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = rc5_skey.c; sourceTree = ""; }; + C280AE3D0534BBD900F7E802 /* asn1.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = asn1.h; sourceTree = ""; }; + C280AE3E0534BBD900F7E802 /* bio.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = bio.h; sourceTree = ""; }; + C280AE3F0534BBD900F7E802 /* blowfish.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = blowfish.h; sourceTree = ""; }; + C280AE400534BBD900F7E802 /* bn.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = bn.h; sourceTree = ""; }; + C280AE410534BBD900F7E802 /* buffer.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = buffer.h; sourceTree = ""; }; + C280AE420534BBD900F7E802 /* cast.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cast.h; sourceTree = ""; }; + C280AE430534BBD900F7E802 /* crypto.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = crypto.h; sourceTree = ""; }; + C280AE440534BBD900F7E802 /* dh.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = dh.h; sourceTree = ""; }; + C280AE450534BBD900F7E802 /* dsa.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = dsa.h; sourceTree = ""; }; + C280AE460534BBD900F7E802 /* e_os.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = e_os.h; sourceTree = ""; }; + C280AE470534BBD900F7E802 /* e_os2.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = e_os2.h; sourceTree = ""; }; + C280AE480534BBD900F7E802 /* err.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = err.h; sourceTree = ""; }; + C280AE490534BBD900F7E802 /* evp.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = evp.h; sourceTree = ""; }; + C280AE4A0534BBD900F7E802 /* lhash.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = lhash.h; sourceTree = ""; }; + C280AE4C0534BBD900F7E802 /* objects.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = objects.h; sourceTree = ""; }; + C280AE4D0534BBD900F7E802 /* openssl_pkcs7.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = openssl_pkcs7.h; sourceTree = ""; }; + C280AE4E0534BBD900F7E802 /* opensslconf.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = opensslconf.h; sourceTree = ""; }; + C280AE4F0534BBD900F7E802 /* opensslv.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = opensslv.h; sourceTree = ""; }; + C280AE500534BBD900F7E802 /* rand.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = rand.h; sourceTree = ""; }; + C280AE510534BBD900F7E802 /* rc2.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = rc2.h; sourceTree = ""; }; + C280AE530534BBD900F7E802 /* rc5.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = rc5.h; sourceTree = ""; }; + C280AE540534BBD900F7E802 /* rsa.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = rsa.h; sourceTree = ""; }; + C280AE550534BBD900F7E802 /* safestack.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = safestack.h; sourceTree = ""; }; + C280AE570534BBD900F7E802 /* stack.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = stack.h; sourceTree = ""; }; + C280AE580534BBD900F7E802 /* x509.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = x509.h; sourceTree = ""; }; + C280AE590534BBD900F7E802 /* x509_vfy.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = x509_vfy.h; sourceTree = ""; }; + C280AE5B0534BBD900F7E802 /* opensslAsn1.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = opensslAsn1.cpp; sourceTree = ""; }; + C280AE5C0534BBD900F7E802 /* opensslAsn1.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = opensslAsn1.h; sourceTree = ""; }; + C280AE5D0534BBD900F7E802 /* opensslUtils.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = opensslUtils.cpp; sourceTree = ""; }; + C280AE5E0534BBD900F7E802 /* opensslUtils.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = opensslUtils.h; sourceTree = ""; }; + C280AE620534BBD900F7E802 /* rsa_chk.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = rsa_chk.c; sourceTree = ""; }; + C280AE630534BBD900F7E802 /* rsa_eay.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = rsa_eay.c; sourceTree = ""; }; + C280AE640534BBD900F7E802 /* rsa_err.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = rsa_err.c; sourceTree = ""; }; + C280AE650534BBD900F7E802 /* rsa_gen.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = rsa_gen.c; sourceTree = ""; }; + C280AE660534BBD900F7E802 /* rsa_lib.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = rsa_lib.c; sourceTree = ""; }; + C280AE670534BBD900F7E802 /* rsa_none.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = rsa_none.c; sourceTree = ""; }; + C280AE680534BBD900F7E802 /* rsa_null.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = rsa_null.c; sourceTree = ""; }; + C280AE690534BBD900F7E802 /* rsa_pk1.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = rsa_pk1.c; sourceTree = ""; }; + C280AE6A0534BBD900F7E802 /* rsa_saos.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = rsa_saos.c; sourceTree = ""; }; + C280AE6B0534BBD900F7E802 /* rsa_sign.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = rsa_sign.c; sourceTree = ""; }; + C280AE6C0534BBD900F7E802 /* rsa_ssl.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = rsa_ssl.c; sourceTree = ""; }; + C280AE6E0534BBD900F7E802 /* stack.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = stack.c; sourceTree = ""; }; + C28436FD053488AB000AE0FC /* aesCommon.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = aesCommon.h; sourceTree = ""; }; + C28436FE053488AB000AE0FC /* aescsp.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = aescsp.cpp; sourceTree = ""; }; + C28436FF053488AB000AE0FC /* aescspi.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = aescspi.h; sourceTree = ""; }; + C2843700053488AB000AE0FC /* algmaker.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = algmaker.cpp; sourceTree = ""; }; + C2843701053488AB000AE0FC /* AppleCSP.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = AppleCSP.cpp; sourceTree = ""; }; + C2843702053488AB000AE0FC /* AppleCSP.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = AppleCSP.h; sourceTree = ""; }; + C2843703053488AB000AE0FC /* AppleCSPContext.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = AppleCSPContext.cpp; sourceTree = ""; }; + C2843704053488AB000AE0FC /* AppleCSPContext.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = AppleCSPContext.h; sourceTree = ""; }; + C2843705053488AB000AE0FC /* AppleCSPKeys.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = AppleCSPKeys.cpp; sourceTree = ""; }; + C2843706053488AB000AE0FC /* AppleCSPKeys.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = AppleCSPKeys.h; sourceTree = ""; }; + C2843707053488AB000AE0FC /* AppleCSPPlugin.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = AppleCSPPlugin.cpp; sourceTree = ""; }; + C2843708053488AB000AE0FC /* AppleCSPSession.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = AppleCSPSession.h; sourceTree = ""; }; + C2843709053488AB000AE0FC /* AppleCSPUtils.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = AppleCSPUtils.cpp; sourceTree = ""; }; + C284370A053488AB000AE0FC /* AppleCSPUtils.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = AppleCSPUtils.h; sourceTree = ""; }; + C284370B053488AB000AE0FC /* ascContext.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ascContext.cpp; sourceTree = ""; }; + C284370C053488AB000AE0FC /* ascContext.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ascContext.h; sourceTree = ""; }; + C284370D053488AB000AE0FC /* ascFactory.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ascFactory.h; sourceTree = ""; }; + C284370E053488AB000AE0FC /* bfContext.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = bfContext.cpp; sourceTree = ""; }; + C284370F053488AB000AE0FC /* bfContext.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = bfContext.h; sourceTree = ""; }; + C2843710053488AB000AE0FC /* BinaryKey.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = BinaryKey.h; sourceTree = ""; }; + C2843711053488AB000AE0FC /* BlockCryptor.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = BlockCryptor.cpp; sourceTree = ""; }; + C2843712053488AB000AE0FC /* BlockCryptor.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = BlockCryptor.h; sourceTree = ""; }; + C2843713053488AB000AE0FC /* boxes-ref.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = "boxes-ref.c"; sourceTree = ""; }; + C2843714053488AB000AE0FC /* boxes-ref.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = "boxes-ref.h"; sourceTree = ""; }; + C2843715053488AB000AE0FC /* bsafeAsymmetric.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = bsafeAsymmetric.cpp; sourceTree = ""; }; + C2843716053488AB000AE0FC /* bsafeContext.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = bsafeContext.cpp; sourceTree = ""; }; + C2843717053488AB000AE0FC /* bsafecsp.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = bsafecsp.h; sourceTree = ""; }; + C2843718053488AB000AE0FC /* bsafecspi.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = bsafecspi.h; sourceTree = ""; }; + C2843719053488AB000AE0FC /* bsafeKeyGen.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = bsafeKeyGen.cpp; sourceTree = ""; }; + C284371A053488AB000AE0FC /* bsafePKCS1.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = bsafePKCS1.cpp; sourceTree = ""; }; + C284371B053488AB000AE0FC /* bsafePKCS1.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = bsafePKCS1.h; sourceTree = ""; }; + C284371C053488AB000AE0FC /* bsafeSymmetric.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = bsafeSymmetric.cpp; sourceTree = ""; }; + C284371D053488AB000AE0FC /* bsobjects.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = bsobjects.h; sourceTree = ""; }; + C284371E053488AB000AE0FC /* castContext.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = castContext.cpp; sourceTree = ""; }; + C284371F053488AB000AE0FC /* castContext.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = castContext.h; sourceTree = ""; }; + C2843722053488AB000AE0FC /* cryptkitcsp.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = cryptkitcsp.cpp; sourceTree = ""; }; + C2843723053488AB000AE0FC /* cryptkitcsp.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cryptkitcsp.h; sourceTree = ""; }; + C2843725053488AB000AE0FC /* CryptKitSpace.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = CryptKitSpace.h; sourceTree = ""; }; + C2843726053488AB000AE0FC /* cspdebugging.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = cspdebugging.c; sourceTree = ""; }; + C2843727053488AB000AE0FC /* cspdebugging.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cspdebugging.h; sourceTree = ""; }; + C2843728053488AB000AE0FC /* cssmplugin.exp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.exports; path = cssmplugin.exp; sourceTree = ""; }; + C2843729053488AB000AE0FC /* deriveKey.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = deriveKey.cpp; sourceTree = ""; }; + C284372C053488AB000AE0FC /* desContext.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = desContext.cpp; sourceTree = ""; }; + C284372D053488AB000AE0FC /* desContext.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = desContext.h; sourceTree = ""; }; + C284372E053488AB000AE0FC /* DH_csp.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = DH_csp.cpp; sourceTree = ""; }; + C284372F053488AB000AE0FC /* DH_csp.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DH_csp.h; sourceTree = ""; }; + C2843730053488AB000AE0FC /* DH_exchange.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = DH_exchange.cpp; sourceTree = ""; }; + C2843731053488AB000AE0FC /* DH_exchange.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DH_exchange.h; sourceTree = ""; }; + C2843732053488AB000AE0FC /* DH_keys.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = DH_keys.cpp; sourceTree = ""; }; + C2843733053488AB000AE0FC /* DH_keys.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DH_keys.h; sourceTree = ""; }; + C2843734053488AB000AE0FC /* DH_utils.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = DH_utils.cpp; sourceTree = ""; }; + C2843735053488AB000AE0FC /* DH_utils.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DH_utils.h; sourceTree = ""; }; + C2843736053488AB000AE0FC /* DigestContext.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = DigestContext.cpp; sourceTree = ""; }; + C2843737053488AB000AE0FC /* DigestContext.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DigestContext.h; sourceTree = ""; }; + C2843738053488AB000AE0FC /* FEEAsymmetricContext.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = FEEAsymmetricContext.cpp; sourceTree = ""; }; + C2843739053488AB000AE0FC /* FEEAsymmetricContext.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = FEEAsymmetricContext.h; sourceTree = ""; }; + C284373A053488AB000AE0FC /* FEECSPUtils.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = FEECSPUtils.cpp; sourceTree = ""; }; + C284373B053488AB000AE0FC /* FEECSPUtils.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = FEECSPUtils.h; sourceTree = ""; }; + C284373C053488AB000AE0FC /* FEEKeys.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = FEEKeys.cpp; sourceTree = ""; }; + C284373D053488AB000AE0FC /* FEEKeys.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = FEEKeys.h; sourceTree = ""; }; + C284373E053488AB000AE0FC /* FEESignatureObject.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = FEESignatureObject.cpp; sourceTree = ""; }; + C284373F053488AB000AE0FC /* FEESignatureObject.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = FEESignatureObject.h; sourceTree = ""; }; + C2843740053488AB000AE0FC /* gladmanContext.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = gladmanContext.cpp; sourceTree = ""; }; + C2843741053488AB000AE0FC /* gladmanContext.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = gladmanContext.h; sourceTree = ""; }; + C2843744053488AB000AE0FC /* MacContext.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = MacContext.cpp; sourceTree = ""; }; + C2843745053488AB000AE0FC /* MacContext.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = MacContext.h; sourceTree = ""; }; + C2843746053488AB000AE0FC /* MD2Object.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = MD2Object.cpp; sourceTree = ""; }; + C2843747053488AB000AE0FC /* MD2Object.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = MD2Object.h; sourceTree = ""; }; + C284374A053488AB000AE0FC /* memory.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = memory.cpp; sourceTree = ""; }; + C284374B053488AB000AE0FC /* miscAlgFactory.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = miscAlgFactory.cpp; sourceTree = ""; }; + C284374C053488AB000AE0FC /* miscAlgFactory.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = miscAlgFactory.h; sourceTree = ""; }; + C284374D053488AB000AE0FC /* miscalgorithms.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = miscalgorithms.cpp; sourceTree = ""; }; + C284374E053488AC000AE0FC /* NullCryptor.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = NullCryptor.h; sourceTree = ""; }; + C284374F053488AC000AE0FC /* pbkdDigest.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = pbkdDigest.cpp; sourceTree = ""; }; + C2843750053488AC000AE0FC /* pbkdDigest.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = pbkdDigest.h; sourceTree = ""; }; + C2843751053488AC000AE0FC /* pbkdf2.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = pbkdf2.c; sourceTree = ""; }; + C2843752053488AC000AE0FC /* pbkdf2.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = pbkdf2.h; sourceTree = ""; }; + C2843753053488AC000AE0FC /* pkcs12Derive.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = pkcs12Derive.cpp; sourceTree = ""; }; + C2843754053488AC000AE0FC /* pkcs12Derive.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = pkcs12Derive.h; sourceTree = ""; }; + C2843755053488AC000AE0FC /* pkcs8.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = pkcs8.cpp; sourceTree = ""; }; + C2843756053488AC000AE0FC /* pkcs8.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = pkcs8.h; sourceTree = ""; }; + C2843758053488AC000AE0FC /* RawSigner.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = RawSigner.h; sourceTree = ""; }; + C2843759053488AC000AE0FC /* rc2Context.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = rc2Context.cpp; sourceTree = ""; }; + C284375A053488AC000AE0FC /* rc2Context.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = rc2Context.h; sourceTree = ""; }; + C284375B053488AC000AE0FC /* rc4Context.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = rc4Context.cpp; sourceTree = ""; }; + C284375C053488AC000AE0FC /* rc4Context.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = rc4Context.h; sourceTree = ""; }; + C284375D053488AC000AE0FC /* rc5Context.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = rc5Context.cpp; sourceTree = ""; }; + C284375E053488AC000AE0FC /* rc5Context.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = rc5Context.h; sourceTree = ""; }; + C284375F053488AC000AE0FC /* rijndael-alg-ref.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = "rijndael-alg-ref.c"; sourceTree = ""; }; + C2843760053488AC000AE0FC /* rijndael-alg-ref.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = "rijndael-alg-ref.h"; sourceTree = ""; }; + C2843761053488AC000AE0FC /* rijndaelApi.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = rijndaelApi.c; sourceTree = ""; }; + C2843762053488AC000AE0FC /* rijndaelApi.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = rijndaelApi.h; sourceTree = ""; }; + C2843765053488AC000AE0FC /* RSA_asymmetric.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = RSA_asymmetric.cpp; sourceTree = ""; }; + C2843766053488AC000AE0FC /* RSA_asymmetric.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = RSA_asymmetric.h; sourceTree = ""; }; + C2843767053488AC000AE0FC /* RSA_DSA_csp.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = RSA_DSA_csp.cpp; sourceTree = ""; }; + C2843768053488AC000AE0FC /* RSA_DSA_csp.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = RSA_DSA_csp.h; sourceTree = ""; }; + C2843769053488AC000AE0FC /* RSA_DSA_keys.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = RSA_DSA_keys.cpp; sourceTree = ""; }; + C284376A053488AC000AE0FC /* RSA_DSA_keys.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = RSA_DSA_keys.h; sourceTree = ""; }; + C284376B053488AC000AE0FC /* RSA_DSA_signature.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = RSA_DSA_signature.cpp; sourceTree = ""; }; + C284376C053488AC000AE0FC /* RSA_DSA_signature.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = RSA_DSA_signature.h; sourceTree = ""; }; + C284376D053488AC000AE0FC /* RSA_DSA_utils.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = RSA_DSA_utils.cpp; sourceTree = ""; }; + C284376E053488AC000AE0FC /* RSA_DSA_utils.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = RSA_DSA_utils.h; sourceTree = ""; }; + C2843771053488AC000AE0FC /* SHA1_MD5_Object.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SHA1_MD5_Object.cpp; sourceTree = ""; }; + C2843772053488AC000AE0FC /* SHA1_MD5_Object.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SHA1_MD5_Object.h; sourceTree = ""; }; + C2843775053488AC000AE0FC /* SignatureContext.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SignatureContext.cpp; sourceTree = ""; }; + C2843776053488AC000AE0FC /* SignatureContext.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SignatureContext.h; sourceTree = ""; }; + C2843777053488AC000AE0FC /* vRijndael-alg-ref.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = "vRijndael-alg-ref.c"; sourceTree = ""; }; + C2843778053488AC000AE0FC /* wrapKey.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = wrapKey.cpp; sourceTree = ""; }; + C2843779053488AC000AE0FC /* wrapKeyCms.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = wrapKeyCms.cpp; sourceTree = ""; }; + C284377A053488AC000AE0FC /* YarrowConnection.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = YarrowConnection.cpp; sourceTree = ""; }; + C284377B053488AC000AE0FC /* YarrowConnection.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = YarrowConnection.h; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 4CA1FEBB052A3C8100F22E42 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 05065316056A96DA008AD683 /* RSA_DSA */ = { + isa = PBXGroup; + children = ( + C2843765053488AC000AE0FC /* RSA_asymmetric.cpp */, + C284376B053488AC000AE0FC /* RSA_DSA_signature.cpp */, + C284376C053488AC000AE0FC /* RSA_DSA_signature.h */, + C284376D053488AC000AE0FC /* RSA_DSA_utils.cpp */, + C284376E053488AC000AE0FC /* RSA_DSA_utils.h */, + C2843767053488AC000AE0FC /* RSA_DSA_csp.cpp */, + C2843768053488AC000AE0FC /* RSA_DSA_csp.h */, + C2843769053488AC000AE0FC /* RSA_DSA_keys.cpp */, + C284376A053488AC000AE0FC /* RSA_DSA_keys.h */, + C2843766053488AC000AE0FC /* RSA_asymmetric.h */, + 053ABEFD0AA4C94900CA6DC3 /* opensshCoding.h */, + 053ABEFE0AA4C94900CA6DC3 /* opensshCoding.cpp */, + 053ABF600AA4F3EB00CA6DC3 /* opensshWrap.cpp */, + ); + name = RSA_DSA; + sourceTree = ""; + }; + 05065317056A96E2008AD683 /* ComCryption */ = { + isa = PBXGroup; + children = ( + C284370B053488AB000AE0FC /* ascContext.cpp */, + C284370C053488AB000AE0FC /* ascContext.h */, + C284370D053488AB000AE0FC /* ascFactory.h */, + ); + name = ComCryption; + sourceTree = ""; + }; + 05065318056A96EC008AD683 /* MiscCSPAlgs */ = { + isa = PBXGroup; + children = ( + 05065393056A9A2E008AD683 /* Digest */, + 05065394056A9AA6008AD683 /* PKCS */, + 05065392056A9A28008AD683 /* Symmetric */, + C284374B053488AB000AE0FC /* miscAlgFactory.cpp */, + C284374C053488AB000AE0FC /* miscAlgFactory.h */, + ); + name = MiscCSPAlgs; + sourceTree = ""; + }; + 05065319056A96F3008AD683 /* AES */ = { + isa = PBXGroup; + children = ( + C28436FD053488AB000AE0FC /* aesCommon.h */, + C28436FE053488AB000AE0FC /* aescsp.cpp */, + C28436FF053488AB000AE0FC /* aescspi.h */, + C2843713053488AB000AE0FC /* boxes-ref.c */, + C2843714053488AB000AE0FC /* boxes-ref.h */, + C2843740053488AB000AE0FC /* gladmanContext.cpp */, + C2843741053488AB000AE0FC /* gladmanContext.h */, + C284375F053488AC000AE0FC /* rijndael-alg-ref.c */, + C2843760053488AC000AE0FC /* rijndael-alg-ref.h */, + C2843761053488AC000AE0FC /* rijndaelApi.c */, + C2843762053488AC000AE0FC /* rijndaelApi.h */, + C2843777053488AC000AE0FC /* vRijndael-alg-ref.c */, + ); + name = AES; + sourceTree = ""; + }; + 0506531A056A96F7008AD683 /* AppleCSP */ = { + isa = PBXGroup; + children = ( + C2843701053488AB000AE0FC /* AppleCSP.cpp */, + C2843702053488AB000AE0FC /* AppleCSP.h */, + C2196B39053B5905005808D4 /* AppleCSPBuiltin.cpp */, + C2843703053488AB000AE0FC /* AppleCSPContext.cpp */, + C2843704053488AB000AE0FC /* AppleCSPContext.h */, + C2843705053488AB000AE0FC /* AppleCSPKeys.cpp */, + C2843706053488AB000AE0FC /* AppleCSPKeys.h */, + C2843707053488AB000AE0FC /* AppleCSPPlugin.cpp */, + C2843708053488AB000AE0FC /* AppleCSPSession.h */, + C2843709053488AB000AE0FC /* AppleCSPUtils.cpp */, + C284370A053488AB000AE0FC /* AppleCSPUtils.h */, + C2843710053488AB000AE0FC /* BinaryKey.h */, + C2843711053488AB000AE0FC /* BlockCryptor.cpp */, + C2843712053488AB000AE0FC /* BlockCryptor.h */, + C2843726053488AB000AE0FC /* cspdebugging.c */, + C2843727053488AB000AE0FC /* cspdebugging.h */, + C2843728053488AB000AE0FC /* cssmplugin.exp */, + C2843729053488AB000AE0FC /* deriveKey.cpp */, + C2843736053488AB000AE0FC /* DigestContext.cpp */, + C2843737053488AB000AE0FC /* DigestContext.h */, + C2843744053488AB000AE0FC /* MacContext.cpp */, + C2843745053488AB000AE0FC /* MacContext.h */, + C2843758053488AC000AE0FC /* RawSigner.h */, + C2843775053488AC000AE0FC /* SignatureContext.cpp */, + C2843776053488AC000AE0FC /* SignatureContext.h */, + C2843778053488AC000AE0FC /* wrapKey.cpp */, + C2843779053488AC000AE0FC /* wrapKeyCms.cpp */, + C284377A053488AC000AE0FC /* YarrowConnection.cpp */, + C284377B053488AC000AE0FC /* YarrowConnection.h */, + ); + name = AppleCSP; + sourceTree = ""; + }; + 0506531B056A96FC008AD683 /* BSafeCSP */ = { + isa = PBXGroup; + children = ( + C2843700053488AB000AE0FC /* algmaker.cpp */, + C2843715053488AB000AE0FC /* bsafeAsymmetric.cpp */, + C2843716053488AB000AE0FC /* bsafeContext.cpp */, + C2843717053488AB000AE0FC /* bsafecsp.h */, + C2843718053488AB000AE0FC /* bsafecspi.h */, + C2843719053488AB000AE0FC /* bsafeKeyGen.cpp */, + C284371A053488AB000AE0FC /* bsafePKCS1.cpp */, + C284371B053488AB000AE0FC /* bsafePKCS1.h */, + C284371C053488AB000AE0FC /* bsafeSymmetric.cpp */, + C284371D053488AB000AE0FC /* bsobjects.h */, + C284374A053488AB000AE0FC /* memory.cpp */, + C284374D053488AB000AE0FC /* miscalgorithms.cpp */, + ); + name = BSafeCSP; + sourceTree = ""; + }; + 0506531C056A9702008AD683 /* CryptKitCSP */ = { + isa = PBXGroup; + children = ( + C2843722053488AB000AE0FC /* cryptkitcsp.cpp */, + C2843723053488AB000AE0FC /* cryptkitcsp.h */, + C2843725053488AB000AE0FC /* CryptKitSpace.h */, + C2843738053488AB000AE0FC /* FEEAsymmetricContext.cpp */, + C2843739053488AB000AE0FC /* FEEAsymmetricContext.h */, + C284373A053488AB000AE0FC /* FEECSPUtils.cpp */, + C284373B053488AB000AE0FC /* FEECSPUtils.h */, + C284373C053488AB000AE0FC /* FEEKeys.cpp */, + C284373D053488AB000AE0FC /* FEEKeys.h */, + C284373E053488AB000AE0FC /* FEESignatureObject.cpp */, + C284373F053488AB000AE0FC /* FEESignatureObject.h */, + ); + name = CryptKitCSP; + sourceTree = ""; + }; + 0506531D056A9709008AD683 /* PBKDF2 */ = { + isa = PBXGroup; + children = ( + 05BFEE0C09E1D71800F3D7E0 /* HMACSHA1.c */, + 05BFEE0D09E1D71800F3D7E0 /* HMACSHA1.h */, + C284374F053488AC000AE0FC /* pbkdDigest.cpp */, + C2843750053488AC000AE0FC /* pbkdDigest.h */, + C2843751053488AC000AE0FC /* pbkdf2.c */, + C2843752053488AC000AE0FC /* pbkdf2.h */, + ); + name = PBKDF2; + sourceTree = ""; + }; + 0506531E056A9712008AD683 /* DiffieHellman */ = { + isa = PBXGroup; + children = ( + C284372E053488AB000AE0FC /* DH_csp.cpp */, + C284372F053488AB000AE0FC /* DH_csp.h */, + C2843730053488AB000AE0FC /* DH_exchange.cpp */, + C2843731053488AB000AE0FC /* DH_exchange.h */, + C2843732053488AB000AE0FC /* DH_keys.cpp */, + C2843733053488AB000AE0FC /* DH_keys.h */, + C2843734053488AB000AE0FC /* DH_utils.cpp */, + C2843735053488AB000AE0FC /* DH_utils.h */, + ); + name = DiffieHellman; + sourceTree = ""; + }; + 05065392056A9A28008AD683 /* Symmetric */ = { + isa = PBXGroup; + children = ( + C284370E053488AB000AE0FC /* bfContext.cpp */, + C284370F053488AB000AE0FC /* bfContext.h */, + C284371E053488AB000AE0FC /* castContext.cpp */, + C284371F053488AB000AE0FC /* castContext.h */, + C284372C053488AB000AE0FC /* desContext.cpp */, + C284372D053488AB000AE0FC /* desContext.h */, + C284374E053488AC000AE0FC /* NullCryptor.h */, + C2843759053488AC000AE0FC /* rc2Context.cpp */, + C284375A053488AC000AE0FC /* rc2Context.h */, + C284375B053488AC000AE0FC /* rc4Context.cpp */, + C284375C053488AC000AE0FC /* rc4Context.h */, + C284375D053488AC000AE0FC /* rc5Context.cpp */, + C284375E053488AC000AE0FC /* rc5Context.h */, + ); + name = Symmetric; + sourceTree = ""; + }; + 05065393056A9A2E008AD683 /* Digest */ = { + isa = PBXGroup; + children = ( + C2843746053488AB000AE0FC /* MD2Object.cpp */, + C2843747053488AB000AE0FC /* MD2Object.h */, + C2843771053488AC000AE0FC /* SHA1_MD5_Object.cpp */, + C2843772053488AC000AE0FC /* SHA1_MD5_Object.h */, + 05622BAA06CC352100784EED /* SHA2_Object.cpp */, + 05622BAB06CC352100784EED /* SHA2_Object.h */, + ); + name = Digest; + sourceTree = ""; + }; + 05065394056A9AA6008AD683 /* PKCS */ = { + isa = PBXGroup; + children = ( + C2843753053488AC000AE0FC /* pkcs12Derive.cpp */, + C2843754053488AC000AE0FC /* pkcs12Derive.h */, + C2843755053488AC000AE0FC /* pkcs8.cpp */, + C2843756053488AC000AE0FC /* pkcs8.h */, + ); + name = PKCS; + sourceTree = ""; + }; + 053910790A3771EF00B9E848 /* docs */ = { + isa = PBXGroup; + children = ( + 053910810A37725A00B9E848 /* libsecurity_apple_csp.plist */, + 053910820A37725A00B9E848 /* libsecurity_apple_csp.txt */, + ); + path = docs; + sourceTree = ""; + }; + 18446064146DE98E00B12992 /* config */ = { + isa = PBXGroup; + children = ( + 18446065146DE98E00B12992 /* base.xcconfig */, + 18446066146DE98E00B12992 /* debug.xcconfig */, + 18446067146DE98E00B12992 /* lib.xcconfig */, + 18446068146DE98E00B12992 /* release.xcconfig */, + ); + name = config; + path = ../config; + sourceTree = ""; + }; + 18446091146DFBC800B12992 /* Products */ = { + isa = PBXGroup; + children = ( + 18446096146DFBC900B12992 /* libsecurity_cdsa_plugin.a */, + ); + name = Products; + sourceTree = ""; + }; + 4094B0DB057EA70300B44BCC /* mds */ = { + isa = PBXGroup; + children = ( + 4094B0DC057EA70300B44BCC /* csp_capabilities.mdsinfo */, + 4094B0DD057EA70300B44BCC /* csp_capabilities_common.mds */, + 4094B0DE057EA70300B44BCC /* csp_common.mdsinfo */, + 4094B0DF057EA70300B44BCC /* csp_primary.mdsinfo */, + ); + path = mds; + sourceTree = ""; + }; + 4CA1FEA7052A3C3800F22E42 = { + isa = PBXGroup; + children = ( + 18446090146DFBC800B12992 /* libsecurity_cdsa_plugin.xcodeproj */, + C28436FC053488AB000AE0FC /* lib */, + 18446064146DE98E00B12992 /* config */, + 4094B0DB057EA70300B44BCC /* mds */, + C280ADE60534BBD900F7E802 /* open_ssl */, + 053910790A3771EF00B9E848 /* docs */, + 4CA1FEBF052A3C8100F22E42 /* Products */, + ); + sourceTree = ""; + }; + 4CA1FEBF052A3C8100F22E42 /* Products */ = { + isa = PBXGroup; + children = ( + 4CA1FEBE052A3C8100F22E42 /* libsecurity_apple_csp.a */, + ); + name = Products; + sourceTree = ""; + }; + C280ADE60534BBD900F7E802 /* open_ssl */ = { + isa = PBXGroup; + children = ( + C280ADE70534BBD900F7E802 /* bf */, + C280ADEF0534BBD900F7E802 /* bio */, + C280ADF20534BBD900F7E802 /* bn */, + C280AE100534BBD900F7E802 /* buffer */, + C280AE190534BBD900F7E802 /* cryptlib.c */, + C280AE1A0534BBD900F7E802 /* cryptlib.h */, + C280AE1B0534BBD900F7E802 /* dh */, + C280AE210534BBD900F7E802 /* dsa */, + C280AE2A0534BBD900F7E802 /* err */, + C280AE2D0534BBD900F7E802 /* ex_data.c */, + C280AE2E0534BBD900F7E802 /* lhash */, + C280AE300534BBD900F7E802 /* LICENSE */, + C280AE310534BBD900F7E802 /* mem.c */, + C280AE320534BBD900F7E802 /* misc */, + C280AE3C0534BBD900F7E802 /* openssl */, + C280AE610534BBD900F7E802 /* rsa */, + C280AE6D0534BBD900F7E802 /* stack */, + ); + path = open_ssl; + sourceTree = ""; + }; + C280ADE70534BBD900F7E802 /* bf */ = { + isa = PBXGroup; + children = ( + C280ADE80534BBD900F7E802 /* bf_ecb.c */, + C280ADE90534BBD900F7E802 /* bf_enc.c */, + C280ADEA0534BBD900F7E802 /* bf_locl.h */, + C280ADEB0534BBD900F7E802 /* bf_pi.h */, + C280ADEC0534BBD900F7E802 /* bf_skey.c */, + C280ADED0534BBD900F7E802 /* COPYRIGHT */, + C280ADEE0534BBD900F7E802 /* README */, + ); + path = bf; + sourceTree = ""; + }; + C280ADEF0534BBD900F7E802 /* bio */ = { + isa = PBXGroup; + children = ( + C280ADF00534BBD900F7E802 /* bio_lib.c */, + C280ADF10534BBD900F7E802 /* bss_file.c */, + ); + path = bio; + sourceTree = ""; + }; + C280ADF20534BBD900F7E802 /* bn */ = { + isa = PBXGroup; + children = ( + C280ADF30534BBD900F7E802 /* bn_add.c */, + C280ADF40534BBD900F7E802 /* bn_asm.c */, + C280ADF50534BBD900F7E802 /* bn_blind.c */, + C280ADF60534BBD900F7E802 /* bn_ctx.c */, + C280ADF70534BBD900F7E802 /* bn_div.c */, + C280ADF80534BBD900F7E802 /* bn_err.c */, + C280ADF90534BBD900F7E802 /* bn_exp.c */, + C280ADFA0534BBD900F7E802 /* bn_exp2.c */, + C280ADFB0534BBD900F7E802 /* bn_gcd.c */, + C280ADFC0534BBD900F7E802 /* bn_lcl.h */, + C280ADFD0534BBD900F7E802 /* bn_lib.c */, + C280ADFE0534BBD900F7E802 /* bn_mont.c */, + C280ADFF0534BBD900F7E802 /* bn_mpi.c */, + C280AE000534BBD900F7E802 /* bn_mul.c */, + C280AE010534BBD900F7E802 /* bn_prime.c */, + C280AE020534BBD900F7E802 /* bn_prime.h */, + C280AE030534BBD900F7E802 /* bn_print.c */, + C280AE040534BBD900F7E802 /* bn_rand.c */, + C280AE050534BBD900F7E802 /* bn_recp.c */, + C280AE060534BBD900F7E802 /* bn_shift.c */, + C280AE070534BBD900F7E802 /* bn_sqr.c */, + C280AE080534BBD900F7E802 /* bn_word.c */, + C280AE090534BBD900F7E802 /* bnspeed.c */, + C280AE0A0534BBD900F7E802 /* bntest.c */, + C280AE0B0534BBD900F7E802 /* divtest.c */, + C280AE0C0534BBD900F7E802 /* exp.c */, + C280AE0D0534BBD900F7E802 /* expspeed.c */, + C280AE0E0534BBD900F7E802 /* exptest.c */, + C280AE0F0534BBD900F7E802 /* vms-helper.c */, + ); + path = bn; + sourceTree = ""; + }; + C280AE100534BBD900F7E802 /* buffer */ = { + isa = PBXGroup; + children = ( + C280AE110534BBD900F7E802 /* buf_err.c */, + C280AE120534BBD900F7E802 /* buffer.c */, + ); + path = buffer; + sourceTree = ""; + }; + C280AE1B0534BBD900F7E802 /* dh */ = { + isa = PBXGroup; + children = ( + C280AE1C0534BBD900F7E802 /* dh_check.c */, + C280AE1D0534BBD900F7E802 /* dh_err.c */, + C280AE1E0534BBD900F7E802 /* dh_gen.c */, + C280AE1F0534BBD900F7E802 /* dh_key.c */, + C280AE200534BBD900F7E802 /* dh_lib.c */, + ); + path = dh; + sourceTree = ""; + }; + C280AE210534BBD900F7E802 /* dsa */ = { + isa = PBXGroup; + children = ( + C280AE220534BBD900F7E802 /* dsa_asn1.c */, + C280AE230534BBD900F7E802 /* dsa_err.c */, + C280AE240534BBD900F7E802 /* dsa_gen.c */, + C280AE250534BBD900F7E802 /* dsa_key.c */, + C280AE260534BBD900F7E802 /* dsa_lib.c */, + C280AE270534BBD900F7E802 /* dsa_ossl.c */, + C280AE280534BBD900F7E802 /* dsa_sign.c */, + C280AE290534BBD900F7E802 /* dsa_vrf.c */, + ); + path = dsa; + sourceTree = ""; + }; + C280AE2A0534BBD900F7E802 /* err */ = { + isa = PBXGroup; + children = ( + C280AE2B0534BBD900F7E802 /* err.c */, + C280AE2C0534BBD900F7E802 /* err_prn.c */, + ); + path = err; + sourceTree = ""; + }; + C280AE2E0534BBD900F7E802 /* lhash */ = { + isa = PBXGroup; + children = ( + C280AE2F0534BBD900F7E802 /* lhash.c */, + ); + path = lhash; + sourceTree = ""; + }; + C280AE320534BBD900F7E802 /* misc */ = { + isa = PBXGroup; + children = ( + C280AE340534BBD900F7E802 /* rc2_cbc.c */, + C280AE350534BBD900F7E802 /* rc2_locl.h */, + C280AE360534BBD900F7E802 /* rc2_skey.c */, + C280AE390534BBD900F7E802 /* rc5_enc.c */, + C280AE3A0534BBD900F7E802 /* rc5_locl.h */, + C280AE3B0534BBD900F7E802 /* rc5_skey.c */, + ); + path = misc; + sourceTree = ""; + }; + C280AE3C0534BBD900F7E802 /* openssl */ = { + isa = PBXGroup; + children = ( + C280AE3D0534BBD900F7E802 /* asn1.h */, + C280AE3E0534BBD900F7E802 /* bio.h */, + C280AE3F0534BBD900F7E802 /* blowfish.h */, + C280AE400534BBD900F7E802 /* bn.h */, + C280AE410534BBD900F7E802 /* buffer.h */, + C280AE420534BBD900F7E802 /* cast.h */, + C280AE430534BBD900F7E802 /* crypto.h */, + C280AE440534BBD900F7E802 /* dh.h */, + C280AE450534BBD900F7E802 /* dsa.h */, + C280AE460534BBD900F7E802 /* e_os.h */, + C280AE470534BBD900F7E802 /* e_os2.h */, + C280AE480534BBD900F7E802 /* err.h */, + C280AE490534BBD900F7E802 /* evp.h */, + C280AE4A0534BBD900F7E802 /* lhash.h */, + C280AE4C0534BBD900F7E802 /* objects.h */, + C280AE4D0534BBD900F7E802 /* openssl_pkcs7.h */, + C280AE4E0534BBD900F7E802 /* opensslconf.h */, + C280AE4F0534BBD900F7E802 /* opensslv.h */, + C280AE500534BBD900F7E802 /* rand.h */, + C280AE510534BBD900F7E802 /* rc2.h */, + C280AE530534BBD900F7E802 /* rc5.h */, + C280AE540534BBD900F7E802 /* rsa.h */, + C280AE550534BBD900F7E802 /* safestack.h */, + C280AE570534BBD900F7E802 /* stack.h */, + C280AE580534BBD900F7E802 /* x509.h */, + C280AE590534BBD900F7E802 /* x509_vfy.h */, + ); + path = openssl; + sourceTree = ""; + }; + C280AE5A0534BBD900F7E802 /* opensslUtils */ = { + isa = PBXGroup; + children = ( + C280AE5B0534BBD900F7E802 /* opensslAsn1.cpp */, + C280AE5C0534BBD900F7E802 /* opensslAsn1.h */, + C280AE5D0534BBD900F7E802 /* opensslUtils.cpp */, + C280AE5E0534BBD900F7E802 /* opensslUtils.h */, + ); + name = opensslUtils; + path = open_ssl/opensslUtils; + sourceTree = SOURCE_ROOT; + }; + C280AE610534BBD900F7E802 /* rsa */ = { + isa = PBXGroup; + children = ( + C280AE620534BBD900F7E802 /* rsa_chk.c */, + C280AE630534BBD900F7E802 /* rsa_eay.c */, + C280AE640534BBD900F7E802 /* rsa_err.c */, + C280AE650534BBD900F7E802 /* rsa_gen.c */, + C280AE660534BBD900F7E802 /* rsa_lib.c */, + C280AE670534BBD900F7E802 /* rsa_none.c */, + C280AE680534BBD900F7E802 /* rsa_null.c */, + C280AE690534BBD900F7E802 /* rsa_pk1.c */, + C280AE6A0534BBD900F7E802 /* rsa_saos.c */, + C280AE6B0534BBD900F7E802 /* rsa_sign.c */, + C280AE6C0534BBD900F7E802 /* rsa_ssl.c */, + ); + path = rsa; + sourceTree = ""; + }; + C280AE6D0534BBD900F7E802 /* stack */ = { + isa = PBXGroup; + children = ( + C280AE6E0534BBD900F7E802 /* stack.c */, + ); + path = stack; + sourceTree = ""; + }; + C28436FC053488AB000AE0FC /* lib */ = { + isa = PBXGroup; + children = ( + 05065319056A96F3008AD683 /* AES */, + 0506531A056A96F7008AD683 /* AppleCSP */, + 0506531B056A96FC008AD683 /* BSafeCSP */, + 05065317056A96E2008AD683 /* ComCryption */, + 0506531C056A9702008AD683 /* CryptKitCSP */, + 0506531E056A9712008AD683 /* DiffieHellman */, + 0506531D056A9709008AD683 /* PBKDF2 */, + 05065318056A96EC008AD683 /* MiscCSPAlgs */, + 05065316056A96DA008AD683 /* RSA_DSA */, + C280AE5A0534BBD900F7E802 /* opensslUtils */, + ); + path = lib; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 4CA1FEB9052A3C8100F22E42 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + C284377C053488AC000AE0FC /* aesCommon.h in Headers */, + C284377E053488AC000AE0FC /* aescspi.h in Headers */, + C2843781053488AC000AE0FC /* AppleCSP.h in Headers */, + C2843783053488AC000AE0FC /* AppleCSPContext.h in Headers */, + C2843785053488AC000AE0FC /* AppleCSPKeys.h in Headers */, + C2843787053488AC000AE0FC /* AppleCSPSession.h in Headers */, + C2843789053488AC000AE0FC /* AppleCSPUtils.h in Headers */, + C284378B053488AC000AE0FC /* ascContext.h in Headers */, + C284378C053488AC000AE0FC /* ascFactory.h in Headers */, + C284378E053488AC000AE0FC /* bfContext.h in Headers */, + C284378F053488AC000AE0FC /* BinaryKey.h in Headers */, + C2843791053488AC000AE0FC /* BlockCryptor.h in Headers */, + C2843793053488AC000AE0FC /* boxes-ref.h in Headers */, + C2843796053488AC000AE0FC /* bsafecsp.h in Headers */, + C2843797053488AC000AE0FC /* bsafecspi.h in Headers */, + C284379A053488AC000AE0FC /* bsafePKCS1.h in Headers */, + C284379C053488AC000AE0FC /* bsobjects.h in Headers */, + C284379E053488AC000AE0FC /* castContext.h in Headers */, + C28437A2053488AC000AE0FC /* cryptkitcsp.h in Headers */, + C28437A4053488AC000AE0FC /* CryptKitSpace.h in Headers */, + C28437A6053488AC000AE0FC /* cspdebugging.h in Headers */, + C28437AC053488AC000AE0FC /* desContext.h in Headers */, + C28437AE053488AC000AE0FC /* DH_csp.h in Headers */, + C28437B0053488AC000AE0FC /* DH_exchange.h in Headers */, + C28437B2053488AC000AE0FC /* DH_keys.h in Headers */, + C28437B4053488AC000AE0FC /* DH_utils.h in Headers */, + C28437B6053488AC000AE0FC /* DigestContext.h in Headers */, + C28437B8053488AC000AE0FC /* FEEAsymmetricContext.h in Headers */, + C28437BA053488AC000AE0FC /* FEECSPUtils.h in Headers */, + C28437BC053488AC000AE0FC /* FEEKeys.h in Headers */, + C28437BE053488AC000AE0FC /* FEESignatureObject.h in Headers */, + C28437C0053488AC000AE0FC /* gladmanContext.h in Headers */, + C28437C4053488AC000AE0FC /* MacContext.h in Headers */, + C28437C6053488AC000AE0FC /* MD2Object.h in Headers */, + C28437CB053488AC000AE0FC /* miscAlgFactory.h in Headers */, + C28437CD053488AC000AE0FC /* NullCryptor.h in Headers */, + C28437CF053488AC000AE0FC /* pbkdDigest.h in Headers */, + C28437D1053488AC000AE0FC /* pbkdf2.h in Headers */, + C28437D3053488AC000AE0FC /* pkcs12Derive.h in Headers */, + C28437D5053488AC000AE0FC /* pkcs8.h in Headers */, + C28437D7053488AC000AE0FC /* RawSigner.h in Headers */, + C28437D9053488AC000AE0FC /* rc2Context.h in Headers */, + C28437DB053488AC000AE0FC /* rc4Context.h in Headers */, + C28437DD053488AC000AE0FC /* rc5Context.h in Headers */, + C28437DF053488AC000AE0FC /* rijndael-alg-ref.h in Headers */, + C28437E1053488AC000AE0FC /* rijndaelApi.h in Headers */, + C28437E5053488AC000AE0FC /* RSA_asymmetric.h in Headers */, + C28437E7053488AC000AE0FC /* RSA_DSA_csp.h in Headers */, + C28437E9053488AC000AE0FC /* RSA_DSA_keys.h in Headers */, + C28437EB053488AC000AE0FC /* RSA_DSA_signature.h in Headers */, + C28437ED053488AC000AE0FC /* RSA_DSA_utils.h in Headers */, + C28437F1053488AC000AE0FC /* SHA1_MD5_Object.h in Headers */, + C28437F5053488AC000AE0FC /* SignatureContext.h in Headers */, + C28437FA053488AC000AE0FC /* YarrowConnection.h in Headers */, + C280AE710534BBD900F7E802 /* bf_locl.h in Headers */, + C280AE720534BBD900F7E802 /* bf_pi.h in Headers */, + C280AE7F0534BBD900F7E802 /* bn_lcl.h in Headers */, + C280AE850534BBD900F7E802 /* bn_prime.h in Headers */, + C280AE9B0534BBD900F7E802 /* cryptlib.h in Headers */, + C280AEB00534BBD900F7E802 /* rc2_locl.h in Headers */, + C280AEB50534BBD900F7E802 /* rc5_locl.h in Headers */, + C280AEB70534BBD900F7E802 /* asn1.h in Headers */, + C280AEB80534BBD900F7E802 /* bio.h in Headers */, + C280AEB90534BBD900F7E802 /* blowfish.h in Headers */, + C280AEBA0534BBD900F7E802 /* bn.h in Headers */, + C280AEBB0534BBD900F7E802 /* buffer.h in Headers */, + C280AEBC0534BBD900F7E802 /* cast.h in Headers */, + C280AEBD0534BBD900F7E802 /* crypto.h in Headers */, + C280AEBE0534BBD900F7E802 /* dh.h in Headers */, + C280AEBF0534BBD900F7E802 /* dsa.h in Headers */, + C280AEC00534BBD900F7E802 /* e_os.h in Headers */, + C280AEC10534BBD900F7E802 /* e_os2.h in Headers */, + C280AEC20534BBD900F7E802 /* err.h in Headers */, + C280AEC30534BBD900F7E802 /* evp.h in Headers */, + C280AEC40534BBD900F7E802 /* lhash.h in Headers */, + C280AEC60534BBD900F7E802 /* objects.h in Headers */, + C280AEC70534BBD900F7E802 /* openssl_pkcs7.h in Headers */, + C280AEC80534BBD900F7E802 /* opensslconf.h in Headers */, + C280AEC90534BBD900F7E802 /* opensslv.h in Headers */, + C280AECA0534BBD900F7E802 /* rand.h in Headers */, + C280AECB0534BBD900F7E802 /* rc2.h in Headers */, + C280AECD0534BBD900F7E802 /* rc5.h in Headers */, + C280AECE0534BBD900F7E802 /* rsa.h in Headers */, + C280AECF0534BBD900F7E802 /* safestack.h in Headers */, + C280AED10534BBD900F7E802 /* stack.h in Headers */, + C280AED20534BBD900F7E802 /* x509.h in Headers */, + C280AED30534BBD900F7E802 /* x509_vfy.h in Headers */, + C280AED50534BBD900F7E802 /* opensslAsn1.h in Headers */, + C280AED70534BBD900F7E802 /* opensslUtils.h in Headers */, + 05622BAD06CC352100784EED /* SHA2_Object.h in Headers */, + 05BFEE0F09E1D71800F3D7E0 /* HMACSHA1.h in Headers */, + 053ABEFF0AA4C94900CA6DC3 /* opensshCoding.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 4CA1FEBD052A3C8100F22E42 /* libsecurity_apple_csp */ = { + isa = PBXNativeTarget; + buildConfigurationList = C27AD2500987FCDC001272E0 /* Build configuration list for PBXNativeTarget "libsecurity_apple_csp" */; + buildPhases = ( + 4CA1FEB9052A3C8100F22E42 /* Headers */, + 4CA1FEBA052A3C8100F22E42 /* Sources */, + 4CA1FEBB052A3C8100F22E42 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + 182BB345146F10ED000BF1F3 /* PBXTargetDependency */, + 053910800A37724600B9E848 /* PBXTargetDependency */, + ); + name = libsecurity_apple_csp; + productInstallPath = /usr/local/lib; + productName = libsecurity_apple_csp; + productReference = 4CA1FEBE052A3C8100F22E42 /* libsecurity_apple_csp.a */; + productType = "com.apple.product-type.library.static"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 4CA1FEAB052A3C3800F22E42 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0420; + }; + buildConfigurationList = C27AD2550987FCDC001272E0 /* Build configuration list for PBXProject "libsecurity_apple_csp" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 1; + knownRegions = ( + en, + ); + mainGroup = 4CA1FEA7052A3C3800F22E42; + productRefGroup = 4CA1FEBF052A3C8100F22E42 /* Products */; + projectDirPath = ""; + projectReferences = ( + { + ProductGroup = 18446091146DFBC800B12992 /* Products */; + ProjectRef = 18446090146DFBC800B12992 /* libsecurity_cdsa_plugin.xcodeproj */; + }, + ); + projectRoot = ""; + targets = ( + 4CA1FEBD052A3C8100F22E42 /* libsecurity_apple_csp */, + 0539107D0A37721E00B9E848 /* Copy Open Source Docs */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXReferenceProxy section */ + 18446096146DFBC900B12992 /* libsecurity_cdsa_plugin.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libsecurity_cdsa_plugin.a; + remoteRef = 18446095146DFBC900B12992 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; +/* End PBXReferenceProxy section */ + +/* Begin PBXSourcesBuildPhase section */ + 4CA1FEBA052A3C8100F22E42 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + C284377D053488AC000AE0FC /* aescsp.cpp in Sources */, + C284377F053488AC000AE0FC /* algmaker.cpp in Sources */, + C2843780053488AC000AE0FC /* AppleCSP.cpp in Sources */, + C2843782053488AC000AE0FC /* AppleCSPContext.cpp in Sources */, + C2843784053488AC000AE0FC /* AppleCSPKeys.cpp in Sources */, + C2843788053488AC000AE0FC /* AppleCSPUtils.cpp in Sources */, + C284378A053488AC000AE0FC /* ascContext.cpp in Sources */, + C284378D053488AC000AE0FC /* bfContext.cpp in Sources */, + C2843790053488AC000AE0FC /* BlockCryptor.cpp in Sources */, + C2843792053488AC000AE0FC /* boxes-ref.c in Sources */, + C2843794053488AC000AE0FC /* bsafeAsymmetric.cpp in Sources */, + C2843795053488AC000AE0FC /* bsafeContext.cpp in Sources */, + C2843798053488AC000AE0FC /* bsafeKeyGen.cpp in Sources */, + C2843799053488AC000AE0FC /* bsafePKCS1.cpp in Sources */, + C284379B053488AC000AE0FC /* bsafeSymmetric.cpp in Sources */, + C284379D053488AC000AE0FC /* castContext.cpp in Sources */, + C28437A1053488AC000AE0FC /* cryptkitcsp.cpp in Sources */, + C28437A5053488AC000AE0FC /* cspdebugging.c in Sources */, + C28437A8053488AC000AE0FC /* deriveKey.cpp in Sources */, + C28437AB053488AC000AE0FC /* desContext.cpp in Sources */, + C28437AD053488AC000AE0FC /* DH_csp.cpp in Sources */, + C28437AF053488AC000AE0FC /* DH_exchange.cpp in Sources */, + C28437B1053488AC000AE0FC /* DH_keys.cpp in Sources */, + C28437B3053488AC000AE0FC /* DH_utils.cpp in Sources */, + C28437B5053488AC000AE0FC /* DigestContext.cpp in Sources */, + C28437B7053488AC000AE0FC /* FEEAsymmetricContext.cpp in Sources */, + C28437B9053488AC000AE0FC /* FEECSPUtils.cpp in Sources */, + C28437BB053488AC000AE0FC /* FEEKeys.cpp in Sources */, + C28437BD053488AC000AE0FC /* FEESignatureObject.cpp in Sources */, + C28437BF053488AC000AE0FC /* gladmanContext.cpp in Sources */, + C28437C3053488AC000AE0FC /* MacContext.cpp in Sources */, + C28437C5053488AC000AE0FC /* MD2Object.cpp in Sources */, + C28437C9053488AC000AE0FC /* memory.cpp in Sources */, + C28437CA053488AC000AE0FC /* miscAlgFactory.cpp in Sources */, + C28437CC053488AC000AE0FC /* miscalgorithms.cpp in Sources */, + C28437CE053488AC000AE0FC /* pbkdDigest.cpp in Sources */, + C28437D0053488AC000AE0FC /* pbkdf2.c in Sources */, + C28437D2053488AC000AE0FC /* pkcs12Derive.cpp in Sources */, + C28437D4053488AC000AE0FC /* pkcs8.cpp in Sources */, + C28437D8053488AC000AE0FC /* rc2Context.cpp in Sources */, + C28437DA053488AC000AE0FC /* rc4Context.cpp in Sources */, + C28437DC053488AC000AE0FC /* rc5Context.cpp in Sources */, + C28437DE053488AC000AE0FC /* rijndael-alg-ref.c in Sources */, + C28437E0053488AC000AE0FC /* rijndaelApi.c in Sources */, + C28437E4053488AC000AE0FC /* RSA_asymmetric.cpp in Sources */, + C28437E6053488AC000AE0FC /* RSA_DSA_csp.cpp in Sources */, + C28437E8053488AC000AE0FC /* RSA_DSA_keys.cpp in Sources */, + C28437EA053488AC000AE0FC /* RSA_DSA_signature.cpp in Sources */, + C28437EC053488AC000AE0FC /* RSA_DSA_utils.cpp in Sources */, + C28437F0053488AC000AE0FC /* SHA1_MD5_Object.cpp in Sources */, + C28437F4053488AC000AE0FC /* SignatureContext.cpp in Sources */, + C28437F6053488AC000AE0FC /* vRijndael-alg-ref.c in Sources */, + C28437F7053488AC000AE0FC /* wrapKey.cpp in Sources */, + C28437F8053488AC000AE0FC /* wrapKeyCms.cpp in Sources */, + C28437F9053488AC000AE0FC /* YarrowConnection.cpp in Sources */, + C280AE6F0534BBD900F7E802 /* bf_ecb.c in Sources */, + C280AE700534BBD900F7E802 /* bf_enc.c in Sources */, + C280AE730534BBD900F7E802 /* bf_skey.c in Sources */, + C280AE740534BBD900F7E802 /* bio_lib.c in Sources */, + C280AE750534BBD900F7E802 /* bss_file.c in Sources */, + C280AE760534BBD900F7E802 /* bn_add.c in Sources */, + C280AE770534BBD900F7E802 /* bn_asm.c in Sources */, + C280AE780534BBD900F7E802 /* bn_blind.c in Sources */, + C280AE790534BBD900F7E802 /* bn_ctx.c in Sources */, + C280AE7A0534BBD900F7E802 /* bn_div.c in Sources */, + C280AE7B0534BBD900F7E802 /* bn_err.c in Sources */, + C280AE7C0534BBD900F7E802 /* bn_exp.c in Sources */, + C280AE7D0534BBD900F7E802 /* bn_exp2.c in Sources */, + C280AE7E0534BBD900F7E802 /* bn_gcd.c in Sources */, + C280AE800534BBD900F7E802 /* bn_lib.c in Sources */, + C280AE810534BBD900F7E802 /* bn_mont.c in Sources */, + C280AE820534BBD900F7E802 /* bn_mpi.c in Sources */, + C280AE830534BBD900F7E802 /* bn_mul.c in Sources */, + C280AE840534BBD900F7E802 /* bn_prime.c in Sources */, + C280AE860534BBD900F7E802 /* bn_print.c in Sources */, + C280AE870534BBD900F7E802 /* bn_rand.c in Sources */, + C280AE880534BBD900F7E802 /* bn_recp.c in Sources */, + C280AE890534BBD900F7E802 /* bn_shift.c in Sources */, + C280AE8A0534BBD900F7E802 /* bn_sqr.c in Sources */, + C280AE8B0534BBD900F7E802 /* bn_word.c in Sources */, + C280AE930534BBD900F7E802 /* buf_err.c in Sources */, + C280AE940534BBD900F7E802 /* buffer.c in Sources */, + C280AE9A0534BBD900F7E802 /* cryptlib.c in Sources */, + C280AE9C0534BBD900F7E802 /* dh_check.c in Sources */, + C280AE9D0534BBD900F7E802 /* dh_err.c in Sources */, + C280AE9E0534BBD900F7E802 /* dh_gen.c in Sources */, + C280AE9F0534BBD900F7E802 /* dh_key.c in Sources */, + C280AEA00534BBD900F7E802 /* dh_lib.c in Sources */, + C280AEA10534BBD900F7E802 /* dsa_asn1.c in Sources */, + C280AEA20534BBD900F7E802 /* dsa_err.c in Sources */, + C280AEA30534BBD900F7E802 /* dsa_gen.c in Sources */, + C280AEA40534BBD900F7E802 /* dsa_key.c in Sources */, + C280AEA50534BBD900F7E802 /* dsa_lib.c in Sources */, + C280AEA60534BBD900F7E802 /* dsa_ossl.c in Sources */, + C280AEA70534BBD900F7E802 /* dsa_sign.c in Sources */, + C280AEA80534BBD900F7E802 /* dsa_vrf.c in Sources */, + C280AEA90534BBD900F7E802 /* err.c in Sources */, + C280AEAA0534BBD900F7E802 /* err_prn.c in Sources */, + C280AEAB0534BBD900F7E802 /* ex_data.c in Sources */, + C280AEAC0534BBD900F7E802 /* lhash.c in Sources */, + C280AEAD0534BBD900F7E802 /* mem.c in Sources */, + C280AEAF0534BBD900F7E802 /* rc2_cbc.c in Sources */, + C280AEB10534BBD900F7E802 /* rc2_skey.c in Sources */, + C280AEB40534BBD900F7E802 /* rc5_enc.c in Sources */, + C280AEB60534BBD900F7E802 /* rc5_skey.c in Sources */, + C280AED40534BBD900F7E802 /* opensslAsn1.cpp in Sources */, + C280AED60534BBD900F7E802 /* opensslUtils.cpp in Sources */, + C280AEDA0534BBD900F7E802 /* rsa_chk.c in Sources */, + C280AEDB0534BBD900F7E802 /* rsa_eay.c in Sources */, + C280AEDC0534BBD900F7E802 /* rsa_err.c in Sources */, + C280AEDD0534BBD900F7E802 /* rsa_gen.c in Sources */, + C280AEDE0534BBD900F7E802 /* rsa_lib.c in Sources */, + C280AEDF0534BBD900F7E802 /* rsa_none.c in Sources */, + C280AEE00534BBD900F7E802 /* rsa_null.c in Sources */, + C280AEE10534BBD900F7E802 /* rsa_pk1.c in Sources */, + C280AEE20534BBD900F7E802 /* rsa_saos.c in Sources */, + C280AEE30534BBD900F7E802 /* rsa_sign.c in Sources */, + C280AEE40534BBD900F7E802 /* rsa_ssl.c in Sources */, + C280AEE50534BBD900F7E802 /* stack.c in Sources */, + C2196B3A053B5905005808D4 /* AppleCSPBuiltin.cpp in Sources */, + 05622BAC06CC352100784EED /* SHA2_Object.cpp in Sources */, + 05BFEE0E09E1D71800F3D7E0 /* HMACSHA1.c in Sources */, + 053ABF000AA4C94900CA6DC3 /* opensshCoding.cpp in Sources */, + 053ABF620AA4F3EB00CA6DC3 /* opensshWrap.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 053910800A37724600B9E848 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 0539107D0A37721E00B9E848 /* Copy Open Source Docs */; + targetProxy = 0539107F0A37724600B9E848 /* PBXContainerItemProxy */; + }; + 182BB345146F10ED000BF1F3 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = libsecurity_cdsa_plugin_generate; + targetProxy = 182BB344146F10ED000BF1F3 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 053910870A37725A00B9E848 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + }; + name = Debug; + }; + 0539108A0A37725A00B9E848 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + }; + name = Release; + }; + C27AD2510987FCDC001272E0 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 18446066146DE98E00B12992 /* debug.xcconfig */; + buildSettings = { + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/open_ssl", + ); + OTHER_CFLAGS = ( + "$(inherited)", + "-DALLOW_ZERO_PASSWORD", + "-DCRYPTKIT_CSP_ENABLE", + "-DASC_CSP_ENABLE", + "-DCK_SECURITY_BUILD", + ); + }; + name = Debug; + }; + C27AD2540987FCDC001272E0 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 18446068146DE98E00B12992 /* release.xcconfig */; + buildSettings = { + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/open_ssl", + ); + OTHER_CFLAGS = ( + "$(inherited)", + "-DALLOW_ZERO_PASSWORD", + "-DCRYPTKIT_CSP_ENABLE", + "-DASC_CSP_ENABLE", + "-DCK_SECURITY_BUILD", + ); + }; + name = Release; + }; + C27AD2560987FCDC001272E0 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 18446067146DE98E00B12992 /* lib.xcconfig */; + buildSettings = { + }; + name = Debug; + }; + C27AD2590987FCDC001272E0 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 18446067146DE98E00B12992 /* lib.xcconfig */; + buildSettings = { + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 053910860A37725A00B9E848 /* Build configuration list for PBXAggregateTarget "Copy Open Source Docs" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 053910870A37725A00B9E848 /* Debug */, + 0539108A0A37725A00B9E848 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C27AD2500987FCDC001272E0 /* Build configuration list for PBXNativeTarget "libsecurity_apple_csp" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C27AD2510987FCDC001272E0 /* Debug */, + C27AD2540987FCDC001272E0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C27AD2550987FCDC001272E0 /* Build configuration list for PBXProject "libsecurity_apple_csp" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C27AD2560987FCDC001272E0 /* Debug */, + C27AD2590987FCDC001272E0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 4CA1FEAB052A3C3800F22E42 /* Project object */; +} diff --git a/libsecurity_apple_csp/mds/csp_capabilities.mdsinfo b/libsecurity_apple_csp/mds/csp_capabilities.mdsinfo new file mode 100644 index 00000000..1526a12b --- /dev/null +++ b/libsecurity_apple_csp/mds/csp_capabilities.mdsinfo @@ -0,0 +1,18 @@ + + + + + Capabilities + file:csp_capabilities_common.mds + MdsFileDescription + Built-in CSP Capabilities + MdsFileType + PluginSpecific + MdsRecordType + MDS_CDSADIR_CSP_CAPABILITY_RECORDTYPE + ModuleID + {87191ca2-0fc9-11d4-849a-000502b52122} + SSID + 0 + + diff --git a/libsecurity_apple_csp/mds/csp_capabilities_common.mds b/libsecurity_apple_csp/mds/csp_capabilities_common.mds new file mode 100644 index 00000000..e37381fd --- /dev/null +++ b/libsecurity_apple_csp/mds/csp_capabilities_common.mds @@ -0,0 +1,903 @@ + + + + + + AlgType + CSSM_ALGID_SHA1 + Attributes + + + AttributeType + CSSM_ATTRIBUTE_OUTPUT_SIZE + AttributeValue + 20 + + + ContextType + CSSM_ALGCLASS_DIGEST + Description + SHA1 Digest + UseeTag + CSSM_USEE_NONE + + + AlgType + CSSM_ALGID_MD5 + Attributes + + + AttributeType + CSSM_ATTRIBUTE_OUTPUT_SIZE + AttributeValue + 16 + + + ContextType + CSSM_ALGCLASS_DIGEST + Description + MD5 Digest + UseeTag + CSSM_USEE_NONE + + + AlgType + CSSM_ALGID_MD2 + Attributes + + + AttributeType + CSSM_ATTRIBUTE_OUTPUT_SIZE + AttributeValue + 16 + + + ContextType + CSSM_ALGCLASS_DIGEST + Description + MD2 Digest + UseeTag + CSSM_USEE_NONE + + + AlgType + CSSM_ALGID_RSA + Attributes + + + AttributeType + CSSM_ATTRIBUTE_NONE + AttributeValue + + + + ContextType + CSSM_ALGCLASS_KEYGEN + Description + RSA Key Pair Generation + UseeTag + CSSM_USEE_NONE + + + AlgType + CSSM_ALGID_DES + Attributes + + + AttributeType + CSSM_ATTRIBUTE_KEY_LENGTH + AttributeValue + 64 + + + ContextType + CSSM_ALGCLASS_KEYGEN + Description + DES Key Generation + UseeTag + CSSM_USEE_NONE + + + AlgType + CSSM_ALGID_3DES_3KEY + Attributes + + + AttributeType + CSSM_ATTRIBUTE_KEY_LENGTH + AttributeValue + 192 + + + ContextType + CSSM_ALGCLASS_KEYGEN + Description + 3DES Key Generation + UseeTag + CSSM_USEE_NONE + + + AlgType + CSSM_ALGID_RC2 + Attributes + + + AttributeType + CSSM_ATTRIBUTE_NONE + AttributeValue + + + + ContextType + CSSM_ALGCLASS_KEYGEN + Description + RC2 Key Generation + UseeTag + CSSM_USEE_NONE + + + AlgType + CSSM_ALGID_RC4 + Attributes + + + AttributeType + CSSM_ATTRIBUTE_NONE + AttributeValue + + + + ContextType + CSSM_ALGCLASS_KEYGEN + Description + RC4 Key Generation + UseeTag + CSSM_USEE_NONE + + + AlgType + CSSM_ALGID_RC5 + Attributes + + + AttributeType + CSSM_ATTRIBUTE_NONE + AttributeValue + + + + ContextType + CSSM_ALGCLASS_KEYGEN + Description + RC5 Key Generation + UseeTag + CSSM_USEE_NONE + + + AlgType + CSSM_ALGID_CAST + Attributes + + + AttributeType + CSSM_ATTRIBUTE_NONE + New item + + + + ContextType + CSSM_ALGCLASS_KEYGEN + Description + CAST Key Generation + UseeTag + CSSM_USEE_NONE + + + AlgType + CSSM_ALGID_BLOWFISH + Attributes + + + AttributeType + CSSM_ATTRIBUTE_NONE + AttributeValue + + + + ContextType + CSSM_ALGCLASS_KEYGEN + Description + Blowfish Key Generation + UseeTag + CSSM_USEE_NONE + + + AlgType + CSSM_ALGID_SHA1HMAC + Attributes + + + AttributeType + CSSM_ATTRIBUTE_NONE + AttributeValue + + + + ContextType + CSSM_ALGCLASS_KEYGEN + Description + SHA1HMAC Key Generation + UseeTag + CSSM_USEE_NONE + + + AlgType + CSSM_ALGID_MD5HMAC + Attributes + + + AttributeType + CSSM_ATTRIBUTE_NONE + AttributeValue + + + + ContextType + CSSM_ALGCLASS_KEYGEN + Description + MD5HMAC Key Generation + UseeTag + CSSM_USEE_NONE + + + AlgType + CSSM_ALGID_AES + Attributes + + + AttributeType + CSSM_ATTRIBUTE_KEY_LENGTH + AttributeValue + + 128 + 192 + 256 + + + + ContextType + CSSM_ALGCLASS_KEYGEN + Description + AES Key Generation + UseeTag + CSSM_USEE_NONE + + + AlgType + CSSM_ALGID_ASC + Attributes + + + AttributeType + CSSM_ATTRIBUTE_NONE + AttributeValue + + + + ContextType + CSSM_ALGCLASS_KEYGEN + Description + ASC Key Generation + UseeTag + CSSM_USEE_NONE + + + AlgType + CSSM_ALGID_FEE + Attributes + + + AttributeType + CSSM_ATTRIBUTE_KEY_LENGTH + AttributeValue + + 31 + 127 + 128 + 161 + 192 + + + + ContextType + CSSM_ALGCLASS_KEYGEN + Description + FEE Key Pair Generation + UseeTag + CSSM_USEE_NONE + + + AlgType + CSSM_ALGID_DSA + Attributes + + + AttributeType + CSSM_ATTRIBUTE_NONE + AttributeValue + + + + ContextType + CSSM_ALGCLASS_KEYGEN + Description + DSA Key Pair Generation + UseeTag + CSSM_USEE_NONE + + + AlgType + CSSM_ALGID_PKCS5_PBKDF2 + Attributes + + + AttributeType + CSSM_ATTRIBUTE_NONE + AttributeValue + + + + ContextType + CSSM_ALGCLASS_DERIVEKEY + Description + PKCS5 Key Derivation + UseeTag + CSSM_USEE_NONE + + + AlgType + CSSM_ALGID_PKCS5_PBKDF1_MD5 + Attributes + + + AttributeType + CSSM_ATTRIBUTE_NONE + AttributeValue + + + + ContextType + CSSM_ALGCLASS_DERIVEKEY + Description + PKCS5 PBKDF1 MD5 Key Derivation + UseeTag + CSSM_USEE_NONE + + + AlgType + CSSM_ALGID_PKCS5_PBKDF1_MD2 + Attributes + + + AttributeType + CSSM_ATTRIBUTE_NONE + AttributeValue + + + + ContextType + CSSM_ALGCLASS_DERIVEKEY + Description + PKCS5 PBKDF1 MD2 Key Derivation + UseeTag + CSSM_USEE_NONE + + + AlgType + CSSM_ALGID_PKCS5_PBKDF1_SHA1 + Attributes + + + AttributeType + CSSM_ATTRIBUTE_NONE + AttributeValue + + + + ContextType + CSSM_ALGCLASS_DERIVEKEY + Description + PKCS5 PBKDF1 SHA1 Key Derivation + UseeTag + CSSM_USEE_NONE + + + AlgType + CSSM_ALGID_DES + Attributes + + + AttributeType + CSSM_ATTRIBUTE_MODE + AttributeValue + + 2 + 3 + 5 + 6 + + + + ContextType + CSSM_ALGCLASS_SYMMETRIC + Description + DES Encryption + UseeTag + CSSM_USEE_NONE + + + AlgType + CSSM_ALGID_3DES_3KEY_EDE + Attributes + + + AttributeType + CSSM_ATTRIBUTE_MODE + AttributeValue + + 2 + 3 + 5 + 6 + + + + ContextType + CSSM_ALGCLASS_SYMMETRIC + Description + 3DES EDE Encryption + UseeTag + CSSM_USEE_NONE + + + AlgType + CSSM_ALGID_AES + Attributes + + + AttributeType + CSSM_ATTRIBUTE_MODE + AttributeValue + + 2 + 3 + 5 + 6 + + + + ContextType + CSSM_ALGCLASS_SYMMETRIC + Description + AES Encryption + UseeTag + CSSM_USEE_NONE + + + AlgType + CSSM_ALGID_RC4 + Attributes + + + AttributeType + CSSM_ATTRIBUTE_MODE + AttributeValue + + 0 + + + + ContextType + CSSM_ALGCLASS_SYMMETRIC + Description + RC4 Encryption + UseeTag + CSSM_USEE_NONE + + + AlgType + CSSM_ALGID_RC5 + Attributes + + + AttributeType + CSSM_ATTRIBUTE_MODE + AttributeValue + + 2 + 3 + 5 + 6 + + + + ContextType + CSSM_ALGCLASS_SYMMETRIC + Description + RC5 Encryption + UseeTag + CSSM_USEE_NONE + + + AlgType + CSSM_ALGID_BLOWFISH + Attributes + + + AttributeType + CSSM_ATTRIBUTE_MODE + AttributeValue + + 2 + 3 + 5 + 6 + + + + ContextType + CSSM_ALGCLASS_SYMMETRIC + Description + Blowfish Encryption + UseeTag + CSSM_USEE_NONE + + + AlgType + CSSM_ALGID_CAST + Attributes + + + AttributeType + CSSM_ATTRIBUTE_MODE + AttributeValue + + 2 + 3 + 5 + 6 + + + + ContextType + CSSM_ALGCLASS_SYMMETRIC + Description + CAST Encryption + UseeTag + CSSM_USEE_NONE + + + AlgType + CSSM_ALGID_RSA + Attributes + + + AttributeType + CSSM_ATTRIBUTE_NONE + AttributeValue + + + + ContextType + CSSM_ALGCLASS_ASYMMETRIC + Description + RSA Encryption + UseeTag + CSSM_USEE_NONE + + + AlgType + CSSM_ALGID_FEEDEXP + Attributes + + + AttributeType + CSSM_ATTRIBUTE_NONE + AttributeValue + + + + ContextType + CSSM_ALGCLASS_ASYMMETRIC + Description + FEEDExp Encryption + UseeTag + CSSM_USEE_NONE + + + AlgType + CSSM_ALGID_FEED + Attributes + + + AttributeType + CSSM_ATTRIBUTE_NONE + AttributeValue + + + + ContextType + CSSM_ALGCLASS_ASYMMETRIC + Description + FEED Encryption + UseeTag + CSSM_USEE_NONE + + + AlgType + CSSM_ALGID_SHA1WithRSA + Attributes + + + AttributeType + CSSM_ATTRIBUTE_NONE + AttributeValue + + + + ContextType + CSSM_ALGCLASS_SIGNATURE + Description + SHA1 With RSA Signature + UseeTag + CSSM_USEE_NONE + + + AlgType + CSSM_ALGID_MD5WithRSA + Attributes + + + AttributeType + CSSM_ATTRIBUTE_NONE + AttributeValue + + + + ContextType + CSSM_ALGCLASS_SIGNATURE + Description + MD5 With RSA Signature + UseeTag + CSSM_USEE_NONE + + + AlgType + CSSM_ALGID_MD2WithRSA + Attributes + + + AttributeType + CSSM_ATTRIBUTE_NONE + AttributeValue + + + + ContextType + CSSM_ALGCLASS_SIGNATURE + Description + MD2 With RSA Signature + UseeTag + CSSM_USEE_NONE + + + AlgType + CSSM_ALGID_RSA + Attributes + + + AttributeType + CSSM_ATTRIBUTE_NONE + AttributeValue + + + + ContextType + CSSM_ALGCLASS_SIGNATURE + Description + Raw RSA Signature + UseeTag + CSSM_USEE_NONE + + + AlgType + CSSM_ALGID_SHA1WithDSA + Attributes + + + AttributeType + CSSM_ATTRIBUTE_NONE + AttributeValue + + + + ContextType + CSSM_ALGCLASS_SIGNATURE + Description + SHA1 With DSA Signature + UseeTag + CSSM_USEE_NONE + + + AlgType + CSSM_ALGID_DSA + Attributes + + + AttributeType + CSSM_ATTRIBUTE_NONE + AttributeValue + + + + ContextType + CSSM_ALGCLASS_SIGNATURE + Description + Raw DSA Signature + UseeTag + CSSM_USEE_NONE + + + AlgType + CSSM_ALGID_FEE_MD5 + Attributes + + + AttributeType + CSSM_ATTRIBUTE_NONE + AttributeValue + + + + ContextType + CSSM_ALGCLASS_SIGNATURE + Description + MD5 with FEE Signature + UseeTag + CSSM_USEE_NONE + + + AlgType + CSSM_ALGID_FEE_SHA1 + Attributes + + + AttributeType + CSSM_ATTRIBUTE_NONE + AttributeValue + + + + ContextType + CSSM_ALGCLASS_SIGNATURE + Description + SHA1 with FEE Signature + UseeTag + CSSM_USEE_NONE + + + AlgType + CSSM_ALGID_FEE + Attributes + + + AttributeType + CSSM_ATTRIBUTE_NONE + AttributeValue + + + + ContextType + CSSM_ALGCLASS_SIGNATURE + Description + Raw FEE Signature + UseeTag + CSSM_USEE_NONE + + + AlgType + CSSM_ALGID_SHA1WithECDSA + Attributes + + + AttributeType + CSSM_ATTRIBUTE_NONE + AttributeValue + + + + ContextType + CSSM_ALGCLASS_SIGNATURE + Description + SHA1 with ECDSA Signature + UseeTag + CSSM_USEE_NONE + + + AlgType + CSSM_ALGID_ECDSA + Attributes + + + AttributeType + CSSM_ATTRIBUTE_NONE + AttributeValue + + + + ContextType + CSSM_ALGCLASS_SIGNATURE + Description + Raw ECDSA Signature + UseeTag + CSSM_USEE_NONE + + + AlgType + CSSM_ALGID_SHA1HMAC + Attributes + + + AttributeType + CSSM_ATTRIBUTE_OUTPUT_SIZE + AttributeValue + 20 + + + ContextType + CSSM_ALGCLASS_MAC + Description + SHA1HMAC MAC + UseeTag + CSSM_USEE_NONE + + + AlgType + CSSM_ALGID_SHA1HMAC_LEGACY + Attributes + + + AttributeType + CSSM_ATTRIBUTE_OUTPUT_SIZE + AttributeValue + 20 + + + ContextType + CSSM_ALGCLASS_MAC + Description + SHA1HMAC MAC Legacy + UseeTag + CSSM_USEE_NONE + + + AlgType + CSSM_ALGID_APPLE_YARROW + Attributes + + + AttributeType + CSSM_ATTRIBUTE_NONE + AttributeValue + + + + ContextType + CSSM_ALGCLASS_RANDOMGEN + Description + Yarrow PRNG + UseeTag + CSSM_USEE_NONE + + + diff --git a/libsecurity_apple_csp/mds/csp_common.mdsinfo b/libsecurity_apple_csp/mds/csp_common.mdsinfo new file mode 100644 index 00000000..740a2709 --- /dev/null +++ b/libsecurity_apple_csp/mds/csp_common.mdsinfo @@ -0,0 +1,30 @@ + + + + + BuiltIn + + CDSAVersion + 2.0 + Desc + Apple built-in CSP + DynamicFlag + + MdsFileDescription + Built-in CSP Common info + MdsFileType + PluginCommon + ModuleID + {87191ca2-0fc9-11d4-849a-000502b52122} + ModuleName + AppleCSP + MultiThreadFlag + + ProductVersion + 1.0 + ServiceMask + CSSM_SERVICE_CSP + Path + *AppleCSP + + diff --git a/libsecurity_apple_csp/mds/csp_primary.mdsinfo b/libsecurity_apple_csp/mds/csp_primary.mdsinfo new file mode 100644 index 00000000..6b0a777d --- /dev/null +++ b/libsecurity_apple_csp/mds/csp_primary.mdsinfo @@ -0,0 +1,36 @@ + + + + + AclSubjectTypes + + AuthTags + + CspCustomFlags + 0 + CspFlags + + CspType + CSSM_CSP_SOFTWARE + MdsFileDescription + Built-in CSP Primary info + MdsFileType + PluginSpecific + MdsRecordType + MDS_CDSADIR_CSP_PRIMARY_RECORDTYPE + ModuleID + {87191ca2-0fc9-11d4-849a-000502b52122} + ModuleName + AppleCSP + ProductVersion + 1.0 + SSID + 0 + SampleTypes + + UseeTags + + Vendor + Apple Computer, Inc. + + diff --git a/libsecurity_apple_csp/open_ssl/LICENSE b/libsecurity_apple_csp/open_ssl/LICENSE new file mode 100644 index 00000000..c885273f --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/LICENSE @@ -0,0 +1,60 @@ + Original SSLeay License + ----------------------- + +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + diff --git a/libsecurity_apple_csp/open_ssl/bf/COPYRIGHT b/libsecurity_apple_csp/open_ssl/bf/COPYRIGHT new file mode 100644 index 00000000..68572235 --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/bf/COPYRIGHT @@ -0,0 +1,46 @@ +Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) +All rights reserved. + +This package is an Blowfish implementation written +by Eric Young (eay@cryptsoft.com). + +This library is free for commercial and non-commercial use as long as +the following conditions are aheared to. The following conditions +apply to all code found in this distribution. + +Copyright remains Eric Young's, and as such any Copyright notices in +the code are not to be removed. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. All advertising materials mentioning features or use of this software + must display the following acknowledgement: + This product includes software developed by Eric Young (eay@cryptsoft.com) + +THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. + +The license and distribution terms for any publically available version or +derivative of this code cannot be changed. i.e. this code cannot simply be +copied and put under another distrubution license +[including the GNU Public License.] + +The reason behind this being stated in this direct manner is past +experience in code simply being copied and the attribution removed +from it and then being distributed as part of other packages. This +implementation was a non-trivial and unpaid effort. diff --git a/libsecurity_apple_csp/open_ssl/bf/README b/libsecurity_apple_csp/open_ssl/bf/README new file mode 100644 index 00000000..f2712fd0 --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/bf/README @@ -0,0 +1,8 @@ +This is a quick packaging up of my blowfish code into a library. +It has been lifted from SSLeay. +The copyright notices seem a little harsh because I have not spent the +time to rewrite the conditions from the normal SSLeay ones. + +Basically if you just want to play with the library, not a problem. + +eric 15-Apr-1997 diff --git a/libsecurity_apple_csp/open_ssl/bf/bf_ecb.c b/libsecurity_apple_csp/open_ssl/bf/bf_ecb.c new file mode 100644 index 00000000..34199163 --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/bf/bf_ecb.c @@ -0,0 +1,96 @@ +/* crypto/bf/bf_ecb.c */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include +#include "bf_locl.h" +#include + +/* Blowfish as implemented from 'Blowfish: Springer-Verlag paper' + * (From LECTURE NOTES IN COMPUTER SCIENCE 809, FAST SOFTWARE ENCRYPTION, + * CAMBRIDGE SECURITY WORKSHOP, CAMBRIDGE, U.K., DECEMBER 9-11, 1993) + */ + +const char *BF_version="Blowfish" OPENSSL_VERSION_PTEXT; + +const char *BF_options(void) + { +#ifdef BF_PTR + return("blowfish(ptr)"); +#elif defined(BF_PTR2) + return("blowfish(ptr2)"); +#else + return("blowfish(idx)"); +#endif + } + +void BF_ecb_encrypt(const unsigned char *in, unsigned char *out, + const BF_KEY *key, int encrypt) + { + BF_LONG l,d[2]; + + n2l(in,l); d[0]=l; + n2l(in,l); d[1]=l; + if (encrypt) + BF_encrypt(d,key); + else + BF_decrypt(d,key); + l=d[0]; l2n(l,out); + l=d[1]; l2n(l,out); + l=d[0]=d[1]=0; + } + diff --git a/libsecurity_apple_csp/open_ssl/bf/bf_enc.c b/libsecurity_apple_csp/open_ssl/bf/bf_enc.c new file mode 100644 index 00000000..b380acf9 --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/bf/bf_enc.c @@ -0,0 +1,306 @@ +/* crypto/bf/bf_enc.c */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include +#include "bf_locl.h" + +/* Blowfish as implemented from 'Blowfish: Springer-Verlag paper' + * (From LECTURE NOTES IN COMPUTER SCIENCE 809, FAST SOFTWARE ENCRYPTION, + * CAMBRIDGE SECURITY WORKSHOP, CAMBRIDGE, U.K., DECEMBER 9-11, 1993) + */ + +#if (BF_ROUNDS != 16) && (BF_ROUNDS != 20) +#error If you set BF_ROUNDS to some value other than 16 or 20, you will have \ +to modify the code. +#endif + +void BF_encrypt(BF_LONG *data, const BF_KEY *key) + { +#ifndef BF_PTR2 + register BF_LONG l,r; + const register BF_LONG *p,*s; + + p=key->P; + s= &(key->S[0]); + l=data[0]; + r=data[1]; + + l^=p[0]; + BF_ENC(r,l,s,p[ 1]); + BF_ENC(l,r,s,p[ 2]); + BF_ENC(r,l,s,p[ 3]); + BF_ENC(l,r,s,p[ 4]); + BF_ENC(r,l,s,p[ 5]); + BF_ENC(l,r,s,p[ 6]); + BF_ENC(r,l,s,p[ 7]); + BF_ENC(l,r,s,p[ 8]); + BF_ENC(r,l,s,p[ 9]); + BF_ENC(l,r,s,p[10]); + BF_ENC(r,l,s,p[11]); + BF_ENC(l,r,s,p[12]); + BF_ENC(r,l,s,p[13]); + BF_ENC(l,r,s,p[14]); + BF_ENC(r,l,s,p[15]); + BF_ENC(l,r,s,p[16]); +#if BF_ROUNDS == 20 + BF_ENC(r,l,s,p[17]); + BF_ENC(l,r,s,p[18]); + BF_ENC(r,l,s,p[19]); + BF_ENC(l,r,s,p[20]); +#endif + r^=p[BF_ROUNDS+1]; + + data[1]=l&0xffffffffL; + data[0]=r&0xffffffffL; +#else + register BF_LONG l,r,t,*k; + + l=data[0]; + r=data[1]; + k=(BF_LONG*)key; + + l^=k[0]; + BF_ENC(r,l,k, 1); + BF_ENC(l,r,k, 2); + BF_ENC(r,l,k, 3); + BF_ENC(l,r,k, 4); + BF_ENC(r,l,k, 5); + BF_ENC(l,r,k, 6); + BF_ENC(r,l,k, 7); + BF_ENC(l,r,k, 8); + BF_ENC(r,l,k, 9); + BF_ENC(l,r,k,10); + BF_ENC(r,l,k,11); + BF_ENC(l,r,k,12); + BF_ENC(r,l,k,13); + BF_ENC(l,r,k,14); + BF_ENC(r,l,k,15); + BF_ENC(l,r,k,16); +#if BF_ROUNDS == 20 + BF_ENC(r,l,k,17); + BF_ENC(l,r,k,18); + BF_ENC(r,l,k,19); + BF_ENC(l,r,k,20); +#endif + r^=k[BF_ROUNDS+1]; + + data[1]=l&0xffffffffL; + data[0]=r&0xffffffffL; +#endif + } + +#ifndef BF_DEFAULT_OPTIONS + +void BF_decrypt(BF_LONG *data, const BF_KEY *key) + { +#ifndef BF_PTR2 + register BF_LONG l,r; + const register BF_LONG *p,*s; + + p=key->P; + s= &(key->S[0]); + l=data[0]; + r=data[1]; + + l^=p[BF_ROUNDS+1]; +#if BF_ROUNDS == 20 + BF_ENC(r,l,s,p[20]); + BF_ENC(l,r,s,p[19]); + BF_ENC(r,l,s,p[18]); + BF_ENC(l,r,s,p[17]); +#endif + BF_ENC(r,l,s,p[16]); + BF_ENC(l,r,s,p[15]); + BF_ENC(r,l,s,p[14]); + BF_ENC(l,r,s,p[13]); + BF_ENC(r,l,s,p[12]); + BF_ENC(l,r,s,p[11]); + BF_ENC(r,l,s,p[10]); + BF_ENC(l,r,s,p[ 9]); + BF_ENC(r,l,s,p[ 8]); + BF_ENC(l,r,s,p[ 7]); + BF_ENC(r,l,s,p[ 6]); + BF_ENC(l,r,s,p[ 5]); + BF_ENC(r,l,s,p[ 4]); + BF_ENC(l,r,s,p[ 3]); + BF_ENC(r,l,s,p[ 2]); + BF_ENC(l,r,s,p[ 1]); + r^=p[0]; + + data[1]=l&0xffffffffL; + data[0]=r&0xffffffffL; +#else + register BF_LONG l,r,t,*k; + + l=data[0]; + r=data[1]; + k=(BF_LONG *)key; + + l^=k[BF_ROUNDS+1]; +#if BF_ROUNDS == 20 + BF_ENC(r,l,k,20); + BF_ENC(l,r,k,19); + BF_ENC(r,l,k,18); + BF_ENC(l,r,k,17); +#endif + BF_ENC(r,l,k,16); + BF_ENC(l,r,k,15); + BF_ENC(r,l,k,14); + BF_ENC(l,r,k,13); + BF_ENC(r,l,k,12); + BF_ENC(l,r,k,11); + BF_ENC(r,l,k,10); + BF_ENC(l,r,k, 9); + BF_ENC(r,l,k, 8); + BF_ENC(l,r,k, 7); + BF_ENC(r,l,k, 6); + BF_ENC(l,r,k, 5); + BF_ENC(r,l,k, 4); + BF_ENC(l,r,k, 3); + BF_ENC(r,l,k, 2); + BF_ENC(l,r,k, 1); + r^=k[0]; + + data[1]=l&0xffffffffL; + data[0]=r&0xffffffffL; +#endif + } + +void BF_cbc_encrypt(const unsigned char *in, unsigned char *out, long length, + const BF_KEY *schedule, unsigned char *ivec, int encrypt) + { + register BF_LONG tin0,tin1; + register BF_LONG tout0,tout1,xor0,xor1; + register long l=length; + BF_LONG tin[2]; + + if (encrypt) + { + n2l(ivec,tout0); + n2l(ivec,tout1); + ivec-=8; + for (l-=8; l>=0; l-=8) + { + n2l(in,tin0); + n2l(in,tin1); + tin0^=tout0; + tin1^=tout1; + tin[0]=tin0; + tin[1]=tin1; + BF_encrypt(tin,schedule); + tout0=tin[0]; + tout1=tin[1]; + l2n(tout0,out); + l2n(tout1,out); + } + if (l != -8) + { + n2ln(in,tin0,tin1,l+8); + tin0^=tout0; + tin1^=tout1; + tin[0]=tin0; + tin[1]=tin1; + BF_encrypt(tin,schedule); + tout0=tin[0]; + tout1=tin[1]; + l2n(tout0,out); + l2n(tout1,out); + } + l2n(tout0,ivec); + l2n(tout1,ivec); + } + else + { + n2l(ivec,xor0); + n2l(ivec,xor1); + ivec-=8; + for (l-=8; l>=0; l-=8) + { + n2l(in,tin0); + n2l(in,tin1); + tin[0]=tin0; + tin[1]=tin1; + BF_decrypt(tin,schedule); + tout0=tin[0]^xor0; + tout1=tin[1]^xor1; + l2n(tout0,out); + l2n(tout1,out); + xor0=tin0; + xor1=tin1; + } + if (l != -8) + { + n2l(in,tin0); + n2l(in,tin1); + tin[0]=tin0; + tin[1]=tin1; + BF_decrypt(tin,schedule); + tout0=tin[0]^xor0; + tout1=tin[1]^xor1; + l2nn(tout0,tout1,out,l+8); + xor0=tin0; + xor1=tin1; + } + l2n(xor0,ivec); + l2n(xor1,ivec); + } + tin0=tin1=tout0=tout1=xor0=xor1=0; + tin[0]=tin[1]=0; + } + +#endif diff --git a/libsecurity_apple_csp/open_ssl/bf/bf_locl.h b/libsecurity_apple_csp/open_ssl/bf/bf_locl.h new file mode 100644 index 00000000..778420b0 --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/bf/bf_locl.h @@ -0,0 +1,232 @@ +/* crypto/bf/bf_locl.h */ +/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef HEADER_BF_LOCL_H +#define HEADER_BF_LOCL_H +#include /* BF_PTR, BF_PTR2 */ + +#undef c2l +#define c2l(c,l) (l =((unsigned long)(*((c)++))) , \ + l|=((unsigned long)(*((c)++)))<< 8L, \ + l|=((unsigned long)(*((c)++)))<<16L, \ + l|=((unsigned long)(*((c)++)))<<24L) + +/* NOTE - c is not incremented as per c2l */ +#undef c2ln +#define c2ln(c,l1,l2,n) { \ + c+=n; \ + l1=l2=0; \ + switch (n) { \ + case 8: l2 =((unsigned long)(*(--(c))))<<24L; \ + case 7: l2|=((unsigned long)(*(--(c))))<<16L; \ + case 6: l2|=((unsigned long)(*(--(c))))<< 8L; \ + case 5: l2|=((unsigned long)(*(--(c)))); \ + case 4: l1 =((unsigned long)(*(--(c))))<<24L; \ + case 3: l1|=((unsigned long)(*(--(c))))<<16L; \ + case 2: l1|=((unsigned long)(*(--(c))))<< 8L; \ + case 1: l1|=((unsigned long)(*(--(c)))); \ + } \ + } + +#undef l2c +#define l2c(l,c) (*((c)++)=(unsigned char)(((l) )&0xff), \ + *((c)++)=(unsigned char)(((l)>> 8L)&0xff), \ + *((c)++)=(unsigned char)(((l)>>16L)&0xff), \ + *((c)++)=(unsigned char)(((l)>>24L)&0xff)) + +/* NOTE - c is not incremented as per l2c */ +#undef l2cn +#define l2cn(l1,l2,c,n) { \ + c+=n; \ + switch (n) { \ + case 8: *(--(c))=(unsigned char)(((l2)>>24L)&0xff); \ + case 7: *(--(c))=(unsigned char)(((l2)>>16L)&0xff); \ + case 6: *(--(c))=(unsigned char)(((l2)>> 8L)&0xff); \ + case 5: *(--(c))=(unsigned char)(((l2) )&0xff); \ + case 4: *(--(c))=(unsigned char)(((l1)>>24L)&0xff); \ + case 3: *(--(c))=(unsigned char)(((l1)>>16L)&0xff); \ + case 2: *(--(c))=(unsigned char)(((l1)>> 8L)&0xff); \ + case 1: *(--(c))=(unsigned char)(((l1) )&0xff); \ + } \ + } + +/* NOTE - c is not incremented as per n2l */ +#define n2ln(c,l1,l2,n) { \ + c+=n; \ + l1=l2=0; \ + switch (n) { \ + case 8: l2 =((unsigned long)(*(--(c)))) ; \ + case 7: l2|=((unsigned long)(*(--(c))))<< 8; \ + case 6: l2|=((unsigned long)(*(--(c))))<<16; \ + case 5: l2|=((unsigned long)(*(--(c))))<<24; \ + case 4: l1 =((unsigned long)(*(--(c)))) ; \ + case 3: l1|=((unsigned long)(*(--(c))))<< 8; \ + case 2: l1|=((unsigned long)(*(--(c))))<<16; \ + case 1: l1|=((unsigned long)(*(--(c))))<<24; \ + } \ + } + +/* NOTE - c is not incremented as per l2n */ +#define l2nn(l1,l2,c,n) { \ + c+=n; \ + switch (n) { \ + case 8: *(--(c))=(unsigned char)(((l2) )&0xff); \ + case 7: *(--(c))=(unsigned char)(((l2)>> 8)&0xff); \ + case 6: *(--(c))=(unsigned char)(((l2)>>16)&0xff); \ + case 5: *(--(c))=(unsigned char)(((l2)>>24)&0xff); \ + case 4: *(--(c))=(unsigned char)(((l1) )&0xff); \ + case 3: *(--(c))=(unsigned char)(((l1)>> 8)&0xff); \ + case 2: *(--(c))=(unsigned char)(((l1)>>16)&0xff); \ + case 1: *(--(c))=(unsigned char)(((l1)>>24)&0xff); \ + } \ + } + +#undef n2l +#if defined(__GNUC__) && defined(__ppc__) +/* alignment tolerant big-endian optimization */ + #define n2l(c,l) { l= *((unsigned long *)c); c += 4; } +#else +/* little endian, etc. */ + #define n2l(c,l) (l =((unsigned long)(*((c)++)))<<24L, \ + l|=((unsigned long)(*((c)++)))<<16L, \ + l|=((unsigned long)(*((c)++)))<< 8L, \ + l|=((unsigned long)(*((c)++)))) +#endif + +#undef l2n +#if defined(__GNUC__) && defined(__ppc__) + /* alignment tolerant big-endian optimization */ + #define l2n(l,c) { *((unsigned long *)c) = l; c += 4; } +#else + /* little endian, etc. */ + #define l2n(l,c) (*((c)++)=(unsigned char)(((l)>>24L)&0xff), \ + *((c)++)=(unsigned char)(((l)>>16L)&0xff), \ + *((c)++)=(unsigned char)(((l)>> 8L)&0xff), \ + *((c)++)=(unsigned char)(((l) )&0xff)) + +#endif /* GNU, big endian */ + +/* This is actually a big endian algorithm, the most significant byte + * is used to lookup array 0 */ + +#if defined(BF_PTR2) + +/* + * This is basically a special Intel version. Point is that Intel + * doesn't have many registers, but offers a reach choice of addressing + * modes. So we spare some registers by directly traversing BF_KEY + * structure and hiring the most decorated addressing mode. The code + * generated by EGCS is *perfectly* competitive with assembler + * implementation! + */ +#define BF_ENC(LL,R,KEY,Pi) (\ + LL^=KEY[Pi], \ + t= KEY[BF_ROUNDS+2 + 0 + ((R>>24)&0xFF)], \ + t+= KEY[BF_ROUNDS+2 + 256 + ((R>>16)&0xFF)], \ + t^= KEY[BF_ROUNDS+2 + 512 + ((R>>8 )&0xFF)], \ + t+= KEY[BF_ROUNDS+2 + 768 + ((R )&0xFF)], \ + LL^=t \ + ) + +#elif defined(BF_PTR) + +#ifndef BF_LONG_LOG2 +#define BF_LONG_LOG2 2 /* default to BF_LONG being 32 bits */ +#endif +#define BF_M (0xFF<>BF_i)&BF_M gets folded into a single instruction, namely + * rlwinm. So let'em double-check if their compiler does it. + */ + +#define BF_ENC(LL,R,S,P) ( \ + LL^=P, \ + LL^= (((*(BF_LONG *)((unsigned char *)&(S[ 0])+((R>>BF_0)&BF_M))+ \ + *(BF_LONG *)((unsigned char *)&(S[256])+((R>>BF_1)&BF_M)))^ \ + *(BF_LONG *)((unsigned char *)&(S[512])+((R>>BF_2)&BF_M)))+ \ + *(BF_LONG *)((unsigned char *)&(S[768])+((R<>24)&0xff)] + \ + S[0x0100+((int)(R>>16)&0xff)])^ \ + S[0x0200+((int)(R>> 8)&0xff)])+ \ + S[0x0300+((int)(R )&0xff)])&0xffffffffL \ + ) +#endif + +#endif diff --git a/libsecurity_apple_csp/open_ssl/bf/bf_pi.h b/libsecurity_apple_csp/open_ssl/bf/bf_pi.h new file mode 100644 index 00000000..9949513c --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/bf/bf_pi.h @@ -0,0 +1,325 @@ +/* crypto/bf/bf_pi.h */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +static const BF_KEY bf_init= { + { + 0x243f6a88L, 0x85a308d3L, 0x13198a2eL, 0x03707344L, + 0xa4093822L, 0x299f31d0L, 0x082efa98L, 0xec4e6c89L, + 0x452821e6L, 0x38d01377L, 0xbe5466cfL, 0x34e90c6cL, + 0xc0ac29b7L, 0xc97c50ddL, 0x3f84d5b5L, 0xb5470917L, + 0x9216d5d9L, 0x8979fb1b + },{ + 0xd1310ba6L, 0x98dfb5acL, 0x2ffd72dbL, 0xd01adfb7L, + 0xb8e1afedL, 0x6a267e96L, 0xba7c9045L, 0xf12c7f99L, + 0x24a19947L, 0xb3916cf7L, 0x0801f2e2L, 0x858efc16L, + 0x636920d8L, 0x71574e69L, 0xa458fea3L, 0xf4933d7eL, + 0x0d95748fL, 0x728eb658L, 0x718bcd58L, 0x82154aeeL, + 0x7b54a41dL, 0xc25a59b5L, 0x9c30d539L, 0x2af26013L, + 0xc5d1b023L, 0x286085f0L, 0xca417918L, 0xb8db38efL, + 0x8e79dcb0L, 0x603a180eL, 0x6c9e0e8bL, 0xb01e8a3eL, + 0xd71577c1L, 0xbd314b27L, 0x78af2fdaL, 0x55605c60L, + 0xe65525f3L, 0xaa55ab94L, 0x57489862L, 0x63e81440L, + 0x55ca396aL, 0x2aab10b6L, 0xb4cc5c34L, 0x1141e8ceL, + 0xa15486afL, 0x7c72e993L, 0xb3ee1411L, 0x636fbc2aL, + 0x2ba9c55dL, 0x741831f6L, 0xce5c3e16L, 0x9b87931eL, + 0xafd6ba33L, 0x6c24cf5cL, 0x7a325381L, 0x28958677L, + 0x3b8f4898L, 0x6b4bb9afL, 0xc4bfe81bL, 0x66282193L, + 0x61d809ccL, 0xfb21a991L, 0x487cac60L, 0x5dec8032L, + 0xef845d5dL, 0xe98575b1L, 0xdc262302L, 0xeb651b88L, + 0x23893e81L, 0xd396acc5L, 0x0f6d6ff3L, 0x83f44239L, + 0x2e0b4482L, 0xa4842004L, 0x69c8f04aL, 0x9e1f9b5eL, + 0x21c66842L, 0xf6e96c9aL, 0x670c9c61L, 0xabd388f0L, + 0x6a51a0d2L, 0xd8542f68L, 0x960fa728L, 0xab5133a3L, + 0x6eef0b6cL, 0x137a3be4L, 0xba3bf050L, 0x7efb2a98L, + 0xa1f1651dL, 0x39af0176L, 0x66ca593eL, 0x82430e88L, + 0x8cee8619L, 0x456f9fb4L, 0x7d84a5c3L, 0x3b8b5ebeL, + 0xe06f75d8L, 0x85c12073L, 0x401a449fL, 0x56c16aa6L, + 0x4ed3aa62L, 0x363f7706L, 0x1bfedf72L, 0x429b023dL, + 0x37d0d724L, 0xd00a1248L, 0xdb0fead3L, 0x49f1c09bL, + 0x075372c9L, 0x80991b7bL, 0x25d479d8L, 0xf6e8def7L, + 0xe3fe501aL, 0xb6794c3bL, 0x976ce0bdL, 0x04c006baL, + 0xc1a94fb6L, 0x409f60c4L, 0x5e5c9ec2L, 0x196a2463L, + 0x68fb6fafL, 0x3e6c53b5L, 0x1339b2ebL, 0x3b52ec6fL, + 0x6dfc511fL, 0x9b30952cL, 0xcc814544L, 0xaf5ebd09L, + 0xbee3d004L, 0xde334afdL, 0x660f2807L, 0x192e4bb3L, + 0xc0cba857L, 0x45c8740fL, 0xd20b5f39L, 0xb9d3fbdbL, + 0x5579c0bdL, 0x1a60320aL, 0xd6a100c6L, 0x402c7279L, + 0x679f25feL, 0xfb1fa3ccL, 0x8ea5e9f8L, 0xdb3222f8L, + 0x3c7516dfL, 0xfd616b15L, 0x2f501ec8L, 0xad0552abL, + 0x323db5faL, 0xfd238760L, 0x53317b48L, 0x3e00df82L, + 0x9e5c57bbL, 0xca6f8ca0L, 0x1a87562eL, 0xdf1769dbL, + 0xd542a8f6L, 0x287effc3L, 0xac6732c6L, 0x8c4f5573L, + 0x695b27b0L, 0xbbca58c8L, 0xe1ffa35dL, 0xb8f011a0L, + 0x10fa3d98L, 0xfd2183b8L, 0x4afcb56cL, 0x2dd1d35bL, + 0x9a53e479L, 0xb6f84565L, 0xd28e49bcL, 0x4bfb9790L, + 0xe1ddf2daL, 0xa4cb7e33L, 0x62fb1341L, 0xcee4c6e8L, + 0xef20cadaL, 0x36774c01L, 0xd07e9efeL, 0x2bf11fb4L, + 0x95dbda4dL, 0xae909198L, 0xeaad8e71L, 0x6b93d5a0L, + 0xd08ed1d0L, 0xafc725e0L, 0x8e3c5b2fL, 0x8e7594b7L, + 0x8ff6e2fbL, 0xf2122b64L, 0x8888b812L, 0x900df01cL, + 0x4fad5ea0L, 0x688fc31cL, 0xd1cff191L, 0xb3a8c1adL, + 0x2f2f2218L, 0xbe0e1777L, 0xea752dfeL, 0x8b021fa1L, + 0xe5a0cc0fL, 0xb56f74e8L, 0x18acf3d6L, 0xce89e299L, + 0xb4a84fe0L, 0xfd13e0b7L, 0x7cc43b81L, 0xd2ada8d9L, + 0x165fa266L, 0x80957705L, 0x93cc7314L, 0x211a1477L, + 0xe6ad2065L, 0x77b5fa86L, 0xc75442f5L, 0xfb9d35cfL, + 0xebcdaf0cL, 0x7b3e89a0L, 0xd6411bd3L, 0xae1e7e49L, + 0x00250e2dL, 0x2071b35eL, 0x226800bbL, 0x57b8e0afL, + 0x2464369bL, 0xf009b91eL, 0x5563911dL, 0x59dfa6aaL, + 0x78c14389L, 0xd95a537fL, 0x207d5ba2L, 0x02e5b9c5L, + 0x83260376L, 0x6295cfa9L, 0x11c81968L, 0x4e734a41L, + 0xb3472dcaL, 0x7b14a94aL, 0x1b510052L, 0x9a532915L, + 0xd60f573fL, 0xbc9bc6e4L, 0x2b60a476L, 0x81e67400L, + 0x08ba6fb5L, 0x571be91fL, 0xf296ec6bL, 0x2a0dd915L, + 0xb6636521L, 0xe7b9f9b6L, 0xff34052eL, 0xc5855664L, + 0x53b02d5dL, 0xa99f8fa1L, 0x08ba4799L, 0x6e85076aL, + 0x4b7a70e9L, 0xb5b32944L, 0xdb75092eL, 0xc4192623L, + 0xad6ea6b0L, 0x49a7df7dL, 0x9cee60b8L, 0x8fedb266L, + 0xecaa8c71L, 0x699a17ffL, 0x5664526cL, 0xc2b19ee1L, + 0x193602a5L, 0x75094c29L, 0xa0591340L, 0xe4183a3eL, + 0x3f54989aL, 0x5b429d65L, 0x6b8fe4d6L, 0x99f73fd6L, + 0xa1d29c07L, 0xefe830f5L, 0x4d2d38e6L, 0xf0255dc1L, + 0x4cdd2086L, 0x8470eb26L, 0x6382e9c6L, 0x021ecc5eL, + 0x09686b3fL, 0x3ebaefc9L, 0x3c971814L, 0x6b6a70a1L, + 0x687f3584L, 0x52a0e286L, 0xb79c5305L, 0xaa500737L, + 0x3e07841cL, 0x7fdeae5cL, 0x8e7d44ecL, 0x5716f2b8L, + 0xb03ada37L, 0xf0500c0dL, 0xf01c1f04L, 0x0200b3ffL, + 0xae0cf51aL, 0x3cb574b2L, 0x25837a58L, 0xdc0921bdL, + 0xd19113f9L, 0x7ca92ff6L, 0x94324773L, 0x22f54701L, + 0x3ae5e581L, 0x37c2dadcL, 0xc8b57634L, 0x9af3dda7L, + 0xa9446146L, 0x0fd0030eL, 0xecc8c73eL, 0xa4751e41L, + 0xe238cd99L, 0x3bea0e2fL, 0x3280bba1L, 0x183eb331L, + 0x4e548b38L, 0x4f6db908L, 0x6f420d03L, 0xf60a04bfL, + 0x2cb81290L, 0x24977c79L, 0x5679b072L, 0xbcaf89afL, + 0xde9a771fL, 0xd9930810L, 0xb38bae12L, 0xdccf3f2eL, + 0x5512721fL, 0x2e6b7124L, 0x501adde6L, 0x9f84cd87L, + 0x7a584718L, 0x7408da17L, 0xbc9f9abcL, 0xe94b7d8cL, + 0xec7aec3aL, 0xdb851dfaL, 0x63094366L, 0xc464c3d2L, + 0xef1c1847L, 0x3215d908L, 0xdd433b37L, 0x24c2ba16L, + 0x12a14d43L, 0x2a65c451L, 0x50940002L, 0x133ae4ddL, + 0x71dff89eL, 0x10314e55L, 0x81ac77d6L, 0x5f11199bL, + 0x043556f1L, 0xd7a3c76bL, 0x3c11183bL, 0x5924a509L, + 0xf28fe6edL, 0x97f1fbfaL, 0x9ebabf2cL, 0x1e153c6eL, + 0x86e34570L, 0xeae96fb1L, 0x860e5e0aL, 0x5a3e2ab3L, + 0x771fe71cL, 0x4e3d06faL, 0x2965dcb9L, 0x99e71d0fL, + 0x803e89d6L, 0x5266c825L, 0x2e4cc978L, 0x9c10b36aL, + 0xc6150ebaL, 0x94e2ea78L, 0xa5fc3c53L, 0x1e0a2df4L, + 0xf2f74ea7L, 0x361d2b3dL, 0x1939260fL, 0x19c27960L, + 0x5223a708L, 0xf71312b6L, 0xebadfe6eL, 0xeac31f66L, + 0xe3bc4595L, 0xa67bc883L, 0xb17f37d1L, 0x018cff28L, + 0xc332ddefL, 0xbe6c5aa5L, 0x65582185L, 0x68ab9802L, + 0xeecea50fL, 0xdb2f953bL, 0x2aef7dadL, 0x5b6e2f84L, + 0x1521b628L, 0x29076170L, 0xecdd4775L, 0x619f1510L, + 0x13cca830L, 0xeb61bd96L, 0x0334fe1eL, 0xaa0363cfL, + 0xb5735c90L, 0x4c70a239L, 0xd59e9e0bL, 0xcbaade14L, + 0xeecc86bcL, 0x60622ca7L, 0x9cab5cabL, 0xb2f3846eL, + 0x648b1eafL, 0x19bdf0caL, 0xa02369b9L, 0x655abb50L, + 0x40685a32L, 0x3c2ab4b3L, 0x319ee9d5L, 0xc021b8f7L, + 0x9b540b19L, 0x875fa099L, 0x95f7997eL, 0x623d7da8L, + 0xf837889aL, 0x97e32d77L, 0x11ed935fL, 0x16681281L, + 0x0e358829L, 0xc7e61fd6L, 0x96dedfa1L, 0x7858ba99L, + 0x57f584a5L, 0x1b227263L, 0x9b83c3ffL, 0x1ac24696L, + 0xcdb30aebL, 0x532e3054L, 0x8fd948e4L, 0x6dbc3128L, + 0x58ebf2efL, 0x34c6ffeaL, 0xfe28ed61L, 0xee7c3c73L, + 0x5d4a14d9L, 0xe864b7e3L, 0x42105d14L, 0x203e13e0L, + 0x45eee2b6L, 0xa3aaabeaL, 0xdb6c4f15L, 0xfacb4fd0L, + 0xc742f442L, 0xef6abbb5L, 0x654f3b1dL, 0x41cd2105L, + 0xd81e799eL, 0x86854dc7L, 0xe44b476aL, 0x3d816250L, + 0xcf62a1f2L, 0x5b8d2646L, 0xfc8883a0L, 0xc1c7b6a3L, + 0x7f1524c3L, 0x69cb7492L, 0x47848a0bL, 0x5692b285L, + 0x095bbf00L, 0xad19489dL, 0x1462b174L, 0x23820e00L, + 0x58428d2aL, 0x0c55f5eaL, 0x1dadf43eL, 0x233f7061L, + 0x3372f092L, 0x8d937e41L, 0xd65fecf1L, 0x6c223bdbL, + 0x7cde3759L, 0xcbee7460L, 0x4085f2a7L, 0xce77326eL, + 0xa6078084L, 0x19f8509eL, 0xe8efd855L, 0x61d99735L, + 0xa969a7aaL, 0xc50c06c2L, 0x5a04abfcL, 0x800bcadcL, + 0x9e447a2eL, 0xc3453484L, 0xfdd56705L, 0x0e1e9ec9L, + 0xdb73dbd3L, 0x105588cdL, 0x675fda79L, 0xe3674340L, + 0xc5c43465L, 0x713e38d8L, 0x3d28f89eL, 0xf16dff20L, + 0x153e21e7L, 0x8fb03d4aL, 0xe6e39f2bL, 0xdb83adf7L, + 0xe93d5a68L, 0x948140f7L, 0xf64c261cL, 0x94692934L, + 0x411520f7L, 0x7602d4f7L, 0xbcf46b2eL, 0xd4a20068L, + 0xd4082471L, 0x3320f46aL, 0x43b7d4b7L, 0x500061afL, + 0x1e39f62eL, 0x97244546L, 0x14214f74L, 0xbf8b8840L, + 0x4d95fc1dL, 0x96b591afL, 0x70f4ddd3L, 0x66a02f45L, + 0xbfbc09ecL, 0x03bd9785L, 0x7fac6dd0L, 0x31cb8504L, + 0x96eb27b3L, 0x55fd3941L, 0xda2547e6L, 0xabca0a9aL, + 0x28507825L, 0x530429f4L, 0x0a2c86daL, 0xe9b66dfbL, + 0x68dc1462L, 0xd7486900L, 0x680ec0a4L, 0x27a18deeL, + 0x4f3ffea2L, 0xe887ad8cL, 0xb58ce006L, 0x7af4d6b6L, + 0xaace1e7cL, 0xd3375fecL, 0xce78a399L, 0x406b2a42L, + 0x20fe9e35L, 0xd9f385b9L, 0xee39d7abL, 0x3b124e8bL, + 0x1dc9faf7L, 0x4b6d1856L, 0x26a36631L, 0xeae397b2L, + 0x3a6efa74L, 0xdd5b4332L, 0x6841e7f7L, 0xca7820fbL, + 0xfb0af54eL, 0xd8feb397L, 0x454056acL, 0xba489527L, + 0x55533a3aL, 0x20838d87L, 0xfe6ba9b7L, 0xd096954bL, + 0x55a867bcL, 0xa1159a58L, 0xcca92963L, 0x99e1db33L, + 0xa62a4a56L, 0x3f3125f9L, 0x5ef47e1cL, 0x9029317cL, + 0xfdf8e802L, 0x04272f70L, 0x80bb155cL, 0x05282ce3L, + 0x95c11548L, 0xe4c66d22L, 0x48c1133fL, 0xc70f86dcL, + 0x07f9c9eeL, 0x41041f0fL, 0x404779a4L, 0x5d886e17L, + 0x325f51ebL, 0xd59bc0d1L, 0xf2bcc18fL, 0x41113564L, + 0x257b7834L, 0x602a9c60L, 0xdff8e8a3L, 0x1f636c1bL, + 0x0e12b4c2L, 0x02e1329eL, 0xaf664fd1L, 0xcad18115L, + 0x6b2395e0L, 0x333e92e1L, 0x3b240b62L, 0xeebeb922L, + 0x85b2a20eL, 0xe6ba0d99L, 0xde720c8cL, 0x2da2f728L, + 0xd0127845L, 0x95b794fdL, 0x647d0862L, 0xe7ccf5f0L, + 0x5449a36fL, 0x877d48faL, 0xc39dfd27L, 0xf33e8d1eL, + 0x0a476341L, 0x992eff74L, 0x3a6f6eabL, 0xf4f8fd37L, + 0xa812dc60L, 0xa1ebddf8L, 0x991be14cL, 0xdb6e6b0dL, + 0xc67b5510L, 0x6d672c37L, 0x2765d43bL, 0xdcd0e804L, + 0xf1290dc7L, 0xcc00ffa3L, 0xb5390f92L, 0x690fed0bL, + 0x667b9ffbL, 0xcedb7d9cL, 0xa091cf0bL, 0xd9155ea3L, + 0xbb132f88L, 0x515bad24L, 0x7b9479bfL, 0x763bd6ebL, + 0x37392eb3L, 0xcc115979L, 0x8026e297L, 0xf42e312dL, + 0x6842ada7L, 0xc66a2b3bL, 0x12754cccL, 0x782ef11cL, + 0x6a124237L, 0xb79251e7L, 0x06a1bbe6L, 0x4bfb6350L, + 0x1a6b1018L, 0x11caedfaL, 0x3d25bdd8L, 0xe2e1c3c9L, + 0x44421659L, 0x0a121386L, 0xd90cec6eL, 0xd5abea2aL, + 0x64af674eL, 0xda86a85fL, 0xbebfe988L, 0x64e4c3feL, + 0x9dbc8057L, 0xf0f7c086L, 0x60787bf8L, 0x6003604dL, + 0xd1fd8346L, 0xf6381fb0L, 0x7745ae04L, 0xd736fcccL, + 0x83426b33L, 0xf01eab71L, 0xb0804187L, 0x3c005e5fL, + 0x77a057beL, 0xbde8ae24L, 0x55464299L, 0xbf582e61L, + 0x4e58f48fL, 0xf2ddfda2L, 0xf474ef38L, 0x8789bdc2L, + 0x5366f9c3L, 0xc8b38e74L, 0xb475f255L, 0x46fcd9b9L, + 0x7aeb2661L, 0x8b1ddf84L, 0x846a0e79L, 0x915f95e2L, + 0x466e598eL, 0x20b45770L, 0x8cd55591L, 0xc902de4cL, + 0xb90bace1L, 0xbb8205d0L, 0x11a86248L, 0x7574a99eL, + 0xb77f19b6L, 0xe0a9dc09L, 0x662d09a1L, 0xc4324633L, + 0xe85a1f02L, 0x09f0be8cL, 0x4a99a025L, 0x1d6efe10L, + 0x1ab93d1dL, 0x0ba5a4dfL, 0xa186f20fL, 0x2868f169L, + 0xdcb7da83L, 0x573906feL, 0xa1e2ce9bL, 0x4fcd7f52L, + 0x50115e01L, 0xa70683faL, 0xa002b5c4L, 0x0de6d027L, + 0x9af88c27L, 0x773f8641L, 0xc3604c06L, 0x61a806b5L, + 0xf0177a28L, 0xc0f586e0L, 0x006058aaL, 0x30dc7d62L, + 0x11e69ed7L, 0x2338ea63L, 0x53c2dd94L, 0xc2c21634L, + 0xbbcbee56L, 0x90bcb6deL, 0xebfc7da1L, 0xce591d76L, + 0x6f05e409L, 0x4b7c0188L, 0x39720a3dL, 0x7c927c24L, + 0x86e3725fL, 0x724d9db9L, 0x1ac15bb4L, 0xd39eb8fcL, + 0xed545578L, 0x08fca5b5L, 0xd83d7cd3L, 0x4dad0fc4L, + 0x1e50ef5eL, 0xb161e6f8L, 0xa28514d9L, 0x6c51133cL, + 0x6fd5c7e7L, 0x56e14ec4L, 0x362abfceL, 0xddc6c837L, + 0xd79a3234L, 0x92638212L, 0x670efa8eL, 0x406000e0L, + 0x3a39ce37L, 0xd3faf5cfL, 0xabc27737L, 0x5ac52d1bL, + 0x5cb0679eL, 0x4fa33742L, 0xd3822740L, 0x99bc9bbeL, + 0xd5118e9dL, 0xbf0f7315L, 0xd62d1c7eL, 0xc700c47bL, + 0xb78c1b6bL, 0x21a19045L, 0xb26eb1beL, 0x6a366eb4L, + 0x5748ab2fL, 0xbc946e79L, 0xc6a376d2L, 0x6549c2c8L, + 0x530ff8eeL, 0x468dde7dL, 0xd5730a1dL, 0x4cd04dc6L, + 0x2939bbdbL, 0xa9ba4650L, 0xac9526e8L, 0xbe5ee304L, + 0xa1fad5f0L, 0x6a2d519aL, 0x63ef8ce2L, 0x9a86ee22L, + 0xc089c2b8L, 0x43242ef6L, 0xa51e03aaL, 0x9cf2d0a4L, + 0x83c061baL, 0x9be96a4dL, 0x8fe51550L, 0xba645bd6L, + 0x2826a2f9L, 0xa73a3ae1L, 0x4ba99586L, 0xef5562e9L, + 0xc72fefd3L, 0xf752f7daL, 0x3f046f69L, 0x77fa0a59L, + 0x80e4a915L, 0x87b08601L, 0x9b09e6adL, 0x3b3ee593L, + 0xe990fd5aL, 0x9e34d797L, 0x2cf0b7d9L, 0x022b8b51L, + 0x96d5ac3aL, 0x017da67dL, 0xd1cf3ed6L, 0x7c7d2d28L, + 0x1f9f25cfL, 0xadf2b89bL, 0x5ad6b472L, 0x5a88f54cL, + 0xe029ac71L, 0xe019a5e6L, 0x47b0acfdL, 0xed93fa9bL, + 0xe8d3c48dL, 0x283b57ccL, 0xf8d56629L, 0x79132e28L, + 0x785f0191L, 0xed756055L, 0xf7960e44L, 0xe3d35e8cL, + 0x15056dd4L, 0x88f46dbaL, 0x03a16125L, 0x0564f0bdL, + 0xc3eb9e15L, 0x3c9057a2L, 0x97271aecL, 0xa93a072aL, + 0x1b3f6d9bL, 0x1e6321f5L, 0xf59c66fbL, 0x26dcf319L, + 0x7533d928L, 0xb155fdf5L, 0x03563482L, 0x8aba3cbbL, + 0x28517711L, 0xc20ad9f8L, 0xabcc5167L, 0xccad925fL, + 0x4de81751L, 0x3830dc8eL, 0x379d5862L, 0x9320f991L, + 0xea7a90c2L, 0xfb3e7bceL, 0x5121ce64L, 0x774fbe32L, + 0xa8b6e37eL, 0xc3293d46L, 0x48de5369L, 0x6413e680L, + 0xa2ae0810L, 0xdd6db224L, 0x69852dfdL, 0x09072166L, + 0xb39a460aL, 0x6445c0ddL, 0x586cdecfL, 0x1c20c8aeL, + 0x5bbef7ddL, 0x1b588d40L, 0xccd2017fL, 0x6bb4e3bbL, + 0xdda26a7eL, 0x3a59ff45L, 0x3e350a44L, 0xbcb4cdd5L, + 0x72eacea8L, 0xfa6484bbL, 0x8d6612aeL, 0xbf3c6f47L, + 0xd29be463L, 0x542f5d9eL, 0xaec2771bL, 0xf64e6370L, + 0x740e0d8dL, 0xe75b1357L, 0xf8721671L, 0xaf537d5dL, + 0x4040cb08L, 0x4eb4e2ccL, 0x34d2466aL, 0x0115af84L, + 0xe1b00428L, 0x95983a1dL, 0x06b89fb4L, 0xce6ea048L, + 0x6f3f3b82L, 0x3520ab82L, 0x011a1d4bL, 0x277227f8L, + 0x611560b1L, 0xe7933fdcL, 0xbb3a792bL, 0x344525bdL, + 0xa08839e1L, 0x51ce794bL, 0x2f32c9b7L, 0xa01fbac9L, + 0xe01cc87eL, 0xbcc7d1f6L, 0xcf0111c3L, 0xa1e8aac7L, + 0x1a908749L, 0xd44fbd9aL, 0xd0dadecbL, 0xd50ada38L, + 0x0339c32aL, 0xc6913667L, 0x8df9317cL, 0xe0b12b4fL, + 0xf79e59b7L, 0x43f5bb3aL, 0xf2d519ffL, 0x27d9459cL, + 0xbf97222cL, 0x15e6fc2aL, 0x0f91fc71L, 0x9b941525L, + 0xfae59361L, 0xceb69cebL, 0xc2a86459L, 0x12baa8d1L, + 0xb6c1075eL, 0xe3056a0cL, 0x10d25065L, 0xcb03a442L, + 0xe0ec6e0eL, 0x1698db3bL, 0x4c98a0beL, 0x3278e964L, + 0x9f1f9532L, 0xe0d392dfL, 0xd3a0342bL, 0x8971f21eL, + 0x1b0a7441L, 0x4ba3348cL, 0xc5be7120L, 0xc37632d8L, + 0xdf359f8dL, 0x9b992f2eL, 0xe60b6f47L, 0x0fe3f11dL, + 0xe54cda54L, 0x1edad891L, 0xce6279cfL, 0xcd3e7e6fL, + 0x1618b166L, 0xfd2c1d05L, 0x848fd2c5L, 0xf6fb2299L, + 0xf523f357L, 0xa6327623L, 0x93a83531L, 0x56cccd02L, + 0xacf08162L, 0x5a75ebb5L, 0x6e163697L, 0x88d273ccL, + 0xde966292L, 0x81b949d0L, 0x4c50901bL, 0x71c65614L, + 0xe6c6c7bdL, 0x327a140aL, 0x45e1d006L, 0xc3f27b9aL, + 0xc9aa53fdL, 0x62a80f00L, 0xbb25bfe2L, 0x35bdd2f6L, + 0x71126905L, 0xb2040222L, 0xb6cbcf7cL, 0xcd769c2bL, + 0x53113ec0L, 0x1640e3d3L, 0x38abbd60L, 0x2547adf0L, + 0xba38209cL, 0xf746ce76L, 0x77afa1c5L, 0x20756060L, + 0x85cbfe4eL, 0x8ae88dd8L, 0x7aaaf9b0L, 0x4cf9aa7eL, + 0x1948c25cL, 0x02fb8a8cL, 0x01c36ae4L, 0xd6ebe1f9L, + 0x90d4f869L, 0xa65cdea0L, 0x3f09252dL, 0xc208e69fL, + 0xb74e6132L, 0xce77e25bL, 0x578fdfe3L, 0x3ac372e6L, + } + }; + diff --git a/libsecurity_apple_csp/open_ssl/bf/bf_skey.c b/libsecurity_apple_csp/open_ssl/bf/bf_skey.c new file mode 100644 index 00000000..4d6a232f --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/bf/bf_skey.c @@ -0,0 +1,116 @@ +/* crypto/bf/bf_skey.c */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include +#include +#include +#include "bf_locl.h" +#include "bf_pi.h" + +void BF_set_key(BF_KEY *key, int len, const unsigned char *data) + { + int i; + BF_LONG *p,ri,in[2]; + const unsigned char *d,*end; + + + memcpy((char *)key,(char *)&bf_init,sizeof(BF_KEY)); + p=key->P; + + if (len > ((BF_ROUNDS+2)*4)) len=(BF_ROUNDS+2)*4; + + d=data; + end= &(data[len]); + for (i=0; i<(BF_ROUNDS+2); i++) + { + ri= *(d++); + if (d >= end) d=data; + + ri<<=8; + ri|= *(d++); + if (d >= end) d=data; + + ri<<=8; + ri|= *(d++); + if (d >= end) d=data; + + ri<<=8; + ri|= *(d++); + if (d >= end) d=data; + + p[i]^=ri; + } + + in[0]=0L; + in[1]=0L; + for (i=0; i<(BF_ROUNDS+2); i+=2) + { + BF_encrypt(in,key); + p[i ]=in[0]; + p[i+1]=in[1]; + } + + p=key->S; + for (i=0; i<4*256; i+=2) + { + BF_encrypt(in,key); + p[i ]=in[0]; + p[i+1]=in[1]; + } + } + diff --git a/libsecurity_apple_csp/open_ssl/bio/bio_lib.c b/libsecurity_apple_csp/open_ssl/bio/bio_lib.c new file mode 100644 index 00000000..4040be73 --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/bio/bio_lib.c @@ -0,0 +1,552 @@ +/* + * 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. + */ + + +/* crypto/bio/bio_lib.c */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include +#include +#include +#include "cryptlib.h" +#include +#include + +static STACK_OF(CRYPTO_EX_DATA_FUNCS) *bio_meth=NULL; +static int bio_meth_num=0; + +BIO *BIO_new(const BIO_METHOD *method) + { + BIO *ret=NULL; + + ret=(BIO *)Malloc(sizeof(BIO)); + if (ret == NULL) + { + BIOerr(BIO_F_BIO_NEW,ERR_R_MALLOC_FAILURE); + return(NULL); + } + if (!BIO_set(ret,method)) + { + Free(ret); + ret=NULL; + } + return(ret); + } + +int BIO_set(BIO *bio, const BIO_METHOD *method) + { + bio->method=method; + bio->callback=NULL; + bio->cb_arg=NULL; + bio->init=0; + bio->shutdown=1; + bio->flags=0; + bio->retry_reason=0; + bio->num=0; + bio->ptr=NULL; + bio->prev_bio=NULL; + bio->next_bio=NULL; + bio->references=1; + bio->num_read=0L; + bio->num_write=0L; + CRYPTO_new_ex_data(bio_meth,bio,&bio->ex_data); + if (method->create != NULL) + if (!method->create(bio)) + return(0); + return(1); + } + +int BIO_free(BIO *a) + { + int ret=0,i; + + if (a == NULL) return(0); + + i=CRYPTO_add(&a->references,-1,CRYPTO_LOCK_BIO); +#ifdef REF_PRINT + REF_PRINT("BIO",a); +#endif + if (i > 0) return(1); +#ifdef REF_CHECK + if (i < 0) + { + fprintf(stderr,"BIO_free, bad reference count\n"); + abort(); + } +#endif + if ((a->callback != NULL) && + ((i=(int)a->callback(a,BIO_CB_FREE,NULL,0,0L,1L)) <= 0)) + return(i); + + CRYPTO_free_ex_data(bio_meth,a,&a->ex_data); + + if ((a->method == NULL) || (a->method->destroy == NULL)) return(1); + ret=a->method->destroy(a); + Free(a); + return(1); + } + +int BIO_read(BIO *b, void *out, int outl) + { + int i; + long (*cb)(); + + if ((b == NULL) || (b->method == NULL) || (b->method->bread == NULL)) + { + BIOerr(BIO_F_BIO_READ,BIO_R_UNSUPPORTED_METHOD); + return(-2); + } + + cb=b->callback; + if ((cb != NULL) && + ((i=(int)cb(b,BIO_CB_READ,out,outl,0L,1L)) <= 0)) + return(i); + + if (!b->init) + { + BIOerr(BIO_F_BIO_READ,BIO_R_UNINITIALIZED); + return(-2); + } + + i=b->method->bread(b,out,outl); + + if (i > 0) b->num_read+=(unsigned long)i; + + if (cb != NULL) + i=(int)cb(b,BIO_CB_READ|BIO_CB_RETURN,out,outl, + 0L,(long)i); + return(i); + } + +int BIO_write(BIO *b, const void *in, int inl) + { + int i; + long (*cb)(); + + if (b == NULL) + return(0); + + cb=b->callback; + if ((b->method == NULL) || (b->method->bwrite == NULL)) + { + BIOerr(BIO_F_BIO_WRITE,BIO_R_UNSUPPORTED_METHOD); + return(-2); + } + + if ((cb != NULL) && + ((i=(int)cb(b,BIO_CB_WRITE,in,inl,0L,1L)) <= 0)) + return(i); + + if (!b->init) + { + BIOerr(BIO_F_BIO_WRITE,BIO_R_UNINITIALIZED); + return(-2); + } + + i=b->method->bwrite(b,in,inl); + + if (i > 0) b->num_write+=(unsigned long)i; + + /* This is evil and not thread safe. If the BIO has been freed, + * we must not call the callback. The only way to be able to + * determine this is the reference count which is now invalid since + * the memory has been free()ed. + */ + if (b->references <= 0) abort(); + if (cb != NULL) /* && (b->references >= 1)) */ + i=(int)cb(b,BIO_CB_WRITE|BIO_CB_RETURN,in,inl, + 0L,(long)i); + return(i); + } + +int BIO_puts(BIO *b, const char *in) + { + int i; + long (*cb)(); + + if ((b == NULL) || (b->method == NULL) || (b->method->bputs == NULL)) + { + BIOerr(BIO_F_BIO_PUTS,BIO_R_UNSUPPORTED_METHOD); + return(-2); + } + + cb=b->callback; + + if ((cb != NULL) && + ((i=(int)cb(b,BIO_CB_PUTS,in,0,0L,1L)) <= 0)) + return(i); + + if (!b->init) + { + BIOerr(BIO_F_BIO_PUTS,BIO_R_UNINITIALIZED); + return(-2); + } + + i=b->method->bputs(b,in); + + if (cb != NULL) + i=(int)cb(b,BIO_CB_PUTS|BIO_CB_RETURN,in,0, + 0L,(long)i); + return(i); + } + +int BIO_gets(BIO *b, char *in, int inl) + { + int i; + long (*cb)(); + + if ((b == NULL) || (b->method == NULL) || (b->method->bgets == NULL)) + { + BIOerr(BIO_F_BIO_GETS,BIO_R_UNSUPPORTED_METHOD); + return(-2); + } + + cb=b->callback; + + if ((cb != NULL) && + ((i=(int)cb(b,BIO_CB_GETS,in,inl,0L,1L)) <= 0)) + return(i); + + if (!b->init) + { + BIOerr(BIO_F_BIO_GETS,BIO_R_UNINITIALIZED); + return(-2); + } + + i=b->method->bgets(b,in,inl); + + if (cb != NULL) + i=(int)cb(b,BIO_CB_GETS|BIO_CB_RETURN,in,inl, + 0L,(long)i); + return(i); + } + +long BIO_int_ctrl(BIO *b, int cmd, long larg, int iarg) + { + int i; + + i=iarg; + return(BIO_ctrl(b,cmd,larg,(char *)&i)); + } + +char *BIO_ptr_ctrl(BIO *b, int cmd, long larg) + { + char *p=NULL; + + if (BIO_ctrl(b,cmd,larg,(char *)&p) <= 0) + return(NULL); + else + return(p); + } + +long BIO_ctrl(BIO *b, int cmd, long larg, void *parg) + { + long ret; + long (*cb)(); + + if (b == NULL) return(0); + + if ((b->method == NULL) || (b->method->ctrl == NULL)) + { + BIOerr(BIO_F_BIO_CTRL,BIO_R_UNSUPPORTED_METHOD); + return(-2); + } + + cb=b->callback; + + if ((cb != NULL) && + ((ret=cb(b,BIO_CB_CTRL,parg,cmd,larg,1L)) <= 0)) + return(ret); + + ret=b->method->ctrl(b,cmd,larg,parg); + + if (cb != NULL) + ret=cb(b,BIO_CB_CTRL|BIO_CB_RETURN,parg,cmd, + larg,ret); + return(ret); + } + +long BIO_callback_ctrl(BIO *b, int cmd, void (*fp)()) + { + long ret; + long (*cb)(); + + if (b == NULL) return(0); + + if ((b->method == NULL) || (b->method->callback_ctrl == NULL)) + { + BIOerr(BIO_F_BIO_CTRL,BIO_R_UNSUPPORTED_METHOD); + return(-2); + } + + cb=b->callback; + + if ((cb != NULL) && + ((ret=cb(b,BIO_CB_CTRL,(void *)&fp,cmd,0,1L)) <= 0)) + return(ret); + + ret=b->method->callback_ctrl(b,cmd,fp); + + if (cb != NULL) + ret=cb(b,BIO_CB_CTRL|BIO_CB_RETURN,(void *)&fp,cmd, + 0,ret); + return(ret); + } + +/* It is unfortunate to duplicate in functions what the BIO_(w)pending macros + * do; but those macros have inappropriate return type, and for interfacing + * from other programming languages, C macros aren't much of a help anyway. */ +size_t BIO_ctrl_pending(BIO *bio) + { + return BIO_ctrl(bio, BIO_CTRL_PENDING, 0, NULL); + } + +size_t BIO_ctrl_wpending(BIO *bio) + { + return BIO_ctrl(bio, BIO_CTRL_WPENDING, 0, NULL); + } + + +/* put the 'bio' on the end of b's list of operators */ +BIO *BIO_push(BIO *b, BIO *bio) + { + BIO *lb; + + if (b == NULL) return(bio); + lb=b; + while (lb->next_bio != NULL) + lb=lb->next_bio; + lb->next_bio=bio; + if (bio != NULL) + bio->prev_bio=lb; + /* called to do internal processing */ + BIO_ctrl(b,BIO_CTRL_PUSH,0,NULL); + return(b); + } + +/* Remove the first and return the rest */ +BIO *BIO_pop(BIO *b) + { + BIO *ret; + + if (b == NULL) return(NULL); + ret=b->next_bio; + + if (b->prev_bio != NULL) + b->prev_bio->next_bio=b->next_bio; + if (b->next_bio != NULL) + b->next_bio->prev_bio=b->prev_bio; + + b->next_bio=NULL; + b->prev_bio=NULL; + BIO_ctrl(b,BIO_CTRL_POP,0,NULL); + return(ret); + } + +BIO *BIO_get_retry_BIO(BIO *bio, int *reason) + { + BIO *b,*last; + + b=last=bio; + for (;;) + { + if (!BIO_should_retry(b)) break; + last=b; + b=b->next_bio; + if (b == NULL) break; + } + if (reason != NULL) *reason=last->retry_reason; + return(last); + } + +int BIO_get_retry_reason(BIO *bio) + { + return(bio->retry_reason); + } + +BIO *BIO_find_type(BIO *bio, int type) + { + int mt,mask; + + mask=type&0xff; + do { + if (bio->method != NULL) + { + mt=bio->method->type; + + if (!mask) + { + if (mt & type) return(bio); + } + else if (mt == type) + return(bio); + } + bio=bio->next_bio; + } while (bio != NULL); + return(NULL); + } + +void BIO_free_all(BIO *bio) + { + BIO *b; + int ref; + + while (bio != NULL) + { + b=bio; + ref=b->references; + bio=bio->next_bio; + BIO_free(b); + /* Since ref count > 1, don't free anyone else. */ + if (ref > 1) break; + } + } + +BIO *BIO_dup_chain(BIO *in) + { + BIO *ret=NULL,*eoc=NULL,*bio,*new; + + for (bio=in; bio != NULL; bio=bio->next_bio) + { + if ((new=BIO_new(bio->method)) == NULL) goto err; + new->callback=bio->callback; + new->cb_arg=bio->cb_arg; + new->init=bio->init; + new->shutdown=bio->shutdown; + new->flags=bio->flags; + + /* This will let SSL_s_sock() work with stdin/stdout */ + new->num=bio->num; + + if (!BIO_dup_state(bio,(char *)new)) + { + BIO_free(new); + goto err; + } + + /* copy app data */ + if (!CRYPTO_dup_ex_data(bio_meth,&new->ex_data,&bio->ex_data)) + goto err; + + if (ret == NULL) + { + eoc=new; + ret=eoc; + } + else + { + BIO_push(eoc,new); + eoc=new; + } + } + return(ret); +err: + if (ret != NULL) + BIO_free(ret); + return(NULL); + } + +void BIO_copy_next_retry(BIO *b) + { + BIO_set_flags(b,BIO_get_retry_flags(b->next_bio)); + b->retry_reason=b->next_bio->retry_reason; + } + +int BIO_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, + CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func) + { + bio_meth_num++; + return(CRYPTO_get_ex_new_index(bio_meth_num-1,&bio_meth, + argl,argp,new_func,dup_func,free_func)); + } + +int BIO_set_ex_data(BIO *bio, int idx, void *data) + { + return(CRYPTO_set_ex_data(&(bio->ex_data),idx,data)); + } + +void *BIO_get_ex_data(BIO *bio, int idx) + { + return(CRYPTO_get_ex_data(&(bio->ex_data),idx)); + } + +unsigned long BIO_number_read(BIO *bio) +{ + if(bio) return bio->num_read; + return 0; +} + +unsigned long BIO_number_written(BIO *bio) +{ + if(bio) return bio->num_write; + return 0; +} diff --git a/libsecurity_apple_csp/open_ssl/bio/bss_file.c b/libsecurity_apple_csp/open_ssl/bio/bss_file.c new file mode 100644 index 00000000..97ad27b7 --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/bio/bss_file.c @@ -0,0 +1,328 @@ +/* + * 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. + */ + + +/* crypto/bio/bss_file.c */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +/* + * 03-Dec-1997 rdenny@dc3.com Fix bug preventing use of stdin/stdout + * with binary data (e.g. asn1parse -inform DER < xxx) under + * Windows + */ + +#ifndef HEADER_BSS_FILE_C +#define HEADER_BSS_FILE_C + +#include +#include +#include "cryptlib.h" +#include +#include + +#if !defined(NO_STDIO) + +static int MS_CALLBACK file_write(BIO *h,char *buf,int num); +static int MS_CALLBACK file_read(BIO *h,char *buf,int size); +static int MS_CALLBACK file_puts(BIO *h,char *str); +static int MS_CALLBACK file_gets(BIO *h,char *str,int size); +static long MS_CALLBACK file_ctrl(BIO *h,int cmd,long arg1,char *arg2); +static int MS_CALLBACK file_new(BIO *h); +static int MS_CALLBACK file_free(BIO *data); +static const BIO_METHOD methods_filep= + { + BIO_TYPE_FILE, + "FILE pointer", + file_write, + file_read, + file_puts, + file_gets, + file_ctrl, + file_new, + file_free, + NULL, + }; + +BIO *BIO_new_file(const char *filename, const char *mode) + { + BIO *ret; + FILE *file; + + if ((file=fopen(filename,mode)) == NULL) + { + SYSerr(SYS_F_FOPEN,get_last_sys_error()); + ERR_add_error_data(5,"fopen('",filename,"','",mode,"')"); + BIOerr(BIO_F_BIO_NEW_FILE,ERR_R_SYS_LIB); + return(NULL); + } + if ((ret=BIO_new(BIO_s_file_internal())) == NULL) + return(NULL); + + BIO_set_fp(ret,file,BIO_CLOSE); + return(ret); + } + +BIO *BIO_new_fp(FILE *stream, int close_flag) + { + BIO *ret; + + if ((ret=BIO_new(BIO_s_file())) == NULL) + return(NULL); + + BIO_set_fp(ret,stream,close_flag); + return(ret); + } + +const BIO_METHOD *BIO_s_file(void) + { + return(&methods_filep); + } + +static int MS_CALLBACK file_new(BIO *bi) + { + bi->init=0; + bi->num=0; + bi->ptr=NULL; + return(1); + } + +static int MS_CALLBACK file_free(BIO *a) + { + if (a == NULL) return(0); + if (a->shutdown) + { + if ((a->init) && (a->ptr != NULL)) + { + fclose((FILE *)a->ptr); + a->ptr=NULL; + } + a->init=0; + } + return(1); + } + +static int MS_CALLBACK file_read(BIO *b, char *out, int outl) + { + int ret=0; + + if (b->init && (out != NULL)) + { + ret=fread(out,1,(int)outl,(FILE *)b->ptr); + } + return(ret); + } + +static int MS_CALLBACK file_write(BIO *b, char *in, int inl) + { + int ret=0; + + if (b->init && (in != NULL)) + { + if (fwrite(in,(int)inl,1,(FILE *)b->ptr)) + ret=inl; + /* ret=fwrite(in,1,(int)inl,(FILE *)b->ptr); */ + /* according to Tim Hudson , the commented + * out version above can cause 'inl' write calls under + * some stupid stdio implementations (VMS) */ + } + return(ret); + } + +static long MS_CALLBACK file_ctrl(BIO *b, int cmd, long num, char *ptr) + { + long ret=1; + FILE *fp=(FILE *)b->ptr; + FILE **fpp; + char p[4]; + + switch (cmd) + { + case BIO_C_FILE_SEEK: + case BIO_CTRL_RESET: + ret=(long)fseek(fp,num,0); + break; + case BIO_CTRL_EOF: + ret=(long)feof(fp); + break; + case BIO_C_FILE_TELL: + case BIO_CTRL_INFO: + ret=ftell(fp); + break; + case BIO_C_SET_FILE_PTR: + file_free(b); + b->shutdown=(int)num&BIO_CLOSE; + b->ptr=(char *)ptr; + b->init=1; +#if defined(MSDOS) || defined(WINDOWS) + /* Set correct text/binary mode */ + if (num & BIO_FP_TEXT) + _setmode(fileno((FILE *)ptr),_O_TEXT); + else + _setmode(fileno((FILE *)ptr),_O_BINARY); +#endif + break; + case BIO_C_SET_FILENAME: + file_free(b); + b->shutdown=(int)num&BIO_CLOSE; + if (num & BIO_FP_APPEND) + { + if (num & BIO_FP_READ) + strcpy(p,"a+"); + else strcpy(p,"a"); + } + else if ((num & BIO_FP_READ) && (num & BIO_FP_WRITE)) + strcpy(p,"r+"); + else if (num & BIO_FP_WRITE) + strcpy(p,"w"); + else if (num & BIO_FP_READ) + strcpy(p,"r"); + else + { + BIOerr(BIO_F_FILE_CTRL,BIO_R_BAD_FOPEN_MODE); + ret=0; + break; + } +#if defined(MSDOS) || defined(WINDOWS) + if (!(num & BIO_FP_TEXT)) + strcat(p,"b"); + else + strcat(p,"t"); +#endif + fp=fopen(ptr,p); + if (fp == NULL) + { + SYSerr(SYS_F_FOPEN,get_last_sys_error()); + ERR_add_error_data(5,"fopen('",ptr,"','",p,"')"); + BIOerr(BIO_F_FILE_CTRL,ERR_R_SYS_LIB); + ret=0; + break; + } + b->ptr=(char *)fp; + b->init=1; + break; + case BIO_C_GET_FILE_PTR: + /* the ptr parameter is actually a FILE ** in this case. */ + if (ptr != NULL) + { + fpp=(FILE **)ptr; + *fpp=(FILE *)b->ptr; + } + break; + case BIO_CTRL_GET_CLOSE: + ret=(long)b->shutdown; + break; + case BIO_CTRL_SET_CLOSE: + b->shutdown=(int)num; + break; + case BIO_CTRL_FLUSH: + fflush((FILE *)b->ptr); + break; + case BIO_CTRL_DUP: + ret=1; + break; + + case BIO_CTRL_WPENDING: + case BIO_CTRL_PENDING: + case BIO_CTRL_PUSH: + case BIO_CTRL_POP: + default: + ret=0; + break; + } + return(ret); + } + +static int MS_CALLBACK file_gets(BIO *bp, char *buf, int size) + { + int ret=0; + + buf[0]='\0'; + fgets(buf,size,(FILE *)bp->ptr); + if (buf[0] != '\0') + ret=strlen(buf); + return(ret); + } + +static int MS_CALLBACK file_puts(BIO *bp, char *str) + { + int n,ret; + + n=strlen(str); + ret=file_write(bp,str,n); + return(ret); + } + +#endif /* NO_STDIO */ + +#endif /* HEADER_BSS_FILE_C */ + + diff --git a/libsecurity_apple_csp/open_ssl/bn/bn_add.c b/libsecurity_apple_csp/open_ssl/bn/bn_add.c new file mode 100644 index 00000000..3abd7499 --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/bn/bn_add.c @@ -0,0 +1,325 @@ +/* + * 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. + */ + + +/* crypto/bn/bn_add.c */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include +#include "cryptlib.h" +#include "bn_lcl.h" + +/* r can == a or b */ +int BN_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b) + { + const BIGNUM *tmp; + + bn_check_top(a); + bn_check_top(b); + + /* a + b a+b + * a + -b a-b + * -a + b b-a + * -a + -b -(a+b) + */ + if (a->neg ^ b->neg) + { + /* only one is negative */ + if (a->neg) + { tmp=a; a=b; b=tmp; } + + /* we are now a - b */ + + if (BN_ucmp(a,b) < 0) + { + if (!BN_usub(r,b,a)) return(0); + r->neg=1; + } + else + { + if (!BN_usub(r,a,b)) return(0); + r->neg=0; + } + return(1); + } + + if (a->neg) /* both are neg */ + r->neg=1; + else + r->neg=0; + + if (!BN_uadd(r,a,b)) return(0); + return(1); + } + +/* unsigned add of b to a, r must be large enough */ +int BN_uadd(BIGNUM *r, const BIGNUM *a, const BIGNUM *b) + { + register int i; + int max,min; + BN_ULONG *ap,*bp,*rp,carry,t1; + const BIGNUM *tmp; + + bn_check_top(a); + bn_check_top(b); + + if (a->top < b->top) + { tmp=a; a=b; b=tmp; } + max=a->top; + min=b->top; + + if (bn_wexpand(r,max+1) == NULL) + return(0); + + r->top=max; + + + ap=a->d; + bp=b->d; + rp=r->d; + carry=0; + + carry=bn_add_words(rp,ap,bp,min); + rp+=min; + ap+=min; + bp+=min; + i=min; + + if (carry) + { + while (i < max) + { + i++; + t1= *(ap++); + if ((*(rp++)=(t1+1)&BN_MASK2) >= t1) + { + carry=0; + break; + } + } + if ((i >= max) && carry) + { + *(rp++)=1; + r->top++; + } + } + if (rp != ap) + { + for (; itop < b->top) /* hmm... should not be happening */ + { + BNerr(BN_F_BN_USUB,BN_R_ARG2_LT_ARG3); + return(0); + } + + max=a->top; + min=b->top; + if (bn_wexpand(r,max) == NULL) return(0); + + ap=a->d; + bp=b->d; + rp=r->d; + +#if 1 + carry=0; + for (i=0; i t2) break; + } + } +#if 0 + memcpy(rp,ap,sizeof(*rp)*(max-i)); +#else + if (rp != ap) + { + for (;;) + { + if (i++ >= max) break; + rp[0]=ap[0]; + if (i++ >= max) break; + rp[1]=ap[1]; + if (i++ >= max) break; + rp[2]=ap[2]; + if (i++ >= max) break; + rp[3]=ap[3]; + rp+=4; + ap+=4; + } + } +#endif + + r->top=max; + bn_fix_top(r); + return(1); + } + +int BN_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b) + { + int max; + int add=0,neg=0; + const BIGNUM *tmp; + + bn_check_top(a); + bn_check_top(b); + + /* a - b a-b + * a - -b a+b + * -a - b -(a+b) + * -a - -b b-a + */ + if (a->neg) + { + if (b->neg) + { tmp=a; a=b; b=tmp; } + else + { add=1; neg=1; } + } + else + { + if (b->neg) { add=1; neg=0; } + } + + if (add) + { + if (!BN_uadd(r,a,b)) return(0); + r->neg=neg; + return(1); + } + + /* We are actually doing a - b :-) */ + + max=(a->top > b->top)?a->top:b->top; + if (bn_wexpand(r,max) == NULL) return(0); + if (BN_ucmp(a,b) < 0) + { + if (!BN_usub(r,b,a)) return(0); + r->neg=1; + } + else + { + if (!BN_usub(r,a,b)) return(0); + r->neg=0; + } + return(1); + } + diff --git a/libsecurity_apple_csp/open_ssl/bn/bn_asm.c b/libsecurity_apple_csp/open_ssl/bn/bn_asm.c new file mode 100644 index 00000000..d5c137f3 --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/bn/bn_asm.c @@ -0,0 +1,855 @@ +/* + * 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. + */ + + +/* crypto/bn/bn_asm.c */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef BN_DEBUG +# undef NDEBUG /* avoid conflicting definitions */ +# define NDEBUG +#endif + +#include +#include +#include "cryptlib.h" +#include "bn_lcl.h" + +#if defined(BN_LLONG) || defined(BN_UMULT_HIGH) + +BN_ULONG bn_mul_add_words(BN_ULONG *rp, BN_ULONG *ap, int num, BN_ULONG w) + { + BN_ULONG c1=0; + + assert(num >= 0); + if (num <= 0) return(c1); + + while (num&~3) + { + mul_add(rp[0],ap[0],w,c1); + mul_add(rp[1],ap[1],w,c1); + mul_add(rp[2],ap[2],w,c1); + mul_add(rp[3],ap[3],w,c1); + ap+=4; rp+=4; num-=4; + } + if (num) + { + mul_add(rp[0],ap[0],w,c1); if (--num==0) return c1; + mul_add(rp[1],ap[1],w,c1); if (--num==0) return c1; + mul_add(rp[2],ap[2],w,c1); return c1; + } + + return(c1); + } + +BN_ULONG bn_mul_words(BN_ULONG *rp, BN_ULONG *ap, int num, BN_ULONG w) + { + BN_ULONG c1=0; + + assert(num >= 0); + if (num <= 0) return(c1); + + while (num&~3) + { + mul(rp[0],ap[0],w,c1); + mul(rp[1],ap[1],w,c1); + mul(rp[2],ap[2],w,c1); + mul(rp[3],ap[3],w,c1); + ap+=4; rp+=4; num-=4; + } + if (num) + { + mul(rp[0],ap[0],w,c1); if (--num == 0) return c1; + mul(rp[1],ap[1],w,c1); if (--num == 0) return c1; + mul(rp[2],ap[2],w,c1); + } + return(c1); + } + +void bn_sqr_words(BN_ULONG *r, BN_ULONG *a, int n) + { + assert(n >= 0); + if (n <= 0) return; + while (n&~3) + { + sqr(r[0],r[1],a[0]); + sqr(r[2],r[3],a[1]); + sqr(r[4],r[5],a[2]); + sqr(r[6],r[7],a[3]); + a+=4; r+=8; n-=4; + } + if (n) + { + sqr(r[0],r[1],a[0]); if (--n == 0) return; + sqr(r[2],r[3],a[1]); if (--n == 0) return; + sqr(r[4],r[5],a[2]); + } + } + +#else /* !(defined(BN_LLONG) || defined(BN_UMULT_HIGH)) */ + +BN_ULONG bn_mul_add_words(BN_ULONG *rp, BN_ULONG *ap, int num, BN_ULONG w) + { + BN_ULONG c=0; + BN_ULONG bl,bh; + + assert(num >= 0); + if (num <= 0) return((BN_ULONG)0); + + bl=LBITS(w); + bh=HBITS(w); + + for (;;) + { + mul_add(rp[0],ap[0],bl,bh,c); + if (--num == 0) break; + mul_add(rp[1],ap[1],bl,bh,c); + if (--num == 0) break; + mul_add(rp[2],ap[2],bl,bh,c); + if (--num == 0) break; + mul_add(rp[3],ap[3],bl,bh,c); + if (--num == 0) break; + ap+=4; + rp+=4; + } + return(c); + } + +BN_ULONG bn_mul_words(BN_ULONG *rp, BN_ULONG *ap, int num, BN_ULONG w) + { + BN_ULONG carry=0; + BN_ULONG bl,bh; + + assert(num >= 0); + if (num <= 0) return((BN_ULONG)0); + + bl=LBITS(w); + bh=HBITS(w); + + for (;;) + { + mul(rp[0],ap[0],bl,bh,carry); + if (--num == 0) break; + mul(rp[1],ap[1],bl,bh,carry); + if (--num == 0) break; + mul(rp[2],ap[2],bl,bh,carry); + if (--num == 0) break; + mul(rp[3],ap[3],bl,bh,carry); + if (--num == 0) break; + ap+=4; + rp+=4; + } + return(carry); + } + +void bn_sqr_words(BN_ULONG *r, BN_ULONG *a, int n) + { + assert(n >= 0); + if (n <= 0) return; + for (;;) + { + sqr64(r[0],r[1],a[0]); + if (--n == 0) break; + + sqr64(r[2],r[3],a[1]); + if (--n == 0) break; + + sqr64(r[4],r[5],a[2]); + if (--n == 0) break; + + sqr64(r[6],r[7],a[3]); + if (--n == 0) break; + + a+=4; + r+=8; + } + } + +#endif /* !(defined(BN_LLONG) || defined(BN_UMULT_HIGH)) */ + +#if defined(BN_LLONG) && defined(BN_DIV2W) + +BN_ULONG bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d) + { + return((BN_ULONG)(((((BN_ULLONG)h)< (BN_ULONG)1<= d) h-=d; + + if (i) + { + d<<=i; + h=(h<>(BN_BITS2-i)); + l<<=i; + } + dh=(d&BN_MASK2h)>>BN_BITS4; + dl=(d&BN_MASK2l); + for (;;) + { + if ((h>>BN_BITS4) == dh) + q=BN_MASK2l; + else + q=h/dh; + + th=q*dh; + tl=dl*q; + for (;;) + { + t=h-th; + if ((t&BN_MASK2h) || + ((tl) <= ( + (t<>BN_BITS4)))) + break; + q--; + th-=dh; + tl-=dl; + } + t=(tl>>BN_BITS4); + tl=(tl<>BN_BITS4))&BN_MASK2; + l=(l&BN_MASK2l)<= 0); + if (n <= 0) return((BN_ULONG)0); + + for (;;) + { + ll+=(BN_ULLONG)a[0]+b[0]; + r[0]=(BN_ULONG)ll&BN_MASK2; + ll>>=BN_BITS2; + if (--n <= 0) break; + + ll+=(BN_ULLONG)a[1]+b[1]; + r[1]=(BN_ULONG)ll&BN_MASK2; + ll>>=BN_BITS2; + if (--n <= 0) break; + + ll+=(BN_ULLONG)a[2]+b[2]; + r[2]=(BN_ULONG)ll&BN_MASK2; + ll>>=BN_BITS2; + if (--n <= 0) break; + + ll+=(BN_ULLONG)a[3]+b[3]; + r[3]=(BN_ULONG)ll&BN_MASK2; + ll>>=BN_BITS2; + if (--n <= 0) break; + + a+=4; + b+=4; + r+=4; + } + return((BN_ULONG)ll); + } +#else /* !BN_LLONG */ +BN_ULONG bn_add_words(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n) + { + BN_ULONG c,l,t; + + assert(n >= 0); + if (n <= 0) return((BN_ULONG)0); + + c=0; + for (;;) + { + t=a[0]; + t=(t+c)&BN_MASK2; + c=(t < c); + l=(t+b[0])&BN_MASK2; + c+=(l < t); + r[0]=l; + if (--n <= 0) break; + + t=a[1]; + t=(t+c)&BN_MASK2; + c=(t < c); + l=(t+b[1])&BN_MASK2; + c+=(l < t); + r[1]=l; + if (--n <= 0) break; + + t=a[2]; + t=(t+c)&BN_MASK2; + c=(t < c); + l=(t+b[2])&BN_MASK2; + c+=(l < t); + r[2]=l; + if (--n <= 0) break; + + t=a[3]; + t=(t+c)&BN_MASK2; + c=(t < c); + l=(t+b[3])&BN_MASK2; + c+=(l < t); + r[3]=l; + if (--n <= 0) break; + + a+=4; + b+=4; + r+=4; + } + return((BN_ULONG)c); + } +#endif /* !BN_LLONG */ + +BN_ULONG bn_sub_words(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n) + { + BN_ULONG t1,t2; + int c=0; + + assert(n >= 0); + if (n <= 0) return((BN_ULONG)0); + + for (;;) + { + t1=a[0]; t2=b[0]; + r[0]=(t1-t2-c)&BN_MASK2; + if (t1 != t2) c=(t1 < t2); + if (--n <= 0) break; + + t1=a[1]; t2=b[1]; + r[1]=(t1-t2-c)&BN_MASK2; + if (t1 != t2) c=(t1 < t2); + if (--n <= 0) break; + + t1=a[2]; t2=b[2]; + r[2]=(t1-t2-c)&BN_MASK2; + if (t1 != t2) c=(t1 < t2); + if (--n <= 0) break; + + t1=a[3]; t2=b[3]; + r[3]=(t1-t2-c)&BN_MASK2; + if (t1 != t2) c=(t1 < t2); + if (--n <= 0) break; + + a+=4; + b+=4; + r+=4; + } + return(c); + } + +#ifdef BN_MUL_COMBA + +#undef bn_mul_comba8 +#undef bn_mul_comba4 +#undef bn_sqr_comba8 +#undef bn_sqr_comba4 + +/* mul_add_c(a,b,c0,c1,c2) -- c+=a*b for three word number c=(c2,c1,c0) */ +/* mul_add_c2(a,b,c0,c1,c2) -- c+=2*a*b for three word number c=(c2,c1,c0) */ +/* sqr_add_c(a,i,c0,c1,c2) -- c+=a[i]^2 for three word number c=(c2,c1,c0) */ +/* sqr_add_c2(a,i,c0,c1,c2) -- c+=2*a[i]*a[j] for three word number c=(c2,c1,c0) */ + +#ifdef BN_LLONG +#define mul_add_c(a,b,c0,c1,c2) \ + t=(BN_ULLONG)a*b; \ + t1=(BN_ULONG)Lw(t); \ + t2=(BN_ULONG)Hw(t); \ + c0=(c0+t1)&BN_MASK2; if ((c0) < t1) t2++; \ + c1=(c1+t2)&BN_MASK2; if ((c1) < t2) c2++; + +#define mul_add_c2(a,b,c0,c1,c2) \ + t=(BN_ULLONG)a*b; \ + tt=(t+t)&BN_MASK; \ + if (tt < t) c2++; \ + t1=(BN_ULONG)Lw(tt); \ + t2=(BN_ULONG)Hw(tt); \ + c0=(c0+t1)&BN_MASK2; \ + if ((c0 < t1) && (((++t2)&BN_MASK2) == 0)) c2++; \ + c1=(c1+t2)&BN_MASK2; if ((c1) < t2) c2++; + +#define sqr_add_c(a,i,c0,c1,c2) \ + t=(BN_ULLONG)a[i]*a[i]; \ + t1=(BN_ULONG)Lw(t); \ + t2=(BN_ULONG)Hw(t); \ + c0=(c0+t1)&BN_MASK2; if ((c0) < t1) t2++; \ + c1=(c1+t2)&BN_MASK2; if ((c1) < t2) c2++; + +#define sqr_add_c2(a,i,j,c0,c1,c2) \ + mul_add_c2((a)[i],(a)[j],c0,c1,c2) + +#elif defined(BN_UMULT_HIGH) + +#define mul_add_c(a,b,c0,c1,c2) { \ + BN_ULONG ta=(a),tb=(b); \ + t1 = ta * tb; \ + t2 = BN_UMULT_HIGH(ta,tb); \ + c0 += t1; t2 += (c0 +#include "cryptlib.h" +#include "bn_lcl.h" + +BN_BLINDING *BN_BLINDING_new(BIGNUM *A, BIGNUM *Ai, BIGNUM *mod) + { + BN_BLINDING *ret=NULL; + + bn_check_top(Ai); + bn_check_top(mod); + + if ((ret=(BN_BLINDING *)Malloc(sizeof(BN_BLINDING))) == NULL) + { + BNerr(BN_F_BN_BLINDING_NEW,ERR_R_MALLOC_FAILURE); + return(NULL); + } + memset(ret,0,sizeof(BN_BLINDING)); + if ((ret->A=BN_new()) == NULL) goto err; + if ((ret->Ai=BN_new()) == NULL) goto err; + if (!BN_copy(ret->A,A)) goto err; + if (!BN_copy(ret->Ai,Ai)) goto err; + ret->mod=mod; + return(ret); +err: + if (ret != NULL) BN_BLINDING_free(ret); + return(NULL); + } + +void BN_BLINDING_free(BN_BLINDING *r) + { + if(r == NULL) + return; + + if (r->A != NULL) BN_free(r->A ); + if (r->Ai != NULL) BN_free(r->Ai); + Free(r); + } + +int BN_BLINDING_update(BN_BLINDING *b, BN_CTX *ctx) + { + int ret=0; + + if ((b->A == NULL) || (b->Ai == NULL)) + { + BNerr(BN_F_BN_BLINDING_UPDATE,BN_R_NOT_INITIALIZED); + goto err; + } + + if (!BN_mod_mul(b->A,b->A,b->A,b->mod,ctx)) goto err; + if (!BN_mod_mul(b->Ai,b->Ai,b->Ai,b->mod,ctx)) goto err; + + ret=1; +err: + return(ret); + } + +int BN_BLINDING_convert(BIGNUM *n, BN_BLINDING *b, BN_CTX *ctx) + { + bn_check_top(n); + + if ((b->A == NULL) || (b->Ai == NULL)) + { + BNerr(BN_F_BN_BLINDING_CONVERT,BN_R_NOT_INITIALIZED); + return(0); + } + return(BN_mod_mul(n,n,b->A,b->mod,ctx)); + } + +int BN_BLINDING_invert(BIGNUM *n, BN_BLINDING *b, BN_CTX *ctx) + { + int ret; + + bn_check_top(n); + if ((b->A == NULL) || (b->Ai == NULL)) + { + BNerr(BN_F_BN_BLINDING_INVERT,BN_R_NOT_INITIALIZED); + return(0); + } + if ((ret=BN_mod_mul(n,n,b->Ai,b->mod,ctx)) >= 0) + { + if (!BN_BLINDING_update(b,ctx)) + return(0); + } + return(ret); + } + diff --git a/libsecurity_apple_csp/open_ssl/bn/bn_ctx.c b/libsecurity_apple_csp/open_ssl/bn/bn_ctx.c new file mode 100644 index 00000000..bcb922cb --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/bn/bn_ctx.c @@ -0,0 +1,162 @@ +/* + * 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. + */ + + +/* crypto/bn/bn_ctx.c */ +/* Written by Ulf Moeller for the OpenSSL project. */ +/* ==================================================================== + * Copyright (c) 1998-2000 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#ifndef BN_CTX_DEBUG +# undef NDEBUG /* avoid conflicting definitions */ +# define NDEBUG +#endif + +#include +#include +#include "cryptlib.h" +#include + + +BN_CTX *BN_CTX_new(void) + { + BN_CTX *ret; + + ret=(BN_CTX *)Malloc(sizeof(BN_CTX)); + if (ret == NULL) + { + BNerr(BN_F_BN_CTX_NEW,ERR_R_MALLOC_FAILURE); + return(NULL); + } + + BN_CTX_init(ret); + ret->flags=BN_FLG_MALLOCED; + return(ret); + } + +void BN_CTX_init(BN_CTX *ctx) + { + int i; + ctx->tos = 0; + ctx->flags = 0; + ctx->depth = 0; + ctx->too_many = 0; + for (i = 0; i < BN_CTX_NUM; i++) + BN_init(&(ctx->bn[i])); + } + +void BN_CTX_free(BN_CTX *ctx) + { + int i; + + if (ctx == NULL) return; + assert(ctx->depth == 0); + + for (i=0; i < BN_CTX_NUM; i++) + BN_clear_free(&(ctx->bn[i])); + if (ctx->flags & BN_FLG_MALLOCED) + Free(ctx); + } + +void BN_CTX_start(BN_CTX *ctx) + { + if (ctx->depth < BN_CTX_NUM_POS) + ctx->pos[ctx->depth] = ctx->tos; + ctx->depth++; + } + +BIGNUM *BN_CTX_get(BN_CTX *ctx) + { + if (ctx->depth > BN_CTX_NUM_POS || ctx->tos >= BN_CTX_NUM) + { + if (!ctx->too_many) + { + BNerr(BN_F_BN_CTX_GET,BN_R_TOO_MANY_TEMPORARY_VARIABLES); + /* disable error code until BN_CTX_end is called: */ + ctx->too_many = 1; + } + return NULL; + } + return (&(ctx->bn[ctx->tos++])); + } + +void BN_CTX_end(BN_CTX *ctx) + { + if (ctx == NULL) return; + assert(ctx->depth > 0); + if (ctx->depth == 0) + /* should never happen, but we can tolerate it if not in + * debug mode (could be a 'goto err' in the calling function + * before BN_CTX_start was reached) */ + BN_CTX_start(ctx); + + ctx->too_many = 0; + ctx->depth--; + if (ctx->depth < BN_CTX_NUM_POS) + ctx->tos = ctx->pos[ctx->depth]; + } diff --git a/libsecurity_apple_csp/open_ssl/bn/bn_div.c b/libsecurity_apple_csp/open_ssl/bn/bn_div.c new file mode 100644 index 00000000..a85fb3a4 --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/bn/bn_div.c @@ -0,0 +1,398 @@ +/* + * 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. + */ + + +/* crypto/bn/bn_div.c */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include +#include +#include "cryptlib.h" +#include "bn_lcl.h" + +/* The old slow way */ +#if 0 +int BN_div(BIGNUM *dv, BIGNUM *rem, const BIGNUM *m, const BIGNUM *d, + BN_CTX *ctx) + { + int i,nm,nd; + int ret = 0; + BIGNUM *D; + + bn_check_top(m); + bn_check_top(d); + if (BN_is_zero(d)) + { + BNerr(BN_F_BN_DIV,BN_R_DIV_BY_ZERO); + return(0); + } + + if (BN_ucmp(m,d) < 0) + { + if (rem != NULL) + { if (BN_copy(rem,m) == NULL) return(0); } + if (dv != NULL) BN_zero(dv); + return(1); + } + + BN_CTX_start(ctx); + D = BN_CTX_get(ctx); + if (dv == NULL) dv = BN_CTX_get(ctx); + if (rem == NULL) rem = BN_CTX_get(ctx); + if (D == NULL || dv == NULL || rem == NULL) + goto end; + + nd=BN_num_bits(d); + nm=BN_num_bits(m); + if (BN_copy(D,d) == NULL) goto end; + if (BN_copy(rem,m) == NULL) goto end; + + /* The next 2 are needed so we can do a dv->d[0]|=1 later + * since BN_lshift1 will only work once there is a value :-) */ + BN_zero(dv); + bn_wexpand(dv,1); + dv->top=1; + + if (!BN_lshift(D,D,nm-nd)) goto end; + for (i=nm-nd; i>=0; i--) + { + if (!BN_lshift1(dv,dv)) goto end; + if (BN_ucmp(rem,D) >= 0) + { + dv->d[0]|=1; + if (!BN_usub(rem,rem,D)) goto end; + } +/* CAN IMPROVE (and have now :=) */ + if (!BN_rshift1(D,D)) goto end; + } + rem->neg=BN_is_zero(rem)?0:m->neg; + dv->neg=m->neg^d->neg; + ret = 1; + end: + BN_CTX_end(ctx); + return(ret); + } + +#else + +#if !defined(NO_ASM) && !defined(NO_INLINE_ASM) && !defined(PEDANTIC) && !defined(BN_DIV3W) +# if defined(__GNUC__) && __GNUC__>=2 +# if defined(__i386) + /* + * There were two reasons for implementing this template: + * - GNU C generates a call to a function (__udivdi3 to be exact) + * in reply to ((((BN_ULLONG)n0)< + */ +# define bn_div_words(n0,n1,d0) \ + ({ asm volatile ( \ + "divl %4" \ + : "=a"(q), "=d"(rem) \ + : "a"(n1), "d"(n0), "g"(d0) \ + : "cc"); \ + q; \ + }) +# define REMAINDER_IS_ALREADY_CALCULATED +# endif /* __ */ +# endif /* __GNUC__ */ +#endif /* NO_ASM */ + +int BN_div(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num, const BIGNUM *divisor, + BN_CTX *ctx) + { + int norm_shift,i,j,loop; + BIGNUM *tmp,wnum,*snum,*sdiv,*res; + BN_ULONG *resp,*wnump; + BN_ULONG d0,d1; + int num_n,div_n; + + bn_check_top(num); + bn_check_top(divisor); + + if (BN_is_zero(divisor)) + { + BNerr(BN_F_BN_DIV,BN_R_DIV_BY_ZERO); + return(0); + } + + if (BN_ucmp(num,divisor) < 0) + { + if (rm != NULL) + { if (BN_copy(rm,num) == NULL) return(0); } + if (dv != NULL) BN_zero(dv); + return(1); + } + + BN_CTX_start(ctx); + tmp=BN_CTX_get(ctx); + tmp->neg=0; + snum=BN_CTX_get(ctx); + sdiv=BN_CTX_get(ctx); + if (dv == NULL) + res=BN_CTX_get(ctx); + else res=dv; + if (res == NULL) goto err; + + /* First we normalise the numbers */ + norm_shift=BN_BITS2-((BN_num_bits(divisor))%BN_BITS2); + BN_lshift(sdiv,divisor,norm_shift); + sdiv->neg=0; + norm_shift+=BN_BITS2; + BN_lshift(snum,num,norm_shift); + snum->neg=0; + div_n=sdiv->top; + num_n=snum->top; + loop=num_n-div_n; + + /* Lets setup a 'window' into snum + * This is the part that corresponds to the current + * 'area' being divided */ + BN_init(&wnum); + wnum.d= &(snum->d[loop]); + wnum.top= div_n; + wnum.max= snum->max+1; /* a bit of a lie */ + + /* Get the top 2 words of sdiv */ + /* i=sdiv->top; */ + d0=sdiv->d[div_n-1]; + d1=(div_n == 1)?0:sdiv->d[div_n-2]; + + /* pointer to the 'top' of snum */ + wnump= &(snum->d[num_n-1]); + + /* Setup to 'res' */ + res->neg= (num->neg^divisor->neg); + if (!bn_wexpand(res,(loop+1))) goto err; + res->top=loop; + resp= &(res->d[loop-1]); + + /* space for temp */ + if (!bn_wexpand(tmp,(div_n+1))) goto err; + + if (BN_ucmp(&wnum,sdiv) >= 0) + { + if (!BN_usub(&wnum,&wnum,sdiv)) goto err; + *resp=1; + res->d[res->top-1]=1; + } + else + res->top--; + resp--; + + for (i=0; id,sdiv->d,div_n,q); + wnum.d--; wnum.top++; + tmp->d[div_n]=l0; + for (j=div_n+1; j>0; j--) + if (tmp->d[j-1]) break; + tmp->top=j; + + j=wnum.top; + BN_sub(&wnum,&wnum,tmp); + + snum->top=snum->top+wnum.top-j; + + if (wnum.neg) + { + q--; + j=wnum.top; + BN_add(&wnum,&wnum,sdiv); + snum->top+=wnum.top-j; + } + *(resp--)=q; + wnump--; + } + if (rm != NULL) + { + BN_rshift(rm,snum,norm_shift); + rm->neg=num->neg; + } + BN_CTX_end(ctx); + return(1); +err: + BN_CTX_end(ctx); + return(0); + } + +#endif + +/* rem != m */ +int BN_mod(BIGNUM *rem, const BIGNUM *m, const BIGNUM *d, BN_CTX *ctx) + { +#if 0 /* The old slow way */ + int i,nm,nd; + BIGNUM *dv; + + if (BN_ucmp(m,d) < 0) + return((BN_copy(rem,m) == NULL)?0:1); + + BN_CTX_start(ctx); + dv=BN_CTX_get(ctx); + + if (!BN_copy(rem,m)) goto err; + + nm=BN_num_bits(rem); + nd=BN_num_bits(d); + if (!BN_lshift(dv,d,nm-nd)) goto err; + for (i=nm-nd; i>=0; i--) + { + if (BN_cmp(rem,dv) >= 0) + { + if (!BN_sub(rem,rem,dv)) goto err; + } + if (!BN_rshift1(dv,dv)) goto err; + } + BN_CTX_end(ctx); + return(1); + err: + BN_CTX_end(ctx); + return(0); +#else + return(BN_div(NULL,rem,m,d,ctx)); +#endif + } + diff --git a/libsecurity_apple_csp/open_ssl/bn/bn_err.c b/libsecurity_apple_csp/open_ssl/bn/bn_err.c new file mode 100644 index 00000000..d706e586 --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/bn/bn_err.c @@ -0,0 +1,140 @@ +/* + * 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. + */ + + +/* crypto/bn/bn_err.c */ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +/* NOTE: this file was auto generated by the mkerr.pl script: any changes + * made to it will be overwritten when the script next updates this file, + * only reason strings will be preserved. + */ + +#include +#include +#include + +/* BEGIN ERROR CODES */ +#ifndef NO_ERR +static ERR_STRING_DATA BN_str_functs[]= + { +{ERR_PACK(0,BN_F_BN_BLINDING_CONVERT,0), "BN_BLINDING_convert"}, +{ERR_PACK(0,BN_F_BN_BLINDING_INVERT,0), "BN_BLINDING_invert"}, +{ERR_PACK(0,BN_F_BN_BLINDING_NEW,0), "BN_BLINDING_new"}, +{ERR_PACK(0,BN_F_BN_BLINDING_UPDATE,0), "BN_BLINDING_update"}, +{ERR_PACK(0,BN_F_BN_BN2DEC,0), "BN_bn2dec"}, +{ERR_PACK(0,BN_F_BN_BN2HEX,0), "BN_bn2hex"}, +{ERR_PACK(0,BN_F_BN_CTX_GET,0), "BN_CTX_get"}, +{ERR_PACK(0,BN_F_BN_CTX_NEW,0), "BN_CTX_new"}, +{ERR_PACK(0,BN_F_BN_DIV,0), "BN_div"}, +{ERR_PACK(0,BN_F_BN_EXPAND2,0), "bn_expand2"}, +{ERR_PACK(0,BN_F_BN_MOD_EXP_MONT,0), "BN_mod_exp_mont"}, +{ERR_PACK(0,BN_F_BN_MOD_EXP_MONT_WORD,0), "BN_mod_exp_mont_word"}, +{ERR_PACK(0,BN_F_BN_MOD_INVERSE,0), "BN_mod_inverse"}, +{ERR_PACK(0,BN_F_BN_MOD_MUL_RECIPROCAL,0), "BN_mod_mul_reciprocal"}, +{ERR_PACK(0,BN_F_BN_MPI2BN,0), "BN_mpi2bn"}, +{ERR_PACK(0,BN_F_BN_NEW,0), "BN_new"}, +{ERR_PACK(0,BN_F_BN_RAND,0), "BN_rand"}, +{ERR_PACK(0,BN_F_BN_RAND_RANGE,0), "BN_rand_range"}, +{ERR_PACK(0,BN_F_BN_USUB,0), "BN_usub"}, +{0,NULL} + }; + +static ERR_STRING_DATA BN_str_reasons[]= + { +{BN_R_ARG2_LT_ARG3 ,"arg2 lt arg3"}, +{BN_R_BAD_RECIPROCAL ,"bad reciprocal"}, +{BN_R_CALLED_WITH_EVEN_MODULUS ,"called with even modulus"}, +{BN_R_DIV_BY_ZERO ,"div by zero"}, +{BN_R_ENCODING_ERROR ,"encoding error"}, +{BN_R_EXPAND_ON_STATIC_BIGNUM_DATA ,"expand on static bignum data"}, +{BN_R_INVALID_LENGTH ,"invalid length"}, +{BN_R_INVALID_RANGE ,"invalid range"}, +{BN_R_NOT_INITIALIZED ,"not initialized"}, +{BN_R_NO_INVERSE ,"no inverse"}, +{BN_R_TOO_MANY_TEMPORARY_VARIABLES ,"too many temporary variables"}, +{0,NULL} + }; + +#endif + +void ERR_load_BN_strings(void) + { + static int init=1; + + if (init) + { + init=0; +#ifndef NO_ERR + ERR_load_strings(ERR_LIB_BN,BN_str_functs); + ERR_load_strings(ERR_LIB_BN,BN_str_reasons); +#endif + + } + } diff --git a/libsecurity_apple_csp/open_ssl/bn/bn_exp.c b/libsecurity_apple_csp/open_ssl/bn/bn_exp.c new file mode 100644 index 00000000..81173237 --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/bn/bn_exp.c @@ -0,0 +1,901 @@ +/* crypto/bn/bn_exp.c */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright (c) 1998-2000 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + + +#include +#include "cryptlib.h" +#include "bn_lcl.h" +#ifdef ATALLA +# include +# include +# include +# include +#endif + + +#define TABLE_SIZE 32 + +/* slow but works */ +int BN_mod_mul(BIGNUM *ret, BIGNUM *a, BIGNUM *b, const BIGNUM *m, BN_CTX *ctx) + { + BIGNUM *t; + int r=0; + + bn_check_top(a); + bn_check_top(b); + bn_check_top(m); + + BN_CTX_start(ctx); + if ((t = BN_CTX_get(ctx)) == NULL) goto err; + if (a == b) + { if (!BN_sqr(t,a,ctx)) goto err; } + else + { if (!BN_mul(t,a,b,ctx)) goto err; } + if (!BN_mod(ret,t,m,ctx)) goto err; + r=1; +err: + BN_CTX_end(ctx); + return(r); + } + + +/* this one works - simple but works */ +int BN_exp(BIGNUM *r, BIGNUM *a, BIGNUM *p, BN_CTX *ctx) + { + int i,bits,ret=0; + BIGNUM *v,*rr; + + BN_CTX_start(ctx); + if ((r == a) || (r == p)) + rr = BN_CTX_get(ctx); + else + rr = r; + if ((v = BN_CTX_get(ctx)) == NULL) goto err; + + if (BN_copy(v,a) == NULL) goto err; + bits=BN_num_bits(p); + + if (BN_is_odd(p)) + { if (BN_copy(rr,a) == NULL) goto err; } + else { if (!BN_one(rr)) goto err; } + + for (i=1; i= m. eay 07-May-97 */ +/* if ((m->d[m->top-1]&BN_TBIT) && BN_is_odd(m)) */ + + if (BN_is_odd(m)) + { + if (a->top == 1) + { + BN_ULONG A = a->d[0]; + ret=BN_mod_exp_mont_word(r,A,p,m,ctx,NULL); + } + else + ret=BN_mod_exp_mont(r,a,p,m,ctx,NULL); + } + else +#endif +#ifdef RECP_MUL_MOD + { ret=BN_mod_exp_recp(r,a,p,m,ctx); } +#else + { ret=BN_mod_exp_simple(r,a,p,m,ctx); } +#endif + +#ifdef ATALLA + tried_atalla=0; +#endif + + return(ret); + } + + +int BN_mod_exp_recp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx) + { + int i,j,bits,ret=0,wstart,wend,window,wvalue; + int start=1,ts=0; + BIGNUM *aa; + BIGNUM val[TABLE_SIZE]; + BN_RECP_CTX recp; + + bits=BN_num_bits(p); + + if (bits == 0) + { + BN_one(r); + return(1); + } + + BN_CTX_start(ctx); + if ((aa = BN_CTX_get(ctx)) == NULL) goto err; + + BN_RECP_CTX_init(&recp); + if (BN_RECP_CTX_set(&recp,m,ctx) <= 0) goto err; + + BN_init(&(val[0])); + ts=1; + + if (!BN_mod(&(val[0]),a,m,ctx)) goto err; /* 1 */ + + window = BN_window_bits_for_exponent_size(bits); + if (window > 1) + { + if (!BN_mod_mul_reciprocal(aa,&(val[0]),&(val[0]),&recp,ctx)) + goto err; /* 2 */ + j=1<<(window-1); + for (i=1; i>1]),&recp,ctx)) + goto err; + + /* move the 'window' down further */ + wstart-=wend+1; + wvalue=0; + start=0; + if (wstart < 0) break; + } + ret=1; +err: + BN_CTX_end(ctx); + for (i=0; id[0] & 1)) + { + BNerr(BN_F_BN_MOD_EXP_MONT,BN_R_CALLED_WITH_EVEN_MODULUS); + return(0); + } + bits=BN_num_bits(p); + if (bits == 0) + { + BN_one(rr); + return(1); + } + BN_CTX_start(ctx); + d = BN_CTX_get(ctx); + r = BN_CTX_get(ctx); + if (d == NULL || r == NULL) goto err; + + /* If this is not done, things will break in the montgomery + * part */ + + if (in_mont != NULL) + mont=in_mont; + else + { + if ((mont=BN_MONT_CTX_new()) == NULL) goto err; + if (!BN_MONT_CTX_set(mont,m,ctx)) goto err; + } + + BN_init(&val[0]); + ts=1; + if (BN_ucmp(a,m) >= 0) + { + if (!BN_mod(&(val[0]),a,m,ctx)) + goto err; + aa= &(val[0]); + } + else + aa=a; + if (!BN_to_montgomery(&(val[0]),aa,mont,ctx)) goto err; /* 1 */ + + window = BN_window_bits_for_exponent_size(bits); + if (window > 1) + { + if (!BN_mod_mul_montgomery(d,&(val[0]),&(val[0]),mont,ctx)) goto err; /* 2 */ + j=1<<(window-1); + for (i=1; i>1]),mont,ctx)) + goto err; + + /* move the 'window' down further */ + wstart-=wend+1; + wvalue=0; + start=0; + if (wstart < 0) break; + } + if (!BN_from_montgomery(rr,r,mont,ctx)) goto err; + ret=1; +err: + if ((in_mont == NULL) && (mont != NULL)) BN_MONT_CTX_free(mont); + BN_CTX_end(ctx); + for (i=0; id[0] & 1)) + { + BNerr(BN_F_BN_MOD_EXP_MONT_WORD,BN_R_CALLED_WITH_EVEN_MODULUS); + return(0); + } + bits = BN_num_bits(p); + if (bits == 0) + { + BN_one(rr); + return(1); + } + BN_CTX_start(ctx); + d = BN_CTX_get(ctx); + r = BN_CTX_get(ctx); + t = BN_CTX_get(ctx); + if (d == NULL || r == NULL || t == NULL) goto err; + +#ifdef ATALLA + if (!tried_atalla) + { + BN_set_word(t, a); + if (BN_mod_exp_atalla(rr, t, p, m)) + { + BN_CTX_end(ctx); + return 1; + } + } +/* If it fails, try the other methods */ +#endif + + if (in_mont != NULL) + mont=in_mont; + else + { + if ((mont = BN_MONT_CTX_new()) == NULL) goto err; + if (!BN_MONT_CTX_set(mont, m, ctx)) goto err; + } + + r_is_one = 1; /* except for Montgomery factor */ + + /* bits-1 >= 0 */ + + /* The result is accumulated in the product r*w. */ + w = a; /* bit 'bits-1' of 'p' is always set */ + for (b = bits-2; b >= 0; b--) + { + /* First, square r*w. */ + next_w = w*w; + if ((next_w/w) != w) /* overflow */ + { + if (r_is_one) + { + if (!BN_TO_MONTGOMERY_WORD(r, w, mont)) goto err; + r_is_one = 0; + } + else + { + if (!BN_MOD_MUL_WORD(r, w, m)) goto err; + } + next_w = 1; + } + w = next_w; + if (!r_is_one) + { + if (!BN_mod_mul_montgomery(r, r, r, mont, ctx)) goto err; + } + + /* Second, multiply r*w by 'a' if exponent bit is set. */ + if (BN_is_bit_set(p, b)) + { + next_w = w*a; + if ((next_w/a) != w) /* overflow */ + { + if (r_is_one) + { + if (!BN_TO_MONTGOMERY_WORD(r, w, mont)) goto err; + r_is_one = 0; + } + else + { + if (!BN_MOD_MUL_WORD(r, w, m)) goto err; + } + next_w = a; + } + w = next_w; + } + } + + /* Finally, set r:=r*w. */ + if (w != 1) + { + if (r_is_one) + { + if (!BN_TO_MONTGOMERY_WORD(r, w, mont)) goto err; + r_is_one = 0; + } + else + { + if (!BN_MOD_MUL_WORD(r, w, m)) goto err; + } + } + + if (r_is_one) /* can happen only if a == 1*/ + { + if (!BN_one(rr)) goto err; + } + else + { + if (!BN_from_montgomery(rr, r, mont, ctx)) goto err; + } + ret = 1; +err: + if ((in_mont == NULL) && (mont != NULL)) BN_MONT_CTX_free(mont); + BN_CTX_end(ctx); + return(ret); + } + + +/* The old fallback, simple version :-) */ +int BN_mod_exp_simple(BIGNUM *r, BIGNUM *a, BIGNUM *p, BIGNUM *m, + BN_CTX *ctx) + { + int i,j,bits,ret=0,wstart,wend,window,wvalue,ts=0; + int start=1; + BIGNUM *d; + BIGNUM val[TABLE_SIZE]; + + bits=BN_num_bits(p); + + if (bits == 0) + { + BN_one(r); + return(1); + } + + BN_CTX_start(ctx); + if ((d = BN_CTX_get(ctx)) == NULL) goto err; + + BN_init(&(val[0])); + ts=1; + if (!BN_mod(&(val[0]),a,m,ctx)) goto err; /* 1 */ + + window = BN_window_bits_for_exponent_size(bits); + if (window > 1) + { + if (!BN_mod_mul(d,&(val[0]),&(val[0]),m,ctx)) + goto err; /* 2 */ + j=1<<(window-1); + for (i=1; i>1]),m,ctx)) + goto err; + + /* move the 'window' down further */ + wstart-=wend+1; + wvalue=0; + start=0; + if (wstart < 0) break; + } + ret=1; +err: + BN_CTX_end(ctx); + for (i=0; i +#include "cryptlib.h" +#include "bn_lcl.h" + +/* I've done some timing with different table sizes. + * The main hassle is that even with bits set at 3, this requires + * 63 BIGNUMs to store the pre-calculated values. + * 512 1024 + * bits=1 75.4% 79.4% + * bits=2 61.2% 62.4% + * bits=3 61.3% 59.3% + * The lack of speed improvement is also a function of the pre-calculation + * which could be removed. + */ +#define EXP2_TABLE_BITS 2 /* 1 2 3 4 5 */ +#define EXP2_TABLE_SIZE 4 /* 2 4 8 16 32 */ + +int BN_mod_exp2_mont(BIGNUM *rr, BIGNUM *a1, BIGNUM *p1, BIGNUM *a2, + BIGNUM *p2, BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *in_mont) + { + int i,j,k,bits,bits1,bits2,ret=0,wstart,wend,window,xvalue,yvalue; + int start=1,ts=0,x,y; + BIGNUM *d,*aa1,*aa2,*r; + BIGNUM val[EXP2_TABLE_SIZE][EXP2_TABLE_SIZE]; + BN_MONT_CTX *mont=NULL; + + bn_check_top(a1); + bn_check_top(p1); + bn_check_top(a2); + bn_check_top(p2); + bn_check_top(m); + + if (!(m->d[0] & 1)) + { + BNerr(BN_F_BN_MOD_EXP_MONT,BN_R_CALLED_WITH_EVEN_MODULUS); + return(0); + } + bits1=BN_num_bits(p1); + bits2=BN_num_bits(p2); + if ((bits1 == 0) && (bits2 == 0)) + { + BN_one(rr); + return(1); + } + + BN_CTX_start(ctx); + d = BN_CTX_get(ctx); + r = BN_CTX_get(ctx); + if (d == NULL || r == NULL) goto err; + + bits=(bits1 > bits2)?bits1:bits2; + + /* If this is not done, things will break in the montgomery + * part */ + + if (in_mont != NULL) + mont=in_mont; + else + { + if ((mont=BN_MONT_CTX_new()) == NULL) goto err; + if (!BN_MONT_CTX_set(mont,m,ctx)) goto err; + } + + BN_init(&(val[0][0])); + BN_init(&(val[1][1])); + BN_init(&(val[0][1])); + BN_init(&(val[1][0])); + ts=1; + if (BN_ucmp(a1,m) >= 0) + { + BN_mod(&(val[1][0]),a1,m,ctx); + aa1= &(val[1][0]); + } + else + aa1=a1; + if (BN_ucmp(a2,m) >= 0) + { + BN_mod(&(val[0][1]),a2,m,ctx); + aa2= &(val[0][1]); + } + else + aa2=a2; + if (!BN_to_montgomery(&(val[1][0]),aa1,mont,ctx)) goto err; + if (!BN_to_montgomery(&(val[0][1]),aa2,mont,ctx)) goto err; + if (!BN_mod_mul_montgomery(&(val[1][1]), + &(val[1][0]),&(val[0][1]),mont,ctx)) + goto err; + +#if 0 + if (bits <= 20) /* This is probably 3 or 0x10001, so just do singles */ + window=1; + else if (bits > 250) + window=5; /* max size of window */ + else if (bits >= 120) + window=4; + else + window=3; +#else + window=EXP2_TABLE_BITS; +#endif + + k=1<= 2) + { + BN_init(&(val[x][0])); + BN_init(&(val[x][1])); + if (!BN_mod_mul_montgomery(&(val[x][0]), + &(val[1][0]),&(val[x-1][0]),mont,ctx)) goto err; + if (!BN_mod_mul_montgomery(&(val[x][1]), + &(val[1][0]),&(val[x-1][1]),mont,ctx)) goto err; + } + for (y=2; y +#include "cryptlib.h" +#include "bn_lcl.h" + +static BIGNUM *euclid(BIGNUM *a, BIGNUM *b); + +int BN_gcd(BIGNUM *r, BIGNUM *in_a, BIGNUM *in_b, BN_CTX *ctx) + { + BIGNUM *a,*b,*t; + int ret=0; + + bn_check_top(in_a); + bn_check_top(in_b); + + BN_CTX_start(ctx); + a = BN_CTX_get(ctx); + b = BN_CTX_get(ctx); + if (a == NULL || b == NULL) goto err; + + if (BN_copy(a,in_a) == NULL) goto err; + if (BN_copy(b,in_b) == NULL) goto err; + + if (BN_cmp(a,b) < 0) { t=a; a=b; b=t; } + t=euclid(a,b); + if (t == NULL) goto err; + + if (BN_copy(r,t) == NULL) goto err; + ret=1; +err: + BN_CTX_end(ctx); + return(ret); + } + +static BIGNUM *euclid(BIGNUM *a, BIGNUM *b) + { + BIGNUM *t; + int shifts=0; + + bn_check_top(a); + bn_check_top(b); + + for (;;) + { + if (BN_is_zero(b)) + break; + + if (BN_is_odd(a)) + { + if (BN_is_odd(b)) + { + if (!BN_sub(a,a,b)) goto err; + if (!BN_rshift1(a,a)) goto err; + if (BN_cmp(a,b) < 0) + { t=a; a=b; b=t; } + } + else /* a odd - b even */ + { + if (!BN_rshift1(b,b)) goto err; + if (BN_cmp(a,b) < 0) + { t=a; a=b; b=t; } + } + } + else /* a is even */ + { + if (BN_is_odd(b)) + { + if (!BN_rshift1(a,a)) goto err; + if (BN_cmp(a,b) < 0) + { t=a; a=b; b=t; } + } + else /* a even - b even */ + { + if (!BN_rshift1(a,a)) goto err; + if (!BN_rshift1(b,b)) goto err; + shifts++; + } + } + } + if (shifts) + { + if (!BN_lshift(a,a,shifts)) goto err; + } + return(a); +err: + return(NULL); + } + +/* solves ax == 1 (mod n) */ +BIGNUM *BN_mod_inverse(BIGNUM *in, BIGNUM *a, const BIGNUM *n, BN_CTX *ctx) + { + BIGNUM *A,*B,*X,*Y,*M,*D,*R=NULL; + BIGNUM *T,*ret=NULL; + int sign; + + bn_check_top(a); + bn_check_top(n); + + BN_CTX_start(ctx); + A = BN_CTX_get(ctx); + B = BN_CTX_get(ctx); + X = BN_CTX_get(ctx); + D = BN_CTX_get(ctx); + M = BN_CTX_get(ctx); + Y = BN_CTX_get(ctx); + if (Y == NULL) goto err; + + if (in == NULL) + R=BN_new(); + else + R=in; + if (R == NULL) goto err; + + BN_zero(X); + BN_one(Y); + if (BN_copy(A,a) == NULL) goto err; + if (BN_copy(B,n) == NULL) goto err; + sign=1; + + while (!BN_is_zero(B)) + { + if (!BN_div(D,M,A,B,ctx)) goto err; + T=A; + A=B; + B=M; + /* T has a struct, M does not */ + + if (!BN_mul(T,D,X,ctx)) goto err; + if (!BN_add(T,T,Y)) goto err; + M=Y; + Y=X; + X=T; + sign= -sign; + } + if (sign < 0) + { + if (!BN_sub(Y,n,Y)) goto err; + } + + if (BN_is_one(A)) + { if (!BN_mod(R,Y,n,ctx)) goto err; } + else + { + BNerr(BN_F_BN_MOD_INVERSE,BN_R_NO_INVERSE); + goto err; + } + ret=R; +err: + if ((ret == NULL) && (in == NULL)) BN_free(R); + BN_CTX_end(ctx); + return(ret); + } + diff --git a/libsecurity_apple_csp/open_ssl/bn/bn_lcl.h b/libsecurity_apple_csp/open_ssl/bn/bn_lcl.h new file mode 100644 index 00000000..9c959921 --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/bn/bn_lcl.h @@ -0,0 +1,419 @@ +/* crypto/bn/bn_lcl.h */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright (c) 1998-2000 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#ifndef HEADER_BN_LCL_H +#define HEADER_BN_LCL_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +/* + * BN_window_bits_for_exponent_size -- macro for sliding window mod_exp functions + * + * + * For window size 'w' (w >= 2) and a random 'b' bits exponent, + * the number of multiplications is a constant plus on average + * + * 2^(w-1) + (b-w)/(w+1); + * + * here 2^(w-1) is for precomputing the table (we actually need + * entries only for windows that have the lowest bit set), and + * (b-w)/(w+1) is an approximation for the expected number of + * w-bit windows, not counting the first one. + * + * Thus we should use + * + * w >= 6 if b > 671 + * w = 5 if 671 > b > 239 + * w = 4 if 239 > b > 79 + * w = 3 if 79 > b > 23 + * w <= 2 if 23 > b + * + * (with draws in between). Very small exponents are often selected + * with low Hamming weight, so we use w = 1 for b <= 23. + */ +#if 1 +#define BN_window_bits_for_exponent_size(b) \ + ((b) > 671 ? 6 : \ + (b) > 239 ? 5 : \ + (b) > 79 ? 4 : \ + (b) > 23 ? 3 : 1) +#else +/* Old SSLeay/OpenSSL table. + * Maximum window size was 5, so this table differs for b==1024; + * but it coincides for other interesting values (b==160, b==512). + */ +#define BN_window_bits_for_exponent_size(b) \ + ((b) > 255 ? 5 : \ + (b) > 127 ? 4 : \ + (b) > 17 ? 3 : 1) +#endif + + + +/* Pentium pro 16,16,16,32,64 */ +/* Alpha 16,16,16,16.64 */ +#define BN_MULL_SIZE_NORMAL (16) /* 32 */ +#define BN_MUL_RECURSIVE_SIZE_NORMAL (16) /* 32 less than */ +#define BN_SQR_RECURSIVE_SIZE_NORMAL (16) /* 32 */ +#define BN_MUL_LOW_RECURSIVE_SIZE_NORMAL (32) /* 32 */ +#define BN_MONT_CTX_SET_SIZE_WORD (64) /* 32 */ + +#if !defined(NO_ASM) && !defined(NO_INLINE_ASM) && !defined(PEDANTIC) +/* + * BN_UMULT_HIGH section. + * + * No, I'm not trying to overwhelm you when stating that the + * product of N-bit numbers is 2*N bits wide:-) No, I don't expect + * you to be impressed when I say that if the compiler doesn't + * support 2*N integer type, then you have to replace every N*N + * multiplication with 4 (N/2)*(N/2) accompanied by some shifts + * and additions which unavoidably results in severe performance + * penalties. Of course provided that the hardware is capable of + * producing 2*N result... That's when you normally start + * considering assembler implementation. However! It should be + * pointed out that some CPUs (most notably Alpha, PowerPC and + * upcoming IA-64 family:-) provide *separate* instruction + * calculating the upper half of the product placing the result + * into a general purpose register. Now *if* the compiler supports + * inline assembler, then it's not impossible to implement the + * "bignum" routines (and have the compiler optimize 'em) + * exhibiting "native" performance in C. That's what BN_UMULT_HIGH + * macro is about:-) + * + * + */ +# if defined(__alpha) && (defined(SIXTY_FOUR_BIT_LONG) || defined(SIXTY_FOUR_BIT)) +# if defined(__DECC) +# include +# define BN_UMULT_HIGH(a,b) (BN_ULONG)asm("umulh %a0,%a1,%v0",(a),(b)) +# elif defined(__GNUC__) +# define BN_UMULT_HIGH(a,b) ({ \ + register BN_ULONG ret; \ + asm ("umulh %1,%2,%0" \ + : "=r"(ret) \ + : "r"(a), "r"(b)); \ + ret; }) +# endif /* compiler */ +# elif defined(_ARCH_PPC) && defined(__64BIT__) && defined(SIXTY_FOUR_BIT_LONG) +# if defined(__GNUC__) +# define BN_UMULT_HIGH(a,b) ({ \ + register BN_ULONG ret; \ + asm ("mulhdu %0,%1,%2" \ + : "=r"(ret) \ + : "r"(a), "r"(b)); \ + ret; }) +# endif /* compiler */ +# endif /* cpu */ +#endif /* NO_ASM */ + +/************************************************************* + * Using the long long type + */ +#define Lw(t) (((BN_ULONG)(t))&BN_MASK2) +#define Hw(t) (((BN_ULONG)((t)>>BN_BITS2))&BN_MASK2) + +/* This is used for internal error checking and is not normally used */ +#ifdef BN_DEBUG +# include +# define bn_check_top(a) assert ((a)->top >= 0 && (a)->top <= (a)->dmax); +#else +# define bn_check_top(a) +#endif + +/* This macro is to add extra stuff for development checking */ +#ifdef BN_DEBUG +#define bn_set_max(r) ((r)->max=(r)->top,BN_set_flags((r),BN_FLG_STATIC_DATA)) +#else +#define bn_set_max(r) +#endif + +/* These macros are used to 'take' a section of a bignum for read only use */ +#define bn_set_low(r,a,n) \ + { \ + (r)->top=((a)->top > (n))?(n):(a)->top; \ + (r)->d=(a)->d; \ + (r)->neg=(a)->neg; \ + (r)->flags|=BN_FLG_STATIC_DATA; \ + bn_set_max(r); \ + } + +#define bn_set_high(r,a,n) \ + { \ + if ((a)->top > (n)) \ + { \ + (r)->top=(a)->top-n; \ + (r)->d= &((a)->d[n]); \ + } \ + else \ + (r)->top=0; \ + (r)->neg=(a)->neg; \ + (r)->flags|=BN_FLG_STATIC_DATA; \ + bn_set_max(r); \ + } + +#ifdef BN_LLONG +#define mul_add(r,a,w,c) { \ + BN_ULLONG t; \ + t=(BN_ULLONG)w * (a) + (r) + (c); \ + (r)= Lw(t); \ + (c)= Hw(t); \ + } + +#define mul(r,a,w,c) { \ + BN_ULLONG t; \ + t=(BN_ULLONG)w * (a) + (c); \ + (r)= Lw(t); \ + (c)= Hw(t); \ + } + +#define sqr(r0,r1,a) { \ + BN_ULLONG t; \ + t=(BN_ULLONG)(a)*(a); \ + (r0)=Lw(t); \ + (r1)=Hw(t); \ + } + +#elif defined(BN_UMULT_HIGH) +#define mul_add(r,a,w,c) { \ + BN_ULONG high,low,ret,tmp=(a); \ + ret = (r); \ + high= BN_UMULT_HIGH(w,tmp); \ + ret += (c); \ + low = (w) * tmp; \ + (c) = (ret<(c))?1:0; \ + (c) += high; \ + ret += low; \ + (c) += (ret>BN_BITS4)&BN_MASK2l) +#define L2HBITS(a) ((BN_ULONG)((a)&BN_MASK2l)<>BN_BITS2)&BN_MASKl) +#define LL2HBITS(a) ((BN_ULLONG)((a)&BN_MASKl)<>(BN_BITS4-1); \ + m =(m&BN_MASK2l)<<(BN_BITS4+1); \ + l=(l+m)&BN_MASK2; if (l < m) h++; \ + (lo)=l; \ + (ho)=h; \ + } + +#define mul_add(r,a,bl,bh,c) { \ + BN_ULONG l,h; \ + \ + h= (a); \ + l=LBITS(h); \ + h=HBITS(h); \ + mul64(l,h,(bl),(bh)); \ + \ + /* non-multiply part */ \ + l=(l+(c))&BN_MASK2; if (l < (c)) h++; \ + (c)=(r); \ + l=(l+(c))&BN_MASK2; if (l < (c)) h++; \ + (c)=h&BN_MASK2; \ + (r)=l; \ + } + +#define mul(r,a,bl,bh,c) { \ + BN_ULONG l,h; \ + \ + h= (a); \ + l=LBITS(h); \ + h=HBITS(h); \ + mul64(l,h,(bl),(bh)); \ + \ + /* non-multiply part */ \ + l+=(c); if ((l&BN_MASK2) < (c)) h++; \ + (c)=h&BN_MASK2; \ + (r)=l&BN_MASK2; \ + } +#endif /* !BN_LLONG */ + +void bn_mul_normal(BN_ULONG *r,BN_ULONG *a,int na,BN_ULONG *b,int nb); +void bn_mul_comba8(BN_ULONG *r,BN_ULONG *a,BN_ULONG *b); +void bn_mul_comba4(BN_ULONG *r,BN_ULONG *a,BN_ULONG *b); +void bn_sqr_normal(BN_ULONG *r, BN_ULONG *a, int n, BN_ULONG *tmp); +void bn_sqr_comba8(BN_ULONG *r,BN_ULONG *a); +void bn_sqr_comba4(BN_ULONG *r,BN_ULONG *a); +int bn_cmp_words(BN_ULONG *a,BN_ULONG *b,int n); +void bn_mul_recursive(BN_ULONG *r,BN_ULONG *a,BN_ULONG *b,int n2,BN_ULONG *t); +void bn_mul_part_recursive(BN_ULONG *r,BN_ULONG *a,BN_ULONG *b, + int tn, int n,BN_ULONG *t); +void bn_sqr_recursive(BN_ULONG *r,BN_ULONG *a, int n2, BN_ULONG *t); +void bn_mul_low_normal(BN_ULONG *r,BN_ULONG *a,BN_ULONG *b, int n); +void bn_mul_low_recursive(BN_ULONG *r,BN_ULONG *a,BN_ULONG *b,int n2, + BN_ULONG *t); +void bn_mul_high(BN_ULONG *r,BN_ULONG *a,BN_ULONG *b,BN_ULONG *l,int n2, + BN_ULONG *t); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libsecurity_apple_csp/open_ssl/bn/bn_lib.c b/libsecurity_apple_csp/open_ssl/bn/bn_lib.c new file mode 100644 index 00000000..667dca23 --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/bn/bn_lib.c @@ -0,0 +1,778 @@ +/* + * 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. + */ + + +/* crypto/bn/bn_lib.c */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include +#include "cryptlib.h" +#include "bn_lcl.h" + +const char *BN_version="Big Number" OPENSSL_VERSION_PTEXT; + +#if BN_PARAMS_ENABLE + +/* For a 32 bit machine + * 2 - 4 == 128 + * 3 - 8 == 256 + * 4 - 16 == 512 + * 5 - 32 == 1024 + * 6 - 64 == 2048 + * 7 - 128 == 4096 + * 8 - 256 == 8192 + */ +static int bn_limit_bits=0; +static int bn_limit_num=8; /* (1<= 0) + { + if (mult > (sizeof(int)*8)-1) + mult=sizeof(int)*8-1; + bn_limit_bits=mult; + bn_limit_num=1<= 0) + { + if (high > (sizeof(int)*8)-1) + high=sizeof(int)*8-1; + bn_limit_bits_high=high; + bn_limit_num_high=1<= 0) + { + if (low > (sizeof(int)*8)-1) + low=sizeof(int)*8-1; + bn_limit_bits_low=low; + bn_limit_num_low=1<= 0) + { + if (mont > (sizeof(int)*8)-1) + mont=sizeof(int)*8-1; + bn_limit_bits_mont=mont; + bn_limit_num_mont=1<>56)]+56); + } + else return(bits[(int)(l>>48)]+48); + } + else + { + if (l & 0x0000ff0000000000L) + { + return(bits[(int)(l>>40)]+40); + } + else return(bits[(int)(l>>32)]+32); + } + } + else +#else +#ifdef SIXTY_FOUR_BIT + if (l & 0xffffffff00000000LL) + { + if (l & 0xffff000000000000LL) + { + if (l & 0xff00000000000000LL) + { + return(bits[(int)(l>>56)]+56); + } + else return(bits[(int)(l>>48)]+48); + } + else + { + if (l & 0x0000ff0000000000LL) + { + return(bits[(int)(l>>40)]+40); + } + else return(bits[(int)(l>>32)]+32); + } + } + else +#endif +#endif + { +#if defined(THIRTY_TWO_BIT) || defined(SIXTY_FOUR_BIT) || defined(SIXTY_FOUR_BIT_LONG) + if (l & 0xffff0000L) + { + if (l & 0xff000000L) + return(bits[(int)(l>>24L)]+24); + else return(bits[(int)(l>>16L)]+16); + } + else +#endif + { +#if defined(SIXTEEN_BIT) || defined(THIRTY_TWO_BIT) || defined(SIXTY_FOUR_BIT) || defined(SIXTY_FOUR_BIT_LONG) + if (l & 0xff00L) + return(bits[(int)(l>>8)]+8); + else +#endif + return(bits[(int)(l )] ); + } + } + } + +int BN_num_bits(const BIGNUM *a) + { + BN_ULONG l; + int i; + + bn_check_top(a); + + if (a->top == 0) return(0); + l=a->d[a->top-1]; + i=(a->top-1)*BN_BITS2; + if (l == 0) + { +#if !defined(NO_STDIO) && !defined(WIN16) + fprintf(stderr,"BAD TOP VALUE\n"); +#endif + abort(); + } + return(i+BN_num_bits_word(l)); + } + +void BN_clear_free(BIGNUM *a) + { + int i; + + if (a == NULL) return; + if (a->d != NULL) + { + memset(a->d,0,a->max*sizeof(a->d[0])); + if (!(BN_get_flags(a,BN_FLG_STATIC_DATA))) + Free(a->d); + } + i=BN_get_flags(a,BN_FLG_MALLOCED); + memset(a,0,sizeof(BIGNUM)); + if (i) + Free(a); + } + +void BN_free(BIGNUM *a) + { + if (a == NULL) return; + if ((a->d != NULL) && !(BN_get_flags(a,BN_FLG_STATIC_DATA))) + Free(a->d); + a->flags|=BN_FLG_FREE; /* REMOVE? */ + if (a->flags & BN_FLG_MALLOCED) + Free(a); + } + +void BN_init(BIGNUM *a) + { + memset(a,0,sizeof(BIGNUM)); + } + +BIGNUM *BN_new(void) + { + BIGNUM *ret; + + if ((ret=(BIGNUM *)Malloc(sizeof(BIGNUM))) == NULL) + { + BNerr(BN_F_BN_NEW,ERR_R_MALLOC_FAILURE); + return(NULL); + } + ret->flags=BN_FLG_MALLOCED; + ret->top=0; + ret->neg=0; + ret->max=0; + ret->d=NULL; + return(ret); + } + +/* This is an internal function that should not be used in applications. + * It ensures that 'b' has enough room for a 'words' word number number. + * It is mostly used by the various BIGNUM routines. If there is an error, + * NULL is returned. If not, 'b' is returned. */ + +BIGNUM *bn_expand2(BIGNUM *b, int words) + { + BN_ULONG *A,*a; + const BN_ULONG *B; + int i; + + bn_check_top(b); + + if (words > b->max) + { + bn_check_top(b); + if (BN_get_flags(b,BN_FLG_STATIC_DATA)) + { + BNerr(BN_F_BN_EXPAND2,BN_R_EXPAND_ON_STATIC_BIGNUM_DATA); + return(NULL); + } + a=A=(BN_ULONG *)Malloc(sizeof(BN_ULONG)*(words+1)); + if (A == NULL) + { + BNerr(BN_F_BN_EXPAND2,ERR_R_MALLOC_FAILURE); + return(NULL); + } +#if 1 + B=b->d; + /* Check if the previous number needs to be copied */ + if (B != NULL) + { +#if 0 + /* This lot is an unrolled loop to copy b->top + * BN_ULONGs from B to A + */ +/* + * I have nothing against unrolling but it's usually done for + * several reasons, namely: + * - minimize percentage of decision making code, i.e. branches; + * - avoid cache trashing; + * - make it possible to schedule loads earlier; + * Now let's examine the code below. The cornerstone of C is + * "programmer is always right" and that's what we love it for:-) + * For this very reason C compilers have to be paranoid when it + * comes to data aliasing and assume the worst. Yeah, but what + * does it mean in real life? This means that loop body below will + * be compiled to sequence of loads immediately followed by stores + * as compiler assumes the worst, something in A==B+1 style. As a + * result CPU pipeline is going to starve for incoming data. Secondly + * if A and B happen to share same cache line such code is going to + * cause severe cache trashing. Both factors have severe impact on + * performance of modern CPUs and this is the reason why this + * particular piece of code is #ifdefed away and replaced by more + * "friendly" version found in #else section below. This comment + * also applies to BN_copy function. + * + * + */ + for (i=b->top&(~7); i>0; i-=8) + { + A[0]=B[0]; A[1]=B[1]; A[2]=B[2]; A[3]=B[3]; + A[4]=B[4]; A[5]=B[5]; A[6]=B[6]; A[7]=B[7]; + A+=8; + B+=8; + } + switch (b->top&7) + { + case 7: + A[6]=B[6]; + case 6: + A[5]=B[5]; + case 5: + A[4]=B[4]; + case 4: + A[3]=B[3]; + case 3: + A[2]=B[2]; + case 2: + A[1]=B[1]; + case 1: + A[0]=B[0]; + case 0: + /* I need the 'case 0' entry for utrix cc. + * If the optimizer is turned on, it does the + * switch table by doing + * a=top&7 + * a--; + * goto jump_table[a]; + * If top is 0, this makes us jump to 0xffffffc + * which is rather bad :-(. + * eric 23-Apr-1998 + */ + ; + } +#else + for (i=b->top>>2; i>0; i--,A+=4,B+=4) + { + /* + * The fact that the loop is unrolled + * 4-wise is a tribute to Intel. It's + * the one that doesn't have enough + * registers to accomodate more data. + * I'd unroll it 8-wise otherwise:-) + * + * + */ + BN_ULONG a0,a1,a2,a3; + a0=B[0]; a1=B[1]; a2=B[2]; a3=B[3]; + A[0]=a0; A[1]=a1; A[2]=a2; A[3]=a3; + } + switch (b->top&3) + { + case 3: A[2]=B[2]; + case 2: A[1]=B[1]; + case 1: A[0]=B[0]; + case 0: ; /* ultrix cc workaround, see above */ + } +#endif + Free(b->d); + } + + b->d=a; + b->max=words; + + /* Now need to zero any data between b->top and b->max */ + + A= &(b->d[b->top]); + for (i=(b->max - b->top)>>3; i>0; i--,A+=8) + { + A[0]=0; A[1]=0; A[2]=0; A[3]=0; + A[4]=0; A[5]=0; A[6]=0; A[7]=0; + } + for (i=(b->max - b->top)&7; i>0; i--,A++) + A[0]=0; +#else + memset(A,0,sizeof(BN_ULONG)*(words+1)); + memcpy(A,b->d,sizeof(b->d[0])*b->top); + b->d=a; + b->max=words; +#endif + +/* memset(&(p[b->max]),0,((words+1)-b->max)*sizeof(BN_ULONG)); */ +/* { int i; for (i=b->max; itop) == NULL) return(NULL); + +#if 1 + A=a->d; + B=b->d; + for (i=b->top>>2; i>0; i--,A+=4,B+=4) + { + BN_ULONG a0,a1,a2,a3; + a0=B[0]; a1=B[1]; a2=B[2]; a3=B[3]; + A[0]=a0; A[1]=a1; A[2]=a2; A[3]=a3; + } + switch (b->top&3) + { + case 3: A[2]=B[2]; + case 2: A[1]=B[1]; + case 1: A[0]=B[0]; + case 0: ; /* ultrix cc workaround, see comments in bn_expand2 */ + } +#else + memcpy(a->d,b->d,sizeof(b->d[0])*b->top); +#endif + +/* memset(&(a->d[b->top]),0,sizeof(a->d[0])*(a->max-b->top));*/ + a->top=b->top; + if ((a->top == 0) && (a->d != NULL)) + a->d[0]=0; + a->neg=b->neg; + return(a); + } + +void BN_clear(BIGNUM *a) + { + if (a->d != NULL) + memset(a->d,0,a->max*sizeof(a->d[0])); + a->top=0; + a->neg=0; + } + +BN_ULONG BN_get_word(BIGNUM *a) + { + int i; + unsigned n; + BN_ULONG ret=0; + + n=BN_num_bytes(a); + if (n > sizeof(BN_ULONG)) + return(BN_MASK2); + for (i=a->top-1; i>=0; i--) + { +#ifndef SIXTY_FOUR_BIT /* the data item > unsigned long */ + ret<<=BN_BITS4; /* stops the compiler complaining */ + ret<<=BN_BITS4; +#else + ret=0; +#endif + ret|=a->d[i]; + } + return(ret); + } + +int BN_set_word(BIGNUM *a, BN_ULONG w) + { + int i,n; + + if (bn_expand(a,(int)(sizeof(BN_ULONG)*8)) == NULL) return(0); + + n=sizeof(BN_ULONG)/BN_BYTES; + a->neg=0; + a->top=0; + a->d[0]=(BN_ULONG)w&BN_MASK2; + if (a->d[0] != 0) a->top=1; + for (i=1; i>=BN_BITS2 so compilers don't complain + * on builds where sizeof(long) == BN_TYPES */ +#ifndef SIXTY_FOUR_BIT /* the data item > unsigned long */ + w>>=BN_BITS4; + w>>=BN_BITS4; +#else + w=0; +#endif + a->d[i]=(BN_ULONG)w&BN_MASK2; + if (a->d[i] != 0) a->top=i+1; + } + return(1); + } + +/* ignore negative */ +BIGNUM *BN_bin2bn(const unsigned char *s, int len, BIGNUM *ret) + { + unsigned int i,m; + unsigned int n; + BN_ULONG l; + + if (ret == NULL) ret=BN_new(); + if (ret == NULL) return(NULL); + l=0; + n=len; + if (n == 0) + { + ret->top=0; + return(ret); + } + if (bn_expand(ret,(int)(n+2)*8) == NULL) + return(NULL); + i=((n-1)/BN_BYTES)+1; + m=((n-1)%(BN_BYTES)); + ret->top=i; + while (n-- > 0) + { + l=(l<<8L)| *(s++); + if (m-- == 0) + { + ret->d[--i]=l; + l=0; + m=BN_BYTES-1; + } + } + /* need to call this due to clear byte at top if avoiding + * having the top bit set (-ve number) */ + bn_fix_top(ret); + return(ret); + } + +/* ignore negative */ +int BN_bn2bin(const BIGNUM *a, unsigned char *to) + { + int n,i; + BN_ULONG l; + + n=i=BN_num_bytes(a); + while (i-- > 0) + { + l=a->d[i/BN_BYTES]; + *(to++)=(unsigned char)(l>>(8*(i%BN_BYTES)))&0xff; + } + return(n); + } + +int BN_ucmp(const BIGNUM *a, const BIGNUM *b) + { + int i; + BN_ULONG t1,t2,*ap,*bp; + + bn_check_top(a); + bn_check_top(b); + + i=a->top-b->top; + if (i != 0) return(i); + ap=a->d; + bp=b->d; + for (i=a->top-1; i>=0; i--) + { + t1= ap[i]; + t2= bp[i]; + if (t1 != t2) + return(t1 > t2?1:-1); + } + return(0); + } + +int BN_cmp(const BIGNUM *a, const BIGNUM *b) + { + int i; + int gt,lt; + BN_ULONG t1,t2; + + if ((a == NULL) || (b == NULL)) + { + if (a != NULL) + return(-1); + else if (b != NULL) + return(1); + else + return(0); + } + + bn_check_top(a); + bn_check_top(b); + + if (a->neg != b->neg) + { + if (a->neg) + return(-1); + else return(1); + } + if (a->neg == 0) + { gt=1; lt= -1; } + else { gt= -1; lt=1; } + + if (a->top > b->top) return(gt); + if (a->top < b->top) return(lt); + for (i=a->top-1; i>=0; i--) + { + t1=a->d[i]; + t2=b->d[i]; + if (t1 > t2) return(gt); + if (t1 < t2) return(lt); + } + return(0); + } + +int BN_set_bit(BIGNUM *a, int n) + { + int i,j,k; + + i=n/BN_BITS2; + j=n%BN_BITS2; + if (a->top <= i) + { + if (bn_wexpand(a,i+1) == NULL) return(0); + for(k=a->top; kd[k]=0; + a->top=i+1; + } + + a->d[i]|=(((BN_ULONG)1)<top <= i) return(0); + + a->d[i]&=(~(((BN_ULONG)1)<top <= i) return(0); + return((a->d[i]&(((BN_ULONG)1)<= a->top) return(0); + if (b == 0) + a->top=w; + else + { + a->top=w+1; + a->d[w]&= ~(BN_MASK2< bb)?1:-1); + for (i=n-2; i>=0; i--) + { + aa=a[i]; + bb=b[i]; + if (aa != bb) return((aa > bb)?1:-1); + } + return(0); + } + diff --git a/libsecurity_apple_csp/open_ssl/bn/bn_mont.c b/libsecurity_apple_csp/open_ssl/bn/bn_mont.c new file mode 100644 index 00000000..69e573b3 --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/bn/bn_mont.c @@ -0,0 +1,357 @@ +/* + * 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. + */ + + +/* crypto/bn/bn_mont.c */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +/* + * Details about Montgomery multiplication algorithms can be found at + * http://security.ece.orst.edu/publications.html, e.g. + * http://security.ece.orst.edu/koc/papers/j37acmon.pdf and + * sections 3.8 and 4.2 in http://security.ece.orst.edu/koc/papers/r01rsasw.pdf + */ + +#include +#include "cryptlib.h" +#include "bn_lcl.h" + +#define MONT_WORD /* use the faster word-based algorithm */ + +int BN_mod_mul_montgomery(BIGNUM *r, BIGNUM *a, BIGNUM *b, + BN_MONT_CTX *mont, BN_CTX *ctx) + { + BIGNUM *tmp,*tmp2; + int ret=0; + + BN_CTX_start(ctx); + tmp = BN_CTX_get(ctx); + tmp2 = BN_CTX_get(ctx); + if (tmp == NULL || tmp2 == NULL) goto err; + + bn_check_top(tmp); + bn_check_top(tmp2); + + if (a == b) + { +#if 0 + bn_wexpand(tmp,a->top*2); + bn_wexpand(tmp2,a->top*4); + bn_sqr_recursive(tmp->d,a->d,a->top,tmp2->d); + tmp->top=a->top*2; + if (tmp->d[tmp->top-1] == 0) + tmp->top--; +#else + if (!BN_sqr(tmp,a,ctx)) goto err; +#endif + } + else + { + if (!BN_mul(tmp,a,b,ctx)) goto err; + } + /* reduce from aRR to aR */ + if (!BN_from_montgomery(r,tmp,mont,ctx)) goto err; + ret=1; +err: + BN_CTX_end(ctx); + return(ret); + } + +int BN_from_montgomery(BIGNUM *ret, BIGNUM *a, BN_MONT_CTX *mont, + BN_CTX *ctx) + { + int retn=0; + +#ifdef MONT_WORD + BIGNUM *n,*r; + BN_ULONG *ap,*np,*rp,n0,v,*nrp; + int al,nl,max,i,x,ri; + + BN_CTX_start(ctx); + if ((r = BN_CTX_get(ctx)) == NULL) goto err; + + if (!BN_copy(r,a)) goto err; + n= &(mont->N); + + ap=a->d; + /* mont->ri is the size of mont->N in bits (rounded up + to the word size) */ + al=ri=mont->ri/BN_BITS2; + + nl=n->top; + if ((al == 0) || (nl == 0)) { r->top=0; return(1); } + + max=(nl+al+1); /* allow for overflow (no?) XXX */ + if (bn_wexpand(r,max) == NULL) goto err; + if (bn_wexpand(ret,max) == NULL) goto err; + + r->neg=a->neg^n->neg; + np=n->d; + rp=r->d; + nrp= &(r->d[nl]); + + /* clear the top words of T */ +#if 1 + for (i=r->top; id[i]=0; +#else + memset(&(r->d[r->top]),0,(max-r->top)*sizeof(BN_ULONG)); +#endif + + r->top=max; + n0=mont->n0; + +#ifdef BN_COUNT + printf("word BN_from_montgomery %d * %d\n",nl,nl); +#endif + for (i=0; i= v) + continue; + else + { + if (((++nrp[0])&BN_MASK2) != 0) continue; + if (((++nrp[1])&BN_MASK2) != 0) continue; + for (x=2; (((++nrp[x])&BN_MASK2) == 0); x++) ; + } + } + bn_fix_top(r); + + /* mont->ri will be a multiple of the word size */ +#if 0 + BN_rshift(ret,r,mont->ri); +#else + x=ri; + rp=ret->d; + ap= &(r->d[x]); + if (r->top < x) + al=0; + else + al=r->top-x; + ret->top=al; + al-=4; + for (i=0; iri); + + if (!BN_mul(t2,t1,&mont->Ni,ctx)) goto err; + BN_mask_bits(t2,mont->ri); + + if (!BN_mul(t1,t2,&mont->N,ctx)) goto err; + if (!BN_add(t2,a,t1)) goto err; + BN_rshift(ret,t2,mont->ri); +#endif /* MONT_WORD */ + + if (BN_ucmp(ret, &(mont->N)) >= 0) + { + BN_usub(ret,ret,&(mont->N)); + } + retn=1; + err: + BN_CTX_end(ctx); + return(retn); + } + +BN_MONT_CTX *BN_MONT_CTX_new(void) + { + BN_MONT_CTX *ret; + + if ((ret=(BN_MONT_CTX *)Malloc(sizeof(BN_MONT_CTX))) == NULL) + return(NULL); + + BN_MONT_CTX_init(ret); + ret->flags=BN_FLG_MALLOCED; + return(ret); + } + +void BN_MONT_CTX_init(BN_MONT_CTX *ctx) + { + ctx->ri=0; + BN_init(&(ctx->RR)); + BN_init(&(ctx->N)); + BN_init(&(ctx->Ni)); + ctx->flags=0; + } + +void BN_MONT_CTX_free(BN_MONT_CTX *mont) + { + if(mont == NULL) + return; + + BN_free(&(mont->RR)); + BN_free(&(mont->N)); + BN_free(&(mont->Ni)); + if (mont->flags & BN_FLG_MALLOCED) + Free(mont); + } + +int BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod, BN_CTX *ctx) + { + BIGNUM Ri,*R; + + BN_init(&Ri); + R= &(mont->RR); /* grab RR as a temp */ + BN_copy(&(mont->N),mod); /* Set N */ + +#ifdef MONT_WORD + { + BIGNUM tmod; + BN_ULONG buf[2]; + + mont->ri=(BN_num_bits(mod)+(BN_BITS2-1))/BN_BITS2*BN_BITS2; + BN_zero(R); + BN_set_bit(R,BN_BITS2); /* R */ + + buf[0]=mod->d[0]; /* tmod = N mod word size */ + buf[1]=0; + tmod.d=buf; + tmod.top=1; + tmod.max=2; + tmod.neg=mod->neg; + /* Ri = R^-1 mod N*/ + if ((BN_mod_inverse(&Ri,R,&tmod,ctx)) == NULL) + goto err; + BN_lshift(&Ri,&Ri,BN_BITS2); /* R*Ri */ + if (!BN_is_zero(&Ri)) + BN_sub_word(&Ri,1); + else /* if N mod word size == 1 */ + BN_set_word(&Ri,BN_MASK2); /* Ri-- (mod word size) */ + BN_div(&Ri,NULL,&Ri,&tmod,ctx); /* Ni = (R*Ri-1)/N, + * keep only least significant word: */ + mont->n0=Ri.d[0]; + BN_free(&Ri); + } +#else /* !MONT_WORD */ + { /* bignum version */ + mont->ri=BN_num_bits(mod); + BN_zero(R); + BN_set_bit(R,mont->ri); /* R = 2^ri */ + /* Ri = R^-1 mod N*/ + if ((BN_mod_inverse(&Ri,R,mod,ctx)) == NULL) + goto err; + BN_lshift(&Ri,&Ri,mont->ri); /* R*Ri */ + BN_sub_word(&Ri,1); + /* Ni = (R*Ri-1) / N */ + BN_div(&(mont->Ni),NULL,&Ri,mod,ctx); + BN_free(&Ri); + } +#endif + + /* setup RR for conversions */ + BN_zero(&(mont->RR)); + BN_set_bit(&(mont->RR),mont->ri*2); + BN_mod(&(mont->RR),&(mont->RR),&(mont->N),ctx); + + return(1); +err: + return(0); + } + +BN_MONT_CTX *BN_MONT_CTX_copy(BN_MONT_CTX *to, BN_MONT_CTX *from) + { + if (to == from) return(to); + + BN_copy(&(to->RR),&(from->RR)); + BN_copy(&(to->N),&(from->N)); + BN_copy(&(to->Ni),&(from->Ni)); + to->ri=from->ri; + to->n0=from->n0; + return(to); + } + diff --git a/libsecurity_apple_csp/open_ssl/bn/bn_mpi.c b/libsecurity_apple_csp/open_ssl/bn/bn_mpi.c new file mode 100644 index 00000000..1aefdaaf --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/bn/bn_mpi.c @@ -0,0 +1,147 @@ +/* + * 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. + */ + + +/* crypto/bn/bn_mpi.c */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include +#include "cryptlib.h" +#include "bn_lcl.h" + +int BN_bn2mpi(const BIGNUM *a, unsigned char *d) + { + int bits; + int num=0; + int ext=0; + long l; + + bits=BN_num_bits(a); + num=(bits+7)/8; + if (bits > 0) + { + ext=((bits & 0x07) == 0); + } + if (d == NULL) + return(num+4+ext); + + l=num+ext; + d[0]=(unsigned char)(l>>24)&0xff; + d[1]=(unsigned char)(l>>16)&0xff; + d[2]=(unsigned char)(l>> 8)&0xff; + d[3]=(unsigned char)(l )&0xff; + if (ext) d[4]=0; + num=BN_bn2bin(a,&(d[4+ext])); + if (a->neg) + d[4]|=0x80; + return(num+4+ext); + } + +BIGNUM *BN_mpi2bn(unsigned char *d, int n, BIGNUM *a) + { + long len; + int neg=0; + + if (n < 4) + { + BNerr(BN_F_BN_MPI2BN,BN_R_INVALID_LENGTH); + return(NULL); + } + len=((long)d[0]<<24)|((long)d[1]<<16)|((int)d[2]<<8)|(int)d[3]; + if ((len+4) != n) + { + BNerr(BN_F_BN_MPI2BN,BN_R_ENCODING_ERROR); + return(NULL); + } + + if (a == NULL) a=BN_new(); + if (a == NULL) return(NULL); + + if (len == 0) + { + a->neg=0; + a->top=0; + return(a); + } + d+=4; + if ((*d) & 0x80) + neg=1; + if (BN_bin2bn(d,(int)len,a) == NULL) + return(NULL); + a->neg=neg; + if (neg) + { + BN_clear_bit(a,BN_num_bits(a)-1); + } + return(a); + } + diff --git a/libsecurity_apple_csp/open_ssl/bn/bn_mul.c b/libsecurity_apple_csp/open_ssl/bn/bn_mul.c new file mode 100644 index 00000000..20987d95 --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/bn/bn_mul.c @@ -0,0 +1,812 @@ +/* + * 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. + */ + + +/* crypto/bn/bn_mul.c */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include +#include "cryptlib.h" +#include "bn_lcl.h" + +#ifdef BN_RECURSION +/* Karatsuba recursive multiplication algorithm + * (cf. Knuth, The Art of Computer Programming, Vol. 2) */ + +/* r is 2*n2 words in size, + * a and b are both n2 words in size. + * n2 must be a power of 2. + * We multiply and return the result. + * t must be 2*n2 words in size + * We calculate + * a[0]*b[0] + * a[0]*b[0]+a[1]*b[1]+(a[0]-a[1])*(b[1]-b[0]) + * a[1]*b[1] + */ +void bn_mul_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n2, + BN_ULONG *t) + { + int n=n2/2,c1,c2; + unsigned int neg,zero; + BN_ULONG ln,lo,*p; + +# ifdef BN_COUNT + printf(" bn_mul_recursive %d * %d\n",n2,n2); +# endif +# ifdef BN_MUL_COMBA +# if 0 + if (n2 == 4) + { + bn_mul_comba4(r,a,b); + return; + } +# endif + if (n2 == 8) + { + bn_mul_comba8(r,a,b); + return; + } +# endif /* BN_MUL_COMBA */ + if (n2 < BN_MUL_RECURSIVE_SIZE_NORMAL) + { + /* This should not happen */ + bn_mul_normal(r,a,n2,b,n2); + return; + } + /* r=(a[0]-a[1])*(b[1]-b[0]) */ + c1=bn_cmp_words(a,&(a[n]),n); + c2=bn_cmp_words(&(b[n]),b,n); + zero=neg=0; + switch (c1*3+c2) + { + case -4: + bn_sub_words(t, &(a[n]),a, n); /* - */ + bn_sub_words(&(t[n]),b, &(b[n]),n); /* - */ + break; + case -3: + zero=1; + break; + case -2: + bn_sub_words(t, &(a[n]),a, n); /* - */ + bn_sub_words(&(t[n]),&(b[n]),b, n); /* + */ + neg=1; + break; + case -1: + case 0: + case 1: + zero=1; + break; + case 2: + bn_sub_words(t, a, &(a[n]),n); /* + */ + bn_sub_words(&(t[n]),b, &(b[n]),n); /* - */ + neg=1; + break; + case 3: + zero=1; + break; + case 4: + bn_sub_words(t, a, &(a[n]),n); + bn_sub_words(&(t[n]),&(b[n]),b, n); + break; + } + +# ifdef BN_MUL_COMBA + if (n == 4) + { + if (!zero) + bn_mul_comba4(&(t[n2]),t,&(t[n])); + else + memset(&(t[n2]),0,8*sizeof(BN_ULONG)); + + bn_mul_comba4(r,a,b); + bn_mul_comba4(&(r[n2]),&(a[n]),&(b[n])); + } + else if (n == 8) + { + if (!zero) + bn_mul_comba8(&(t[n2]),t,&(t[n])); + else + memset(&(t[n2]),0,16*sizeof(BN_ULONG)); + + bn_mul_comba8(r,a,b); + bn_mul_comba8(&(r[n2]),&(a[n]),&(b[n])); + } + else +# endif /* BN_MUL_COMBA */ + { + p= &(t[n2*2]); + if (!zero) + bn_mul_recursive(&(t[n2]),t,&(t[n]),n,p); + else + memset(&(t[n2]),0,n2*sizeof(BN_ULONG)); + bn_mul_recursive(r,a,b,n,p); + bn_mul_recursive(&(r[n2]),&(a[n]),&(b[n]),n,p); + } + + /* t[32] holds (a[0]-a[1])*(b[1]-b[0]), c1 is the sign + * r[10] holds (a[0]*b[0]) + * r[32] holds (b[1]*b[1]) + */ + + c1=(int)(bn_add_words(t,r,&(r[n2]),n2)); + + if (neg) /* if t[32] is negative */ + { + c1-=(int)(bn_sub_words(&(t[n2]),t,&(t[n2]),n2)); + } + else + { + /* Might have a carry */ + c1+=(int)(bn_add_words(&(t[n2]),&(t[n2]),t,n2)); + } + + /* t[32] holds (a[0]-a[1])*(b[1]-b[0])+(a[0]*b[0])+(a[1]*b[1]) + * r[10] holds (a[0]*b[0]) + * r[32] holds (b[1]*b[1]) + * c1 holds the carry bits + */ + c1+=(int)(bn_add_words(&(r[n]),&(r[n]),&(t[n2]),n2)); + if (c1) + { + p= &(r[n+n2]); + lo= *p; + ln=(lo+c1)&BN_MASK2; + *p=ln; + + /* The overflow will stop before we over write + * words we should not overwrite */ + if (ln < (BN_ULONG)c1) + { + do { + p++; + lo= *p; + ln=(lo+1)&BN_MASK2; + *p=ln; + } while (ln == 0); + } + } + } + +/* n+tn is the word length + * t needs to be n*4 is size, as does r */ +void bn_mul_part_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int tn, + int n, BN_ULONG *t) + { + int i,j,n2=n*2; + unsigned int c1,c2,neg,zero; + BN_ULONG ln,lo,*p; + +# ifdef BN_COUNT + printf(" bn_mul_part_recursive %d * %d\n",tn+n,tn+n); +# endif + if (n < 8) + { + i=tn+n; + bn_mul_normal(r,a,i,b,i); + return; + } + + /* r=(a[0]-a[1])*(b[1]-b[0]) */ + c1=bn_cmp_words(a,&(a[n]),n); + c2=bn_cmp_words(&(b[n]),b,n); + zero=neg=0; + switch (c1*3+c2) + { + case -4: + bn_sub_words(t, &(a[n]),a, n); /* - */ + bn_sub_words(&(t[n]),b, &(b[n]),n); /* - */ + break; + case -3: + zero=1; + /* break; */ + case -2: + bn_sub_words(t, &(a[n]),a, n); /* - */ + bn_sub_words(&(t[n]),&(b[n]),b, n); /* + */ + neg=1; + break; + case -1: + case 0: + case 1: + zero=1; + /* break; */ + case 2: + bn_sub_words(t, a, &(a[n]),n); /* + */ + bn_sub_words(&(t[n]),b, &(b[n]),n); /* - */ + neg=1; + break; + case 3: + zero=1; + /* break; */ + case 4: + bn_sub_words(t, a, &(a[n]),n); + bn_sub_words(&(t[n]),&(b[n]),b, n); + break; + } + /* The zero case isn't yet implemented here. The speedup + would probably be negligible. */ +# if 0 + if (n == 4) + { + bn_mul_comba4(&(t[n2]),t,&(t[n])); + bn_mul_comba4(r,a,b); + bn_mul_normal(&(r[n2]),&(a[n]),tn,&(b[n]),tn); + memset(&(r[n2+tn*2]),0,sizeof(BN_ULONG)*(n2-tn*2)); + } + else +# endif + if (n == 8) + { + bn_mul_comba8(&(t[n2]),t,&(t[n])); + bn_mul_comba8(r,a,b); + bn_mul_normal(&(r[n2]),&(a[n]),tn,&(b[n]),tn); + memset(&(r[n2+tn*2]),0,sizeof(BN_ULONG)*(n2-tn*2)); + } + else + { + p= &(t[n2*2]); + bn_mul_recursive(&(t[n2]),t,&(t[n]),n,p); + bn_mul_recursive(r,a,b,n,p); + i=n/2; + /* If there is only a bottom half to the number, + * just do it */ + j=tn-i; + if (j == 0) + { + bn_mul_recursive(&(r[n2]),&(a[n]),&(b[n]),i,p); + memset(&(r[n2+i*2]),0,sizeof(BN_ULONG)*(n2-i*2)); + } + else if (j > 0) /* eg, n == 16, i == 8 and tn == 11 */ + { + bn_mul_part_recursive(&(r[n2]),&(a[n]),&(b[n]), + j,i,p); + memset(&(r[n2+tn*2]),0, + sizeof(BN_ULONG)*(n2-tn*2)); + } + else /* (j < 0) eg, n == 16, i == 8 and tn == 5 */ + { + memset(&(r[n2]),0,sizeof(BN_ULONG)*n2); + if (tn < BN_MUL_RECURSIVE_SIZE_NORMAL) + { + bn_mul_normal(&(r[n2]),&(a[n]),tn,&(b[n]),tn); + } + else + { + for (;;) + { + i/=2; + if (i < tn) + { + bn_mul_part_recursive(&(r[n2]), + &(a[n]),&(b[n]), + tn-i,i,p); + break; + } + else if (i == tn) + { + bn_mul_recursive(&(r[n2]), + &(a[n]),&(b[n]), + i,p); + break; + } + } + } + } + } + + /* t[32] holds (a[0]-a[1])*(b[1]-b[0]), c1 is the sign + * r[10] holds (a[0]*b[0]) + * r[32] holds (b[1]*b[1]) + */ + + c1=(int)(bn_add_words(t,r,&(r[n2]),n2)); + + if (neg) /* if t[32] is negative */ + { + c1-=(int)(bn_sub_words(&(t[n2]),t,&(t[n2]),n2)); + } + else + { + /* Might have a carry */ + c1+=(int)(bn_add_words(&(t[n2]),&(t[n2]),t,n2)); + } + + /* t[32] holds (a[0]-a[1])*(b[1]-b[0])+(a[0]*b[0])+(a[1]*b[1]) + * r[10] holds (a[0]*b[0]) + * r[32] holds (b[1]*b[1]) + * c1 holds the carry bits + */ + c1+=(int)(bn_add_words(&(r[n]),&(r[n]),&(t[n2]),n2)); + if (c1) + { + p= &(r[n+n2]); + lo= *p; + ln=(lo+c1)&BN_MASK2; + *p=ln; + + /* The overflow will stop before we over write + * words we should not overwrite */ + if (ln < c1) + { + do { + p++; + lo= *p; + ln=(lo+1)&BN_MASK2; + *p=ln; + } while (ln == 0); + } + } + } + +/* a and b must be the same size, which is n2. + * r needs to be n2 words and t needs to be n2*2 + */ +void bn_mul_low_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n2, + BN_ULONG *t) + { + int n=n2/2; + +# ifdef BN_COUNT + printf(" bn_mul_low_recursive %d * %d\n",n2,n2); +# endif + + bn_mul_recursive(r,a,b,n,&(t[0])); + if (n >= BN_MUL_LOW_RECURSIVE_SIZE_NORMAL) + { + bn_mul_low_recursive(&(t[0]),&(a[0]),&(b[n]),n,&(t[n2])); + bn_add_words(&(r[n]),&(r[n]),&(t[0]),n); + bn_mul_low_recursive(&(t[0]),&(a[n]),&(b[0]),n,&(t[n2])); + bn_add_words(&(r[n]),&(r[n]),&(t[0]),n); + } + else + { + bn_mul_low_normal(&(t[0]),&(a[0]),&(b[n]),n); + bn_mul_low_normal(&(t[n]),&(a[n]),&(b[0]),n); + bn_add_words(&(r[n]),&(r[n]),&(t[0]),n); + bn_add_words(&(r[n]),&(r[n]),&(t[n]),n); + } + } + +/* a and b must be the same size, which is n2. + * r needs to be n2 words and t needs to be n2*2 + * l is the low words of the output. + * t needs to be n2*3 + */ +void bn_mul_high(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, BN_ULONG *l, int n2, + BN_ULONG *t) + { + int i,n; + int c1,c2; + int neg,oneg,zero; + BN_ULONG ll,lc,*lp,*mp; + +# ifdef BN_COUNT + printf(" bn_mul_high %d * %d\n",n2,n2); +# endif + n=n2/2; + + /* Calculate (al-ah)*(bh-bl) */ + neg=zero=0; + c1=bn_cmp_words(&(a[0]),&(a[n]),n); + c2=bn_cmp_words(&(b[n]),&(b[0]),n); + switch (c1*3+c2) + { + case -4: + bn_sub_words(&(r[0]),&(a[n]),&(a[0]),n); + bn_sub_words(&(r[n]),&(b[0]),&(b[n]),n); + break; + case -3: + zero=1; + break; + case -2: + bn_sub_words(&(r[0]),&(a[n]),&(a[0]),n); + bn_sub_words(&(r[n]),&(b[n]),&(b[0]),n); + neg=1; + break; + case -1: + case 0: + case 1: + zero=1; + break; + case 2: + bn_sub_words(&(r[0]),&(a[0]),&(a[n]),n); + bn_sub_words(&(r[n]),&(b[0]),&(b[n]),n); + neg=1; + break; + case 3: + zero=1; + break; + case 4: + bn_sub_words(&(r[0]),&(a[0]),&(a[n]),n); + bn_sub_words(&(r[n]),&(b[n]),&(b[0]),n); + break; + } + + oneg=neg; + /* t[10] = (a[0]-a[1])*(b[1]-b[0]) */ + /* r[10] = (a[1]*b[1]) */ +# ifdef BN_MUL_COMBA + if (n == 8) + { + bn_mul_comba8(&(t[0]),&(r[0]),&(r[n])); + bn_mul_comba8(r,&(a[n]),&(b[n])); + } + else +# endif + { + bn_mul_recursive(&(t[0]),&(r[0]),&(r[n]),n,&(t[n2])); + bn_mul_recursive(r,&(a[n]),&(b[n]),n,&(t[n2])); + } + + /* s0 == low(al*bl) + * s1 == low(ah*bh)+low((al-ah)*(bh-bl))+low(al*bl)+high(al*bl) + * We know s0 and s1 so the only unknown is high(al*bl) + * high(al*bl) == s1 - low(ah*bh+s0+(al-ah)*(bh-bl)) + * high(al*bl) == s1 - (r[0]+l[0]+t[0]) + */ + if (l != NULL) + { + lp= &(t[n2+n]); + c1=(int)(bn_add_words(lp,&(r[0]),&(l[0]),n)); + } + else + { + c1=0; + lp= &(r[0]); + } + + if (neg) + neg=(int)(bn_sub_words(&(t[n2]),lp,&(t[0]),n)); + else + { + bn_add_words(&(t[n2]),lp,&(t[0]),n); + neg=0; + } + + if (l != NULL) + { + bn_sub_words(&(t[n2+n]),&(l[n]),&(t[n2]),n); + } + else + { + lp= &(t[n2+n]); + mp= &(t[n2]); + for (i=0; i 0) + { + lc=c1; + do { + ll=(r[i]+lc)&BN_MASK2; + r[i++]=ll; + lc=(lc > ll); + } while (lc); + } + else + { + lc= -c1; + do { + ll=r[i]; + r[i++]=(ll-lc)&BN_MASK2; + lc=(lc > ll); + } while (lc); + } + } + if (c2 != 0) /* Add starting at r[1] */ + { + i=n; + if (c2 > 0) + { + lc=c2; + do { + ll=(r[i]+lc)&BN_MASK2; + r[i++]=ll; + lc=(lc > ll); + } while (lc); + } + else + { + lc= -c2; + do { + ll=r[i]; + r[i++]=(ll-lc)&BN_MASK2; + lc=(lc > ll); + } while (lc); + } + } + } +#endif /* BN_RECURSION */ + +int BN_mul(BIGNUM *r, BIGNUM *a, BIGNUM *b, BN_CTX *ctx) + { + int top,al,bl; + BIGNUM *rr; + int ret = 0; +#if defined(BN_MUL_COMBA) || defined(BN_RECURSION) + int i; +#endif +#ifdef BN_RECURSION + BIGNUM *t; + int j,k; +#endif + +#ifdef BN_COUNT + printf("BN_mul %d * %d\n",a->top,b->top); +#endif + + bn_check_top(a); + bn_check_top(b); + bn_check_top(r); + + al=a->top; + bl=b->top; + r->neg=a->neg^b->neg; + + if ((al == 0) || (bl == 0)) + { + BN_zero(r); + return(1); + } + top=al+bl; + + BN_CTX_start(ctx); + if ((r == a) || (r == b)) + { + if ((rr = BN_CTX_get(ctx)) == NULL) goto err; + } + else + rr = r; + +#if defined(BN_MUL_COMBA) || defined(BN_RECURSION) + i = al-bl; +#endif +#ifdef BN_MUL_COMBA + if (i == 0) + { +# if 0 + if (al == 4) + { + if (bn_wexpand(rr,8) == NULL) goto err; + rr->top=8; + bn_mul_comba4(rr->d,a->d,b->d); + goto end; + } +# endif + if (al == 8) + { + if (bn_wexpand(rr,16) == NULL) goto err; + rr->top=16; + bn_mul_comba8(rr->d,a->d,b->d); + goto end; + } + } +#endif /* BN_MUL_COMBA */ +#ifdef BN_RECURSION + if ((al >= BN_MULL_SIZE_NORMAL) && (bl >= BN_MULL_SIZE_NORMAL)) + { + if (i == 1 && !BN_get_flags(b,BN_FLG_STATIC_DATA)) + { + bn_wexpand(b,al); + b->d[bl]=0; + bl++; + i--; + } + else if (i == -1 && !BN_get_flags(a,BN_FLG_STATIC_DATA)) + { + bn_wexpand(a,bl); + a->d[al]=0; + al++; + i++; + } + if (i == 0) + { + /* symmetric and > 4 */ + /* 16 or larger */ + j=BN_num_bits_word((BN_ULONG)al); + j=1<<(j-1); + k=j+j; + t = BN_CTX_get(ctx); + if (al == j) /* exact multiple */ + { + bn_wexpand(t,k*2); + bn_wexpand(rr,k*2); + bn_mul_recursive(rr->d,a->d,b->d,al,t->d); + } + else + { + bn_wexpand(a,k); + bn_wexpand(b,k); + bn_wexpand(t,k*4); + bn_wexpand(rr,k*4); + for (i=a->top; id[i]=0; + for (i=b->top; id[i]=0; + bn_mul_part_recursive(rr->d,a->d,b->d,al-j,j,t->d); + } + rr->top=top; + goto end; + } + } +#endif /* BN_RECURSION */ + if (bn_wexpand(rr,top) == NULL) goto err; + rr->top=top; + bn_mul_normal(rr->d,a->d,al,b->d,bl); + +#if defined(BN_MUL_COMBA) || defined(BN_RECURSION) +end: +#endif + bn_fix_top(rr); + if (r != rr) BN_copy(r,rr); + ret=1; +err: + BN_CTX_end(ctx); + return(ret); + } + +void bn_mul_normal(BN_ULONG *r, BN_ULONG *a, int na, BN_ULONG *b, int nb) + { + BN_ULONG *rr; + +#ifdef BN_COUNT + printf(" bn_mul_normal %d * %d\n",na,nb); +#endif + + if (na < nb) + { + int itmp; + BN_ULONG *ltmp; + + itmp=na; na=nb; nb=itmp; + ltmp=a; a=b; b=ltmp; + + } + rr= &(r[na]); + rr[0]=bn_mul_words(r,a,na,b[0]); + + for (;;) + { + if (--nb <= 0) return; + rr[1]=bn_mul_add_words(&(r[1]),a,na,b[1]); + if (--nb <= 0) return; + rr[2]=bn_mul_add_words(&(r[2]),a,na,b[2]); + if (--nb <= 0) return; + rr[3]=bn_mul_add_words(&(r[3]),a,na,b[3]); + if (--nb <= 0) return; + rr[4]=bn_mul_add_words(&(r[4]),a,na,b[4]); + rr+=4; + r+=4; + b+=4; + } + } + +void bn_mul_low_normal(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n) + { +#ifdef BN_COUNT + printf(" bn_mul_low_normal %d * %d\n",n,n); +#endif + bn_mul_words(r,a,n,b[0]); + + for (;;) + { + if (--n <= 0) return; + bn_mul_add_words(&(r[1]),a,n,b[1]); + if (--n <= 0) return; + bn_mul_add_words(&(r[2]),a,n,b[2]); + if (--n <= 0) return; + bn_mul_add_words(&(r[3]),a,n,b[3]); + if (--n <= 0) return; + bn_mul_add_words(&(r[4]),a,n,b[4]); + r+=4; + b+=4; + } + } diff --git a/libsecurity_apple_csp/open_ssl/bn/bn_prime.c b/libsecurity_apple_csp/open_ssl/bn/bn_prime.c new file mode 100644 index 00000000..a1dad1ec --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/bn/bn_prime.c @@ -0,0 +1,483 @@ +/* + * 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. + */ + + +/* crypto/bn/bn_prime.c */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright (c) 1998-2000 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include +#include +#include "cryptlib.h" +#include "bn_lcl.h" +#include + +/* The quick sieve algorithm approach to weeding out primes is + * Philip Zimmermann's, as implemented in PGP. I have had a read of + * his comments and implemented my own version. + */ +#include "bn_prime.h" + +static int witness(BIGNUM *w, const BIGNUM *a, const BIGNUM *a1, + const BIGNUM *a1_odd, int k, BN_CTX *ctx, BN_MONT_CTX *mont); +static int probable_prime(BIGNUM *rnd, int bits); +static int probable_prime_dh(BIGNUM *rnd, int bits, + BIGNUM *add, BIGNUM *rem, BN_CTX *ctx); +static int probable_prime_dh_safe(BIGNUM *rnd, int bits, + BIGNUM *add, BIGNUM *rem, BN_CTX *ctx); + +BIGNUM *BN_generate_prime(BIGNUM *ret, int bits, int safe, BIGNUM *add, + BIGNUM *rem, void (*callback)(int,int,void *), void *cb_arg) + { + BIGNUM *rnd=NULL; + BIGNUM t; + int found=0; + int i,j,c1=0; + BN_CTX *ctx; + int checks = BN_prime_checks_for_size(bits); + + ctx=BN_CTX_new(); + if (ctx == NULL) goto err; + if (ret == NULL) + { + if ((rnd=BN_new()) == NULL) goto err; + } + else + rnd=ret; + BN_init(&t); +loop: + /* make a random number and set the top and bottom bits */ + if (add == NULL) + { + if (!probable_prime(rnd,bits)) goto err; + } + else + { + if (safe) + { + if (!probable_prime_dh_safe(rnd,bits,add,rem,ctx)) + goto err; + } + else + { + if (!probable_prime_dh(rnd,bits,add,rem,ctx)) + goto err; + } + } + /* if (BN_mod_word(rnd,(BN_ULONG)3) == 1) goto loop; */ + if (callback != NULL) callback(0,c1++,cb_arg); + + if (!safe) + { + i=BN_is_prime_fasttest(rnd,checks,callback,ctx,cb_arg,0); + if (i == -1) goto err; + if (i == 0) goto loop; + } + else + { + /* for "safe prime" generation, + * check that (p-1)/2 is prime. + * Since a prime is odd, We just + * need to divide by 2 */ + if (!BN_rshift1(&t,rnd)) goto err; + + for (i=0; ineg) + { + BIGNUM *t; + if ((t = BN_CTX_get(ctx)) == NULL) goto err; + BN_copy(t, a); + t->neg = 0; + A = t; + } + else + A = a; + A1 = BN_CTX_get(ctx); + A1_odd = BN_CTX_get(ctx); + check = BN_CTX_get(ctx); + if (check == NULL) goto err; + + /* compute A1 := A - 1 */ + if (!BN_copy(A1, A)) + goto err; + if (!BN_sub_word(A1, 1)) + goto err; + if (BN_is_zero(A1)) + { + ret = 0; + goto err; + } + + /* write A1 as A1_odd * 2^k */ + k = 1; + while (!BN_is_bit_set(A1, k)) + k++; + if (!BN_rshift(A1_odd, A1, k)) + goto err; + + /* Montgomery setup for computations mod A */ + mont = BN_MONT_CTX_new(); + if (mont == NULL) + goto err; + if (!BN_MONT_CTX_set(mont, A, ctx)) + goto err; + + for (i = 0; i < checks; i++) + { + if (!BN_pseudo_rand(check, BN_num_bits(A1), 0, 0)) + goto err; + if (BN_cmp(check, A1) >= 0) + if (!BN_sub(check, check, A1)) + goto err; + if (!BN_add_word(check, 1)) + goto err; + /* now 1 <= check < A */ + + j = witness(check, A, A1, A1_odd, k, ctx, mont); + if (j == -1) goto err; + if (j) + { + ret=0; + goto err; + } + if (callback != NULL) callback(1,i,cb_arg); + } + ret=1; +err: + if (ctx != NULL) + { + BN_CTX_end(ctx); + if (ctx_passed == NULL) + BN_CTX_free(ctx); + } + if (mont != NULL) + BN_MONT_CTX_free(mont); + + return(ret); + } + +static int witness(BIGNUM *w, const BIGNUM *a, const BIGNUM *a1, + const BIGNUM *a1_odd, int k, BN_CTX *ctx, BN_MONT_CTX *mont) + { + if (!BN_mod_exp_mont(w, w, a1_odd, a, ctx, mont)) /* w := w^a1_odd mod a */ + return -1; + if (BN_is_one(w)) + return 0; /* probably prime */ + if (BN_cmp(w, a1) == 0) + return 0; /* w == -1 (mod a), 'a' is probably prime */ + while (--k) + { + if (!BN_mod_mul(w, w, w, a, ctx)) /* w := w^2 mod a */ + return -1; + if (BN_is_one(w)) + return 1; /* 'a' is composite, otherwise a previous 'w' would + * have been == -1 (mod 'a') */ + if (BN_cmp(w, a1) == 0) + return 0; /* w == -1 (mod a), 'a' is probably prime */ + } + /* If we get here, 'w' is the (a-1)/2-th power of the original 'w', + * and it is neither -1 nor +1 -- so 'a' cannot be prime */ + return 1; + } + +static int probable_prime(BIGNUM *rnd, int bits) + { + int i; + BN_ULONG mods[NUMPRIMES]; + BN_ULONG delta,d; + +again: + if (!BN_rand(rnd,bits,1,1)) return(0); + /* we now have a random number 'rand' to test. */ + for (i=1; i +#include +#include "cryptlib.h" +#include +#include "bn_lcl.h" + +static const char *Hex="0123456789ABCDEF"; + +/* Must 'Free' the returned data */ +char *BN_bn2hex(const BIGNUM *a) + { + int i,j,v,z=0; + char *buf; + char *p; + + buf=(char *)Malloc(a->top*BN_BYTES*2+2); + if (buf == NULL) + { + BNerr(BN_F_BN_BN2HEX,ERR_R_MALLOC_FAILURE); + goto err; + } + p=buf; + if (a->neg) *(p++)='-'; + if (a->top == 0) *(p++)='0'; + for (i=a->top-1; i >=0; i--) + { + for (j=BN_BITS2-8; j >= 0; j-=8) + { + /* strip leading zeros */ + v=((int)(a->d[i]>>(long)j))&0xff; + if (z || (v != 0)) + { + *(p++)=Hex[v>>4]; + *(p++)=Hex[v&0x0f]; + z=1; + } + } + } + *p='\0'; +err: + return(buf); + } + +/* Must 'Free' the returned data */ +char *BN_bn2dec(const BIGNUM *a) + { + int i=0,num; + char *buf=NULL; + char *p; + BIGNUM *t=NULL; + BN_ULONG *bn_data=NULL,*lp; + + i=BN_num_bits(a)*3; + num=(i/10+i/1000+3)+1; + bn_data=(BN_ULONG *)Malloc((num/BN_DEC_NUM+1)*sizeof(BN_ULONG)); + buf=(char *)Malloc(num+3); + if ((buf == NULL) || (bn_data == NULL)) + { + BNerr(BN_F_BN_BN2DEC,ERR_R_MALLOC_FAILURE); + goto err; + } + if ((t=BN_dup(a)) == NULL) goto err; + + p=buf; + lp=bn_data; + if (t->neg) *(p++)='-'; + if (t->top == 0) + { + *(p++)='0'; + *(p++)='\0'; + } + else + { + i=0; + while (!BN_is_zero(t)) + { + *lp=BN_div_word(t,BN_DEC_CONV); + lp++; + } + lp--; + /* We now have a series of blocks, BN_DEC_NUM chars + * in length, where the last one needs truncation. + * The blocks need to be reversed in order. */ + sprintf(p,BN_DEC_FMT1,*lp); + while (*p) p++; + while (lp != bn_data) + { + lp--; + sprintf(p,BN_DEC_FMT2,*lp); + while (*p) p++; + } + } +err: + if (bn_data != NULL) Free(bn_data); + if (t != NULL) BN_free(t); + return(buf); + } + +int BN_hex2bn(BIGNUM **bn, const char *a) + { + BIGNUM *ret=NULL; + BN_ULONG l=0; + int neg=0,h,m,i,j,k,c; + int num; + + if ((a == NULL) || (*a == '\0')) return(0); + + if (*a == '-') { neg=1; a++; } + + for (i=0; isxdigit((unsigned char) a[i]); i++) + ; + + num=i+neg; + if (bn == NULL) return(num); + + /* a is the start of the hex digits, and it is 'i' long */ + if (*bn == NULL) + { + if ((ret=BN_new()) == NULL) return(0); + } + else + { + ret= *bn; + BN_zero(ret); + } + + /* i is the number of hex digests; */ + if (bn_expand(ret,i*4) == NULL) goto err; + + j=i; /* least significant 'hex' */ + m=0; + h=0; + while (j > 0) + { + m=((BN_BYTES*2) <= j)?(BN_BYTES*2):j; + l=0; + for (;;) + { + c=a[j-m]; + if ((c >= '0') && (c <= '9')) k=c-'0'; + else if ((c >= 'a') && (c <= 'f')) k=c-'a'+10; + else if ((c >= 'A') && (c <= 'F')) k=c-'A'+10; + else k=0; /* paranoia */ + l=(l<<4)|k; + + if (--m <= 0) + { + ret->d[h++]=l; + break; + } + } + j-=(BN_BYTES*2); + } + ret->top=h; + bn_fix_top(ret); + ret->neg=neg; + + *bn=ret; + return(num); +err: + if (*bn == NULL) BN_free(ret); + return(0); + } + +int BN_dec2bn(BIGNUM **bn, const char *a) + { + BIGNUM *ret=NULL; + BN_ULONG l=0; + int neg=0,i,j; + int num; + + if ((a == NULL) || (*a == '\0')) return(0); + if (*a == '-') { neg=1; a++; } + + for (i=0; isdigit((unsigned char) a[i]); i++) + ; + + num=i+neg; + if (bn == NULL) return(num); + + /* a is the start of the digits, and it is 'i' long. + * We chop it into BN_DEC_NUM digits at a time */ + if (*bn == NULL) + { + if ((ret=BN_new()) == NULL) return(0); + } + else + { + ret= *bn; + BN_zero(ret); + } + + /* i is the number of digests, a bit of an over expand; */ + if (bn_expand(ret,i*4) == NULL) goto err; + + j=BN_DEC_NUM-(i%BN_DEC_NUM); + if (j == BN_DEC_NUM) j=0; + l=0; + while (*a) + { + l*=10; + l+= *a-'0'; + a++; + if (++j == BN_DEC_NUM) + { + BN_mul_word(ret,BN_DEC_CONV); + BN_add_word(ret,l); + l=0; + j=0; + } + } + ret->neg=neg; + + bn_fix_top(ret); + *bn=ret; + return(num); +err: + if (*bn == NULL) BN_free(ret); + return(0); + } + +#ifndef NO_BIO +#ifndef NO_FP_API +int BN_print_fp(FILE *fp, const BIGNUM *a) + { + BIO *b; + int ret; + + if ((b=BIO_new(BIO_s_file())) == NULL) + return(0); + BIO_set_fp(b,fp,BIO_NOCLOSE); + ret=BN_print(b,a); + BIO_free(b); + return(ret); + } +#endif + +int BN_print(BIO *bp, const BIGNUM *a) + { + int i,j,v,z=0; + int ret=0; + + if ((a->neg) && (BIO_write(bp,"-",1) != 1)) goto end; + if ((a->top == 0) && (BIO_write(bp,"0",1) != 1)) goto end; + for (i=a->top-1; i >=0; i--) + { + for (j=BN_BITS2-4; j >= 0; j-=4) + { + /* strip leading zeros */ + v=((int)(a->d[i]>>(long)j))&0x0f; + if (z || (v != 0)) + { + if (BIO_write(bp,&(Hex[v]),1) != 1) + goto end; + z=1; + } + } + } + ret=1; +end: + return(ret); + } +#endif + +#ifdef BN_DEBUG +void bn_dump1(FILE *o, const char *a, BN_ULONG *b,int n) + { + int i; + fprintf(o, "%s=", a); + for (i=n-1;i>=0;i--) + fprintf(o, "%08lX", b[i]); /* assumes 32-bit BN_ULONG */ + fprintf(o, "\n"); + } +#endif diff --git a/libsecurity_apple_csp/open_ssl/bn/bn_rand.c b/libsecurity_apple_csp/open_ssl/bn/bn_rand.c new file mode 100644 index 00000000..05eeff1f --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/bn/bn_rand.c @@ -0,0 +1,223 @@ +/* crypto/bn/bn_rand.c */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include +#include +#include "cryptlib.h" +#include "bn_lcl.h" +#include + +static int bnrand(int pseudorand, BIGNUM *rnd, int bits, int top, int bottom) + { + unsigned char *buf=NULL; + int ret=0,bit,bytes,mask; + time_t tim; + + if (bits == 0) + { + BN_zero(rnd); + return 1; + } + + bytes=(bits+7)/8; + bit=(bits-1)%8; + mask=0xff<<(bit+1); + + buf=(unsigned char *)Malloc(bytes); + if (buf == NULL) + { + BNerr(BN_F_BN_RAND,ERR_R_MALLOC_FAILURE); + goto err; + } + + /* make a random number and set the top and bottom bits */ + time(&tim); + RAND_add(&tim,sizeof(tim),0); + + if (pseudorand) + { + if (RAND_pseudo_bytes(buf, bytes) == -1) + goto err; + } + else + { + if (RAND_bytes(buf, bytes) <= 0) + goto err; + } + +#if 1 + if (pseudorand == 2) + { + /* generate patterns that are more likely to trigger BN + library bugs */ + int i; + unsigned char c; + + for (i = 0; i < bytes; i++) + { + RAND_pseudo_bytes(&c, 1); + if (c >= 128 && i > 0) + buf[i] = buf[i-1]; + else if (c < 42) + buf[i] = 0; + else if (c < 84) + buf[i] = 255; + } + } +#endif + + if (top != -1) + { + if (top) + { + if (bit == 0) + { + buf[0]=1; + buf[1]|=0x80; + } + else + { + buf[0]|=(3<<(bit-1)); + } + } + else + { + buf[0]|=(1<neg || BN_is_zero(range)) + { + BNerr(BN_F_BN_RAND_RANGE, BN_R_INVALID_RANGE); + return 0; + } + + n = BN_num_bits(range); /* n > 0 */ + + if (n == 1) + { + if (!BN_zero(r)) return 0; + } + else if (BN_is_bit_set(range, n - 2)) + { + do + { + /* range = 11..._2, so each iteration succeeds with probability >= .75 */ + if (!BN_rand(r, n, -1, 0)) return 0; + } + while (BN_cmp(r, range) >= 0); + } + else + { + /* range = 10..._2, + * so 3*range (= 11..._2) is exactly one bit longer than range */ + do + { + if (!BN_rand(r, n + 1, -1, 0)) return 0; + /* If r < 3*range, use r := r MOD range + * (which is either r, r - range, or r - 2*range). + * Otherwise, iterate once more. + * Since 3*range = 11..._2, each iteration succeeds with + * probability >= .75. */ + if (BN_cmp(r ,range) >= 0) + { + if (!BN_sub(r, r, range)) return 0; + if (BN_cmp(r, range) >= 0) + if (!BN_sub(r, r, range)) return 0; + } + } + while (BN_cmp(r, range) >= 0); + } + + return 1; + } diff --git a/libsecurity_apple_csp/open_ssl/bn/bn_recp.c b/libsecurity_apple_csp/open_ssl/bn/bn_recp.c new file mode 100644 index 00000000..6fc6952a --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/bn/bn_recp.c @@ -0,0 +1,238 @@ +/* + * 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. + */ + + +/* crypto/bn/bn_recp.c */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include +#include "cryptlib.h" +#include "bn_lcl.h" + +void BN_RECP_CTX_init(BN_RECP_CTX *recp) + { + BN_init(&(recp->N)); + BN_init(&(recp->Nr)); + recp->num_bits=0; + recp->flags=0; + } + +BN_RECP_CTX *BN_RECP_CTX_new(void) + { + BN_RECP_CTX *ret; + + if ((ret=(BN_RECP_CTX *)Malloc(sizeof(BN_RECP_CTX))) == NULL) + return(NULL); + + BN_RECP_CTX_init(ret); + ret->flags=BN_FLG_MALLOCED; + return(ret); + } + +void BN_RECP_CTX_free(BN_RECP_CTX *recp) + { + if(recp == NULL) + return; + + BN_free(&(recp->N)); + BN_free(&(recp->Nr)); + if (recp->flags & BN_FLG_MALLOCED) + Free(recp); + } + +int BN_RECP_CTX_set(BN_RECP_CTX *recp, const BIGNUM *d, BN_CTX *ctx) + { + BN_copy(&(recp->N),d); + BN_zero(&(recp->Nr)); + recp->num_bits=BN_num_bits(d); + recp->shift=0; + return(1); + } + +int BN_mod_mul_reciprocal(BIGNUM *r, BIGNUM *x, BIGNUM *y, BN_RECP_CTX *recp, + BN_CTX *ctx) + { + int ret=0; + BIGNUM *a; + + BN_CTX_start(ctx); + if ((a = BN_CTX_get(ctx)) == NULL) goto err; + if (y != NULL) + { + if (x == y) + { if (!BN_sqr(a,x,ctx)) goto err; } + else + { if (!BN_mul(a,x,y,ctx)) goto err; } + } + else + a=x; /* Just do the mod */ + + BN_div_recp(NULL,r,a,recp,ctx); + ret=1; +err: + BN_CTX_end(ctx); + return(ret); + } + +int BN_div_recp(BIGNUM *dv, BIGNUM *rem, BIGNUM *m, BN_RECP_CTX *recp, + BN_CTX *ctx) + { + int i,j,ret=0; + BIGNUM *a,*b,*d,*r; + + BN_CTX_start(ctx); + a=BN_CTX_get(ctx); + b=BN_CTX_get(ctx); + if (dv != NULL) + d=dv; + else + d=BN_CTX_get(ctx); + if (rem != NULL) + r=rem; + else + r=BN_CTX_get(ctx); + if (a == NULL || b == NULL || d == NULL || r == NULL) goto err; + + if (BN_ucmp(m,&(recp->N)) < 0) + { + BN_zero(d); + BN_copy(r,m); + BN_CTX_end(ctx); + return(1); + } + + /* We want the remainder + * Given input of ABCDEF / ab + * we need multiply ABCDEF by 3 digests of the reciprocal of ab + * + */ + i=BN_num_bits(m); + + j=recp->num_bits<<1; + if (j>i) i=j; + j>>=1; + + if (i != recp->shift) + recp->shift=BN_reciprocal(&(recp->Nr),&(recp->N), + i,ctx); + + if (!BN_rshift(a,m,j)) goto err; + if (!BN_mul(b,a,&(recp->Nr),ctx)) goto err; + if (!BN_rshift(d,b,i-j)) goto err; + d->neg=0; + if (!BN_mul(b,&(recp->N),d,ctx)) goto err; + if (!BN_usub(r,m,b)) goto err; + r->neg=0; + +#if 1 + j=0; + while (BN_ucmp(r,&(recp->N)) >= 0) + { + if (j++ > 2) + { + BNerr(BN_F_BN_MOD_MUL_RECIPROCAL,BN_R_BAD_RECIPROCAL); + goto err; + } + if (!BN_usub(r,r,&(recp->N))) goto err; + if (!BN_add_word(d,1)) goto err; + } +#endif + + r->neg=BN_is_zero(r)?0:m->neg; + d->neg=m->neg^recp->N.neg; + ret=1; +err: + BN_CTX_end(ctx); + return(ret); + } + +/* len is the expected size of the result + * We actually calculate with an extra word of precision, so + * we can do faster division if the remainder is not required. + */ +int BN_reciprocal(BIGNUM *r, BIGNUM *m, int len, BN_CTX *ctx) + { + int ret= -1; + BIGNUM t; + + BN_init(&t); + + BN_zero(&t); + if (!BN_set_bit(&t,len)) goto err; + + if (!BN_div(r,NULL,&t,m,ctx)) goto err; + ret=len; +err: + BN_free(&t); + return(ret); + } + diff --git a/libsecurity_apple_csp/open_ssl/bn/bn_shift.c b/libsecurity_apple_csp/open_ssl/bn/bn_shift.c new file mode 100644 index 00000000..879a6757 --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/bn/bn_shift.c @@ -0,0 +1,218 @@ +/* + * 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. + */ + + +/* crypto/bn/bn_shift.c */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include +#include "cryptlib.h" +#include "bn_lcl.h" + +int BN_lshift1(BIGNUM *r, BIGNUM *a) + { + register BN_ULONG *ap,*rp,t,c; + int i; + + if (r != a) + { + r->neg=a->neg; + if (bn_wexpand(r,a->top+1) == NULL) return(0); + r->top=a->top; + } + else + { + if (bn_wexpand(r,a->top+1) == NULL) return(0); + } + ap=a->d; + rp=r->d; + c=0; + for (i=0; itop; i++) + { + t= *(ap++); + *(rp++)=((t<<1)|c)&BN_MASK2; + c=(t & BN_TBIT)?1:0; + } + if (c) + { + *rp=1; + r->top++; + } + return(1); + } + +int BN_rshift1(BIGNUM *r, BIGNUM *a) + { + BN_ULONG *ap,*rp,t,c; + int i; + + if (BN_is_zero(a)) + { + BN_zero(r); + return(1); + } + if (a != r) + { + if (bn_wexpand(r,a->top) == NULL) return(0); + r->top=a->top; + r->neg=a->neg; + } + ap=a->d; + rp=r->d; + c=0; + for (i=a->top-1; i>=0; i--) + { + t=ap[i]; + rp[i]=((t>>1)&BN_MASK2)|c; + c=(t&1)?BN_TBIT:0; + } + bn_fix_top(r); + return(1); + } + +int BN_lshift(BIGNUM *r, const BIGNUM *a, int n) + { + int i,nw,lb,rb; + BN_ULONG *t,*f; + BN_ULONG l; + + r->neg=a->neg; + if (bn_wexpand(r,a->top+(n/BN_BITS2)+1) == NULL) return(0); + nw=n/BN_BITS2; + lb=n%BN_BITS2; + rb=BN_BITS2-lb; + f=a->d; + t=r->d; + t[a->top+nw]=0; + if (lb == 0) + for (i=a->top-1; i>=0; i--) + t[nw+i]=f[i]; + else + for (i=a->top-1; i>=0; i--) + { + l=f[i]; + t[nw+i+1]|=(l>>rb)&BN_MASK2; + t[nw+i]=(l<top=a->top+nw+1; + bn_fix_top(r); + return(1); + } + +int BN_rshift(BIGNUM *r, BIGNUM *a, int n) + { + int i,j,nw,lb,rb; + BN_ULONG *t,*f; + BN_ULONG l,tmp; + + nw=n/BN_BITS2; + rb=n%BN_BITS2; + lb=BN_BITS2-rb; + if (nw > a->top) + { + BN_zero(r); + return(1); + } + if (r != a) + { + r->neg=a->neg; + if (bn_wexpand(r,a->top-nw+1) == NULL) return(0); + } + + f= &(a->d[nw]); + t=r->d; + j=a->top-nw; + r->top=j; + + if (rb == 0) + { + for (i=j+1; i > 0; i--) + *(t++)= *(f++); + } + else + { + l= *(f++); + for (i=1; i>rb)&BN_MASK2; + l= *(f++); + *(t++) =(tmp|(l<>rb)&BN_MASK2; + } + *t=0; + bn_fix_top(r); + return(1); + } diff --git a/libsecurity_apple_csp/open_ssl/bn/bn_sqr.c b/libsecurity_apple_csp/open_ssl/bn/bn_sqr.c new file mode 100644 index 00000000..0c08ced2 --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/bn/bn_sqr.c @@ -0,0 +1,306 @@ +/* + * 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. + */ + + +/* crypto/bn/bn_sqr.c */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include +#include "cryptlib.h" +#include "bn_lcl.h" + +/* r must not be a */ +/* I've just gone over this and it is now %20 faster on x86 - eay - 27 Jun 96 */ +int BN_sqr(BIGNUM *r, BIGNUM *a, BN_CTX *ctx) + { + int max,al; + int ret = 0; + BIGNUM *tmp,*rr; + +#ifdef BN_COUNT +printf("BN_sqr %d * %d\n",a->top,a->top); +#endif + bn_check_top(a); + + al=a->top; + if (al <= 0) + { + r->top=0; + return(1); + } + + BN_CTX_start(ctx); + rr=(a != r) ? r : BN_CTX_get(ctx); + tmp=BN_CTX_get(ctx); + if (tmp == NULL) goto err; + + max=(al+al); + if (bn_wexpand(rr,max+1) == NULL) goto err; + + r->neg=0; + if (al == 4) + { +#ifndef BN_SQR_COMBA + BN_ULONG t[8]; + bn_sqr_normal(rr->d,a->d,4,t); +#else + bn_sqr_comba4(rr->d,a->d); +#endif + } + else if (al == 8) + { +#ifndef BN_SQR_COMBA + BN_ULONG t[16]; + bn_sqr_normal(rr->d,a->d,8,t); +#else + bn_sqr_comba8(rr->d,a->d); +#endif + } + else + { +#if defined(BN_RECURSION) + if (al < BN_SQR_RECURSIVE_SIZE_NORMAL) + { + BN_ULONG t[BN_SQR_RECURSIVE_SIZE_NORMAL*2]; + bn_sqr_normal(rr->d,a->d,al,t); + } + else + { + int j,k; + + j=BN_num_bits_word((BN_ULONG)al); + j=1<<(j-1); + k=j+j; + if (al == j) + { + if (bn_wexpand(a,k*2) == NULL) goto err; + if (bn_wexpand(tmp,k*2) == NULL) goto err; + bn_sqr_recursive(rr->d,a->d,al,tmp->d); + } + else + { + if (bn_wexpand(tmp,max) == NULL) goto err; + bn_sqr_normal(rr->d,a->d,al,tmp->d); + } + } +#else + if (bn_wexpand(tmp,max) == NULL) goto err; + bn_sqr_normal(rr->d,a->d,al,tmp->d); +#endif + } + + rr->top=max; + if ((max > 0) && (rr->d[max-1] == 0)) rr->top--; + if (rr != r) BN_copy(r,rr); + ret = 1; + err: + BN_CTX_end(ctx); + return(ret); + } + +/* tmp must have 2*n words */ +void bn_sqr_normal(BN_ULONG *r, BN_ULONG *a, int n, BN_ULONG *tmp) + { + int i,j,max; + BN_ULONG *ap,*rp; + + max=n*2; + ap=a; + rp=r; + rp[0]=rp[max-1]=0; + rp++; + j=n; + + if (--j > 0) + { + ap++; + rp[j]=bn_mul_words(rp,ap,j,ap[-1]); + rp+=2; + } + + for (i=n-2; i>0; i--) + { + j--; + ap++; + rp[j]=bn_mul_add_words(rp,ap,j,ap[-1]); + rp+=2; + } + + bn_add_words(r,r,r,max); + + /* There will not be a carry */ + + bn_sqr_words(tmp,a,n); + + bn_add_words(r,r,tmp,max); + } + +#ifdef BN_RECURSION +/* r is 2*n words in size, + * a and b are both n words in size. + * n must be a power of 2. + * We multiply and return the result. + * t must be 2*n words in size + * We calculate + * a[0]*b[0] + * a[0]*b[0]+a[1]*b[1]+(a[0]-a[1])*(b[1]-b[0]) + * a[1]*b[1] + */ +void bn_sqr_recursive(BN_ULONG *r, BN_ULONG *a, int n2, BN_ULONG *t) + { + int n=n2/2; + int zero,c1; + BN_ULONG ln,lo,*p; + +#ifdef BN_COUNT +printf(" bn_sqr_recursive %d * %d\n",n2,n2); +#endif + if (n2 == 4) + { +#ifndef BN_SQR_COMBA + bn_sqr_normal(r,a,4,t); +#else + bn_sqr_comba4(r,a); +#endif + return; + } + else if (n2 == 8) + { +#ifndef BN_SQR_COMBA + bn_sqr_normal(r,a,8,t); +#else + bn_sqr_comba8(r,a); +#endif + return; + } + if (n2 < BN_SQR_RECURSIVE_SIZE_NORMAL) + { + bn_sqr_normal(r,a,n2,t); + return; + } + /* r=(a[0]-a[1])*(a[1]-a[0]) */ + c1=bn_cmp_words(a,&(a[n]),n); + zero=0; + if (c1 > 0) + bn_sub_words(t,a,&(a[n]),n); + else if (c1 < 0) + bn_sub_words(t,&(a[n]),a,n); + else + zero=1; + + /* The result will always be negative unless it is zero */ + p= &(t[n2*2]); + + if (!zero) + bn_sqr_recursive(&(t[n2]),t,n,p); + else + memset(&(t[n2]),0,n*sizeof(BN_ULONG)); + bn_sqr_recursive(r,a,n,p); + bn_sqr_recursive(&(r[n2]),&(a[n]),n,p); + + /* t[32] holds (a[0]-a[1])*(a[1]-a[0]), it is negative or zero + * r[10] holds (a[0]*b[0]) + * r[32] holds (b[1]*b[1]) + */ + + c1=(int)(bn_add_words(t,r,&(r[n2]),n2)); + + /* t[32] is negative */ + c1-=(int)(bn_sub_words(&(t[n2]),t,&(t[n2]),n2)); + + /* t[32] holds (a[0]-a[1])*(a[1]-a[0])+(a[0]*a[0])+(a[1]*a[1]) + * r[10] holds (a[0]*a[0]) + * r[32] holds (a[1]*a[1]) + * c1 holds the carry bits + */ + c1+=(int)(bn_add_words(&(r[n]),&(r[n]),&(t[n2]),n2)); + if (c1) + { + p= &(r[n+n2]); + lo= *p; + ln=(lo+c1)&BN_MASK2; + *p=ln; + + /* The overflow will stop before we over write + * words we should not overwrite */ + if (ln < (BN_ULONG)c1) + { + do { + p++; + lo= *p; + ln=(lo+1)&BN_MASK2; + *p=ln; + } while (ln == 0); + } + } + } +#endif diff --git a/libsecurity_apple_csp/open_ssl/bn/bn_word.c b/libsecurity_apple_csp/open_ssl/bn/bn_word.c new file mode 100644 index 00000000..d970d351 --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/bn/bn_word.c @@ -0,0 +1,212 @@ +/* + * 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. + */ + + +/* crypto/bn/bn_word.c */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include +#include "cryptlib.h" +#include "bn_lcl.h" + +BN_ULONG BN_mod_word(const BIGNUM *a, BN_ULONG w) + { +#ifndef BN_LLONG + BN_ULONG ret=0; +#else + BN_ULLONG ret=0; +#endif + int i; + + w&=BN_MASK2; + for (i=a->top-1; i>=0; i--) + { +#ifndef BN_LLONG + ret=((ret<d[i]>>BN_BITS4)&BN_MASK2l))%w; + ret=((ret<d[i]&BN_MASK2l))%w; +#else + ret=(BN_ULLONG)(((ret<<(BN_ULLONG)BN_BITS2)|a->d[i])% + (BN_ULLONG)w); +#endif + } + return((BN_ULONG)ret); + } + +BN_ULONG BN_div_word(BIGNUM *a, BN_ULONG w) + { + BN_ULONG ret; + int i; + + if (a->top == 0) return(0); + ret=0; + w&=BN_MASK2; + for (i=a->top-1; i>=0; i--) + { + BN_ULONG l,d; + + l=a->d[i]; + d=bn_div_words(ret,l,w); + ret=(l-((d*w)&BN_MASK2))&BN_MASK2; + a->d[i]=d; + } + if ((a->top > 0) && (a->d[a->top-1] == 0)) + a->top--; + return(ret); + } + +int BN_add_word(BIGNUM *a, BN_ULONG w) + { + BN_ULONG l; + int i; + + if (a->neg) + { + a->neg=0; + i=BN_sub_word(a,w); + if (!BN_is_zero(a)) + a->neg=1; + return(i); + } + w&=BN_MASK2; + if (bn_wexpand(a,a->top+1) == NULL) return(0); + i=0; + for (;;) + { + l=(a->d[i]+(BN_ULONG)w)&BN_MASK2; + a->d[i]=l; + if (w > l) + w=1; + else + break; + i++; + } + if (i >= a->top) + a->top++; + return(1); + } + +int BN_sub_word(BIGNUM *a, BN_ULONG w) + { + int i; + + if (a->neg) + { + a->neg=0; + i=BN_add_word(a,w); + a->neg=1; + return(i); + } + + w&=BN_MASK2; + if ((a->top == 1) && (a->d[0] < w)) + { + a->d[0]=w-a->d[0]; + a->neg=1; + return(1); + } + i=0; + for (;;) + { + if (a->d[i] >= w) + { + a->d[i]-=w; + break; + } + else + { + a->d[i]=(a->d[i]-w)&BN_MASK2; + i++; + w=1; + } + } + if ((a->d[i] == 0) && (i == (a->top-1))) + a->top--; + return(1); + } + +int BN_mul_word(BIGNUM *a, BN_ULONG w) + { + BN_ULONG ll; + + w&=BN_MASK2; + if (a->top) + { + ll=bn_mul_words(a->d,a->d,a->top,w); + if (ll) + { + if (bn_wexpand(a,a->top+1) == NULL) return(0); + a->d[a->top++]=ll; + } + } + return(1); + } + diff --git a/libsecurity_apple_csp/open_ssl/bn/bnspeed.c b/libsecurity_apple_csp/open_ssl/bn/bnspeed.c new file mode 100644 index 00000000..41b47b06 --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/bn/bnspeed.c @@ -0,0 +1,251 @@ +/* + * 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. + */ + + +/* unused */ + +/* crypto/bn/bnspeed.c */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +/* most of this code has been pilfered from my libdes speed.c program */ + +#define BASENUM 1000000 +#undef PROG +#define PROG bnspeed_main + +#include +#include +#include +#include +#include +#include + +#if !defined(MSDOS) && (!defined(VMS) || defined(__DECC)) +#define TIMES +#endif + +#ifndef _IRIX +#include +#endif +#ifdef TIMES +#include +#include +#endif + +/* Depending on the VMS version, the tms structure is perhaps defined. + The __TMS macro will show if it was. If it wasn't defined, we should + undefine TIMES, since that tells the rest of the program how things + should be handled. -- Richard Levitte */ +#if defined(VMS) && defined(__DECC) && !defined(__TMS) +#undef TIMES +#endif + +#ifndef TIMES +#include +#endif + +#if defined(sun) || defined(__ultrix) +#define _POSIX_SOURCE +#include +#include +#endif + +#include +#include + +/* The following if from times(3) man page. It may need to be changed */ +#ifndef HZ +# ifndef CLK_TCK +# ifndef _BSD_CLK_TCK_ /* FreeBSD hack */ +# define HZ 100.0 +# else /* _BSD_CLK_TCK_ */ +# define HZ ((double)_BSD_CLK_TCK_) +# endif +# else /* CLK_TCK */ +# define HZ ((double)CLK_TCK) +# endif +#endif + +#undef BUFSIZE +#define BUFSIZE ((long)1024*8) +int run=0; + +static double Time_F(int s); +#define START 0 +#define STOP 1 + +static double Time_F(int s) + { + double ret; +#ifdef TIMES + static struct tms tstart,tend; + + if (s == START) + { + times(&tstart); + return(0); + } + else + { + times(&tend); + ret=((double)(tend.tms_utime-tstart.tms_utime))/HZ; + return((ret < 1e-3)?1e-3:ret); + } +#else /* !times() */ + static struct timeb tstart,tend; + long i; + + if (s == START) + { + ftime(&tstart); + return(0); + } + else + { + ftime(&tend); + i=(long)tend.millitm-(long)tstart.millitm; + ret=((double)(tend.time-tstart.time))+((double)i)/1000.0; + return((ret < 0.001)?0.001:ret); + } +#endif + } + +#define NUM_SIZES 5 +static int sizes[NUM_SIZES]={128,256,512,1024,2048}; +/*static int sizes[NUM_SIZES]={59,179,299,419,539}; */ + +void do_mul(BIGNUM *r,BIGNUM *a,BIGNUM *b,BN_CTX *ctx); + +int main(int argc, char **argv) + { + BN_CTX *ctx; + BIGNUM a,b,c; + + ctx=BN_CTX_new(); + BN_init(&a); + BN_init(&b); + BN_init(&c); + + do_mul(&a,&b,&c,ctx); + } + +void do_mul(BIGNUM *r, BIGNUM *a, BIGNUM *b, BN_CTX *ctx) + { + int i,j,k; + double tm; + long num; + + for (i=0; i %8.3fms\n",sizes[i],sizes[j],tm*1000.0/num); + } + } + + for (i=0; i %8.3fms\n",sizes[i],sizes[i],tm*1000.0/num); + } + + for (i=0; i %8.3fms\n",sizes[j],sizes[i]-1,tm*1000.0/num); + } + } + } + diff --git a/libsecurity_apple_csp/open_ssl/bn/bntest.c b/libsecurity_apple_csp/open_ssl/bn/bntest.c new file mode 100644 index 00000000..4549814f --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/bn/bntest.c @@ -0,0 +1,1096 @@ +/* + * 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. + */ + + +/* crypto/bn/bntest.c */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include +#include +#include + +#include "openssl/e_os.h" + +#include +#include +#include +#include +#include + +#ifdef WINDOWS +#include "../bio/bss_file.c" +#endif + +const int num0 = 100; /* number of tests */ +const int num1 = 50; /* additional tests for some functions */ +const int num2 = 5; /* number of tests for slow functions */ + +int test_add(BIO *bp); +int test_sub(BIO *bp); +int test_lshift1(BIO *bp); +int test_lshift(BIO *bp,BN_CTX *ctx,BIGNUM *a_); +int test_rshift1(BIO *bp); +int test_rshift(BIO *bp,BN_CTX *ctx); +int test_div(BIO *bp,BN_CTX *ctx); +int test_div_recp(BIO *bp,BN_CTX *ctx); +int test_mul(BIO *bp); +int test_sqr(BIO *bp,BN_CTX *ctx); +int test_mont(BIO *bp,BN_CTX *ctx); +int test_mod(BIO *bp,BN_CTX *ctx); +int test_mod_mul(BIO *bp,BN_CTX *ctx); +int test_mod_exp(BIO *bp,BN_CTX *ctx); +int test_exp(BIO *bp,BN_CTX *ctx); +int rand_neg(void); +static int results=0; + +#ifdef NO_STDIO +#define APPS_WIN16 +#include "bss_file.c" +#endif + +static unsigned char lst[]="\xC6\x4F\x43\x04\x2A\xEA\xCA\x6E\x58\x36\x80\x5B\xE8\xC9" +"\x9B\x04\x5D\x48\x36\xC2\xFD\x16\xC9\x64\xF0"; + +static const char rnd_seed[] = "string to make the random number generator think it has entropy"; + +static void message(BIO *out, char *m) + { + fprintf(stderr, "test %s\n", m); +#if defined(linux) || defined(__FreeBSD__) /* can we use GNU bc features? */ + BIO_puts(out, "print \"test "); + BIO_puts(out, m); + BIO_puts(out, "\\n\"\n"); +#endif + } + +int main(int argc, char *argv[]) + { + BN_CTX *ctx; + BIO *out; + char *outfile=NULL; + + results = 0; + + RAND_seed(rnd_seed, sizeof rnd_seed); /* or BN_rand may fail, and we don't + * even check its return value + * (which we should) */ + + argc--; + argv++; + while (argc >= 1) + { + if (strcmp(*argv,"-results") == 0) + results=1; + else if (strcmp(*argv,"-out") == 0) + { + if (--argc < 1) break; + outfile= *(++argv); + } + argc--; + argv++; + } + + + ctx=BN_CTX_new(); + if (ctx == NULL) exit(1); + + out=BIO_new(BIO_s_file()); + if (out == NULL) exit(1); + if (outfile == NULL) + { + BIO_set_fp(out,stdout,BIO_NOCLOSE); + } + else + { + if (!BIO_write_filename(out,outfile)) + { + perror(outfile); + exit(1); + } + } + + if (!results) + BIO_puts(out,"obase=16\nibase=16\n"); + + message(out,"BN_add"); + if (!test_add(out)) goto err; + BIO_flush(out); + + message(out,"BN_sub"); + if (!test_sub(out)) goto err; + BIO_flush(out); + + message(out,"BN_lshift1"); + if (!test_lshift1(out)) goto err; + BIO_flush(out); + + message(out,"BN_lshift (fixed)"); + if (!test_lshift(out,ctx,BN_bin2bn(lst,sizeof(lst)-1,NULL))) + goto err; + BIO_flush(out); + + message(out,"BN_lshift"); + if (!test_lshift(out,ctx,NULL)) goto err; + BIO_flush(out); + + message(out,"BN_rshift1"); + if (!test_rshift1(out)) goto err; + BIO_flush(out); + + message(out,"BN_rshift"); + if (!test_rshift(out,ctx)) goto err; + BIO_flush(out); + + message(out,"BN_sqr"); + if (!test_sqr(out,ctx)) goto err; + BIO_flush(out); + + message(out,"BN_mul"); + if (!test_mul(out)) goto err; + BIO_flush(out); + + message(out,"BN_div"); + if (!test_div(out,ctx)) goto err; + BIO_flush(out); + + message(out,"BN_div_recp"); + if (!test_div_recp(out,ctx)) goto err; + BIO_flush(out); + + message(out,"BN_mod"); + if (!test_mod(out,ctx)) goto err; + BIO_flush(out); + + message(out,"BN_mod_mul"); + if (!test_mod_mul(out,ctx)) goto err; + BIO_flush(out); + + message(out,"BN_mont"); + if (!test_mont(out,ctx)) goto err; + BIO_flush(out); + + message(out,"BN_mod_exp"); + if (!test_mod_exp(out,ctx)) goto err; + BIO_flush(out); + + message(out,"BN_exp"); + if (!test_exp(out,ctx)) goto err; + BIO_flush(out); + + BN_CTX_free(ctx); + BIO_free(out); + +/**/ + exit(0); +err: + BIO_puts(out,"1\n"); /* make sure the Perl script fed by bc notices + * the failure, see test_bn in test/Makefile.ssl*/ + BIO_flush(out); + ERR_load_crypto_strings(); + ERR_print_errors_fp(stderr); + exit(1); + return(1); + } + +int test_add(BIO *bp) + { + BIGNUM a,b,c; + int i; + int j; + + BN_init(&a); + BN_init(&b); + BN_init(&c); + + BN_rand(&a,512,0,0); + for (i=0; iN)); +#endif + BN_print(bp,&a); + BIO_puts(bp," * "); + BN_print(bp,&b); + BIO_puts(bp," % "); + BN_print(bp,&(mont->N)); + BIO_puts(bp," - "); + } + BN_print(bp,&A); + BIO_puts(bp,"\n"); + } + BN_mod_mul(&d,&a,&b,&n,ctx); + BN_sub(&d,&d,&A); + if(!BN_is_zero(&d)) + { + fprintf(stderr,"Montgomery multiplication test failed!\n"); + return 0; + } + } + BN_MONT_CTX_free(mont); + BN_free(&a); + BN_free(&b); + BN_free(&c); + BN_free(&d); + BN_free(&A); + BN_free(&B); + BN_free(&n); + return(1); + } + +int test_mod(BIO *bp, BN_CTX *ctx) + { + BIGNUM *a,*b,*c,*d,*e; + int i; + int j; + + a=BN_new(); + b=BN_new(); + c=BN_new(); + d=BN_new(); + e=BN_new(); + + BN_rand(a,1024,0,0); /**/ + for (i=0; ineg=rand_neg(); + b->neg=rand_neg(); + if (bp == NULL) + for (j=0; j<100; j++) + BN_mod(c,a,b,ctx);/**/ + BN_mod(c,a,b,ctx);/**/ + if (bp != NULL) + { + if (!results) + { + BN_print(bp,a); + BIO_puts(bp," % "); + BN_print(bp,b); + BIO_puts(bp," - "); + } + BN_print(bp,c); + BIO_puts(bp,"\n"); + } + BN_div(d,e,a,b,ctx); + BN_sub(e,e,c); + if(!BN_is_zero(e)) + { + fprintf(stderr,"Modulo test failed!\n"); + return 0; + } + } + BN_free(a); + BN_free(b); + BN_free(c); + BN_free(d); + BN_free(e); + return(1); + } + +int test_mod_mul(BIO *bp, BN_CTX *ctx) + { + BIGNUM *a,*b,*c,*d,*e; + int i; + + a=BN_new(); + b=BN_new(); + c=BN_new(); + d=BN_new(); + e=BN_new(); + + BN_rand(c,1024,0,0); /**/ + for (i=0; ineg=rand_neg(); + b->neg=rand_neg(); + /* if (bp == NULL) + for (j=0; j<100; j++) + BN_mod_mul(d,a,b,c,ctx);*/ /**/ + + if (!BN_mod_mul(e,a,b,c,ctx)) + { + unsigned long l; + + while ((l=ERR_get_error())) + fprintf(stderr,"ERROR:%s\n", + ERR_error_string(l,NULL)); + exit(1); + } + if (bp != NULL) + { + if (!results) + { + BN_print(bp,a); + BIO_puts(bp," * "); + BN_print(bp,b); + BIO_puts(bp," % "); + BN_print(bp,c); + BIO_puts(bp," - "); + } + BN_print(bp,e); + BIO_puts(bp,"\n"); + } + BN_mul(d,a,b,ctx); + BN_sub(d,d,e); + BN_div(a,b,d,c,ctx); + if(!BN_is_zero(b)) + { + fprintf(stderr,"Modulo multiply test failed!\n"); + return 0; + } + } + BN_free(a); + BN_free(b); + BN_free(c); + BN_free(d); + BN_free(e); + return(1); + } + +int test_mod_exp(BIO *bp, BN_CTX *ctx) + { + BIGNUM *a,*b,*c,*d,*e; + int i; + + a=BN_new(); + b=BN_new(); + c=BN_new(); + d=BN_new(); + e=BN_new(); + + BN_rand(c,30,0,1); /* must be odd for montgomery */ + for (i=0; ineg=rand_neg(); + } + for (i=0; ineg=rand_neg(); + for (i=0; ineg=rand_neg(); + for (i=0; ineg=rand_neg(); + for (i=0; i +#include + +static int rand(n) +{ + unsigned char x[2]; + RAND_pseudo_bytes(x,2); + return (x[0] + 2*x[1]); +} + +static void bug(char *m, BIGNUM *a, BIGNUM *b) +{ + printf("%s!\na=",m); + BN_print_fp(stdout, a); + printf("\nb="); + BN_print_fp(stdout, b); + printf("\n"); + fflush(stdout); +} + +main() +{ + BIGNUM *a=BN_new(), *b=BN_new(), *c=BN_new(), *d=BN_new(), + *C=BN_new(), *D=BN_new(); + BN_RECP_CTX *recp=BN_RECP_CTX_new(); + BN_CTX *ctx=BN_CTX_new(); + + for(;;) { + BN_pseudo_rand(a,rand(),0,0); + BN_pseudo_rand(b,rand(),0,0); + if (BN_is_zero(b)) continue; + + BN_RECP_CTX_set(recp,b,ctx); + if (BN_div(C,D,a,b,ctx) != 1) + bug("BN_div failed",a,b); + if (BN_div_recp(c,d,a,recp,ctx) != 1) + bug("BN_div_recp failed",a,b); + else if (BN_cmp(c,C) != 0 || BN_cmp(c,C) != 0) + bug("mismatch",a,b); + } +} diff --git a/libsecurity_apple_csp/open_ssl/bn/exp.c b/libsecurity_apple_csp/open_ssl/bn/exp.c new file mode 100644 index 00000000..7daec41d --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/bn/exp.c @@ -0,0 +1,80 @@ +/* + * 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. + */ + + +/* unused */ + +#include +#include +#include "bn_lcl.h" + +#define SIZE 256 +#define NUM (8*8*8) +#define MOD (8*8*8*8*8) + +main(argc,argv) +int argc; +char *argv[]; + { + BN_CTX ctx; + BIGNUM a,b,c,r,rr,t,l; + int j,i,size=SIZE,num=NUM,mod=MOD; + char *start,*end; + BN_MONT_CTX mont; + double d,md; + + BN_MONT_CTX_init(&mont); + BN_CTX_init(&ctx); + BN_init(&a); + BN_init(&b); + BN_init(&c); + BN_init(&r); + + start=ms_time_new(); + end=ms_time_new(); + while (size <= 1024*8) + { + BN_rand(&a,size,0,0); + BN_rand(&b,size,1,0); + BN_rand(&c,size,0,1); + + BN_mod(&a,&a,&c,&ctx); + + ms_time_get(start); + for (i=0; i<10; i++) + BN_MONT_CTX_set(&mont,&c,&ctx); + ms_time_get(end); + md=ms_time_diff(start,end); + + ms_time_get(start); + for (i=0; i +#include +#include +#include +#include +#include + +#if !defined(MSDOS) && (!defined(VMS) || defined(__DECC)) +#define TIMES +#endif + +#ifndef _IRIX +#include +#endif +#ifdef TIMES +#include +#include +#endif + +/* Depending on the VMS version, the tms structure is perhaps defined. + The __TMS macro will show if it was. If it wasn't defined, we should + undefine TIMES, since that tells the rest of the program how things + should be handled. -- Richard Levitte */ +#if defined(VMS) && defined(__DECC) && !defined(__TMS) +#undef TIMES +#endif + +#ifndef TIMES +#include +#endif + +#if defined(sun) || defined(__ultrix) +#define _POSIX_SOURCE +#include +#include +#endif + +#include +#include + +/* The following if from times(3) man page. It may need to be changed */ +#ifndef HZ +# ifndef CLK_TCK +# ifndef _BSD_CLK_TCK_ /* FreeBSD hack */ +# define HZ 100.0 +# else /* _BSD_CLK_TCK_ */ +# define HZ ((double)_BSD_CLK_TCK_) +# endif +# else /* CLK_TCK */ +# define HZ ((double)CLK_TCK) +# endif +#endif + +#undef BUFSIZE +#define BUFSIZE ((long)1024*8) +int run=0; + +static double Time_F(int s); +#define START 0 +#define STOP 1 + +static double Time_F(int s) + { + double ret; +#ifdef TIMES + static struct tms tstart,tend; + + if (s == START) + { + times(&tstart); + return(0); + } + else + { + times(&tend); + ret=((double)(tend.tms_utime-tstart.tms_utime))/HZ; + return((ret < 1e-3)?1e-3:ret); + } +#else /* !times() */ + static struct timeb tstart,tend; + long i; + + if (s == START) + { + ftime(&tstart); + return(0); + } + else + { + ftime(&tend); + i=(long)tend.millitm-(long)tstart.millitm; + ret=((double)(tend.time-tstart.time))+((double)i)/1000.0; + return((ret < 0.001)?0.001:ret); + } +#endif + } + +#define NUM_SIZES 6 +static int sizes[NUM_SIZES]={256,512,1024,2048,4096,8192}; +static int mul_c[NUM_SIZES]={8*8*8*8*8,8*8*8*8,8*8*8,8*8,8,1}; +/*static int sizes[NUM_SIZES]={59,179,299,419,539}; */ + +void do_mul_exp(BIGNUM *r,BIGNUM *a,BIGNUM *b,BIGNUM *c,BN_CTX *ctx); + +int main(int argc, char **argv) + { + BN_CTX *ctx; + BIGNUM *a,*b,*c,*r; + + ctx=BN_CTX_new(); + a=BN_new(); + b=BN_new(); + c=BN_new(); + r=BN_new(); + + do_mul_exp(r,a,b,c,ctx); + } + +void do_mul_exp(BIGNUM *r, BIGNUM *a, BIGNUM *b, BIGNUM *c, BN_CTX *ctx) + { + int i,k; + double tm; + long num; + BN_MONT_CTX m; + + memset(&m,0,sizeof(m)); + + num=BASENUM; + for (i=0; i %8.3fms %5.1f\n",sizes[i],sizes[i],sizes[i],tm*1000.0/num,tm*mul_c[i]/num); + num/=7; + if (num <= 0) num=1; + } + + } + diff --git a/libsecurity_apple_csp/open_ssl/bn/exptest.c b/libsecurity_apple_csp/open_ssl/bn/exptest.c new file mode 100644 index 00000000..92ce6b00 --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/bn/exptest.c @@ -0,0 +1,205 @@ +/* + * 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. + */ + + +/* crypto/bn/exptest.c */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include +#include +#include +#include +#include +#include +#include +#ifdef WINDOWS +#include "../bio/bss_file.c" +#endif + +#define NUM_BITS (BN_BITS*2) + +static const char rnd_seed[] = "string to make the random number generator think it has entropy"; + +int main(int argc, char *argv[]) + { + BN_CTX *ctx; + BIO *out=NULL; + int i,ret; + unsigned char c; + BIGNUM *r_mont,*r_recp,*r_simple,*a,*b,*m; + + RAND_seed(rnd_seed, sizeof rnd_seed); /* or BN_rand may fail, and we don't + * even check its return value + * (which we should) */ + + ERR_load_BN_strings(); + + ctx=BN_CTX_new(); + if (ctx == NULL) exit(1); + r_mont=BN_new(); + r_recp=BN_new(); + r_simple=BN_new(); + a=BN_new(); + b=BN_new(); + m=BN_new(); + if ( (r_mont == NULL) || (r_recp == NULL) || + (a == NULL) || (b == NULL)) + goto err; + + out=BIO_new(BIO_s_file()); + + if (out == NULL) exit(1); + BIO_set_fp(out,stdout,BIO_NOCLOSE); + + for (i=0; i<200; i++) + { + RAND_bytes(&c,1); + c=(c%BN_BITS)-BN_BITS2; + BN_rand(a,NUM_BITS+c,0,0); + + RAND_bytes(&c,1); + c=(c%BN_BITS)-BN_BITS2; + BN_rand(b,NUM_BITS+c,0,0); + + RAND_bytes(&c,1); + c=(c%BN_BITS)-BN_BITS2; + BN_rand(m,NUM_BITS+c,0,1); + + BN_mod(a,a,m,ctx); + BN_mod(b,b,m,ctx); + + ret=BN_mod_exp_mont(r_mont,a,b,m,ctx,NULL); + if (ret <= 0) + { + printf("BN_mod_exp_mont() problems\n"); + ERR_print_errors(out); + exit(1); + } + + ret=BN_mod_exp_recp(r_recp,a,b,m,ctx); + if (ret <= 0) + { + printf("BN_mod_exp_recp() problems\n"); + ERR_print_errors(out); + exit(1); + } + + ret=BN_mod_exp_simple(r_simple,a,b,m,ctx); + if (ret <= 0) + { + printf("BN_mod_exp_simple() problems\n"); + ERR_print_errors(out); + exit(1); + } + + if (BN_cmp(r_simple, r_mont) == 0 + && BN_cmp(r_simple,r_recp) == 0) + { + printf("."); + fflush(stdout); + } + else + { + if (BN_cmp(r_simple,r_mont) != 0) + printf("\nsimple and mont results differ\n"); + if (BN_cmp(r_simple,r_recp) != 0) + printf("\nsimple and recp results differ\n"); + + printf("a (%3d) = ",BN_num_bits(a)); BN_print(out,a); + printf("\nb (%3d) = ",BN_num_bits(b)); BN_print(out,b); + printf("\nm (%3d) = ",BN_num_bits(m)); BN_print(out,m); + printf("\nsimple ="); BN_print(out,r_simple); + printf("\nrecp ="); BN_print(out,r_recp); + printf("\nmont ="); BN_print(out,r_mont); + printf("\n"); + exit(1); + } + } + BN_free(r_mont); + BN_free(r_recp); + BN_free(r_simple); + BN_free(a); + BN_free(b); + BN_free(m); + BN_CTX_free(ctx); + ERR_remove_state(0); + CRYPTO_mem_leaks(out); + BIO_free(out); + printf(" done\n"); + exit(0); +err: + ERR_load_crypto_strings(); + ERR_print_errors(out); + exit(1); + return(1); + } + diff --git a/libsecurity_apple_csp/open_ssl/bn/vms-helper.c b/libsecurity_apple_csp/open_ssl/bn/vms-helper.c new file mode 100644 index 00000000..f0ec672a --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/bn/vms-helper.c @@ -0,0 +1,84 @@ +/* + * 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. + */ + + +/* vms-helper.c */ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include +#include "cryptlib.h" +#include "bn_lcl.h" + +bn_div_words_abort(int i) +{ +#if !defined(NO_STDIO) && !defined(WIN16) + fprintf(stderr,"Division would overflow (%d)\n",i); +#endif + abort(); +} diff --git a/libsecurity_apple_csp/open_ssl/buffer/buf_err.c b/libsecurity_apple_csp/open_ssl/buffer/buf_err.c new file mode 100644 index 00000000..223547fd --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/buffer/buf_err.c @@ -0,0 +1,113 @@ +/* + * 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. + */ + + +/* crypto/buffer/buf_err.c */ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +/* NOTE: this file was auto generated by the mkerr.pl script: any changes + * made to it will be overwritten when the script next updates this file, + * only reason strings will be preserved. + */ + +#include +#include +#include + +/* BEGIN ERROR CODES */ +#ifndef NO_ERR +static ERR_STRING_DATA BUF_str_functs[]= + { +{ERR_PACK(0,BUF_F_BUF_MEM_GROW,0), "BUF_MEM_grow"}, +{ERR_PACK(0,BUF_F_BUF_MEM_NEW,0), "BUF_MEM_new"}, +{ERR_PACK(0,BUF_F_BUF_STRDUP,0), "BUF_strdup"}, +{0,NULL} + }; + +static ERR_STRING_DATA BUF_str_reasons[]= + { +{0,NULL} + }; + +#endif + +void ERR_load_BUF_strings(void) + { + static int init=1; + + if (init) + { + init=0; +#ifndef NO_ERR + ERR_load_strings(ERR_LIB_BUF,BUF_str_functs); + ERR_load_strings(ERR_LIB_BUF,BUF_str_reasons); +#endif + + } + } diff --git a/libsecurity_apple_csp/open_ssl/buffer/buffer.c b/libsecurity_apple_csp/open_ssl/buffer/buffer.c new file mode 100644 index 00000000..5fa4d11d --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/buffer/buffer.c @@ -0,0 +1,162 @@ +/* + * 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. + */ + + +/* crypto/buffer/buffer.c */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include +#include "cryptlib.h" +#include + +BUF_MEM *BUF_MEM_new(void) + { + BUF_MEM *ret; + + ret=Malloc(sizeof(BUF_MEM)); + if (ret == NULL) + { + BUFerr(BUF_F_BUF_MEM_NEW,ERR_R_MALLOC_FAILURE); + return(NULL); + } + ret->length=0; + ret->max=0; + ret->data=NULL; + return(ret); + } + +void BUF_MEM_free(BUF_MEM *a) + { + if(a == NULL) + return; + + if (a->data != NULL) + { + memset(a->data,0,(unsigned int)a->max); + Free(a->data); + } + Free(a); + } + +int BUF_MEM_grow(BUF_MEM *str, int len) + { + char *ret; + unsigned int n; + + if (str->length >= len) + { + str->length=len; + return(len); + } + if (str->max >= len) + { + memset(&str->data[str->length],0,len-str->length); + str->length=len; + return(len); + } + n=(len+3)/3*4; + if (str->data == NULL) + ret=Malloc(n); + else + ret=Realloc(str->data,n); + if (ret == NULL) + { + BUFerr(BUF_F_BUF_MEM_GROW,ERR_R_MALLOC_FAILURE); + len=0; + } + else + { + str->data=ret; + str->length=len; + str->max=n; + } + return(len); + } + +char *BUF_strdup(const char *str) + { + char *ret; + int n; + + if (str == NULL) return(NULL); + + n=strlen(str); + ret=Malloc(n+1); + if (ret == NULL) + { + BUFerr(BUF_F_BUF_STRDUP,ERR_R_MALLOC_FAILURE); + return(NULL); + } + memcpy(ret,str,n+1); + return(ret); + } + diff --git a/libsecurity_apple_csp/open_ssl/cryptlib.c b/libsecurity_apple_csp/open_ssl/cryptlib.c new file mode 100644 index 00000000..50255293 --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/cryptlib.c @@ -0,0 +1,350 @@ +/* + * 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. + */ + + +/* crypto/cryptlib.c */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include +#include +#include "cryptlib.h" +#include + +#if defined(WIN32) || defined(WIN16) +static double SSLeay_MSVC5_hack=0.0; /* and for VC1.5 */ +#endif + +/* real #defines in crypto.h, keep these upto date */ +#if defined(LOCK_DEBUG) +static const char* const lock_names[CRYPTO_NUM_LOCKS] = + { + "<>", + "err", + "err_hash", + "x509", + "x509_info", + "x509_pkey", + "x509_crl", + "x509_req", + "dsa", + "rsa", + "evp_pkey", + "x509_store", + "ssl_ctx", + "ssl_cert", + "ssl_session", + "ssl_sess_cert", + "ssl", + "rand", + "debug_malloc", + "BIO", + "gethostbyname", + "getservbyname", + "readdir", + "RSA_blinding", + "dh", + "debug_malloc2", +#if CRYPTO_NUM_LOCKS != 26 +# error "Inconsistency between crypto.h and cryptlib.c" +#endif + }; +#endif /*LOCK_DEBUG*/ + +static STACK *app_locks=NULL; + +#if CRYPTO_CALLBACK_ENABLE +static void (MS_FAR *locking_callback)(int mode,int type, + const char *file,int line)=NULL; +static int (MS_FAR *add_lock_callback)(int *pointer,int amount, + int type,const char *file,int line)=NULL; +static unsigned long (MS_FAR *id_callback)(void)=NULL; +#endif /* CRYPTO_CALLBACK_ENABLE */ + +int CRYPTO_get_new_lockid(char *name) + { + char *str; + int i; + + /* A hack to make Visual C++ 5.0 work correctly when linking as + * a DLL using /MT. Without this, the application cannot use + * and floating point printf's. + * It also seems to be needed for Visual C 1.5 (win16) */ +#if defined(WIN32) || defined(WIN16) + SSLeay_MSVC5_hack=(double)name[0]*(double)name[1]; +#endif + + if ((app_locks == NULL) && ((app_locks=sk_new_null()) == NULL)) + { + CRYPTOerr(CRYPTO_F_CRYPTO_GET_NEW_LOCKID,ERR_R_MALLOC_FAILURE); + return(0); + } + if ((str=BUF_strdup(name)) == NULL) + return(0); + i=sk_push(app_locks,str); + if (!i) + Free(str); + else + i+=CRYPTO_NUM_LOCKS; /* gap of one :-) */ + return(i); + } + +int CRYPTO_num_locks(void) + { + return CRYPTO_NUM_LOCKS; + } + +void (*CRYPTO_get_locking_callback(void))(int mode,int type,const char *file, + int line) + { + #if CRYPTO_CALLBACK_ENABLE + return(locking_callback); + #else + return NULL; + #endif + } + +int (*CRYPTO_get_add_lock_callback(void))(int *num,int mount,int type, + const char *file,int line) + { + #if CRYPTO_CALLBACK_ENABLE + return(add_lock_callback); + #else + return NULL; + #endif + } + +void CRYPTO_set_locking_callback(void (*func)(int mode,int type, + const char *file,int line)) + { + #if CRYPTO_CALLBACK_ENABLE + locking_callback=func; + #endif + } + +void CRYPTO_set_add_lock_callback(int (*func)(int *num,int mount,int type, + const char *file,int line)) + { + #if CRYPTO_CALLBACK_ENABLE + add_lock_callback=func; + #endif + } + +unsigned long (*CRYPTO_get_id_callback(void))(void) + { + #if CRYPTO_CALLBACK_ENABLE + return(id_callback); + #else + return NULL; + #endif + } + +void CRYPTO_set_id_callback(unsigned long (*func)(void)) + { + #if CRYPTO_CALLBACK_ENABLE + id_callback=func; + #endif + } + +unsigned long CRYPTO_thread_id(void) + { + unsigned long ret=0; + +#if CRYPTO_CALLBACK_ENABLE + if (id_callback == NULL) + { +#ifdef WIN16 + ret=(unsigned long)GetCurrentTask(); +#elif defined(WIN32) + ret=(unsigned long)GetCurrentThreadId(); +#elif defined(GETPID_IS_MEANINGLESS) + ret=1L; +#else + ret=(unsigned long)getpid(); +#endif + } + else + ret=id_callback(); +#endif /* CRYPTO_CALLBACK_ENABLE */ + return(ret); + } + +void CRYPTO_lock(int mode, int type, const char *file, int line) + { +#ifdef LOCK_DEBUG + { + char *rw_text,*operation_text; + + if (mode & CRYPTO_LOCK) + operation_text="lock "; + else if (mode & CRYPTO_UNLOCK) + operation_text="unlock"; + else + operation_text="ERROR "; + + if (mode & CRYPTO_READ) + rw_text="r"; + else if (mode & CRYPTO_WRITE) + rw_text="w"; + else + rw_text="ERROR"; + + fprintf(stderr,"lock:%08lx:(%s)%s %-18s %s:%d\n", + CRYPTO_thread_id(), rw_text, operation_text, + CRYPTO_get_lock_name(type), file, line); + } +#endif +#if CRYPTO_CALLBACK_ENABLE + if (locking_callback != NULL) + locking_callback(mode,type,file,line); +#endif + } + +int CRYPTO_add_lock(int *pointer, int amount, int type, const char *file, + int line) + { + int ret; +#if CRYPTO_CALLBACK_ENABLE + if (add_lock_callback != NULL) + { +#ifdef LOCK_DEBUG + int before= *pointer; +#endif + + ret=add_lock_callback(pointer,amount,type,file,line); +#ifdef LOCK_DEBUG + fprintf(stderr,"ladd:%08lx:%2d+%2d->%2d %-18s %s:%d\n", + CRYPTO_thread_id(), + before,amount,ret, + CRYPTO_get_lock_name(type), + file,line); +#endif + *pointer=ret; + } + else +#endif /* CRYPTO_CALLBACK_ENABLE */ + { + CRYPTO_lock(CRYPTO_LOCK|CRYPTO_WRITE,type,file,line); + + ret= *pointer+amount; +#ifdef LOCK_DEBUG + fprintf(stderr,"ladd:%08lx:%2d+%2d->%2d %-18s %s:%d\n", + CRYPTO_thread_id(), + *pointer,amount,ret, + CRYPTO_get_lock_name(type), + file,line); +#endif + *pointer=ret; + CRYPTO_lock(CRYPTO_UNLOCK|CRYPTO_WRITE,type,file,line); + } + return(ret); + } + +#ifdef LOCK_DEBUG +const char *CRYPTO_get_lock_name(int type) + { + if (type < 0) + return("ERROR"); + else if (type < CRYPTO_NUM_LOCKS) + return(lock_names[type]); + else if (type-CRYPTO_NUM_LOCKS >= sk_num(app_locks)) + return("ERROR"); + else + return(sk_value(app_locks,type-CRYPTO_NUM_LOCKS)); + } +#endif /*LOCK_DEBUG*/ + +#ifdef _DLL +#ifdef WIN32 + +/* All we really need to do is remove the 'error' state when a thread + * detaches */ + +BOOL WINAPI DLLEntryPoint(HINSTANCE hinstDLL, DWORD fdwReason, + LPVOID lpvReserved) + { + switch(fdwReason) + { + case DLL_PROCESS_ATTACH: + break; + case DLL_THREAD_ATTACH: + break; + case DLL_THREAD_DETACH: + ERR_remove_state(0); + break; + case DLL_PROCESS_DETACH: + break; + } + return(TRUE); + } +#endif + +#endif diff --git a/libsecurity_apple_csp/open_ssl/cryptlib.h b/libsecurity_apple_csp/open_ssl/cryptlib.h new file mode 100644 index 00000000..438031b3 --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/cryptlib.h @@ -0,0 +1,114 @@ +/* + * 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. + */ + + +/* crypto/cryptlib.h */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef HEADER_CRYPTLIB_H +#define HEADER_CRYPTLIB_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#include "openssl/e_os.h" + +#include +#include +#include +#include +#include + +#ifndef VMS +#define X509_CERT_AREA OPENSSLDIR +#define X509_CERT_DIR OPENSSLDIR "/certs" +#define X509_CERT_FILE OPENSSLDIR "/cert.pem" +#define X509_PRIVATE_DIR OPENSSLDIR "/private" +#else +#define X509_CERT_AREA "SSLROOT:[000000]" +#define X509_CERT_DIR "SSLCERTS:" +#define X509_CERT_FILE "SSLCERTS:cert.pem" +#define X509_PRIVATE_DIR "SSLPRIVATE:" +#endif + +#define X509_CERT_DIR_EVP "SSL_CERT_DIR" +#define X509_CERT_FILE_EVP "SSL_CERT_FILE" + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libsecurity_apple_csp/open_ssl/dh/dh_check.c b/libsecurity_apple_csp/open_ssl/dh/dh_check.c new file mode 100644 index 00000000..3737f379 --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/dh/dh_check.c @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2000-2002 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. + */ + +/* crypto/dh/dh_check.c */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include +#include "cryptlib.h" +#include +#include + +/* Check that p is a safe prime and + * if g is 2, 3 or 5, check that is is a suitable generator + * where + * for 2, p mod 24 == 11 + * for 3, p mod 12 == 5 + * for 5, p mod 10 == 3 or 7 + * should hold. + */ + +int DH_check(DH *dh, int *ret) + { + int ok=0; + BN_CTX *ctx=NULL; + BN_ULONG l; + BIGNUM *q=NULL; + + *ret=0; + ctx=BN_CTX_new(); + if (ctx == NULL) goto err; + q=BN_new(); + if (q == NULL) goto err; + + if (BN_is_word(dh->g,DH_GENERATOR_2)) + { + l=BN_mod_word(dh->p,24); + if (l != 11) *ret|=DH_NOT_SUITABLE_GENERATOR; + } +#if 0 + else if (BN_is_word(dh->g,DH_GENERATOR_3)) + { + l=BN_mod_word(dh->p,12); + if (l != 5) *ret|=DH_NOT_SUITABLE_GENERATOR; + } +#endif + else if (BN_is_word(dh->g,DH_GENERATOR_5)) + { + l=BN_mod_word(dh->p,10); + if ((l != 3) && (l != 7)) + *ret|=DH_NOT_SUITABLE_GENERATOR; + } + else + *ret|=DH_UNABLE_TO_CHECK_GENERATOR; + + if (!BN_is_prime(dh->p,BN_prime_checks,NULL,ctx,NULL)) + *ret|=DH_CHECK_P_NOT_PRIME; + else + { + if (!BN_rshift1(q,dh->p)) goto err; + if (!BN_is_prime(q,BN_prime_checks,NULL,ctx,NULL)) + *ret|=DH_CHECK_P_NOT_SAFE_PRIME; + } + ok=1; +err: + if (ctx != NULL) BN_CTX_free(ctx); + if (q != NULL) BN_free(q); + return(ok); + } diff --git a/libsecurity_apple_csp/open_ssl/dh/dh_err.c b/libsecurity_apple_csp/open_ssl/dh/dh_err.c new file mode 100644 index 00000000..edf04592 --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/dh/dh_err.c @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2000-2002 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. + */ + +/* crypto/dh/dh_err.c */ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +/* NOTE: this file was auto generated by the mkerr.pl script: any changes + * made to it will be overwritten when the script next updates this file, + * only reason strings will be preserved. + */ + +#include +#include +#include + +/* BEGIN ERROR CODES */ +#ifndef NO_ERR +static ERR_STRING_DATA DH_str_functs[]= + { +{ERR_PACK(0,DH_F_DHPARAMS_PRINT,0), "DHparams_print"}, +{ERR_PACK(0,DH_F_DHPARAMS_PRINT_FP,0), "DHparams_print_fp"}, +{ERR_PACK(0,DH_F_DH_COMPUTE_KEY,0), "DH_compute_key"}, +{ERR_PACK(0,DH_F_DH_GENERATE_KEY,0), "DH_generate_key"}, +{ERR_PACK(0,DH_F_DH_GENERATE_PARAMETERS,0), "DH_generate_parameters"}, +{ERR_PACK(0,DH_F_DH_NEW,0), "DH_new"}, +{0,NULL} + }; + +static ERR_STRING_DATA DH_str_reasons[]= + { +{DH_R_NO_PRIVATE_VALUE ,"no private value"}, +{0,NULL} + }; + +#endif + +void ERR_load_DH_strings(void) + { + static int init=1; + + if (init) + { + init=0; +#ifndef NO_ERR + ERR_load_strings(ERR_LIB_DH,DH_str_functs); + ERR_load_strings(ERR_LIB_DH,DH_str_reasons); +#endif + + } + } diff --git a/libsecurity_apple_csp/open_ssl/dh/dh_gen.c b/libsecurity_apple_csp/open_ssl/dh/dh_gen.c new file mode 100644 index 00000000..e0d7ffba --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/dh/dh_gen.c @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2000-2002 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. + */ + +/* crypto/dh/dh_gen.c */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include +#include "cryptlib.h" +#include +#include + +/* We generate DH parameters as follows + * find a prime q which is prime_len/2 bits long. + * p=(2*q)+1 or (p-1)/2 = q + * For this case, g is a generator if + * g^((p-1)/q) mod p != 1 for values of q which are the factors of p-1. + * Since the factors of p-1 are q and 2, we just need to check + * g^2 mod p != 1 and g^q mod p != 1. + * + * Having said all that, + * there is another special case method for the generators 2, 3 and 5. + * for 2, p mod 24 == 11 + * for 3, p mod 12 == 5 <<<<< does not work for safe primes. + * for 5, p mod 10 == 3 or 7 + * + * Thanks to Phil Karn for the pointers about the + * special generators and for answering some of my questions. + * + * I've implemented the second simple method :-). + * Since DH should be using a safe prime (both p and q are prime), + * this generator function can take a very very long time to run. + */ + +DH *DH_generate_parameters(int prime_len, int generator, + void (*callback)(int,int,void *), void *cb_arg) + { + BIGNUM *p=NULL,*t1,*t2; + DH *ret=NULL; + int g,ok= -1; + BN_CTX *ctx=NULL; + + ret=DH_new(); + if (ret == NULL) goto err; + ctx=BN_CTX_new(); + if (ctx == NULL) goto err; + BN_CTX_start(ctx); + t1 = BN_CTX_get(ctx); + t2 = BN_CTX_get(ctx); + if (t1 == NULL || t2 == NULL) goto err; + + if (generator == DH_GENERATOR_2) + { + BN_set_word(t1,24); + BN_set_word(t2,11); + g=2; + } +#ifdef undef /* does not work for safe primes */ + else if (generator == DH_GENERATOR_3) + { + BN_set_word(t1,12); + BN_set_word(t2,5); + g=3; + } +#endif + else if (generator == DH_GENERATOR_5) + { + BN_set_word(t1,10); + BN_set_word(t2,3); + /* BN_set_word(t3,7); just have to miss + * out on these ones :-( */ + g=5; + } + else + g=generator; + + p=BN_generate_prime(NULL,prime_len,1,t1,t2,callback,cb_arg); + if (p == NULL) goto err; + if (callback != NULL) callback(3,0,cb_arg); + ret->p=p; + ret->g=BN_new(); + if (!BN_set_word(ret->g,g)) goto err; + ok=1; +err: + if (ok == -1) + { + DHerr(DH_F_DH_GENERATE_PARAMETERS,ERR_R_BN_LIB); + ok=0; + } + + if (ctx != NULL) + { + BN_CTX_end(ctx); + BN_CTX_free(ctx); + } + if (!ok && (ret != NULL)) + { + DH_free(ret); + ret=NULL; + } + return(ret); + } diff --git a/libsecurity_apple_csp/open_ssl/dh/dh_key.c b/libsecurity_apple_csp/open_ssl/dh/dh_key.c new file mode 100644 index 00000000..d1af8573 --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/dh/dh_key.c @@ -0,0 +1,230 @@ +/* + * Copyright (c) 2000-2002 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. + */ + +/* crypto/dh/dh_key.c */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include +#include "cryptlib.h" +#include +#include +#include + +static int generate_key(DH *dh); +static int compute_key(unsigned char *key, BIGNUM *pub_key, DH *dh); +static int dh_bn_mod_exp(DH *dh, BIGNUM *r, BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx, + BN_MONT_CTX *m_ctx); +static int dh_init(DH *dh); +static int dh_finish(DH *dh); + +int DH_generate_key(DH *dh) + { + return dh->meth->generate_key(dh); + } + +int DH_compute_key(unsigned char *key, BIGNUM *pub_key, DH *dh) + { + return dh->meth->compute_key(key, pub_key, dh); + } + +static DH_METHOD dh_ossl = { +"OpenSSL DH Method", +generate_key, +compute_key, +dh_bn_mod_exp, +dh_init, +dh_finish, +0, +NULL +}; + +DH_METHOD *DH_OpenSSL(void) +{ + return &dh_ossl; +} + +static int generate_key(DH *dh) + { + int ok=0; + BN_CTX ctx; + BN_MONT_CTX *mont; + BIGNUM *pub_key=NULL,*priv_key=NULL; + + BN_CTX_init(&ctx); + + if (dh->priv_key == NULL) + { + priv_key=BN_new(); + if (priv_key == NULL) goto err; + do + if (!BN_rand_range(priv_key, dh->p)) goto err; + while (BN_is_zero(priv_key)); + } + else + priv_key=dh->priv_key; + + if (dh->pub_key == NULL) + { + pub_key=BN_new(); + if (pub_key == NULL) goto err; + } + else + pub_key=dh->pub_key; + + if ((dh->method_mont_p == NULL) && (dh->flags & DH_FLAG_CACHE_MONT_P)) + { + if ((dh->method_mont_p=(char *)BN_MONT_CTX_new()) != NULL) + if (!BN_MONT_CTX_set((BN_MONT_CTX *)dh->method_mont_p, + dh->p,&ctx)) goto err; + } + mont=(BN_MONT_CTX *)dh->method_mont_p; + + if (!dh->meth->bn_mod_exp(dh, pub_key,dh->g,priv_key,dh->p,&ctx,mont)) + goto err; + + dh->pub_key=pub_key; + dh->priv_key=priv_key; + ok=1; +err: + if (ok != 1) + DHerr(DH_F_DH_GENERATE_KEY,ERR_R_BN_LIB); + + if ((pub_key != NULL) && (dh->pub_key == NULL)) BN_free(pub_key); + if ((priv_key != NULL) && (dh->priv_key == NULL)) BN_free(priv_key); + BN_CTX_free(&ctx); + return(ok); + } + +static int compute_key(unsigned char *key, BIGNUM *pub_key, DH *dh) + { + BN_CTX ctx; + BN_MONT_CTX *mont; + BIGNUM *tmp; + int ret= -1; + + BN_CTX_init(&ctx); + BN_CTX_start(&ctx); + tmp = BN_CTX_get(&ctx); + + if (dh->priv_key == NULL) + { + DHerr(DH_F_DH_COMPUTE_KEY,DH_R_NO_PRIVATE_VALUE); + goto err; + } + if ((dh->method_mont_p == NULL) && (dh->flags & DH_FLAG_CACHE_MONT_P)) + { + if ((dh->method_mont_p=(char *)BN_MONT_CTX_new()) != NULL) + if (!BN_MONT_CTX_set((BN_MONT_CTX *)dh->method_mont_p, + dh->p,&ctx)) goto err; + } + + mont=(BN_MONT_CTX *)dh->method_mont_p; + if (!dh->meth->bn_mod_exp(dh, tmp,pub_key,dh->priv_key,dh->p,&ctx,mont)) + { + DHerr(DH_F_DH_COMPUTE_KEY,ERR_R_BN_LIB); + goto err; + } + + ret=BN_bn2bin(tmp,key); +err: + BN_CTX_end(&ctx); + BN_CTX_free(&ctx); + return(ret); + } + +static int dh_bn_mod_exp(DH *dh, BIGNUM *r, BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx, + BN_MONT_CTX *m_ctx) + { + if (a->top == 1) + { + BN_ULONG A = a->d[0]; + return BN_mod_exp_mont_word(r,A,p,m,ctx,m_ctx); + } + else + return BN_mod_exp_mont(r,a,p,m,ctx,m_ctx); + } + + +static int dh_init(DH *dh) + { + dh->flags |= DH_FLAG_CACHE_MONT_P; + return(1); + } + +static int dh_finish(DH *dh) + { + if(dh->method_mont_p) + BN_MONT_CTX_free((BN_MONT_CTX *)dh->method_mont_p); + return(1); + } diff --git a/libsecurity_apple_csp/open_ssl/dh/dh_lib.c b/libsecurity_apple_csp/open_ssl/dh/dh_lib.c new file mode 100644 index 00000000..ff639b2a --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/dh/dh_lib.c @@ -0,0 +1,203 @@ +/* + * Copyright (c) 2000-2002 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. + */ + +/* crypto/dh/dh_lib.c */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include +#include "cryptlib.h" +#include +#include + +const char *DH_version="Diffie-Hellman" OPENSSL_VERSION_PTEXT; + +static DH_METHOD *default_DH_method; +static int dh_meth_num = 0; +static STACK_OF(CRYPTO_EX_DATA_FUNCS) *dh_meth = NULL; + +void DH_set_default_method(DH_METHOD *meth) +{ + default_DH_method = meth; +} + +DH_METHOD *DH_get_default_method(void) +{ + if(!default_DH_method) default_DH_method = DH_OpenSSL(); + return default_DH_method; +} + +DH_METHOD *DH_set_method(DH *dh, DH_METHOD *meth) +{ + DH_METHOD *mtmp; + mtmp = dh->meth; + if (mtmp->finish) mtmp->finish(dh); + dh->meth = meth; + if (meth->init) meth->init(dh); + return mtmp; +} + +DH *DH_new(void) +{ + return DH_new_method(NULL); +} + +DH *DH_new_method(DH_METHOD *meth) + { + DH *ret; + ret=(DH *)Malloc(sizeof(DH)); + + if (ret == NULL) + { + DHerr(DH_F_DH_NEW,ERR_R_MALLOC_FAILURE); + return(NULL); + } + if(meth) ret->meth = meth; + else ret->meth = DH_get_default_method(); + ret->pad=0; + ret->version=0; + ret->p=NULL; + ret->g=NULL; + ret->length=0; + ret->pub_key=NULL; + ret->priv_key=NULL; + ret->q=NULL; + ret->j=NULL; + ret->seed = NULL; + ret->seedlen = 0; + ret->counter = NULL; + ret->method_mont_p=NULL; + ret->references = 1; + ret->flags=ret->meth->flags; + CRYPTO_new_ex_data(dh_meth,ret,&ret->ex_data); + if ((ret->meth->init != NULL) && !ret->meth->init(ret)) + { + CRYPTO_free_ex_data(dh_meth,ret,&ret->ex_data); + Free(ret); + ret=NULL; + } + return(ret); + } + +void DH_free(DH *r) + { + int i; + if(r == NULL) return; + i = CRYPTO_add(&r->references, -1, CRYPTO_LOCK_DH); +#ifdef REF_PRINT + REF_PRINT("DH",r); +#endif + if (i > 0) return; +#ifdef REF_CHECK + if (i < 0) + { + fprintf(stderr,"DH_free, bad reference count\n"); + abort(); + } +#endif + + if(r->meth->finish) r->meth->finish(r); + + CRYPTO_free_ex_data(dh_meth, r, &r->ex_data); + + if (r->p != NULL) BN_clear_free(r->p); + if (r->g != NULL) BN_clear_free(r->g); + if (r->q != NULL) BN_clear_free(r->q); + if (r->j != NULL) BN_clear_free(r->j); + if (r->seed) Free(r->seed); + if (r->counter != NULL) BN_clear_free(r->counter); + if (r->pub_key != NULL) BN_clear_free(r->pub_key); + if (r->priv_key != NULL) BN_clear_free(r->priv_key); + Free(r); + } + +int DH_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, + CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func) + { + dh_meth_num++; + return(CRYPTO_get_ex_new_index(dh_meth_num-1, + &dh_meth,argl,argp,new_func,dup_func,free_func)); + } + +int DH_set_ex_data(DH *d, int idx, void *arg) + { + return(CRYPTO_set_ex_data(&d->ex_data,idx,arg)); + } + +void *DH_get_ex_data(DH *d, int idx) + { + return(CRYPTO_get_ex_data(&d->ex_data,idx)); + } + +int DH_size(DH *dh) + { + return(BN_num_bytes(dh->p)); + } diff --git a/libsecurity_apple_csp/open_ssl/dsa/dsa_asn1.c b/libsecurity_apple_csp/open_ssl/dsa/dsa_asn1.c new file mode 100644 index 00000000..ac46c6cb --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/dsa/dsa_asn1.c @@ -0,0 +1,120 @@ +/* + * 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. + */ + + +/* crypto/dsa/dsa_asn1.c */ + +#include +#include "cryptlib.h" +#include +#include +#ifndef _OPENSSL_APPLE_CDSA_ +#include +#endif + +DSA_SIG *DSA_SIG_new(void) +{ + DSA_SIG *ret; + + ret = Malloc(sizeof(DSA_SIG)); + if (ret == NULL) + { + DSAerr(DSA_F_DSA_SIG_NEW,ERR_R_MALLOC_FAILURE); + return(NULL); + } + ret->r = NULL; + ret->s = NULL; + return(ret); +} + +void DSA_SIG_free(DSA_SIG *r) +{ + if (r == NULL) return; + if (r->r) BN_clear_free(r->r); + if (r->s) BN_clear_free(r->s); + Free(r); +} + +#ifndef _OPENSSL_APPLE_CDSA_ + +int i2d_DSA_SIG(DSA_SIG *v, unsigned char **pp) +{ + int t=0,len; + ASN1_INTEGER rbs,sbs; + unsigned char *p; + + rbs.data=Malloc(BN_num_bits(v->r)/8+1); + if (rbs.data == NULL) + { + DSAerr(DSA_F_I2D_DSA_SIG, ERR_R_MALLOC_FAILURE); + return(0); + } + rbs.type=V_ASN1_INTEGER; + rbs.length=BN_bn2bin(v->r,rbs.data); + sbs.data=Malloc(BN_num_bits(v->s)/8+1); + if (sbs.data == NULL) + { + Free(rbs.data); + DSAerr(DSA_F_I2D_DSA_SIG, ERR_R_MALLOC_FAILURE); + return(0); + } + sbs.type=V_ASN1_INTEGER; + sbs.length=BN_bn2bin(v->s,sbs.data); + + len=i2d_ASN1_INTEGER(&rbs,NULL); + len+=i2d_ASN1_INTEGER(&sbs,NULL); + + if (pp) + { + p=*pp; + ASN1_put_object(&p,1,len,V_ASN1_SEQUENCE,V_ASN1_UNIVERSAL); + i2d_ASN1_INTEGER(&rbs,&p); + i2d_ASN1_INTEGER(&sbs,&p); + } + t=ASN1_object_size(1,len,V_ASN1_SEQUENCE); + Free(rbs.data); + Free(sbs.data); + return(t); +} + +DSA_SIG *d2i_DSA_SIG(DSA_SIG **a, unsigned char **pp, long length) +{ + int i=ERR_R_NESTED_ASN1_ERROR; + ASN1_INTEGER *bs=NULL; + M_ASN1_D2I_vars(a,DSA_SIG *,DSA_SIG_new); + + M_ASN1_D2I_Init(); + M_ASN1_D2I_start_sequence(); + M_ASN1_D2I_get(bs,d2i_ASN1_INTEGER); + if ((ret->r=BN_bin2bn(bs->data,bs->length,ret->r)) == NULL) + goto err_bn; + M_ASN1_D2I_get(bs,d2i_ASN1_INTEGER); + if ((ret->s=BN_bin2bn(bs->data,bs->length,ret->s)) == NULL) + goto err_bn; + M_ASN1_BIT_STRING_free(bs); + M_ASN1_D2I_Finish_2(a); + +err_bn: + i=ERR_R_BN_LIB; +err: + DSAerr(DSA_F_D2I_DSA_SIG,i); + if ((ret != NULL) && ((a == NULL) || (*a != ret))) DSA_SIG_free(ret); + if (bs != NULL) M_ASN1_BIT_STRING_free(bs); + return(NULL); +} + +#endif /* _OPENSSL_APPLE_CDSA_ */ diff --git a/libsecurity_apple_csp/open_ssl/dsa/dsa_err.c b/libsecurity_apple_csp/open_ssl/dsa/dsa_err.c new file mode 100644 index 00000000..9ddab261 --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/dsa/dsa_err.c @@ -0,0 +1,124 @@ +/* + * 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. + */ + + +/* crypto/dsa/dsa_err.c */ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +/* NOTE: this file was auto generated by the mkerr.pl script: any changes + * made to it will be overwritten when the script next updates this file, + * only reason strings will be preserved. + */ + +#include +#include +#include + +/* BEGIN ERROR CODES */ +#ifndef NO_ERR +static ERR_STRING_DATA DSA_str_functs[]= + { +{ERR_PACK(0,DSA_F_D2I_DSA_SIG,0), "d2i_DSA_SIG"}, +{ERR_PACK(0,DSA_F_DSAPARAMS_PRINT,0), "DSAparams_print"}, +{ERR_PACK(0,DSA_F_DSAPARAMS_PRINT_FP,0), "DSAparams_print_fp"}, +{ERR_PACK(0,DSA_F_DSA_DO_SIGN,0), "DSA_do_sign"}, +{ERR_PACK(0,DSA_F_DSA_DO_VERIFY,0), "DSA_do_verify"}, +{ERR_PACK(0,DSA_F_DSA_NEW,0), "DSA_new"}, +{ERR_PACK(0,DSA_F_DSA_PRINT,0), "DSA_print"}, +{ERR_PACK(0,DSA_F_DSA_PRINT_FP,0), "DSA_print_fp"}, +{ERR_PACK(0,DSA_F_DSA_SIGN,0), "DSA_sign"}, +{ERR_PACK(0,DSA_F_DSA_SIGN_SETUP,0), "DSA_sign_setup"}, +{ERR_PACK(0,DSA_F_DSA_SIG_NEW,0), "DSA_SIG_new"}, +{ERR_PACK(0,DSA_F_DSA_VERIFY,0), "DSA_verify"}, +{ERR_PACK(0,DSA_F_I2D_DSA_SIG,0), "i2d_DSA_SIG"}, +{0,NULL} + }; + +static ERR_STRING_DATA DSA_str_reasons[]= + { +{DSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE ,"data too large for key size"}, +{0,NULL} + }; + +#endif + +void ERR_load_DSA_strings(void) + { + static int init=1; + + if (init) + { + init=0; +#ifndef NO_ERR + ERR_load_strings(ERR_LIB_DSA,DSA_str_functs); + ERR_load_strings(ERR_LIB_DSA,DSA_str_reasons); +#endif + + } + } diff --git a/libsecurity_apple_csp/open_ssl/dsa/dsa_gen.c b/libsecurity_apple_csp/open_ssl/dsa/dsa_gen.c new file mode 100644 index 00000000..951b4b80 --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/dsa/dsa_gen.c @@ -0,0 +1,312 @@ +/* + * 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. + */ + + +/* crypto/dsa/dsa_gen.c */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#undef GENUINE_DSA + +#ifdef GENUINE_DSA +/* Parameter generation follows the original release of FIPS PUB 186, + * Appendix 2.2 (i.e. use SHA as defined in FIPS PUB 180) */ +#define HASH SHA +#else +/* Parameter generation follows the updated Appendix 2.2 for FIPS PUB 186, + * also Appendix 2.2 of FIPS PUB 186-1 (i.e. use SHA as defined in + * FIPS PUB 180-1) */ +#define HASH SHA1 +#endif + +#ifndef NO_SHA + +#include +#include +#include "cryptlib.h" +#include +#include +#include +#include + +DSA *DSA_generate_parameters(int bits, unsigned char *seed_in, int seed_len, + int *counter_ret, unsigned long *h_ret, + void (*callback)(int, int, void *), + void *cb_arg) + { + int ok=0; + unsigned char seed[SHA_DIGEST_LENGTH]; + unsigned char md[SHA_DIGEST_LENGTH]; + unsigned char buf[SHA_DIGEST_LENGTH],buf2[SHA_DIGEST_LENGTH]; + BIGNUM *r0,*W,*X,*c,*test; + BIGNUM *g=NULL,*q=NULL,*p=NULL; + BN_MONT_CTX *mont=NULL; + int k,n=0,i,b,m=0; + int counter=0; + int r=0; + BN_CTX *ctx=NULL,*ctx2=NULL,*ctx3=NULL; + unsigned int h=2; + DSA *ret=NULL; + + if (bits < 512) bits=512; + bits=(bits+63)/64*64; + + if (seed_len < 20) + seed_in = NULL; /* seed buffer too small -- ignore */ + if (seed_len > 20) + seed_len = 20; /* App. 2.2 of FIPS PUB 186 allows larger SEED, + * but our internal buffers are restricted to 160 bits*/ + if ((seed_in != NULL) && (seed_len == 20)) + memcpy(seed,seed_in,seed_len); + + if ((ctx=BN_CTX_new()) == NULL) goto err; + if ((ctx2=BN_CTX_new()) == NULL) goto err; + if ((ctx3=BN_CTX_new()) == NULL) goto err; + if ((ret=DSA_new()) == NULL) goto err; + + if ((mont=BN_MONT_CTX_new()) == NULL) goto err; + + BN_CTX_start(ctx2); + r0 = BN_CTX_get(ctx2); + g = BN_CTX_get(ctx2); + W = BN_CTX_get(ctx2); + q = BN_CTX_get(ctx2); + X = BN_CTX_get(ctx2); + c = BN_CTX_get(ctx2); + p = BN_CTX_get(ctx2); + test = BN_CTX_get(ctx2); + + BN_lshift(test,BN_value_one(),bits-1); + + for (;;) + { + for (;;) /* find q */ + { + int seed_is_random; + + /* step 1 */ + if (callback != NULL) callback(0,m++,cb_arg); + + if (!seed_len) + { + RAND_pseudo_bytes(seed,SHA_DIGEST_LENGTH); + seed_is_random = 1; + } + else + { + seed_is_random = 0; + seed_len=0; /* use random seed if 'seed_in' turns out to be bad*/ + } + memcpy(buf,seed,SHA_DIGEST_LENGTH); + memcpy(buf2,seed,SHA_DIGEST_LENGTH); + /* precompute "SEED + 1" for step 7: */ + for (i=SHA_DIGEST_LENGTH-1; i >= 0; i--) + { + buf[i]++; + if (buf[i] != 0) break; + } + + /* step 2 */ + HASH(seed,SHA_DIGEST_LENGTH,md); + HASH(buf,SHA_DIGEST_LENGTH,buf2); + for (i=0; i 0) + break; + if (r != 0) + goto err; + + /* do a callback call */ + /* step 5 */ + } + + if (callback != NULL) callback(2,0,cb_arg); + if (callback != NULL) callback(3,0,cb_arg); + + /* step 6 */ + counter=0; + /* "offset = 2" */ + + n=(bits-1)/160; + b=(bits-1)-n*160; + + for (;;) + { + if (callback != NULL && counter != 0) + callback(0,counter,cb_arg); + + /* step 7 */ + BN_zero(W); + /* now 'buf' contains "SEED + offset - 1" */ + for (k=0; k<=n; k++) + { + /* obtain "SEED + offset + k" by incrementing: */ + for (i=SHA_DIGEST_LENGTH-1; i >= 0; i--) + { + buf[i]++; + if (buf[i] != 0) break; + } + + HASH(buf,SHA_DIGEST_LENGTH,md); + + /* step 8 */ + if (!BN_bin2bn(md,SHA_DIGEST_LENGTH,r0)) + goto err; + BN_lshift(r0,r0,160*k); + BN_add(W,W,r0); + } + + /* more of step 8 */ + BN_mask_bits(W,bits-1); + BN_copy(X,W); /* this should be ok */ + BN_add(X,X,test); /* this should be ok */ + + /* step 9 */ + BN_lshift1(r0,q); + BN_mod(c,X,r0,ctx); + BN_sub(r0,c,BN_value_one()); + BN_sub(p,X,r0); + + /* step 10 */ + if (BN_cmp(p,test) >= 0) + { + /* step 11 */ + r = BN_is_prime_fasttest(p, DSS_prime_checks, callback, ctx3, cb_arg, 1); + if (r > 0) + goto end; /* found it */ + if (r != 0) + goto err; + } + + /* step 13 */ + counter++; + /* "offset = offset + n + 1" */ + + /* step 14 */ + if (counter >= 4096) break; + } + } +end: + if (callback != NULL) callback(2,1,cb_arg); + + /* We now need to generate g */ + /* Set r0=(p-1)/q */ + BN_sub(test,p,BN_value_one()); + BN_div(r0,NULL,test,q,ctx); + + BN_set_word(test,h); + BN_MONT_CTX_set(mont,p,ctx); + + for (;;) + { + /* g=test^r0%p */ + BN_mod_exp_mont(g,test,r0,p,ctx,mont); + if (!BN_is_one(g)) break; + BN_add(test,test,BN_value_one()); + h++; + } + + if (callback != NULL) callback(3,1,cb_arg); + + ok=1; +err: + if (!ok) + { + if (ret != NULL) DSA_free(ret); + } + else + { + ret->p=BN_dup(p); + ret->q=BN_dup(q); + ret->g=BN_dup(g); + if ((m > 1) && (seed_in != NULL)) memcpy(seed_in,seed,20); + if (counter_ret != NULL) *counter_ret=counter; + if (h_ret != NULL) *h_ret=h; + } + if (ctx != NULL) BN_CTX_free(ctx); + if (ctx2 != NULL) + { + BN_CTX_end(ctx2); + BN_CTX_free(ctx2); + } + if (ctx3 != NULL) BN_CTX_free(ctx3); + if (mont != NULL) BN_MONT_CTX_free(mont); + return(ok?ret:NULL); + } +#endif diff --git a/libsecurity_apple_csp/open_ssl/dsa/dsa_key.c b/libsecurity_apple_csp/open_ssl/dsa/dsa_key.c new file mode 100644 index 00000000..0af87775 --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/dsa/dsa_key.c @@ -0,0 +1,129 @@ +/* + * 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. + */ + + +/* crypto/dsa/dsa_key.c */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include +#include +#include "cryptlib.h" +//#include +#include +#include +#include + +int DSA_generate_key(DSA *dsa) + { + int ok=0; + unsigned int i; + BN_CTX *ctx=NULL; + BIGNUM *pub_key=NULL,*priv_key=NULL; + + if ((ctx=BN_CTX_new()) == NULL) goto err; + + if (dsa->priv_key == NULL) + { + if ((priv_key=BN_new()) == NULL) goto err; + } + else + priv_key=dsa->priv_key; + + i=BN_num_bits(dsa->q); + for (;;) + { + if (!BN_rand(priv_key,i,1,0)) + goto err; + if (BN_cmp(priv_key,dsa->q) >= 0) + BN_sub(priv_key,priv_key,dsa->q); + if (!BN_is_zero(priv_key)) break; + } + + if (dsa->pub_key == NULL) + { + if ((pub_key=BN_new()) == NULL) goto err; + } + else + pub_key=dsa->pub_key; + + if (!BN_mod_exp(pub_key,dsa->g,priv_key,dsa->p,ctx)) goto err; + + dsa->priv_key=priv_key; + dsa->pub_key=pub_key; + ok=1; + +err: + if ((pub_key != NULL) && (dsa->pub_key == NULL)) BN_free(pub_key); + if ((priv_key != NULL) && (dsa->priv_key == NULL)) BN_free(priv_key); + if (ctx != NULL) BN_CTX_free(ctx); + return(ok); + } diff --git a/libsecurity_apple_csp/open_ssl/dsa/dsa_lib.c b/libsecurity_apple_csp/open_ssl/dsa/dsa_lib.c new file mode 100644 index 00000000..aad0f5e5 --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/dsa/dsa_lib.c @@ -0,0 +1,266 @@ +/* + * 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. + */ + + +/* crypto/dsa/dsa_lib.c */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +/* Original version from Steven Schoch */ + +#include +#include "cryptlib.h" +#include +#include +#include + +const char *DSA_version="DSA" OPENSSL_VERSION_PTEXT; + +static const DSA_METHOD *default_DSA_method; +static int dsa_meth_num = 0; +static STACK_OF(CRYPTO_EX_DATA_FUNCS) *dsa_meth = NULL; + +void DSA_set_default_method(const DSA_METHOD *meth) +{ + default_DSA_method = meth; +} + +const DSA_METHOD *DSA_get_default_method(void) +{ + if(!default_DSA_method) default_DSA_method = DSA_OpenSSL(); + return default_DSA_method; +} + +DSA *DSA_new(void) +{ + return DSA_new_method(NULL); +} + +const DSA_METHOD *DSA_set_method(DSA *dsa, const DSA_METHOD *meth) +{ + const DSA_METHOD *mtmp; + mtmp = dsa->meth; + if (mtmp->finish) mtmp->finish(dsa); + dsa->meth = meth; + if (meth->init) meth->init(dsa); + return mtmp; +} + + +DSA *DSA_new_method(const DSA_METHOD *meth) + { + DSA *ret; + + ret=(DSA *)Malloc(sizeof(DSA)); + if (ret == NULL) + { + DSAerr(DSA_F_DSA_NEW,ERR_R_MALLOC_FAILURE); + return(NULL); + } + if(!default_DSA_method) default_DSA_method = DSA_OpenSSL(); + if(meth) ret->meth = meth; + else ret->meth = default_DSA_method; + ret->pad=0; + ret->version=0; + ret->write_params=1; + ret->p=NULL; + ret->q=NULL; + ret->g=NULL; + + ret->pub_key=NULL; + ret->priv_key=NULL; + + ret->kinv=NULL; + ret->r=NULL; + ret->method_mont_p=NULL; + + ret->references=1; + ret->flags=ret->meth->flags; + if ((ret->meth->init != NULL) && !ret->meth->init(ret)) + { + Free(ret); + ret=NULL; + } + else + CRYPTO_new_ex_data(dsa_meth,ret,&ret->ex_data); + + return(ret); + } + +void DSA_free(DSA *r) + { + int i; + + if (r == NULL) return; + + i=CRYPTO_add(&r->references,-1,CRYPTO_LOCK_DSA); +#ifdef REF_PRINT + REF_PRINT("DSA",r); +#endif + if (i > 0) return; +#ifdef REF_CHECK + if (i < 0) + { + fprintf(stderr,"DSA_free, bad reference count\n"); + abort(); + } +#endif + + CRYPTO_free_ex_data(dsa_meth, r, &r->ex_data); + + if(r->meth->finish) r->meth->finish(r); + + if (r->p != NULL) BN_clear_free(r->p); + if (r->q != NULL) BN_clear_free(r->q); + if (r->g != NULL) BN_clear_free(r->g); + if (r->pub_key != NULL) BN_clear_free(r->pub_key); + if (r->priv_key != NULL) BN_clear_free(r->priv_key); + if (r->kinv != NULL) BN_clear_free(r->kinv); + if (r->r != NULL) BN_clear_free(r->r); + Free(r); + } + +#ifndef _OPENSSL_APPLE_CDSA_ +int DSA_size(DSA *r) + { + int ret,i; + ASN1_INTEGER bs; + unsigned char buf[4]; + + i=BN_num_bits(r->q); + bs.length=(i+7)/8; + bs.data=buf; + bs.type=V_ASN1_INTEGER; + /* If the top bit is set the asn1 encoding is 1 larger. */ + buf[0]=0xff; + + i=i2d_ASN1_INTEGER(&bs,NULL); + i+=i; /* r and s */ + ret=ASN1_object_size(1,i,V_ASN1_SEQUENCE); + return(ret); + } +#endif /* _OPENSSL_APPLE_CDSA_ */ + +int DSA_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, + CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func) + { + dsa_meth_num++; + return(CRYPTO_get_ex_new_index(dsa_meth_num-1, + &dsa_meth,argl,argp,new_func,dup_func,free_func)); + } + +int DSA_set_ex_data(DSA *d, int idx, void *arg) + { + return(CRYPTO_set_ex_data(&d->ex_data,idx,arg)); + } + +void *DSA_get_ex_data(DSA *d, int idx) + { + return(CRYPTO_get_ex_data(&d->ex_data,idx)); + } + +#ifndef NO_DH +DH *DSA_dup_DH(DSA *r) + { + /* DSA has p, q, g, optional pub_key, optional priv_key. + * DH has p, optional length, g, optional pub_key, optional priv_key. + */ + + DH *ret = NULL; + + if (r == NULL) + goto err; + ret = DH_new(); + if (ret == NULL) + goto err; + if (r->p != NULL) + if ((ret->p = BN_dup(r->p)) == NULL) + goto err; + if (r->q != NULL) + ret->length = BN_num_bits(r->q); + if (r->g != NULL) + if ((ret->g = BN_dup(r->g)) == NULL) + goto err; + if (r->pub_key != NULL) + if ((ret->pub_key = BN_dup(r->pub_key)) == NULL) + goto err; + if (r->priv_key != NULL) + if ((ret->priv_key = BN_dup(r->priv_key)) == NULL) + goto err; + + return ret; + + err: + if (ret != NULL) + DH_free(ret); + return NULL; + } +#endif diff --git a/libsecurity_apple_csp/open_ssl/dsa/dsa_ossl.c b/libsecurity_apple_csp/open_ssl/dsa/dsa_ossl.c new file mode 100644 index 00000000..aae23451 --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/dsa/dsa_ossl.c @@ -0,0 +1,339 @@ +/* + * 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. + */ + + +/* crypto/dsa/dsa_ossl.c */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +/* Original version from Steven Schoch */ + +#include +#include "cryptlib.h" +#include +#include +#include +#include + +static DSA_SIG *dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa); +static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp); +static int dsa_do_verify(const unsigned char *dgst, int dgst_len, DSA_SIG *sig, + DSA *dsa); +static int dsa_init(DSA *dsa); +static int dsa_finish(DSA *dsa); +static int dsa_mod_exp(DSA *dsa, BIGNUM *rr, BIGNUM *a1, BIGNUM *p1, + BIGNUM *a2, BIGNUM *p2, BIGNUM *m, BN_CTX *ctx, + BN_MONT_CTX *in_mont); +static int dsa_bn_mod_exp(DSA *dsa, BIGNUM *r, BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx, + BN_MONT_CTX *m_ctx); + +static const DSA_METHOD openssl_dsa_meth = { +"OpenSSL DSA method", +dsa_do_sign, +dsa_sign_setup, +dsa_do_verify, +dsa_mod_exp, +dsa_bn_mod_exp, +dsa_init, +dsa_finish, +0, +NULL +}; + +const DSA_METHOD *DSA_OpenSSL(void) +{ + return &openssl_dsa_meth; +} + +static DSA_SIG *dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa) + { + BIGNUM *kinv=NULL,*r=NULL,*s=NULL; + BIGNUM m; + BIGNUM xr; + BN_CTX *ctx=NULL; + int i,reason=ERR_R_BN_LIB; + DSA_SIG *ret=NULL; + + BN_init(&m); + BN_init(&xr); + s=BN_new(); + if (s == NULL) goto err; + + i=BN_num_bytes(dsa->q); /* should be 20 */ + if ((dlen > i) || (dlen > 50)) + { + reason=DSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE; + goto err; + } + + ctx=BN_CTX_new(); + if (ctx == NULL) goto err; + + if ((dsa->kinv == NULL) || (dsa->r == NULL)) + { + if (!DSA_sign_setup(dsa,ctx,&kinv,&r)) goto err; + } + else + { + kinv=dsa->kinv; + dsa->kinv=NULL; + r=dsa->r; + dsa->r=NULL; + } + + if (BN_bin2bn(dgst,dlen,&m) == NULL) goto err; + + /* Compute s = inv(k) (m + xr) mod q */ + if (!BN_mod_mul(&xr,dsa->priv_key,r,dsa->q,ctx)) goto err;/* s = xr */ + if (!BN_add(s, &xr, &m)) goto err; /* s = m + xr */ + if (BN_cmp(s,dsa->q) > 0) + BN_sub(s,s,dsa->q); + if (!BN_mod_mul(s,s,kinv,dsa->q,ctx)) goto err; + + ret=DSA_SIG_new(); + if (ret == NULL) goto err; + ret->r = r; + ret->s = s; + +err: + if (!ret) + { + DSAerr(DSA_F_DSA_DO_SIGN,reason); + BN_free(r); + BN_free(s); + } + if (ctx != NULL) BN_CTX_free(ctx); + BN_clear_free(&m); + BN_clear_free(&xr); + if (kinv != NULL) /* dsa->kinv is NULL now if we used it */ + BN_clear_free(kinv); + return(ret); + } + +static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp) + { + BN_CTX *ctx; + BIGNUM k,*kinv=NULL,*r=NULL; + int ret=0; + + if (ctx_in == NULL) + { + if ((ctx=BN_CTX_new()) == NULL) goto err; + } + else + ctx=ctx_in; + + BN_init(&k); + if ((r=BN_new()) == NULL) goto err; + kinv=NULL; + + /* Get random k */ + for (;;) + { + if (!BN_rand(&k, BN_num_bits(dsa->q), 1, 0)) goto err; + if (BN_cmp(&k,dsa->q) >= 0) + BN_sub(&k,&k,dsa->q); + if (!BN_is_zero(&k)) break; + } + + if ((dsa->method_mont_p == NULL) && (dsa->flags & DSA_FLAG_CACHE_MONT_P)) + { + if ((dsa->method_mont_p=(char *)BN_MONT_CTX_new()) != NULL) + if (!BN_MONT_CTX_set((BN_MONT_CTX *)dsa->method_mont_p, + dsa->p,ctx)) goto err; + } + + /* Compute r = (g^k mod p) mod q */ + if (!dsa->meth->bn_mod_exp(dsa, r,dsa->g,&k,dsa->p,ctx, + (BN_MONT_CTX *)dsa->method_mont_p)) goto err; + if (!BN_mod(r,r,dsa->q,ctx)) goto err; + + /* Compute part of 's = inv(k) (m + xr) mod q' */ + if ((kinv=BN_mod_inverse(NULL,&k,dsa->q,ctx)) == NULL) goto err; + + if (*kinvp != NULL) BN_clear_free(*kinvp); + *kinvp=kinv; + kinv=NULL; + if (*rp != NULL) BN_clear_free(*rp); + *rp=r; + ret=1; +err: + if (!ret) + { + DSAerr(DSA_F_DSA_SIGN_SETUP,ERR_R_BN_LIB); + if (kinv != NULL) BN_clear_free(kinv); + if (r != NULL) BN_clear_free(r); + } + if (ctx_in == NULL) BN_CTX_free(ctx); + if (kinv != NULL) BN_clear_free(kinv); + BN_clear_free(&k); + return(ret); + } + +static int dsa_do_verify(const unsigned char *dgst, int dgst_len, DSA_SIG *sig, + DSA *dsa) + { + BN_CTX *ctx; + BIGNUM u1,u2,t1; + BN_MONT_CTX *mont=NULL; + int ret = -1; + + if ((ctx=BN_CTX_new()) == NULL) goto err; + BN_init(&u1); + BN_init(&u2); + BN_init(&t1); + + /* Calculate W = inv(S) mod Q + * save W in u2 */ + if ((BN_mod_inverse(&u2,sig->s,dsa->q,ctx)) == NULL) goto err; + + /* save M in u1 */ + if (BN_bin2bn(dgst,dgst_len,&u1) == NULL) goto err; + + /* u1 = M * w mod q */ + if (!BN_mod_mul(&u1,&u1,&u2,dsa->q,ctx)) goto err; + + /* u2 = r * w mod q */ + if (!BN_mod_mul(&u2,sig->r,&u2,dsa->q,ctx)) goto err; + + if ((dsa->method_mont_p == NULL) && (dsa->flags & DSA_FLAG_CACHE_MONT_P)) + { + if ((dsa->method_mont_p=(char *)BN_MONT_CTX_new()) != NULL) + if (!BN_MONT_CTX_set((BN_MONT_CTX *)dsa->method_mont_p, + dsa->p,ctx)) goto err; + } + mont=(BN_MONT_CTX *)dsa->method_mont_p; + +#if 0 + { + BIGNUM t2; + + BN_init(&t2); + /* v = ( g^u1 * y^u2 mod p ) mod q */ + /* let t1 = g ^ u1 mod p */ + if (!BN_mod_exp_mont(&t1,dsa->g,&u1,dsa->p,ctx,mont)) goto err; + /* let t2 = y ^ u2 mod p */ + if (!BN_mod_exp_mont(&t2,dsa->pub_key,&u2,dsa->p,ctx,mont)) goto err; + /* let u1 = t1 * t2 mod p */ + if (!BN_mod_mul(&u1,&t1,&t2,dsa->p,ctx)) goto err_bn; + BN_free(&t2); + } + /* let u1 = u1 mod q */ + if (!BN_mod(&u1,&u1,dsa->q,ctx)) goto err; +#else + { + if (!dsa->meth->dsa_mod_exp(dsa, &t1,dsa->g,&u1,dsa->pub_key,&u2, + dsa->p,ctx,mont)) goto err; + /* BN_copy(&u1,&t1); */ + /* let u1 = u1 mod q */ + if (!BN_mod(&u1,&t1,dsa->q,ctx)) goto err; + } +#endif + /* V is now in u1. If the signature is correct, it will be + * equal to R. */ + ret=(BN_ucmp(&u1, sig->r) == 0); + + err: + if (ret != 1) DSAerr(DSA_F_DSA_DO_VERIFY,ERR_R_BN_LIB); + if (ctx != NULL) BN_CTX_free(ctx); + BN_free(&u1); + BN_free(&u2); + BN_free(&t1); + return(ret); + } + +static int dsa_init(DSA *dsa) +{ + dsa->flags|=DSA_FLAG_CACHE_MONT_P; + return(1); +} + +static int dsa_finish(DSA *dsa) +{ + if(dsa->method_mont_p) + BN_MONT_CTX_free((BN_MONT_CTX *)dsa->method_mont_p); + return(1); +} + +static int dsa_mod_exp(DSA *dsa, BIGNUM *rr, BIGNUM *a1, BIGNUM *p1, + BIGNUM *a2, BIGNUM *p2, BIGNUM *m, BN_CTX *ctx, + BN_MONT_CTX *in_mont) +{ + return BN_mod_exp2_mont(rr, a1, p1, a2, p2, m, ctx, in_mont); +} + +static int dsa_bn_mod_exp(DSA *dsa, BIGNUM *r, BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx, + BN_MONT_CTX *m_ctx) +{ + return BN_mod_exp_mont(r, a, p, m, ctx, m_ctx); +} diff --git a/libsecurity_apple_csp/open_ssl/dsa/dsa_sign.c b/libsecurity_apple_csp/open_ssl/dsa/dsa_sign.c new file mode 100644 index 00000000..e4d62a79 --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/dsa/dsa_sign.c @@ -0,0 +1,112 @@ +/* + * 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. + */ + + +/* crypto/dsa/dsa_sign.c */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +/* Original version from Steven Schoch */ + +#include +#include "cryptlib.h" +#include +#include +#include +#include + +DSA_SIG * DSA_do_sign(const unsigned char *dgst, int dlen, DSA *dsa) + { + return dsa->meth->dsa_do_sign(dgst, dlen, dsa); + } + +#ifndef _OPENSSL_APPLE_CDSA_ +int DSA_sign(int type, const unsigned char *dgst, int dlen, unsigned char *sig, + unsigned int *siglen, DSA *dsa) + { + DSA_SIG *s; + s=DSA_do_sign(dgst,dlen,dsa); + if (s == NULL) + { + *siglen=0; + return(0); + } + *siglen=i2d_DSA_SIG(s,&sig); + DSA_SIG_free(s); + return(1); + } +#endif /* _OPENSSL_APPLE_CDSA_ */ + +int DSA_sign_setup(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp) + { + return dsa->meth->dsa_sign_setup(dsa, ctx_in, kinvp, rp); + } + diff --git a/libsecurity_apple_csp/open_ssl/dsa/dsa_vrf.c b/libsecurity_apple_csp/open_ssl/dsa/dsa_vrf.c new file mode 100644 index 00000000..1ed605b7 --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/dsa/dsa_vrf.c @@ -0,0 +1,114 @@ +/* + * 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. + */ + + +/* crypto/dsa/dsa_vrf.c */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +/* Original version from Steven Schoch */ + +#include +#include "cryptlib.h" +#include +#include +#include +#include +//#include + +int DSA_do_verify(const unsigned char *dgst, int dgst_len, DSA_SIG *sig, + DSA *dsa) + { + return dsa->meth->dsa_do_verify(dgst, dgst_len, sig, dsa); + } + +/* data has already been hashed (probably with SHA or SHA-1). */ +/* returns + * 1: correct signature + * 0: incorrect signature + * -1: error + */ +#ifndef _OPENSSL_APPLE_CDSA_ +int DSA_verify(int type, const unsigned char *dgst, int dgst_len, + unsigned char *sigbuf, int siglen, DSA *dsa) + { + DSA_SIG *s; + int ret=-1; + + s = DSA_SIG_new(); + if (s == NULL) return(ret); + if (d2i_DSA_SIG(&s,&sigbuf,siglen) == NULL) goto err; + ret=DSA_do_verify(dgst,dgst_len,s,dsa); +err: + DSA_SIG_free(s); + return(ret); + } +#endif /* _OPENSSL_APPLE_CDSA_ */ diff --git a/libsecurity_apple_csp/open_ssl/err/err.c b/libsecurity_apple_csp/open_ssl/err/err.c new file mode 100644 index 00000000..32325ca1 --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/err/err.c @@ -0,0 +1,781 @@ +/* + * 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. + */ + + +/* crypto/err/err.c */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright (c) 1998-2000 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include +#include +#include +#include +#include +#include +#include "cryptlib.h" +#include +#include +#include + + +static LHASH *error_hash=NULL; +static LHASH *thread_hash=NULL; + +static unsigned long err_hash(ERR_STRING_DATA *a); +static int err_cmp(ERR_STRING_DATA *a, ERR_STRING_DATA *b); +static unsigned long pid_hash(ERR_STATE *pid); +static int pid_cmp(ERR_STATE *a,ERR_STATE *pid); +static unsigned long get_error_values(int inc,const char **file,int *line, + const char **data,int *flags); +static void ERR_STATE_free(ERR_STATE *s); +#ifndef NO_ERR +static ERR_STRING_DATA ERR_str_libraries[]= + { +{ERR_PACK(ERR_LIB_NONE,0,0) ,"unknown library"}, +{ERR_PACK(ERR_LIB_SYS,0,0) ,"system library"}, +{ERR_PACK(ERR_LIB_BN,0,0) ,"bignum routines"}, +{ERR_PACK(ERR_LIB_RSA,0,0) ,"rsa routines"}, +{ERR_PACK(ERR_LIB_DH,0,0) ,"Diffie-Hellman routines"}, +{ERR_PACK(ERR_LIB_EVP,0,0) ,"digital envelope routines"}, +{ERR_PACK(ERR_LIB_BUF,0,0) ,"memory buffer routines"}, +{ERR_PACK(ERR_LIB_BIO,0,0) ,"BIO routines"}, +{ERR_PACK(ERR_LIB_OBJ,0,0) ,"object identifier routines"}, +{ERR_PACK(ERR_LIB_PEM,0,0) ,"PEM routines"}, +{ERR_PACK(ERR_LIB_ASN1,0,0) ,"asn1 encoding routines"}, +{ERR_PACK(ERR_LIB_X509,0,0) ,"x509 certificate routines"}, +{ERR_PACK(ERR_LIB_CONF,0,0) ,"configuration file routines"}, +{ERR_PACK(ERR_LIB_METH,0,0) ,"X509 lookup 'method' routines"}, +{ERR_PACK(ERR_LIB_SSL,0,0) ,"SSL routines"}, +{ERR_PACK(ERR_LIB_RSAREF,0,0) ,"RSAref routines"}, +{ERR_PACK(ERR_LIB_PROXY,0,0) ,"Proxy routines"}, +{ERR_PACK(ERR_LIB_BIO,0,0) ,"BIO routines"}, +{ERR_PACK(ERR_LIB_PKCS7,0,0) ,"PKCS7 routines"}, +{ERR_PACK(ERR_LIB_X509V3,0,0) ,"X509 V3 routines"}, +{ERR_PACK(ERR_LIB_PKCS12,0,0) ,"PKCS12 routines"}, +{ERR_PACK(ERR_LIB_RAND,0,0) ,"random number generator"}, +{0,NULL}, + }; + +static ERR_STRING_DATA ERR_str_functs[]= + { + {ERR_PACK(0,SYS_F_FOPEN,0), "fopen"}, + {ERR_PACK(0,SYS_F_CONNECT,0), "connect"}, + {ERR_PACK(0,SYS_F_GETSERVBYNAME,0), "getservbyname"}, + {ERR_PACK(0,SYS_F_SOCKET,0), "socket"}, + {ERR_PACK(0,SYS_F_IOCTLSOCKET,0), "ioctlsocket"}, + {ERR_PACK(0,SYS_F_BIND,0), "bind"}, + {ERR_PACK(0,SYS_F_LISTEN,0), "listen"}, + {ERR_PACK(0,SYS_F_ACCEPT,0), "accept"}, +#ifdef WINDOWS + {ERR_PACK(0,SYS_F_WSASTARTUP,0), "WSAstartup"}, +#endif + {ERR_PACK(0,SYS_F_OPENDIR,0), "opendir"}, + {0,NULL}, + }; + +static ERR_STRING_DATA ERR_str_reasons[]= + { +{ERR_R_FATAL ,"fatal"}, +{ERR_R_SYS_LIB ,"system lib"}, +{ERR_R_BN_LIB ,"BN lib"}, +{ERR_R_RSA_LIB ,"RSA lib"}, +{ERR_R_DH_LIB ,"DH lib"}, +{ERR_R_EVP_LIB ,"EVP lib"}, +{ERR_R_BUF_LIB ,"BUF lib"}, +{ERR_R_BIO_LIB ,"BIO lib"}, +{ERR_R_OBJ_LIB ,"OBJ lib"}, +{ERR_R_PEM_LIB ,"PEM lib"}, +{ERR_R_X509_LIB ,"X509 lib"}, +{ERR_R_METH_LIB ,"METH lib"}, +{ERR_R_ASN1_LIB ,"ASN1 lib"}, +{ERR_R_CONF_LIB ,"CONF lib"}, +{ERR_R_SSL_LIB ,"SSL lib"}, +{ERR_R_PROXY_LIB ,"PROXY lib"}, +{ERR_R_BIO_LIB ,"BIO lib"}, +{ERR_R_PKCS7_LIB ,"PKCS7 lib"}, +{ERR_R_PKCS12_LIB ,"PKCS12 lib"}, +{ERR_R_MALLOC_FAILURE ,"Malloc failure"}, +{ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED ,"called a function you should not call"}, +{ERR_R_PASSED_NULL_PARAMETER ,"passed a null parameter"}, +{ERR_R_NESTED_ASN1_ERROR ,"nested asn1 error"}, +{ERR_R_BAD_ASN1_OBJECT_HEADER ,"bad asn1 object header"}, +{ERR_R_BAD_GET_ASN1_OBJECT_CALL ,"bad get asn1 object call"}, +{ERR_R_EXPECTING_AN_ASN1_SEQUENCE ,"expecting an asn1 sequence"}, +{ERR_R_ASN1_LENGTH_MISMATCH ,"asn1 length mismatch"}, +{ERR_R_MISSING_ASN1_EOS ,"missing asn1 eos"}, + +{0,NULL}, + }; + + +#define NUM_SYS_STR_REASONS 127 +#define LEN_SYS_STR_REASON 32 + +static ERR_STRING_DATA SYS_str_reasons[NUM_SYS_STR_REASONS + 1]; +/* SYS_str_reasons is filled with copies of strerror() results at + * initialization. + * 'errno' values up to 127 should cover all usual errors, + * others will be displayed numerically by ERR_error_string. + * It is crucial that we have something for each reason code + * that occurs in ERR_str_reasons, or bogus reason strings + * will be returned for SYSerr(), which always gets an errno + * value and never one of those 'standard' reason codes. */ + +static void build_SYS_str_reasons() + { + /* Malloc cannot be used here, use static storage instead */ + static char strerror_tab[NUM_SYS_STR_REASONS][LEN_SYS_STR_REASON]; + int i; + + CRYPTO_w_lock(CRYPTO_LOCK_ERR_HASH); + + for (i = 1; i <= NUM_SYS_STR_REASONS; i++) + { + ERR_STRING_DATA *str = &SYS_str_reasons[i - 1]; + + str->error = (unsigned long)i; + if (str->string == NULL) + { + char (*dest)[LEN_SYS_STR_REASON] = &(strerror_tab[i - 1]); + char *src = strerror(i); + if (src != NULL) + { + strncpy(*dest, src, sizeof *dest); + (*dest)[sizeof *dest - 1] = '\0'; + str->string = *dest; + } + } + if (str->string == NULL) + str->string = "unknown"; + } + + /* Now we still have SYS_str_reasons[NUM_SYS_STR_REASONS] = {0, NULL}, + * as required by ERR_load_strings. */ + + CRYPTO_w_unlock(CRYPTO_LOCK_ERR_HASH); + } +#endif + +#define err_clear_data(p,i) \ + if (((p)->err_data[i] != NULL) && \ + (p)->err_data_flags[i] & ERR_TXT_MALLOCED) \ + { \ + Free((p)->err_data[i]); \ + (p)->err_data[i]=NULL; \ + } \ + (p)->err_data_flags[i]=0; + +static void ERR_STATE_free(ERR_STATE *s) + { + int i; + + if(s == NULL) + return; + + for (i=0; ierror) + { + str->error|=ERR_PACK(lib,0,0); + lh_insert(error_hash,str); + str++; + } + CRYPTO_w_unlock(CRYPTO_LOCK_ERR_HASH); + } + +void ERR_free_strings(void) + { + CRYPTO_w_lock(CRYPTO_LOCK_ERR); + + if (error_hash != NULL) + { + lh_free(error_hash); + error_hash=NULL; + } + + CRYPTO_w_unlock(CRYPTO_LOCK_ERR); + } + +/********************************************************/ + +void ERR_put_error(int lib, int func, int reason, const char *file, + int line) + { + ERR_STATE *es; + +#ifdef _OSD_POSIX + /* In the BS2000-OSD POSIX subsystem, the compiler generates + * path names in the form "*POSIX(/etc/passwd)". + * This dirty hack strips them to something sensible. + * @@@ We shouldn't modify a const string, though. + */ + if (strncmp(file,"*POSIX(", sizeof("*POSIX(")-1) == 0) { + char *end; + + /* Skip the "*POSIX(" prefix */ + file += sizeof("*POSIX(")-1; + end = &file[strlen(file)-1]; + if (*end == ')') + *end = '\0'; + /* Optional: use the basename of the path only. */ + if ((end = strrchr(file, '/')) != NULL) + file = &end[1]; + } +#endif + es=ERR_get_state(); + + es->top=(es->top+1)%ERR_NUM_ERRORS; + if (es->top == es->bottom) + es->bottom=(es->bottom+1)%ERR_NUM_ERRORS; + es->err_buffer[es->top]=ERR_PACK(lib,func,reason); + es->err_file[es->top]=file; + es->err_line[es->top]=line; + err_clear_data(es,es->top); + } + +void ERR_clear_error(void) + { + ERR_STATE *es; + + es=ERR_get_state(); + +#if 0 + /* hmm... is this needed */ + for (i=0; ierr_buffer[i]=0; + es->err_file[i]=NULL; + es->err_line[i]= -1; + err_clear_data(es,i); + } +#endif + es->top=es->bottom=0; + } + + +unsigned long ERR_get_error(void) + { return(get_error_values(1,NULL,NULL,NULL,NULL)); } + +unsigned long ERR_get_error_line(const char **file, + int *line) + { return(get_error_values(1,file,line,NULL,NULL)); } + +unsigned long ERR_get_error_line_data(const char **file, int *line, + const char **data, int *flags) + { return(get_error_values(1,file,line, + data,flags)); } + +unsigned long ERR_peek_error(void) + { return(get_error_values(0,NULL,NULL,NULL,NULL)); } + +unsigned long ERR_peek_error_line(const char **file, + int *line) + { return(get_error_values(0,file,line,NULL,NULL)); } + +unsigned long ERR_peek_error_line_data(const char **file, int *line, + const char **data, int *flags) + { return(get_error_values(0,file,line, + data,flags)); } + +static unsigned long get_error_values(int inc, const char **file, int *line, + const char **data, int *flags) + { + int i=0; + ERR_STATE *es; + unsigned long ret; + + es=ERR_get_state(); + + if (es->bottom == es->top) return(0); + i=(es->bottom+1)%ERR_NUM_ERRORS; + + ret=es->err_buffer[i]; + if (inc) + { + es->bottom=i; + es->err_buffer[i]=0; + } + + if ((file != NULL) && (line != NULL)) + { + if (es->err_file[i] == NULL) + { + *file="NA"; + if (line != NULL) *line=0; + } + else + { + *file=es->err_file[i]; + if (line != NULL) *line=es->err_line[i]; + } + } + + if (data != NULL) + { + if (es->err_data[i] == NULL) + { + *data=""; + if (flags != NULL) *flags=0; + } + else + { + *data=es->err_data[i]; + if (flags != NULL) *flags=es->err_data_flags[i]; + } + } + return(ret); + } + +/* BAD for multi-threaded, uses a local buffer if ret == NULL */ +char *ERR_error_string(unsigned long e, char *ret) + { + #ifdef NO_ERR + if(ret != NULL) { + strcpy(ret, "No Error String Info."); + } + return "No Error String info."; + #else + static char buf[256]; + const char *ls,*fs,*rs; + unsigned long l,f,r; + int i; + + l=ERR_GET_LIB(e); + f=ERR_GET_FUNC(e); + r=ERR_GET_REASON(e); + + ls=ERR_lib_error_string(e); + fs=ERR_func_error_string(e); + rs=ERR_reason_error_string(e); + + if (ret == NULL) ret=buf; + + sprintf(&(ret[0]),"error:%08lX:",e); + i=strlen(ret); + if (ls == NULL) + sprintf(&(ret[i]),":lib(%lu) ",l); + else sprintf(&(ret[i]),"%s",ls); + i=strlen(ret); + if (fs == NULL) + sprintf(&(ret[i]),":func(%lu) ",f); + else sprintf(&(ret[i]),":%s",fs); + i=strlen(ret); + if (rs == NULL) + sprintf(&(ret[i]),":reason(%lu)",r); + else sprintf(&(ret[i]),":%s",rs); + + return(ret); + #endif + } + +LHASH *ERR_get_string_table(void) + { + return(error_hash); + } + +LHASH *ERR_get_err_state_table(void) + { + return(thread_hash); + } + +const char *ERR_lib_error_string(unsigned long e) + { + ERR_STRING_DATA d,*p=NULL; + unsigned long l; + + l=ERR_GET_LIB(e); + + CRYPTO_r_lock(CRYPTO_LOCK_ERR_HASH); + + if (error_hash != NULL) + { + d.error=ERR_PACK(l,0,0); + p=(ERR_STRING_DATA *)lh_retrieve(error_hash,&d); + } + + CRYPTO_r_unlock(CRYPTO_LOCK_ERR_HASH); + + return((p == NULL)?NULL:p->string); + } + +const char *ERR_func_error_string(unsigned long e) + { + ERR_STRING_DATA d,*p=NULL; + unsigned long l,f; + + l=ERR_GET_LIB(e); + f=ERR_GET_FUNC(e); + + CRYPTO_r_lock(CRYPTO_LOCK_ERR_HASH); + + if (error_hash != NULL) + { + d.error=ERR_PACK(l,f,0); + p=(ERR_STRING_DATA *)lh_retrieve(error_hash,&d); + } + + CRYPTO_r_unlock(CRYPTO_LOCK_ERR_HASH); + + return((p == NULL)?NULL:p->string); + } + +const char *ERR_reason_error_string(unsigned long e) + { + ERR_STRING_DATA d,*p=NULL; + unsigned long l,r; + + l=ERR_GET_LIB(e); + r=ERR_GET_REASON(e); + + CRYPTO_r_lock(CRYPTO_LOCK_ERR_HASH); + + if (error_hash != NULL) + { + d.error=ERR_PACK(l,0,r); + p=(ERR_STRING_DATA *)lh_retrieve(error_hash,&d); + if (p == NULL) + { + d.error=ERR_PACK(0,0,r); + p=(ERR_STRING_DATA *)lh_retrieve(error_hash,&d); + } + } + + CRYPTO_r_unlock(CRYPTO_LOCK_ERR_HASH); + + return((p == NULL)?NULL:p->string); + } + +static unsigned long err_hash(ERR_STRING_DATA *a) + { + unsigned long ret,l; + + l=a->error; + ret=l^ERR_GET_LIB(l)^ERR_GET_FUNC(l); + return(ret^ret%19*13); + } + +static int err_cmp(ERR_STRING_DATA *a, ERR_STRING_DATA *b) + { + return((int)(a->error-b->error)); + } + +static unsigned long pid_hash(ERR_STATE *a) + { + return(a->pid*13); + } + +static int pid_cmp(ERR_STATE *a, ERR_STATE *b) + { + return((int)((long)a->pid - (long)b->pid)); + } + +void ERR_remove_state(unsigned long pid) + { + ERR_STATE *p,tmp; + + if (thread_hash == NULL) + return; + if (pid == 0) + pid=(unsigned long)CRYPTO_thread_id(); + tmp.pid=pid; + CRYPTO_w_lock(CRYPTO_LOCK_ERR); + p=(ERR_STATE *)lh_delete(thread_hash,&tmp); + CRYPTO_w_unlock(CRYPTO_LOCK_ERR); + + if (p != NULL) ERR_STATE_free(p); + } + +static ERR_STATE *fallback = NULL; +static ERR_STATE *getFallback() +{ + if(fallback == NULL) { + fallback = (ERR_STATE *)Malloc(sizeof(ERR_STATE)); + } + return fallback; +} + +ERR_STATE *ERR_get_state(void) + { + ERR_STATE *ret=NULL,tmp,*tmpp; + int i; + unsigned long pid; + + pid=(unsigned long)CRYPTO_thread_id(); + + CRYPTO_r_lock(CRYPTO_LOCK_ERR); + if (thread_hash == NULL) + { + CRYPTO_r_unlock(CRYPTO_LOCK_ERR); + CRYPTO_w_lock(CRYPTO_LOCK_ERR); + if (thread_hash == NULL) + { + MemCheck_off(); + thread_hash=lh_new(pid_hash,pid_cmp); + MemCheck_on(); + CRYPTO_w_unlock(CRYPTO_LOCK_ERR); + if (thread_hash == NULL) return(getFallback()); + } + else + CRYPTO_w_unlock(CRYPTO_LOCK_ERR); + } + else + { + tmp.pid=pid; + ret=(ERR_STATE *)lh_retrieve(thread_hash,&tmp); + CRYPTO_r_unlock(CRYPTO_LOCK_ERR); + } + + /* ret == the error state, if NULL, make a new one */ + if (ret == NULL) + { + ret=(ERR_STATE *)Malloc(sizeof(ERR_STATE)); + if (ret == NULL) return(getFallback()); + ret->pid=pid; + ret->top=0; + ret->bottom=0; + for (i=0; ierr_data[i]=NULL; + ret->err_data_flags[i]=0; + } + CRYPTO_w_lock(CRYPTO_LOCK_ERR); + tmpp=(ERR_STATE *)lh_insert(thread_hash,ret); + CRYPTO_w_unlock(CRYPTO_LOCK_ERR); + if (tmpp != NULL) /* old entry - should not happen */ + { + ERR_STATE_free(tmpp); + } + } + return(ret); + } + +int ERR_get_next_error_library(void) + { + static int value=ERR_LIB_USER; + + return(value++); + } + +void ERR_set_error_data(char *data, int flags) + { + ERR_STATE *es; + int i; + + es=ERR_get_state(); + + i=es->top; + if (i == 0) + i=ERR_NUM_ERRORS-1; + + es->err_data[i]=data; + es->err_data_flags[es->top]=flags; + } + +void ERR_add_error_data(int num, ...) + { + va_list args; + int i,n,s; + char *str,*p,*a; + + s=64; + str=Malloc(s+1); + if (str == NULL) return; + str[0]='\0'; + + va_start(args, num); + n=0; + for (i=0; i */ + if (a != NULL) + { + n+=strlen(a); + if (n > s) + { + s=n+20; + p=Realloc(str,s+1); + if (p == NULL) + { + Free(str); + return; + } + else + str=p; + } + strcat(str,a); + } + } + ERR_set_error_data(str,ERR_TXT_MALLOCED|ERR_TXT_STRING); + + va_end(args); + } + diff --git a/libsecurity_apple_csp/open_ssl/err/err_prn.c b/libsecurity_apple_csp/open_ssl/err/err_prn.c new file mode 100644 index 00000000..a878c75f --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/err/err_prn.c @@ -0,0 +1,123 @@ +/* + * 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. + */ + + +/* crypto/err/err_prn.c */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include +#include +#include +#include "cryptlib.h" +#include +#include +#include + +#ifndef NO_FP_API +void ERR_print_errors_fp(FILE *fp) + { + unsigned long l; + char buf[200]; + const char *file,*data; + int line,flags; + unsigned long es; + + es=CRYPTO_thread_id(); + while ((l=ERR_get_error_line_data(&file,&line,&data,&flags)) != 0) + { + fprintf(fp,"%lu:%s:%s:%d:%s\n",es,ERR_error_string(l,buf), + file,line,(flags&ERR_TXT_STRING)?data:""); + } + } +#endif + +void ERR_print_errors(BIO *bp) + { + unsigned long l; + char buf[256]; + char buf2[256]; + const char *file,*data; + int line,flags; + unsigned long es; + + es=CRYPTO_thread_id(); + while ((l=ERR_get_error_line_data(&file,&line,&data,&flags)) != 0) + { + sprintf(buf2,"%lu:%s:%s:%d:",es,ERR_error_string(l,buf), + file,line); + BIO_write(bp,buf2,strlen(buf2)); + if (flags & ERR_TXT_STRING) + BIO_write(bp,data,strlen(data)); + BIO_write(bp,"\n",1); + } + } + diff --git a/libsecurity_apple_csp/open_ssl/ex_data.c b/libsecurity_apple_csp/open_ssl/ex_data.c new file mode 100644 index 00000000..faadeea2 --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/ex_data.c @@ -0,0 +1,241 @@ +/* + * 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. + */ + + +/* crypto/ex_data.c */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include +#include +#include +#include +#include +#include "cryptlib.h" + +int CRYPTO_get_ex_new_index(int idx, STACK_OF(CRYPTO_EX_DATA_FUNCS) **skp, long argl, void *argp, + CRYPTO_EX_new *new_func, CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func) + { + int ret= -1; + CRYPTO_EX_DATA_FUNCS *a; + + MemCheck_off(); + if (*skp == NULL) + *skp=sk_CRYPTO_EX_DATA_FUNCS_new_null(); + if (*skp == NULL) + { + CRYPTOerr(CRYPTO_F_CRYPTO_GET_EX_NEW_INDEX,ERR_R_MALLOC_FAILURE); + goto err; + } + a=(CRYPTO_EX_DATA_FUNCS *)Malloc(sizeof(CRYPTO_EX_DATA_FUNCS)); + if (a == NULL) + { + CRYPTOerr(CRYPTO_F_CRYPTO_GET_EX_NEW_INDEX,ERR_R_MALLOC_FAILURE); + goto err; + } + a->argl=argl; + a->argp=argp; + a->new_func=new_func; + a->dup_func=dup_func; + a->free_func=free_func; + while (sk_CRYPTO_EX_DATA_FUNCS_num(*skp) <= idx) + { + if (!sk_CRYPTO_EX_DATA_FUNCS_push(*skp,NULL)) + { + CRYPTOerr(CRYPTO_F_CRYPTO_GET_EX_NEW_INDEX,ERR_R_MALLOC_FAILURE); + Free(a); + goto err; + } + } + sk_CRYPTO_EX_DATA_FUNCS_set(*skp,idx, a); + ret=idx; +err: + MemCheck_on(); + return(idx); + } + +int CRYPTO_set_ex_data(CRYPTO_EX_DATA *ad, int idx, void *val) + { + int i; + + if (ad->sk == NULL) + { + if ((ad->sk=sk_new_null()) == NULL) + { + CRYPTOerr(CRYPTO_F_CRYPTO_SET_EX_DATA,ERR_R_MALLOC_FAILURE); + return(0); + } + } + i=sk_num(ad->sk); + + while (i <= idx) + { + if (!sk_push(ad->sk,NULL)) + { + CRYPTOerr(CRYPTO_F_CRYPTO_SET_EX_DATA,ERR_R_MALLOC_FAILURE); + return(0); + } + i++; + } + sk_set(ad->sk,idx,val); + return(1); + } + +void *CRYPTO_get_ex_data(CRYPTO_EX_DATA *ad, int idx) + { + if (ad->sk == NULL) + return(0); + else if (idx >= sk_num(ad->sk)) + return(0); + else + return(sk_value(ad->sk,idx)); + } + +/* The callback is called with the 'object', which is the original data object + * being duplicated, a pointer to the + * 'new' object to be inserted, the index, and the argi/argp + */ +int CRYPTO_dup_ex_data(STACK_OF(CRYPTO_EX_DATA_FUNCS) *meth, CRYPTO_EX_DATA *to, + CRYPTO_EX_DATA *from) + { + int i,j,m,r; + CRYPTO_EX_DATA_FUNCS *mm; + char *from_d; + + if (meth == NULL) return(1); + if (from->sk == NULL) return(1); + m=sk_CRYPTO_EX_DATA_FUNCS_num(meth); + j=sk_num(from->sk); + for (i=0; idup_func != NULL) + r=mm->dup_func(to,from,(char **)&from_d,i, + mm->argl,mm->argp); + } + CRYPTO_set_ex_data(to,i,from_d); + } + return(1); + } + +/* Call each free callback */ +void CRYPTO_free_ex_data(STACK_OF(CRYPTO_EX_DATA_FUNCS) *meth, void *obj, CRYPTO_EX_DATA *ad) + { + CRYPTO_EX_DATA_FUNCS *m; + void *ptr; + int i,max; + + if (meth != NULL) + { + max=sk_CRYPTO_EX_DATA_FUNCS_num(meth); + for (i=0; ifree_func != NULL)) + { + ptr=CRYPTO_get_ex_data(ad,i); + m->free_func(obj,ptr,ad,i,m->argl,m->argp); + } + } + } + if (ad->sk != NULL) + { + sk_free(ad->sk); + ad->sk=NULL; + } + } + +void CRYPTO_new_ex_data(STACK_OF(CRYPTO_EX_DATA_FUNCS) *meth, void *obj, CRYPTO_EX_DATA *ad) + { + CRYPTO_EX_DATA_FUNCS *m; + void *ptr; + int i,max; + + ad->sk=NULL; + if (meth != NULL) + { + max=sk_CRYPTO_EX_DATA_FUNCS_num(meth); + for (i=0; inew_func != NULL)) + { + ptr=CRYPTO_get_ex_data(ad,i); + m->new_func(obj,ptr,ad,i,m->argl,m->argp); + } + } + } + } + +IMPLEMENT_STACK_OF(CRYPTO_EX_DATA_FUNCS) diff --git a/libsecurity_apple_csp/open_ssl/lhash/lhash.c b/libsecurity_apple_csp/open_ssl/lhash/lhash.c new file mode 100644 index 00000000..9169be4b --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/lhash/lhash.c @@ -0,0 +1,479 @@ +/* + * 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. + */ + + +/* crypto/lhash/lhash.c */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +/* Code for dynamic hash table routines + * Author - Eric Young v 2.0 + * + * 2.2 eay - added #include "crypto.h" so the memory leak checking code is + * present. eay 18-Jun-98 + * + * 2.1 eay - Added an 'error in last operation' flag. eay 6-May-98 + * + * 2.0 eay - Fixed a bug that occurred when using lh_delete + * from inside lh_doall(). As entries were deleted, + * the 'table' was 'contract()ed', making some entries + * jump from the end of the table to the start, there by + * skipping the lh_doall() processing. eay - 4/12/95 + * + * 1.9 eay - Fixed a memory leak in lh_free, the LHASH_NODEs + * were not being free()ed. 21/11/95 + * + * 1.8 eay - Put the stats routines into a separate file, lh_stats.c + * 19/09/95 + * + * 1.7 eay - Removed the fputs() for realloc failures - the code + * should silently tolerate them. I have also fixed things + * lint complained about 04/05/95 + * + * 1.6 eay - Fixed an invalid pointers in contract/expand 27/07/92 + * + * 1.5 eay - Fixed a misuse of realloc in expand 02/03/1992 + * + * 1.4 eay - Fixed lh_doall so the function can call lh_delete 28/05/91 + * + * 1.3 eay - Fixed a few lint problems 19/3/1991 + * + * 1.2 eay - Fixed lh_doall problem 13/3/1991 + * + * 1.1 eay - Added lh_doall + * + * 1.0 eay - First version + */ +#include +#include +#include +#include +#include + +const char *lh_version="lhash" OPENSSL_VERSION_PTEXT; + +#undef MIN_NODES +#define MIN_NODES 16 +#define UP_LOAD (2*LH_LOAD_MULT) /* load times 256 (default 2) */ +#define DOWN_LOAD (LH_LOAD_MULT) /* load times 256 (default 1) */ + +static void expand(LHASH *lh); +static void contract(LHASH *lh); +static LHASH_NODE **getrn(LHASH *lh, void *data, unsigned long *rhash); + +LHASH *lh_new(unsigned long (*h)(), int (*c)()) + { + LHASH *ret; + int i; + + if ((ret=(LHASH *)Malloc(sizeof(LHASH))) == NULL) + goto err0; + if ((ret->b=(LHASH_NODE **)Malloc(sizeof(LHASH_NODE *)*MIN_NODES)) == NULL) + goto err1; + for (i=0; ib[i]=NULL; + ret->comp=((c == NULL)?(int (*)())strcmp:c); + ret->hash=((h == NULL)?(unsigned long (*)())lh_strhash:h); + ret->num_nodes=MIN_NODES/2; + ret->num_alloc_nodes=MIN_NODES; + ret->p=0; + ret->pmax=MIN_NODES/2; + ret->up_load=UP_LOAD; + ret->down_load=DOWN_LOAD; + ret->num_items=0; + + ret->num_expands=0; + ret->num_expand_reallocs=0; + ret->num_contracts=0; + ret->num_contract_reallocs=0; + ret->num_hash_calls=0; + ret->num_comp_calls=0; + ret->num_insert=0; + ret->num_replace=0; + ret->num_delete=0; + ret->num_no_delete=0; + ret->num_retrieve=0; + ret->num_retrieve_miss=0; + ret->num_hash_comps=0; + + ret->error=0; + return(ret); +err1: + Free(ret); +err0: + return(NULL); + } + +void lh_free(LHASH *lh) + { + unsigned int i; + LHASH_NODE *n,*nn; + + if (lh == NULL) + return; + + for (i=0; inum_nodes; i++) + { + n=lh->b[i]; + while (n != NULL) + { + nn=n->next; + Free(n); + n=nn; + } + } + Free(lh->b); + Free(lh); + } + +void *lh_insert(LHASH *lh, void *data) + { + unsigned long hash; + LHASH_NODE *nn,**rn; + void *ret; + + lh->error=0; + if (lh->up_load <= (lh->num_items*LH_LOAD_MULT/lh->num_nodes)) + expand(lh); + + rn=getrn(lh,data,&hash); + + if (*rn == NULL) + { + if ((nn=(LHASH_NODE *)Malloc(sizeof(LHASH_NODE))) == NULL) + { + lh->error++; + return(NULL); + } + nn->data=data; + nn->next=NULL; +#ifndef NO_HASH_COMP + nn->hash=hash; +#endif + *rn=nn; + ret=NULL; + lh->num_insert++; + lh->num_items++; + } + else /* replace same key */ + { + ret= (*rn)->data; + (*rn)->data=data; + lh->num_replace++; + } + return(ret); + } + +void *lh_delete(LHASH *lh, void *data) + { + unsigned long hash; + LHASH_NODE *nn,**rn; + void *ret; + + lh->error=0; + rn=getrn(lh,data,&hash); + + if (*rn == NULL) + { + lh->num_no_delete++; + return(NULL); + } + else + { + nn= *rn; + *rn=nn->next; + ret=nn->data; + Free(nn); + lh->num_delete++; + } + + lh->num_items--; + if ((lh->num_nodes > MIN_NODES) && + (lh->down_load >= (lh->num_items*LH_LOAD_MULT/lh->num_nodes))) + contract(lh); + + return(ret); + } + +void *lh_retrieve(LHASH *lh, void *data) + { + unsigned long hash; + LHASH_NODE **rn; + void *ret; + + lh->error=0; + rn=getrn(lh,data,&hash); + + if (*rn == NULL) + { + lh->num_retrieve_miss++; + return(NULL); + } + else + { + ret= (*rn)->data; + lh->num_retrieve++; + } + return(ret); + } + +void lh_doall(LHASH *lh, void (*func)()) + { + lh_doall_arg(lh,func,NULL); + } + +void lh_doall_arg(LHASH *lh, void (*func)(), void *arg) + { + int i; + LHASH_NODE *a,*n; + + /* reverse the order so we search from 'top to bottom' + * We were having memory leaks otherwise */ + for (i=lh->num_nodes-1; i>=0; i--) + { + a=lh->b[i]; + while (a != NULL) + { + /* 28/05/91 - eay - n added so items can be deleted + * via lh_doall */ + n=a->next; + func(a->data,arg); + a=n; + } + } + } + +static void expand(LHASH *lh) + { + LHASH_NODE **n,**n1,**n2,*np; + unsigned int p,i,j; + unsigned long hash,nni; + + lh->num_nodes++; + lh->num_expands++; + p=(int)lh->p++; + n1= &(lh->b[p]); + n2= &(lh->b[p+(int)lh->pmax]); + *n2=NULL; /* 27/07/92 - eay - undefined pointer bug */ + nni=lh->num_alloc_nodes; + + for (np= *n1; np != NULL; ) + { +#ifndef NO_HASH_COMP + hash=np->hash; +#else + hash=(*(lh->hash))(np->data); + lh->num_hash_calls++; +#endif + if ((hash%nni) != p) + { /* move it */ + *n1= (*n1)->next; + np->next= *n2; + *n2=np; + } + else + n1= &((*n1)->next); + np= *n1; + } + + if ((lh->p) >= lh->pmax) + { + j=(int)lh->num_alloc_nodes*2; + n=(LHASH_NODE **)Realloc(lh->b, + (unsigned int)sizeof(LHASH_NODE *)*j); + if (n == NULL) + { +/* fputs("realloc error in lhash",stderr); */ + lh->error++; + lh->p=0; + return; + } + /* else */ + for (i=(int)lh->num_alloc_nodes; ipmax=lh->num_alloc_nodes; + lh->num_alloc_nodes=j; + lh->num_expand_reallocs++; + lh->p=0; + lh->b=n; + } + } + +static void contract(LHASH *lh) + { + LHASH_NODE **n,*n1,*np; + + np=lh->b[lh->p+lh->pmax-1]; + lh->b[lh->p+lh->pmax-1]=NULL; /* 24/07-92 - eay - weird but :-( */ + if (lh->p == 0) + { + n=(LHASH_NODE **)Realloc(lh->b, + (unsigned int)(sizeof(LHASH_NODE *)*lh->pmax)); + if (n == NULL) + { +/* fputs("realloc error in lhash",stderr); */ + lh->error++; + return; + } + lh->num_contract_reallocs++; + lh->num_alloc_nodes/=2; + lh->pmax/=2; + lh->p=lh->pmax-1; + lh->b=n; + } + else + lh->p--; + + lh->num_nodes--; + lh->num_contracts++; + + n1=lh->b[(int)lh->p]; + if (n1 == NULL) + lh->b[(int)lh->p]=np; + else + { + while (n1->next != NULL) + n1=n1->next; + n1->next=np; + } + } + +static LHASH_NODE **getrn(LHASH *lh, void *data, unsigned long *rhash) + { + LHASH_NODE **ret,*n1; + unsigned long hash,nn; + int (*cf)(); + + hash=(*(lh->hash))(data); + lh->num_hash_calls++; + *rhash=hash; + + nn=hash%lh->pmax; + if (nn < lh->p) + nn=hash%lh->num_alloc_nodes; + + cf=lh->comp; + ret= &(lh->b[(int)nn]); + for (n1= *ret; n1 != NULL; n1=n1->next) + { +#ifndef NO_HASH_COMP + lh->num_hash_comps++; + if (n1->hash != hash) + { + ret= &(n1->next); + continue; + } +#endif + lh->num_comp_calls++; + if ((*cf)(n1->data,data) == 0) + break; + ret= &(n1->next); + } + return(ret); + } + +/* The following hash seems to work very well on normal text strings + * no collisions on /usr/dict/words and it distributes on %2^n quite + * well, not as good as MD5, but still good. + */ +unsigned long lh_strhash(const char *c) + { + unsigned long ret=0; + long n; + unsigned long v; + int r; + + if ((c == NULL) || (*c == '\0')) + return(ret); +/* + unsigned char b[16]; + MD5(c,strlen(c),b); + return(b[0]|(b[1]<<8)|(b[2]<<16)|(b[3]<<24)); +*/ + + n=0x100; + while (*c) + { + v=n|(*c); + n+=0x100; + r= (int)((v>>2)^v)&0x0f; + ret=(ret<>(32-r)); + ret&=0xFFFFFFFFL; + ret^=v*v; + c++; + } + return((ret>>16)^ret); + } + +unsigned long lh_num_items(LHASH *lh) + { + return lh ? lh->num_items : 0; + } diff --git a/libsecurity_apple_csp/open_ssl/mem.c b/libsecurity_apple_csp/open_ssl/mem.c new file mode 100644 index 00000000..fd995d0c --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/mem.c @@ -0,0 +1,279 @@ +/* + * 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. + */ + + +/* crypto/mem.c */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include +#include +#include +#include "cryptlib.h" + + +static int allow_customize = 1; /* we provide flexible functions for */ +static int allow_customize_debug = 1;/* exchanging memory-related functions at + * run-time, but this must be done + * before any blocks are actually + * allocated; or we'll run into huge + * problems when malloc/free pairs + * don't match etc. */ + +/* may be changed as long as `allow_customize' is set */ +static void *(*malloc_locked_func)(size_t) = malloc; +static void (*free_locked_func)(void *) = free; +static void *(*malloc_func)(size_t) = malloc; +static void *(*realloc_func)(void *, size_t)= realloc; +static void (*free_func)(void *) = free; + +/* may be changed as long as `allow_customize_debug' is set */ +/* XXX use correct function pointer types */ +#ifdef CRYPTO_MDEBUG + /* use default functions from mem_dbg.c */ + static void (*malloc_debug_func)()= (void (*)())CRYPTO_dbg_malloc; + static void (*realloc_debug_func)()= (void (*)())CRYPTO_dbg_realloc; + static void (*free_debug_func)()= (void (*)())CRYPTO_dbg_free; + static void (*set_debug_options_func)()= (void (*)())CRYPTO_dbg_set_options; + static long (*get_debug_options_func)()= (long (*)())CRYPTO_dbg_get_options; +#else + /* applications can use CRYPTO_malloc_debug_init() to select above case + * at run-time */ + static void (*malloc_debug_func)()= NULL; + static void (*realloc_debug_func)()= NULL; + static void (*free_debug_func)()= NULL; + static void (*set_debug_options_func)()= NULL; + static long (*get_debug_options_func)()= NULL; +#endif + + +int CRYPTO_set_mem_functions(void *(*m)(size_t), void *(*r)(void *, size_t), + void (*f)(void *)) + { + if (!allow_customize) + return 0; + if ((m == NULL) || (r == NULL) || (f == NULL)) + return 0; + malloc_func=m; + realloc_func=r; + free_func=f; + malloc_locked_func=m; + free_locked_func=f; + return 1; + } + +int CRYPTO_set_locked_mem_functions(void *(*m)(size_t), void (*f)(void *)) + { + if (!allow_customize) + return 0; + if ((m == NULL) || (f == NULL)) + return 0; + malloc_locked_func=m; + free_locked_func=f; + return 1; + } + +int CRYPTO_set_mem_debug_functions(void (*m)(), void (*r)(), void (*f)(),void (*so)(),long (*go)()) + { + if (!allow_customize_debug) + return 0; + malloc_debug_func=m; + realloc_debug_func=r; + free_debug_func=f; + set_debug_options_func=so; + get_debug_options_func=go; + return 1; + } + +void CRYPTO_get_mem_functions(void *(**m)(size_t), void *(**r)(void *, size_t), + void (**f)(void *)) + { + if (m != NULL) *m=malloc_func; + if (r != NULL) *r=realloc_func; + if (f != NULL) *f=free_func; + } + +void CRYPTO_get_locked_mem_functions(void *(**m)(size_t), void (**f)(void *)) + { + if (m != NULL) *m=malloc_locked_func; + if (f != NULL) *f=free_locked_func; + } + +void CRYPTO_get_mem_debug_functions(void (**m)(), void (**r)(), void (**f)(),void (**so)(),long (**go)()) + { + if (m != NULL) *m=malloc_debug_func; + if (r != NULL) *r=realloc_debug_func; + if (f != NULL) *f=free_debug_func; + if (so != NULL) *so=set_debug_options_func; + if (go != NULL) *go=get_debug_options_func; + } + + +void *CRYPTO_malloc_locked(int num, const char *file, int line) + { + char *ret = NULL; + + allow_customize = 0; + if (malloc_debug_func != NULL) + { + allow_customize_debug = 0; + malloc_debug_func(NULL, num, file, line, 0); + } + ret = malloc_locked_func(num); +#ifdef LEVITTE_DEBUG + fprintf(stderr, "LEVITTE_DEBUG: > 0x%p (%d)\n", ret, num); +#endif + if (malloc_debug_func != NULL) + malloc_debug_func(ret, num, file, line, 1); + + return ret; + } + +void CRYPTO_free_locked(void *str) + { + if (free_debug_func != NULL) + free_debug_func(str, 0); +#ifdef LEVITTE_DEBUG + fprintf(stderr, "LEVITTE_DEBUG: < 0x%p\n", str); +#endif + free_locked_func(str); + if (free_debug_func != NULL) + free_debug_func(NULL, 1); + } + +void *CRYPTO_malloc(int num, const char *file, int line) + { + char *ret = NULL; + + allow_customize = 0; + if (malloc_debug_func != NULL) + { + allow_customize_debug = 0; + malloc_debug_func(NULL, num, file, line, 0); + } + ret = malloc_func(num); +#ifdef LEVITTE_DEBUG + fprintf(stderr, "LEVITTE_DEBUG: > 0x%p (%d)\n", ret, num); +#endif + if (malloc_debug_func != NULL) + malloc_debug_func(ret, num, file, line, 1); + + return ret; + } + +void *CRYPTO_realloc(void *str, int num, const char *file, int line) + { + char *ret = NULL; + + if (realloc_debug_func != NULL) + realloc_debug_func(str, NULL, num, file, line, 0); + ret = realloc_func(str,num); +#ifdef LEVITTE_DEBUG + fprintf(stderr, "LEVITTE_DEBUG: | 0x%p -> 0x%p (%d)\n", str, ret, num); +#endif + if (realloc_debug_func != NULL) + realloc_debug_func(str, ret, num, file, line, 1); + + return ret; + } + +void CRYPTO_free(void *str) + { + if (free_debug_func != NULL) + free_debug_func(str, 0); +#ifdef LEVITTE_DEBUG + fprintf(stderr, "LEVITTE_DEBUG: < 0x%p\n", str); +#endif + free_func(str); + if (free_debug_func != NULL) + free_debug_func(NULL, 1); + } + +void *CRYPTO_remalloc(void *a, int num, const char *file, int line) + { + if (a != NULL) Free(a); + a=(char *)Malloc(num); + return(a); + } + + +void CRYPTO_set_mem_debug_options(long bits) + { + if (set_debug_options_func != NULL) + set_debug_options_func(bits); + } + +long CRYPTO_get_mem_debug_options(void) + { + if (get_debug_options_func != NULL) + return get_debug_options_func(); + return 0; + } diff --git a/libsecurity_apple_csp/open_ssl/misc/rc2_cbc.c b/libsecurity_apple_csp/open_ssl/misc/rc2_cbc.c new file mode 100644 index 00000000..f53628c4 --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/misc/rc2_cbc.c @@ -0,0 +1,256 @@ +/* + * 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. + */ + + +/* crypto/rc2/rc2_cbc.c */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include +#include "rc2_locl.h" + +#ifndef _OPENSSL_APPLE_CDSA_ + +void RC2_cbc_encrypt(unsigned char *in, unsigned char *out, long length, + RC2_KEY *ks, unsigned char *iv, int encrypt) + { + register unsigned long tin0,tin1; + register unsigned long tout0,tout1,xor0,xor1; + register long l=length; + unsigned long tin[2]; + + if (encrypt) + { + c2l(iv,tout0); + c2l(iv,tout1); + iv-=8; + for (l-=8; l>=0; l-=8) + { + c2l(in,tin0); + c2l(in,tin1); + tin0^=tout0; + tin1^=tout1; + tin[0]=tin0; + tin[1]=tin1; + RC2_encrypt(tin,ks); + tout0=tin[0]; l2c(tout0,out); + tout1=tin[1]; l2c(tout1,out); + } + if (l != -8) + { + c2ln(in,tin0,tin1,l+8); + tin0^=tout0; + tin1^=tout1; + tin[0]=tin0; + tin[1]=tin1; + RC2_encrypt(tin,ks); + tout0=tin[0]; l2c(tout0,out); + tout1=tin[1]; l2c(tout1,out); + } + l2c(tout0,iv); + l2c(tout1,iv); + } + else + { + c2l(iv,xor0); + c2l(iv,xor1); + iv-=8; + for (l-=8; l>=0; l-=8) + { + c2l(in,tin0); tin[0]=tin0; + c2l(in,tin1); tin[1]=tin1; + RC2_decrypt(tin,ks); + tout0=tin[0]^xor0; + tout1=tin[1]^xor1; + l2c(tout0,out); + l2c(tout1,out); + xor0=tin0; + xor1=tin1; + } + if (l != -8) + { + c2l(in,tin0); tin[0]=tin0; + c2l(in,tin1); tin[1]=tin1; + RC2_decrypt(tin,ks); + tout0=tin[0]^xor0; + tout1=tin[1]^xor1; + l2cn(tout0,tout1,out,l+8); + xor0=tin0; + xor1=tin1; + } + l2c(xor0,iv); + l2c(xor1,iv); + } + tin0=tin1=tout0=tout1=xor0=xor1=0; + tin[0]=tin[1]=0; + } + +#endif /* _OPENSSL_APPLE_CDSA_ */ + +#ifdef _OPENSSL_APPLE_CDSA_ +void RC2_encrypt(RC2_INT *d, RC2_KEY *key) +#else +void RC2_encrypt(unsigned long *d, RC2_KEY *key) +#endif + { + int i,n; + register RC2_INT *p0,*p1; + register RC2_INT x0,x1,x2,x3,t; + unsigned long l; + + l=d[0]; + x0=(RC2_INT)l&0xffff; + x1=(RC2_INT)(l>>16L); + l=d[1]; + x2=(RC2_INT)l&0xffff; + x3=(RC2_INT)(l>>16L); + + n=3; + i=5; + + p0=p1= &(key->data[0]); + for (;;) + { + t=(x0+(x1& ~x3)+(x2&x3)+ *(p0++))&0xffff; + x0=(t<<1)|(t>>15); + t=(x1+(x2& ~x0)+(x3&x0)+ *(p0++))&0xffff; + x1=(t<<2)|(t>>14); + t=(x2+(x3& ~x1)+(x0&x1)+ *(p0++))&0xffff; + x2=(t<<3)|(t>>13); + t=(x3+(x0& ~x2)+(x1&x2)+ *(p0++))&0xffff; + x3=(t<<5)|(t>>11); + + if (--i == 0) + { + if (--n == 0) break; + i=(n == 2)?6:5; + + x0+=p1[x3&0x3f]; + x1+=p1[x0&0x3f]; + x2+=p1[x1&0x3f]; + x3+=p1[x2&0x3f]; + } + } + + d[0]=(unsigned long)(x0&0xffff)|((unsigned long)(x1&0xffff)<<16L); + d[1]=(unsigned long)(x2&0xffff)|((unsigned long)(x3&0xffff)<<16L); + } + +#ifdef _OPENSSL_APPLE_CDSA_ +void RC2_decrypt(RC2_INT *d, RC2_KEY *key) +#else +void RC2_decrypt(unsigned long *d, RC2_KEY *key) +#endif + { + int i,n; + register RC2_INT *p0,*p1; + register RC2_INT x0,x1,x2,x3,t; + unsigned long l; + + l=d[0]; + x0=(RC2_INT)l&0xffff; + x1=(RC2_INT)(l>>16L); + l=d[1]; + x2=(RC2_INT)l&0xffff; + x3=(RC2_INT)(l>>16L); + + n=3; + i=5; + + p0= &(key->data[63]); + p1= &(key->data[0]); + for (;;) + { + t=((x3<<11)|(x3>>5))&0xffff; + x3=(t-(x0& ~x2)-(x1&x2)- *(p0--))&0xffff; + t=((x2<<13)|(x2>>3))&0xffff; + x2=(t-(x3& ~x1)-(x0&x1)- *(p0--))&0xffff; + t=((x1<<14)|(x1>>2))&0xffff; + x1=(t-(x2& ~x0)-(x3&x0)- *(p0--))&0xffff; + t=((x0<<15)|(x0>>1))&0xffff; + x0=(t-(x1& ~x3)-(x2&x3)- *(p0--))&0xffff; + + if (--i == 0) + { + if (--n == 0) break; + i=(n == 2)?6:5; + + x3=(x3-p1[x2&0x3f])&0xffff; + x2=(x2-p1[x1&0x3f])&0xffff; + x1=(x1-p1[x0&0x3f])&0xffff; + x0=(x0-p1[x3&0x3f])&0xffff; + } + } + + d[0]=(unsigned long)(x0&0xffff)|((unsigned long)(x1&0xffff)<<16L); + d[1]=(unsigned long)(x2&0xffff)|((unsigned long)(x3&0xffff)<<16L); + } + diff --git a/libsecurity_apple_csp/open_ssl/misc/rc2_locl.h b/libsecurity_apple_csp/open_ssl/misc/rc2_locl.h new file mode 100644 index 00000000..6b66202b --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/misc/rc2_locl.h @@ -0,0 +1,174 @@ +/* + * 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. + */ + + +/* crypto/rc2/rc2_locl.h */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#undef c2l +#define c2l(c,l) (l =((unsigned long)(*((c)++))) , \ + l|=((unsigned long)(*((c)++)))<< 8L, \ + l|=((unsigned long)(*((c)++)))<<16L, \ + l|=((unsigned long)(*((c)++)))<<24L) + +/* NOTE - c is not incremented as per c2l */ +#undef c2ln +#define c2ln(c,l1,l2,n) { \ + c+=n; \ + l1=l2=0; \ + switch (n) { \ + case 8: l2 =((unsigned long)(*(--(c))))<<24L; \ + case 7: l2|=((unsigned long)(*(--(c))))<<16L; \ + case 6: l2|=((unsigned long)(*(--(c))))<< 8L; \ + case 5: l2|=((unsigned long)(*(--(c)))); \ + case 4: l1 =((unsigned long)(*(--(c))))<<24L; \ + case 3: l1|=((unsigned long)(*(--(c))))<<16L; \ + case 2: l1|=((unsigned long)(*(--(c))))<< 8L; \ + case 1: l1|=((unsigned long)(*(--(c)))); \ + } \ + } + +#undef l2c +#define l2c(l,c) (*((c)++)=(unsigned char)(((l) )&0xff), \ + *((c)++)=(unsigned char)(((l)>> 8L)&0xff), \ + *((c)++)=(unsigned char)(((l)>>16L)&0xff), \ + *((c)++)=(unsigned char)(((l)>>24L)&0xff)) + +/* NOTE - c is not incremented as per l2c */ +#undef l2cn +#define l2cn(l1,l2,c,n) { \ + c+=n; \ + switch (n) { \ + case 8: *(--(c))=(unsigned char)(((l2)>>24L)&0xff); \ + case 7: *(--(c))=(unsigned char)(((l2)>>16L)&0xff); \ + case 6: *(--(c))=(unsigned char)(((l2)>> 8L)&0xff); \ + case 5: *(--(c))=(unsigned char)(((l2) )&0xff); \ + case 4: *(--(c))=(unsigned char)(((l1)>>24L)&0xff); \ + case 3: *(--(c))=(unsigned char)(((l1)>>16L)&0xff); \ + case 2: *(--(c))=(unsigned char)(((l1)>> 8L)&0xff); \ + case 1: *(--(c))=(unsigned char)(((l1) )&0xff); \ + } \ + } + +/* NOTE - c is not incremented as per n2l */ +#define n2ln(c,l1,l2,n) { \ + c+=n; \ + l1=l2=0; \ + switch (n) { \ + case 8: l2 =((unsigned long)(*(--(c)))) ; \ + case 7: l2|=((unsigned long)(*(--(c))))<< 8; \ + case 6: l2|=((unsigned long)(*(--(c))))<<16; \ + case 5: l2|=((unsigned long)(*(--(c))))<<24; \ + case 4: l1 =((unsigned long)(*(--(c)))) ; \ + case 3: l1|=((unsigned long)(*(--(c))))<< 8; \ + case 2: l1|=((unsigned long)(*(--(c))))<<16; \ + case 1: l1|=((unsigned long)(*(--(c))))<<24; \ + } \ + } + +/* NOTE - c is not incremented as per l2n */ +#define l2nn(l1,l2,c,n) { \ + c+=n; \ + switch (n) { \ + case 8: *(--(c))=(unsigned char)(((l2) )&0xff); \ + case 7: *(--(c))=(unsigned char)(((l2)>> 8)&0xff); \ + case 6: *(--(c))=(unsigned char)(((l2)>>16)&0xff); \ + case 5: *(--(c))=(unsigned char)(((l2)>>24)&0xff); \ + case 4: *(--(c))=(unsigned char)(((l1) )&0xff); \ + case 3: *(--(c))=(unsigned char)(((l1)>> 8)&0xff); \ + case 2: *(--(c))=(unsigned char)(((l1)>>16)&0xff); \ + case 1: *(--(c))=(unsigned char)(((l1)>>24)&0xff); \ + } \ + } + +#undef n2l +#define n2l(c,l) (l =((unsigned long)(*((c)++)))<<24L, \ + l|=((unsigned long)(*((c)++)))<<16L, \ + l|=((unsigned long)(*((c)++)))<< 8L, \ + l|=((unsigned long)(*((c)++)))) + +#undef l2n +#define l2n(l,c) (*((c)++)=(unsigned char)(((l)>>24L)&0xff), \ + *((c)++)=(unsigned char)(((l)>>16L)&0xff), \ + *((c)++)=(unsigned char)(((l)>> 8L)&0xff), \ + *((c)++)=(unsigned char)(((l) )&0xff)) + +#define C_RC2(n) \ + t=(x0+(x1& ~x3)+(x2&x3)+ *(p0++))&0xffff; \ + x0=(t<<1)|(t>>15); \ + t=(x1+(x2& ~x0)+(x3&x0)+ *(p0++))&0xffff; \ + x1=(t<<2)|(t>>14); \ + t=(x2+(x3& ~x1)+(x0&x1)+ *(p0++))&0xffff; \ + x2=(t<<3)|(t>>13); \ + t=(x3+(x0& ~x2)+(x1&x2)+ *(p0++))&0xffff; \ + x3=(t<<5)|(t>>11); + diff --git a/libsecurity_apple_csp/open_ssl/misc/rc2_skey.c b/libsecurity_apple_csp/open_ssl/misc/rc2_skey.c new file mode 100644 index 00000000..ea73fb6a --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/misc/rc2_skey.c @@ -0,0 +1,156 @@ +/* + * 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. + */ + + +/* crypto/rc2/rc2_skey.c */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include +#include "rc2_locl.h" + +static const unsigned char key_table[256]={ + 0xd9,0x78,0xf9,0xc4,0x19,0xdd,0xb5,0xed,0x28,0xe9,0xfd,0x79, + 0x4a,0xa0,0xd8,0x9d,0xc6,0x7e,0x37,0x83,0x2b,0x76,0x53,0x8e, + 0x62,0x4c,0x64,0x88,0x44,0x8b,0xfb,0xa2,0x17,0x9a,0x59,0xf5, + 0x87,0xb3,0x4f,0x13,0x61,0x45,0x6d,0x8d,0x09,0x81,0x7d,0x32, + 0xbd,0x8f,0x40,0xeb,0x86,0xb7,0x7b,0x0b,0xf0,0x95,0x21,0x22, + 0x5c,0x6b,0x4e,0x82,0x54,0xd6,0x65,0x93,0xce,0x60,0xb2,0x1c, + 0x73,0x56,0xc0,0x14,0xa7,0x8c,0xf1,0xdc,0x12,0x75,0xca,0x1f, + 0x3b,0xbe,0xe4,0xd1,0x42,0x3d,0xd4,0x30,0xa3,0x3c,0xb6,0x26, + 0x6f,0xbf,0x0e,0xda,0x46,0x69,0x07,0x57,0x27,0xf2,0x1d,0x9b, + 0xbc,0x94,0x43,0x03,0xf8,0x11,0xc7,0xf6,0x90,0xef,0x3e,0xe7, + 0x06,0xc3,0xd5,0x2f,0xc8,0x66,0x1e,0xd7,0x08,0xe8,0xea,0xde, + 0x80,0x52,0xee,0xf7,0x84,0xaa,0x72,0xac,0x35,0x4d,0x6a,0x2a, + 0x96,0x1a,0xd2,0x71,0x5a,0x15,0x49,0x74,0x4b,0x9f,0xd0,0x5e, + 0x04,0x18,0xa4,0xec,0xc2,0xe0,0x41,0x6e,0x0f,0x51,0xcb,0xcc, + 0x24,0x91,0xaf,0x50,0xa1,0xf4,0x70,0x39,0x99,0x7c,0x3a,0x85, + 0x23,0xb8,0xb4,0x7a,0xfc,0x02,0x36,0x5b,0x25,0x55,0x97,0x31, + 0x2d,0x5d,0xfa,0x98,0xe3,0x8a,0x92,0xae,0x05,0xdf,0x29,0x10, + 0x67,0x6c,0xba,0xc9,0xd3,0x00,0xe6,0xcf,0xe1,0x9e,0xa8,0x2c, + 0x63,0x16,0x01,0x3f,0x58,0xe2,0x89,0xa9,0x0d,0x38,0x34,0x1b, + 0xab,0x33,0xff,0xb0,0xbb,0x48,0x0c,0x5f,0xb9,0xb1,0xcd,0x2e, + 0xc5,0xf3,0xdb,0x47,0xe5,0xa5,0x9c,0x77,0x0a,0xa6,0x20,0x68, + 0xfe,0x7f,0xc1,0xad, + }; + +/* It has come to my attention that there are 2 versions of the RC2 + * key schedule. One which is normal, and anther which has a hook to + * use a reduced key length. + * BSAFE uses the 'retarded' version. What I previously shipped is + * the same as specifying 1024 for the 'bits' parameter. Bsafe uses + * a version where the bits parameter is the same as len*8 */ +void RC2_set_key(RC2_KEY *key, int len, unsigned char *data, int bits) + { + int i,j; + unsigned char *k; + RC2_INT *ki; + unsigned int c,d; + + k= (unsigned char *)&(key->data[0]); + *k=0; /* for if there is a zero length key */ + + if (len > 128) len=128; + if (bits <= 0) bits=1024; + if (bits > 1024) bits=1024; + + for (i=0; i>3; + i=128-j; + c= (0xff>>(-bits & 0x07)); + + d=key_table[k[i]&c]; + k[i]=d; + while (i--) + { + d=key_table[k[i+j]^d]; + k[i]=d; + } + + /* copy from bytes into RC2_INT's */ + ki= &(key->data[63]); + for (i=127; i>=0; i-=2) + *(ki--)=((k[i]<<8)|k[i-1])&0xffff; + } + diff --git a/libsecurity_apple_csp/open_ssl/misc/rc5_enc.c b/libsecurity_apple_csp/open_ssl/misc/rc5_enc.c new file mode 100644 index 00000000..630e5eac --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/misc/rc5_enc.c @@ -0,0 +1,243 @@ +/* + * 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. + */ + + +/* crypto/rc5/rc5_enc.c */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include +#include +#include "rc5_locl.h" + +#ifndef _OPENSSL_APPLE_CDSA_ +void RC5_32_cbc_encrypt(unsigned char *in, unsigned char *out, long length, + RC5_32_KEY *ks, unsigned char *iv, int encrypt) + { + register unsigned long tin0,tin1; + register unsigned long tout0,tout1,xor0,xor1; + register long l=length; + unsigned long tin[2]; + + if (encrypt) + { + c2l(iv,tout0); + c2l(iv,tout1); + iv-=8; + for (l-=8; l>=0; l-=8) + { + c2l(in,tin0); + c2l(in,tin1); + tin0^=tout0; + tin1^=tout1; + tin[0]=tin0; + tin[1]=tin1; + RC5_32_encrypt(tin,ks); + tout0=tin[0]; l2c(tout0,out); + tout1=tin[1]; l2c(tout1,out); + } + if (l != -8) + { + c2ln(in,tin0,tin1,l+8); + tin0^=tout0; + tin1^=tout1; + tin[0]=tin0; + tin[1]=tin1; + RC5_32_encrypt(tin,ks); + tout0=tin[0]; l2c(tout0,out); + tout1=tin[1]; l2c(tout1,out); + } + l2c(tout0,iv); + l2c(tout1,iv); + } + else + { + c2l(iv,xor0); + c2l(iv,xor1); + iv-=8; + for (l-=8; l>=0; l-=8) + { + c2l(in,tin0); tin[0]=tin0; + c2l(in,tin1); tin[1]=tin1; + RC5_32_decrypt(tin,ks); + tout0=tin[0]^xor0; + tout1=tin[1]^xor1; + l2c(tout0,out); + l2c(tout1,out); + xor0=tin0; + xor1=tin1; + } + if (l != -8) + { + c2l(in,tin0); tin[0]=tin0; + c2l(in,tin1); tin[1]=tin1; + RC5_32_decrypt(tin,ks); + tout0=tin[0]^xor0; + tout1=tin[1]^xor1; + l2cn(tout0,tout1,out,l+8); + xor0=tin0; + xor1=tin1; + } + l2c(xor0,iv); + l2c(xor1,iv); + } + tin0=tin1=tout0=tout1=xor0=xor1=0; + tin[0]=tin[1]=0; + } + +#endif + +#ifdef _OPENSSL_APPLE_CDSA_ +void RC5_32_encrypt(RC5_32_INT *d, RC5_32_KEY *key) +#else +void RC5_32_encrypt(unsigned long *d, RC5_32_KEY *key) +#endif /* _OPENSSL_APPLE_CDSA_ */ + { + RC5_32_INT a,b,*s; + + s=key->data; + + a=d[0]+s[0]; + b=d[1]+s[1]; + E_RC5_32(a,b,s, 2); + E_RC5_32(a,b,s, 4); + E_RC5_32(a,b,s, 6); + E_RC5_32(a,b,s, 8); + E_RC5_32(a,b,s,10); + E_RC5_32(a,b,s,12); + E_RC5_32(a,b,s,14); + E_RC5_32(a,b,s,16); + if (key->rounds == 12) + { + E_RC5_32(a,b,s,18); + E_RC5_32(a,b,s,20); + E_RC5_32(a,b,s,22); + E_RC5_32(a,b,s,24); + } + else if (key->rounds == 16) + { + /* Do a full expansion to avoid a jump */ + E_RC5_32(a,b,s,18); + E_RC5_32(a,b,s,20); + E_RC5_32(a,b,s,22); + E_RC5_32(a,b,s,24); + E_RC5_32(a,b,s,26); + E_RC5_32(a,b,s,28); + E_RC5_32(a,b,s,30); + E_RC5_32(a,b,s,32); + } + d[0]=a; + d[1]=b; + } + +#ifdef _OPENSSL_APPLE_CDSA_ +void RC5_32_decrypt(RC5_32_INT *d, RC5_32_KEY *key) +#else +void RC5_32_decrypt(unsigned long *d, RC5_32_KEY *key) +#endif /* _OPENSSL_APPLE_CDSA_*/ + { + RC5_32_INT a,b,*s; + + s=key->data; + + a=d[0]; + b=d[1]; + if (key->rounds == 16) + { + D_RC5_32(a,b,s,32); + D_RC5_32(a,b,s,30); + D_RC5_32(a,b,s,28); + D_RC5_32(a,b,s,26); + /* Do a full expansion to avoid a jump */ + D_RC5_32(a,b,s,24); + D_RC5_32(a,b,s,22); + D_RC5_32(a,b,s,20); + D_RC5_32(a,b,s,18); + } + else if (key->rounds == 12) + { + D_RC5_32(a,b,s,24); + D_RC5_32(a,b,s,22); + D_RC5_32(a,b,s,20); + D_RC5_32(a,b,s,18); + } + D_RC5_32(a,b,s,16); + D_RC5_32(a,b,s,14); + D_RC5_32(a,b,s,12); + D_RC5_32(a,b,s,10); + D_RC5_32(a,b,s, 8); + D_RC5_32(a,b,s, 6); + D_RC5_32(a,b,s, 4); + D_RC5_32(a,b,s, 2); + d[0]=a-s[0]; + d[1]=b-s[1]; + } + diff --git a/libsecurity_apple_csp/open_ssl/misc/rc5_locl.h b/libsecurity_apple_csp/open_ssl/misc/rc5_locl.h new file mode 100644 index 00000000..2c45d85d --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/misc/rc5_locl.h @@ -0,0 +1,205 @@ +/* + * 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. + */ + + +/* crypto/rc5/rc5_locl.h */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include + +#undef c2l +#define c2l(c,l) (l =((unsigned long)(*((c)++))) , \ + l|=((unsigned long)(*((c)++)))<< 8L, \ + l|=((unsigned long)(*((c)++)))<<16L, \ + l|=((unsigned long)(*((c)++)))<<24L) + +/* NOTE - c is not incremented as per c2l */ +#undef c2ln +#define c2ln(c,l1,l2,n) { \ + c+=n; \ + l1=l2=0; \ + switch (n) { \ + case 8: l2 =((unsigned long)(*(--(c))))<<24L; \ + case 7: l2|=((unsigned long)(*(--(c))))<<16L; \ + case 6: l2|=((unsigned long)(*(--(c))))<< 8L; \ + case 5: l2|=((unsigned long)(*(--(c)))); \ + case 4: l1 =((unsigned long)(*(--(c))))<<24L; \ + case 3: l1|=((unsigned long)(*(--(c))))<<16L; \ + case 2: l1|=((unsigned long)(*(--(c))))<< 8L; \ + case 1: l1|=((unsigned long)(*(--(c)))); \ + } \ + } + +#undef l2c +#define l2c(l,c) (*((c)++)=(unsigned char)(((l) )&0xff), \ + *((c)++)=(unsigned char)(((l)>> 8L)&0xff), \ + *((c)++)=(unsigned char)(((l)>>16L)&0xff), \ + *((c)++)=(unsigned char)(((l)>>24L)&0xff)) + +/* NOTE - c is not incremented as per l2c */ +#undef l2cn +#define l2cn(l1,l2,c,n) { \ + c+=n; \ + switch (n) { \ + case 8: *(--(c))=(unsigned char)(((l2)>>24L)&0xff); \ + case 7: *(--(c))=(unsigned char)(((l2)>>16L)&0xff); \ + case 6: *(--(c))=(unsigned char)(((l2)>> 8L)&0xff); \ + case 5: *(--(c))=(unsigned char)(((l2) )&0xff); \ + case 4: *(--(c))=(unsigned char)(((l1)>>24L)&0xff); \ + case 3: *(--(c))=(unsigned char)(((l1)>>16L)&0xff); \ + case 2: *(--(c))=(unsigned char)(((l1)>> 8L)&0xff); \ + case 1: *(--(c))=(unsigned char)(((l1) )&0xff); \ + } \ + } + +/* NOTE - c is not incremented as per n2l */ +#define n2ln(c,l1,l2,n) { \ + c+=n; \ + l1=l2=0; \ + switch (n) { \ + case 8: l2 =((unsigned long)(*(--(c)))) ; \ + case 7: l2|=((unsigned long)(*(--(c))))<< 8; \ + case 6: l2|=((unsigned long)(*(--(c))))<<16; \ + case 5: l2|=((unsigned long)(*(--(c))))<<24; \ + case 4: l1 =((unsigned long)(*(--(c)))) ; \ + case 3: l1|=((unsigned long)(*(--(c))))<< 8; \ + case 2: l1|=((unsigned long)(*(--(c))))<<16; \ + case 1: l1|=((unsigned long)(*(--(c))))<<24; \ + } \ + } + +/* NOTE - c is not incremented as per l2n */ +#define l2nn(l1,l2,c,n) { \ + c+=n; \ + switch (n) { \ + case 8: *(--(c))=(unsigned char)(((l2) )&0xff); \ + case 7: *(--(c))=(unsigned char)(((l2)>> 8)&0xff); \ + case 6: *(--(c))=(unsigned char)(((l2)>>16)&0xff); \ + case 5: *(--(c))=(unsigned char)(((l2)>>24)&0xff); \ + case 4: *(--(c))=(unsigned char)(((l1) )&0xff); \ + case 3: *(--(c))=(unsigned char)(((l1)>> 8)&0xff); \ + case 2: *(--(c))=(unsigned char)(((l1)>>16)&0xff); \ + case 1: *(--(c))=(unsigned char)(((l1)>>24)&0xff); \ + } \ + } + +#undef n2l +#define n2l(c,l) (l =((unsigned long)(*((c)++)))<<24L, \ + l|=((unsigned long)(*((c)++)))<<16L, \ + l|=((unsigned long)(*((c)++)))<< 8L, \ + l|=((unsigned long)(*((c)++)))) + +#undef l2n +#define l2n(l,c) (*((c)++)=(unsigned char)(((l)>>24L)&0xff), \ + *((c)++)=(unsigned char)(((l)>>16L)&0xff), \ + *((c)++)=(unsigned char)(((l)>> 8L)&0xff), \ + *((c)++)=(unsigned char)(((l) )&0xff)) + +#if defined(WIN32) && defined(_MSC_VER) +#define ROTATE_l32(a,n) _lrotl(a,n) +#define ROTATE_r32(a,n) _lrotr(a,n) +#else +#define ROTATE_l32(a,n) (((a)<<(n&0x1f))|(((a)&0xffffffff)>>(32-(n&0x1f)))) +#define ROTATE_r32(a,n) (((a)<<(32-(n&0x1f)))|(((a)&0xffffffff)>>(n&0x1f))) +#endif + +#define RC5_32_MASK 0xffffffffL + +#define RC5_16_P 0xB7E1 +#define RC5_16_Q 0x9E37 +#define RC5_32_P 0xB7E15163L +#define RC5_32_Q 0x9E3779B9L +#define RC5_64_P 0xB7E151628AED2A6BLL +#define RC5_64_Q 0x9E3779B97F4A7C15LL + +#define E_RC5_32(a,b,s,n) \ + a^=b; \ + a=ROTATE_l32(a,b); \ + a+=s[n]; \ + a&=RC5_32_MASK; \ + b^=a; \ + b=ROTATE_l32(b,a); \ + b+=s[n+1]; \ + b&=RC5_32_MASK; + +#define D_RC5_32(a,b,s,n) \ + b-=s[n+1]; \ + b&=RC5_32_MASK; \ + b=ROTATE_r32(b,a); \ + b^=a; \ + a-=s[n]; \ + a&=RC5_32_MASK; \ + a=ROTATE_r32(a,b); \ + a^=b; + + + diff --git a/libsecurity_apple_csp/open_ssl/misc/rc5_skey.c b/libsecurity_apple_csp/open_ssl/misc/rc5_skey.c new file mode 100644 index 00000000..f1aad501 --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/misc/rc5_skey.c @@ -0,0 +1,131 @@ +/* + * 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. + */ + + +/* crypto/rc5/rc5_skey.c */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include +#include "rc5_locl.h" + +void RC5_32_set_key(RC5_32_KEY *key, int len, unsigned char *data, + int rounds) + { + RC5_32_INT L[64],l,ll,A,B,*S,k; + int i,j,m,c,t,ii,jj; + + if ( (rounds != RC5_16_ROUNDS) && + (rounds != RC5_12_ROUNDS) && + (rounds != RC5_8_ROUNDS)) + rounds=RC5_16_ROUNDS; + + key->rounds=rounds; + S= &(key->data[0]); + j=0; + for (i=0; i<=(len-8); i+=8) + { + c2l(data,l); + L[j++]=l; + c2l(data,l); + L[j++]=l; + } + ii=len-i; + if (ii) + { + k=len&0x07; + c2ln(data,l,ll,k); + L[j+0]=l; + L[j+1]=ll; + } + + c=(len+3)/4; + t=(rounds+1)*2; + S[0]=RC5_32_P; + for (i=1; ic)?t:c; + j*=3; + ii=jj=0; + A=B=0; + for (i=0; i= t) ii=0; + if (++jj >= c) jj=0; + } + } + diff --git a/libsecurity_apple_csp/open_ssl/openssl/asn1.h b/libsecurity_apple_csp/open_ssl/openssl/asn1.h new file mode 100644 index 00000000..021405ca --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/openssl/asn1.h @@ -0,0 +1,1085 @@ +/* + * 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. + */ + + +/* crypto/asn1/asn1.h */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef HEADER_ASN1_H +#define HEADER_ASN1_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include + +#ifdef VMS +#include +#endif + +#define V_ASN1_UNIVERSAL 0x00 +#define V_ASN1_APPLICATION 0x40 +#define V_ASN1_CONTEXT_SPECIFIC 0x80 +#define V_ASN1_PRIVATE 0xc0 + +#define V_ASN1_CONSTRUCTED 0x20 +#define V_ASN1_PRIMITIVE_TAG 0x1f +#define V_ASN1_PRIMATIVE_TAG 0x1f + +#define V_ASN1_APP_CHOOSE -2 /* let the recipient choose */ + +#define V_ASN1_UNDEF -1 +#define V_ASN1_EOC 0 +#define V_ASN1_BOOLEAN 1 /**/ +#define V_ASN1_INTEGER 2 +#define V_ASN1_NEG_INTEGER (2+0x100) +#define V_ASN1_BIT_STRING 3 +#define V_ASN1_OCTET_STRING 4 +#define V_ASN1_NULL 5 +#define V_ASN1_OBJECT 6 +#define V_ASN1_OBJECT_DESCRIPTOR 7 +#define V_ASN1_EXTERNAL 8 +#define V_ASN1_REAL 9 +#define V_ASN1_ENUMERATED 10 +#define V_ASN1_NEG_ENUMERATED (10+0x100) +#define V_ASN1_UTF8STRING 12 +#define V_ASN1_SEQUENCE 16 +#define V_ASN1_SET 17 +#define V_ASN1_NUMERICSTRING 18 /**/ +#define V_ASN1_PRINTABLESTRING 19 +#define V_ASN1_T61STRING 20 +#define V_ASN1_TELETEXSTRING 20 /* alias */ +#define V_ASN1_VIDEOTEXSTRING 21 /**/ +#define V_ASN1_IA5STRING 22 +#define V_ASN1_UTCTIME 23 +#define V_ASN1_GENERALIZEDTIME 24 /**/ +#define V_ASN1_GRAPHICSTRING 25 /**/ +#define V_ASN1_ISO64STRING 26 /**/ +#define V_ASN1_VISIBLESTRING 26 /* alias */ +#define V_ASN1_GENERALSTRING 27 /**/ +#define V_ASN1_UNIVERSALSTRING 28 /**/ +#define V_ASN1_BMPSTRING 30 + +/* For use with d2i_ASN1_type_bytes() */ +#define B_ASN1_NUMERICSTRING 0x0001 +#define B_ASN1_PRINTABLESTRING 0x0002 +#define B_ASN1_T61STRING 0x0004 +#define B_ASN1_TELETEXSTRING 0x0008 +#define B_ASN1_VIDEOTEXSTRING 0x0008 +#define B_ASN1_IA5STRING 0x0010 +#define B_ASN1_GRAPHICSTRING 0x0020 +#define B_ASN1_ISO64STRING 0x0040 +#define B_ASN1_VISIBLESTRING 0x0040 +#define B_ASN1_GENERALSTRING 0x0080 +#define B_ASN1_UNIVERSALSTRING 0x0100 +#define B_ASN1_OCTET_STRING 0x0200 +#define B_ASN1_BIT_STRING 0x0400 +#define B_ASN1_BMPSTRING 0x0800 +#define B_ASN1_UNKNOWN 0x1000 +#define B_ASN1_UTF8STRING 0x2000 + +/* For use with ASN1_mbstring_copy() */ +#define MBSTRING_FLAG 0x1000 +#define MBSTRING_ASC (MBSTRING_FLAG|1) +#define MBSTRING_BMP (MBSTRING_FLAG|2) +#define MBSTRING_UNIV (MBSTRING_FLAG|3) +#define MBSTRING_UTF8 (MBSTRING_FLAG|4) + +#define DECLARE_ASN1_SET_OF(type) \ +int i2d_ASN1_SET_OF_##type(STACK_OF(type) *a,unsigned char **pp, \ + int (*func)(type *,unsigned char **), int ex_tag, \ + int ex_class, int is_set); \ +STACK_OF(type) *d2i_ASN1_SET_OF_##type(STACK_OF(type) **a,unsigned char **pp, \ + long length, \ + type *(*func)(type **, \ + unsigned char **,long), \ + void (*free_func)(type *), \ + int ex_tag,int ex_class); + +#define IMPLEMENT_ASN1_SET_OF(type) \ +int i2d_ASN1_SET_OF_##type(STACK_OF(type) *a,unsigned char **pp, \ + int (*func)(type *,unsigned char **), int ex_tag, \ + int ex_class, int is_set) \ + { return i2d_ASN1_SET((STACK *)a,pp,func,ex_tag,ex_class,is_set); } \ +STACK_OF(type) *d2i_ASN1_SET_OF_##type(STACK_OF(type) **a,unsigned char **pp, \ + long length, \ + type *(*func)(type **, \ + unsigned char **,long), \ + void (*free_func)(type *), \ + int ex_tag,int ex_class) \ + { return (STACK_OF(type) *)d2i_ASN1_SET((STACK **)a,pp,length, \ + (char *(*)())func, \ + (void (*)())free_func, \ + ex_tag,ex_class); } + +typedef struct asn1_ctx_st + { + unsigned char *p;/* work char pointer */ + int eos; /* end of sequence read for indefinite encoding */ + int error; /* error code to use when returning an error */ + int inf; /* constructed if 0x20, indefinite is 0x21 */ + int tag; /* tag from last 'get object' */ + int xclass; /* class from last 'get object' */ + long slen; /* length of last 'get object' */ + unsigned char *max; /* largest value of p allowed */ + unsigned char *q;/* temporary variable */ + unsigned char **pp;/* variable */ + int line; /* used in error processing */ + } ASN1_CTX; + +/* These are used internally in the ASN1_OBJECT to keep track of + * whether the names and data need to be free()ed */ +#define ASN1_OBJECT_FLAG_DYNAMIC 0x01 /* internal use */ +#define ASN1_OBJECT_FLAG_CRITICAL 0x02 /* critical x509v3 object id */ +#define ASN1_OBJECT_FLAG_DYNAMIC_STRINGS 0x04 /* internal use */ +#define ASN1_OBJECT_FLAG_DYNAMIC_DATA 0x08 /* internal use */ +typedef struct asn1_object_st + { + const char *sn,*ln; + int nid; + int length; + unsigned char *data; + int flags; /* Should we free this one */ + } ASN1_OBJECT; + +#define ASN1_STRING_FLAG_BITS_LEFT 0x08 /* Set if 0x07 has bits left value */ +/* This is the base type that holds just about everything :-) */ +typedef struct asn1_string_st + { + int length; + int type; + unsigned char *data; + /* The value of the following field depends on the type being + * held. It is mostly being used for BIT_STRING so if the + * input data has a non-zero 'unused bits' value, it will be + * handled correctly */ + long flags; + } ASN1_STRING; + +#define STABLE_FLAGS_MALLOC 0x01 +#define STABLE_NO_MASK 0x02 +#define DIRSTRING_TYPE \ + (B_ASN1_PRINTABLESTRING|B_ASN1_T61STRING|B_ASN1_BMPSTRING|B_ASN1_UTF8STRING) +#define PKCS9STRING_TYPE (DIRSTRING_TYPE|B_ASN1_IA5STRING) + +typedef struct asn1_string_table_st { + int nid; + long minsize; + long maxsize; + unsigned long mask; + unsigned long flags; +} ASN1_STRING_TABLE; + +DECLARE_STACK_OF(ASN1_STRING_TABLE) + +/* size limits: this stuff is taken straight from RFC2459 */ + +#define ub_name 32768 +#define ub_common_name 64 +#define ub_locality_name 128 +#define ub_state_name 128 +#define ub_organization_name 64 +#define ub_organization_unit_name 64 +#define ub_title 64 +#define ub_email_address 128 + +#ifdef NO_ASN1_TYPEDEFS +#define ASN1_INTEGER ASN1_STRING +#define ASN1_ENUMERATED ASN1_STRING +#define ASN1_BIT_STRING ASN1_STRING +#define ASN1_OCTET_STRING ASN1_STRING +#define ASN1_PRINTABLESTRING ASN1_STRING +#define ASN1_T61STRING ASN1_STRING +#define ASN1_IA5STRING ASN1_STRING +#define ASN1_UTCTIME ASN1_STRING +#define ASN1_GENERALIZEDTIME ASN1_STRING +#define ASN1_TIME ASN1_STRING +#define ASN1_GENERALSTRING ASN1_STRING +#define ASN1_UNIVERSALSTRING ASN1_STRING +#define ASN1_BMPSTRING ASN1_STRING +#define ASN1_VISIBLESTRING ASN1_STRING +#define ASN1_UTF8STRING ASN1_STRING +#else +typedef struct asn1_string_st ASN1_INTEGER; +typedef struct asn1_string_st ASN1_ENUMERATED; +typedef struct asn1_string_st ASN1_BIT_STRING; +typedef struct asn1_string_st ASN1_OCTET_STRING; +typedef struct asn1_string_st ASN1_PRINTABLESTRING; +typedef struct asn1_string_st ASN1_T61STRING; +typedef struct asn1_string_st ASN1_IA5STRING; +typedef struct asn1_string_st ASN1_GENERALSTRING; +typedef struct asn1_string_st ASN1_UNIVERSALSTRING; +typedef struct asn1_string_st ASN1_BMPSTRING; +typedef struct asn1_string_st ASN1_UTCTIME; +typedef struct asn1_string_st ASN1_TIME; +typedef struct asn1_string_st ASN1_GENERALIZEDTIME; +typedef struct asn1_string_st ASN1_VISIBLESTRING; +typedef struct asn1_string_st ASN1_UTF8STRING; +#endif + +typedef int ASN1_NULL; + +typedef struct asn1_type_st + { + int type; + union { + char *ptr; + ASN1_STRING * asn1_string; + ASN1_OBJECT * object; + ASN1_INTEGER * integer; + ASN1_ENUMERATED * enumerated; + ASN1_BIT_STRING * bit_string; + ASN1_OCTET_STRING * octet_string; + ASN1_PRINTABLESTRING * printablestring; + ASN1_T61STRING * t61string; + ASN1_IA5STRING * ia5string; + ASN1_GENERALSTRING * generalstring; + ASN1_BMPSTRING * bmpstring; + ASN1_UNIVERSALSTRING * universalstring; + ASN1_UTCTIME * utctime; + ASN1_GENERALIZEDTIME * generalizedtime; + ASN1_VISIBLESTRING * visiblestring; + ASN1_UTF8STRING * utf8string; + /* set and sequence are left complete and still + * contain the set or sequence bytes */ + ASN1_STRING * set; + ASN1_STRING * sequence; + } value; + } ASN1_TYPE; + +DECLARE_STACK_OF(ASN1_TYPE) +DECLARE_ASN1_SET_OF(ASN1_TYPE) + +typedef struct asn1_method_st + { + int (*i2d)(); + char *(*d2i)(); + char *(*create)(); + void (*destroy)(); + } ASN1_METHOD; + +/* This is used when parsing some Netscape objects */ +typedef struct asn1_header_st + { + ASN1_OCTET_STRING *header; + char *data; + ASN1_METHOD *meth; + } ASN1_HEADER; + +/* This is used to contain a list of bit names */ +typedef struct BIT_STRING_BITNAME_st { + int bitnum; + const char *lname; + const char *sname; +} BIT_STRING_BITNAME; + + +#define M_ASN1_STRING_length(x) ((x)->length) +#define M_ASN1_STRING_length_set(x, n) ((x)->length = (n)) +#define M_ASN1_STRING_type(x) ((x)->type) +#define M_ASN1_STRING_data(x) ((x)->data) + +/* Macros for string operations */ +#define M_ASN1_BIT_STRING_new() (ASN1_BIT_STRING *)\ + ASN1_STRING_type_new(V_ASN1_BIT_STRING) +#define M_ASN1_BIT_STRING_free(a) ASN1_STRING_free((ASN1_STRING *)a) +#define M_ASN1_BIT_STRING_dup(a) (ASN1_BIT_STRING *)\ + ASN1_STRING_dup((ASN1_STRING *)a) +#define M_ASN1_BIT_STRING_cmp(a,b) ASN1_STRING_cmp(\ + (ASN1_STRING *)a,(ASN1_STRING *)b) +#define M_ASN1_BIT_STRING_set(a,b,c) ASN1_STRING_set((ASN1_STRING *)a,b,c) + +#define M_ASN1_INTEGER_new() (ASN1_INTEGER *)\ + ASN1_STRING_type_new(V_ASN1_INTEGER) +#define M_ASN1_INTEGER_free(a) ASN1_STRING_free((ASN1_STRING *)a) +#define M_ASN1_INTEGER_dup(a) (ASN1_INTEGER *)ASN1_STRING_dup((ASN1_STRING *)a) +#define M_ASN1_INTEGER_cmp(a,b) ASN1_STRING_cmp(\ + (ASN1_STRING *)a,(ASN1_STRING *)b) + +#define M_ASN1_ENUMERATED_new() (ASN1_ENUMERATED *)\ + ASN1_STRING_type_new(V_ASN1_ENUMERATED) +#define M_ASN1_ENUMERATED_free(a) ASN1_STRING_free((ASN1_STRING *)a) +#define M_ASN1_ENUMERATED_dup(a) (ASN1_ENUMERATED *)ASN1_STRING_dup((ASN1_STRING *)a) +#define M_ASN1_ENUMERATED_cmp(a,b) ASN1_STRING_cmp(\ + (ASN1_STRING *)a,(ASN1_STRING *)b) + +#define M_ASN1_OCTET_STRING_new() (ASN1_OCTET_STRING *)\ + ASN1_STRING_type_new(V_ASN1_OCTET_STRING) +#define M_ASN1_OCTET_STRING_free(a) ASN1_STRING_free((ASN1_STRING *)a) +#define M_ASN1_OCTET_STRING_dup(a) (ASN1_OCTET_STRING *)\ + ASN1_STRING_dup((ASN1_STRING *)a) +#define M_ASN1_OCTET_STRING_cmp(a,b) ASN1_STRING_cmp(\ + (ASN1_STRING *)a,(ASN1_STRING *)b) +#define M_ASN1_OCTET_STRING_set(a,b,c) ASN1_STRING_set((ASN1_STRING *)a,b,c) +#define M_ASN1_OCTET_STRING_print(a,b) ASN1_STRING_print(a,(ASN1_STRING *)b) +#define M_i2d_ASN1_OCTET_STRING(a,pp) \ + i2d_ASN1_bytes((ASN1_STRING *)a,pp,V_ASN1_OCTET_STRING,\ + V_ASN1_UNIVERSAL) + +#define M_ASN1_PRINTABLE_new() ASN1_STRING_type_new(V_ASN1_T61STRING) +#define M_ASN1_PRINTABLE_free(a) ASN1_STRING_free((ASN1_STRING *)a) +#define M_i2d_ASN1_PRINTABLE(a,pp) i2d_ASN1_bytes((ASN1_STRING *)a,\ + pp,a->type,V_ASN1_UNIVERSAL) +#define M_d2i_ASN1_PRINTABLE(a,pp,l) \ + d2i_ASN1_type_bytes((ASN1_STRING **)a,pp,l, \ + B_ASN1_PRINTABLESTRING| \ + B_ASN1_T61STRING| \ + B_ASN1_IA5STRING| \ + B_ASN1_BIT_STRING| \ + B_ASN1_UNIVERSALSTRING|\ + B_ASN1_BMPSTRING|\ + B_ASN1_UTF8STRING|\ + B_ASN1_UNKNOWN) + +#define M_DIRECTORYSTRING_new() ASN1_STRING_type_new(V_ASN1_PRINTABLESTRING) +#define M_DIRECTORYSTRING_free(a) ASN1_STRING_free((ASN1_STRING *)a) +#define M_i2d_DIRECTORYSTRING(a,pp) i2d_ASN1_bytes((ASN1_STRING *)a,\ + pp,a->type,V_ASN1_UNIVERSAL) +#define M_d2i_DIRECTORYSTRING(a,pp,l) \ + d2i_ASN1_type_bytes((ASN1_STRING **)a,pp,l, \ + B_ASN1_PRINTABLESTRING| \ + B_ASN1_TELETEXSTRING|\ + B_ASN1_BMPSTRING|\ + B_ASN1_UNIVERSALSTRING|\ + B_ASN1_UTF8STRING) + +#define M_DISPLAYTEXT_new() ASN1_STRING_type_new(V_ASN1_VISIBLESTRING) +#define M_DISPLAYTEXT_free(a) ASN1_STRING_free((ASN1_STRING *)a) +#define M_i2d_DISPLAYTEXT(a,pp) i2d_ASN1_bytes((ASN1_STRING *)a,\ + pp,a->type,V_ASN1_UNIVERSAL) +#define M_d2i_DISPLAYTEXT(a,pp,l) \ + d2i_ASN1_type_bytes((ASN1_STRING **)a,pp,l, \ + B_ASN1_VISIBLESTRING| \ + B_ASN1_BMPSTRING|\ + B_ASN1_UTF8STRING) + +#define M_ASN1_PRINTABLESTRING_new() (ASN1_PRINTABLESTRING *)\ + ASN1_STRING_type_new(V_ASN1_PRINTABLESTRING) +#define M_ASN1_PRINTABLESTRING_free(a) ASN1_STRING_free((ASN1_STRING *)a) +#define M_i2d_ASN1_PRINTABLESTRING(a,pp) \ + i2d_ASN1_bytes((ASN1_STRING *)a,pp,V_ASN1_PRINTABLESTRING,\ + V_ASN1_UNIVERSAL) +#define M_d2i_ASN1_PRINTABLESTRING(a,pp,l) \ + (ASN1_PRINTABLESTRING *)d2i_ASN1_type_bytes\ + ((ASN1_STRING **)a,pp,l,B_ASN1_PRINTABLESTRING) + +#define M_ASN1_T61STRING_new() (ASN1_T61STRING *)\ + ASN1_STRING_type_new(V_ASN1_T61STRING) +#define M_ASN1_T61STRING_free(a) ASN1_STRING_free((ASN1_STRING *)a) +#define M_i2d_ASN1_T61STRING(a,pp) \ + i2d_ASN1_bytes((ASN1_STRING *)a,pp,V_ASN1_T61STRING,\ + V_ASN1_UNIVERSAL) +#define M_d2i_ASN1_T61STRING(a,pp,l) \ + (ASN1_T61STRING *)d2i_ASN1_type_bytes\ + ((ASN1_STRING **)a,pp,l,B_ASN1_T61STRING) + +#define M_ASN1_IA5STRING_new() (ASN1_IA5STRING *)\ + ASN1_STRING_type_new(V_ASN1_IA5STRING) +#define M_ASN1_IA5STRING_free(a) ASN1_STRING_free((ASN1_STRING *)a) +#define M_ASN1_IA5STRING_dup(a) \ + (ASN1_IA5STRING *)ASN1_STRING_dup((ASN1_STRING *)a) +#define M_i2d_ASN1_IA5STRING(a,pp) \ + i2d_ASN1_bytes((ASN1_STRING *)a,pp,V_ASN1_IA5STRING,\ + V_ASN1_UNIVERSAL) +#define M_d2i_ASN1_IA5STRING(a,pp,l) \ + (ASN1_IA5STRING *)d2i_ASN1_type_bytes((ASN1_STRING **)a,pp,l,\ + B_ASN1_IA5STRING) + +#define M_ASN1_UTCTIME_new() (ASN1_UTCTIME *)\ + ASN1_STRING_type_new(V_ASN1_UTCTIME) +#define M_ASN1_UTCTIME_free(a) ASN1_STRING_free((ASN1_STRING *)a) +#define M_ASN1_UTCTIME_dup(a) (ASN1_UTCTIME *)ASN1_STRING_dup((ASN1_STRING *)a) + +#define M_ASN1_GENERALIZEDTIME_new() (ASN1_GENERALIZEDTIME *)\ + ASN1_STRING_type_new(V_ASN1_GENERALIZEDTIME) +#define M_ASN1_GENERALIZEDTIME_free(a) ASN1_STRING_free((ASN1_STRING *)a) +#define M_ASN1_GENERALIZEDTIME_dup(a) (ASN1_GENERALIZEDTIME *)ASN1_STRING_dup(\ + (ASN1_STRING *)a) + +#define M_ASN1_TIME_new() (ASN1_TIME *)\ + ASN1_STRING_type_new(V_ASN1_UTCTIME) +#define M_ASN1_TIME_free(a) ASN1_STRING_free((ASN1_STRING *)a) +#define M_ASN1_TIME_dup(a) (ASN1_TIME *)ASN1_STRING_dup((ASN1_STRING *)a) + +#define M_ASN1_GENERALSTRING_new() (ASN1_GENERALSTRING *)\ + ASN1_STRING_type_new(V_ASN1_GENERALSTRING) +#define M_ASN1_GENERALSTRING_free(a) ASN1_STRING_free((ASN1_STRING *)a) +#define M_i2d_ASN1_GENERALSTRING(a,pp) \ + i2d_ASN1_bytes((ASN1_STRING *)a,pp,V_ASN1_GENERALSTRING,\ + V_ASN1_UNIVERSAL) +#define M_d2i_ASN1_GENERALSTRING(a,pp,l) \ + (ASN1_GENERALSTRING *)d2i_ASN1_type_bytes\ + ((ASN1_STRING **)a,pp,l,B_ASN1_GENERALSTRING) + +#define M_ASN1_UNIVERSALSTRING_new() (ASN1_UNIVERSALSTRING *)\ + ASN1_STRING_type_new(V_ASN1_UNIVERSALSTRING) +#define M_ASN1_UNIVERSALSTRING_free(a) ASN1_STRING_free((ASN1_STRING *)a) +#define M_i2d_ASN1_UNIVERSALSTRING(a,pp) \ + i2d_ASN1_bytes((ASN1_STRING *)a,pp,V_ASN1_UNIVERSALSTRING,\ + V_ASN1_UNIVERSAL) +#define M_d2i_ASN1_UNIVERSALSTRING(a,pp,l) \ + (ASN1_UNIVERSALSTRING *)d2i_ASN1_type_bytes\ + ((ASN1_STRING **)a,pp,l,B_ASN1_UNIVERSALSTRING) + +#define M_ASN1_BMPSTRING_new() (ASN1_BMPSTRING *)\ + ASN1_STRING_type_new(V_ASN1_BMPSTRING) +#define M_ASN1_BMPSTRING_free(a) ASN1_STRING_free((ASN1_STRING *)a) +#define M_i2d_ASN1_BMPSTRING(a,pp) \ + i2d_ASN1_bytes((ASN1_STRING *)a,pp,V_ASN1_BMPSTRING,\ + V_ASN1_UNIVERSAL) +#define M_d2i_ASN1_BMPSTRING(a,pp,l) \ + (ASN1_BMPSTRING *)d2i_ASN1_type_bytes\ + ((ASN1_STRING **)a,pp,l,B_ASN1_BMPSTRING) + +#define M_ASN1_VISIBLESTRING_new() (ASN1_VISIBLESTRING *)\ + ASN1_STRING_type_new(V_ASN1_VISIBLESTRING) +#define M_ASN1_VISIBLESTRING_free(a) ASN1_STRING_free((ASN1_STRING *)a) +#define M_i2d_ASN1_VISIBLESTRING(a,pp) \ + i2d_ASN1_bytes((ASN1_STRING *)a,pp,V_ASN1_VISIBLESTRING,\ + V_ASN1_UNIVERSAL) +#define M_d2i_ASN1_VISIBLESTRING(a,pp,l) \ + (ASN1_VISIBLESTRING *)d2i_ASN1_type_bytes\ + ((ASN1_STRING **)a,pp,l,B_ASN1_VISIBLESTRING) + +#define M_ASN1_UTF8STRING_new() (ASN1_UTF8STRING *)\ + ASN1_STRING_type_new(V_ASN1_UTF8STRING) +#define M_ASN1_UTF8STRING_free(a) ASN1_STRING_free((ASN1_STRING *)a) +#define M_i2d_ASN1_UTF8STRING(a,pp) \ + i2d_ASN1_bytes((ASN1_STRING *)a,pp,V_ASN1_UTF8STRING,\ + V_ASN1_UNIVERSAL) +#define M_d2i_ASN1_UTF8STRING(a,pp,l) \ + (ASN1_UTF8STRING *)d2i_ASN1_type_bytes\ + ((ASN1_STRING **)a,pp,l,B_ASN1_UTF8STRING) + + /* for the is_set parameter to i2d_ASN1_SET */ +#define IS_SEQUENCE 0 +#define IS_SET 1 + +ASN1_TYPE * ASN1_TYPE_new(void ); +void ASN1_TYPE_free(ASN1_TYPE *a); +int i2d_ASN1_TYPE(ASN1_TYPE *a,unsigned char **pp); +ASN1_TYPE * d2i_ASN1_TYPE(ASN1_TYPE **a,unsigned char **pp,long length); +int ASN1_TYPE_get(ASN1_TYPE *a); +void ASN1_TYPE_set(ASN1_TYPE *a, int type, void *value); + +ASN1_OBJECT * ASN1_OBJECT_new(void ); +void ASN1_OBJECT_free(ASN1_OBJECT *a); +int i2d_ASN1_OBJECT(ASN1_OBJECT *a,unsigned char **pp); +ASN1_OBJECT * d2i_ASN1_OBJECT(ASN1_OBJECT **a,unsigned char **pp, + long length); + +DECLARE_STACK_OF(ASN1_OBJECT) +DECLARE_ASN1_SET_OF(ASN1_OBJECT) + +ASN1_STRING * ASN1_STRING_new(void); +void ASN1_STRING_free(ASN1_STRING *a); +ASN1_STRING * ASN1_STRING_dup(ASN1_STRING *a); +ASN1_STRING * ASN1_STRING_type_new(int type ); +int ASN1_STRING_cmp(ASN1_STRING *a, ASN1_STRING *b); + /* Since this is used to store all sorts of things, via macros, for now, make + its data void * */ +int ASN1_STRING_set(ASN1_STRING *str, const void *data, int len); +int ASN1_STRING_length(ASN1_STRING *x); +void ASN1_STRING_length_set(ASN1_STRING *x, int n); +int ASN1_STRING_type(ASN1_STRING *x); +unsigned char * ASN1_STRING_data(ASN1_STRING *x); + +ASN1_BIT_STRING * ASN1_BIT_STRING_new(void); +void ASN1_BIT_STRING_free(ASN1_BIT_STRING *a); +int i2d_ASN1_BIT_STRING(ASN1_BIT_STRING *a,unsigned char **pp); +ASN1_BIT_STRING *d2i_ASN1_BIT_STRING(ASN1_BIT_STRING **a,unsigned char **pp, + long length); +int ASN1_BIT_STRING_set(ASN1_BIT_STRING *a, unsigned char *d, + int length ); +int ASN1_BIT_STRING_set_bit(ASN1_BIT_STRING *a, int n, int value); +int ASN1_BIT_STRING_get_bit(ASN1_BIT_STRING *a, int n); + +#ifdef HEADER_BIO_H +int ASN1_BIT_STRING_name_print(BIO *out, ASN1_BIT_STRING *bs, + BIT_STRING_BITNAME *tbl, int indent); +#endif +int ASN1_BIT_STRING_num_asc(char *name, BIT_STRING_BITNAME *tbl); +int ASN1_BIT_STRING_set_asc(ASN1_BIT_STRING *bs, char *name, int value, + BIT_STRING_BITNAME *tbl); + +int i2d_ASN1_BOOLEAN(int a,unsigned char **pp); +int d2i_ASN1_BOOLEAN(int *a,unsigned char **pp,long length); + +ASN1_INTEGER * ASN1_INTEGER_new(void); +void ASN1_INTEGER_free(ASN1_INTEGER *a); +int i2d_ASN1_INTEGER(ASN1_INTEGER *a,unsigned char **pp); +ASN1_INTEGER *d2i_ASN1_INTEGER(ASN1_INTEGER **a,unsigned char **pp, + long length); +ASN1_INTEGER *d2i_ASN1_UINTEGER(ASN1_INTEGER **a,unsigned char **pp, + long length); +ASN1_INTEGER * ASN1_INTEGER_dup(ASN1_INTEGER *x); +int ASN1_INTEGER_cmp(ASN1_INTEGER *x, ASN1_INTEGER *y); + +ASN1_ENUMERATED * ASN1_ENUMERATED_new(void); +void ASN1_ENUMERATED_free(ASN1_ENUMERATED *a); +int i2d_ASN1_ENUMERATED(ASN1_ENUMERATED *a,unsigned char **pp); +ASN1_ENUMERATED *d2i_ASN1_ENUMERATED(ASN1_ENUMERATED **a,unsigned char **pp, + long length); + +int ASN1_UTCTIME_check(ASN1_UTCTIME *a); +ASN1_UTCTIME *ASN1_UTCTIME_set(ASN1_UTCTIME *s,time_t t); +int ASN1_UTCTIME_set_string(ASN1_UTCTIME *s, char *str); + +int ASN1_GENERALIZEDTIME_check(ASN1_GENERALIZEDTIME *a); +ASN1_GENERALIZEDTIME *ASN1_GENERALIZEDTIME_set(ASN1_GENERALIZEDTIME *s,time_t t); +int ASN1_GENERALIZEDTIME_set_string(ASN1_GENERALIZEDTIME *s, char *str); + +ASN1_OCTET_STRING * ASN1_OCTET_STRING_new(void); +void ASN1_OCTET_STRING_free(ASN1_OCTET_STRING *a); +int i2d_ASN1_OCTET_STRING(ASN1_OCTET_STRING *a,unsigned char **pp); +ASN1_OCTET_STRING *d2i_ASN1_OCTET_STRING(ASN1_OCTET_STRING **a, + unsigned char **pp,long length); +ASN1_OCTET_STRING * ASN1_OCTET_STRING_dup(ASN1_OCTET_STRING *a); +int ASN1_OCTET_STRING_cmp(ASN1_OCTET_STRING *a, ASN1_OCTET_STRING *b); +int ASN1_OCTET_STRING_set(ASN1_OCTET_STRING *str, unsigned char *data, int len); + +ASN1_VISIBLESTRING * ASN1_VISIBLESTRING_new(void); +void ASN1_VISIBLESTRING_free(ASN1_VISIBLESTRING *a); +int i2d_ASN1_VISIBLESTRING(ASN1_VISIBLESTRING *a,unsigned char **pp); +ASN1_VISIBLESTRING *d2i_ASN1_VISIBLESTRING(ASN1_VISIBLESTRING **a, + unsigned char **pp,long length); + +ASN1_UTF8STRING * ASN1_UTF8STRING_new(void); +void ASN1_UTF8STRING_free(ASN1_UTF8STRING *a); +int i2d_ASN1_UTF8STRING(ASN1_UTF8STRING *a,unsigned char **pp); +ASN1_UTF8STRING *d2i_ASN1_UTF8STRING(ASN1_UTF8STRING **a, + unsigned char **pp,long length); + +ASN1_NULL * ASN1_NULL_new(void); +void ASN1_NULL_free(ASN1_NULL *a); +int i2d_ASN1_NULL(ASN1_NULL *a,unsigned char **pp); +ASN1_NULL *d2i_ASN1_NULL(ASN1_NULL **a, unsigned char **pp,long length); + +ASN1_BMPSTRING * ASN1_BMPSTRING_new(void); +void ASN1_BMPSTRING_free(ASN1_BMPSTRING *a); +int i2d_ASN1_BMPSTRING(ASN1_BMPSTRING *a, unsigned char **pp); +ASN1_BMPSTRING *d2i_ASN1_BMPSTRING(ASN1_BMPSTRING **a, unsigned char **pp, + long length); + + +int UTF8_getc(const unsigned char *str, int len, unsigned long *val); +int UTF8_putc(unsigned char *str, int len, unsigned long value); + +int i2d_ASN1_PRINTABLE(ASN1_STRING *a,unsigned char **pp); +ASN1_STRING *d2i_ASN1_PRINTABLE(ASN1_STRING **a, + unsigned char **pp, long l); + +ASN1_PRINTABLESTRING * ASN1_PRINTABLESTRING_new(void); +void ASN1_PRINTABLESTRING_free(ASN1_PRINTABLESTRING *a); +ASN1_PRINTABLESTRING *d2i_ASN1_PRINTABLESTRING(ASN1_PRINTABLESTRING **a, + unsigned char **pp, long l); +int i2d_ASN1_PRINTABLESTRING(ASN1_PRINTABLESTRING *a, unsigned char **pp); + +ASN1_STRING * DIRECTORYSTRING_new(void); +void DIRECTORYSTRING_free(ASN1_STRING *a); +int i2d_DIRECTORYSTRING(ASN1_STRING *a,unsigned char **pp); +ASN1_STRING *d2i_DIRECTORYSTRING(ASN1_STRING **a, unsigned char **pp, + long length); + +ASN1_STRING * DISPLAYTEXT_new(void); +void DISPLAYTEXT_free(ASN1_STRING *a); +int i2d_DISPLAYTEXT(ASN1_STRING *a,unsigned char **pp); +ASN1_STRING *d2i_DISPLAYTEXT(ASN1_STRING **a, unsigned char **pp, long length); + +ASN1_T61STRING * ASN1_T61STRING_new(void); +void ASN1_T61STRING_free(ASN1_IA5STRING *a); +ASN1_T61STRING *d2i_ASN1_T61STRING(ASN1_T61STRING **a, + unsigned char **pp, long l); + +ASN1_IA5STRING * ASN1_IA5STRING_new(void); +void ASN1_IA5STRING_free(ASN1_IA5STRING *a); +int i2d_ASN1_IA5STRING(ASN1_IA5STRING *a,unsigned char **pp); +ASN1_IA5STRING *d2i_ASN1_IA5STRING(ASN1_IA5STRING **a, + unsigned char **pp, long l); + +ASN1_UTCTIME * ASN1_UTCTIME_new(void); +void ASN1_UTCTIME_free(ASN1_UTCTIME *a); +int i2d_ASN1_UTCTIME(ASN1_UTCTIME *a,unsigned char **pp); +ASN1_UTCTIME * d2i_ASN1_UTCTIME(ASN1_UTCTIME **a,unsigned char **pp, + long length); + +ASN1_GENERALIZEDTIME * ASN1_GENERALIZEDTIME_new(void); +void ASN1_GENERALIZEDTIME_free(ASN1_GENERALIZEDTIME *a); +int i2d_ASN1_GENERALIZEDTIME(ASN1_GENERALIZEDTIME *a,unsigned char **pp); +ASN1_GENERALIZEDTIME * d2i_ASN1_GENERALIZEDTIME(ASN1_GENERALIZEDTIME **a,unsigned char **pp, + long length); + +ASN1_TIME * ASN1_TIME_new(void); +void ASN1_TIME_free(ASN1_TIME *a); +int i2d_ASN1_TIME(ASN1_TIME *a,unsigned char **pp); +ASN1_TIME * d2i_ASN1_TIME(ASN1_TIME **a,unsigned char **pp, long length); +ASN1_TIME *ASN1_TIME_set(ASN1_TIME *s,time_t t); + +int i2d_ASN1_SET(STACK *a, unsigned char **pp, + int (*func)(), int ex_tag, int ex_class, int is_set); +STACK * d2i_ASN1_SET(STACK **a, unsigned char **pp, long length, + char *(*func)(), void (*free_func)(), + int ex_tag, int ex_class); + +#ifdef HEADER_BIO_H +int i2a_ASN1_INTEGER(BIO *bp, ASN1_INTEGER *a); +int a2i_ASN1_INTEGER(BIO *bp,ASN1_INTEGER *bs,char *buf,int size); +int i2a_ASN1_ENUMERATED(BIO *bp, ASN1_ENUMERATED *a); +int a2i_ASN1_ENUMERATED(BIO *bp,ASN1_ENUMERATED *bs,char *buf,int size); +int i2a_ASN1_OBJECT(BIO *bp,ASN1_OBJECT *a); +int a2i_ASN1_STRING(BIO *bp,ASN1_STRING *bs,char *buf,int size); +int i2a_ASN1_STRING(BIO *bp, ASN1_STRING *a, int type); +#endif +int i2t_ASN1_OBJECT(char *buf,int buf_len,ASN1_OBJECT *a); + +int a2d_ASN1_OBJECT(unsigned char *out,int olen, const char *buf, int num); +ASN1_OBJECT *ASN1_OBJECT_create(int nid, unsigned char *data,int len, + char *sn, char *ln); + +int ASN1_INTEGER_set(ASN1_INTEGER *a, long v); +long ASN1_INTEGER_get(ASN1_INTEGER *a); +ASN1_INTEGER *BN_to_ASN1_INTEGER(BIGNUM *bn, ASN1_INTEGER *ai); +BIGNUM *ASN1_INTEGER_to_BN(ASN1_INTEGER *ai,BIGNUM *bn); + +int ASN1_ENUMERATED_set(ASN1_ENUMERATED *a, long v); +long ASN1_ENUMERATED_get(ASN1_ENUMERATED *a); +ASN1_ENUMERATED *BN_to_ASN1_ENUMERATED(BIGNUM *bn, ASN1_ENUMERATED *ai); +BIGNUM *ASN1_ENUMERATED_to_BN(ASN1_ENUMERATED *ai,BIGNUM *bn); + +/* General */ +/* given a string, return the correct type, max is the maximum length */ +int ASN1_PRINTABLE_type(unsigned char *s, int max); + +int i2d_ASN1_bytes(ASN1_STRING *a, unsigned char **pp, int tag, int xclass); +ASN1_STRING *d2i_ASN1_bytes(ASN1_STRING **a, unsigned char **pp, + long length, int Ptag, int Pclass); +/* type is one or more of the B_ASN1_ values. */ +ASN1_STRING *d2i_ASN1_type_bytes(ASN1_STRING **a,unsigned char **pp, + long length,int type); + +/* PARSING */ +int asn1_Finish(ASN1_CTX *c); + +/* SPECIALS */ +int ASN1_get_object(unsigned char **pp, long *plength, int *ptag, + int *pclass, long omax); +int ASN1_check_infinite_end(unsigned char **p,long len); +void ASN1_put_object(unsigned char **pp, int constructed, int length, + int tag, int xclass); +int ASN1_object_size(int constructed, int length, int tag); + +/* Used to implement other functions */ +char *ASN1_dup(int (*i2d)(),char *(*d2i)(),char *x); + +#ifndef NO_FP_API +char *ASN1_d2i_fp(char *(*xnew)(),char *(*d2i)(),FILE *fp,unsigned char **x); +int ASN1_i2d_fp(int (*i2d)(),FILE *out,unsigned char *x); +#endif + +#ifdef HEADER_BIO_H +char *ASN1_d2i_bio(char *(*xnew)(),char *(*d2i)(),BIO *bp,unsigned char **x); +int ASN1_i2d_bio(int (*i2d)(),BIO *out,unsigned char *x); +int ASN1_UTCTIME_print(BIO *fp,ASN1_UTCTIME *a); +int ASN1_GENERALIZEDTIME_print(BIO *fp,ASN1_GENERALIZEDTIME *a); +int ASN1_TIME_print(BIO *fp,ASN1_TIME *a); +int ASN1_STRING_print(BIO *bp,ASN1_STRING *v); +int ASN1_parse(BIO *bp,unsigned char *pp,long len,int indent); +#endif +const char *ASN1_tag2str(int tag); + +/* Used to load and write netscape format cert/key */ +int i2d_ASN1_HEADER(ASN1_HEADER *a,unsigned char **pp); +ASN1_HEADER *d2i_ASN1_HEADER(ASN1_HEADER **a,unsigned char **pp, long length); +ASN1_HEADER *ASN1_HEADER_new(void ); +void ASN1_HEADER_free(ASN1_HEADER *a); + +int ASN1_UNIVERSALSTRING_to_string(ASN1_UNIVERSALSTRING *s); + +void ERR_load_ASN1_strings(void); + +/* Not used that much at this point, except for the first two */ +ASN1_METHOD *X509_asn1_meth(void); +ASN1_METHOD *RSAPrivateKey_asn1_meth(void); +ASN1_METHOD *ASN1_IA5STRING_asn1_meth(void); +ASN1_METHOD *ASN1_BIT_STRING_asn1_meth(void); + +int ASN1_TYPE_set_octetstring(ASN1_TYPE *a, + unsigned char *data, int len); +int ASN1_TYPE_get_octetstring(ASN1_TYPE *a, + unsigned char *data, int max_len); +int ASN1_TYPE_set_int_octetstring(ASN1_TYPE *a, long num, + unsigned char *data, int len); +int ASN1_TYPE_get_int_octetstring(ASN1_TYPE *a,long *num, + unsigned char *data, int max_len); + +STACK *ASN1_seq_unpack(unsigned char *buf, int len, char *(*d2i)(), + void (*free_func)() ); +unsigned char *ASN1_seq_pack(STACK *safes, int (*i2d)(), unsigned char **buf, + int *len ); +void *ASN1_unpack_string(ASN1_STRING *oct, char *(*d2i)()); +ASN1_STRING *ASN1_pack_string(void *obj, int (*i2d)(), ASN1_OCTET_STRING **oct); + +void ASN1_STRING_set_default_mask(unsigned long mask); +int ASN1_STRING_set_default_mask_asc(char *p); +unsigned long ASN1_STRING_get_default_mask(void); +int ASN1_mbstring_copy(ASN1_STRING **out, const unsigned char *in, int len, + int inform, unsigned long mask); +int ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in, int len, + int inform, unsigned long mask, + long minsize, long maxsize); + +ASN1_STRING *ASN1_STRING_set_by_NID(ASN1_STRING **out, + const unsigned char *in, int inlen, int inform, int nid); +ASN1_STRING_TABLE *ASN1_STRING_TABLE_get(int nid); +int ASN1_STRING_TABLE_add(int, long, long, unsigned long, unsigned long); +void ASN1_STRING_TABLE_cleanup(void); + +/* BEGIN ERROR CODES */ +/* The following lines are auto generated by the script mkerr.pl. Any changes + * made after this point may be overwritten when the script is next run. + */ + +/* Error codes for the ASN1 functions. */ + +/* Function codes. */ +#define ASN1_F_A2D_ASN1_OBJECT 100 +#define ASN1_F_A2I_ASN1_ENUMERATED 236 +#define ASN1_F_A2I_ASN1_INTEGER 101 +#define ASN1_F_A2I_ASN1_STRING 102 +#define ASN1_F_ACCESS_DESCRIPTION_NEW 291 +#define ASN1_F_ASN1_COLLATE_PRIMITIVE 103 +#define ASN1_F_ASN1_D2I_BIO 104 +#define ASN1_F_ASN1_D2I_FP 105 +#define ASN1_F_ASN1_DUP 106 +#define ASN1_F_ASN1_ENUMERATED_SET 232 +#define ASN1_F_ASN1_ENUMERATED_TO_BN 233 +#define ASN1_F_ASN1_GENERALIZEDTIME_NEW 222 +#define ASN1_F_ASN1_GET_OBJECT 107 +#define ASN1_F_ASN1_HEADER_NEW 108 +#define ASN1_F_ASN1_I2D_BIO 109 +#define ASN1_F_ASN1_I2D_FP 110 +#define ASN1_F_ASN1_INTEGER_SET 111 +#define ASN1_F_ASN1_INTEGER_TO_BN 112 +#define ASN1_F_ASN1_MBSTRING_COPY 282 +#define ASN1_F_ASN1_OBJECT_NEW 113 +#define ASN1_F_ASN1_PACK_STRING 245 +#define ASN1_F_ASN1_PBE_SET 253 +#define ASN1_F_ASN1_SEQ_PACK 246 +#define ASN1_F_ASN1_SEQ_UNPACK 247 +#define ASN1_F_ASN1_SIGN 114 +#define ASN1_F_ASN1_STRING_NEW 115 +#define ASN1_F_ASN1_STRING_TABLE_ADD 283 +#define ASN1_F_ASN1_STRING_TYPE_NEW 116 +#define ASN1_F_ASN1_TYPE_GET_INT_OCTETSTRING 117 +#define ASN1_F_ASN1_TYPE_GET_OCTETSTRING 118 +#define ASN1_F_ASN1_TYPE_NEW 119 +#define ASN1_F_ASN1_UNPACK_STRING 248 +#define ASN1_F_ASN1_UTCTIME_NEW 120 +#define ASN1_F_ASN1_VERIFY 121 +#define ASN1_F_AUTHORITY_KEYID_NEW 237 +#define ASN1_F_BASIC_CONSTRAINTS_NEW 226 +#define ASN1_F_BN_TO_ASN1_ENUMERATED 234 +#define ASN1_F_BN_TO_ASN1_INTEGER 122 +#define ASN1_F_D2I_ACCESS_DESCRIPTION 284 +#define ASN1_F_D2I_ASN1_BIT_STRING 123 +#define ASN1_F_D2I_ASN1_BMPSTRING 124 +#define ASN1_F_D2I_ASN1_BOOLEAN 125 +#define ASN1_F_D2I_ASN1_BYTES 126 +#define ASN1_F_D2I_ASN1_ENUMERATED 235 +#define ASN1_F_D2I_ASN1_GENERALIZEDTIME 223 +#define ASN1_F_D2I_ASN1_HEADER 127 +#define ASN1_F_D2I_ASN1_INTEGER 128 +#define ASN1_F_D2I_ASN1_NULL 292 +#define ASN1_F_D2I_ASN1_OBJECT 129 +#define ASN1_F_D2I_ASN1_OCTET_STRING 130 +#define ASN1_F_D2I_ASN1_PRINT_TYPE 131 +#define ASN1_F_D2I_ASN1_SET 132 +#define ASN1_F_D2I_ASN1_TIME 224 +#define ASN1_F_D2I_ASN1_TYPE 133 +#define ASN1_F_D2I_ASN1_TYPE_BYTES 134 +#define ASN1_F_D2I_ASN1_UINTEGER 280 +#define ASN1_F_D2I_ASN1_UTCTIME 135 +#define ASN1_F_D2I_ASN1_UTF8STRING 266 +#define ASN1_F_D2I_ASN1_VISIBLESTRING 267 +#define ASN1_F_D2I_AUTHORITY_KEYID 238 +#define ASN1_F_D2I_BASIC_CONSTRAINTS 227 +#define ASN1_F_D2I_DHPARAMS 136 +#define ASN1_F_D2I_DIST_POINT 276 +#define ASN1_F_D2I_DIST_POINT_NAME 277 +#define ASN1_F_D2I_DSAPARAMS 137 +#define ASN1_F_D2I_DSAPRIVATEKEY 138 +#define ASN1_F_D2I_DSAPUBLICKEY 139 +#define ASN1_F_D2I_GENERAL_NAME 230 +#define ASN1_F_D2I_NETSCAPE_CERT_SEQUENCE 228 +#define ASN1_F_D2I_NETSCAPE_PKEY 140 +#define ASN1_F_D2I_NETSCAPE_RSA 141 +#define ASN1_F_D2I_NETSCAPE_RSA_2 142 +#define ASN1_F_D2I_NETSCAPE_SPKAC 143 +#define ASN1_F_D2I_NETSCAPE_SPKI 144 +#define ASN1_F_D2I_NOTICEREF 268 +#define ASN1_F_D2I_OTHERNAME 287 +#define ASN1_F_D2I_PBE2PARAM 262 +#define ASN1_F_D2I_PBEPARAM 249 +#define ASN1_F_D2I_PBKDF2PARAM 263 +#define ASN1_F_D2I_PKCS12 254 +#define ASN1_F_D2I_PKCS12_BAGS 255 +#define ASN1_F_D2I_PKCS12_MAC_DATA 256 +#define ASN1_F_D2I_PKCS12_SAFEBAG 257 +#define ASN1_F_D2I_PKCS7 145 +#define ASN1_F_D2I_PKCS7_DIGEST 146 +#define ASN1_F_D2I_PKCS7_ENCRYPT 147 +#define ASN1_F_D2I_PKCS7_ENC_CONTENT 148 +#define ASN1_F_D2I_PKCS7_ENVELOPE 149 +#define ASN1_F_D2I_PKCS7_ISSUER_AND_SERIAL 150 +#define ASN1_F_D2I_PKCS7_RECIP_INFO 151 +#define ASN1_F_D2I_PKCS7_SIGNED 152 +#define ASN1_F_D2I_PKCS7_SIGNER_INFO 153 +#define ASN1_F_D2I_PKCS7_SIGN_ENVELOPE 154 +#define ASN1_F_D2I_PKCS8_PRIV_KEY_INFO 250 +#define ASN1_F_D2I_PKEY_USAGE_PERIOD 239 +#define ASN1_F_D2I_POLICYINFO 269 +#define ASN1_F_D2I_POLICYQUALINFO 270 +#define ASN1_F_D2I_PRIVATEKEY 155 +#define ASN1_F_D2I_PUBLICKEY 156 +#define ASN1_F_D2I_RSAPRIVATEKEY 157 +#define ASN1_F_D2I_RSAPUBLICKEY 158 +#define ASN1_F_D2I_SXNET 241 +#define ASN1_F_D2I_SXNETID 243 +#define ASN1_F_D2I_USERNOTICE 271 +#define ASN1_F_D2I_X509 159 +#define ASN1_F_D2I_X509_ALGOR 160 +#define ASN1_F_D2I_X509_ATTRIBUTE 161 +#define ASN1_F_D2I_X509_CERT_AUX 285 +#define ASN1_F_D2I_X509_CINF 162 +#define ASN1_F_D2I_X509_CRL 163 +#define ASN1_F_D2I_X509_CRL_INFO 164 +#define ASN1_F_D2I_X509_EXTENSION 165 +#define ASN1_F_D2I_X509_KEY 166 +#define ASN1_F_D2I_X509_NAME 167 +#define ASN1_F_D2I_X509_NAME_ENTRY 168 +#define ASN1_F_D2I_X509_PKEY 169 +#define ASN1_F_D2I_X509_PUBKEY 170 +#define ASN1_F_D2I_X509_REQ 171 +#define ASN1_F_D2I_X509_REQ_INFO 172 +#define ASN1_F_D2I_X509_REVOKED 173 +#define ASN1_F_D2I_X509_SIG 174 +#define ASN1_F_D2I_X509_VAL 175 +#define ASN1_F_DIST_POINT_NAME_NEW 278 +#define ASN1_F_DIST_POINT_NEW 279 +#define ASN1_F_GENERAL_NAME_NEW 231 +#define ASN1_F_I2D_ASN1_HEADER 176 +#define ASN1_F_I2D_ASN1_TIME 225 +#define ASN1_F_I2D_DHPARAMS 177 +#define ASN1_F_I2D_DSAPARAMS 178 +#define ASN1_F_I2D_DSAPRIVATEKEY 179 +#define ASN1_F_I2D_DSAPUBLICKEY 180 +#define ASN1_F_I2D_DSA_PUBKEY 290 +#define ASN1_F_I2D_NETSCAPE_RSA 181 +#define ASN1_F_I2D_PKCS7 182 +#define ASN1_F_I2D_PRIVATEKEY 183 +#define ASN1_F_I2D_PUBLICKEY 184 +#define ASN1_F_I2D_RSAPRIVATEKEY 185 +#define ASN1_F_I2D_RSAPUBLICKEY 186 +#define ASN1_F_I2D_RSA_PUBKEY 289 +#define ASN1_F_I2D_X509_ATTRIBUTE 187 +#define ASN1_F_I2T_ASN1_OBJECT 188 +#define ASN1_F_NETSCAPE_CERT_SEQUENCE_NEW 229 +#define ASN1_F_NETSCAPE_PKEY_NEW 189 +#define ASN1_F_NETSCAPE_SPKAC_NEW 190 +#define ASN1_F_NETSCAPE_SPKI_NEW 191 +#define ASN1_F_NOTICEREF_NEW 272 +#define ASN1_F_OTHERNAME_NEW 288 +#define ASN1_F_PBE2PARAM_NEW 264 +#define ASN1_F_PBEPARAM_NEW 251 +#define ASN1_F_PBKDF2PARAM_NEW 265 +#define ASN1_F_PKCS12_BAGS_NEW 258 +#define ASN1_F_PKCS12_MAC_DATA_NEW 259 +#define ASN1_F_PKCS12_NEW 260 +#define ASN1_F_PKCS12_SAFEBAG_NEW 261 +#define ASN1_F_PKCS5_PBE2_SET 281 +#define ASN1_F_PKCS7_DIGEST_NEW 192 +#define ASN1_F_PKCS7_ENCRYPT_NEW 193 +#define ASN1_F_PKCS7_ENC_CONTENT_NEW 194 +#define ASN1_F_PKCS7_ENVELOPE_NEW 195 +#define ASN1_F_PKCS7_ISSUER_AND_SERIAL_NEW 196 +#define ASN1_F_PKCS7_NEW 197 +#define ASN1_F_PKCS7_RECIP_INFO_NEW 198 +#define ASN1_F_PKCS7_SIGNED_NEW 199 +#define ASN1_F_PKCS7_SIGNER_INFO_NEW 200 +#define ASN1_F_PKCS7_SIGN_ENVELOPE_NEW 201 +#define ASN1_F_PKCS8_PRIV_KEY_INFO_NEW 252 +#define ASN1_F_PKEY_USAGE_PERIOD_NEW 240 +#define ASN1_F_POLICYINFO_NEW 273 +#define ASN1_F_POLICYQUALINFO_NEW 274 +#define ASN1_F_SXNETID_NEW 244 +#define ASN1_F_SXNET_NEW 242 +#define ASN1_F_USERNOTICE_NEW 275 +#define ASN1_F_X509_ALGOR_NEW 202 +#define ASN1_F_X509_ATTRIBUTE_NEW 203 +#define ASN1_F_X509_CERT_AUX_NEW 286 +#define ASN1_F_X509_CINF_NEW 204 +#define ASN1_F_X509_CRL_INFO_NEW 205 +#define ASN1_F_X509_CRL_NEW 206 +#define ASN1_F_X509_DHPARAMS_NEW 207 +#define ASN1_F_X509_EXTENSION_NEW 208 +#define ASN1_F_X509_INFO_NEW 209 +#define ASN1_F_X509_KEY_NEW 210 +#define ASN1_F_X509_NAME_ENTRY_NEW 211 +#define ASN1_F_X509_NAME_NEW 212 +#define ASN1_F_X509_NEW 213 +#define ASN1_F_X509_PKEY_NEW 214 +#define ASN1_F_X509_PUBKEY_NEW 215 +#define ASN1_F_X509_REQ_INFO_NEW 216 +#define ASN1_F_X509_REQ_NEW 217 +#define ASN1_F_X509_REVOKED_NEW 218 +#define ASN1_F_X509_SIG_NEW 219 +#define ASN1_F_X509_VAL_FREE 220 +#define ASN1_F_X509_VAL_NEW 221 + +/* Reason codes. */ +#define ASN1_R_BAD_CLASS 100 +#define ASN1_R_BAD_OBJECT_HEADER 101 +#define ASN1_R_BAD_PASSWORD_READ 102 +#define ASN1_R_BAD_PKCS7_CONTENT 103 +#define ASN1_R_BAD_PKCS7_TYPE 104 +#define ASN1_R_BAD_TAG 105 +#define ASN1_R_BAD_TYPE 106 +#define ASN1_R_BN_LIB 107 +#define ASN1_R_BOOLEAN_IS_WRONG_LENGTH 108 +#define ASN1_R_BUFFER_TOO_SMALL 109 +#define ASN1_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER 166 +#define ASN1_R_DATA_IS_WRONG 110 +#define ASN1_R_DECODE_ERROR 155 +#define ASN1_R_DECODING_ERROR 111 +#define ASN1_R_ENCODE_ERROR 156 +#define ASN1_R_ERROR_PARSING_SET_ELEMENT 112 +#define ASN1_R_ERROR_SETTING_CIPHER_PARAMS 157 +#define ASN1_R_EXPECTING_AN_ENUMERATED 154 +#define ASN1_R_EXPECTING_AN_INTEGER 113 +#define ASN1_R_EXPECTING_AN_OBJECT 114 +#define ASN1_R_EXPECTING_AN_OCTET_STRING 115 +#define ASN1_R_EXPECTING_A_BIT_STRING 116 +#define ASN1_R_EXPECTING_A_BOOLEAN 117 +#define ASN1_R_EXPECTING_A_GENERALIZEDTIME 151 +#define ASN1_R_EXPECTING_A_NULL 164 +#define ASN1_R_EXPECTING_A_TIME 152 +#define ASN1_R_EXPECTING_A_UTCTIME 118 +#define ASN1_R_FIRST_NUM_TOO_LARGE 119 +#define ASN1_R_GENERALIZEDTIME_TOO_LONG 153 +#define ASN1_R_HEADER_TOO_LONG 120 +#define ASN1_R_ILLEGAL_CHARACTERS 158 +#define ASN1_R_INVALID_BMPSTRING_LENGTH 159 +#define ASN1_R_INVALID_DIGIT 121 +#define ASN1_R_INVALID_SEPARATOR 122 +#define ASN1_R_INVALID_TIME_FORMAT 123 +#define ASN1_R_INVALID_UNIVERSALSTRING_LENGTH 160 +#define ASN1_R_INVALID_UTF8STRING 161 +#define ASN1_R_IV_TOO_LARGE 124 +#define ASN1_R_LENGTH_ERROR 125 +#define ASN1_R_MISSING_SECOND_NUMBER 126 +#define ASN1_R_NON_HEX_CHARACTERS 127 +#define ASN1_R_NOT_ENOUGH_DATA 128 +#define ASN1_R_NULL_IS_WRONG_LENGTH 165 +#define ASN1_R_ODD_NUMBER_OF_CHARS 129 +#define ASN1_R_PARSING 130 +#define ASN1_R_PRIVATE_KEY_HEADER_MISSING 131 +#define ASN1_R_SECOND_NUMBER_TOO_LARGE 132 +#define ASN1_R_SHORT_LINE 133 +#define ASN1_R_STRING_TOO_LONG 163 +#define ASN1_R_STRING_TOO_SHORT 134 +#define ASN1_R_TAG_VALUE_TOO_HIGH 135 +#define ASN1_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD 136 +#define ASN1_R_TOO_LONG 137 +#define ASN1_R_UNABLE_TO_DECODE_RSA_KEY 138 +#define ASN1_R_UNABLE_TO_DECODE_RSA_PRIVATE_KEY 139 +#define ASN1_R_UNKNOWN_ATTRIBUTE_TYPE 140 +#define ASN1_R_UNKNOWN_FORMAT 162 +#define ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM 141 +#define ASN1_R_UNKNOWN_OBJECT_TYPE 142 +#define ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE 143 +#define ASN1_R_UNSUPPORTED_CIPHER 144 +#define ASN1_R_UNSUPPORTED_ENCRYPTION_ALGORITHM 145 +#define ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE 146 +#define ASN1_R_UTCTIME_TOO_LONG 147 +#define ASN1_R_WRONG_PRINTABLE_TYPE 148 +#define ASN1_R_WRONG_TAG 149 +#define ASN1_R_WRONG_TYPE 150 + +#ifdef __cplusplus +} +#endif +#endif + diff --git a/libsecurity_apple_csp/open_ssl/openssl/bio.h b/libsecurity_apple_csp/open_ssl/openssl/bio.h new file mode 100644 index 00000000..0c96f118 --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/openssl/bio.h @@ -0,0 +1,685 @@ +/* + * 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. + */ + + +/* crypto/bio/bio.h */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef HEADER_BIO_H +#define HEADER_BIO_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +/* These are the 'types' of BIOs */ +#define BIO_TYPE_NONE 0 +#define BIO_TYPE_MEM (1|0x0400) +#define BIO_TYPE_FILE (2|0x0400) + +#define BIO_TYPE_FD (4|0x0400|0x0100) +#define BIO_TYPE_SOCKET (5|0x0400|0x0100) +#define BIO_TYPE_NULL (6|0x0400) +#define BIO_TYPE_SSL (7|0x0200) +#define BIO_TYPE_MD (8|0x0200) /* passive filter */ +#define BIO_TYPE_BUFFER (9|0x0200) /* filter */ +#define BIO_TYPE_CIPHER (10|0x0200) /* filter */ +#define BIO_TYPE_BASE64 (11|0x0200) /* filter */ +#define BIO_TYPE_CONNECT (12|0x0400|0x0100) /* socket - connect */ +#define BIO_TYPE_ACCEPT (13|0x0400|0x0100) /* socket for accept */ +#define BIO_TYPE_PROXY_CLIENT (14|0x0200) /* client proxy BIO */ +#define BIO_TYPE_PROXY_SERVER (15|0x0200) /* server proxy BIO */ +#define BIO_TYPE_NBIO_TEST (16|0x0200) /* server proxy BIO */ +#define BIO_TYPE_NULL_FILTER (17|0x0200) +#define BIO_TYPE_BER (18|0x0200) /* BER -> bin filter */ +#define BIO_TYPE_BIO (19|0x0400) /* (half a) BIO pair */ + +#define BIO_TYPE_DESCRIPTOR 0x0100 /* socket, fd, connect or accept */ +#define BIO_TYPE_FILTER 0x0200 +#define BIO_TYPE_SOURCE_SINK 0x0400 + +/* BIO_FILENAME_READ|BIO_CLOSE to open or close on free. + * BIO_set_fp(in,stdin,BIO_NOCLOSE); */ +#define BIO_NOCLOSE 0x00 +#define BIO_CLOSE 0x01 + +/* These are used in the following macros and are passed to + * BIO_ctrl() */ +#define BIO_CTRL_RESET 1 /* opt - rewind/zero etc */ +#define BIO_CTRL_EOF 2 /* opt - are we at the eof */ +#define BIO_CTRL_INFO 3 /* opt - extra tit-bits */ +#define BIO_CTRL_SET 4 /* man - set the 'IO' type */ +#define BIO_CTRL_GET 5 /* man - get the 'IO' type */ +#define BIO_CTRL_PUSH 6 /* opt - internal, used to signify change */ +#define BIO_CTRL_POP 7 /* opt - internal, used to signify change */ +#define BIO_CTRL_GET_CLOSE 8 /* man - set the 'close' on free */ +#define BIO_CTRL_SET_CLOSE 9 /* man - set the 'close' on free */ +#define BIO_CTRL_PENDING 10 /* opt - is their more data buffered */ +#define BIO_CTRL_FLUSH 11 /* opt - 'flush' buffered output */ +#define BIO_CTRL_DUP 12 /* man - extra stuff for 'duped' BIO */ +#define BIO_CTRL_WPENDING 13 /* opt - number of bytes still to write */ +/* callback is int cb(BIO *bio,state,ret); */ +#define BIO_CTRL_SET_CALLBACK 14 /* opt - set callback function */ +#define BIO_CTRL_GET_CALLBACK 15 /* opt - set callback function */ + +#define BIO_CTRL_SET_FILENAME 30 /* BIO_s_file special */ + +/* modifiers */ +#define BIO_FP_READ 0x02 +#define BIO_FP_WRITE 0x04 +#define BIO_FP_APPEND 0x08 +#define BIO_FP_TEXT 0x10 + +#define BIO_FLAGS_READ 0x01 +#define BIO_FLAGS_WRITE 0x02 +#define BIO_FLAGS_IO_SPECIAL 0x04 +#define BIO_FLAGS_RWS (BIO_FLAGS_READ|BIO_FLAGS_WRITE|BIO_FLAGS_IO_SPECIAL) +#define BIO_FLAGS_SHOULD_RETRY 0x08 + +/* Used in BIO_gethostbyname() */ +#define BIO_GHBN_CTRL_HITS 1 +#define BIO_GHBN_CTRL_MISSES 2 +#define BIO_GHBN_CTRL_CACHE_SIZE 3 +#define BIO_GHBN_CTRL_GET_ENTRY 4 +#define BIO_GHBN_CTRL_FLUSH 5 + +/* Mostly used in the SSL BIO */ +/* Not used anymore + * #define BIO_FLAGS_PROTOCOL_DELAYED_READ 0x10 + * #define BIO_FLAGS_PROTOCOL_DELAYED_WRITE 0x20 + * #define BIO_FLAGS_PROTOCOL_STARTUP 0x40 + */ + +#define BIO_FLAGS_BASE64_NO_NL 0x100 + +/* This is used with memory BIOs: it means we shouldn't free up or change the + * data in any way. + */ +#define BIO_FLAGS_MEM_RDONLY 0x200 + +#define BIO_set_flags(b,f) ((b)->flags|=(f)) +#define BIO_get_flags(b) ((b)->flags) +#define BIO_set_retry_special(b) \ + ((b)->flags|=(BIO_FLAGS_IO_SPECIAL|BIO_FLAGS_SHOULD_RETRY)) +#define BIO_set_retry_read(b) \ + ((b)->flags|=(BIO_FLAGS_READ|BIO_FLAGS_SHOULD_RETRY)) +#define BIO_set_retry_write(b) \ + ((b)->flags|=(BIO_FLAGS_WRITE|BIO_FLAGS_SHOULD_RETRY)) + +/* These are normally used internally in BIOs */ +#define BIO_clear_flags(b,f) ((b)->flags&= ~(f)) +#define BIO_clear_retry_flags(b) \ + ((b)->flags&= ~(BIO_FLAGS_RWS|BIO_FLAGS_SHOULD_RETRY)) +#define BIO_get_retry_flags(b) \ + ((b)->flags&(BIO_FLAGS_RWS|BIO_FLAGS_SHOULD_RETRY)) + +/* These should be used by the application to tell why we should retry */ +#define BIO_should_read(a) ((a)->flags & BIO_FLAGS_READ) +#define BIO_should_write(a) ((a)->flags & BIO_FLAGS_WRITE) +#define BIO_should_io_special(a) ((a)->flags & BIO_FLAGS_IO_SPECIAL) +#define BIO_retry_type(a) ((a)->flags & BIO_FLAGS_RWS) +#define BIO_should_retry(a) ((a)->flags & BIO_FLAGS_SHOULD_RETRY) + +/* The next two are used in conjunction with the + * BIO_should_io_special() condition. After this returns true, + * BIO *BIO_get_retry_BIO(BIO *bio, int *reason); will walk the BIO + * stack and return the 'reason' for the special and the offending BIO. + * Given a BIO, BIO_get_retry_reason(bio) will return the code. */ +/* Returned from the SSL bio when the certificate retrieval code had an error */ +#define BIO_RR_SSL_X509_LOOKUP 0x01 +/* Returned from the connect BIO when a connect would have blocked */ +#define BIO_RR_CONNECT 0x02 + +/* These are passed by the BIO callback */ +#define BIO_CB_FREE 0x01 +#define BIO_CB_READ 0x02 +#define BIO_CB_WRITE 0x03 +#define BIO_CB_PUTS 0x04 +#define BIO_CB_GETS 0x05 +#define BIO_CB_CTRL 0x06 + +/* The callback is called before and after the underling operation, + * The BIO_CB_RETURN flag indicates if it is after the call */ +#define BIO_CB_RETURN 0x80 +#define BIO_CB_return(a) ((a)|BIO_CB_RETURN)) +#define BIO_cb_pre(a) (!((a)&BIO_CB_RETURN)) +#define BIO_cb_post(a) ((a)&BIO_CB_RETURN) + +#define BIO_set_callback(b,cb) ((b)->callback=(cb)) +#define BIO_set_callback_arg(b,arg) ((b)->cb_arg=(char *)(arg)) +#define BIO_get_callback_arg(b) ((b)->cb_arg) +#define BIO_get_callback(b) ((b)->callback) +#define BIO_method_name(b) ((b)->method->name) +#define BIO_method_type(b) ((b)->method->type) + +#ifndef WIN16 +typedef struct bio_method_st + { + int type; + const char *name; + int (*bwrite)(); + int (*bread)(); + int (*bputs)(); + int (*bgets)(); + long (*ctrl)(); + int (*create)(); + int (*destroy)(); + long (*callback_ctrl)(); + } BIO_METHOD; +#else +typedef struct bio_method_st + { + int type; + const char *name; + int (_far *bwrite)(); + int (_far *bread)(); + int (_far *bputs)(); + int (_far *bgets)(); + long (_far *ctrl)(); + int (_far *create)(); + int (_far *destroy)(); + long (_fat *callback_ctrl)(); + } BIO_METHOD; +#endif + +typedef struct bio_st + { + const BIO_METHOD *method; + /* bio, mode, argp, argi, argl, ret */ + long (*callback)(struct bio_st *,int,const char *,int, long,long); + char *cb_arg; /* first argument for the callback */ + + int init; + int shutdown; + int flags; /* extra storage */ + int retry_reason; + int num; + void *ptr; + struct bio_st *next_bio; /* used by filter BIOs */ + struct bio_st *prev_bio; /* used by filter BIOs */ + int references; + unsigned long num_read; + unsigned long num_write; + + CRYPTO_EX_DATA ex_data; + } BIO; + +typedef struct bio_f_buffer_ctx_struct + { + /* BIO *bio; */ /* this is now in the BIO struct */ + int ibuf_size; /* how big is the input buffer */ + int obuf_size; /* how big is the output buffer */ + + char *ibuf; /* the char array */ + int ibuf_len; /* how many bytes are in it */ + int ibuf_off; /* write/read offset */ + + char *obuf; /* the char array */ + int obuf_len; /* how many bytes are in it */ + int obuf_off; /* write/read offset */ + } BIO_F_BUFFER_CTX; + +/* connect BIO stuff */ +#define BIO_CONN_S_BEFORE 1 +#define BIO_CONN_S_GET_IP 2 +#define BIO_CONN_S_GET_PORT 3 +#define BIO_CONN_S_CREATE_SOCKET 4 +#define BIO_CONN_S_CONNECT 5 +#define BIO_CONN_S_OK 6 +#define BIO_CONN_S_BLOCKED_CONNECT 7 +#define BIO_CONN_S_NBIO 8 +/*#define BIO_CONN_get_param_hostname BIO_ctrl */ + +#define BIO_C_SET_CONNECT 100 +#define BIO_C_DO_STATE_MACHINE 101 +#define BIO_C_SET_NBIO 102 +#define BIO_C_SET_PROXY_PARAM 103 +#define BIO_C_SET_FD 104 +#define BIO_C_GET_FD 105 +#define BIO_C_SET_FILE_PTR 106 +#define BIO_C_GET_FILE_PTR 107 +#define BIO_C_SET_FILENAME 108 +#define BIO_C_SET_SSL 109 +#define BIO_C_GET_SSL 110 +#define BIO_C_SET_MD 111 +#define BIO_C_GET_MD 112 +#define BIO_C_GET_CIPHER_STATUS 113 +#define BIO_C_SET_BUF_MEM 114 +#define BIO_C_GET_BUF_MEM_PTR 115 +#define BIO_C_GET_BUFF_NUM_LINES 116 +#define BIO_C_SET_BUFF_SIZE 117 +#define BIO_C_SET_ACCEPT 118 +#define BIO_C_SSL_MODE 119 +#define BIO_C_GET_MD_CTX 120 +#define BIO_C_GET_PROXY_PARAM 121 +#define BIO_C_SET_BUFF_READ_DATA 122 /* data to read first */ +#define BIO_C_GET_CONNECT 123 +#define BIO_C_GET_ACCEPT 124 +#define BIO_C_SET_SSL_RENEGOTIATE_BYTES 125 +#define BIO_C_GET_SSL_NUM_RENEGOTIATES 126 +#define BIO_C_SET_SSL_RENEGOTIATE_TIMEOUT 127 +#define BIO_C_FILE_SEEK 128 +#define BIO_C_GET_CIPHER_CTX 129 +#define BIO_C_SET_BUF_MEM_EOF_RETURN 130/*return end of input value*/ +#define BIO_C_SET_BIND_MODE 131 +#define BIO_C_GET_BIND_MODE 132 +#define BIO_C_FILE_TELL 133 +#define BIO_C_GET_SOCKS 134 +#define BIO_C_SET_SOCKS 135 + +#define BIO_C_SET_WRITE_BUF_SIZE 136/* for BIO_s_bio */ +#define BIO_C_GET_WRITE_BUF_SIZE 137 +#define BIO_C_MAKE_BIO_PAIR 138 +#define BIO_C_DESTROY_BIO_PAIR 139 +#define BIO_C_GET_WRITE_GUARANTEE 140 +#define BIO_C_GET_READ_REQUEST 141 +#define BIO_C_SHUTDOWN_WR 142 +#define BIO_C_NREAD0 143 +#define BIO_C_NREAD 144 +#define BIO_C_NWRITE0 145 +#define BIO_C_NWRITE 146 +#define BIO_C_RESET_READ_REQUEST 147 + + +#define BIO_set_app_data(s,arg) BIO_set_ex_data(s,0,arg) +#define BIO_get_app_data(s) BIO_get_ex_data(s,0) + +/* BIO_s_connect() and BIO_s_socks4a_connect() */ +#define BIO_set_conn_hostname(b,name) BIO_ctrl(b,BIO_C_SET_CONNECT,0,(char *)name) +#define BIO_set_conn_port(b,port) BIO_ctrl(b,BIO_C_SET_CONNECT,1,(char *)port) +#define BIO_set_conn_ip(b,ip) BIO_ctrl(b,BIO_C_SET_CONNECT,2,(char *)ip) +#define BIO_set_conn_int_port(b,port) BIO_ctrl(b,BIO_C_SET_CONNECT,3,(char *)port) +#define BIO_get_conn_hostname(b) BIO_ptr_ctrl(b,BIO_C_GET_CONNECT,0) +#define BIO_get_conn_port(b) BIO_ptr_ctrl(b,BIO_C_GET_CONNECT,1) +#define BIO_get_conn_ip(b,ip) BIO_ptr_ctrl(b,BIO_C_SET_CONNECT,2) +#define BIO_get_conn_int_port(b,port) BIO_int_ctrl(b,BIO_C_SET_CONNECT,3,port) + + +#define BIO_set_nbio(b,n) BIO_ctrl(b,BIO_C_SET_NBIO,(n),NULL) + +/* BIO_s_accept_socket() */ +#define BIO_set_accept_port(b,name) BIO_ctrl(b,BIO_C_SET_ACCEPT,0,(char *)name) +#define BIO_get_accept_port(b) BIO_ptr_ctrl(b,BIO_C_GET_ACCEPT,0) +/* #define BIO_set_nbio(b,n) BIO_ctrl(b,BIO_C_SET_NBIO,(n),NULL) */ +#define BIO_set_nbio_accept(b,n) BIO_ctrl(b,BIO_C_SET_ACCEPT,1,(n)?"a":NULL) +#define BIO_set_accept_bios(b,bio) BIO_ctrl(b,BIO_C_SET_ACCEPT,2,(char *)bio) + +#define BIO_BIND_NORMAL 0 +#define BIO_BIND_REUSEADDR_IF_UNUSED 1 +#define BIO_BIND_REUSEADDR 2 +#define BIO_set_bind_mode(b,mode) BIO_ctrl(b,BIO_C_SET_BIND_MODE,mode,NULL) +#define BIO_get_bind_mode(b,mode) BIO_ctrl(b,BIO_C_GET_BIND_MODE,0,NULL) + +#define BIO_do_connect(b) BIO_do_handshake(b) +#define BIO_do_accept(b) BIO_do_handshake(b) +#define BIO_do_handshake(b) BIO_ctrl(b,BIO_C_DO_STATE_MACHINE,0,NULL) + +/* BIO_s_proxy_client() */ +#define BIO_set_url(b,url) BIO_ctrl(b,BIO_C_SET_PROXY_PARAM,0,(char *)(url)) +#define BIO_set_proxies(b,p) BIO_ctrl(b,BIO_C_SET_PROXY_PARAM,1,(char *)(p)) +/* BIO_set_nbio(b,n) */ +#define BIO_set_filter_bio(b,s) BIO_ctrl(b,BIO_C_SET_PROXY_PARAM,2,(char *)(s)) +/* BIO *BIO_get_filter_bio(BIO *bio); */ +#define BIO_set_proxy_cb(b,cb) BIO_callback_ctrl(b,BIO_C_SET_PROXY_PARAM,3,(void *(*cb)())) +#define BIO_set_proxy_header(b,sk) BIO_ctrl(b,BIO_C_SET_PROXY_PARAM,4,(char *)sk) +#define BIO_set_no_connect_return(b,bool) BIO_int_ctrl(b,BIO_C_SET_PROXY_PARAM,5,bool) + +#define BIO_get_proxy_header(b,skp) BIO_ctrl(b,BIO_C_GET_PROXY_PARAM,0,(char *)skp) +#define BIO_get_proxies(b,pxy_p) BIO_ctrl(b,BIO_C_GET_PROXY_PARAM,1,(char *)(pxy_p)) +#define BIO_get_url(b,url) BIO_ctrl(b,BIO_C_GET_PROXY_PARAM,2,(char *)(url)) +#define BIO_get_no_connect_return(b) BIO_ctrl(b,BIO_C_GET_PROXY_PARAM,5,NULL) + +#define BIO_set_fd(b,fd,c) BIO_int_ctrl(b,BIO_C_SET_FD,c,fd) +#define BIO_get_fd(b,c) BIO_ctrl(b,BIO_C_GET_FD,0,(char *)c) + +#define BIO_set_fp(b,fp,c) BIO_ctrl(b,BIO_C_SET_FILE_PTR,c,(char *)fp) +#define BIO_get_fp(b,fpp) BIO_ctrl(b,BIO_C_GET_FILE_PTR,0,(char *)fpp) + +#define BIO_seek(b,ofs) (int)BIO_ctrl(b,BIO_C_FILE_SEEK,ofs,NULL) +#define BIO_tell(b) (int)BIO_ctrl(b,BIO_C_FILE_TELL,0,NULL) + +/* name is cast to lose const, but might be better to route through a function + so we can do it safely */ +#ifdef CONST_STRICT +/* If you are wondering why this isn't defined, its because CONST_STRICT is + * purely a compile-time kludge to allow const to be checked. + */ +int BIO_read_filename(BIO *b,const char *name); +#else +#define BIO_read_filename(b,name) BIO_ctrl(b,BIO_C_SET_FILENAME, \ + BIO_CLOSE|BIO_FP_READ,(char *)name) +#endif +#define BIO_write_filename(b,name) BIO_ctrl(b,BIO_C_SET_FILENAME, \ + BIO_CLOSE|BIO_FP_WRITE,name) +#define BIO_append_filename(b,name) BIO_ctrl(b,BIO_C_SET_FILENAME, \ + BIO_CLOSE|BIO_FP_APPEND,name) +#define BIO_rw_filename(b,name) BIO_ctrl(b,BIO_C_SET_FILENAME, \ + BIO_CLOSE|BIO_FP_READ|BIO_FP_WRITE,name) + +/* WARNING WARNING, this ups the reference count on the read bio of the + * SSL structure. This is because the ssl read BIO is now pointed to by + * the next_bio field in the bio. So when you free the BIO, make sure + * you are doing a BIO_free_all() to catch the underlying BIO. */ +#define BIO_set_ssl(b,ssl,c) BIO_ctrl(b,BIO_C_SET_SSL,c,(char *)ssl) +#define BIO_get_ssl(b,sslp) BIO_ctrl(b,BIO_C_GET_SSL,0,(char *)sslp) +#define BIO_set_ssl_mode(b,client) BIO_ctrl(b,BIO_C_SSL_MODE,client,NULL) +#define BIO_set_ssl_renegotiate_bytes(b,num) \ + BIO_ctrl(b,BIO_C_SET_SSL_RENEGOTIATE_BYTES,num,NULL); +#define BIO_get_num_renegotiates(b) \ + BIO_ctrl(b,BIO_C_SET_SSL_NUM_RENEGOTIATES,0,NULL); +#define BIO_set_ssl_renegotiate_timeout(b,seconds) \ + BIO_ctrl(b,BIO_C_SET_SSL_RENEGOTIATE_TIMEOUT,seconds,NULL); + +/* defined in evp.h */ +/* #define BIO_set_md(b,md) BIO_ctrl(b,BIO_C_SET_MD,1,(char *)md) */ + +#define BIO_get_mem_data(b,pp) BIO_ctrl(b,BIO_CTRL_INFO,0,(char *)pp) +#define BIO_set_mem_buf(b,bm,c) BIO_ctrl(b,BIO_C_SET_BUF_MEM,c,(char *)bm) +#define BIO_get_mem_ptr(b,pp) BIO_ctrl(b,BIO_C_GET_BUF_MEM_PTR,0,(char *)pp) +#define BIO_set_mem_eof_return(b,v) \ + BIO_ctrl(b,BIO_C_SET_BUF_MEM_EOF_RETURN,v,NULL) + +/* For the BIO_f_buffer() type */ +#define BIO_get_buffer_num_lines(b) BIO_ctrl(b,BIO_C_GET_BUFF_NUM_LINES,0,NULL) +#define BIO_set_buffer_size(b,size) BIO_ctrl(b,BIO_C_SET_BUFF_SIZE,size,NULL) +#define BIO_set_read_buffer_size(b,size) BIO_int_ctrl(b,BIO_C_SET_BUFF_SIZE,size,0) +#define BIO_set_write_buffer_size(b,size) BIO_int_ctrl(b,BIO_C_SET_BUFF_SIZE,size,1) +#define BIO_set_buffer_read_data(b,buf,num) BIO_ctrl(b,BIO_C_SET_BUFF_READ_DATA,num,buf) + +/* Don't use the next one unless you know what you are doing :-) */ +#define BIO_dup_state(b,ret) BIO_ctrl(b,BIO_CTRL_DUP,0,(char *)(ret)) + +#define BIO_reset(b) (int)BIO_ctrl(b,BIO_CTRL_RESET,0,NULL) +#define BIO_eof(b) (int)BIO_ctrl(b,BIO_CTRL_EOF,0,NULL) +#define BIO_set_close(b,c) (int)BIO_ctrl(b,BIO_CTRL_SET_CLOSE,(c),NULL) +#define BIO_get_close(b) (int)BIO_ctrl(b,BIO_CTRL_GET_CLOSE,0,NULL) +#define BIO_pending(b) (int)BIO_ctrl(b,BIO_CTRL_PENDING,0,NULL) +#define BIO_wpending(b) (int)BIO_ctrl(b,BIO_CTRL_WPENDING,0,NULL) +/* ...pending macros have inappropriate return type */ +size_t BIO_ctrl_pending(BIO *b); +size_t BIO_ctrl_wpending(BIO *b); +#define BIO_flush(b) (int)BIO_ctrl(b,BIO_CTRL_FLUSH,0,NULL) +#define BIO_get_info_callback(b,cbp) (int)BIO_ctrl(b,BIO_CTRL_GET_CALLBACK,0,(void (**)())(cbp)) +#define BIO_set_info_callback(b,cb) (int)BIO_callback_ctrl(b,BIO_CTRL_SET_CALLBACK,(void (*)())(cb)) + +/* For the BIO_f_buffer() type */ +#define BIO_buffer_get_num_lines(b) BIO_ctrl(b,BIO_CTRL_GET,0,NULL) + +/* For BIO_s_bio() */ +#define BIO_set_write_buf_size(b,size) (int)BIO_ctrl(b,BIO_C_SET_WRITE_BUF_SIZE,size,NULL) +#define BIO_get_write_buf_size(b,size) (size_t)BIO_ctrl(b,BIO_C_GET_WRITE_BUF_SIZE,size,NULL) +#define BIO_make_bio_pair(b1,b2) (int)BIO_ctrl(b1,BIO_C_MAKE_BIO_PAIR,0,b2) +#define BIO_destroy_bio_pair(b) (int)BIO_ctrl(b,BIO_C_DESTROY_BIO_PAIR,0,NULL) +/* macros with inappropriate type -- but ...pending macros use int too: */ +#define BIO_get_write_guarantee(b) (int)BIO_ctrl(b,BIO_C_GET_WRITE_GUARANTEE,0,NULL) +#define BIO_get_read_request(b) (int)BIO_ctrl(b,BIO_C_GET_READ_REQUEST,0,NULL) +size_t BIO_ctrl_get_write_guarantee(BIO *b); +size_t BIO_ctrl_get_read_request(BIO *b); +int BIO_ctrl_reset_read_request(BIO *b); + +#ifdef NO_STDIO +#define NO_FP_API +#endif + + +/* These two aren't currently implemented */ +/* int BIO_get_ex_num(BIO *bio); */ +/* void BIO_set_ex_free_func(BIO *bio,int idx,void (*cb)()); */ +int BIO_set_ex_data(BIO *bio,int idx,void *data); +void *BIO_get_ex_data(BIO *bio,int idx); +int BIO_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, + CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func); +unsigned long BIO_number_read(BIO *bio); +unsigned long BIO_number_written(BIO *bio); + +# if defined(WIN16) && defined(_WINDLL) +BIO_METHOD *BIO_s_file_internal(void); +BIO *BIO_new_file_internal(char *filename, char *mode); +BIO *BIO_new_fp_internal(FILE *stream, int close_flag); +# define BIO_s_file BIO_s_file_internal +# define BIO_new_file BIO_new_file_internal +# define BIO_new_fp BIO_new_fp_internal +# else /* FP_API */ +const BIO_METHOD *BIO_s_file(void ); +BIO *BIO_new_file(const char *filename, const char *mode); +BIO *BIO_new_fp(FILE *stream, int close_flag); +# define BIO_s_file_internal BIO_s_file +# define BIO_new_file_internal BIO_new_file +# define BIO_new_fp_internal BIO_s_file +# endif /* FP_API */ +BIO * BIO_new(const BIO_METHOD *type); +int BIO_set(BIO *a,const BIO_METHOD *type); +int BIO_free(BIO *a); +int BIO_read(BIO *b, void *data, int len); +int BIO_gets(BIO *bp,char *buf, int size); +int BIO_write(BIO *b, const void *data, int len); +int BIO_puts(BIO *bp,const char *buf); +long BIO_ctrl(BIO *bp,int cmd,long larg,void *parg); +long BIO_callback_ctrl(BIO *bp,int cmd,void (*fp)()); +char * BIO_ptr_ctrl(BIO *bp,int cmd,long larg); +long BIO_int_ctrl(BIO *bp,int cmd,long larg,int iarg); +BIO * BIO_push(BIO *b,BIO *append); +BIO * BIO_pop(BIO *b); +void BIO_free_all(BIO *a); +BIO * BIO_find_type(BIO *b,int bio_type); +BIO * BIO_get_retry_BIO(BIO *bio, int *reason); +int BIO_get_retry_reason(BIO *bio); +BIO * BIO_dup_chain(BIO *in); + +int BIO_nread0(BIO *bio, char **buf); +int BIO_nread(BIO *bio, char **buf, int num); +int BIO_nwrite0(BIO *bio, char **buf); +int BIO_nwrite(BIO *bio, char **buf, int num); + +#ifndef WIN16 +long BIO_debug_callback(BIO *bio,int cmd,const char *argp,int argi, + long argl,long ret); +#else +long _far _loadds BIO_debug_callback(BIO *bio,int cmd,const char *argp,int argi, + long argl,long ret); +#endif + +BIO_METHOD *BIO_s_mem(void); +BIO *BIO_new_mem_buf(void *buf, int len); +BIO_METHOD *BIO_s_socket(void); +BIO_METHOD *BIO_s_connect(void); +BIO_METHOD *BIO_s_accept(void); +BIO_METHOD *BIO_s_fd(void); +BIO_METHOD *BIO_s_log(void); +BIO_METHOD *BIO_s_bio(void); +BIO_METHOD *BIO_s_null(void); +BIO_METHOD *BIO_f_null(void); +BIO_METHOD *BIO_f_buffer(void); +BIO_METHOD *BIO_f_nbio_test(void); +/* BIO_METHOD *BIO_f_ber(void); */ + +int BIO_sock_should_retry(int i); +int BIO_sock_non_fatal_error(int error); +int BIO_fd_should_retry(int i); +int BIO_fd_non_fatal_error(int error); +int BIO_dump(BIO *b,const char *bytes,int len); + +struct hostent *BIO_gethostbyname(const char *name); +/* We might want a thread-safe interface too: + * struct hostent *BIO_gethostbyname_r(const char *name, + * struct hostent *result, void *buffer, size_t buflen); + * or something similar (caller allocates a struct hostent, + * pointed to by "result", and additional buffer space for the various + * substructures; if the buffer does not suffice, NULL is returned + * and an appropriate error code is set). + */ +int BIO_sock_error(int sock); +int BIO_socket_ioctl(int fd, long type, unsigned long *arg); +int BIO_socket_nbio(int fd,int mode); +int BIO_get_port(const char *str, unsigned short *port_ptr); +int BIO_get_host_ip(const char *str, unsigned char *ip); +int BIO_get_accept_socket(char *host_port,int mode); +int BIO_accept(int sock,char **ip_port); +int BIO_sock_init(void ); +void BIO_sock_cleanup(void); +int BIO_set_tcp_ndelay(int sock,int turn_on); + +void ERR_load_BIO_strings(void ); + +BIO *BIO_new_socket(int sock, int close_flag); +BIO *BIO_new_fd(int fd, int close_flag); +BIO *BIO_new_connect(char *host_port); +BIO *BIO_new_accept(char *host_port); + +int BIO_new_bio_pair(BIO **bio1, size_t writebuf1, + BIO **bio2, size_t writebuf2); +/* If successful, returns 1 and in *bio1, *bio2 two BIO pair endpoints. + * Otherwise returns 0 and sets *bio1 and *bio2 to NULL. + * Size 0 uses default value. + */ + +void BIO_copy_next_retry(BIO *b); + +long BIO_ghbn_ctrl(int cmd,int iarg,char *parg); + +int BIO_printf(BIO *bio, ...); + +/* BEGIN ERROR CODES */ +/* The following lines are auto generated by the script mkerr.pl. Any changes + * made after this point may be overwritten when the script is next run. + */ + +/* Error codes for the BIO functions. */ + +/* Function codes. */ +#define BIO_F_ACPT_STATE 100 +#define BIO_F_BIO_ACCEPT 101 +#define BIO_F_BIO_BER_GET_HEADER 102 +#define BIO_F_BIO_CTRL 103 +#define BIO_F_BIO_GETHOSTBYNAME 120 +#define BIO_F_BIO_GETS 104 +#define BIO_F_BIO_GET_ACCEPT_SOCKET 105 +#define BIO_F_BIO_GET_HOST_IP 106 +#define BIO_F_BIO_GET_PORT 107 +#define BIO_F_BIO_MAKE_PAIR 121 +#define BIO_F_BIO_NEW 108 +#define BIO_F_BIO_NEW_FILE 109 +#define BIO_F_BIO_NEW_MEM_BUF 126 +#define BIO_F_BIO_NREAD 123 +#define BIO_F_BIO_NREAD0 124 +#define BIO_F_BIO_NWRITE 125 +#define BIO_F_BIO_NWRITE0 122 +#define BIO_F_BIO_PUTS 110 +#define BIO_F_BIO_READ 111 +#define BIO_F_BIO_SOCK_INIT 112 +#define BIO_F_BIO_WRITE 113 +#define BIO_F_BUFFER_CTRL 114 +#define BIO_F_CONN_CTRL 127 +#define BIO_F_CONN_STATE 115 +#define BIO_F_FILE_CTRL 116 +#define BIO_F_MEM_WRITE 117 +#define BIO_F_SSL_NEW 118 +#define BIO_F_WSASTARTUP 119 + +/* Reason codes. */ +#define BIO_R_ACCEPT_ERROR 100 +#define BIO_R_BAD_FOPEN_MODE 101 +#define BIO_R_BAD_HOSTNAME_LOOKUP 102 +#define BIO_R_BROKEN_PIPE 124 +#define BIO_R_CONNECT_ERROR 103 +#define BIO_R_ERROR_SETTING_NBIO 104 +#define BIO_R_ERROR_SETTING_NBIO_ON_ACCEPTED_SOCKET 105 +#define BIO_R_ERROR_SETTING_NBIO_ON_ACCEPT_SOCKET 106 +#define BIO_R_GETHOSTBYNAME_ADDR_IS_NOT_AF_INET 107 +#define BIO_R_INVALID_ARGUMENT 125 +#define BIO_R_INVALID_IP_ADDRESS 108 +#define BIO_R_IN_USE 123 +#define BIO_R_KEEPALIVE 109 +#define BIO_R_NBIO_CONNECT_ERROR 110 +#define BIO_R_NO_ACCEPT_PORT_SPECIFIED 111 +#define BIO_R_NO_HOSTNAME_SPECIFIED 112 +#define BIO_R_NO_PORT_DEFINED 113 +#define BIO_R_NO_PORT_SPECIFIED 114 +#define BIO_R_NULL_PARAMETER 115 +#define BIO_R_TAG_MISMATCH 116 +#define BIO_R_UNABLE_TO_BIND_SOCKET 117 +#define BIO_R_UNABLE_TO_CREATE_SOCKET 118 +#define BIO_R_UNABLE_TO_LISTEN_SOCKET 119 +#define BIO_R_UNINITIALIZED 120 +#define BIO_R_UNSUPPORTED_METHOD 121 +#define BIO_R_WRITE_TO_READ_ONLY_BIO 126 +#define BIO_R_WSASTARTUP 122 + +#ifdef __cplusplus +} +#endif +#endif + diff --git a/libsecurity_apple_csp/open_ssl/openssl/blowfish.h b/libsecurity_apple_csp/open_ssl/openssl/blowfish.h new file mode 100644 index 00000000..6fb2aff8 --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/openssl/blowfish.h @@ -0,0 +1,131 @@ +/* crypto/bf/blowfish.h */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef HEADER_BLOWFISH_H +#define HEADER_BLOWFISH_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef NO_BF +#error BF is disabled. +#endif + +#define BF_ENCRYPT 1 +#define BF_DECRYPT 0 + +/* + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + * ! BF_LONG has to be at least 32 bits wide. If it's wider, then ! + * ! BF_LONG_LOG2 has to be defined along. ! + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + */ + +#if defined(WIN16) || defined(__LP32__) || \ + ((defined(__ppc__) || defined(__i386__)) && defined(__APPLE__)) +#define BF_LONG unsigned long +#elif defined(_CRAY) || defined(__ILP64__) +#define BF_LONG unsigned long +#define BF_LONG_LOG2 3 +/* + * _CRAY note. I could declare short, but I have no idea what impact + * does it have on performance on none-T3E machines. I could declare + * int, but at least on C90 sizeof(int) can be chosen at compile time. + * So I've chosen long... + * + */ +#elif defined(__LP64__) +#define BF_LONG unsigned int +#else +#warning BF_LONG really should be explicitly defined +#define BF_LONG unsigned int +#endif + +#define BF_ROUNDS 16 +#define BF_BLOCK 8 /* block size in bytes */ +#define BF_MIN_KEY_SIZE_BYTES (32 / 8) +#define BF_MAX_KEY_SIZE_BYTES (448 / 8) /* 56 */ + +typedef struct bf_key_st + { + BF_LONG P[BF_ROUNDS+2]; + BF_LONG S[4*256]; + } BF_KEY; + + +void BF_set_key(BF_KEY *key, int len, const unsigned char *data); + +void BF_encrypt(BF_LONG *data,const BF_KEY *key); +void BF_decrypt(BF_LONG *data,const BF_KEY *key); + +void BF_ecb_encrypt(const unsigned char *in, unsigned char *out, + const BF_KEY *key, int enc); +void BF_cbc_encrypt(const unsigned char *in, unsigned char *out, long length, + const BF_KEY *schedule, unsigned char *ivec, int enc); +void BF_cfb64_encrypt(const unsigned char *in, unsigned char *out, long length, + const BF_KEY *schedule, unsigned char *ivec, int *num, int enc); +void BF_ofb64_encrypt(const unsigned char *in, unsigned char *out, long length, + const BF_KEY *schedule, unsigned char *ivec, int *num); +const char *BF_options(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libsecurity_apple_csp/open_ssl/openssl/bn.h b/libsecurity_apple_csp/open_ssl/openssl/bn.h new file mode 100644 index 00000000..6a731afc --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/openssl/bn.h @@ -0,0 +1,544 @@ +/* + * 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. + */ + + +/* crypto/bn/bn.h */ +/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef HEADER_BN_H +#define HEADER_BN_H + +#ifndef WIN16 +#include /* FILE */ +#endif +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef VMS +#undef BN_LLONG /* experimental, so far... */ +#endif + +#define BN_MUL_COMBA +#define BN_SQR_COMBA +#define BN_RECURSION +#define RECP_MUL_MOD +#define MONT_MUL_MOD + +/* This next option uses the C libraries (2 word)/(1 word) function. + * If it is not defined, I use my C version (which is slower). + * The reason for this flag is that when the particular C compiler + * library routine is used, and the library is linked with a different + * compiler, the library is missing. This mostly happens when the + * library is built with gcc and then linked using normal cc. This would + * be a common occurrence because gcc normally produces code that is + * 2 times faster than system compilers for the big number stuff. + * For machines with only one compiler (or shared libraries), this should + * be on. Again this in only really a problem on machines + * using "long long's", are 32bit, and are not using my assembler code. */ +#if defined(MSDOS) || defined(WINDOWS) || defined(WIN32) || defined(linux) +#define BN_DIV2W +#endif + +/* assuming long is 64bit - this is the DEC Alpha + * unsigned long long is only 64 bits :-(, don't define + * BN_LLONG for the DEC Alpha */ +#ifdef SIXTY_FOUR_BIT_LONG +#define BN_ULLONG unsigned long long +#define BN_ULONG unsigned long +#define BN_LONG long +#define BN_BITS 128 +#define BN_BYTES 8 +#define BN_BITS2 64 +#define BN_BITS4 32 +#define BN_MASK (0xffffffffffffffffffffffffffffffffLL) +#define BN_MASK2 (0xffffffffffffffffL) +#define BN_MASK2l (0xffffffffL) +#define BN_MASK2h (0xffffffff00000000L) +#define BN_MASK2h1 (0xffffffff80000000L) +#define BN_TBIT (0x8000000000000000L) +#define BN_DEC_CONV (10000000000000000000UL) +#define BN_DEC_FMT1 "%lu" +#define BN_DEC_FMT2 "%019lu" +#define BN_DEC_NUM 19 +#endif + +/* This is where the long long data type is 64 bits, but long is 32. + * For machines where there are 64bit registers, this is the mode to use. + * IRIX, on R4000 and above should use this mode, along with the relevant + * assembler code :-). Do NOT define BN_LLONG. + */ +#ifdef SIXTY_FOUR_BIT +#undef BN_LLONG +#undef BN_ULLONG +#define BN_ULONG unsigned long long +#define BN_LONG long long +#define BN_BITS 128 +#define BN_BYTES 8 +#define BN_BITS2 64 +#define BN_BITS4 32 +#define BN_MASK2 (0xffffffffffffffffLL) +#define BN_MASK2l (0xffffffffL) +#define BN_MASK2h (0xffffffff00000000LL) +#define BN_MASK2h1 (0xffffffff80000000LL) +#define BN_TBIT (0x8000000000000000LL) +#define BN_DEC_CONV (10000000000000000000LL) +#define BN_DEC_FMT1 "%llu" +#define BN_DEC_FMT2 "%019llu" +#define BN_DEC_NUM 19 +#endif + +#ifdef THIRTY_TWO_BIT +#if defined(WIN32) && !defined(__GNUC__) +#define BN_ULLONG unsigned _int64 +#elif defined(__LP64__) +#define BN_ULLONG unsigned +#else +#define BN_ULLONG unsigned long long +#endif +#ifdef __LP64__ + /* still 32 bits here */ +#define BN_ULONG unsigned +#define BN_LONG int +#else +#define BN_ULONG unsigned long +#define BN_LONG long +#endif +#define BN_BITS 64 +#define BN_BYTES 4 +#define BN_BITS2 32 +#define BN_BITS4 16 +#ifdef WIN32 +/* VC++ doesn't like the LL suffix */ +#define BN_MASK (0xffffffffffffffffL) +#else +#define BN_MASK (0xffffffffffffffffLL) +#endif +#define BN_MASK2 (0xffffffffL) +#define BN_MASK2l (0xffff) +#define BN_MASK2h1 (0xffff8000L) +#define BN_MASK2h (0xffff0000L) +#define BN_TBIT (0x80000000L) +#define BN_DEC_CONV (1000000000L) +#define BN_DEC_FMT1 "%lu" +#define BN_DEC_FMT2 "%09lu" +#define BN_DEC_NUM 9 +#endif + +#ifdef SIXTEEN_BIT +#ifndef BN_DIV2W +#define BN_DIV2W +#endif +#define BN_ULLONG unsigned long +#define BN_ULONG unsigned short +#define BN_LONG short +#define BN_BITS 32 +#define BN_BYTES 2 +#define BN_BITS2 16 +#define BN_BITS4 8 +#define BN_MASK (0xffffffff) +#define BN_MASK2 (0xffff) +#define BN_MASK2l (0xff) +#define BN_MASK2h1 (0xff80) +#define BN_MASK2h (0xff00) +#define BN_TBIT (0x8000) +#define BN_DEC_CONV (100000) +#define BN_DEC_FMT1 "%u" +#define BN_DEC_FMT2 "%05u" +#define BN_DEC_NUM 5 +#endif + +#ifdef EIGHT_BIT +#ifndef BN_DIV2W +#define BN_DIV2W +#endif +#define BN_ULLONG unsigned short +#define BN_ULONG unsigned char +#define BN_LONG char +#define BN_BITS 16 +#define BN_BYTES 1 +#define BN_BITS2 8 +#define BN_BITS4 4 +#define BN_MASK (0xffff) +#define BN_MASK2 (0xff) +#define BN_MASK2l (0xf) +#define BN_MASK2h1 (0xf8) +#define BN_MASK2h (0xf0) +#define BN_TBIT (0x80) +#define BN_DEC_CONV (100) +#define BN_DEC_FMT1 "%u" +#define BN_DEC_FMT2 "%02u" +#define BN_DEC_NUM 2 +#endif + +#define BN_DEFAULT_BITS 1280 + +#ifdef BIGNUM +#undef BIGNUM +#endif + +#define BN_FLG_MALLOCED 0x01 +#define BN_FLG_STATIC_DATA 0x02 +#define BN_FLG_FREE 0x8000 /* used for debuging */ +#define BN_set_flags(b,n) ((b)->flags|=(n)) +#define BN_get_flags(b,n) ((b)->flags&(n)) + +typedef struct bignum_st + { + BN_ULONG *d; /* Pointer to an array of 'BN_BITS2' bit chunks. */ + int top; /* Index of last used d +1. */ + /* The next are internal book keeping for bn_expand. */ + int max; /* Size of the d array. */ + int neg; /* one if the number is negative */ + int flags; + } BIGNUM; + +/* Used for temp variables */ +#define BN_CTX_NUM 12 +#define BN_CTX_NUM_POS 12 +typedef struct bignum_ctx + { + int tos; + BIGNUM bn[BN_CTX_NUM]; + int flags; + int depth; + int pos[BN_CTX_NUM_POS]; + int too_many; + } BN_CTX; + +typedef struct bn_blinding_st + { + int init; + BIGNUM *A; + BIGNUM *Ai; + BIGNUM *mod; /* just a reference */ + } BN_BLINDING; + +/* Used for montgomery multiplication */ +typedef struct bn_mont_ctx_st + { + int ri; /* number of bits in R */ + BIGNUM RR; /* used to convert to montgomery form */ + BIGNUM N; /* The modulus */ + BIGNUM Ni; /* R*(1/R mod N) - N*Ni = 1 + * (Ni is only stored for bignum algorithm) */ + BN_ULONG n0; /* least significant word of Ni */ + int flags; + } BN_MONT_CTX; + +/* Used for reciprocal division/mod functions + * It cannot be shared between threads + */ +typedef struct bn_recp_ctx_st + { + BIGNUM N; /* the divisor */ + BIGNUM Nr; /* the reciprocal */ + int num_bits; + int shift; + int flags; + } BN_RECP_CTX; + +#define BN_to_montgomery(r,a,mont,ctx) BN_mod_mul_montgomery(\ + r,a,&((mont)->RR),(mont),ctx) + +#define BN_prime_checks 0 /* default: select number of iterations + based on the size of the number */ + +/* number of Miller-Rabin iterations for an error rate of less than 2^-80 + * for random 'b'-bit input, b >= 100 (taken from table 4.4 in the Handbook + * of Applied Cryptography [Menezes, van Oorschot, Vanstone; CRC Press 1996]; + * original paper: Damgaard, Landrock, Pomerance: Average case error estimates + * for the strong probable prime test. -- Math. Comp. 61 (1993) 177-194) */ +#define BN_prime_checks_for_size(b) ((b) >= 1300 ? 2 : \ + (b) >= 850 ? 3 : \ + (b) >= 650 ? 4 : \ + (b) >= 550 ? 5 : \ + (b) >= 450 ? 6 : \ + (b) >= 400 ? 7 : \ + (b) >= 350 ? 8 : \ + (b) >= 300 ? 9 : \ + (b) >= 250 ? 12 : \ + (b) >= 200 ? 15 : \ + (b) >= 150 ? 18 : \ + /* b >= 100 */ 27) + +#define BN_num_bytes(a) ((BN_num_bits(a)+7)/8) +#define BN_is_word(a,w) (((a)->top == 1) && ((a)->d[0] == (BN_ULONG)(w))) +#define BN_is_zero(a) (((a)->top == 0) || BN_is_word(a,0)) +#define BN_is_one(a) (BN_is_word((a),1)) +#define BN_is_odd(a) (((a)->top > 0) && ((a)->d[0] & 1)) +#define BN_one(a) (BN_set_word((a),1)) +#define BN_zero(a) (BN_set_word((a),0)) + +/*#define BN_ascii2bn(a) BN_hex2bn(a) */ +/*#define BN_bn2ascii(a) BN_bn2hex(a) */ + +BIGNUM *BN_value_one(void); +char * BN_options(void); +BN_CTX *BN_CTX_new(void); +void BN_CTX_init(BN_CTX *c); +void BN_CTX_free(BN_CTX *c); +void BN_CTX_start(BN_CTX *ctx); +BIGNUM *BN_CTX_get(BN_CTX *ctx); +void BN_CTX_end(BN_CTX *ctx); +int BN_rand(BIGNUM *rnd, int bits, int top,int bottom); +int BN_pseudo_rand(BIGNUM *rnd, int bits, int top,int bottom); +int BN_rand_range(BIGNUM *rnd, BIGNUM *range); +int BN_num_bits(const BIGNUM *a); +int BN_num_bits_word(BN_ULONG); +BIGNUM *BN_new(void); +void BN_init(BIGNUM *); +void BN_clear_free(BIGNUM *a); +BIGNUM *BN_copy(BIGNUM *a, const BIGNUM *b); +BIGNUM *BN_bin2bn(const unsigned char *s,int len,BIGNUM *ret); +int BN_bn2bin(const BIGNUM *a, unsigned char *to); +BIGNUM *BN_mpi2bn(unsigned char *s,int len,BIGNUM *ret); +int BN_bn2mpi(const BIGNUM *a, unsigned char *to); +int BN_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b); +int BN_usub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b); +int BN_uadd(BIGNUM *r, const BIGNUM *a, const BIGNUM *b); +int BN_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b); +int BN_mod(BIGNUM *rem, const BIGNUM *m, const BIGNUM *d, BN_CTX *ctx); +int BN_div(BIGNUM *dv, BIGNUM *rem, const BIGNUM *m, const BIGNUM *d, + BN_CTX *ctx); +int BN_mul(BIGNUM *r, BIGNUM *a, BIGNUM *b, BN_CTX *ctx); +int BN_sqr(BIGNUM *r, BIGNUM *a,BN_CTX *ctx); +BN_ULONG BN_mod_word(const BIGNUM *a, BN_ULONG w); +BN_ULONG BN_div_word(BIGNUM *a, BN_ULONG w); +int BN_mul_word(BIGNUM *a, BN_ULONG w); +int BN_add_word(BIGNUM *a, BN_ULONG w); +int BN_sub_word(BIGNUM *a, BN_ULONG w); +int BN_set_word(BIGNUM *a, BN_ULONG w); +BN_ULONG BN_get_word(BIGNUM *a); +int BN_cmp(const BIGNUM *a, const BIGNUM *b); +void BN_free(BIGNUM *a); +int BN_is_bit_set(const BIGNUM *a, int n); +int BN_lshift(BIGNUM *r, const BIGNUM *a, int n); +int BN_lshift1(BIGNUM *r, BIGNUM *a); +int BN_exp(BIGNUM *r, BIGNUM *a, BIGNUM *p,BN_CTX *ctx); +int BN_mod_exp(BIGNUM *r, BIGNUM *a, const BIGNUM *p, + const BIGNUM *m,BN_CTX *ctx); +int BN_mod_exp_mont(BIGNUM *r, BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx); +int BN_mod_exp_mont_word(BIGNUM *r, BN_ULONG a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx); +int BN_mod_exp2_mont(BIGNUM *r, BIGNUM *a1, BIGNUM *p1,BIGNUM *a2, + BIGNUM *p2,BIGNUM *m,BN_CTX *ctx,BN_MONT_CTX *m_ctx); +int BN_mod_exp_simple(BIGNUM *r, BIGNUM *a, BIGNUM *p, + BIGNUM *m,BN_CTX *ctx); +int BN_mask_bits(BIGNUM *a,int n); +int BN_mod_mul(BIGNUM *ret, BIGNUM *a, BIGNUM *b, const BIGNUM *m, BN_CTX *ctx); +#ifndef NO_FP_API +int BN_print_fp(FILE *fp, const BIGNUM *a); +#endif +#ifdef HEADER_BIO_H +int BN_print(BIO *fp, const BIGNUM *a); +#else +int BN_print(void *fp, const BIGNUM *a); +#endif +int BN_reciprocal(BIGNUM *r, BIGNUM *m, int len, BN_CTX *ctx); +int BN_rshift(BIGNUM *r, BIGNUM *a, int n); +int BN_rshift1(BIGNUM *r, BIGNUM *a); +void BN_clear(BIGNUM *a); +BIGNUM *BN_dup(const BIGNUM *a); +int BN_ucmp(const BIGNUM *a, const BIGNUM *b); +int BN_set_bit(BIGNUM *a, int n); +int BN_clear_bit(BIGNUM *a, int n); +char * BN_bn2hex(const BIGNUM *a); +char * BN_bn2dec(const BIGNUM *a); +int BN_hex2bn(BIGNUM **a, const char *str); +int BN_dec2bn(BIGNUM **a, const char *str); +int BN_gcd(BIGNUM *r,BIGNUM *in_a,BIGNUM *in_b,BN_CTX *ctx); +BIGNUM *BN_mod_inverse(BIGNUM *ret,BIGNUM *a, const BIGNUM *n,BN_CTX *ctx); +BIGNUM *BN_generate_prime(BIGNUM *ret,int bits,int safe,BIGNUM *add, + BIGNUM *rem,void (*callback)(int,int,void *),void *cb_arg); +int BN_is_prime(const BIGNUM *p,int nchecks, + void (*callback)(int,int,void *), + BN_CTX *ctx,void *cb_arg); +int BN_is_prime_fasttest(const BIGNUM *p,int nchecks, + void (*callback)(int,int,void *),BN_CTX *ctx,void *cb_arg, + int do_trial_division); +void ERR_load_BN_strings(void ); + +BN_MONT_CTX *BN_MONT_CTX_new(void ); +void BN_MONT_CTX_init(BN_MONT_CTX *ctx); +int BN_mod_mul_montgomery(BIGNUM *r,BIGNUM *a,BIGNUM *b,BN_MONT_CTX *mont, + BN_CTX *ctx); +int BN_from_montgomery(BIGNUM *r,BIGNUM *a,BN_MONT_CTX *mont,BN_CTX *ctx); +void BN_MONT_CTX_free(BN_MONT_CTX *mont); +int BN_MONT_CTX_set(BN_MONT_CTX *mont,const BIGNUM *modulus,BN_CTX *ctx); +BN_MONT_CTX *BN_MONT_CTX_copy(BN_MONT_CTX *to,BN_MONT_CTX *from); + +BN_BLINDING *BN_BLINDING_new(BIGNUM *A,BIGNUM *Ai,BIGNUM *mod); +void BN_BLINDING_free(BN_BLINDING *b); +int BN_BLINDING_update(BN_BLINDING *b,BN_CTX *ctx); +int BN_BLINDING_convert(BIGNUM *n, BN_BLINDING *r, BN_CTX *ctx); +int BN_BLINDING_invert(BIGNUM *n, BN_BLINDING *b, BN_CTX *ctx); + +#if BN_PARAMS_ENABLE +void BN_set_params(int mul,int high,int low,int mont); +int BN_get_params(int which); /* 0, mul, 1 high, 2 low, 3 mont */ +#endif /* BN_PARAMS_ENABLE */ + +void BN_RECP_CTX_init(BN_RECP_CTX *recp); +BN_RECP_CTX *BN_RECP_CTX_new(void); +void BN_RECP_CTX_free(BN_RECP_CTX *recp); +int BN_RECP_CTX_set(BN_RECP_CTX *recp,const BIGNUM *rdiv,BN_CTX *ctx); +int BN_mod_mul_reciprocal(BIGNUM *r, BIGNUM *x, BIGNUM *y, + BN_RECP_CTX *recp,BN_CTX *ctx); +int BN_mod_exp_recp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx); +int BN_div_recp(BIGNUM *dv, BIGNUM *rem, BIGNUM *m, + BN_RECP_CTX *recp, BN_CTX *ctx); + +/* library internal functions */ + +#define bn_expand(a,bits) ((((((bits+BN_BITS2-1))/BN_BITS2)) <= (a)->max)?\ + (a):bn_expand2((a),(bits)/BN_BITS2+1)) +#define bn_wexpand(a,words) (((words) <= (a)->max)?(a):bn_expand2((a),(words))) +BIGNUM *bn_expand2(BIGNUM *a, int words); + +#define bn_fix_top(a) \ + { \ + BN_ULONG *ftl; \ + if ((a)->top > 0) \ + { \ + for (ftl= &((a)->d[(a)->top-1]); (a)->top > 0; (a)->top--) \ + if (*(ftl--)) break; \ + } \ + } + +BN_ULONG bn_mul_add_words(BN_ULONG *rp, BN_ULONG *ap, int num, BN_ULONG w); +BN_ULONG bn_mul_words(BN_ULONG *rp, BN_ULONG *ap, int num, BN_ULONG w); +void bn_sqr_words(BN_ULONG *rp, BN_ULONG *ap, int num); +BN_ULONG bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d); +BN_ULONG bn_add_words(BN_ULONG *rp, BN_ULONG *ap, BN_ULONG *bp,int num); +BN_ULONG bn_sub_words(BN_ULONG *rp, BN_ULONG *ap, BN_ULONG *bp,int num); + +#ifdef BN_DEBUG + void bn_dump1(FILE *o, const char *a, BN_ULONG *b,int n); +# define bn_print(a) {fprintf(stderr, #a "="); BN_print_fp(stderr,a); \ + fprintf(stderr,"\n");} +# define bn_dump(a,n) bn_dump1(stderr,#a,a,n); +#else +# define bn_print(a) +# define bn_dump(a,b) +#endif + +/* BEGIN ERROR CODES */ +/* The following lines are auto generated by the script mkerr.pl. Any changes + * made after this point may be overwritten when the script is next run. + */ + +/* Error codes for the BN functions. */ + +/* Function codes. */ +#define BN_F_BN_BLINDING_CONVERT 100 +#define BN_F_BN_BLINDING_INVERT 101 +#define BN_F_BN_BLINDING_NEW 102 +#define BN_F_BN_BLINDING_UPDATE 103 +#define BN_F_BN_BN2DEC 104 +#define BN_F_BN_BN2HEX 105 +#define BN_F_BN_CTX_GET 116 +#define BN_F_BN_CTX_NEW 106 +#define BN_F_BN_DIV 107 +#define BN_F_BN_EXPAND2 108 +#define BN_F_BN_MOD_EXP_MONT 109 +#define BN_F_BN_MOD_EXP_MONT_WORD 117 +#define BN_F_BN_MOD_INVERSE 110 +#define BN_F_BN_MOD_MUL_RECIPROCAL 111 +#define BN_F_BN_MPI2BN 112 +#define BN_F_BN_NEW 113 +#define BN_F_BN_RAND 114 +#define BN_F_BN_RAND_RANGE 122 +#define BN_F_BN_USUB 115 + +/* Reason codes. */ +#define BN_R_ARG2_LT_ARG3 100 +#define BN_R_BAD_RECIPROCAL 101 +#define BN_R_CALLED_WITH_EVEN_MODULUS 102 +#define BN_R_DIV_BY_ZERO 103 +#define BN_R_ENCODING_ERROR 104 +#define BN_R_EXPAND_ON_STATIC_BIGNUM_DATA 105 +#define BN_R_INVALID_LENGTH 106 +#define BN_R_INVALID_RANGE 115 +#define BN_R_NOT_INITIALIZED 107 +#define BN_R_NO_INVERSE 108 +#define BN_R_TOO_MANY_TEMPORARY_VARIABLES 109 + +#ifdef __cplusplus +} +#endif +#endif + diff --git a/libsecurity_apple_csp/open_ssl/openssl/buffer.h b/libsecurity_apple_csp/open_ssl/openssl/buffer.h new file mode 100644 index 00000000..9f9103ab --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/openssl/buffer.h @@ -0,0 +1,116 @@ +/* + * 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. + */ + + +/* crypto/buffer/buffer.h */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef HEADER_BUFFER_H +#define HEADER_BUFFER_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct buf_mem_st + { + int length; /* current number of bytes */ + char *data; + int max; /* size of buffer */ + } BUF_MEM; + +BUF_MEM *BUF_MEM_new(void); +void BUF_MEM_free(BUF_MEM *a); +int BUF_MEM_grow(BUF_MEM *str, int len); +char * BUF_strdup(const char *str); + +void ERR_load_BUF_strings(void ); + +/* BEGIN ERROR CODES */ +/* The following lines are auto generated by the script mkerr.pl. Any changes + * made after this point may be overwritten when the script is next run. + */ + +/* Error codes for the BUF functions. */ + +/* Function codes. */ +#define BUF_F_BUF_MEM_GROW 100 +#define BUF_F_BUF_MEM_NEW 101 +#define BUF_F_BUF_STRDUP 102 + +/* Reason codes. */ + +#ifdef __cplusplus +} +#endif +#endif + diff --git a/libsecurity_apple_csp/open_ssl/openssl/cast.h b/libsecurity_apple_csp/open_ssl/openssl/cast.h new file mode 100644 index 00000000..2c9d0019 --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/openssl/cast.h @@ -0,0 +1,103 @@ +/* crypto/cast/cast.h */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef HEADER_CAST_H +#define HEADER_CAST_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef NO_CAST +#error CAST is disabled. +#endif + +#define CAST_ENCRYPT 1 +#define CAST_DECRYPT 0 + +#define CAST_LONG unsigned long + +#define CAST_BLOCK 8 /* block size in bytes */ +#define CAST_KEY_LENGTH 16 /* MAX key size in bytes */ +#define CAST_MIN_KEY_LENGTH 5 /* MIN key size in bytes */ +typedef struct cast_key_st + { + CAST_LONG data[32]; + int short_key; /* Use reduced rounds for short key */ + } CAST_KEY; + + +void CAST_set_key(CAST_KEY *key, int len, const unsigned char *data); +void CAST_ecb_encrypt(const unsigned char *in,unsigned char *out,CAST_KEY *key, + int enc); +void CAST_encrypt(CAST_LONG *data,CAST_KEY *key); +void CAST_decrypt(CAST_LONG *data,CAST_KEY *key); +void CAST_cbc_encrypt(const unsigned char *in, unsigned char *out, long length, + CAST_KEY *ks, unsigned char *iv, int enc); +void CAST_cfb64_encrypt(const unsigned char *in, unsigned char *out, + long length, CAST_KEY *schedule, unsigned char *ivec, + int *num, int enc); +void CAST_ofb64_encrypt(const unsigned char *in, unsigned char *out, + long length, CAST_KEY *schedule, unsigned char *ivec, + int *num); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libsecurity_apple_csp/open_ssl/openssl/crypto.h b/libsecurity_apple_csp/open_ssl/openssl/crypto.h new file mode 100644 index 00000000..b2c7a6c9 --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/openssl/crypto.h @@ -0,0 +1,391 @@ +/* + * 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. + */ + + +/* crypto/crypto.h */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef HEADER_CRYPTO_H +#define HEADER_CRYPTO_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#ifndef NO_FP_API +#include +#endif + +#include +#include +#include + +#ifdef CHARSET_EBCDIC +#include +#endif + +#if defined(VMS) || defined(__VMS) +#include "vms_idhacks.h" +#endif + + +/* Backward compatibility to SSLeay */ +/* This is more to be used to check the correct DLL is being used + * in the MS world. */ +#define SSLEAY_VERSION_NUMBER OPENSSL_VERSION_NUMBER +#define SSLEAY_VERSION 0 +/* #define SSLEAY_OPTIONS 1 no longer supported */ +#define SSLEAY_CFLAGS 2 +#define SSLEAY_BUILT_ON 3 +#define SSLEAY_PLATFORM 4 + +/* When changing the CRYPTO_LOCK_* list, be sure to maintin the text lock + * names in cryptlib.c + */ + +#define CRYPTO_LOCK_ERR 1 +#define CRYPTO_LOCK_ERR_HASH 2 +#define CRYPTO_LOCK_X509 3 +#define CRYPTO_LOCK_X509_INFO 4 +#define CRYPTO_LOCK_X509_PKEY 5 +#define CRYPTO_LOCK_X509_CRL 6 +#define CRYPTO_LOCK_X509_REQ 7 +#define CRYPTO_LOCK_DSA 8 +#define CRYPTO_LOCK_RSA 9 +#define CRYPTO_LOCK_EVP_PKEY 10 +#define CRYPTO_LOCK_X509_STORE 11 +#define CRYPTO_LOCK_SSL_CTX 12 +#define CRYPTO_LOCK_SSL_CERT 13 +#define CRYPTO_LOCK_SSL_SESSION 14 +#define CRYPTO_LOCK_SSL_SESS_CERT 15 +#define CRYPTO_LOCK_SSL 16 +#define CRYPTO_LOCK_RAND 17 +#define CRYPTO_LOCK_MALLOC 18 +#define CRYPTO_LOCK_BIO 19 +#define CRYPTO_LOCK_GETHOSTBYNAME 20 +#define CRYPTO_LOCK_GETSERVBYNAME 21 +#define CRYPTO_LOCK_READDIR 22 +#define CRYPTO_LOCK_RSA_BLINDING 23 +#define CRYPTO_LOCK_DH 24 +#define CRYPTO_LOCK_MALLOC2 25 +#define CRYPTO_NUM_LOCKS 26 + +#define CRYPTO_LOCK 1 +#define CRYPTO_UNLOCK 2 +#define CRYPTO_READ 4 +#define CRYPTO_WRITE 8 + +#ifndef NO_LOCKING +#ifndef CRYPTO_w_lock +#define CRYPTO_w_lock(type) \ + CRYPTO_lock(CRYPTO_LOCK|CRYPTO_WRITE,type,__FILE__,__LINE__) +#define CRYPTO_w_unlock(type) \ + CRYPTO_lock(CRYPTO_UNLOCK|CRYPTO_WRITE,type,__FILE__,__LINE__) +#define CRYPTO_r_lock(type) \ + CRYPTO_lock(CRYPTO_LOCK|CRYPTO_READ,type,__FILE__,__LINE__) +#define CRYPTO_r_unlock(type) \ + CRYPTO_lock(CRYPTO_UNLOCK|CRYPTO_READ,type,__FILE__,__LINE__) +#define CRYPTO_add(addr,amount,type) \ + CRYPTO_add_lock(addr,amount,type,__FILE__,__LINE__) +#endif +#else +#define CRYPTO_w_lock(a) +#define CRYPTO_w_unlock(a) +#define CRYPTO_r_lock(a) +#define CRYPTO_r_unlock(a) +#define CRYPTO_add(a,b,c) ((*(a))+=(b)) +#endif + +/* The following can be used to detect memory leaks in the SSLeay library. + * It used, it turns on malloc checking */ + +#define CRYPTO_MEM_CHECK_OFF 0x0 /* an enume */ +#define CRYPTO_MEM_CHECK_ON 0x1 /* a bit */ +#define CRYPTO_MEM_CHECK_ENABLE 0x2 /* a bit */ +#define CRYPTO_MEM_CHECK_DISABLE 0x3 /* an enume */ + +/* The following are bit values to turn on or off options connected to the + * malloc checking functionality */ + +/* Adds time to the memory checking information */ +#define V_CRYPTO_MDEBUG_TIME 0x1 /* a bit */ +/* Adds thread number to the memory checking information */ +#define V_CRYPTO_MDEBUG_THREAD 0x2 /* a bit */ + +#define V_CRYPTO_MDEBUG_ALL (V_CRYPTO_MDEBUG_TIME | V_CRYPTO_MDEBUG_THREAD) + + +/* predec of the BIO type */ +typedef struct bio_st BIO_dummy; + +typedef struct crypto_ex_data_st + { + STACK *sk; + int dummy; /* gcc is screwing up this data structure :-( */ + } CRYPTO_EX_DATA; + +/* Called when a new object is created */ +typedef int CRYPTO_EX_new(void *parent, void *ptr, CRYPTO_EX_DATA *ad, + int idx, long argl, void *argp); +/* Called when an object is free()ed */ +typedef void CRYPTO_EX_free(void *parent, void *ptr, CRYPTO_EX_DATA *ad, + int idx, long argl, void *argp); +/* Called when we need to dup an object */ +typedef int CRYPTO_EX_dup(CRYPTO_EX_DATA *to, CRYPTO_EX_DATA *from, void *from_d, + int idx, long argl, void *argp); + +/* This stuff is basically class callback functions + * The current classes are SSL_CTX, SSL, SSL_SESSION, and a few more */ + +typedef struct crypto_ex_data_func_st + { + long argl; /* Arbitary long */ + void *argp; /* Arbitary void * */ + CRYPTO_EX_new *new_func; + CRYPTO_EX_free *free_func; + CRYPTO_EX_dup *dup_func; + } CRYPTO_EX_DATA_FUNCS; + +DECLARE_STACK_OF(CRYPTO_EX_DATA_FUNCS) + +/* Per class, we have a STACK of CRYPTO_EX_DATA_FUNCS for each CRYPTO_EX_DATA + * entry. + */ + +#define CRYPTO_EX_INDEX_BIO 0 +#define CRYPTO_EX_INDEX_SSL 1 +#define CRYPTO_EX_INDEX_SSL_CTX 2 +#define CRYPTO_EX_INDEX_SSL_SESSION 3 +#define CRYPTO_EX_INDEX_X509_STORE 4 +#define CRYPTO_EX_INDEX_X509_STORE_CTX 5 + + +/* This is the default callbacks, but we can have others as well: + * this is needed in Win32 where the application malloc and the + * library malloc may not be the same. + */ +#define CRYPTO_malloc_init() CRYPTO_set_mem_functions(\ + malloc, realloc, free) + +#if defined CRYPTO_MDEBUG_ALL || defined CRYPTO_MDEBUG_TIME || defined CRYPTO_MDEBUG_THREAD +# ifndef CRYPTO_MDEBUG /* avoid duplicate #define */ +# define CRYPTO_MDEBUG +# endif +#endif + +/* Set standard debugging functions (not done by default + * unless CRYPTO_MDEBUG is defined) */ +#define CRYPTO_malloc_debug_init() do {\ + CRYPTO_set_mem_debug_functions(\ + (void (*)())CRYPTO_dbg_malloc,\ + (void (*)())CRYPTO_dbg_realloc,\ + (void (*)())CRYPTO_dbg_free,\ + (void (*)())CRYPTO_dbg_set_options,\ + (long (*)())CRYPTO_dbg_get_options);\ + } while(0) + +int CRYPTO_mem_ctrl(int mode); +int CRYPTO_is_mem_check_on(void); + +/* for applications */ +#define MemCheck_start() CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON) +#define MemCheck_stop() CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_OFF) + +/* for library-internal use */ +#define MemCheck_on() CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE) +#define MemCheck_off() CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_DISABLE) +#define is_MemCheck_on() CRYPTO_is_mem_check_on() + +#define Malloc(num) CRYPTO_malloc((int)num,__FILE__,__LINE__) +#define Realloc(addr,num) \ + CRYPTO_realloc((char *)addr,(int)num,__FILE__,__LINE__) +#define Remalloc(addr,num) \ + CRYPTO_remalloc((char **)addr,(int)num,__FILE__,__LINE__) +#define FreeFunc CRYPTO_free +#define Free(addr) CRYPTO_free(addr) + +#define Malloc_locked(num) CRYPTO_malloc_locked((int)num,__FILE__,__LINE__) +#define Free_locked(addr) CRYPTO_free_locked(addr) + + +/* Case insensiteve linking causes problems.... */ +#if defined(WIN16) || defined(VMS) +#define ERR_load_CRYPTO_strings ERR_load_CRYPTOlib_strings +#endif + + +const char *SSLeay_version(int type); +unsigned long SSLeay(void); + +int CRYPTO_get_ex_new_index(int idx, STACK_OF(CRYPTO_EX_DATA_FUNCS) **skp, long argl, void *argp, + CRYPTO_EX_new *new_func, CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func); +int CRYPTO_set_ex_data(CRYPTO_EX_DATA *ad, int idx, void *val); +void *CRYPTO_get_ex_data(CRYPTO_EX_DATA *ad,int idx); +int CRYPTO_dup_ex_data(STACK_OF(CRYPTO_EX_DATA_FUNCS) *meth, CRYPTO_EX_DATA *to, + CRYPTO_EX_DATA *from); +void CRYPTO_free_ex_data(STACK_OF(CRYPTO_EX_DATA_FUNCS) *meth, void *obj, CRYPTO_EX_DATA *ad); +void CRYPTO_new_ex_data(STACK_OF(CRYPTO_EX_DATA_FUNCS) *meth, void *obj, CRYPTO_EX_DATA *ad); + +int CRYPTO_get_new_lockid(char *name); + +int CRYPTO_num_locks(void); /* return CRYPTO_NUM_LOCKS (shared libs!) */ +void CRYPTO_lock(int mode, int type,const char *file,int line); +void CRYPTO_set_locking_callback(void (*func)(int mode,int type, + const char *file,int line)); +void (*CRYPTO_get_locking_callback(void))(int mode,int type,const char *file, + int line); +void CRYPTO_set_add_lock_callback(int (*func)(int *num,int mount,int type, + const char *file, int line)); +int (*CRYPTO_get_add_lock_callback(void))(int *num,int mount,int type, + const char *file,int line); +void CRYPTO_set_id_callback(unsigned long (*func)(void)); +unsigned long (*CRYPTO_get_id_callback(void))(void); +unsigned long CRYPTO_thread_id(void); +const char *CRYPTO_get_lock_name(int type); +int CRYPTO_add_lock(int *pointer,int amount,int type, const char *file, + int line); + +/* CRYPTO_set_mem_functions includes CRYPTO_set_locked_mem_functions -- + * call the latter last if you need different functions */ +int CRYPTO_set_mem_functions(void *(*m)(size_t),void *(*r)(void *,size_t), void (*f)(void *)); +int CRYPTO_set_locked_mem_functions(void *(*m)(size_t), void (*free_func)(void *)); +int CRYPTO_set_mem_debug_functions(void (*m)(),void (*r)(),void (*f)(),void (*so)(),long (*go)()); +void CRYPTO_get_mem_functions(void *(**m)(size_t),void *(**r)(void *, size_t), void (**f)(void *)); +void CRYPTO_get_locked_mem_functions(void *(**m)(size_t), void (**f)(void *)); +void CRYPTO_get_mem_debug_functions(void (**m)(),void (**r)(),void (**f)(),void (**so)(),long (**go)()); + +void *CRYPTO_malloc_locked(int num, const char *file, int line); +void CRYPTO_free_locked(void *); +void *CRYPTO_malloc(int num, const char *file, int line); +void CRYPTO_free(void *); +void *CRYPTO_realloc(void *addr,int num, const char *file, int line); +void *CRYPTO_remalloc(void *addr,int num, const char *file, int line); + +void CRYPTO_set_mem_debug_options(long bits); +long CRYPTO_get_mem_debug_options(void); + +#define CRYPTO_push_info(info) \ + CRYPTO_push_info_(info, __FILE__, __LINE__); +int CRYPTO_push_info_(const char *info, const char *file, int line); +int CRYPTO_pop_info(void); +int CRYPTO_remove_all_info(void); + +/* The last argument has the following significance: + * + * 0: called before the actual memory allocation has taken place + * 1: called after the actual memory allocation has taken place + */ +void CRYPTO_dbg_malloc(void *addr,int num,const char *file,int line,int before_p); +void CRYPTO_dbg_realloc(void *addr1,void *addr2,int num,const char *file,int line,int before_p); +void CRYPTO_dbg_free(void *addr,int before_p); + +/* Tell the debugging code about options. By default, the following values + * apply: + * + * 0: Clear all options. + * 1: Set the "Show Time" option. + * 2: Set the "Show Thread Number" option. + * 3: 1 + 2 + */ +void CRYPTO_dbg_set_options(long bits); +long CRYPTO_dbg_get_options(void); + +#ifndef NO_FP_API +void CRYPTO_mem_leaks_fp(FILE *); +#endif +void CRYPTO_mem_leaks(struct bio_st *bio); +/* unsigned long order, char *file, int line, int num_bytes, char *addr */ +void CRYPTO_mem_leaks_cb(void (*cb)()); + +void ERR_load_CRYPTO_strings(void); + +/* BEGIN ERROR CODES */ +/* The following lines are auto generated by the script mkerr.pl. Any changes + * made after this point may be overwritten when the script is next run. + */ + +/* Error codes for the CRYPTO functions. */ + +/* Function codes. */ +#define CRYPTO_F_CRYPTO_GET_EX_NEW_INDEX 100 +#define CRYPTO_F_CRYPTO_GET_NEW_LOCKID 101 +#define CRYPTO_F_CRYPTO_SET_EX_DATA 102 + +/* Reason codes. */ + +#ifdef __cplusplus +} +#endif +#endif + diff --git a/libsecurity_apple_csp/open_ssl/openssl/dh.h b/libsecurity_apple_csp/open_ssl/openssl/dh.h new file mode 100644 index 00000000..4903c1a4 --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/openssl/dh.h @@ -0,0 +1,221 @@ +/* + * Copyright (c) 2000-2002 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. + */ + +/* crypto/dh/dh.h */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef HEADER_DH_H +#define HEADER_DH_H + +#ifdef NO_DH +#error DH is disabled. +#endif + +#ifndef NO_BIO +#include +#endif +#include +#include + +#define DH_FLAG_CACHE_MONT_P 0x01 + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct dh_st DH; + +typedef struct dh_method { + const char *name; + /* Methods here */ + int (*generate_key)(DH *dh); + int (*compute_key)(unsigned char *key,BIGNUM *pub_key,DH *dh); + int (*bn_mod_exp)(DH *dh, BIGNUM *r, BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx, + BN_MONT_CTX *m_ctx); /* Can be null */ + + int (*init)(DH *dh); + int (*finish)(DH *dh); + int flags; + char *app_data; +} DH_METHOD; + +struct dh_st + { + /* This first argument is used to pick up errors when + * a DH is passed instead of a EVP_PKEY */ + int pad; + int version; + BIGNUM *p; + BIGNUM *g; + int length; /* optional */ + BIGNUM *pub_key; /* g^x */ + BIGNUM *priv_key; /* x */ + + int flags; + char *method_mont_p; + /* Place holders if we want to do X9.42 DH */ + BIGNUM *q; + BIGNUM *j; + unsigned char *seed; + int seedlen; + BIGNUM *counter; + + int references; + CRYPTO_EX_DATA ex_data; + DH_METHOD *meth; + }; + +#define DH_GENERATOR_2 2 +/* #define DH_GENERATOR_3 3 */ +#define DH_GENERATOR_5 5 + +/* DH_check error codes */ +#define DH_CHECK_P_NOT_PRIME 0x01 +#define DH_CHECK_P_NOT_SAFE_PRIME 0x02 +#define DH_UNABLE_TO_CHECK_GENERATOR 0x04 +#define DH_NOT_SUITABLE_GENERATOR 0x08 + +/* primes p where (p-1)/2 is prime too are called "safe"; we define + this for backward compatibility: */ +#define DH_CHECK_P_NOT_STRONG_PRIME DH_CHECK_P_NOT_SAFE_PRIME + +#define DHparams_dup(x) (DH *)ASN1_dup((int (*)())i2d_DHparams, \ + (char *(*)())d2i_DHparams,(char *)(x)) +#define d2i_DHparams_fp(fp,x) (DH *)ASN1_d2i_fp((char *(*)())DH_new, \ + (char *(*)())d2i_DHparams,(fp),(unsigned char **)(x)) +#define i2d_DHparams_fp(fp,x) ASN1_i2d_fp(i2d_DHparams,(fp), \ + (unsigned char *)(x)) +#define d2i_DHparams_bio(bp,x) (DH *)ASN1_d2i_bio((char *(*)())DH_new, \ + (char *(*)())d2i_DHparams,(bp),(unsigned char **)(x)) +#ifdef __cplusplus +#define i2d_DHparams_bio(bp,x) ASN1_i2d_bio((int (*)())i2d_DHparams,(bp), \ + (unsigned char *)(x)) +#else +#define i2d_DHparams_bio(bp,x) ASN1_i2d_bio(i2d_DHparams,(bp), \ + (unsigned char *)(x)) +#endif + +DH_METHOD *DH_OpenSSL(void); + +void DH_set_default_method(DH_METHOD *meth); +DH_METHOD *DH_get_default_method(void); +DH_METHOD *DH_set_method(DH *dh, DH_METHOD *meth); +DH *DH_new_method(DH_METHOD *meth); + +DH * DH_new(void); +void DH_free(DH *dh); +int DH_size(DH *dh); +int DH_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, + CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func); +int DH_set_ex_data(DH *d, int idx, void *arg); +void *DH_get_ex_data(DH *d, int idx); +DH * DH_generate_parameters(int prime_len,int generator, + void (*callback)(int,int,void *),void *cb_arg); +int DH_check(DH *dh,int *codes); +int DH_generate_key(DH *dh); +int DH_compute_key(unsigned char *key,BIGNUM *pub_key,DH *dh); +DH * d2i_DHparams(DH **a,unsigned char **pp, long length); +int i2d_DHparams(DH *a,unsigned char **pp); +#ifndef NO_FP_API +int DHparams_print_fp(FILE *fp, DH *x); +#endif +#ifndef NO_BIO +int DHparams_print(BIO *bp, DH *x); +#else +int DHparams_print(char *bp, DH *x); +#endif +void ERR_load_DH_strings(void ); + +/* BEGIN ERROR CODES */ +/* The following lines are auto generated by the script mkerr.pl. Any changes + * made after this point may be overwritten when the script is next run. + */ + +/* Error codes for the DH functions. */ + +/* Function codes. */ +#define DH_F_DHPARAMS_PRINT 100 +#define DH_F_DHPARAMS_PRINT_FP 101 +#define DH_F_DH_COMPUTE_KEY 102 +#define DH_F_DH_GENERATE_KEY 103 +#define DH_F_DH_GENERATE_PARAMETERS 104 +#define DH_F_DH_NEW 105 + +/* Reason codes. */ +#define DH_R_NO_PRIVATE_VALUE 100 + +#ifdef __cplusplus +} +#endif +#endif + diff --git a/libsecurity_apple_csp/open_ssl/openssl/dsa.h b/libsecurity_apple_csp/open_ssl/openssl/dsa.h new file mode 100644 index 00000000..08fdfaca --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/openssl/dsa.h @@ -0,0 +1,259 @@ +/* + * Copyright (c) 2000-2002 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. + */ + + +/* crypto/dsa/dsa.h */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +/* + * The DSS routines are based on patches supplied by + * Steven Schoch . He basically did the + * work and I have just tweaked them a little to fit into my + * stylistic vision for SSLeay :-) */ + +#ifndef HEADER_DSA_H +#define HEADER_DSA_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef NO_DSA +#error DSA is disabled. +#endif + +#include +#include +#ifndef NO_DH +# include +#endif + +#define DSA_FLAG_CACHE_MONT_P 0x01 + +typedef struct dsa_st DSA; + +typedef struct DSA_SIG_st + { + BIGNUM *r; + BIGNUM *s; + } DSA_SIG; + +typedef struct dsa_method { + const char *name; + DSA_SIG * (*dsa_do_sign)(const unsigned char *dgst, int dlen, DSA *dsa); + int (*dsa_sign_setup)(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp, + BIGNUM **rp); + int (*dsa_do_verify)(const unsigned char *dgst, int dgst_len, + DSA_SIG *sig, DSA *dsa); + int (*dsa_mod_exp)(DSA *dsa, BIGNUM *rr, BIGNUM *a1, BIGNUM *p1, + BIGNUM *a2, BIGNUM *p2, BIGNUM *m, BN_CTX *ctx, + BN_MONT_CTX *in_mont); + int (*bn_mod_exp)(DSA *dsa, BIGNUM *r, BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx, + BN_MONT_CTX *m_ctx); /* Can be null */ + int (*init)(DSA *dsa); + int (*finish)(DSA *dsa); + int flags; + char *app_data; +} DSA_METHOD; + +struct dsa_st + { + /* This first variable is used to pick up errors where + * a DSA is passed instead of of a EVP_PKEY */ + int pad; + int version; + int write_params; + BIGNUM *p; + BIGNUM *q; /* == 20 */ + BIGNUM *g; + + BIGNUM *pub_key; /* y public key */ + BIGNUM *priv_key; /* x private key */ + + BIGNUM *kinv; /* Signing pre-calc */ + BIGNUM *r; /* Signing pre-calc */ + + int flags; + /* Normally used to cache montgomery values */ + char *method_mont_p; + int references; + CRYPTO_EX_DATA ex_data; + const DSA_METHOD *meth; + }; + +#define DSAparams_dup(x) (DSA *)ASN1_dup((int (*)())i2d_DSAparams, \ + (char *(*)())d2i_DSAparams,(char *)(x)) +#define d2i_DSAparams_fp(fp,x) (DSA *)ASN1_d2i_fp((char *(*)())DSA_new, \ + (char *(*)())d2i_DSAparams,(fp),(unsigned char **)(x)) +#define i2d_DSAparams_fp(fp,x) ASN1_i2d_fp(i2d_DSAparams,(fp), \ + (unsigned char *)(x)) +#define d2i_DSAparams_bio(bp,x) (DSA *)ASN1_d2i_bio((char *(*)())DSA_new, \ + (char *(*)())d2i_DSAparams,(bp),(unsigned char **)(x)) +#define i2d_DSAparams_bio(bp,x) ASN1_i2d_bio(i2d_DSAparams,(bp), \ + (unsigned char *)(x)) + + +DSA_SIG * DSA_SIG_new(void); +void DSA_SIG_free(DSA_SIG *a); +int i2d_DSA_SIG(DSA_SIG *a, unsigned char **pp); +DSA_SIG * d2i_DSA_SIG(DSA_SIG **v, unsigned char **pp, long length); + +DSA_SIG * DSA_do_sign(const unsigned char *dgst,int dlen,DSA *dsa); +int DSA_do_verify(const unsigned char *dgst,int dgst_len, + DSA_SIG *sig,DSA *dsa); + +const DSA_METHOD *DSA_OpenSSL(void); + +void DSA_set_default_method(const DSA_METHOD *); +const DSA_METHOD *DSA_get_default_method(void); +const DSA_METHOD *DSA_set_method(DSA *dsa, const DSA_METHOD *); + +DSA * DSA_new(void); +DSA * DSA_new_method(const DSA_METHOD *meth); +int DSA_size(DSA *); + /* next 4 return -1 on error */ +int DSA_sign_setup( DSA *dsa,BN_CTX *ctx_in,BIGNUM **kinvp,BIGNUM **rp); +int DSA_sign(int type,const unsigned char *dgst,int dlen, + unsigned char *sig, unsigned int *siglen, DSA *dsa); +int DSA_verify(int type,const unsigned char *dgst,int dgst_len, + unsigned char *sigbuf, int siglen, DSA *dsa); +void DSA_free (DSA *r); +int DSA_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, + CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func); +int DSA_set_ex_data(DSA *d, int idx, void *arg); +void *DSA_get_ex_data(DSA *d, int idx); + +void ERR_load_DSA_strings(void ); + +DSA * d2i_DSAPublicKey(DSA **a, unsigned char **pp, long length); +DSA * d2i_DSAPrivateKey(DSA **a, unsigned char **pp, long length); +DSA * d2i_DSAparams(DSA **a, unsigned char **pp, long length); +DSA * DSA_generate_parameters(int bits, unsigned char *seed,int seed_len, + int *counter_ret, unsigned long *h_ret,void + (*callback)(int, int, void *),void *cb_arg); +int DSA_generate_key(DSA *a); +int i2d_DSAPublicKey(DSA *a, unsigned char **pp); +int i2d_DSAPrivateKey(DSA *a, unsigned char **pp); +int i2d_DSAparams(DSA *a,unsigned char **pp); + +#ifdef HEADER_BIO_H +int DSAparams_print(BIO *bp, DSA *x); +int DSA_print(BIO *bp, DSA *x, int off); +#endif +#ifndef NO_FP_API +int DSAparams_print_fp(FILE *fp, DSA *x); +int DSA_print_fp(FILE *bp, DSA *x, int off); +#endif + +#define DSS_prime_checks 50 +/* Primality test according to FIPS PUB 186[-1], Appendix 2.1: + * 50 rounds of Rabin-Miller */ +#define DSA_is_prime(n, callback, cb_arg) \ + BN_is_prime(n, DSS_prime_checks, callback, NULL, cb_arg) + +#ifndef NO_DH +/* Convert DSA structure (key or just parameters) into DH structure + * (be careful to avoid small subgroup attacks when using this!) */ +DH *DSA_dup_DH(DSA *r); +#endif + +/* BEGIN ERROR CODES */ +/* The following lines are auto generated by the script mkerr.pl. Any changes + * made after this point may be overwritten when the script is next run. + */ + +/* Error codes for the DSA functions. */ + +/* Function codes. */ +#define DSA_F_D2I_DSA_SIG 110 +#define DSA_F_DSAPARAMS_PRINT 100 +#define DSA_F_DSAPARAMS_PRINT_FP 101 +#define DSA_F_DSA_DO_SIGN 112 +#define DSA_F_DSA_DO_VERIFY 113 +#define DSA_F_DSA_NEW 103 +#define DSA_F_DSA_PRINT 104 +#define DSA_F_DSA_PRINT_FP 105 +#define DSA_F_DSA_SIGN 106 +#define DSA_F_DSA_SIGN_SETUP 107 +#define DSA_F_DSA_SIG_NEW 109 +#define DSA_F_DSA_VERIFY 108 +#define DSA_F_I2D_DSA_SIG 111 + +/* Reason codes. */ +#define DSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE 100 + +#ifdef __cplusplus +} +#endif +#endif + diff --git a/libsecurity_apple_csp/open_ssl/openssl/e_os.h b/libsecurity_apple_csp/open_ssl/openssl/e_os.h new file mode 100644 index 00000000..c94d6dd9 --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/openssl/e_os.h @@ -0,0 +1,464 @@ +/* + * 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. + */ + + +/* e_os.h */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef HEADER_E_OS_H +#define HEADER_E_OS_H + +#include + +#include +/* contains what we can justify to make visible + * to the outside; this file e_os.h is not part of the exported + * interface. */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Used to checking reference counts, most while doing perl5 stuff :-) */ +#ifdef REF_PRINT +#undef REF_PRINT +#define REF_PRINT(a,b) fprintf(stderr,"%08X:%4d:%s\n",(int)b,b->references,a) +#endif + +#ifndef DEVRANDOM +/* set this to your 'random' device if you have one. + * My default, we will try to read this file */ +#define DEVRANDOM "/dev/urandom" +#endif + +#if defined(__MWERKS__) && defined(macintosh) +# if macintosh==1 +# ifndef MAC_OS_GUSI_SOURCE +# define MAC_OS_pre_X +# define NO_SYS_TYPES_H +# endif +# define NO_SYS_PARAM_H +# define NO_CHMOD +# define NO_SYSLOG +# undef DEVRANDOM +# define GETPID_IS_MEANINGLESS +# endif +#endif + +/******************************************************************** + The Microsoft section + ********************************************************************/ +/* The following is used becaue of the small stack in some + * Microsoft operating systems */ +#if defined(WIN16) || defined(MSDOS) +# define MS_STATIC static +#else +# define MS_STATIC +#endif + +#if defined(_WIN32) && !defined(WIN32) +# define WIN32 +#endif + +#if defined(WIN32) || defined(WIN16) +# ifndef WINDOWS +# define WINDOWS +# endif +# ifndef MSDOS +# define MSDOS +# endif +#endif + +#if defined(MSDOS) && !defined(GETPID_IS_MEANINGLESS) +# define GETPID_IS_MEANINGLESS +#endif + +#ifdef WIN32 +#define get_last_sys_error() GetLastError() +#define clear_sys_error() SetLastError(0) +#if !defined(WINNT) +#define WIN_CONSOLE_BUG +#endif +#else +#define get_last_sys_error() errno +#define clear_sys_error() errno=0 +#endif + +#ifdef WINDOWS +#define get_last_socket_error() WSAGetLastError() +#define clear_socket_error() WSASetLastError(0) +#define readsocket(s,b,n) recv((s),(b),(n),0) +#define writesocket(s,b,n) send((s),(b),(n),0) +#define EADDRINUSE WSAEADDRINUSE +#elif defined(MAC_OS_pre_X) +#define get_last_socket_error() errno +#define clear_socket_error() errno=0 +#define closesocket(s) MacSocket_close(s) +#define readsocket(s,b,n) MacSocket_recv((s),(b),(n),true) +#define writesocket(s,b,n) MacSocket_send((s),(b),(n)) +#else +#define get_last_socket_error() errno +#define clear_socket_error() errno=0 +#define ioctlsocket(a,b,c) ioctl(a,b,c) +#define closesocket(s) close(s) +#define readsocket(s,b,n) read((s),(b),(n)) +#define writesocket(s,b,n) write((s),(b),(n)) +#endif + +#ifdef WIN16 +# define NO_FP_API +# define MS_CALLBACK _far _loadds +# define MS_FAR _far +#else +# define MS_CALLBACK +# define MS_FAR +#endif + +#ifdef NO_STDIO +# define NO_FP_API +#endif + +#if defined(WINDOWS) || defined(MSDOS) + +# ifndef S_IFDIR +# define S_IFDIR _S_IFDIR +# endif + +# ifndef S_IFMT +# define S_IFMT _S_IFMT +# endif + +# if !defined(WINNT) +# define NO_SYSLOG +# endif +# define NO_DIRENT + +# ifdef WINDOWS +# include +# include +# include +# include +# include +# endif +# include +# include + +# define ssize_t long + +# if defined (__BORLANDC__) +# define _setmode setmode +# define _O_TEXT O_TEXT +# define _O_BINARY O_BINARY +# define _int64 __int64 +# define _kbhit kbhit +# endif + +# if defined(WIN16) && !defined(MONOLITH) && defined(SSLEAY) && defined(_WINEXITNOPERSIST) +# define EXIT(n) { if (n == 0) _wsetexit(_WINEXITNOPERSIST); return(n); } +# else +# define EXIT(n) return(n); +# endif +# define LIST_SEPARATOR_CHAR ';' +# ifndef X_OK +# define X_OK 0 +# endif +# ifndef W_OK +# define W_OK 2 +# endif +# ifndef R_OK +# define R_OK 4 +# endif +# define OPENSSL_CONF "openssl.cnf" +# define SSLEAY_CONF OPENSSL_CONF +# define NUL_DEV "nul" +# define RFILE ".rnd" + +#else /* The non-microsoft world world */ + +# if defined(__VMS) && !defined(VMS) +# define VMS 1 +# endif + +# ifdef VMS + /* some programs don't include stdlib, so exit() and others give implicit + function warnings */ +# include +# if defined(__DECC) +# include +# else +# include +# endif +# define OPENSSL_CONF "openssl.cnf" +# define SSLEAY_CONF OPENSSL_CONF +# define RFILE ".rnd" +# define LIST_SEPARATOR_CHAR ',' +# define NUL_DEV "NLA0:" + /* We need to do this since VMS has the following coding on status codes: + + Bits 0-2: status type: 0 = warning, 1 = success, 2 = error, 3 = info ... + The important thing to know is that odd numbers are considered + good, while even ones are considered errors. + Bits 3-15: actual status number + Bits 16-27: facility number. 0 is considered "unknown" + Bits 28-31: control bits. If bit 28 is set, the shell won't try to + output the message (which, for random codes, just looks ugly) + + So, what we do here is to change 0 to 1 to get the default success status, + and everything else is shifted up to fit into the status number field, and + the status is tagged as an error, which I believe is what is wanted here. + -- Richard Levitte + */ +# if !defined(MONOLITH) || defined(OPENSSL_C) +# define EXIT(n) do { int __VMS_EXIT = n; \ + if (__VMS_EXIT == 0) \ + __VMS_EXIT = 1; \ + else \ + __VMS_EXIT = (n << 3) | 2; \ + __VMS_EXIT |= 0x10000000; \ + exit(__VMS_EXIT); \ + return(__VMS_EXIT); } while(0) +# else +# define EXIT(n) return(n) +# endif +# define NO_SYS_PARAM_H +# else + /* !defined VMS */ +# ifdef OPENSSL_UNISTD +# include OPENSSL_UNISTD +# else +# include +# endif +# ifndef NO_SYS_TYPES_H +# include +# endif +# ifdef NeXT +# define pid_t int /* pid_t is missing on NEXTSTEP/OPENSTEP + * (unless when compiling with -D_POSIX_SOURCE, + * which doesn't work for us) */ +# define ssize_t int /* ditto */ +# endif + +# define OPENSSL_CONF "openssl.cnf" +# define SSLEAY_CONF OPENSSL_CONF +# define RFILE ".rnd" +# define LIST_SEPARATOR_CHAR ':' +# define NUL_DEV "/dev/null" +# ifndef MONOLITH +# define EXIT(n) exit(n); return(n) +# else +# define EXIT(n) return(n) +# endif +# endif + +# define SSLeay_getpid() getpid() + +#endif + + +/*************/ + +#ifdef USE_SOCKETS +# if defined(WINDOWS) || defined(MSDOS) + /* windows world */ + +# ifdef NO_SOCK +# define SSLeay_Write(a,b,c) (-1) +# define SSLeay_Read(a,b,c) (-1) +# define SHUTDOWN(fd) close(fd) +# define SHUTDOWN2(fd) close(fd) +# else +# include +extern HINSTANCE _hInstance; +# define SSLeay_Write(a,b,c) send((a),(b),(c),0) +# define SSLeay_Read(a,b,c) recv((a),(b),(c),0) +# define SHUTDOWN(fd) { shutdown((fd),0); closesocket(fd); } +# define SHUTDOWN2(fd) { shutdown((fd),2); closesocket(fd); } +# endif + +# elif defined(MAC_OS_pre_X) + +# include "MacSocket.h" +# define SSLeay_Write(a,b,c) MacSocket_send((a),(b),(c)) +# define SSLeay_Read(a,b,c) MacSocket_recv((a),(b),(c),true) +# define SHUTDOWN(fd) MacSocket_close(fd) +# define SHUTDOWN2(fd) MacSocket_close(fd) + +# else + +# ifndef NO_SYS_PARAM_H +# include +# endif +# include /* Needed under linux for FD_XXX */ + +# include +# if defined(VMS) && !defined(__DECC) +# include +# include +# else +# include +# ifdef FILIO_H +# include /* Added for FIONBIO under unixware */ +# endif +# include +# endif + +# if defined(NeXT) || defined(_NEXT_SOURCE) +# include +# include +# endif + +# ifdef AIX +# include +# endif + +# if defined(sun) +# include +# else +# ifndef VMS +# include +# else + /* ioctl is only in VMS > 7.0 and when socketshr is not used */ +# if !defined(TCPIP_TYPE_SOCKETSHR) && defined(__VMS_VER) && (__VMS_VER > 70000000) +# include +# endif +# endif +# endif + +# ifdef VMS +# include +# if defined(TCPIP_TYPE_SOCKETSHR) +# include +# endif +# endif + +# define SSLeay_Read(a,b,c) read((a),(b),(c)) +# define SSLeay_Write(a,b,c) write((a),(b),(c)) +# define SHUTDOWN(fd) { shutdown((fd),0); closesocket((fd)); } +# define SHUTDOWN2(fd) { shutdown((fd),2); closesocket((fd)); } +# define INVALID_SOCKET (-1) +# endif +#endif + +#if defined(__ultrix) +# ifndef ssize_t +# define ssize_t int +# endif +#endif + +#if defined(THREADS) || defined(sun) +#ifndef _REENTRANT +#define _REENTRANT +#endif +#endif + +/***********************************************/ + +/* do we need to do this for getenv. + * Just define getenv for use under windows */ + +#ifdef WIN16 +/* How to do this needs to be thought out a bit more.... */ +/*char *GETENV(char *); +#define Getenv GETENV*/ +#define Getenv getenv +#else +#define Getenv getenv +#endif + +#define DG_GCC_BUG /* gcc < 2.6.3 on DGUX */ + +#ifdef sgi +#define IRIX_CC_BUG /* all version of IRIX I've tested (4.* 5.*) */ +#endif +#ifdef SNI +#define IRIX_CC_BUG /* CDS++ up to V2.0Bsomething suffered from the same bug.*/ +#endif + +#ifdef NO_MD2 +#define MD2_Init MD2Init +#define MD2_Update MD2Update +#define MD2_Final MD2Final +#define MD2_DIGEST_LENGTH 16 +#endif +#ifdef NO_MD5 +#define MD5_Init MD5Init +#define MD5_Update MD5Update +#define MD5_Final MD5Final +#define MD5_DIGEST_LENGTH 16 +#endif + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/libsecurity_apple_csp/open_ssl/openssl/e_os2.h b/libsecurity_apple_csp/open_ssl/openssl/e_os2.h new file mode 100644 index 00000000..47ab43b3 --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/openssl/e_os2.h @@ -0,0 +1,56 @@ +/* + * 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. + */ + + +/* e_os2.h */ + +#ifndef HEADER_E_OS2_H +#define HEADER_E_OS2_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include /* OPENSSL_UNISTD */ + +#ifdef MSDOS +# define OPENSSL_UNISTD_IO +# define OPENSSL_DECLARE_EXIT extern void exit(int); +#else +# define OPENSSL_UNISTD_IO OPENSSL_UNISTD +# define OPENSSL_DECLARE_EXIT /* declared in unistd.h */ +#endif + +/* Definitions of OPENSSL_GLOBAL and OPENSSL_EXTERN, + to define and declare certain global + symbols that, with some compilers under VMS, have to be defined and + declared explicitely with globaldef and globalref. On other OS:es, + these macros are defined with something sensible. */ + +#if defined(VMS) && !defined(__DECC) +# define OPENSSL_EXTERN globalref +# define OPENSSL_GLOBAL globaldef +#else +# define OPENSSL_EXTERN extern +# define OPENSSL_GLOBAL +#endif + +#ifdef __cplusplus +} +#endif +#endif + diff --git a/libsecurity_apple_csp/open_ssl/openssl/err.h b/libsecurity_apple_csp/open_ssl/openssl/err.h new file mode 100644 index 00000000..255c8cca --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/openssl/err.h @@ -0,0 +1,285 @@ +/* + * 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. + */ + + +/* crypto/err/err.h */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef HEADER_ERR_H +#define HEADER_ERR_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#ifndef NO_FP_API +#include +#endif + +/* The following is a bit of a trick to help the object files only contain + * the 'name of the file' string once. Since 'err.h' is protected by the + * HEADER_ERR_H stuff, this should be included only once per file. */ + +#define ERR_file_name __FILE__ + +#ifndef NO_ERR +#define ERR_PUT_error(a,b,c,d,e) ERR_put_error(a,b,c,d,e) +#else +#define ERR_PUT_error(a,b,c,d,e) ERR_put_error(a,b,c,NULL,0) +#endif + +#include + +#define ERR_TXT_MALLOCED 0x01 +#define ERR_TXT_STRING 0x02 + +#define ERR_NUM_ERRORS 16 +typedef struct err_state_st + { + unsigned long pid; + unsigned long err_buffer[ERR_NUM_ERRORS]; + char *err_data[ERR_NUM_ERRORS]; + int err_data_flags[ERR_NUM_ERRORS]; + const char *err_file[ERR_NUM_ERRORS]; + int err_line[ERR_NUM_ERRORS]; + int top,bottom; + } ERR_STATE; + +/* library */ +#define ERR_LIB_NONE 1 +#define ERR_LIB_SYS 2 +#define ERR_LIB_BN 3 +#define ERR_LIB_RSA 4 +#define ERR_LIB_DH 5 +#define ERR_LIB_EVP 6 +#define ERR_LIB_BUF 7 +#define ERR_LIB_OBJ 8 +#define ERR_LIB_PEM 9 +#define ERR_LIB_DSA 10 +#define ERR_LIB_X509 11 +#define ERR_LIB_METH 12 +#define ERR_LIB_ASN1 13 +#define ERR_LIB_CONF 14 +#define ERR_LIB_CRYPTO 15 +#define ERR_LIB_SSL 20 +#define ERR_LIB_SSL23 21 +#define ERR_LIB_SSL2 22 +#define ERR_LIB_SSL3 23 +#define ERR_LIB_RSAREF 30 +#define ERR_LIB_PROXY 31 +#define ERR_LIB_BIO 32 +#define ERR_LIB_PKCS7 33 +#define ERR_LIB_X509V3 34 +#define ERR_LIB_PKCS12 35 +#define ERR_LIB_RAND 36 + +#define ERR_LIB_USER 128 + +#define SYSerr(f,r) ERR_PUT_error(ERR_LIB_SYS,(f),(r),ERR_file_name,__LINE__) +#define BNerr(f,r) ERR_PUT_error(ERR_LIB_BN,(f),(r),ERR_file_name,__LINE__) +#define RSAerr(f,r) ERR_PUT_error(ERR_LIB_RSA,(f),(r),ERR_file_name,__LINE__) +#define DHerr(f,r) ERR_PUT_error(ERR_LIB_DH,(f),(r),ERR_file_name,__LINE__) +#define EVPerr(f,r) ERR_PUT_error(ERR_LIB_EVP,(f),(r),ERR_file_name,__LINE__) +#define BUFerr(f,r) ERR_PUT_error(ERR_LIB_BUF,(f),(r),ERR_file_name,__LINE__) +#define BIOerr(f,r) ERR_PUT_error(ERR_LIB_BIO,(f),(r),ERR_file_name,__LINE__) +#define OBJerr(f,r) ERR_PUT_error(ERR_LIB_OBJ,(f),(r),ERR_file_name,__LINE__) +#define PEMerr(f,r) ERR_PUT_error(ERR_LIB_PEM,(f),(r),ERR_file_name,__LINE__) +#define DSAerr(f,r) ERR_PUT_error(ERR_LIB_DSA,(f),(r),ERR_file_name,__LINE__) +#define X509err(f,r) ERR_PUT_error(ERR_LIB_X509,(f),(r),ERR_file_name,__LINE__) +#define METHerr(f,r) ERR_PUT_error(ERR_LIB_METH,(f),(r),ERR_file_name,__LINE__) +#define ASN1err(f,r) ERR_PUT_error(ERR_LIB_ASN1,(f),(r),ERR_file_name,__LINE__) +#define CONFerr(f,r) ERR_PUT_error(ERR_LIB_CONF,(f),(r),ERR_file_name,__LINE__) +#define CRYPTOerr(f,r) ERR_PUT_error(ERR_LIB_CRYPTO,(f),(r),ERR_file_name,__LINE__) +#define SSLerr(f,r) ERR_PUT_error(ERR_LIB_SSL,(f),(r),ERR_file_name,__LINE__) +#define SSL23err(f,r) ERR_PUT_error(ERR_LIB_SSL23,(f),(r),ERR_file_name,__LINE__) +#define SSL2err(f,r) ERR_PUT_error(ERR_LIB_SSL2,(f),(r),ERR_file_name,__LINE__) +#define SSL3err(f,r) ERR_PUT_error(ERR_LIB_SSL3,(f),(r),ERR_file_name,__LINE__) +#define RSAREFerr(f,r) ERR_PUT_error(ERR_LIB_RSAREF,(f),(r),ERR_file_name,__LINE__) +#define PROXYerr(f,r) ERR_PUT_error(ERR_LIB_PROXY,(f),(r),ERR_file_name,__LINE__) +#define PKCS7err(f,r) ERR_PUT_error(ERR_LIB_PKCS7,(f),(r),ERR_file_name,__LINE__) +#define X509V3err(f,r) ERR_PUT_error(ERR_LIB_X509V3,(f),(r),ERR_file_name,__LINE__) +#define PKCS12err(f,r) ERR_PUT_error(ERR_LIB_PKCS12,(f),(r),ERR_file_name,__LINE__) +#define RANDerr(f,r) ERR_PUT_error(ERR_LIB_RAND,(f),(r),ERR_file_name,__LINE__) + +/* Borland C seems too stupid to be able to shift and do longs in + * the pre-processor :-( */ +#define ERR_PACK(l,f,r) (((((unsigned long)l)&0xffL)*0x1000000)| \ + ((((unsigned long)f)&0xfffL)*0x1000)| \ + ((((unsigned long)r)&0xfffL))) +#define ERR_GET_LIB(l) (int)((((unsigned long)l)>>24L)&0xffL) +#define ERR_GET_FUNC(l) (int)((((unsigned long)l)>>12L)&0xfffL) +#define ERR_GET_REASON(l) (int)((l)&0xfffL) +#define ERR_FATAL_ERROR(l) (int)((l)&ERR_R_FATAL) + +/* OS functions */ +#define SYS_F_FOPEN 1 +#define SYS_F_CONNECT 2 +#define SYS_F_GETSERVBYNAME 3 +#define SYS_F_SOCKET 4 +#define SYS_F_IOCTLSOCKET 5 +#define SYS_F_BIND 6 +#define SYS_F_LISTEN 7 +#define SYS_F_ACCEPT 8 +#define SYS_F_WSASTARTUP 9 /* Winsock stuff */ +#define SYS_F_OPENDIR 10 + +#define ERR_R_FATAL 32 +/* reasons */ +#define ERR_R_SYS_LIB ERR_LIB_SYS +#define ERR_R_BN_LIB ERR_LIB_BN +#define ERR_R_RSA_LIB ERR_LIB_RSA +#define ERR_R_DSA_LIB ERR_LIB_DSA +#define ERR_R_DH_LIB ERR_LIB_DH +#define ERR_R_EVP_LIB ERR_LIB_EVP +#define ERR_R_BUF_LIB ERR_LIB_BUF +#define ERR_R_BIO_LIB ERR_LIB_BIO +#define ERR_R_OBJ_LIB ERR_LIB_OBJ +#define ERR_R_PEM_LIB ERR_LIB_PEM +#define ERR_R_X509_LIB ERR_LIB_X509 +#define ERR_R_METH_LIB ERR_LIB_METH +#define ERR_R_ASN1_LIB ERR_LIB_ASN1 +#define ERR_R_CONF_LIB ERR_LIB_CONF +#define ERR_R_CRYPTO_LIB ERR_LIB_CRYPTO +#define ERR_R_SSL_LIB ERR_LIB_SSL +#define ERR_R_SSL23_LIB ERR_LIB_SSL23 +#define ERR_R_SSL2_LIB ERR_LIB_SSL2 +#define ERR_R_SSL3_LIB ERR_LIB_SSL3 +#define ERR_R_PROXY_LIB ERR_LIB_PROXY +#define ERR_R_BIO_LIB ERR_LIB_BIO +#define ERR_R_PKCS7_LIB ERR_LIB_PKCS7 +#define ERR_R_PKCS12_LIB ERR_LIB_PKCS12 + +/* fatal error */ +#define ERR_R_MALLOC_FAILURE (1|ERR_R_FATAL) +#define ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED (2|ERR_R_FATAL) +#define ERR_R_PASSED_NULL_PARAMETER (3|ERR_R_FATAL) +#define ERR_R_NESTED_ASN1_ERROR (4) +#define ERR_R_BAD_ASN1_OBJECT_HEADER (5) +#define ERR_R_BAD_GET_ASN1_OBJECT_CALL (6) +#define ERR_R_EXPECTING_AN_ASN1_SEQUENCE (7) +#define ERR_R_ASN1_LENGTH_MISMATCH (8) +#define ERR_R_MISSING_ASN1_EOS (9) + +typedef struct ERR_string_data_st + { + unsigned long error; + const char *string; + } ERR_STRING_DATA; + +void ERR_put_error(int lib, int func,int reason,const char *file,int line); +void ERR_set_error_data(char *data,int flags); + +unsigned long ERR_get_error(void ); +unsigned long ERR_get_error_line(const char **file,int *line); +unsigned long ERR_get_error_line_data(const char **file,int *line, + const char **data, int *flags); +unsigned long ERR_peek_error(void ); +unsigned long ERR_peek_error_line(const char **file,int *line); +unsigned long ERR_peek_error_line_data(const char **file,int *line, + const char **data,int *flags); +void ERR_clear_error(void ); +char *ERR_error_string(unsigned long e,char *buf); +const char *ERR_lib_error_string(unsigned long e); +const char *ERR_func_error_string(unsigned long e); +const char *ERR_reason_error_string(unsigned long e); +#ifndef NO_FP_API +void ERR_print_errors_fp(FILE *fp); +#endif +#ifdef HEADER_BIO_H +void ERR_print_errors(BIO *bp); +void ERR_add_error_data(int num, ...); +#endif +void ERR_load_strings(int lib,ERR_STRING_DATA str[]); +void ERR_load_ERR_strings(void); +void ERR_load_crypto_strings(void); +void ERR_free_strings(void); + +void ERR_remove_state(unsigned long pid); /* if zero we look it up */ +ERR_STATE *ERR_get_state(void); + +#ifdef HEADER_LHASH_H +LHASH *ERR_get_string_table(void ); +LHASH *ERR_get_err_state_table(void ); +#else +char *ERR_get_string_table(void ); +char *ERR_get_err_state_table(void ); +#endif + +int ERR_get_next_error_library(void ); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libsecurity_apple_csp/open_ssl/openssl/evp.h b/libsecurity_apple_csp/open_ssl/openssl/evp.h new file mode 100644 index 00000000..02d69fd3 --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/openssl/evp.h @@ -0,0 +1,761 @@ +/* + * 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. + */ + + +/* crypto/evp/evp.h */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef HEADER_ENVELOPE_H +#define HEADER_ENVELOPE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef NO_MD2 +#include +#endif +#ifndef NO_MD5 +#include +#endif +#ifndef NO_SHA +#include +#endif +#ifndef NO_RIPEMD +#include +#endif +#ifndef NO_DES +#include +#endif +#ifndef NO_RC4 +#include +#endif +#ifndef NO_RC2 +#include +#endif +#ifndef NO_RC5 +#include +#endif +#ifndef NO_BF +#include +#endif +#ifndef NO_CAST +#include +#endif +#ifndef NO_IDEA +#include +#endif +#ifndef NO_MDC2 +#include +#endif + +#define EVP_RC2_KEY_SIZE 16 +#define EVP_RC4_KEY_SIZE 16 +#define EVP_BLOWFISH_KEY_SIZE 16 +#define EVP_CAST5_KEY_SIZE 16 +#define EVP_RC5_32_12_16_KEY_SIZE 16 +#define EVP_MAX_MD_SIZE (16+20) /* The SSLv3 md5+sha1 type */ +#define EVP_MAX_KEY_LENGTH 24 +#define EVP_MAX_IV_LENGTH 8 + +#define PKCS5_SALT_LEN 8 +/* Default PKCS#5 iteration count */ +#define PKCS5_DEFAULT_ITER 2048 + +#ifndef NO_RSA +#include +#endif + +#ifndef NO_DSA +#include +#endif + +#ifndef NO_DH +#include +#endif + +#include + +#define EVP_PK_RSA 0x0001 +#define EVP_PK_DSA 0x0002 +#define EVP_PK_DH 0x0004 +#define EVP_PKT_SIGN 0x0010 +#define EVP_PKT_ENC 0x0020 +#define EVP_PKT_EXCH 0x0040 +#define EVP_PKS_RSA 0x0100 +#define EVP_PKS_DSA 0x0200 +#define EVP_PKT_EXP 0x1000 /* <= 512 bit key */ + +#define EVP_PKEY_NONE NID_undef +#define EVP_PKEY_RSA NID_rsaEncryption +#define EVP_PKEY_RSA2 NID_rsa +#define EVP_PKEY_DSA NID_dsa +#define EVP_PKEY_DSA1 NID_dsa_2 +#define EVP_PKEY_DSA2 NID_dsaWithSHA +#define EVP_PKEY_DSA3 NID_dsaWithSHA1 +#define EVP_PKEY_DSA4 NID_dsaWithSHA1_2 +#define EVP_PKEY_DH NID_dhKeyAgreement + +/* Type needs to be a bit field + * Sub-type needs to be for variations on the method, as in, can it do + * arbitrary encryption.... */ +typedef struct evp_pkey_st + { + int type; + int save_type; + int references; + union { + char *ptr; +#ifndef NO_RSA + struct rsa_st *rsa; /* RSA */ +#endif +#ifndef NO_DSA + struct dsa_st *dsa; /* DSA */ +#endif +#ifndef NO_DH + struct dh_st *dh; /* DH */ +#endif + } pkey; + int save_parameters; + STACK /*X509_ATTRIBUTE*/ *attributes; /* [ 0 ] */ + } EVP_PKEY; + +#define EVP_PKEY_MO_SIGN 0x0001 +#define EVP_PKEY_MO_VERIFY 0x0002 +#define EVP_PKEY_MO_ENCRYPT 0x0004 +#define EVP_PKEY_MO_DECRYPT 0x0008 + +#if 0 +/* This structure is required to tie the message digest and signing together. + * The lookup can be done by md/pkey_method, oid, oid/pkey_method, or + * oid, md and pkey. + * This is required because for various smart-card perform the digest and + * signing/verification on-board. To handle this case, the specific + * EVP_MD and EVP_PKEY_METHODs need to be closely associated. + * When a PKEY is created, it will have a EVP_PKEY_METHOD associated with it. + * This can either be software or a token to provide the required low level + * routines. + */ +typedef struct evp_pkey_md_st + { + int oid; + EVP_MD *md; + EVP_PKEY_METHOD *pkey; + } EVP_PKEY_MD; + +#define EVP_rsa_md2() \ + EVP_PKEY_MD_add(NID_md2WithRSAEncryption,\ + EVP_rsa_pkcs1(),EVP_md2()) +#define EVP_rsa_md5() \ + EVP_PKEY_MD_add(NID_md5WithRSAEncryption,\ + EVP_rsa_pkcs1(),EVP_md5()) +#define EVP_rsa_sha0() \ + EVP_PKEY_MD_add(NID_shaWithRSAEncryption,\ + EVP_rsa_pkcs1(),EVP_sha()) +#define EVP_rsa_sha1() \ + EVP_PKEY_MD_add(NID_sha1WithRSAEncryption,\ + EVP_rsa_pkcs1(),EVP_sha1()) +#define EVP_rsa_ripemd160() \ + EVP_PKEY_MD_add(NID_ripemd160WithRSA,\ + EVP_rsa_pkcs1(),EVP_ripemd160()) +#define EVP_rsa_mdc2() \ + EVP_PKEY_MD_add(NID_mdc2WithRSA,\ + EVP_rsa_octet_string(),EVP_mdc2()) +#define EVP_dsa_sha() \ + EVP_PKEY_MD_add(NID_dsaWithSHA,\ + EVP_dsa(),EVP_mdc2()) +#define EVP_dsa_sha1() \ + EVP_PKEY_MD_add(NID_dsaWithSHA1,\ + EVP_dsa(),EVP_sha1()) + +typedef struct evp_pkey_method_st + { + char *name; + int flags; + int type; /* RSA, DSA, an SSLeay specific constant */ + int oid; /* For the pub-key type */ + int encrypt_oid; /* pub/priv key encryption */ + + int (*sign)(); + int (*verify)(); + struct { + int + int (*set)(); /* get and/or set the underlying type */ + int (*get)(); + int (*encrypt)(); + int (*decrypt)(); + int (*i2d)(); + int (*d2i)(); + int (*dup)(); + } pub,priv; + int (*set_asn1_parameters)(); + int (*get_asn1_parameters)(); + } EVP_PKEY_METHOD; +#endif + +#ifndef EVP_MD +typedef struct env_md_st + { + int type; + int pkey_type; + int md_size; + void (*init)(); + void (*update)(); + void (*final)(); + + int (*sign)(); + int (*verify)(); + int required_pkey_type[5]; /*EVP_PKEY_xxx */ + int block_size; + int ctx_size; /* how big does the ctx need to be */ + } EVP_MD; + + + +#define EVP_PKEY_NULL_method NULL,NULL,{0,0,0,0} + +#ifndef NO_DSA +#define EVP_PKEY_DSA_method DSA_sign,DSA_verify, \ + {EVP_PKEY_DSA,EVP_PKEY_DSA2,EVP_PKEY_DSA3, \ + EVP_PKEY_DSA4,0} +#else +#define EVP_PKEY_DSA_method EVP_PKEY_NULL_method +#endif + +#ifndef NO_RSA +#define EVP_PKEY_RSA_method RSA_sign,RSA_verify, \ + {EVP_PKEY_RSA,EVP_PKEY_RSA2,0,0} +#define EVP_PKEY_RSA_ASN1_OCTET_STRING_method \ + RSA_sign_ASN1_OCTET_STRING, \ + RSA_verify_ASN1_OCTET_STRING, \ + {EVP_PKEY_RSA,EVP_PKEY_RSA2,0,0} +#else +#define EVP_PKEY_RSA_method EVP_PKEY_NULL_method +#define EVP_PKEY_RSA_ASN1_OCTET_STRING_method EVP_PKEY_NULL_method +#endif + +#endif /* !EVP_MD */ + +typedef struct env_md_ctx_st + { + const EVP_MD *digest; + union { + unsigned char base[4]; +#ifndef NO_MD2 + MD2_CTX md2; +#endif +#ifndef NO_MD5 + MD5_CTX md5; +#endif +#ifndef NO_RIPEMD + RIPEMD160_CTX ripemd160; +#endif +#ifndef NO_SHA + SHA_CTX sha; +#endif +#ifndef NO_MDC2 + MDC2_CTX mdc2; +#endif + } md; + } EVP_MD_CTX; + +typedef struct evp_cipher_st + { + int nid; + int block_size; + int key_len; + int iv_len; + void (*init)(); /* init for encryption */ + void (*do_cipher)(); /* encrypt data */ + void (*cleanup)(); /* used by cipher method */ + int ctx_size; /* how big the ctx needs to be */ + /* int set_asn1_parameters(EVP_CIPHER_CTX,ASN1_TYPE *); */ + int (*set_asn1_parameters)(); /* Populate a ASN1_TYPE with parameters */ + /* int get_asn1_parameters(EVP_CIPHER_CTX,ASN1_TYPE *); */ + int (*get_asn1_parameters)(); /* Get parameters from a ASN1_TYPE */ + } EVP_CIPHER; + +typedef struct evp_cipher_info_st + { + const EVP_CIPHER *cipher; + unsigned char iv[EVP_MAX_IV_LENGTH]; + } EVP_CIPHER_INFO; + +typedef struct evp_cipher_ctx_st + { + const EVP_CIPHER *cipher; + int encrypt; /* encrypt or decrypt */ + int buf_len; /* number we have left */ + + unsigned char oiv[EVP_MAX_IV_LENGTH]; /* original iv */ + unsigned char iv[EVP_MAX_IV_LENGTH]; /* working iv */ + unsigned char buf[EVP_MAX_IV_LENGTH]; /* saved partial block */ + int num; /* used by cfb/ofb mode */ + + char *app_data; /* application stuff */ + union { +#ifndef NO_RC4 + struct + { + unsigned char key[EVP_RC4_KEY_SIZE]; + RC4_KEY ks; /* working key */ + } rc4; +#endif +#ifndef NO_DES + des_key_schedule des_ks;/* key schedule */ + struct + { + des_key_schedule ks;/* key schedule */ + des_cblock inw; + des_cblock outw; + } desx_cbc; + struct + { + des_key_schedule ks1;/* key schedule */ + des_key_schedule ks2;/* key schedule (for ede) */ + des_key_schedule ks3;/* key schedule (for ede3) */ + } des_ede; +#endif +#ifndef NO_IDEA + IDEA_KEY_SCHEDULE idea_ks;/* key schedule */ +#endif +#ifndef NO_RC2 + RC2_KEY rc2_ks;/* key schedule */ +#endif +#ifndef NO_RC5 + RC5_32_KEY rc5_ks;/* key schedule */ +#endif +#ifndef NO_BF + BF_KEY bf_ks;/* key schedule */ +#endif +#ifndef NO_CAST + CAST_KEY cast_ks;/* key schedule */ +#endif + } c; + } EVP_CIPHER_CTX; + +typedef struct evp_Encode_Ctx_st + { + int num; /* number saved in a partial encode/decode */ + int length; /* The length is either the output line length + * (in input bytes) or the shortest input line + * length that is ok. Once decoding begins, + * the length is adjusted up each time a longer + * line is decoded */ + unsigned char enc_data[80]; /* data to encode */ + int line_num; /* number read on current line */ + int expect_nl; + } EVP_ENCODE_CTX; + +/* Password based encryption function */ +typedef int (EVP_PBE_KEYGEN)(EVP_CIPHER_CTX *ctx, const char *pass, int passlen, + ASN1_TYPE *param, EVP_CIPHER *cipher, + EVP_MD *md, int en_de); + +#define EVP_PKEY_assign_RSA(pkey,rsa) EVP_PKEY_assign((pkey),EVP_PKEY_RSA,\ + (char *)(rsa)) +#define EVP_PKEY_assign_DSA(pkey,dsa) EVP_PKEY_assign((pkey),EVP_PKEY_DSA,\ + (char *)(dsa)) +#define EVP_PKEY_assign_DH(pkey,dh) EVP_PKEY_assign((pkey),EVP_PKEY_DH,\ + (char *)(dh)) + +/* Add some extra combinations */ +#define EVP_get_digestbynid(a) EVP_get_digestbyname(OBJ_nid2sn(a)) +#define EVP_get_digestbyobj(a) EVP_get_digestbynid(OBJ_obj2nid(a)) +#define EVP_get_cipherbynid(a) EVP_get_cipherbyname(OBJ_nid2sn(a)) +#define EVP_get_cipherbyobj(a) EVP_get_cipherbynid(OBJ_obj2nid(a)) + +#define EVP_MD_type(e) ((e)->type) +#define EVP_MD_pkey_type(e) ((e)->pkey_type) +#define EVP_MD_size(e) ((e)->md_size) +#define EVP_MD_block_size(e) ((e)->block_size) + +#define EVP_MD_CTX_md(e) ((e)->digest) +#define EVP_MD_CTX_size(e) EVP_MD_size((e)->digest) +#define EVP_MD_CTX_block_size(e) EVP_MD_block_size((e)->digest) +#define EVP_MD_CTX_type(e) EVP_MD_type((e)->digest) + +#define EVP_CIPHER_nid(e) ((e)->nid) +#define EVP_CIPHER_block_size(e) ((e)->block_size) +#define EVP_CIPHER_key_length(e) ((e)->key_len) +#define EVP_CIPHER_iv_length(e) ((e)->iv_len) + +#define EVP_CIPHER_CTX_cipher(e) ((e)->cipher) +#define EVP_CIPHER_CTX_nid(e) ((e)->cipher->nid) +#define EVP_CIPHER_CTX_block_size(e) ((e)->cipher->block_size) +#define EVP_CIPHER_CTX_key_length(e) ((e)->cipher->key_len) +#define EVP_CIPHER_CTX_iv_length(e) ((e)->cipher->iv_len) +#define EVP_CIPHER_CTX_get_app_data(e) ((e)->app_data) +#define EVP_CIPHER_CTX_set_app_data(e,d) ((e)->app_data=(char *)(d)) +#define EVP_CIPHER_CTX_type(c) EVP_CIPHER_type(EVP_CIPHER_CTX_cipher(c)) + +#define EVP_ENCODE_LENGTH(l) (((l+2)/3*4)+(l/48+1)*2+80) +#define EVP_DECODE_LENGTH(l) ((l+3)/4*3+80) + +#define EVP_SignInit(a,b) EVP_DigestInit(a,b) +#define EVP_SignUpdate(a,b,c) EVP_DigestUpdate(a,b,c) +#define EVP_VerifyInit(a,b) EVP_DigestInit(a,b) +#define EVP_VerifyUpdate(a,b,c) EVP_DigestUpdate(a,b,c) +#define EVP_OpenUpdate(a,b,c,d,e) EVP_DecryptUpdate(a,b,c,d,e) +#define EVP_SealUpdate(a,b,c,d,e) EVP_EncryptUpdate(a,b,c,d,e) + +#ifdef CONST_STRICT +void BIO_set_md(BIO *,const EVP_MD *md); +#else +# define BIO_set_md(b,md) BIO_ctrl(b,BIO_C_SET_MD,0,(char *)md) +#endif +#define BIO_get_md(b,mdp) BIO_ctrl(b,BIO_C_GET_MD,0,(char *)mdp) +#define BIO_get_md_ctx(b,mdcp) BIO_ctrl(b,BIO_C_GET_MD_CTX,0,(char *)mdcp) +#define BIO_get_cipher_status(b) BIO_ctrl(b,BIO_C_GET_CIPHER_STATUS,0,NULL) +#define BIO_get_cipher_ctx(b,c_pp) BIO_ctrl(b,BIO_C_GET_CIPHER_CTX,0,(char *)c_pp) + +#define EVP_Cipher(c,o,i,l) (c)->cipher->do_cipher((c),(o),(i),(l)) + +#define EVP_add_cipher_alias(n,alias) \ + OBJ_NAME_add((alias),OBJ_NAME_TYPE_CIPHER_METH|OBJ_NAME_ALIAS,(n)) +#define EVP_add_digest_alias(n,alias) \ + OBJ_NAME_add((alias),OBJ_NAME_TYPE_MD_METH|OBJ_NAME_ALIAS,(n)) +#define EVP_delete_cipher_alias(alias) \ + OBJ_NAME_remove(alias,OBJ_NAME_TYPE_CIPHER_METH|OBJ_NAME_ALIAS); +#define EVP_delete_digest_alias(alias) \ + OBJ_NAME_remove(alias,OBJ_NAME_TYPE_MD_METH|OBJ_NAME_ALIAS); + + +int EVP_MD_CTX_copy(EVP_MD_CTX *out,EVP_MD_CTX *in); +void EVP_DigestInit(EVP_MD_CTX *ctx, const EVP_MD *type); +void EVP_DigestUpdate(EVP_MD_CTX *ctx,const void *d, + unsigned int cnt); +void EVP_DigestFinal(EVP_MD_CTX *ctx,unsigned char *md,unsigned int *s); + +int EVP_read_pw_string(char *buf,int length,const char *prompt,int verify); +void EVP_set_pw_prompt(char *prompt); +char * EVP_get_pw_prompt(void); + +int EVP_BytesToKey(const EVP_CIPHER *type,EVP_MD *md,unsigned char *salt, + unsigned char *data, int datal, int count, + unsigned char *key,unsigned char *iv); + +void EVP_EncryptInit(EVP_CIPHER_CTX *ctx,const EVP_CIPHER *type, + unsigned char *key, unsigned char *iv); +void EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, + int *outl, unsigned char *in, int inl); +void EVP_EncryptFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl); + +void EVP_DecryptInit(EVP_CIPHER_CTX *ctx,const EVP_CIPHER *type, + unsigned char *key, unsigned char *iv); +void EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, + int *outl, unsigned char *in, int inl); +int EVP_DecryptFinal(EVP_CIPHER_CTX *ctx, unsigned char *outm, int *outl); + +void EVP_CipherInit(EVP_CIPHER_CTX *ctx,const EVP_CIPHER *type, + unsigned char *key,unsigned char *iv,int enc); +void EVP_CipherUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, + int *outl, unsigned char *in, int inl); +int EVP_CipherFinal(EVP_CIPHER_CTX *ctx, unsigned char *outm, int *outl); + +int EVP_SignFinal(EVP_MD_CTX *ctx,unsigned char *md,unsigned int *s, + EVP_PKEY *pkey); + +int EVP_VerifyFinal(EVP_MD_CTX *ctx,unsigned char *sigbuf, + unsigned int siglen,EVP_PKEY *pkey); + +int EVP_OpenInit(EVP_CIPHER_CTX *ctx,EVP_CIPHER *type,unsigned char *ek, + int ekl,unsigned char *iv,EVP_PKEY *priv); +int EVP_OpenFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl); + +int EVP_SealInit(EVP_CIPHER_CTX *ctx, EVP_CIPHER *type, unsigned char **ek, + int *ekl, unsigned char *iv,EVP_PKEY **pubk, int npubk); +void EVP_SealFinal(EVP_CIPHER_CTX *ctx,unsigned char *out,int *outl); + +void EVP_EncodeInit(EVP_ENCODE_CTX *ctx); +void EVP_EncodeUpdate(EVP_ENCODE_CTX *ctx,unsigned char *out, + int *outl,unsigned char *in,int inl); +void EVP_EncodeFinal(EVP_ENCODE_CTX *ctx,unsigned char *out,int *outl); +int EVP_EncodeBlock(unsigned char *t, const unsigned char *f, int n); + +void EVP_DecodeInit(EVP_ENCODE_CTX *ctx); +int EVP_DecodeUpdate(EVP_ENCODE_CTX *ctx,unsigned char *out,int *outl, + unsigned char *in, int inl); +int EVP_DecodeFinal(EVP_ENCODE_CTX *ctx, unsigned + char *out, int *outl); +int EVP_DecodeBlock(unsigned char *t, const unsigned char *f, int n); + +void ERR_load_EVP_strings(void ); + +void EVP_CIPHER_CTX_init(EVP_CIPHER_CTX *a); +void EVP_CIPHER_CTX_cleanup(EVP_CIPHER_CTX *a); + +#ifdef HEADER_BIO_H +BIO_METHOD *BIO_f_md(void); +BIO_METHOD *BIO_f_base64(void); +BIO_METHOD *BIO_f_cipher(void); +BIO_METHOD *BIO_f_reliable(void); +void BIO_set_cipher(BIO *b,const EVP_CIPHER *c,unsigned char *k, + unsigned char *i, int enc); +#endif + +EVP_MD *EVP_md_null(void); +EVP_MD *EVP_md2(void); +EVP_MD *EVP_md5(void); +EVP_MD *EVP_sha(void); +EVP_MD *EVP_sha1(void); +EVP_MD *EVP_dss(void); +EVP_MD *EVP_dss1(void); +EVP_MD *EVP_mdc2(void); +EVP_MD *EVP_ripemd160(void); + +EVP_CIPHER *EVP_enc_null(void); /* does nothing :-) */ +EVP_CIPHER *EVP_des_ecb(void); +EVP_CIPHER *EVP_des_ede(void); +EVP_CIPHER *EVP_des_ede3(void); +EVP_CIPHER *EVP_des_cfb(void); +EVP_CIPHER *EVP_des_ede_cfb(void); +EVP_CIPHER *EVP_des_ede3_cfb(void); +EVP_CIPHER *EVP_des_ofb(void); +EVP_CIPHER *EVP_des_ede_ofb(void); +EVP_CIPHER *EVP_des_ede3_ofb(void); +EVP_CIPHER *EVP_des_cbc(void); +EVP_CIPHER *EVP_des_ede_cbc(void); +EVP_CIPHER *EVP_des_ede3_cbc(void); +EVP_CIPHER *EVP_desx_cbc(void); +EVP_CIPHER *EVP_rc4(void); +EVP_CIPHER *EVP_rc4_40(void); +EVP_CIPHER *EVP_idea_ecb(void); +EVP_CIPHER *EVP_idea_cfb(void); +EVP_CIPHER *EVP_idea_ofb(void); +EVP_CIPHER *EVP_idea_cbc(void); +EVP_CIPHER *EVP_rc2_ecb(void); +EVP_CIPHER *EVP_rc2_cbc(void); +EVP_CIPHER *EVP_rc2_40_cbc(void); +EVP_CIPHER *EVP_rc2_64_cbc(void); +EVP_CIPHER *EVP_rc2_cfb(void); +EVP_CIPHER *EVP_rc2_ofb(void); +EVP_CIPHER *EVP_bf_ecb(void); +EVP_CIPHER *EVP_bf_cbc(void); +EVP_CIPHER *EVP_bf_cfb(void); +EVP_CIPHER *EVP_bf_ofb(void); +EVP_CIPHER *EVP_cast5_ecb(void); +EVP_CIPHER *EVP_cast5_cbc(void); +EVP_CIPHER *EVP_cast5_cfb(void); +EVP_CIPHER *EVP_cast5_ofb(void); +EVP_CIPHER *EVP_rc5_32_12_16_cbc(void); +EVP_CIPHER *EVP_rc5_32_12_16_ecb(void); +EVP_CIPHER *EVP_rc5_32_12_16_cfb(void); +EVP_CIPHER *EVP_rc5_32_12_16_ofb(void); + +void OpenSSL_add_all_algorithms(void); +void OpenSSL_add_all_ciphers(void); +void OpenSSL_add_all_digests(void); +#define SSLeay_add_all_algorithms() OpenSSL_add_all_algorithms() +#define SSLeay_add_all_ciphers() OpenSSL_add_all_ciphers() +#define SSLeay_add_all_digests() OpenSSL_add_all_digests() + +int EVP_add_cipher(EVP_CIPHER *cipher); +int EVP_add_digest(EVP_MD *digest); + +const EVP_CIPHER *EVP_get_cipherbyname(const char *name); +const EVP_MD *EVP_get_digestbyname(const char *name); +void EVP_cleanup(void); + +int EVP_PKEY_decrypt(unsigned char *dec_key,unsigned char *enc_key, + int enc_key_len,EVP_PKEY *private_key); +int EVP_PKEY_encrypt(unsigned char *enc_key, + unsigned char *key,int key_len,EVP_PKEY *pub_key); +int EVP_PKEY_type(int type); +int EVP_PKEY_bits(EVP_PKEY *pkey); +int EVP_PKEY_size(EVP_PKEY *pkey); +int EVP_PKEY_assign(EVP_PKEY *pkey,int type,char *key); +#ifndef NO_RSA +int EVP_PKEY_set1_RSA(EVP_PKEY *pkey,RSA *key); +RSA * EVP_PKEY_get1_RSA(EVP_PKEY *pkey); +#endif +#ifndef NO_DSA +int EVP_PKEY_set1_DSA(EVP_PKEY *pkey,DSA *key); +DSA * EVP_PKEY_get1_DSA(EVP_PKEY *pkey); +#endif +#ifndef NO_DH +int EVP_PKEY_set1_DH(EVP_PKEY *pkey,DH *key); +DH * EVP_PKEY_get1_DH(EVP_PKEY *pkey); +#endif +EVP_PKEY * EVP_PKEY_new(void); +void EVP_PKEY_free(EVP_PKEY *pkey); +EVP_PKEY * d2i_PublicKey(int type,EVP_PKEY **a, unsigned char **pp, + long length); +int i2d_PublicKey(EVP_PKEY *a, unsigned char **pp); + +EVP_PKEY * d2i_PrivateKey(int type,EVP_PKEY **a, unsigned char **pp, + long length); +EVP_PKEY * d2i_AutoPrivateKey(EVP_PKEY **a, unsigned char **pp, + long length); +int i2d_PrivateKey(EVP_PKEY *a, unsigned char **pp); + +int EVP_PKEY_copy_parameters(EVP_PKEY *to,EVP_PKEY *from); +int EVP_PKEY_missing_parameters(EVP_PKEY *pkey); +int EVP_PKEY_save_parameters(EVP_PKEY *pkey,int mode); +int EVP_PKEY_cmp_parameters(EVP_PKEY *a,EVP_PKEY *b); + +int EVP_CIPHER_type(const EVP_CIPHER *ctx); + +/* calls methods */ +int EVP_CIPHER_param_to_asn1(EVP_CIPHER_CTX *c, ASN1_TYPE *type); +int EVP_CIPHER_asn1_to_param(EVP_CIPHER_CTX *c, ASN1_TYPE *type); + +/* These are used by EVP_CIPHER methods */ +int EVP_CIPHER_set_asn1_iv(EVP_CIPHER_CTX *c,ASN1_TYPE *type); +int EVP_CIPHER_get_asn1_iv(EVP_CIPHER_CTX *c,ASN1_TYPE *type); + +/* PKCS5 password based encryption */ +int PKCS5_PBE_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen, + ASN1_TYPE *param, EVP_CIPHER *cipher, EVP_MD *md, + int en_de); +int PKCS5_PBKDF2_HMAC_SHA1(const char *pass, int passlen, + unsigned char *salt, int saltlen, int iter, + int keylen, unsigned char *out); +int PKCS5_v2_PBE_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen, + ASN1_TYPE *param, EVP_CIPHER *cipher, EVP_MD *md, + int en_de); + +void PKCS5_PBE_add(void); + +int EVP_PBE_CipherInit (ASN1_OBJECT *pbe_obj, const char *pass, int passlen, + ASN1_TYPE *param, EVP_CIPHER_CTX *ctx, int en_de); +int EVP_PBE_alg_add(int nid, EVP_CIPHER *cipher, EVP_MD *md, + EVP_PBE_KEYGEN *keygen); +void EVP_PBE_cleanup(void); + +/* BEGIN ERROR CODES */ +/* The following lines are auto generated by the script mkerr.pl. Any changes + * made after this point may be overwritten when the script is next run. + */ + +/* Error codes for the EVP functions. */ + +/* Function codes. */ +#define EVP_F_D2I_PKEY 100 +#define EVP_F_EVP_DECRYPTFINAL 101 +#define EVP_F_EVP_MD_CTX_COPY 110 +#define EVP_F_EVP_OPENINIT 102 +#define EVP_F_EVP_PBE_ALG_ADD 115 +#define EVP_F_EVP_PBE_CIPHERINIT 116 +#define EVP_F_EVP_PKCS82PKEY 111 +#define EVP_F_EVP_PKCS8_SET_BROKEN 112 +#define EVP_F_EVP_PKEY2PKCS8 113 +#define EVP_F_EVP_PKEY_COPY_PARAMETERS 103 +#define EVP_F_EVP_PKEY_DECRYPT 104 +#define EVP_F_EVP_PKEY_ENCRYPT 105 +#define EVP_F_EVP_PKEY_GET1_DH 119 +#define EVP_F_EVP_PKEY_GET1_DSA 120 +#define EVP_F_EVP_PKEY_GET1_RSA 121 +#define EVP_F_EVP_PKEY_NEW 106 +#define EVP_F_EVP_SIGNFINAL 107 +#define EVP_F_EVP_VERIFYFINAL 108 +#define EVP_F_PKCS5_PBE_KEYIVGEN 117 +#define EVP_F_PKCS5_V2_PBE_KEYIVGEN 118 +#define EVP_F_RC2_MAGIC_TO_METH 109 + +/* Reason codes. */ +#define EVP_R_BAD_DECRYPT 100 +#define EVP_R_BN_DECODE_ERROR 112 +#define EVP_R_BN_PUBKEY_ERROR 113 +#define EVP_R_CIPHER_PARAMETER_ERROR 122 +#define EVP_R_DECODE_ERROR 114 +#define EVP_R_DIFFERENT_KEY_TYPES 101 +#define EVP_R_ENCODE_ERROR 115 +#define EVP_R_EVP_PBE_CIPHERINIT_ERROR 119 +#define EVP_R_EXPECTING_AN_RSA_KEY 127 +#define EVP_R_EXPECTING_A_DH_KEY 128 +#define EVP_R_EXPECTING_A_DSA_KEY 129 +#define EVP_R_INPUT_NOT_INITIALIZED 111 +#define EVP_R_IV_TOO_LARGE 102 +#define EVP_R_KEYGEN_FAILURE 120 +#define EVP_R_MISSING_PARAMETERS 103 +#define EVP_R_NO_DSA_PARAMETERS 116 +#define EVP_R_NO_SIGN_FUNCTION_CONFIGURED 104 +#define EVP_R_NO_VERIFY_FUNCTION_CONFIGURED 105 +#define EVP_R_PKCS8_UNKNOWN_BROKEN_TYPE 117 +#define EVP_R_PUBLIC_KEY_NOT_RSA 106 +#define EVP_R_UNKNOWN_PBE_ALGORITHM 121 +#define EVP_R_UNSUPPORTED_CIPHER 107 +#define EVP_R_UNSUPPORTED_KEYLENGTH 123 +#define EVP_R_UNSUPPORTED_KEY_DERIVATION_FUNCTION 124 +#define EVP_R_UNSUPPORTED_KEY_SIZE 108 +#define EVP_R_UNSUPPORTED_PRF 125 +#define EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM 118 +#define EVP_R_UNSUPPORTED_SALT_TYPE 126 +#define EVP_R_WRONG_FINAL_BLOCK_LENGTH 109 +#define EVP_R_WRONG_PUBLIC_KEY_TYPE 110 + +#ifdef __cplusplus +} +#endif +#endif + diff --git a/libsecurity_apple_csp/open_ssl/openssl/lhash.h b/libsecurity_apple_csp/open_ssl/openssl/lhash.h new file mode 100644 index 00000000..748d47b5 --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/openssl/lhash.h @@ -0,0 +1,163 @@ +/* + * 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. + */ + + +/* crypto/lhash/lhash.h */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +/* Header for dynamic hash table routines + * Author - Eric Young + */ + +#ifndef HEADER_LHASH_H +#define HEADER_LHASH_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef NO_FP_API +#include +#endif + +typedef struct lhash_node_st + { + void *data; + struct lhash_node_st *next; +#ifndef NO_HASH_COMP + unsigned long hash; +#endif + } LHASH_NODE; + +typedef struct lhash_st + { + LHASH_NODE **b; + int (*comp)(); + unsigned long (*hash)(); + unsigned int num_nodes; + unsigned int num_alloc_nodes; + unsigned int p; + unsigned int pmax; + unsigned long up_load; /* load times 256 */ + unsigned long down_load; /* load times 256 */ + unsigned long num_items; + + unsigned long num_expands; + unsigned long num_expand_reallocs; + unsigned long num_contracts; + unsigned long num_contract_reallocs; + unsigned long num_hash_calls; + unsigned long num_comp_calls; + unsigned long num_insert; + unsigned long num_replace; + unsigned long num_delete; + unsigned long num_no_delete; + unsigned long num_retrieve; + unsigned long num_retrieve_miss; + unsigned long num_hash_comps; + + int error; + } LHASH; + +#define LH_LOAD_MULT 256 + +/* Indicates a malloc() error in the last call, this is only bad + * in lh_insert(). */ +#define lh_error(lh) ((lh)->error) + +LHASH *lh_new(unsigned long (*h)(/* void *a */), int (*c)(/* void *a,void *b */)); +void lh_free(LHASH *lh); +void *lh_insert(LHASH *lh, void *data); +void *lh_delete(LHASH *lh, void *data); +void *lh_retrieve(LHASH *lh, void *data); + void lh_doall(LHASH *lh, void (*func)(/*void *b*/)); +void lh_doall_arg(LHASH *lh, void (*func)(/*void *a,void *b*/),void *arg); +unsigned long lh_strhash(const char *c); +unsigned long lh_num_items(LHASH *lh); + +#ifndef NO_FP_API +void lh_stats(LHASH *lh, FILE *out); +void lh_node_stats(LHASH *lh, FILE *out); +void lh_node_usage_stats(LHASH *lh, FILE *out); +#endif + +#ifdef HEADER_BIO_H +void lh_stats_bio(LHASH *lh, BIO *out); +void lh_node_stats_bio(LHASH *lh, BIO *out); +void lh_node_usage_stats_bio(LHASH *lh, BIO *out); +#endif +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/libsecurity_apple_csp/open_ssl/openssl/objects.h b/libsecurity_apple_csp/open_ssl/openssl/objects.h new file mode 100644 index 00000000..d65f8cf9 --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/openssl/objects.h @@ -0,0 +1,1050 @@ +/* + * 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. + */ + + +/* crypto/objects/objects.h */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef HEADER_OBJECTS_H +#define HEADER_OBJECTS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define SN_undef "UNDEF" +#define LN_undef "undefined" +#define NID_undef 0 +#define OBJ_undef 0L + +#define SN_Algorithm "Algorithm" +#define LN_algorithm "algorithm" +#define NID_algorithm 38 +#define OBJ_algorithm 1L,3L,14L,3L,2L + +#define LN_rsadsi "rsadsi" +#define NID_rsadsi 1 +#define OBJ_rsadsi 1L,2L,840L,113549L + +#define LN_pkcs "pkcs" +#define NID_pkcs 2 +#define OBJ_pkcs OBJ_rsadsi,1L + +#define SN_md2 "MD2" +#define LN_md2 "md2" +#define NID_md2 3 +#define OBJ_md2 OBJ_rsadsi,2L,2L + +#define SN_md5 "MD5" +#define LN_md5 "md5" +#define NID_md5 4 +#define OBJ_md5 OBJ_rsadsi,2L,5L + +#define SN_rc4 "RC4" +#define LN_rc4 "rc4" +#define NID_rc4 5 +#define OBJ_rc4 OBJ_rsadsi,3L,4L + +#define LN_rsaEncryption "rsaEncryption" +#define NID_rsaEncryption 6 +#define OBJ_rsaEncryption OBJ_pkcs,1L,1L + +#define SN_md2WithRSAEncryption "RSA-MD2" +#define LN_md2WithRSAEncryption "md2WithRSAEncryption" +#define NID_md2WithRSAEncryption 7 +#define OBJ_md2WithRSAEncryption OBJ_pkcs,1L,2L + +#define SN_md5WithRSAEncryption "RSA-MD5" +#define LN_md5WithRSAEncryption "md5WithRSAEncryption" +#define NID_md5WithRSAEncryption 8 +#define OBJ_md5WithRSAEncryption OBJ_pkcs,1L,4L + +#define SN_pbeWithMD2AndDES_CBC "PBE-MD2-DES" +#define LN_pbeWithMD2AndDES_CBC "pbeWithMD2AndDES-CBC" +#define NID_pbeWithMD2AndDES_CBC 9 +#define OBJ_pbeWithMD2AndDES_CBC OBJ_pkcs,5L,1L + +#define SN_pbeWithMD5AndDES_CBC "PBE-MD5-DES" +#define LN_pbeWithMD5AndDES_CBC "pbeWithMD5AndDES-CBC" +#define NID_pbeWithMD5AndDES_CBC 10 +#define OBJ_pbeWithMD5AndDES_CBC OBJ_pkcs,5L,3L + +#define LN_X500 "X500" +#define NID_X500 11 +#define OBJ_X500 2L,5L + +#define LN_X509 "X509" +#define NID_X509 12 +#define OBJ_X509 OBJ_X500,4L + +#define SN_commonName "CN" +#define LN_commonName "commonName" +#define NID_commonName 13 +#define OBJ_commonName OBJ_X509,3L + +#define SN_countryName "C" +#define LN_countryName "countryName" +#define NID_countryName 14 +#define OBJ_countryName OBJ_X509,6L + +#define SN_localityName "L" +#define LN_localityName "localityName" +#define NID_localityName 15 +#define OBJ_localityName OBJ_X509,7L + +/* Postal Address? PA */ + +/* should be "ST" (rfc1327) but MS uses 'S' */ +#define SN_stateOrProvinceName "ST" +#define LN_stateOrProvinceName "stateOrProvinceName" +#define NID_stateOrProvinceName 16 +#define OBJ_stateOrProvinceName OBJ_X509,8L + +#define SN_organizationName "O" +#define LN_organizationName "organizationName" +#define NID_organizationName 17 +#define OBJ_organizationName OBJ_X509,10L + +#define SN_organizationalUnitName "OU" +#define LN_organizationalUnitName "organizationalUnitName" +#define NID_organizationalUnitName 18 +#define OBJ_organizationalUnitName OBJ_X509,11L + +#define SN_rsa "RSA" +#define LN_rsa "rsa" +#define NID_rsa 19 +#define OBJ_rsa OBJ_X500,8L,1L,1L + +#define LN_pkcs7 "pkcs7" +#define NID_pkcs7 20 +#define OBJ_pkcs7 OBJ_pkcs,7L + +#define LN_pkcs7_data "pkcs7-data" +#define NID_pkcs7_data 21 +#define OBJ_pkcs7_data OBJ_pkcs7,1L + +#define LN_pkcs7_signed "pkcs7-signedData" +#define NID_pkcs7_signed 22 +#define OBJ_pkcs7_signed OBJ_pkcs7,2L + +#define LN_pkcs7_enveloped "pkcs7-envelopedData" +#define NID_pkcs7_enveloped 23 +#define OBJ_pkcs7_enveloped OBJ_pkcs7,3L + +#define LN_pkcs7_signedAndEnveloped "pkcs7-signedAndEnvelopedData" +#define NID_pkcs7_signedAndEnveloped 24 +#define OBJ_pkcs7_signedAndEnveloped OBJ_pkcs7,4L + +#define LN_pkcs7_digest "pkcs7-digestData" +#define NID_pkcs7_digest 25 +#define OBJ_pkcs7_digest OBJ_pkcs7,5L + +#define LN_pkcs7_encrypted "pkcs7-encryptedData" +#define NID_pkcs7_encrypted 26 +#define OBJ_pkcs7_encrypted OBJ_pkcs7,6L + +#define LN_pkcs3 "pkcs3" +#define NID_pkcs3 27 +#define OBJ_pkcs3 OBJ_pkcs,3L + +#define LN_dhKeyAgreement "dhKeyAgreement" +#define NID_dhKeyAgreement 28 +#define OBJ_dhKeyAgreement OBJ_pkcs3,1L + +#define SN_des_ecb "DES-ECB" +#define LN_des_ecb "des-ecb" +#define NID_des_ecb 29 +#define OBJ_des_ecb OBJ_algorithm,6L + +#define SN_des_cfb64 "DES-CFB" +#define LN_des_cfb64 "des-cfb" +#define NID_des_cfb64 30 +/* IV + num */ +#define OBJ_des_cfb64 OBJ_algorithm,9L + +#define SN_des_cbc "DES-CBC" +#define LN_des_cbc "des-cbc" +#define NID_des_cbc 31 +/* IV */ +#define OBJ_des_cbc OBJ_algorithm,7L + +#define SN_des_ede "DES-EDE" +#define LN_des_ede "des-ede" +#define NID_des_ede 32 +/* ?? */ +#define OBJ_des_ede OBJ_algorithm,17L + +#define SN_des_ede3 "DES-EDE3" +#define LN_des_ede3 "des-ede3" +#define NID_des_ede3 33 + +#define SN_idea_cbc "IDEA-CBC" +#define LN_idea_cbc "idea-cbc" +#define NID_idea_cbc 34 +#define OBJ_idea_cbc 1L,3L,6L,1L,4L,1L,188L,7L,1L,1L,2L + +#define SN_idea_cfb64 "IDEA-CFB" +#define LN_idea_cfb64 "idea-cfb" +#define NID_idea_cfb64 35 + +#define SN_idea_ecb "IDEA-ECB" +#define LN_idea_ecb "idea-ecb" +#define NID_idea_ecb 36 + +#define SN_rc2_cbc "RC2-CBC" +#define LN_rc2_cbc "rc2-cbc" +#define NID_rc2_cbc 37 +#define OBJ_rc2_cbc OBJ_rsadsi,3L,2L + +#define SN_rc2_ecb "RC2-ECB" +#define LN_rc2_ecb "rc2-ecb" +#define NID_rc2_ecb 38 + +#define SN_rc2_cfb64 "RC2-CFB" +#define LN_rc2_cfb64 "rc2-cfb" +#define NID_rc2_cfb64 39 + +#define SN_rc2_ofb64 "RC2-OFB" +#define LN_rc2_ofb64 "rc2-ofb" +#define NID_rc2_ofb64 40 + +#define SN_sha "SHA" +#define LN_sha "sha" +#define NID_sha 41 +#define OBJ_sha OBJ_algorithm,18L + +#define SN_shaWithRSAEncryption "RSA-SHA" +#define LN_shaWithRSAEncryption "shaWithRSAEncryption" +#define NID_shaWithRSAEncryption 42 +#define OBJ_shaWithRSAEncryption OBJ_algorithm,15L + +#define SN_des_ede_cbc "DES-EDE-CBC" +#define LN_des_ede_cbc "des-ede-cbc" +#define NID_des_ede_cbc 43 + +#define SN_des_ede3_cbc "DES-EDE3-CBC" +#define LN_des_ede3_cbc "des-ede3-cbc" +#define NID_des_ede3_cbc 44 +#define OBJ_des_ede3_cbc OBJ_rsadsi,3L,7L + +#define SN_des_ofb64 "DES-OFB" +#define LN_des_ofb64 "des-ofb" +#define NID_des_ofb64 45 +#define OBJ_des_ofb64 OBJ_algorithm,8L + +#define SN_idea_ofb64 "IDEA-OFB" +#define LN_idea_ofb64 "idea-ofb" +#define NID_idea_ofb64 46 + +#define LN_pkcs9 "pkcs9" +#define NID_pkcs9 47 +#define OBJ_pkcs9 OBJ_pkcs,9L + +#define SN_pkcs9_emailAddress "Email" +#define LN_pkcs9_emailAddress "emailAddress" +#define NID_pkcs9_emailAddress 48 +#define OBJ_pkcs9_emailAddress OBJ_pkcs9,1L + +#define LN_pkcs9_unstructuredName "unstructuredName" +#define NID_pkcs9_unstructuredName 49 +#define OBJ_pkcs9_unstructuredName OBJ_pkcs9,2L + +#define LN_pkcs9_contentType "contentType" +#define NID_pkcs9_contentType 50 +#define OBJ_pkcs9_contentType OBJ_pkcs9,3L + +#define LN_pkcs9_messageDigest "messageDigest" +#define NID_pkcs9_messageDigest 51 +#define OBJ_pkcs9_messageDigest OBJ_pkcs9,4L + +#define LN_pkcs9_signingTime "signingTime" +#define NID_pkcs9_signingTime 52 +#define OBJ_pkcs9_signingTime OBJ_pkcs9,5L + +#define LN_pkcs9_countersignature "countersignature" +#define NID_pkcs9_countersignature 53 +#define OBJ_pkcs9_countersignature OBJ_pkcs9,6L + +#define LN_pkcs9_challengePassword "challengePassword" +#define NID_pkcs9_challengePassword 54 +#define OBJ_pkcs9_challengePassword OBJ_pkcs9,7L + +#define LN_pkcs9_unstructuredAddress "unstructuredAddress" +#define NID_pkcs9_unstructuredAddress 55 +#define OBJ_pkcs9_unstructuredAddress OBJ_pkcs9,8L + +#define LN_pkcs9_extCertAttributes "extendedCertificateAttributes" +#define NID_pkcs9_extCertAttributes 56 +#define OBJ_pkcs9_extCertAttributes OBJ_pkcs9,9L + +#define SN_netscape "Netscape" +#define LN_netscape "Netscape Communications Corp." +#define NID_netscape 57 +#define OBJ_netscape 2L,16L,840L,1L,113730L + +#define SN_netscape_cert_extension "nsCertExt" +#define LN_netscape_cert_extension "Netscape Certificate Extension" +#define NID_netscape_cert_extension 58 +#define OBJ_netscape_cert_extension OBJ_netscape,1L + +#define SN_netscape_data_type "nsDataType" +#define LN_netscape_data_type "Netscape Data Type" +#define NID_netscape_data_type 59 +#define OBJ_netscape_data_type OBJ_netscape,2L + +#define SN_des_ede_cfb64 "DES-EDE-CFB" +#define LN_des_ede_cfb64 "des-ede-cfb" +#define NID_des_ede_cfb64 60 + +#define SN_des_ede3_cfb64 "DES-EDE3-CFB" +#define LN_des_ede3_cfb64 "des-ede3-cfb" +#define NID_des_ede3_cfb64 61 + +#define SN_des_ede_ofb64 "DES-EDE-OFB" +#define LN_des_ede_ofb64 "des-ede-ofb" +#define NID_des_ede_ofb64 62 + +#define SN_des_ede3_ofb64 "DES-EDE3-OFB" +#define LN_des_ede3_ofb64 "des-ede3-ofb" +#define NID_des_ede3_ofb64 63 + +/* I'm not sure about the object ID */ +#define SN_sha1 "SHA1" +#define LN_sha1 "sha1" +#define NID_sha1 64 +#define OBJ_sha1 OBJ_algorithm,26L +/* 28 Jun 1996 - eay */ +/* #define OBJ_sha1 1L,3L,14L,2L,26L,05L <- wrong */ + +#define SN_sha1WithRSAEncryption "RSA-SHA1" +#define LN_sha1WithRSAEncryption "sha1WithRSAEncryption" +#define NID_sha1WithRSAEncryption 65 +#define OBJ_sha1WithRSAEncryption OBJ_pkcs,1L,5L + +#define SN_dsaWithSHA "DSA-SHA" +#define LN_dsaWithSHA "dsaWithSHA" +#define NID_dsaWithSHA 66 +#define OBJ_dsaWithSHA OBJ_algorithm,13L + +#define SN_dsa_2 "DSA-old" +#define LN_dsa_2 "dsaEncryption-old" +#define NID_dsa_2 67 +#define OBJ_dsa_2 OBJ_algorithm,12L + +/* proposed by microsoft to RSA */ +#define SN_pbeWithSHA1AndRC2_CBC "PBE-SHA1-RC2-64" +#define LN_pbeWithSHA1AndRC2_CBC "pbeWithSHA1AndRC2-CBC" +#define NID_pbeWithSHA1AndRC2_CBC 68 +#define OBJ_pbeWithSHA1AndRC2_CBC OBJ_pkcs,5L,11L + +/* proposed by microsoft to RSA as pbeWithSHA1AndRC4: it is now + * defined explicitly in PKCS#5 v2.0 as id-PBKDF2 which is something + * completely different. + */ +#define LN_id_pbkdf2 "PBKDF2" +#define NID_id_pbkdf2 69 +#define OBJ_id_pbkdf2 OBJ_pkcs,5L,12L + +#define SN_dsaWithSHA1_2 "DSA-SHA1-old" +#define LN_dsaWithSHA1_2 "dsaWithSHA1-old" +#define NID_dsaWithSHA1_2 70 +/* Got this one from 'sdn706r20.pdf' which is actually an NSA document :-) */ +#define OBJ_dsaWithSHA1_2 OBJ_algorithm,27L + +#define SN_netscape_cert_type "nsCertType" +#define LN_netscape_cert_type "Netscape Cert Type" +#define NID_netscape_cert_type 71 +#define OBJ_netscape_cert_type OBJ_netscape_cert_extension,1L + +#define SN_netscape_base_url "nsBaseUrl" +#define LN_netscape_base_url "Netscape Base Url" +#define NID_netscape_base_url 72 +#define OBJ_netscape_base_url OBJ_netscape_cert_extension,2L + +#define SN_netscape_revocation_url "nsRevocationUrl" +#define LN_netscape_revocation_url "Netscape Revocation Url" +#define NID_netscape_revocation_url 73 +#define OBJ_netscape_revocation_url OBJ_netscape_cert_extension,3L + +#define SN_netscape_ca_revocation_url "nsCaRevocationUrl" +#define LN_netscape_ca_revocation_url "Netscape CA Revocation Url" +#define NID_netscape_ca_revocation_url 74 +#define OBJ_netscape_ca_revocation_url OBJ_netscape_cert_extension,4L + +#define SN_netscape_renewal_url "nsRenewalUrl" +#define LN_netscape_renewal_url "Netscape Renewal Url" +#define NID_netscape_renewal_url 75 +#define OBJ_netscape_renewal_url OBJ_netscape_cert_extension,7L + +#define SN_netscape_ca_policy_url "nsCaPolicyUrl" +#define LN_netscape_ca_policy_url "Netscape CA Policy Url" +#define NID_netscape_ca_policy_url 76 +#define OBJ_netscape_ca_policy_url OBJ_netscape_cert_extension,8L + +#define SN_netscape_ssl_server_name "nsSslServerName" +#define LN_netscape_ssl_server_name "Netscape SSL Server Name" +#define NID_netscape_ssl_server_name 77 +#define OBJ_netscape_ssl_server_name OBJ_netscape_cert_extension,12L + +#define SN_netscape_comment "nsComment" +#define LN_netscape_comment "Netscape Comment" +#define NID_netscape_comment 78 +#define OBJ_netscape_comment OBJ_netscape_cert_extension,13L + +#define SN_netscape_cert_sequence "nsCertSequence" +#define LN_netscape_cert_sequence "Netscape Certificate Sequence" +#define NID_netscape_cert_sequence 79 +#define OBJ_netscape_cert_sequence OBJ_netscape_data_type,5L + +#define SN_desx_cbc "DESX-CBC" +#define LN_desx_cbc "desx-cbc" +#define NID_desx_cbc 80 + +#define SN_ld_ce "ld-ce" +#define NID_ld_ce 81 +#define OBJ_ld_ce 2L,5L,29L + +#define SN_subject_key_identifier "subjectKeyIdentifier" +#define LN_subject_key_identifier "X509v3 Subject Key Identifier" +#define NID_subject_key_identifier 82 +#define OBJ_subject_key_identifier OBJ_ld_ce,14L + +#define SN_key_usage "keyUsage" +#define LN_key_usage "X509v3 Key Usage" +#define NID_key_usage 83 +#define OBJ_key_usage OBJ_ld_ce,15L + +#define SN_private_key_usage_period "privateKeyUsagePeriod" +#define LN_private_key_usage_period "X509v3 Private Key Usage Period" +#define NID_private_key_usage_period 84 +#define OBJ_private_key_usage_period OBJ_ld_ce,16L + +#define SN_subject_alt_name "subjectAltName" +#define LN_subject_alt_name "X509v3 Subject Alternative Name" +#define NID_subject_alt_name 85 +#define OBJ_subject_alt_name OBJ_ld_ce,17L + +#define SN_issuer_alt_name "issuerAltName" +#define LN_issuer_alt_name "X509v3 Issuer Alternative Name" +#define NID_issuer_alt_name 86 +#define OBJ_issuer_alt_name OBJ_ld_ce,18L + +#define SN_basic_constraints "basicConstraints" +#define LN_basic_constraints "X509v3 Basic Constraints" +#define NID_basic_constraints 87 +#define OBJ_basic_constraints OBJ_ld_ce,19L + +#define SN_crl_number "crlNumber" +#define LN_crl_number "X509v3 CRL Number" +#define NID_crl_number 88 +#define OBJ_crl_number OBJ_ld_ce,20L + +#define SN_certificate_policies "certificatePolicies" +#define LN_certificate_policies "X509v3 Certificate Policies" +#define NID_certificate_policies 89 +#define OBJ_certificate_policies OBJ_ld_ce,32L + +#define SN_authority_key_identifier "authorityKeyIdentifier" +#define LN_authority_key_identifier "X509v3 Authority Key Identifier" +#define NID_authority_key_identifier 90 +#define OBJ_authority_key_identifier OBJ_ld_ce,35L + +#define SN_bf_cbc "BF-CBC" +#define LN_bf_cbc "bf-cbc" +#define NID_bf_cbc 91 +#define OBJ_bf_cbc 1L,3L,6L,1L,4L,1L,3029L,1L,2L + +#define SN_bf_ecb "BF-ECB" +#define LN_bf_ecb "bf-ecb" +#define NID_bf_ecb 92 + +#define SN_bf_cfb64 "BF-CFB" +#define LN_bf_cfb64 "bf-cfb" +#define NID_bf_cfb64 93 + +#define SN_bf_ofb64 "BF-OFB" +#define LN_bf_ofb64 "bf-ofb" +#define NID_bf_ofb64 94 + +#define SN_mdc2 "MDC2" +#define LN_mdc2 "mdc2" +#define NID_mdc2 95 +#define OBJ_mdc2 2L,5L,8L,3L,101L +/* An alternative? 1L,3L,14L,3L,2L,19L */ + +#define SN_mdc2WithRSA "RSA-MDC2" +#define LN_mdc2WithRSA "mdc2withRSA" +#define NID_mdc2WithRSA 96 +#define OBJ_mdc2WithRSA 2L,5L,8L,3L,100L + +#define SN_rc4_40 "RC4-40" +#define LN_rc4_40 "rc4-40" +#define NID_rc4_40 97 + +#define SN_rc2_40_cbc "RC2-40-CBC" +#define LN_rc2_40_cbc "rc2-40-cbc" +#define NID_rc2_40_cbc 98 + +#define SN_givenName "G" +#define LN_givenName "givenName" +#define NID_givenName 99 +#define OBJ_givenName OBJ_X509,42L + +#define SN_surname "S" +#define LN_surname "surname" +#define NID_surname 100 +#define OBJ_surname OBJ_X509,4L + +#define SN_initials "I" +#define LN_initials "initials" +#define NID_initials 101 +#define OBJ_initials OBJ_X509,43L + +#define SN_uniqueIdentifier "UID" +#define LN_uniqueIdentifier "uniqueIdentifier" +#define NID_uniqueIdentifier 102 +#define OBJ_uniqueIdentifier OBJ_X509,45L + +#define SN_crl_distribution_points "crlDistributionPoints" +#define LN_crl_distribution_points "X509v3 CRL Distribution Points" +#define NID_crl_distribution_points 103 +#define OBJ_crl_distribution_points OBJ_ld_ce,31L + +#define SN_md5WithRSA "RSA-NP-MD5" +#define LN_md5WithRSA "md5WithRSA" +#define NID_md5WithRSA 104 +#define OBJ_md5WithRSA OBJ_algorithm,3L + +#define SN_serialNumber "SN" +#define LN_serialNumber "serialNumber" +#define NID_serialNumber 105 +#define OBJ_serialNumber OBJ_X509,5L + +#define SN_title "T" +#define LN_title "title" +#define NID_title 106 +#define OBJ_title OBJ_X509,12L + +#define SN_description "D" +#define LN_description "description" +#define NID_description 107 +#define OBJ_description OBJ_X509,13L + +/* CAST5 is CAST-128, I'm just sticking with the documentation */ +#define SN_cast5_cbc "CAST5-CBC" +#define LN_cast5_cbc "cast5-cbc" +#define NID_cast5_cbc 108 +#define OBJ_cast5_cbc 1L,2L,840L,113533L,7L,66L,10L + +#define SN_cast5_ecb "CAST5-ECB" +#define LN_cast5_ecb "cast5-ecb" +#define NID_cast5_ecb 109 + +#define SN_cast5_cfb64 "CAST5-CFB" +#define LN_cast5_cfb64 "cast5-cfb" +#define NID_cast5_cfb64 110 + +#define SN_cast5_ofb64 "CAST5-OFB" +#define LN_cast5_ofb64 "cast5-ofb" +#define NID_cast5_ofb64 111 + +#define LN_pbeWithMD5AndCast5_CBC "pbeWithMD5AndCast5CBC" +#define NID_pbeWithMD5AndCast5_CBC 112 +#define OBJ_pbeWithMD5AndCast5_CBC 1L,2L,840L,113533L,7L,66L,12L + +/* This is one sun will soon be using :-( + * id-dsa-with-sha1 ID ::= { + * iso(1) member-body(2) us(840) x9-57 (10040) x9cm(4) 3 } + */ +#define SN_dsaWithSHA1 "DSA-SHA1" +#define LN_dsaWithSHA1 "dsaWithSHA1" +#define NID_dsaWithSHA1 113 +#define OBJ_dsaWithSHA1 1L,2L,840L,10040L,4L,3L + +#define NID_md5_sha1 114 +#define SN_md5_sha1 "MD5-SHA1" +#define LN_md5_sha1 "md5-sha1" + +#define SN_sha1WithRSA "RSA-SHA1-2" +#define LN_sha1WithRSA "sha1WithRSA" +#define NID_sha1WithRSA 115 +#define OBJ_sha1WithRSA OBJ_algorithm,29L + +#define SN_dsa "DSA" +#define LN_dsa "dsaEncryption" +#define NID_dsa 116 +#define OBJ_dsa 1L,2L,840L,10040L,4L,1L + +#define SN_ripemd160 "RIPEMD160" +#define LN_ripemd160 "ripemd160" +#define NID_ripemd160 117 +#define OBJ_ripemd160 1L,3L,36L,3L,2L,1L + +/* The name should actually be rsaSignatureWithripemd160, but I'm going + * to continue using the convention I'm using with the other ciphers */ +#define SN_ripemd160WithRSA "RSA-RIPEMD160" +#define LN_ripemd160WithRSA "ripemd160WithRSA" +#define NID_ripemd160WithRSA 119 +#define OBJ_ripemd160WithRSA 1L,3L,36L,3L,3L,1L,2L + +/* Taken from rfc2040 + * RC5_CBC_Parameters ::= SEQUENCE { + * version INTEGER (v1_0(16)), + * rounds INTEGER (8..127), + * blockSizeInBits INTEGER (64, 128), + * iv OCTET STRING OPTIONAL + * } + */ +#define SN_rc5_cbc "RC5-CBC" +#define LN_rc5_cbc "rc5-cbc" +#define NID_rc5_cbc 120 +#define OBJ_rc5_cbc OBJ_rsadsi,3L,8L + +#define SN_rc5_ecb "RC5-ECB" +#define LN_rc5_ecb "rc5-ecb" +#define NID_rc5_ecb 121 + +#define SN_rc5_cfb64 "RC5-CFB" +#define LN_rc5_cfb64 "rc5-cfb" +#define NID_rc5_cfb64 122 + +#define SN_rc5_ofb64 "RC5-OFB" +#define LN_rc5_ofb64 "rc5-ofb" +#define NID_rc5_ofb64 123 + +#define SN_rle_compression "RLE" +#define LN_rle_compression "run length compression" +#define NID_rle_compression 124 +#define OBJ_rle_compression 1L,1L,1L,1L,666L,1L + +#define SN_zlib_compression "ZLIB" +#define LN_zlib_compression "zlib compression" +#define NID_zlib_compression 125 +#define OBJ_zlib_compression 1L,1L,1L,1L,666L,2L + +#define SN_ext_key_usage "extendedKeyUsage" +#define LN_ext_key_usage "X509v3 Extended Key Usage" +#define NID_ext_key_usage 126 +#define OBJ_ext_key_usage OBJ_ld_ce,37 + +#define SN_id_pkix "PKIX" +#define NID_id_pkix 127 +#define OBJ_id_pkix 1L,3L,6L,1L,5L,5L,7L + +#define SN_id_kp "id-kp" +#define NID_id_kp 128 +#define OBJ_id_kp OBJ_id_pkix,3L + +/* PKIX extended key usage OIDs */ + +#define SN_server_auth "serverAuth" +#define LN_server_auth "TLS Web Server Authentication" +#define NID_server_auth 129 +#define OBJ_server_auth OBJ_id_kp,1L + +#define SN_client_auth "clientAuth" +#define LN_client_auth "TLS Web Client Authentication" +#define NID_client_auth 130 +#define OBJ_client_auth OBJ_id_kp,2L + +#define SN_code_sign "codeSigning" +#define LN_code_sign "Code Signing" +#define NID_code_sign 131 +#define OBJ_code_sign OBJ_id_kp,3L + +#define SN_email_protect "emailProtection" +#define LN_email_protect "E-mail Protection" +#define NID_email_protect 132 +#define OBJ_email_protect OBJ_id_kp,4L + +#define SN_time_stamp "timeStamping" +#define LN_time_stamp "Time Stamping" +#define NID_time_stamp 133 +#define OBJ_time_stamp OBJ_id_kp,8L + +/* Additional extended key usage OIDs: Microsoft */ + +#define SN_ms_code_ind "msCodeInd" +#define LN_ms_code_ind "Microsoft Individual Code Signing" +#define NID_ms_code_ind 134 +#define OBJ_ms_code_ind 1L,3L,6L,1L,4L,1L,311L,2L,1L,21L + +#define SN_ms_code_com "msCodeCom" +#define LN_ms_code_com "Microsoft Commercial Code Signing" +#define NID_ms_code_com 135 +#define OBJ_ms_code_com 1L,3L,6L,1L,4L,1L,311L,2L,1L,22L + +#define SN_ms_ctl_sign "msCTLSign" +#define LN_ms_ctl_sign "Microsoft Trust List Signing" +#define NID_ms_ctl_sign 136 +#define OBJ_ms_ctl_sign 1L,3L,6L,1L,4L,1L,311L,10L,3L,1L + +#define SN_ms_sgc "msSGC" +#define LN_ms_sgc "Microsoft Server Gated Crypto" +#define NID_ms_sgc 137 +#define OBJ_ms_sgc 1L,3L,6L,1L,4L,1L,311L,10L,3L,3L + +#define SN_ms_efs "msEFS" +#define LN_ms_efs "Microsoft Encrypted File System" +#define NID_ms_efs 138 +#define OBJ_ms_efs 1L,3L,6L,1L,4L,1L,311L,10L,3L,4L + +/* Additional usage: Netscape */ + +#define SN_ns_sgc "nsSGC" +#define LN_ns_sgc "Netscape Server Gated Crypto" +#define NID_ns_sgc 139 +#define OBJ_ns_sgc OBJ_netscape,4L,1L + +#define SN_delta_crl "deltaCRL" +#define LN_delta_crl "X509v3 Delta CRL Indicator" +#define NID_delta_crl 140 +#define OBJ_delta_crl OBJ_ld_ce,27L + +#define SN_crl_reason "CRLReason" +#define LN_crl_reason "CRL Reason Code" +#define NID_crl_reason 141 +#define OBJ_crl_reason OBJ_ld_ce,21L + +#define SN_invalidity_date "invalidityDate" +#define LN_invalidity_date "Invalidity Date" +#define NID_invalidity_date 142 +#define OBJ_invalidity_date OBJ_ld_ce,24L + +#define SN_sxnet "SXNetID" +#define LN_sxnet "Strong Extranet ID" +#define NID_sxnet 143 +#define OBJ_sxnet 1L,3L,101L,1L,4L,1L + +/* PKCS12 and related OBJECT IDENTIFIERS */ + +#define OBJ_pkcs12 OBJ_pkcs,12L +#define OBJ_pkcs12_pbeids OBJ_pkcs12, 1 + +#define SN_pbe_WithSHA1And128BitRC4 "PBE-SHA1-RC4-128" +#define LN_pbe_WithSHA1And128BitRC4 "pbeWithSHA1And128BitRC4" +#define NID_pbe_WithSHA1And128BitRC4 144 +#define OBJ_pbe_WithSHA1And128BitRC4 OBJ_pkcs12_pbeids, 1L + +#define SN_pbe_WithSHA1And40BitRC4 "PBE-SHA1-RC4-40" +#define LN_pbe_WithSHA1And40BitRC4 "pbeWithSHA1And40BitRC4" +#define NID_pbe_WithSHA1And40BitRC4 145 +#define OBJ_pbe_WithSHA1And40BitRC4 OBJ_pkcs12_pbeids, 2L + +#define SN_pbe_WithSHA1And3_Key_TripleDES_CBC "PBE-SHA1-3DES" +#define LN_pbe_WithSHA1And3_Key_TripleDES_CBC "pbeWithSHA1And3-KeyTripleDES-CBC" +#define NID_pbe_WithSHA1And3_Key_TripleDES_CBC 146 +#define OBJ_pbe_WithSHA1And3_Key_TripleDES_CBC OBJ_pkcs12_pbeids, 3L + +#define SN_pbe_WithSHA1And2_Key_TripleDES_CBC "PBE-SHA1-2DES" +#define LN_pbe_WithSHA1And2_Key_TripleDES_CBC "pbeWithSHA1And2-KeyTripleDES-CBC" +#define NID_pbe_WithSHA1And2_Key_TripleDES_CBC 147 +#define OBJ_pbe_WithSHA1And2_Key_TripleDES_CBC OBJ_pkcs12_pbeids, 4L + +#define SN_pbe_WithSHA1And128BitRC2_CBC "PBE-SHA1-RC2-128" +#define LN_pbe_WithSHA1And128BitRC2_CBC "pbeWithSHA1And128BitRC2-CBC" +#define NID_pbe_WithSHA1And128BitRC2_CBC 148 +#define OBJ_pbe_WithSHA1And128BitRC2_CBC OBJ_pkcs12_pbeids, 5L + +#define SN_pbe_WithSHA1And40BitRC2_CBC "PBE-SHA1-RC2-40" +#define LN_pbe_WithSHA1And40BitRC2_CBC "pbeWithSHA1And40BitRC2-CBC" +#define NID_pbe_WithSHA1And40BitRC2_CBC 149 +#define OBJ_pbe_WithSHA1And40BitRC2_CBC OBJ_pkcs12_pbeids, 6L + +#define OBJ_pkcs12_Version1 OBJ_pkcs12, 10L + +#define OBJ_pkcs12_BagIds OBJ_pkcs12_Version1, 1L + +#define LN_keyBag "keyBag" +#define NID_keyBag 150 +#define OBJ_keyBag OBJ_pkcs12_BagIds, 1L + +#define LN_pkcs8ShroudedKeyBag "pkcs8ShroudedKeyBag" +#define NID_pkcs8ShroudedKeyBag 151 +#define OBJ_pkcs8ShroudedKeyBag OBJ_pkcs12_BagIds, 2L + +#define LN_certBag "certBag" +#define NID_certBag 152 +#define OBJ_certBag OBJ_pkcs12_BagIds, 3L + +#define LN_crlBag "crlBag" +#define NID_crlBag 153 +#define OBJ_crlBag OBJ_pkcs12_BagIds, 4L + +#define LN_secretBag "secretBag" +#define NID_secretBag 154 +#define OBJ_secretBag OBJ_pkcs12_BagIds, 5L + +#define LN_safeContentsBag "safeContentsBag" +#define NID_safeContentsBag 155 +#define OBJ_safeContentsBag OBJ_pkcs12_BagIds, 6L + +#define LN_friendlyName "friendlyName" +#define NID_friendlyName 156 +#define OBJ_friendlyName OBJ_pkcs9, 20L + +#define LN_localKeyID "localKeyID" +#define NID_localKeyID 157 +#define OBJ_localKeyID OBJ_pkcs9, 21L + +#define OBJ_certTypes OBJ_pkcs9, 22L + +#define LN_x509Certificate "x509Certificate" +#define NID_x509Certificate 158 +#define OBJ_x509Certificate OBJ_certTypes, 1L + +#define LN_sdsiCertificate "sdsiCertificate" +#define NID_sdsiCertificate 159 +#define OBJ_sdsiCertificate OBJ_certTypes, 2L + +#define OBJ_crlTypes OBJ_pkcs9, 23L + +#define LN_x509Crl "x509Crl" +#define NID_x509Crl 160 +#define OBJ_x509Crl OBJ_crlTypes, 1L + +/* PKCS#5 v2 OIDs */ + +#define LN_pbes2 "PBES2" +#define NID_pbes2 161 +#define OBJ_pbes2 OBJ_pkcs,5L,13L + +#define LN_pbmac1 "PBMAC1" +#define NID_pbmac1 162 +#define OBJ_pbmac1 OBJ_pkcs,5L,14L + +#define LN_hmacWithSHA1 "hmacWithSHA1" +#define NID_hmacWithSHA1 163 +#define OBJ_hmacWithSHA1 OBJ_rsadsi,2L,7L + +/* Policy Qualifier Ids */ + +#define LN_id_qt_cps "Policy Qualifier CPS" +#define SN_id_qt_cps "id-qt-cps" +#define NID_id_qt_cps 164 +#define OBJ_id_qt_cps OBJ_id_pkix,2L,1L + +#define LN_id_qt_unotice "Policy Qualifier User Notice" +#define SN_id_qt_unotice "id-qt-unotice" +#define NID_id_qt_unotice 165 +#define OBJ_id_qt_unotice OBJ_id_pkix,2L,2L + +#define SN_rc2_64_cbc "RC2-64-CBC" +#define LN_rc2_64_cbc "rc2-64-cbc" +#define NID_rc2_64_cbc 166 + +#define SN_SMIMECapabilities "SMIME-CAPS" +#define LN_SMIMECapabilities "S/MIME Capabilities" +#define NID_SMIMECapabilities 167 +#define OBJ_SMIMECapabilities OBJ_pkcs9,15L + +#define SN_pbeWithMD2AndRC2_CBC "PBE-MD2-RC2-64" +#define LN_pbeWithMD2AndRC2_CBC "pbeWithMD2AndRC2-CBC" +#define NID_pbeWithMD2AndRC2_CBC 168 +#define OBJ_pbeWithMD2AndRC2_CBC OBJ_pkcs,5L,4L + +#define SN_pbeWithMD5AndRC2_CBC "PBE-MD5-RC2-64" +#define LN_pbeWithMD5AndRC2_CBC "pbeWithMD5AndRC2-CBC" +#define NID_pbeWithMD5AndRC2_CBC 169 +#define OBJ_pbeWithMD5AndRC2_CBC OBJ_pkcs,5L,6L + +#define SN_pbeWithSHA1AndDES_CBC "PBE-SHA1-DES" +#define LN_pbeWithSHA1AndDES_CBC "pbeWithSHA1AndDES-CBC" +#define NID_pbeWithSHA1AndDES_CBC 170 +#define OBJ_pbeWithSHA1AndDES_CBC OBJ_pkcs,5L,10L + +/* Extension request OIDs */ + +#define LN_ms_ext_req "Microsoft Extension Request" +#define SN_ms_ext_req "msExtReq" +#define NID_ms_ext_req 171 +#define OBJ_ms_ext_req 1L,3L,6L,1L,4L,1L,311L,2L,1L,14L + +#define LN_ext_req "Extension Request" +#define SN_ext_req "extReq" +#define NID_ext_req 172 +#define OBJ_ext_req OBJ_pkcs9,14L + +#define SN_name "name" +#define LN_name "name" +#define NID_name 173 +#define OBJ_name OBJ_X509,41L + +#define SN_dnQualifier "dnQualifier" +#define LN_dnQualifier "dnQualifier" +#define NID_dnQualifier 174 +#define OBJ_dnQualifier OBJ_X509,46L + +#define SN_id_pe "id-pe" +#define NID_id_pe 175 +#define OBJ_id_pe OBJ_id_pkix,1L + +#define SN_id_ad "id-ad" +#define NID_id_ad 176 +#define OBJ_id_ad OBJ_id_pkix,48L + +#define SN_info_access "authorityInfoAccess" +#define LN_info_access "Authority Information Access" +#define NID_info_access 177 +#define OBJ_info_access OBJ_id_pe,1L + +#define SN_ad_OCSP "OCSP" +#define LN_ad_OCSP "OCSP" +#define NID_ad_OCSP 178 +#define OBJ_ad_OCSP OBJ_id_ad,1L + +#define SN_ad_ca_issuers "caIssuers" +#define LN_ad_ca_issuers "CA Issuers" +#define NID_ad_ca_issuers 179 +#define OBJ_ad_ca_issuers OBJ_id_ad,2L + +#define SN_OCSP_sign "OCSPSigning" +#define LN_OCSP_sign "OCSP Signing" +#define NID_OCSP_sign 180 +#define OBJ_OCSP_sign OBJ_id_kp,9L + +#include +#include + +#define OBJ_NAME_TYPE_UNDEF 0x00 +#define OBJ_NAME_TYPE_MD_METH 0x01 +#define OBJ_NAME_TYPE_CIPHER_METH 0x02 +#define OBJ_NAME_TYPE_PKEY_METH 0x03 +#define OBJ_NAME_TYPE_COMP_METH 0x04 +#define OBJ_NAME_TYPE_NUM 0x05 + +#define OBJ_NAME_ALIAS 0x8000 + + +typedef struct obj_name_st + { + int type; + int alias; + const char *name; + const char *data; + } OBJ_NAME; + +#define OBJ_create_and_add_object(a,b,c) OBJ_create(a,b,c) + + +int OBJ_NAME_init(void); +int OBJ_NAME_new_index(unsigned long (*hash_func)(),int (*cmp_func)(), + void (*free_func)()); +const char *OBJ_NAME_get(const char *name,int type); +int OBJ_NAME_add(const char *name,int type,const char *data); +int OBJ_NAME_remove(const char *name,int type); +void OBJ_NAME_cleanup(int type); /* -1 for everything */ + +ASN1_OBJECT * OBJ_dup(ASN1_OBJECT *o); +ASN1_OBJECT * OBJ_nid2obj(int n); +const char * OBJ_nid2ln(int n); +const char * OBJ_nid2sn(int n); +int OBJ_obj2nid(ASN1_OBJECT *o); +ASN1_OBJECT * OBJ_txt2obj(const char *s, int no_name); +int OBJ_obj2txt(char *buf, int buf_len, ASN1_OBJECT *a, int no_name); +int OBJ_txt2nid(char *s); +int OBJ_ln2nid(const char *s); +int OBJ_sn2nid(const char *s); +int OBJ_cmp(ASN1_OBJECT *a,ASN1_OBJECT *b); +char * OBJ_bsearch(char *key,char *base,int num,int size,int (*cmp)()); + +void ERR_load_OBJ_strings(void ); + +int OBJ_new_nid(int num); +int OBJ_add_object(ASN1_OBJECT *obj); +int OBJ_create(char *oid,char *sn,char *ln); +void OBJ_cleanup(void ); +int OBJ_create_objects(BIO *in); + +/* BEGIN ERROR CODES */ +/* The following lines are auto generated by the script mkerr.pl. Any changes + * made after this point may be overwritten when the script is next run. + */ + +/* Error codes for the OBJ functions. */ + +/* Function codes. */ +#define OBJ_F_OBJ_CREATE 100 +#define OBJ_F_OBJ_DUP 101 +#define OBJ_F_OBJ_NID2LN 102 +#define OBJ_F_OBJ_NID2OBJ 103 +#define OBJ_F_OBJ_NID2SN 104 + +/* Reason codes. */ +#define OBJ_R_MALLOC_FAILURE 100 +#define OBJ_R_UNKNOWN_NID 101 + +#ifdef __cplusplus +} +#endif +#endif + diff --git a/libsecurity_apple_csp/open_ssl/openssl/openssl_pkcs7.h b/libsecurity_apple_csp/open_ssl/openssl/openssl_pkcs7.h new file mode 100644 index 00000000..223438ba --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/openssl/openssl_pkcs7.h @@ -0,0 +1,516 @@ +/* + * 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. + */ + + +/* crypto/pkcs7/pkcs7.h */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef HEADER_PKCS7_H +#define HEADER_PKCS7_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +#ifdef VMS +#include +#endif + +#ifdef WIN32 +/* Under Win32 thes are defined in wincrypt.h */ +#undef PKCS7_ISSUER_AND_SERIAL +#undef PKCS7_SIGNER_INFO +#endif + +/* +Encryption_ID DES-CBC +Digest_ID MD5 +Digest_Encryption_ID rsaEncryption +Key_Encryption_ID rsaEncryption +*/ + +typedef struct pkcs7_issuer_and_serial_st + { + X509_NAME *issuer; + ASN1_INTEGER *serial; + } PKCS7_ISSUER_AND_SERIAL; + +typedef struct pkcs7_signer_info_st + { + ASN1_INTEGER *version; /* version 1 */ + PKCS7_ISSUER_AND_SERIAL *issuer_and_serial; + X509_ALGOR *digest_alg; + STACK_OF(X509_ATTRIBUTE) *auth_attr; /* [ 0 ] */ + X509_ALGOR *digest_enc_alg; + ASN1_OCTET_STRING *enc_digest; + STACK_OF(X509_ATTRIBUTE) *unauth_attr; /* [ 1 ] */ + + /* The private key to sign with */ + EVP_PKEY *pkey; + } PKCS7_SIGNER_INFO; + +DECLARE_STACK_OF(PKCS7_SIGNER_INFO) +DECLARE_ASN1_SET_OF(PKCS7_SIGNER_INFO) + +typedef struct pkcs7_recip_info_st + { + ASN1_INTEGER *version; /* version 0 */ + PKCS7_ISSUER_AND_SERIAL *issuer_and_serial; + X509_ALGOR *key_enc_algor; + ASN1_OCTET_STRING *enc_key; + X509 *cert; /* get the pub-key from this */ + } PKCS7_RECIP_INFO; + +DECLARE_STACK_OF(PKCS7_RECIP_INFO) +DECLARE_ASN1_SET_OF(PKCS7_RECIP_INFO) + +typedef struct pkcs7_signed_st + { + ASN1_INTEGER *version; /* version 1 */ + STACK_OF(X509_ALGOR) *md_algs; /* md used */ + STACK_OF(X509) *cert; /* [ 0 ] */ + STACK_OF(X509_CRL) *crl; /* [ 1 ] */ + STACK_OF(PKCS7_SIGNER_INFO) *signer_info; + + struct pkcs7_st *contents; + } PKCS7_SIGNED; +/* The above structure is very very similar to PKCS7_SIGN_ENVELOPE. + * How about merging the two */ + +typedef struct pkcs7_enc_content_st + { + ASN1_OBJECT *content_type; + X509_ALGOR *algorithm; + ASN1_OCTET_STRING *enc_data; /* [ 0 ] */ + const EVP_CIPHER *cipher; + } PKCS7_ENC_CONTENT; + +typedef struct pkcs7_enveloped_st + { + ASN1_INTEGER *version; /* version 0 */ + STACK_OF(PKCS7_RECIP_INFO) *recipientinfo; + PKCS7_ENC_CONTENT *enc_data; + } PKCS7_ENVELOPE; + +typedef struct pkcs7_signedandenveloped_st + { + ASN1_INTEGER *version; /* version 1 */ + STACK_OF(X509_ALGOR) *md_algs; /* md used */ + STACK_OF(X509) *cert; /* [ 0 ] */ + STACK_OF(X509_CRL) *crl; /* [ 1 ] */ + STACK_OF(PKCS7_SIGNER_INFO) *signer_info; + + PKCS7_ENC_CONTENT *enc_data; + STACK_OF(PKCS7_RECIP_INFO) *recipientinfo; + } PKCS7_SIGN_ENVELOPE; + +typedef struct pkcs7_digest_st + { + ASN1_INTEGER *version; /* version 0 */ + X509_ALGOR *md; /* md used */ + struct pkcs7_st *contents; + ASN1_OCTET_STRING *digest; + } PKCS7_DIGEST; + +typedef struct pkcs7_encrypted_st + { + ASN1_INTEGER *version; /* version 0 */ + PKCS7_ENC_CONTENT *enc_data; + } PKCS7_ENCRYPT; + +typedef struct pkcs7_st + { + /* The following is non NULL if it contains ASN1 encoding of + * this structure */ + unsigned char *asn1; + long length; + +#define PKCS7_S_HEADER 0 +#define PKCS7_S_BODY 1 +#define PKCS7_S_TAIL 2 + int state; /* used during processing */ + + int detached; + + ASN1_OBJECT *type; + /* content as defined by the type */ + /* all encryption/message digests are applied to the 'contents', + * leaving out the 'type' field. */ + union { + char *ptr; + + /* NID_pkcs7_data */ + ASN1_OCTET_STRING *data; + + /* NID_pkcs7_signed */ + PKCS7_SIGNED *sign; + + /* NID_pkcs7_enveloped */ + PKCS7_ENVELOPE *enveloped; + + /* NID_pkcs7_signedAndEnveloped */ + PKCS7_SIGN_ENVELOPE *signed_and_enveloped; + + /* NID_pkcs7_digest */ + PKCS7_DIGEST *digest; + + /* NID_pkcs7_encrypted */ + PKCS7_ENCRYPT *encrypted; + } d; + } PKCS7; + +#define PKCS7_OP_SET_DETACHED_SIGNATURE 1 +#define PKCS7_OP_GET_DETACHED_SIGNATURE 2 + +#define PKCS7_get_signed_attributes(si) ((si)->auth_attr) +#define PKCS7_get_attributes(si) ((si)->unauth_attr) + +#define PKCS7_type_is_signed(a) (OBJ_obj2nid((a)->type) == NID_pkcs7_signed) +#define PKCS7_type_is_enveloped(a) (OBJ_obj2nid((a)->type) == NID_pkcs7_enveloped) +#define PKCS7_type_is_signedAndEnveloped(a) \ + (OBJ_obj2nid((a)->type) == NID_pkcs7_signedAndEnveloped) +#define PKCS7_type_is_data(a) (OBJ_obj2nid((a)->type) == NID_pkcs7_data) + +#define PKCS7_set_detached(p,v) \ + PKCS7_ctrl(p,PKCS7_OP_SET_DETACHED_SIGNATURE,v,NULL) +#define PKCS7_get_detached(p) \ + PKCS7_ctrl(p,PKCS7_OP_GET_DETACHED_SIGNATURE,0,NULL) + +#ifdef SSLEAY_MACROS +#ifndef PKCS7_ISSUER_AND_SERIAL_digest +#define PKCS7_ISSUER_AND_SERIAL_digest(data,type,md,len) \ + ASN1_digest((int (*)())i2d_PKCS7_ISSUER_AND_SERIAL,type,\ + (char *)data,md,len) +#endif +#endif + +/* S/MIME related flags */ + +#define PKCS7_TEXT 0x1 +#define PKCS7_NOCERTS 0x2 +#define PKCS7_NOSIGS 0x4 +#define PKCS7_NOCHAIN 0x8 +#define PKCS7_NOINTERN 0x10 +#define PKCS7_NOVERIFY 0x20 +#define PKCS7_DETACHED 0x40 +#define PKCS7_BINARY 0x80 +#define PKCS7_NOATTR 0x100 + +/* Flags: for compatibility with older code */ + +#define SMIME_TEXT PKCS7_TEXT +#define SMIME_NOCERTS PKCS7_NOCERTS +#define SMIME_NOSIGS PKCS7_NOSIGS +#define SMIME_NOCHAIN PKCS7_NOCHAIN +#define SMIME_NOINTERN PKCS7_NOINTERN +#define SMIME_NOVERIFY PKCS7_NOVERIFY +#define SMIME_DETACHED PKCS7_DETACHED +#define SMIME_BINARY PKCS7_BINARY +#define SMIME_NOATTR PKCS7_NOATTR + +PKCS7_ISSUER_AND_SERIAL *PKCS7_ISSUER_AND_SERIAL_new(void ); +void PKCS7_ISSUER_AND_SERIAL_free( + PKCS7_ISSUER_AND_SERIAL *a); +int i2d_PKCS7_ISSUER_AND_SERIAL( + PKCS7_ISSUER_AND_SERIAL *a,unsigned char **pp); +PKCS7_ISSUER_AND_SERIAL *d2i_PKCS7_ISSUER_AND_SERIAL( + PKCS7_ISSUER_AND_SERIAL **a, + unsigned char **pp, long length); + +#ifndef SSLEAY_MACROS +int PKCS7_ISSUER_AND_SERIAL_digest(PKCS7_ISSUER_AND_SERIAL *data,const EVP_MD *type, + unsigned char *md,unsigned int *len); +#ifndef NO_FP_API +PKCS7 *d2i_PKCS7_fp(FILE *fp,PKCS7 **p7); +int i2d_PKCS7_fp(FILE *fp,PKCS7 *p7); +#endif +PKCS7 *PKCS7_dup(PKCS7 *p7); +PKCS7 *d2i_PKCS7_bio(BIO *bp,PKCS7 **p7); +int i2d_PKCS7_bio(BIO *bp,PKCS7 *p7); +#endif + +PKCS7_SIGNER_INFO *PKCS7_SIGNER_INFO_new(void); +void PKCS7_SIGNER_INFO_free(PKCS7_SIGNER_INFO *a); +int i2d_PKCS7_SIGNER_INFO(PKCS7_SIGNER_INFO *a, + unsigned char **pp); +PKCS7_SIGNER_INFO *d2i_PKCS7_SIGNER_INFO(PKCS7_SIGNER_INFO **a, + unsigned char **pp,long length); + +PKCS7_RECIP_INFO *PKCS7_RECIP_INFO_new(void); +void PKCS7_RECIP_INFO_free(PKCS7_RECIP_INFO *a); +int i2d_PKCS7_RECIP_INFO(PKCS7_RECIP_INFO *a, + unsigned char **pp); +PKCS7_RECIP_INFO *d2i_PKCS7_RECIP_INFO(PKCS7_RECIP_INFO **a, + unsigned char **pp,long length); + +PKCS7_SIGNED *PKCS7_SIGNED_new(void); +void PKCS7_SIGNED_free(PKCS7_SIGNED *a); +int i2d_PKCS7_SIGNED(PKCS7_SIGNED *a, + unsigned char **pp); +PKCS7_SIGNED *d2i_PKCS7_SIGNED(PKCS7_SIGNED **a, + unsigned char **pp,long length); + +PKCS7_ENC_CONTENT *PKCS7_ENC_CONTENT_new(void); +void PKCS7_ENC_CONTENT_free(PKCS7_ENC_CONTENT *a); +int i2d_PKCS7_ENC_CONTENT(PKCS7_ENC_CONTENT *a, + unsigned char **pp); +PKCS7_ENC_CONTENT *d2i_PKCS7_ENC_CONTENT(PKCS7_ENC_CONTENT **a, + unsigned char **pp,long length); + +PKCS7_ENVELOPE *PKCS7_ENVELOPE_new(void); +void PKCS7_ENVELOPE_free(PKCS7_ENVELOPE *a); +int i2d_PKCS7_ENVELOPE(PKCS7_ENVELOPE *a, + unsigned char **pp); +PKCS7_ENVELOPE *d2i_PKCS7_ENVELOPE(PKCS7_ENVELOPE **a, + unsigned char **pp,long length); + +PKCS7_SIGN_ENVELOPE *PKCS7_SIGN_ENVELOPE_new(void); +void PKCS7_SIGN_ENVELOPE_free(PKCS7_SIGN_ENVELOPE *a); +int i2d_PKCS7_SIGN_ENVELOPE(PKCS7_SIGN_ENVELOPE *a, + unsigned char **pp); +PKCS7_SIGN_ENVELOPE *d2i_PKCS7_SIGN_ENVELOPE(PKCS7_SIGN_ENVELOPE **a, + unsigned char **pp,long length); + +PKCS7_DIGEST *PKCS7_DIGEST_new(void); +void PKCS7_DIGEST_free(PKCS7_DIGEST *a); +int i2d_PKCS7_DIGEST(PKCS7_DIGEST *a, + unsigned char **pp); +PKCS7_DIGEST *d2i_PKCS7_DIGEST(PKCS7_DIGEST **a, + unsigned char **pp,long length); + +PKCS7_ENCRYPT *PKCS7_ENCRYPT_new(void); +void PKCS7_ENCRYPT_free(PKCS7_ENCRYPT *a); +int i2d_PKCS7_ENCRYPT(PKCS7_ENCRYPT *a, + unsigned char **pp); +PKCS7_ENCRYPT *d2i_PKCS7_ENCRYPT(PKCS7_ENCRYPT **a, + unsigned char **pp,long length); + +PKCS7 *PKCS7_new(void); +void PKCS7_free(PKCS7 *a); +void PKCS7_content_free(PKCS7 *a); +int i2d_PKCS7(PKCS7 *a, + unsigned char **pp); +PKCS7 *d2i_PKCS7(PKCS7 **a, + unsigned char **pp,long length); + +void ERR_load_PKCS7_strings(void); + + +long PKCS7_ctrl(PKCS7 *p7, int cmd, long larg, char *parg); + +int PKCS7_set_type(PKCS7 *p7, int type); +int PKCS7_set_content(PKCS7 *p7, PKCS7 *p7_data); +int PKCS7_SIGNER_INFO_set(PKCS7_SIGNER_INFO *p7i, X509 *x509, EVP_PKEY *pkey, + EVP_MD *dgst); +int PKCS7_add_signer(PKCS7 *p7, PKCS7_SIGNER_INFO *p7i); +int PKCS7_add_certificate(PKCS7 *p7, X509 *x509); +int PKCS7_add_crl(PKCS7 *p7, X509_CRL *x509); +int PKCS7_content_new(PKCS7 *p7, int nid); +int PKCS7_dataVerify(X509_STORE *cert_store, X509_STORE_CTX *ctx, + BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si); +int PKCS7_signatureVerify(BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si, + X509 *x509); + +BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio); +int PKCS7_dataFinal(PKCS7 *p7, BIO *bio); +BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert); + + +PKCS7_SIGNER_INFO *PKCS7_add_signature(PKCS7 *p7, X509 *x509, + EVP_PKEY *pkey, EVP_MD *dgst); +X509 *PKCS7_cert_from_signer_info(PKCS7 *p7, PKCS7_SIGNER_INFO *si); +STACK_OF(PKCS7_SIGNER_INFO) *PKCS7_get_signer_info(PKCS7 *p7); + +PKCS7_RECIP_INFO *PKCS7_add_recipient(PKCS7 *p7, X509 *x509); +int PKCS7_add_recipient_info(PKCS7 *p7, PKCS7_RECIP_INFO *ri); +int PKCS7_RECIP_INFO_set(PKCS7_RECIP_INFO *p7i, X509 *x509); +int PKCS7_set_cipher(PKCS7 *p7, const EVP_CIPHER *cipher); + +PKCS7_ISSUER_AND_SERIAL *PKCS7_get_issuer_and_serial(PKCS7 *p7, int idx); +ASN1_OCTET_STRING *PKCS7_digest_from_attributes(STACK_OF(X509_ATTRIBUTE) *sk); +int PKCS7_add_signed_attribute(PKCS7_SIGNER_INFO *p7si,int nid,int type, + void *data); +int PKCS7_add_attribute (PKCS7_SIGNER_INFO *p7si, int nid, int atrtype, + void *value); +ASN1_TYPE *PKCS7_get_attribute(PKCS7_SIGNER_INFO *si, int nid); +ASN1_TYPE *PKCS7_get_signed_attribute(PKCS7_SIGNER_INFO *si, int nid); +int PKCS7_set_signed_attributes(PKCS7_SIGNER_INFO *p7si, + STACK_OF(X509_ATTRIBUTE) *sk); +int PKCS7_set_attributes(PKCS7_SIGNER_INFO *p7si,STACK_OF(X509_ATTRIBUTE) *sk); + + +PKCS7 *PKCS7_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs, + BIO *data, int flags); +int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store, + BIO *indata, BIO *out, int flags); +STACK_OF(X509) *PKCS7_get0_signers(PKCS7 *p7, STACK_OF(X509) *certs, int flags); +PKCS7 *PKCS7_encrypt(STACK_OF(X509) *certs, BIO *in, EVP_CIPHER *cipher, + int flags); +int PKCS7_decrypt(PKCS7 *p7, EVP_PKEY *pkey, X509 *cert, BIO *data, int flags); + +int PKCS7_add_attrib_smimecap(PKCS7_SIGNER_INFO *si, STACK *cap); +STACK *PKCS7_get_smimecap(PKCS7_SIGNER_INFO *si); +int PKCS7_simple_smimecap(STACK *sk, int nid, int arg); + +int SMIME_write_PKCS7(BIO *bio, PKCS7 *p7, BIO *data, int flags); +PKCS7 *SMIME_read_PKCS7(BIO *bio, BIO **bcont); +int SMIME_crlf_copy(BIO *in, BIO *out, int flags); +int SMIME_text(BIO *in, BIO *out); + +/* BEGIN ERROR CODES */ +/* The following lines are auto generated by the script mkerr.pl. Any changes + * made after this point may be overwritten when the script is next run. + */ + +/* Error codes for the PKCS7 functions. */ + +/* Function codes. */ +#define PKCS7_F_B64_READ_PKCS7 120 +#define PKCS7_F_B64_WRITE_PKCS7 121 +#define PKCS7_F_PKCS7_ADD_ATTRIB_SMIMECAP 118 +#define PKCS7_F_PKCS7_ADD_CERTIFICATE 100 +#define PKCS7_F_PKCS7_ADD_CRL 101 +#define PKCS7_F_PKCS7_ADD_RECIPIENT_INFO 102 +#define PKCS7_F_PKCS7_ADD_SIGNER 103 +#define PKCS7_F_PKCS7_CTRL 104 +#define PKCS7_F_PKCS7_DATADECODE 112 +#define PKCS7_F_PKCS7_DATAINIT 105 +#define PKCS7_F_PKCS7_DATASIGN 106 +#define PKCS7_F_PKCS7_DATAVERIFY 107 +#define PKCS7_F_PKCS7_DECRYPT 114 +#define PKCS7_F_PKCS7_ENCRYPT 115 +#define PKCS7_F_PKCS7_GET0_SIGNERS 124 +#define PKCS7_F_PKCS7_SET_CIPHER 108 +#define PKCS7_F_PKCS7_SET_CONTENT 109 +#define PKCS7_F_PKCS7_SET_TYPE 110 +#define PKCS7_F_PKCS7_SIGN 116 +#define PKCS7_F_PKCS7_SIGNATUREVERIFY 113 +#define PKCS7_F_PKCS7_SIMPLE_SMIMECAP 119 +#define PKCS7_F_PKCS7_VERIFY 117 +#define PKCS7_F_SMIME_READ_PKCS7 122 +#define PKCS7_F_SMIME_TEXT 123 + +/* Reason codes. */ +#define PKCS7_R_CERTIFICATE_VERIFY_ERROR 117 +#define PKCS7_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER 144 +#define PKCS7_R_CIPHER_NOT_INITIALIZED 116 +#define PKCS7_R_CONTENT_AND_DATA_PRESENT 118 +#define PKCS7_R_DECODE_ERROR 130 +#define PKCS7_R_DECRYPTED_KEY_IS_WRONG_LENGTH 100 +#define PKCS7_R_DECRYPT_ERROR 119 +#define PKCS7_R_DIGEST_FAILURE 101 +#define PKCS7_R_ERROR_ADDING_RECIPIENT 120 +#define PKCS7_R_ERROR_SETTING_CIPHER 121 +#define PKCS7_R_INTERNAL_ERROR 102 +#define PKCS7_R_INVALID_MIME_TYPE 131 +#define PKCS7_R_INVALID_NULL_POINTER 143 +#define PKCS7_R_MIME_NO_CONTENT_TYPE 132 +#define PKCS7_R_MIME_PARSE_ERROR 133 +#define PKCS7_R_MIME_SIG_PARSE_ERROR 134 +#define PKCS7_R_MISSING_CERIPEND_INFO 103 +#define PKCS7_R_NO_CONTENT 122 +#define PKCS7_R_NO_CONTENT_TYPE 135 +#define PKCS7_R_NO_MULTIPART_BODY_FAILURE 136 +#define PKCS7_R_NO_MULTIPART_BOUNDARY 137 +#define PKCS7_R_NO_RECIPIENT_MATCHES_CERTIFICATE 115 +#define PKCS7_R_NO_SIGNATURES_ON_DATA 123 +#define PKCS7_R_NO_SIGNERS 142 +#define PKCS7_R_NO_SIG_CONTENT_TYPE 138 +#define PKCS7_R_OPERATION_NOT_SUPPORTED_ON_THIS_TYPE 104 +#define PKCS7_R_PKCS7_ADD_SIGNATURE_ERROR 124 +#define PKCS7_R_PKCS7_DATAFINAL_ERROR 125 +#define PKCS7_R_PKCS7_DATASIGN 126 +#define PKCS7_R_PKCS7_PARSE_ERROR 139 +#define PKCS7_R_PKCS7_SIG_PARSE_ERROR 140 +#define PKCS7_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE 127 +#define PKCS7_R_SIGNATURE_FAILURE 105 +#define PKCS7_R_SIGNER_CERTIFICATE_NOT_FOUND 128 +#define PKCS7_R_SIG_INVALID_MIME_TYPE 141 +#define PKCS7_R_SMIME_TEXT_ERROR 129 +#define PKCS7_R_UNABLE_TO_FIND_CERTIFICATE 106 +#define PKCS7_R_UNABLE_TO_FIND_MEM_BIO 107 +#define PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST 108 +#define PKCS7_R_UNKNOWN_DIGEST_TYPE 109 +#define PKCS7_R_UNKNOWN_OPERATION 110 +#define PKCS7_R_UNSUPPORTED_CIPHER_TYPE 111 +#define PKCS7_R_UNSUPPORTED_CONTENT_TYPE 112 +#define PKCS7_R_WRONG_CONTENT_TYPE 113 +#define PKCS7_R_WRONG_PKCS7_TYPE 114 + +#ifdef __cplusplus +} +#endif +#endif + diff --git a/libsecurity_apple_csp/open_ssl/openssl/opensslconf.h b/libsecurity_apple_csp/open_ssl/openssl/opensslconf.h new file mode 100644 index 00000000..4de0f709 --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/openssl/opensslconf.h @@ -0,0 +1,111 @@ +/* + * 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. + */ + + +/* + * Copyright (c) 2000-2002 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. + */ + +/* + * opensslconf.h - hand-rolled config #defines for openssl code used in AppleCSP + * Written by Doug Mitchell 4/3/2001 + */ +#ifndef _OPENSSL_CONF_H_ +#define _OPENSSL_CONF_H_ + +#include /* for uint32, etc. */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Flags to disable a lot of code we don't need. + */ +#define _OPENSSL_APPLE_CDSA_ 1 + +#define NO_MD5 1 +#define NO_RIPEMD 1 +#define NO_DES 1 +#define NO_IDEA 1 +#define NO_MDC2 1 + +#ifdef NDEBUG +#define NO_ERR 1 +#endif + +/* disable the static callback ptrs in cryptlib.c */ +#define CRYPTO_CALLBACK_ENABLE 0 + +/* disable the BN_{set,get}_params mechanism, unused */ +#define BN_PARAMS_ENABLE 0 + +typedef uint32 RC2_INT; +typedef uint32 RC4_INT; + +/* the following two need calibration and lots of testing; see rc4_enc.c... */ +#undef RC4_CHUNK +#undef RC4_INDEX + +typedef uint32 RC5_32_INT; +typedef uint32 MD2_INT; + +#if defined(HEADER_BF_LOCL_H) && !defined(CONFIG_HEADER_BF_LOCL_H) +#define CONFIG_HEADER_BF_LOCL_H +#define BF_PTR +#endif /* HEADER_BF_LOCL_H */ + +/* + * FIXME - this could certainly use some tweaking + */ +/* Should we define BN_DIV2W here? */ + +/* Only one for the following should be defined */ +/* The prime number generation stuff may not work when + * EIGHT_BIT but I don't care since I've only used this mode + * for debuging the bignum libraries */ + +/* + * Using 64 bit results in an 8% speedup for RSA sign, but a 3% + * slowdown for RSA verify on a G4 cubeÊcompared to 32 bit. + * --dpm, 5/10/01 + */ +#undef SIXTY_FOUR_BIT_LONG +#undef SIXTY_FOUR_BIT +#define THIRTY_TWO_BIT +#undef SIXTEEN_BIT +#undef EIGHT_BIT + +#ifdef __cplusplus +} +#endif + + +#endif /* _OPENSSL_CONF_H_ */ diff --git a/libsecurity_apple_csp/open_ssl/openssl/opensslv.h b/libsecurity_apple_csp/open_ssl/openssl/opensslv.h new file mode 100644 index 00000000..81326858 --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/openssl/opensslv.h @@ -0,0 +1,50 @@ +/* + * 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 HEADER_OPENSSLV_H +#define HEADER_OPENSSLV_H + +/* Numeric release version identifier: + * MMNNFFPPS: major minor fix patch status + * The status nibble has one of the values 0 for development, 1 to e for betas + * 1 to 14, and f for release. The patch level is exactly that. + * For example: + * 0.9.3-dev 0x00903000 + * 0.9.3-beta1 0x00903001 + * 0.9.3-beta2-dev 0x00903002 + * 0.9.3-beta2 0x00903002 (same as ...beta2-dev) + * 0.9.3 0x0090300f + * 0.9.3a 0x0090301f + * 0.9.4 0x0090400f + * 1.2.3z 0x102031af + * + * For continuity reasons (because 0.9.5 is already out, and is coded + * 0x00905100), between 0.9.5 and 0.9.6 the coding of the patch level + * part is slightly different, by setting the highest bit. This means + * that 0.9.5a looks like this: 0x0090581f. At 0.9.6, we can start + * with 0x0090600S... + * + * (Prior to 0.9.3-dev a different scheme was used: 0.9.2b is 0x0922.) + * (Prior to 0.9.5a beta1, a different scheme was used: MMNNFFRBB for + * major minor fix final patch/beta) + */ +#define OPENSSL_VERSION_NUMBER 0x0090581fL +#define OPENSSL_VERSION_TEXT "OpenSSL 0.9.5a 1 Apr 2000" +#define OPENSSL_VERSION_PTEXT " part of " OPENSSL_VERSION_TEXT + +#endif /* HEADER_OPENSSLV_H */ diff --git a/libsecurity_apple_csp/open_ssl/openssl/rand.h b/libsecurity_apple_csp/open_ssl/openssl/rand.h new file mode 100644 index 00000000..3175a468 --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/openssl/rand.h @@ -0,0 +1,135 @@ +/* + * 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. + */ + + +/* crypto/rand/rand.h */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef HEADER_RAND_H +#define HEADER_RAND_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct rand_meth_st + { + void (*seed)(const void *buf, int num); + int (*bytes)(unsigned char *buf, int num); + void (*cleanup)(void); + void (*add)(const void *buf, int num, double entropy); + int (*pseudorand)(unsigned char *buf, int num); + int (*status)(void); + } RAND_METHOD; + +#ifdef BN_DEBUG +extern int rand_predictable; +#endif + +void RAND_set_rand_method(RAND_METHOD *meth); +RAND_METHOD *RAND_get_rand_method(void ); +RAND_METHOD *RAND_SSLeay(void); +void RAND_cleanup(void ); +int RAND_bytes(unsigned char *buf,int num); +int RAND_pseudo_bytes(unsigned char *buf,int num); +void RAND_seed(const void *buf,int num); +void RAND_add(const void *buf,int num,double entropy); +int RAND_load_file(const char *file,long max_bytes); +int RAND_write_file(const char *file); +const char *RAND_file_name(char *file,int num); +int RAND_status(void); +int RAND_egd(const char *path); +#if defined(WINDOWS) || defined(WIN32) +#include +void RAND_screen(void); +int RAND_event(UINT, WPARAM, LPARAM); +#endif +void ERR_load_RAND_strings(void); + +/* BEGIN ERROR CODES */ +/* The following lines are auto generated by the script mkerr.pl. Any changes + * made after this point may be overwritten when the script is next run. + */ + +/* Error codes for the RAND functions. */ + +/* Function codes. */ +#define RAND_F_SSLEAY_RAND_BYTES 100 + +/* Reason codes. */ +#define RAND_R_PRNG_NOT_SEEDED 100 + +#ifdef __cplusplus +} +#endif +#endif + diff --git a/libsecurity_apple_csp/open_ssl/openssl/rc2.h b/libsecurity_apple_csp/open_ssl/openssl/rc2.h new file mode 100644 index 00000000..563365e0 --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/openssl/rc2.h @@ -0,0 +1,123 @@ +/* + * 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. + */ + + +/* crypto/rc2/rc2.h */ +/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef HEADER_RC2_H +#define HEADER_RC2_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef NO_RC2 +#error RC2 is disabled. +#endif + +#define RC2_ENCRYPT 1 +#define RC2_DECRYPT 0 + +#include /* RC2_INT */ +#define RC2_BLOCK_SIZE_BYTES 8 +#define RC2_MIN_KEY_SIZE_BYTES 1 +#define RC2_MAX_KEY_SIZE_BYTES 128 + +typedef struct rc2_key_st + { + RC2_INT data[64]; + } RC2_KEY; + + +void RC2_set_key(RC2_KEY *key, int len, unsigned char *data,int bits); +#ifdef _OPENSSL_APPLE_CDSA_ +void RC2_encrypt(RC2_INT *data,RC2_KEY *key); +void RC2_decrypt(RC2_INT *data,RC2_KEY *key); +#else +void RC2_encrypt(unsigned long *data,RC2_KEY *key); +void RC2_decrypt(unsigned long *data,RC2_KEY *key); +void RC2_ecb_encrypt(unsigned char *in,unsigned char *out,RC2_KEY *key, + int enc); +void RC2_cbc_encrypt(unsigned char *in, unsigned char *out, long length, + RC2_KEY *ks, unsigned char *iv, int enc); +void RC2_cfb64_encrypt(unsigned char *in, unsigned char *out, long length, + RC2_KEY *schedule, unsigned char *ivec, int *num, int enc); +void RC2_ofb64_encrypt(unsigned char *in, unsigned char *out, long length, + RC2_KEY *schedule, unsigned char *ivec, int *num); +#endif /* _OPENSSL_APPLE_CDSA_ */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libsecurity_apple_csp/open_ssl/openssl/rc5.h b/libsecurity_apple_csp/open_ssl/openssl/rc5.h new file mode 100644 index 00000000..123374b5 --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/openssl/rc5.h @@ -0,0 +1,150 @@ +/* + * 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. + */ + + +/* crypto/rc5/rc5.h */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef HEADER_RC5_H +#define HEADER_RC5_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef NO_RC5 +#error RC5 is disabled. +#endif + +#define RC5_ENCRYPT 1 +#define RC5_DECRYPT 0 + +#include /* RC5_INT */ + +#ifdef _OPENSSL_APPLE_CDSA_ + +#define RC5_BLOCK_SIZE_BYTES 8 +#define RC5_MIN_KEY_SIZE_BYTES 1 +#define RC5_MAX_KEY_SIZE_BYTES 255 + +#else + +/* 32 bit. For Alpha, things may get weird */ +#define RC5_32_INT unsigned long + +#define RC5_32_BLOCK 8 +#define RC5_32_KEY_LENGTH 16 /* This is a default, max is 255 */ + +#endif /* _OPENSSL_APPLE_CDSA_ */ + +/* This are the only values supported. Tweak the code if you want more + * The most supported modes will be + * RC5-32/12/16 + * RC5-32/16/8 + */ +#define RC5_8_ROUNDS 8 +#define RC5_12_ROUNDS 12 +#define RC5_16_ROUNDS 16 + +typedef struct rc5_key_st + { + /* Number of rounds */ + int rounds; + RC5_32_INT data[2*(RC5_16_ROUNDS+1)]; + } RC5_32_KEY; + + +void RC5_32_set_key(RC5_32_KEY *key, int len, unsigned char *data, + int rounds); + +#ifdef _OPENSSL_APPLE_CDSA_ +void RC5_32_encrypt(RC5_32_INT *data,RC5_32_KEY *key); +void RC5_32_decrypt(RC5_32_INT *data,RC5_32_KEY *key); +#else +void RC5_32_ecb_encrypt(unsigned char *in,unsigned char *out,RC5_32_KEY *key, + int enc); +void RC5_32_encrypt(unsigned long *data,RC5_32_KEY *key); +void RC5_32_decrypt(unsigned long *data,RC5_32_KEY *key); +void RC5_32_cbc_encrypt(unsigned char *in, unsigned char *out, long length, + RC5_32_KEY *ks, unsigned char *iv, int enc); +void RC5_32_cfb64_encrypt(unsigned char *in, unsigned char *out, long length, + RC5_32_KEY *schedule, unsigned char *ivec, int *num, int enc); +void RC5_32_ofb64_encrypt(unsigned char *in, unsigned char *out, long length, + RC5_32_KEY *schedule, unsigned char *ivec, int *num); + +#endif /* _OPENSSL_APPLE_CDSA_ */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libsecurity_apple_csp/open_ssl/openssl/rsa.h b/libsecurity_apple_csp/open_ssl/openssl/rsa.h new file mode 100644 index 00000000..b103eda0 --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/openssl/rsa.h @@ -0,0 +1,364 @@ +/* + * 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. + */ + + +/* crypto/rsa/rsa.h */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef HEADER_RSA_H +#define HEADER_RSA_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +#ifdef NO_RSA +#error RSA is disabled. +#endif + +typedef struct rsa_st RSA; + +typedef struct rsa_meth_st + { + const char *name; + int (*rsa_pub_enc)(int flen,unsigned char *from,unsigned char *to, + RSA *rsa,int padding); + int (*rsa_pub_dec)(int flen,unsigned char *from,unsigned char *to, + RSA *rsa,int padding); + int (*rsa_priv_enc)(int flen,unsigned char *from,unsigned char *to, + RSA *rsa,int padding); + int (*rsa_priv_dec)(int flen,unsigned char *from,unsigned char *to, + RSA *rsa,int padding); + int (*rsa_mod_exp)(BIGNUM *r0,BIGNUM *I,RSA *rsa); /* Can be null */ + int (*bn_mod_exp)(BIGNUM *r, BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx, + BN_MONT_CTX *m_ctx); /* Can be null */ + int (*init)(RSA *rsa); /* called at new */ + int (*finish)(RSA *rsa); /* called at free */ + int flags; /* RSA_METHOD_FLAG_* things */ + char *app_data; /* may be needed! */ +/* New sign and verify functions: some libraries don't allow arbitrary data + * to be signed/verified: this allows them to be used. Note: for this to work + * the RSA_public_decrypt() and RSA_private_encrypt() should *NOT* be used + * RSA_sign(), RSA_verify() should be used instead. Note: for backwards + * compatibility this functionality is only enabled if the RSA_FLAG_SIGN_VER + * option is set in 'flags'. + */ + int (*rsa_sign)(int type, unsigned char *m, unsigned int m_len, + unsigned char *sigret, unsigned int *siglen, RSA *rsa); + int (*rsa_verify)(int dtype, unsigned char *m, unsigned int m_len, + unsigned char *sigbuf, unsigned int siglen, RSA *rsa); + + } RSA_METHOD; + +struct BN_BLINDING_STRUCT; + +struct rsa_st + { + /* The first parameter is used to pickup errors where + * this is passed instead of aEVP_PKEY, it is set to 0 */ + int pad; + int version; + const RSA_METHOD *meth; + BIGNUM *n; + BIGNUM *e; + BIGNUM *d; + BIGNUM *p; + BIGNUM *q; + BIGNUM *dmp1; + BIGNUM *dmq1; + BIGNUM *iqmp; + /* be careful using this if the RSA structure is shared */ + CRYPTO_EX_DATA ex_data; + int references; + int flags; + + /* Used to cache montgomery values */ + BN_MONT_CTX *_method_mod_n; + BN_MONT_CTX *_method_mod_p; + BN_MONT_CTX *_method_mod_q; + + /* all BIGNUM values are actually in the following data, if it is not + * NULL */ + char *bignum_data; + int num_blinding_threads; + pthread_mutex_t blinding_mutex; + struct BN_BLINDING_STRUCT *blinding_array; + }; + +#define RSA_3 0x3L +#define RSA_F4 0x10001L + +#define RSA_METHOD_FLAG_NO_CHECK 0x01 /* don't check pub/private match */ + +#define RSA_FLAG_CACHE_PUBLIC 0x02 +#define RSA_FLAG_CACHE_PRIVATE 0x04 +#define RSA_FLAG_BLINDING 0x08 +#define RSA_FLAG_THREAD_SAFE 0x10 +/* This flag means the private key operations will be handled by rsa_mod_exp + * and that they do not depend on the private key components being present: + * for example a key stored in external hardware. Without this flag bn_mod_exp + * gets called when private key components are absent. + */ +#define RSA_FLAG_EXT_PKEY 0x20 + +/* This flag in the RSA_METHOD enables the new rsa_sign, rsa_verify functions. + */ +#define RSA_FLAG_SIGN_VER 0x40 + +#define RSA_PKCS1_PADDING 1 +#define RSA_SSLV23_PADDING 2 +#define RSA_NO_PADDING 3 +#define RSA_PKCS1_OAEP_PADDING 4 + +#define RSA_set_app_data(s,arg) RSA_set_ex_data(s,0,arg) +#define RSA_get_app_data(s) RSA_get_ex_data(s,0) + +RSA * RSA_new(void); +RSA * RSA_new_method(const RSA_METHOD *method); +int RSA_size(RSA *); +RSA * RSA_generate_key(int bits, unsigned long e,void + (*callback)(int,int,void *),void *cb_arg); +int RSA_check_key(RSA *); + /* next 4 return -1 on error */ +int RSA_public_encrypt(int flen, unsigned char *from, + unsigned char *to, RSA *rsa,int padding); +int RSA_private_encrypt(int flen, unsigned char *from, + unsigned char *to, RSA *rsa,int padding); +int RSA_public_decrypt(int flen, unsigned char *from, + unsigned char *to, RSA *rsa,int padding); +int RSA_private_decrypt(int flen, unsigned char *from, + unsigned char *to, RSA *rsa,int padding); +void RSA_free (RSA *r); + +int RSA_flags(RSA *r); + +void RSA_set_default_method(const RSA_METHOD *meth); +const RSA_METHOD *RSA_get_default_method(void); +const RSA_METHOD *RSA_get_method(RSA *rsa); +const RSA_METHOD *RSA_set_method(RSA *rsa, const RSA_METHOD *meth); + +/* This function needs the memory locking malloc callbacks to be installed */ +int RSA_memory_lock(RSA *r); + +/* If you have RSAref compiled in. */ +const RSA_METHOD *RSA_PKCS1_RSAref(void); + +/* these are the actual SSLeay RSA functions */ +const RSA_METHOD *RSA_PKCS1_SSLeay(void); + +const RSA_METHOD *RSA_null_method(void); + +void ERR_load_RSA_strings(void ); + +RSA * d2i_RSAPublicKey(RSA **a, unsigned char **pp, long length); +int i2d_RSAPublicKey(RSA *a, unsigned char **pp); +RSA * d2i_RSAPrivateKey(RSA **a, unsigned char **pp, long length); +int i2d_RSAPrivateKey(RSA *a, unsigned char **pp); +#ifndef NO_FP_API +int RSA_print_fp(FILE *fp, RSA *r,int offset); +#endif + +#ifdef HEADER_BIO_H +int RSA_print(BIO *bp, RSA *r,int offset); +#endif + +int i2d_Netscape_RSA(RSA *a, unsigned char **pp, int (*cb)()); +RSA *d2i_Netscape_RSA(RSA **a, unsigned char **pp, long length, int (*cb)()); +/* Naughty internal function required elsewhere, to handle a MS structure + * that is the same as the netscape one :-) */ +RSA *d2i_Netscape_RSA_2(RSA **a, unsigned char **pp, long length, int (*cb)()); + +/* The following 2 functions sign and verify a X509_SIG ASN1 object + * inside PKCS#1 padded RSA encryption */ +int RSA_sign(int type, unsigned char *m, unsigned int m_len, + unsigned char *sigret, unsigned int *siglen, RSA *rsa); +int RSA_verify(int type, unsigned char *m, unsigned int m_len, + unsigned char *sigbuf, unsigned int siglen, RSA *rsa); + +/* The following 2 function sign and verify a ASN1_OCTET_STRING + * object inside PKCS#1 padded RSA encryption */ +int RSA_sign_ASN1_OCTET_STRING(int type, unsigned char *m, unsigned int m_len, + unsigned char *sigret, unsigned int *siglen, RSA *rsa); +int RSA_verify_ASN1_OCTET_STRING(int type, unsigned char *m, unsigned int m_len, + unsigned char *sigbuf, unsigned int siglen, RSA *rsa); + +int RSA_blinding_on(RSA *rsa, BN_CTX *ctx); +void RSA_blinding_off(RSA *rsa); + +int RSA_padding_add_PKCS1_type_1(unsigned char *to,int tlen, + unsigned char *f,int fl); +int RSA_padding_check_PKCS1_type_1(unsigned char *to,int tlen, + unsigned char *f,int fl,int rsa_len); +int RSA_padding_add_PKCS1_type_2(unsigned char *to,int tlen, + unsigned char *f,int fl); +int RSA_padding_check_PKCS1_type_2(unsigned char *to,int tlen, + unsigned char *f,int fl,int rsa_len); +int RSA_padding_add_PKCS1_OAEP(unsigned char *to,int tlen, + unsigned char *f,int fl,unsigned char *p, + int pl); +int RSA_padding_check_PKCS1_OAEP(unsigned char *to,int tlen, + unsigned char *f,int fl,int rsa_len, + unsigned char *p,int pl); +int RSA_padding_add_SSLv23(unsigned char *to,int tlen, + unsigned char *f,int fl); +int RSA_padding_check_SSLv23(unsigned char *to,int tlen, + unsigned char *f,int fl,int rsa_len); +int RSA_padding_add_none(unsigned char *to,int tlen, + unsigned char *f,int fl); +int RSA_padding_check_none(unsigned char *to,int tlen, + unsigned char *f,int fl,int rsa_len); + +int RSA_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, + CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func); +int RSA_set_ex_data(RSA *r,int idx,void *arg); +void *RSA_get_ex_data(RSA *r, int idx); + +BN_BLINDING* RSA_get_thread_blinding_ptr(RSA *r); +void RSA_set_thread_blinding_ptr(RSA *r, BN_BLINDING* bnb); +void RSA_free_thread_blinding_ptr(RSA* r); + +/* BEGIN ERROR CODES */ +/* The following lines are auto generated by the script mkerr.pl. Any changes + * made after this point may be overwritten when the script is next run. + */ + +/* Error codes for the RSA functions. */ + +/* Function codes. */ +#define RSA_F_MEMORY_LOCK 100 +#define RSA_F_RSA_CHECK_KEY 123 +#define RSA_F_RSA_EAY_PRIVATE_DECRYPT 101 +#define RSA_F_RSA_EAY_PRIVATE_ENCRYPT 102 +#define RSA_F_RSA_EAY_PUBLIC_DECRYPT 103 +#define RSA_F_RSA_EAY_PUBLIC_ENCRYPT 104 +#define RSA_F_RSA_GENERATE_KEY 105 +#define RSA_F_RSA_NEW_METHOD 106 +#define RSA_F_RSA_NULL 124 +#define RSA_F_RSA_PADDING_ADD_NONE 107 +#define RSA_F_RSA_PADDING_ADD_PKCS1_OAEP 121 +#define RSA_F_RSA_PADDING_ADD_PKCS1_TYPE_1 108 +#define RSA_F_RSA_PADDING_ADD_PKCS1_TYPE_2 109 +#define RSA_F_RSA_PADDING_ADD_SSLV23 110 +#define RSA_F_RSA_PADDING_CHECK_NONE 111 +#define RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP 122 +#define RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_1 112 +#define RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_2 113 +#define RSA_F_RSA_PADDING_CHECK_SSLV23 114 +#define RSA_F_RSA_PRINT 115 +#define RSA_F_RSA_PRINT_FP 116 +#define RSA_F_RSA_SIGN 117 +#define RSA_F_RSA_SIGN_ASN1_OCTET_STRING 118 +#define RSA_F_RSA_VERIFY 119 +#define RSA_F_RSA_VERIFY_ASN1_OCTET_STRING 120 + +/* Reason codes. */ +#define RSA_R_ALGORITHM_MISMATCH 100 +#define RSA_R_BAD_E_VALUE 101 +#define RSA_R_BAD_FIXED_HEADER_DECRYPT 102 +#define RSA_R_BAD_PAD_BYTE_COUNT 103 +#define RSA_R_BAD_SIGNATURE 104 +#define RSA_R_BLOCK_TYPE_IS_NOT_01 106 +#define RSA_R_BLOCK_TYPE_IS_NOT_02 107 +#define RSA_R_DATA_GREATER_THAN_MOD_LEN 108 +#define RSA_R_DATA_TOO_LARGE 109 +#define RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE 110 +#define RSA_R_DATA_TOO_SMALL 111 +#define RSA_R_DATA_TOO_SMALL_FOR_KEY_SIZE 122 +#define RSA_R_DIGEST_TOO_BIG_FOR_RSA_KEY 112 +#define RSA_R_DMP1_NOT_CONGRUENT_TO_D 124 +#define RSA_R_DMQ1_NOT_CONGRUENT_TO_D 125 +#define RSA_R_D_E_NOT_CONGRUENT_TO_1 123 +#define RSA_R_INVALID_MESSAGE_LENGTH 131 +#define RSA_R_IQMP_NOT_INVERSE_OF_Q 126 +#define RSA_R_KEY_SIZE_TOO_SMALL 120 +#define RSA_R_NULL_BEFORE_BLOCK_MISSING 113 +#define RSA_R_N_DOES_NOT_EQUAL_P_Q 127 +#define RSA_R_OAEP_DECODING_ERROR 121 +#define RSA_R_PADDING_CHECK_FAILED 114 +#define RSA_R_P_NOT_PRIME 128 +#define RSA_R_Q_NOT_PRIME 129 +#define RSA_R_RSA_OPERATIONS_NOT_SUPPORTED 130 +#define RSA_R_SSLV3_ROLLBACK_ATTACK 115 +#define RSA_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD 116 +#define RSA_R_UNKNOWN_ALGORITHM_TYPE 117 +#define RSA_R_UNKNOWN_PADDING_TYPE 118 +#define RSA_R_WRONG_SIGNATURE_LENGTH 119 + +#ifdef __cplusplus +} +#endif +#endif + diff --git a/libsecurity_apple_csp/open_ssl/openssl/safestack.h b/libsecurity_apple_csp/open_ssl/openssl/safestack.h new file mode 100644 index 00000000..ce7d3cf5 --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/openssl/safestack.h @@ -0,0 +1,147 @@ +/* + * 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. + */ + + +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#ifndef HEADER_SAFESTACK_H +#define HEADER_SAFESTACK_H + +#include + +#define STACK_OF(type) STACK_##type + +#define DECLARE_STACK_OF(type) \ +typedef struct stack_st_##type \ + { \ + STACK stack; \ + } STACK_OF(type); \ +STACK_OF(type) *sk_##type##_new(int (*cmp)(type **,type **)); \ +STACK_OF(type) *sk_##type##_new_null(void); \ +void sk_##type##_free(STACK_OF(type) *sk); \ +int sk_##type##_num(const STACK_OF(type) *sk); \ +type *sk_##type##_value(const STACK_OF(type) *sk,int n); \ +type *sk_##type##_set(STACK_OF(type) *sk,int n,type *v); \ +void sk_##type##_zero(STACK_OF(type) *sk); \ +int sk_##type##_push(STACK_OF(type) *sk,type *v); \ +int sk_##type##_unshift(STACK_OF(type) *sk,type *v); \ +int sk_##type##_find(STACK_OF(type) *sk,type *v); \ +type *sk_##type##_delete(STACK_OF(type) *sk,int n); \ +void sk_##type##_delete_ptr(STACK_OF(type) *sk,type *v); \ +int sk_##type##_insert(STACK_OF(type) *sk,type *v,int n); \ +int (*sk_##type##_set_cmp_func(STACK_OF(type) *sk, \ + int (*cmp)(type **,type **)))(type **,type **); \ +STACK_OF(type) *sk_##type##_dup(STACK_OF(type) *sk); \ +void sk_##type##_pop_free(STACK_OF(type) *sk,void (*func)(type *)); \ +type *sk_##type##_shift(STACK_OF(type) *sk); \ +type *sk_##type##_pop(STACK_OF(type) *sk); \ +void sk_##type##_sort(STACK_OF(type) *sk); + +#define IMPLEMENT_STACK_OF(type) \ +STACK_OF(type) *sk_##type##_new(int (*cmp)(type **,type **)) \ + { return (STACK_OF(type) *)sk_new(cmp); } \ +STACK_OF(type) *sk_##type##_new_null() \ + { return (STACK_OF(type) *)sk_new_null(); } \ +void sk_##type##_free(STACK_OF(type) *sk) \ + { sk_free((STACK *)sk); } \ +int sk_##type##_num(const STACK_OF(type) *sk) \ + { return M_sk_num((const STACK *)sk); } \ +type *sk_##type##_value(const STACK_OF(type) *sk,int n) \ + { return (type *)sk_value((STACK *)sk,n); } \ +type *sk_##type##_set(STACK_OF(type) *sk,int n,type *v) \ + { return (type *)(sk_set((STACK *)sk,n,(char *)v)); } \ +void sk_##type##_zero(STACK_OF(type) *sk) \ + { sk_zero((STACK *)sk); } \ +int sk_##type##_push(STACK_OF(type) *sk,type *v) \ + { return sk_push((STACK *)sk,(char *)v); } \ +int sk_##type##_unshift(STACK_OF(type) *sk,type *v) \ + { return sk_unshift((STACK *)sk,(char *)v); } \ +int sk_##type##_find(STACK_OF(type) *sk,type *v) \ + { return sk_find((STACK *)sk,(char *)v); } \ +type *sk_##type##_delete(STACK_OF(type) *sk,int n) \ + { return (type *)sk_delete((STACK *)sk,n); } \ +void sk_##type##_delete_ptr(STACK_OF(type) *sk,type *v) \ + { sk_delete_ptr((STACK *)sk,(char *)v); } \ +int sk_##type##_insert(STACK_OF(type) *sk,type *v,int n) \ + { return sk_insert((STACK *)sk,(char *)v,n); } \ +int (*sk_##type##_set_cmp_func(STACK_OF(type) *sk, \ + int (*cmp)(type **,type **)))(type **,type **) \ + { return (int (*)(type **,type **))sk_set_cmp_func((STACK *)sk,cmp); } \ +STACK_OF(type) *sk_##type##_dup(STACK_OF(type) *sk) \ + { return (STACK_OF(type) *)sk_dup((STACK *)sk); } \ +void sk_##type##_pop_free(STACK_OF(type) *sk,void (*func)(type *)) \ + { sk_pop_free((STACK *)sk,func); } \ +type *sk_##type##_shift(STACK_OF(type) *sk) \ + { return (type *)sk_shift((STACK *)sk); } \ +type *sk_##type##_pop(STACK_OF(type) *sk) \ + { return (type *)sk_pop((STACK *)sk); } \ +void sk_##type##_sort(STACK_OF(type) *sk) \ + { sk_sort((STACK *)sk); } + +#endif /* ndef HEADER_SAFESTACK_H */ diff --git a/libsecurity_apple_csp/open_ssl/openssl/stack.h b/libsecurity_apple_csp/open_ssl/openssl/stack.h new file mode 100644 index 00000000..d126b5b1 --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/openssl/stack.h @@ -0,0 +1,125 @@ +/* + * 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. + */ + + +/* crypto/stack/stack.h */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef HEADER_STACK_H +#define HEADER_STACK_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct stack_st + { + int num; + char **data; + int sorted; + + int num_alloc; + int (*comp)(); + } STACK; + + +#define sk_new_null() sk_new(NULL) + +#define M_sk_num(sk) ((sk) ? (sk)->num:-1) +#define M_sk_value(sk,n) ((sk) ? (sk)->data[n] : NULL) + +int sk_num(STACK *); +char *sk_value(STACK *, int); + +char *sk_set(STACK *, int, char *); + +STACK *sk_new(int (*cmp)()); +void sk_free(STACK *); +void sk_pop_free(STACK *st, void (*func)()); +int sk_insert(STACK *sk,char *data,int where); +char *sk_delete(STACK *st,int loc); +char *sk_delete_ptr(STACK *st, char *p); +int sk_find(STACK *st,char *data); +int sk_push(STACK *st,char *data); +int sk_unshift(STACK *st,char *data); +char *sk_shift(STACK *st); +char *sk_pop(STACK *st); +void sk_zero(STACK *st); +int (*sk_set_cmp_func(STACK *sk, int (*c)()))(); +STACK *sk_dup(STACK *st); +void sk_sort(STACK *st); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libsecurity_apple_csp/open_ssl/openssl/x509.h b/libsecurity_apple_csp/open_ssl/openssl/x509.h new file mode 100644 index 00000000..b9cc05dd --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/openssl/x509.h @@ -0,0 +1,1222 @@ +/* + * 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. + */ + + +/* crypto/x509/x509.h */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef HEADER_X509_H +#define HEADER_X509_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef VMS +#undef X509_REVOKED_get_ext_by_critical +#define X509_REVOKED_get_ext_by_critical X509_REVOKED_get_ext_by_critic +#endif + +#include +#include +#include + +#ifndef NO_RSA +#include +#endif + +#ifndef NO_DSA +#include +#endif + +#ifndef NO_DH +#include +#endif + +#include + + +#ifdef WIN32 +/* Under Win32 this is defined in wincrypt.h */ +#undef X509_NAME +#endif + +#define X509_FILETYPE_PEM 1 +#define X509_FILETYPE_ASN1 2 +#define X509_FILETYPE_DEFAULT 3 + +#define X509v3_KU_DIGITAL_SIGNATURE 0x0080 +#define X509v3_KU_NON_REPUDIATION 0x0040 +#define X509v3_KU_KEY_ENCIPHERMENT 0x0020 +#define X509v3_KU_DATA_ENCIPHERMENT 0x0010 +#define X509v3_KU_KEY_AGREEMENT 0x0008 +#define X509v3_KU_KEY_CERT_SIGN 0x0004 +#define X509v3_KU_CRL_SIGN 0x0002 +#define X509v3_KU_ENCIPHER_ONLY 0x0001 +#define X509v3_KU_DECIPHER_ONLY 0x8000 +#define X509v3_KU_UNDEF 0xffff + +typedef struct X509_objects_st + { + int nid; + int (*a2i)(); + int (*i2a)(); + } X509_OBJECTS; + +typedef struct X509_algor_st + { + ASN1_OBJECT *algorithm; + ASN1_TYPE *parameter; + } X509_ALGOR; + +DECLARE_STACK_OF(X509_ALGOR) +DECLARE_ASN1_SET_OF(X509_ALGOR) + +typedef struct X509_val_st + { + ASN1_UTCTIME *notBefore; + ASN1_UTCTIME *notAfter; + } X509_VAL; + +typedef struct X509_pubkey_st + { + X509_ALGOR *algor; + ASN1_BIT_STRING *public_key; + EVP_PKEY *pkey; + } X509_PUBKEY; + +typedef struct X509_sig_st + { + X509_ALGOR *algor; + ASN1_OCTET_STRING *digest; + } X509_SIG; + +typedef struct X509_name_entry_st + { + ASN1_OBJECT *object; + ASN1_STRING *value; + int set; + int size; /* temp variable */ + } X509_NAME_ENTRY; + +DECLARE_STACK_OF(X509_NAME_ENTRY) +DECLARE_ASN1_SET_OF(X509_NAME_ENTRY) + +/* we always keep X509_NAMEs in 2 forms. */ +typedef struct X509_name_st + { + STACK_OF(X509_NAME_ENTRY) *entries; + int modified; /* true if 'bytes' needs to be built */ +#ifdef HEADER_BUFFER_H + BUF_MEM *bytes; +#else + char *bytes; +#endif + unsigned long hash; /* Keep the hash around for lookups */ + } X509_NAME; + +DECLARE_STACK_OF(X509_NAME) + +#define X509_EX_V_NETSCAPE_HACK 0x8000 +#define X509_EX_V_INIT 0x0001 +typedef struct X509_extension_st + { + ASN1_OBJECT *object; + short critical; + short netscape_hack; + ASN1_OCTET_STRING *value; + struct v3_ext_method *method; /* V3 method to use */ + void *ext_val; /* extension value */ + } X509_EXTENSION; + +DECLARE_STACK_OF(X509_EXTENSION) +DECLARE_ASN1_SET_OF(X509_EXTENSION) + +/* a sequence of these are used */ +typedef struct x509_attributes_st + { + ASN1_OBJECT *object; + int set; /* 1 for a set, 0 for a single item (which is wrong) */ + union { + char *ptr; +/* 1 */ STACK_OF(ASN1_TYPE) *set; +/* 0 */ ASN1_TYPE *single; + } value; + } X509_ATTRIBUTE; + +DECLARE_STACK_OF(X509_ATTRIBUTE) +DECLARE_ASN1_SET_OF(X509_ATTRIBUTE) + +typedef struct X509_req_info_st + { + ASN1_INTEGER *version; + X509_NAME *subject; + X509_PUBKEY *pubkey; + /* d=2 hl=2 l= 0 cons: cont: 00 */ + STACK_OF(X509_ATTRIBUTE) *attributes; /* [ 0 ] */ + int req_kludge; + } X509_REQ_INFO; + +typedef struct X509_req_st + { + X509_REQ_INFO *req_info; + X509_ALGOR *sig_alg; + ASN1_BIT_STRING *signature; + int references; + } X509_REQ; + +typedef struct x509_cinf_st + { + ASN1_INTEGER *version; /* [ 0 ] default of v1 */ + ASN1_INTEGER *serialNumber; + X509_ALGOR *signature; + X509_NAME *issuer; + X509_VAL *validity; + X509_NAME *subject; + X509_PUBKEY *key; + ASN1_BIT_STRING *issuerUID; /* [ 1 ] optional in v2 */ + ASN1_BIT_STRING *subjectUID; /* [ 2 ] optional in v2 */ + STACK_OF(X509_EXTENSION) *extensions; /* [ 3 ] optional in v3 */ + } X509_CINF; + +/* This stuff is certificate "auxiliary info" + * it contains details which are useful in certificate + * stores and databases. When used this is tagged onto + * the end of the certificate itself + */ + +typedef struct x509_cert_aux_st + { + STACK_OF(ASN1_OBJECT) *trust; /* trusted uses */ + STACK_OF(ASN1_OBJECT) *reject; /* rejected uses */ + ASN1_UTF8STRING *alias; /* "friendly name" */ + ASN1_OCTET_STRING *keyid; /* key id of private key */ + STACK_OF(X509_ALGOR) *other; /* other unspecified info */ + } X509_CERT_AUX; + +typedef struct x509_st + { + X509_CINF *cert_info; + X509_ALGOR *sig_alg; + ASN1_BIT_STRING *signature; + int valid; + int references; + char *name; + CRYPTO_EX_DATA ex_data; + /* These contain copies of various extension values */ + long ex_pathlen; + unsigned long ex_flags; + unsigned long ex_kusage; + unsigned long ex_xkusage; + unsigned long ex_nscert; +#ifndef NO_SHA + unsigned char sha1_hash[SHA_DIGEST_LENGTH]; +#endif + X509_CERT_AUX *aux; + } X509; + +DECLARE_STACK_OF(X509) +DECLARE_ASN1_SET_OF(X509) + +/* This is used for a table of trust checking functions */ + +typedef struct x509_trust_st { + int trust; + int flags; + int (*check_trust)(struct x509_trust_st *, X509 *, int); + char *name; + int arg1; + void *arg2; +} X509_TRUST; + +DECLARE_STACK_OF(X509_TRUST) + +/* standard trust ids */ + +#define X509_TRUST_DEFAULT -1 /* Only valid in purpose settings */ + +#define X509_TRUST_COMPAT 1 +#define X509_TRUST_SSL_CLIENT 2 +#define X509_TRUST_SSL_SERVER 3 +#define X509_TRUST_EMAIL 4 +#define X509_TRUST_OBJECT_SIGN 5 + +/* Keep these up to date! */ +#define X509_TRUST_MIN 1 +#define X509_TRUST_MAX 5 + + +/* trust_flags values */ +#define X509_TRUST_DYNAMIC 1 +#define X509_TRUST_DYNAMIC_NAME 2 + +/* check_trust return codes */ + +#define X509_TRUST_TRUSTED 1 +#define X509_TRUST_REJECTED 2 +#define X509_TRUST_UNTRUSTED 3 + +typedef struct X509_revoked_st + { + ASN1_INTEGER *serialNumber; + ASN1_UTCTIME *revocationDate; + STACK_OF(X509_EXTENSION) /* optional */ *extensions; + int sequence; /* load sequence */ + } X509_REVOKED; + +DECLARE_STACK_OF(X509_REVOKED) +DECLARE_ASN1_SET_OF(X509_REVOKED) + +typedef struct X509_crl_info_st + { + ASN1_INTEGER *version; + X509_ALGOR *sig_alg; + X509_NAME *issuer; + ASN1_UTCTIME *lastUpdate; + ASN1_UTCTIME *nextUpdate; + STACK_OF(X509_REVOKED) *revoked; + STACK_OF(X509_EXTENSION) /* [0] */ *extensions; + } X509_CRL_INFO; + +typedef struct X509_crl_st + { + /* actual signature */ + X509_CRL_INFO *crl; + X509_ALGOR *sig_alg; + ASN1_BIT_STRING *signature; + int references; + } X509_CRL; + +DECLARE_STACK_OF(X509_CRL) +DECLARE_ASN1_SET_OF(X509_CRL) + +typedef struct private_key_st + { + int version; + /* The PKCS#8 data types */ + X509_ALGOR *enc_algor; + ASN1_OCTET_STRING *enc_pkey; /* encrypted pub key */ + + /* When decrypted, the following will not be NULL */ + EVP_PKEY *dec_pkey; + + /* used to encrypt and decrypt */ + int key_length; + char *key_data; + int key_free; /* true if we should auto free key_data */ + + /* expanded version of 'enc_algor' */ + EVP_CIPHER_INFO cipher; + + int references; + } X509_PKEY; + +#ifdef HEADER_ENVELOPE_H +typedef struct X509_info_st + { + X509 *x509; + X509_CRL *crl; + X509_PKEY *x_pkey; + + EVP_CIPHER_INFO enc_cipher; + int enc_len; + char *enc_data; + + int references; + } X509_INFO; + +DECLARE_STACK_OF(X509_INFO) +#endif + +/* The next 2 structures and their 8 routines were sent to me by + * Pat Richard and are used to manipulate + * Netscapes spki structures - useful if you are writing a CA web page + */ +typedef struct Netscape_spkac_st + { + X509_PUBKEY *pubkey; + ASN1_IA5STRING *challenge; /* challenge sent in atlas >= PR2 */ + } NETSCAPE_SPKAC; + +typedef struct Netscape_spki_st + { + NETSCAPE_SPKAC *spkac; /* signed public key and challenge */ + X509_ALGOR *sig_algor; + ASN1_BIT_STRING *signature; + } NETSCAPE_SPKI; + +/* Netscape certificate sequence structure */ +typedef struct Netscape_certificate_sequence + { + ASN1_OBJECT *type; + STACK_OF(X509) *certs; + } NETSCAPE_CERT_SEQUENCE; + +typedef struct CBCParameter_st + { + unsigned char iv[8]; + } CBC_PARAM; + +/* Password based encryption structure */ + +typedef struct PBEPARAM_st { +ASN1_OCTET_STRING *salt; +ASN1_INTEGER *iter; +} PBEPARAM; + +/* Password based encryption V2 structures */ + +typedef struct PBE2PARAM_st { +X509_ALGOR *keyfunc; +X509_ALGOR *encryption; +} PBE2PARAM; + +typedef struct PBKDF2PARAM_st { +ASN1_TYPE *salt; /* Usually OCTET STRING but could be anything */ +ASN1_INTEGER *iter; +ASN1_INTEGER *keylength; +X509_ALGOR *prf; +} PBKDF2PARAM; + + +/* PKCS#8 private key info structure */ + +typedef struct pkcs8_priv_key_info_st + { + int broken; /* Flag for various broken formats */ +#define PKCS8_OK 0 +#define PKCS8_NO_OCTET 1 +#define PKCS8_EMBEDDED_PARAM 2 +#define PKCS8_NS_DB 3 + ASN1_INTEGER *version; + X509_ALGOR *pkeyalg; + ASN1_TYPE *pkey; /* Should be OCTET STRING but some are broken */ + STACK_OF(X509_ATTRIBUTE) *attributes; + } PKCS8_PRIV_KEY_INFO; + +#include +#include + +#ifdef SSLEAY_MACROS +#define X509_verify(a,r) ASN1_verify((int (*)())i2d_X509_CINF,a->sig_alg,\ + a->signature,(char *)a->cert_info,r) +#define X509_REQ_verify(a,r) ASN1_verify((int (*)())i2d_X509_REQ_INFO, \ + a->sig_alg,a->signature,(char *)a->req_info,r) +#define X509_CRL_verify(a,r) ASN1_verify((int (*)())i2d_X509_CRL_INFO, \ + a->sig_alg, a->signature,(char *)a->crl,r) + +#define X509_sign(x,pkey,md) \ + ASN1_sign((int (*)())i2d_X509_CINF, x->cert_info->signature, \ + x->sig_alg, x->signature, (char *)x->cert_info,pkey,md) +#define X509_REQ_sign(x,pkey,md) \ + ASN1_sign((int (*)())i2d_X509_REQ_INFO,x->sig_alg, NULL, \ + x->signature, (char *)x->req_info,pkey,md) +#define X509_CRL_sign(x,pkey,md) \ + ASN1_sign((int (*)())i2d_X509_CRL_INFO,x->crl->sig_alg,x->sig_alg, \ + x->signature, (char *)x->crl,pkey,md) +#define NETSCAPE_SPKI_sign(x,pkey,md) \ + ASN1_sign((int (*)())i2d_NETSCAPE_SPKAC, x->sig_algor,NULL, \ + x->signature, (char *)x->spkac,pkey,md) + +#define X509_dup(x509) (X509 *)ASN1_dup((int (*)())i2d_X509, \ + (char *(*)())d2i_X509,(char *)x509) +#define X509_ATTRIBUTE_dup(xa) (X509_ATTRIBUTE *)ASN1_dup(\ + (int (*)())i2d_X509_ATTRIBUTE, \ + (char *(*)())d2i_X509_ATTRIBUTE,(char *)xa) +#define X509_EXTENSION_dup(ex) (X509_EXTENSION *)ASN1_dup( \ + (int (*)())i2d_X509_EXTENSION, \ + (char *(*)())d2i_X509_EXTENSION,(char *)ex) +#define d2i_X509_fp(fp,x509) (X509 *)ASN1_d2i_fp((char *(*)())X509_new, \ + (char *(*)())d2i_X509, (fp),(unsigned char **)(x509)) +#define i2d_X509_fp(fp,x509) ASN1_i2d_fp(i2d_X509,fp,(unsigned char *)x509) +#define d2i_X509_bio(bp,x509) (X509 *)ASN1_d2i_bio((char *(*)())X509_new, \ + (char *(*)())d2i_X509, (bp),(unsigned char **)(x509)) +#define i2d_X509_bio(bp,x509) ASN1_i2d_bio(i2d_X509,bp,(unsigned char *)x509) + +#define X509_CRL_dup(crl) (X509_CRL *)ASN1_dup((int (*)())i2d_X509_CRL, \ + (char *(*)())d2i_X509_CRL,(char *)crl) +#define d2i_X509_CRL_fp(fp,crl) (X509_CRL *)ASN1_d2i_fp((char *(*)()) \ + X509_CRL_new,(char *(*)())d2i_X509_CRL, (fp),\ + (unsigned char **)(crl)) +#define i2d_X509_CRL_fp(fp,crl) ASN1_i2d_fp(i2d_X509_CRL,fp,\ + (unsigned char *)crl) +#define d2i_X509_CRL_bio(bp,crl) (X509_CRL *)ASN1_d2i_bio((char *(*)()) \ + X509_CRL_new,(char *(*)())d2i_X509_CRL, (bp),\ + (unsigned char **)(crl)) +#define i2d_X509_CRL_bio(bp,crl) ASN1_i2d_bio(i2d_X509_CRL,bp,\ + (unsigned char *)crl) + +#define PKCS7_dup(p7) (PKCS7 *)ASN1_dup((int (*)())i2d_PKCS7, \ + (char *(*)())d2i_PKCS7,(char *)p7) +#define d2i_PKCS7_fp(fp,p7) (PKCS7 *)ASN1_d2i_fp((char *(*)()) \ + PKCS7_new,(char *(*)())d2i_PKCS7, (fp),\ + (unsigned char **)(p7)) +#define i2d_PKCS7_fp(fp,p7) ASN1_i2d_fp(i2d_PKCS7,fp,\ + (unsigned char *)p7) +#define d2i_PKCS7_bio(bp,p7) (PKCS7 *)ASN1_d2i_bio((char *(*)()) \ + PKCS7_new,(char *(*)())d2i_PKCS7, (bp),\ + (unsigned char **)(p7)) +#define i2d_PKCS7_bio(bp,p7) ASN1_i2d_bio(i2d_PKCS7,bp,\ + (unsigned char *)p7) + +#define X509_REQ_dup(req) (X509_REQ *)ASN1_dup((int (*)())i2d_X509_REQ, \ + (char *(*)())d2i_X509_REQ,(char *)req) +#define d2i_X509_REQ_fp(fp,req) (X509_REQ *)ASN1_d2i_fp((char *(*)())\ + X509_REQ_new, (char *(*)())d2i_X509_REQ, (fp),\ + (unsigned char **)(req)) +#define i2d_X509_REQ_fp(fp,req) ASN1_i2d_fp(i2d_X509_REQ,fp,\ + (unsigned char *)req) +#define d2i_X509_REQ_bio(bp,req) (X509_REQ *)ASN1_d2i_bio((char *(*)())\ + X509_REQ_new, (char *(*)())d2i_X509_REQ, (bp),\ + (unsigned char **)(req)) +#define i2d_X509_REQ_bio(bp,req) ASN1_i2d_bio(i2d_X509_REQ,bp,\ + (unsigned char *)req) + +#define RSAPublicKey_dup(rsa) (RSA *)ASN1_dup((int (*)())i2d_RSAPublicKey, \ + (char *(*)())d2i_RSAPublicKey,(char *)rsa) +#define RSAPrivateKey_dup(rsa) (RSA *)ASN1_dup((int (*)())i2d_RSAPrivateKey, \ + (char *(*)())d2i_RSAPrivateKey,(char *)rsa) + +#define d2i_RSAPrivateKey_fp(fp,rsa) (RSA *)ASN1_d2i_fp((char *(*)())\ + RSA_new,(char *(*)())d2i_RSAPrivateKey, (fp), \ + (unsigned char **)(rsa)) +#define i2d_RSAPrivateKey_fp(fp,rsa) ASN1_i2d_fp(i2d_RSAPrivateKey,fp, \ + (unsigned char *)rsa) +#define d2i_RSAPrivateKey_bio(bp,rsa) (RSA *)ASN1_d2i_bio((char *(*)())\ + RSA_new,(char *(*)())d2i_RSAPrivateKey, (bp), \ + (unsigned char **)(rsa)) +#define i2d_RSAPrivateKey_bio(bp,rsa) ASN1_i2d_bio(i2d_RSAPrivateKey,bp, \ + (unsigned char *)rsa) + +#define d2i_RSAPublicKey_fp(fp,rsa) (RSA *)ASN1_d2i_fp((char *(*)())\ + RSA_new,(char *(*)())d2i_RSAPublicKey, (fp), \ + (unsigned char **)(rsa)) +#define i2d_RSAPublicKey_fp(fp,rsa) ASN1_i2d_fp(i2d_RSAPublicKey,fp, \ + (unsigned char *)rsa) +#define d2i_RSAPublicKey_bio(bp,rsa) (RSA *)ASN1_d2i_bio((char *(*)())\ + RSA_new,(char *(*)())d2i_RSAPublicKey, (bp), \ + (unsigned char **)(rsa)) +#define i2d_RSAPublicKey_bio(bp,rsa) ASN1_i2d_bio(i2d_RSAPublicKey,bp, \ + (unsigned char *)rsa) + +#define d2i_DSAPrivateKey_fp(fp,dsa) (DSA *)ASN1_d2i_fp((char *(*)())\ + DSA_new,(char *(*)())d2i_DSAPrivateKey, (fp), \ + (unsigned char **)(dsa)) +#define i2d_DSAPrivateKey_fp(fp,dsa) ASN1_i2d_fp(i2d_DSAPrivateKey,fp, \ + (unsigned char *)dsa) +#define d2i_DSAPrivateKey_bio(bp,dsa) (DSA *)ASN1_d2i_bio((char *(*)())\ + DSA_new,(char *(*)())d2i_DSAPrivateKey, (bp), \ + (unsigned char **)(dsa)) +#define i2d_DSAPrivateKey_bio(bp,dsa) ASN1_i2d_bio(i2d_DSAPrivateKey,bp, \ + (unsigned char *)dsa) + +#define X509_ALGOR_dup(xn) (X509_ALGOR *)ASN1_dup((int (*)())i2d_X509_ALGOR,\ + (char *(*)())d2i_X509_ALGOR,(char *)xn) + +#define X509_NAME_dup(xn) (X509_NAME *)ASN1_dup((int (*)())i2d_X509_NAME, \ + (char *(*)())d2i_X509_NAME,(char *)xn) +#define X509_NAME_ENTRY_dup(ne) (X509_NAME_ENTRY *)ASN1_dup( \ + (int (*)())i2d_X509_NAME_ENTRY, \ + (char *(*)())d2i_X509_NAME_ENTRY,\ + (char *)ne) + +#define X509_digest(data,type,md,len) \ + ASN1_digest((int (*)())i2d_X509,type,(char *)data,md,len) +#define X509_NAME_digest(data,type,md,len) \ + ASN1_digest((int (*)())i2d_X509_NAME,type,(char *)data,md,len) +#ifndef PKCS7_ISSUER_AND_SERIAL_digest +#define PKCS7_ISSUER_AND_SERIAL_digest(data,type,md,len) \ + ASN1_digest((int (*)())i2d_PKCS7_ISSUER_AND_SERIAL,type,\ + (char *)data,md,len) +#endif +#endif + +#define X509_EXT_PACK_UNKNOWN 1 +#define X509_EXT_PACK_STRING 2 + +#define X509_get_version(x) ASN1_INTEGER_get((x)->cert_info->version) +/* #define X509_get_serialNumber(x) ((x)->cert_info->serialNumber) */ +#define X509_get_notBefore(x) ((x)->cert_info->validity->notBefore) +#define X509_get_notAfter(x) ((x)->cert_info->validity->notAfter) +#define X509_extract_key(x) X509_get_pubkey(x) /*****/ +#define X509_REQ_get_version(x) ASN1_INTEGER_get((x)->req_info->version) +#define X509_REQ_get_subject_name(x) ((x)->req_info->subject) +#define X509_REQ_extract_key(a) X509_REQ_get_pubkey(a) +#define X509_name_cmp(a,b) X509_NAME_cmp((a),(b)) +#define X509_get_signature_type(x) EVP_PKEY_type(OBJ_obj2nid((x)->sig_alg->algorithm)) + +#define X509_CRL_get_version(x) ASN1_INTEGER_get((x)->crl->version) +#define X509_CRL_get_lastUpdate(x) ((x)->crl->lastUpdate) +#define X509_CRL_get_nextUpdate(x) ((x)->crl->nextUpdate) +#define X509_CRL_get_issuer(x) ((x)->crl->issuer) +#define X509_CRL_get_REVOKED(x) ((x)->crl->revoked) + +/* This one is only used so that a binary form can output, as in + * i2d_X509_NAME(X509_get_X509_PUBKEY(x),&buf) */ +#define X509_get_X509_PUBKEY(x) ((x)->cert_info->key) + + +const char *X509_verify_cert_error_string(long n); + +#ifndef SSLEAY_MACROS +#ifdef HEADER_ENVELOPE_H +int X509_verify(X509 *a, EVP_PKEY *r); + +int X509_REQ_verify(X509_REQ *a, EVP_PKEY *r); +int X509_CRL_verify(X509_CRL *a, EVP_PKEY *r); +int NETSCAPE_SPKI_verify(NETSCAPE_SPKI *a, EVP_PKEY *r); + +NETSCAPE_SPKI * NETSCAPE_SPKI_b64_decode(const char *str, int len); +char * NETSCAPE_SPKI_b64_encode(NETSCAPE_SPKI *x); +EVP_PKEY *NETSCAPE_SPKI_get_pubkey(NETSCAPE_SPKI *x); +int NETSCAPE_SPKI_set_pubkey(NETSCAPE_SPKI *x, EVP_PKEY *pkey); + +int NETSCAPE_SPKI_print(BIO *out, NETSCAPE_SPKI *spki); + +int X509_sign(X509 *x, EVP_PKEY *pkey, const EVP_MD *md); +int X509_REQ_sign(X509_REQ *x, EVP_PKEY *pkey, const EVP_MD *md); +int X509_CRL_sign(X509_CRL *x, EVP_PKEY *pkey, const EVP_MD *md); +int NETSCAPE_SPKI_sign(NETSCAPE_SPKI *x, EVP_PKEY *pkey, const EVP_MD *md); + +int X509_digest(X509 *data,const EVP_MD *type,unsigned char *md,unsigned int *len); +int X509_NAME_digest(X509_NAME *data,const EVP_MD *type, + unsigned char *md,unsigned int *len); +#endif + +#ifndef NO_FP_API +X509 *d2i_X509_fp(FILE *fp, X509 **x509); +int i2d_X509_fp(FILE *fp,X509 *x509); +X509_CRL *d2i_X509_CRL_fp(FILE *fp,X509_CRL **crl); +int i2d_X509_CRL_fp(FILE *fp,X509_CRL *crl); +X509_REQ *d2i_X509_REQ_fp(FILE *fp,X509_REQ **req); +int i2d_X509_REQ_fp(FILE *fp,X509_REQ *req); +#ifndef NO_RSA +RSA *d2i_RSAPrivateKey_fp(FILE *fp,RSA **rsa); +int i2d_RSAPrivateKey_fp(FILE *fp,RSA *rsa); +RSA *d2i_RSAPublicKey_fp(FILE *fp,RSA **rsa); +int i2d_RSAPublicKey_fp(FILE *fp,RSA *rsa); +RSA *d2i_RSA_PUBKEY_fp(FILE *fp,RSA **rsa); +int i2d_RSA_PUBKEY_fp(FILE *fp,RSA *rsa); +#endif +#ifndef NO_DSA +DSA *d2i_DSA_PUBKEY_fp(FILE *fp, DSA **dsa); +int i2d_DSA_PUBKEY_fp(FILE *fp, DSA *dsa); +DSA *d2i_DSAPrivateKey_fp(FILE *fp, DSA **dsa); +int i2d_DSAPrivateKey_fp(FILE *fp, DSA *dsa); +#endif +X509_SIG *d2i_PKCS8_fp(FILE *fp,X509_SIG **p8); +int i2d_PKCS8_fp(FILE *fp,X509_SIG *p8); +PKCS8_PRIV_KEY_INFO *d2i_PKCS8_PRIV_KEY_INFO_fp(FILE *fp, + PKCS8_PRIV_KEY_INFO **p8inf); +int i2d_PKCS8_PRIV_KEY_INFO_fp(FILE *fp,PKCS8_PRIV_KEY_INFO *p8inf); +int i2d_PKCS8PrivateKeyInfo_fp(FILE *fp, EVP_PKEY *key); +int i2d_PrivateKey_fp(FILE *fp, EVP_PKEY *pkey); +EVP_PKEY *d2i_PrivateKey_fp(FILE *fp, EVP_PKEY **a); +#endif + +#ifdef HEADER_BIO_H +X509 *d2i_X509_bio(BIO *bp,X509 **x509); +int i2d_X509_bio(BIO *bp,X509 *x509); +X509_CRL *d2i_X509_CRL_bio(BIO *bp,X509_CRL **crl); +int i2d_X509_CRL_bio(BIO *bp,X509_CRL *crl); +X509_REQ *d2i_X509_REQ_bio(BIO *bp,X509_REQ **req); +int i2d_X509_REQ_bio(BIO *bp,X509_REQ *req); +#ifndef NO_RSA +RSA *d2i_RSAPrivateKey_bio(BIO *bp,RSA **rsa); +int i2d_RSAPrivateKey_bio(BIO *bp,RSA *rsa); +RSA *d2i_RSAPublicKey_bio(BIO *bp,RSA **rsa); +int i2d_RSAPublicKey_bio(BIO *bp,RSA *rsa); +RSA *d2i_RSA_PUBKEY_bio(BIO *bp,RSA **rsa); +int i2d_RSA_PUBKEY_bio(BIO *bp,RSA *rsa); +#endif +#ifndef NO_DSA +DSA *d2i_DSA_PUBKEY_bio(BIO *bp, DSA **dsa); +int i2d_DSA_PUBKEY_bio(BIO *bp, DSA *dsa); +DSA *d2i_DSAPrivateKey_bio(BIO *bp, DSA **dsa); +int i2d_DSAPrivateKey_bio(BIO *bp, DSA *dsa); +#endif +X509_SIG *d2i_PKCS8_bio(BIO *bp,X509_SIG **p8); +int i2d_PKCS8_bio(BIO *bp,X509_SIG *p8); +PKCS8_PRIV_KEY_INFO *d2i_PKCS8_PRIV_KEY_INFO_bio(BIO *bp, + PKCS8_PRIV_KEY_INFO **p8inf); +int i2d_PKCS8_PRIV_KEY_INFO_bio(BIO *bp,PKCS8_PRIV_KEY_INFO *p8inf); +int i2d_PKCS8PrivateKeyInfo_bio(BIO *bp, EVP_PKEY *key); +int i2d_PrivateKey_bio(BIO *bp, EVP_PKEY *pkey); +EVP_PKEY *d2i_PrivateKey_bio(BIO *bp, EVP_PKEY **a); +#endif + +X509 *X509_dup(X509 *x509); +X509_ATTRIBUTE *X509_ATTRIBUTE_dup(X509_ATTRIBUTE *xa); +X509_EXTENSION *X509_EXTENSION_dup(X509_EXTENSION *ex); +X509_CRL *X509_CRL_dup(X509_CRL *crl); +X509_REQ *X509_REQ_dup(X509_REQ *req); +X509_ALGOR *X509_ALGOR_dup(X509_ALGOR *xn); +X509_NAME *X509_NAME_dup(X509_NAME *xn); +X509_NAME_ENTRY *X509_NAME_ENTRY_dup(X509_NAME_ENTRY *ne); +#ifndef NO_RSA +RSA *RSAPublicKey_dup(RSA *rsa); +RSA *RSAPrivateKey_dup(RSA *rsa); +#endif + +#endif /* !SSLEAY_MACROS */ + +int X509_cmp_current_time(ASN1_UTCTIME *s); +ASN1_UTCTIME * X509_gmtime_adj(ASN1_UTCTIME *s, long adj); + +const char * X509_get_default_cert_area(void ); +const char * X509_get_default_cert_dir(void ); +const char * X509_get_default_cert_file(void ); +const char * X509_get_default_cert_dir_env(void ); +const char * X509_get_default_cert_file_env(void ); +const char * X509_get_default_private_dir(void ); + +X509_REQ * X509_to_X509_REQ(X509 *x, EVP_PKEY *pkey, const EVP_MD *md); +X509 * X509_REQ_to_X509(X509_REQ *r, int days,EVP_PKEY *pkey); +void ERR_load_X509_strings(void ); + +X509_ALGOR * X509_ALGOR_new(void ); +void X509_ALGOR_free(X509_ALGOR *a); +int i2d_X509_ALGOR(X509_ALGOR *a,unsigned char **pp); +X509_ALGOR * d2i_X509_ALGOR(X509_ALGOR **a,unsigned char **pp, + long length); + +X509_VAL * X509_VAL_new(void ); +void X509_VAL_free(X509_VAL *a); +int i2d_X509_VAL(X509_VAL *a,unsigned char **pp); +X509_VAL * d2i_X509_VAL(X509_VAL **a,unsigned char **pp, + long length); + +X509_PUBKEY * X509_PUBKEY_new(void ); +void X509_PUBKEY_free(X509_PUBKEY *a); +int i2d_X509_PUBKEY(X509_PUBKEY *a,unsigned char **pp); +X509_PUBKEY * d2i_X509_PUBKEY(X509_PUBKEY **a,unsigned char **pp, + long length); +int X509_PUBKEY_set(X509_PUBKEY **x, EVP_PKEY *pkey); +EVP_PKEY * X509_PUBKEY_get(X509_PUBKEY *key); +int X509_get_pubkey_parameters(EVP_PKEY *pkey, + STACK_OF(X509) *chain); +int i2d_PUBKEY(EVP_PKEY *a,unsigned char **pp); +EVP_PKEY * d2i_PUBKEY(EVP_PKEY **a,unsigned char **pp, + long length); +#ifndef NO_RSA +int i2d_RSA_PUBKEY(RSA *a,unsigned char **pp); +RSA * d2i_RSA_PUBKEY(RSA **a,unsigned char **pp, + long length); +#endif +#ifndef NO_DSA +int i2d_DSA_PUBKEY(DSA *a,unsigned char **pp); +DSA * d2i_DSA_PUBKEY(DSA **a,unsigned char **pp, + long length); +#endif + +X509_SIG * X509_SIG_new(void ); +void X509_SIG_free(X509_SIG *a); +int i2d_X509_SIG(X509_SIG *a,unsigned char **pp); +X509_SIG * d2i_X509_SIG(X509_SIG **a,unsigned char **pp,long length); + +X509_REQ_INFO *X509_REQ_INFO_new(void); +void X509_REQ_INFO_free(X509_REQ_INFO *a); +int i2d_X509_REQ_INFO(X509_REQ_INFO *a,unsigned char **pp); +X509_REQ_INFO *d2i_X509_REQ_INFO(X509_REQ_INFO **a,unsigned char **pp, + long length); + +X509_REQ * X509_REQ_new(void); +void X509_REQ_free(X509_REQ *a); +int i2d_X509_REQ(X509_REQ *a,unsigned char **pp); +X509_REQ * d2i_X509_REQ(X509_REQ **a,unsigned char **pp,long length); + +X509_ATTRIBUTE *X509_ATTRIBUTE_new(void ); +void X509_ATTRIBUTE_free(X509_ATTRIBUTE *a); +int i2d_X509_ATTRIBUTE(X509_ATTRIBUTE *a,unsigned char **pp); +X509_ATTRIBUTE *d2i_X509_ATTRIBUTE(X509_ATTRIBUTE **a,unsigned char **pp, + long length); +X509_ATTRIBUTE *X509_ATTRIBUTE_create(int nid, int atrtype, void *value); + + +X509_EXTENSION *X509_EXTENSION_new(void ); +void X509_EXTENSION_free(X509_EXTENSION *a); +int i2d_X509_EXTENSION(X509_EXTENSION *a,unsigned char **pp); +X509_EXTENSION *d2i_X509_EXTENSION(X509_EXTENSION **a,unsigned char **pp, + long length); + +X509_NAME_ENTRY *X509_NAME_ENTRY_new(void); +void X509_NAME_ENTRY_free(X509_NAME_ENTRY *a); +int i2d_X509_NAME_ENTRY(X509_NAME_ENTRY *a,unsigned char **pp); +X509_NAME_ENTRY *d2i_X509_NAME_ENTRY(X509_NAME_ENTRY **a,unsigned char **pp, + long length); + +X509_NAME * X509_NAME_new(void); +void X509_NAME_free(X509_NAME *a); +int i2d_X509_NAME(X509_NAME *a,unsigned char **pp); +X509_NAME * d2i_X509_NAME(X509_NAME **a,unsigned char **pp,long length); +int X509_NAME_set(X509_NAME **xn, X509_NAME *name); + + +X509_CINF * X509_CINF_new(void); +void X509_CINF_free(X509_CINF *a); +int i2d_X509_CINF(X509_CINF *a,unsigned char **pp); +X509_CINF * d2i_X509_CINF(X509_CINF **a,unsigned char **pp,long length); + +X509 * X509_new(void); +void X509_free(X509 *a); +int i2d_X509(X509 *a,unsigned char **pp); +X509 * d2i_X509(X509 **a,unsigned char **pp,long length); +int X509_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, + CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func); +int X509_set_ex_data(X509 *r, int idx, void *arg); +void *X509_get_ex_data(X509 *r, int idx); +int i2d_X509_AUX(X509 *a,unsigned char **pp); +X509 * d2i_X509_AUX(X509 **a,unsigned char **pp,long length); + +X509_CERT_AUX * X509_CERT_AUX_new(void); +void X509_CERT_AUX_free(X509_CERT_AUX *a); +int i2d_X509_CERT_AUX(X509_CERT_AUX *a,unsigned char **pp); +X509_CERT_AUX * d2i_X509_CERT_AUX(X509_CERT_AUX **a,unsigned char **pp, + long length); +int X509_alias_set1(X509 *x, unsigned char *name, int len); +unsigned char * X509_alias_get0(X509 *x, int *len); +int (*X509_TRUST_set_default(int (*trust)(int , X509 *, int)))(int, X509 *, int); +int X509_add1_trust_object(X509 *x, ASN1_OBJECT *obj); +int X509_add1_reject_object(X509 *x, ASN1_OBJECT *obj); +void X509_trust_clear(X509 *x); +void X509_reject_clear(X509 *x); + +X509_REVOKED * X509_REVOKED_new(void); +void X509_REVOKED_free(X509_REVOKED *a); +int i2d_X509_REVOKED(X509_REVOKED *a,unsigned char **pp); +X509_REVOKED * d2i_X509_REVOKED(X509_REVOKED **a,unsigned char **pp,long length); + +X509_CRL_INFO *X509_CRL_INFO_new(void); +void X509_CRL_INFO_free(X509_CRL_INFO *a); +int i2d_X509_CRL_INFO(X509_CRL_INFO *a,unsigned char **pp); +X509_CRL_INFO *d2i_X509_CRL_INFO(X509_CRL_INFO **a,unsigned char **pp, + long length); + +X509_CRL * X509_CRL_new(void); +void X509_CRL_free(X509_CRL *a); +int i2d_X509_CRL(X509_CRL *a,unsigned char **pp); +X509_CRL * d2i_X509_CRL(X509_CRL **a,unsigned char **pp,long length); + +X509_PKEY * X509_PKEY_new(void ); +void X509_PKEY_free(X509_PKEY *a); +int i2d_X509_PKEY(X509_PKEY *a,unsigned char **pp); +X509_PKEY * d2i_X509_PKEY(X509_PKEY **a,unsigned char **pp,long length); + +NETSCAPE_SPKI * NETSCAPE_SPKI_new(void ); +void NETSCAPE_SPKI_free(NETSCAPE_SPKI *a); +int i2d_NETSCAPE_SPKI(NETSCAPE_SPKI *a,unsigned char **pp); +NETSCAPE_SPKI * d2i_NETSCAPE_SPKI(NETSCAPE_SPKI **a,unsigned char **pp, + long length); + +NETSCAPE_SPKAC *NETSCAPE_SPKAC_new(void ); +void NETSCAPE_SPKAC_free(NETSCAPE_SPKAC *a); +int i2d_NETSCAPE_SPKAC(NETSCAPE_SPKAC *a,unsigned char **pp); +NETSCAPE_SPKAC *d2i_NETSCAPE_SPKAC(NETSCAPE_SPKAC **a,unsigned char **pp, + long length); + + +int i2d_NETSCAPE_CERT_SEQUENCE(NETSCAPE_CERT_SEQUENCE *a, unsigned char **pp); +NETSCAPE_CERT_SEQUENCE *NETSCAPE_CERT_SEQUENCE_new(void); +NETSCAPE_CERT_SEQUENCE *d2i_NETSCAPE_CERT_SEQUENCE(NETSCAPE_CERT_SEQUENCE **a, unsigned char **pp, long length); +void NETSCAPE_CERT_SEQUENCE_free(NETSCAPE_CERT_SEQUENCE *a); + +#ifdef HEADER_ENVELOPE_H +X509_INFO * X509_INFO_new(void); +void X509_INFO_free(X509_INFO *a); +char * X509_NAME_oneline(X509_NAME *a,char *buf,int size); + +int ASN1_verify(int (*i2d)(), X509_ALGOR *algor1, + ASN1_BIT_STRING *signature,char *data,EVP_PKEY *pkey); + +int ASN1_digest(int (*i2d)(),const EVP_MD *type,char *data, + unsigned char *md,unsigned int *len); + +int ASN1_sign(int (*i2d)(), X509_ALGOR *algor1, X509_ALGOR *algor2, + ASN1_BIT_STRING *signature, + char *data,EVP_PKEY *pkey, const EVP_MD *type); +#endif + +int X509_set_version(X509 *x,long version); +int X509_set_serialNumber(X509 *x, ASN1_INTEGER *serial); +ASN1_INTEGER * X509_get_serialNumber(X509 *x); +int X509_set_issuer_name(X509 *x, X509_NAME *name); +X509_NAME * X509_get_issuer_name(X509 *a); +int X509_set_subject_name(X509 *x, X509_NAME *name); +X509_NAME * X509_get_subject_name(X509 *a); +int X509_set_notBefore(X509 *x, ASN1_UTCTIME *tm); +int X509_set_notAfter(X509 *x, ASN1_UTCTIME *tm); +int X509_set_pubkey(X509 *x, EVP_PKEY *pkey); +EVP_PKEY * X509_get_pubkey(X509 *x); +int X509_certificate_type(X509 *x,EVP_PKEY *pubkey /* optional */); + +int X509_REQ_set_version(X509_REQ *x,long version); +int X509_REQ_set_subject_name(X509_REQ *req,X509_NAME *name); +int X509_REQ_set_pubkey(X509_REQ *x, EVP_PKEY *pkey); +EVP_PKEY * X509_REQ_get_pubkey(X509_REQ *req); +int X509_REQ_extension_nid(int nid); +int * X509_REQ_get_extension_nids(void); +void X509_REQ_set_extension_nids(int *nids); +STACK_OF(X509_EXTENSION) *X509_REQ_get_extensions(X509_REQ *req); +int X509_REQ_add_extensions_nid(X509_REQ *req, STACK_OF(X509_EXTENSION) *exts, + int nid); +int X509_REQ_add_extensions(X509_REQ *req, STACK_OF(X509_EXTENSION) *exts); +int X509_REQ_get_attr_count(const X509_REQ *req); +int X509_REQ_get_attr_by_NID(const X509_REQ *req, int nid, + int lastpos); +int X509_REQ_get_attr_by_OBJ(const X509_REQ *req, ASN1_OBJECT *obj, + int lastpos); +X509_ATTRIBUTE *X509_REQ_get_attr(const X509_REQ *req, int loc); +X509_ATTRIBUTE *X509_REQ_delete_attr(X509_REQ *req, int loc); +int X509_REQ_add1_attr(X509_REQ *req, X509_ATTRIBUTE *attr); +int X509_REQ_add1_attr_by_OBJ(X509_REQ *req, + ASN1_OBJECT *obj, int type, + unsigned char *bytes, int len); +int X509_REQ_add1_attr_by_NID(X509_REQ *req, + int nid, int type, + unsigned char *bytes, int len); +int X509_REQ_add1_attr_by_txt(X509_REQ *req, + char *attrname, int type, + unsigned char *bytes, int len); + +int X509_check_private_key(X509 *x509,EVP_PKEY *pkey); + +int X509_issuer_and_serial_cmp(X509 *a, X509 *b); +unsigned long X509_issuer_and_serial_hash(X509 *a); + +int X509_issuer_name_cmp(X509 *a, X509 *b); +unsigned long X509_issuer_name_hash(X509 *a); + +int X509_subject_name_cmp(X509 *a,X509 *b); +unsigned long X509_subject_name_hash(X509 *x); + +int X509_cmp (X509 *a, X509 *b); +int X509_NAME_cmp (X509_NAME *a, X509_NAME *b); +unsigned long X509_NAME_hash(X509_NAME *x); + +int X509_CRL_cmp(X509_CRL *a,X509_CRL *b); +#ifndef NO_FP_API +int X509_print_fp(FILE *bp,X509 *x); +int X509_CRL_print_fp(FILE *bp,X509_CRL *x); +int X509_REQ_print_fp(FILE *bp,X509_REQ *req); +#endif + +#ifdef HEADER_BIO_H +int X509_NAME_print(BIO *bp, X509_NAME *name, int obase); +int X509_print(BIO *bp,X509 *x); +int X509_CERT_AUX_print(BIO *bp,X509_CERT_AUX *x, int indent); +int X509_CRL_print(BIO *bp,X509_CRL *x); +int X509_REQ_print(BIO *bp,X509_REQ *req); +#endif + +int X509_NAME_entry_count(X509_NAME *name); +int X509_NAME_get_text_by_NID(X509_NAME *name, int nid, + char *buf,int len); +int X509_NAME_get_text_by_OBJ(X509_NAME *name, ASN1_OBJECT *obj, + char *buf,int len); + +/* NOTE: you should be passsing -1, not 0 as lastpos. The functions that use + * lastpos, search after that position on. */ +int X509_NAME_get_index_by_NID(X509_NAME *name,int nid,int lastpos); +int X509_NAME_get_index_by_OBJ(X509_NAME *name,ASN1_OBJECT *obj, + int lastpos); +X509_NAME_ENTRY *X509_NAME_get_entry(X509_NAME *name, int loc); +X509_NAME_ENTRY *X509_NAME_delete_entry(X509_NAME *name, int loc); +int X509_NAME_add_entry(X509_NAME *name,X509_NAME_ENTRY *ne, + int loc, int set); +int X509_NAME_add_entry_by_OBJ(X509_NAME *name, ASN1_OBJECT *obj, int type, + unsigned char *bytes, int len, int loc, int set); +int X509_NAME_add_entry_by_NID(X509_NAME *name, int nid, int type, + unsigned char *bytes, int len, int loc, int set); +X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_txt(X509_NAME_ENTRY **ne, + char *field, int type, unsigned char *bytes, int len); +X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_NID(X509_NAME_ENTRY **ne, int nid, + int type,unsigned char *bytes, int len); +int X509_NAME_add_entry_by_txt(X509_NAME *name, char *field, int type, + unsigned char *bytes, int len, int loc, int set); +X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_OBJ(X509_NAME_ENTRY **ne, + ASN1_OBJECT *obj, int type,unsigned char *bytes, + int len); +int X509_NAME_ENTRY_set_object(X509_NAME_ENTRY *ne, + ASN1_OBJECT *obj); +int X509_NAME_ENTRY_set_data(X509_NAME_ENTRY *ne, int type, + unsigned char *bytes, int len); +ASN1_OBJECT * X509_NAME_ENTRY_get_object(X509_NAME_ENTRY *ne); +ASN1_STRING * X509_NAME_ENTRY_get_data(X509_NAME_ENTRY *ne); + +int X509v3_get_ext_count(const STACK_OF(X509_EXTENSION) *x); +int X509v3_get_ext_by_NID(const STACK_OF(X509_EXTENSION) *x, + int nid, int lastpos); +int X509v3_get_ext_by_OBJ(const STACK_OF(X509_EXTENSION) *x, + ASN1_OBJECT *obj,int lastpos); +int X509v3_get_ext_by_critical(const STACK_OF(X509_EXTENSION) *x, + int crit, int lastpos); +X509_EXTENSION *X509v3_get_ext(const STACK_OF(X509_EXTENSION) *x, int loc); +X509_EXTENSION *X509v3_delete_ext(STACK_OF(X509_EXTENSION) *x, int loc); +STACK_OF(X509_EXTENSION) *X509v3_add_ext(STACK_OF(X509_EXTENSION) **x, + X509_EXTENSION *ex, int loc); + +int X509_get_ext_count(X509 *x); +int X509_get_ext_by_NID(X509 *x, int nid, int lastpos); +int X509_get_ext_by_OBJ(X509 *x,ASN1_OBJECT *obj,int lastpos); +int X509_get_ext_by_critical(X509 *x, int crit, int lastpos); +X509_EXTENSION *X509_get_ext(X509 *x, int loc); +X509_EXTENSION *X509_delete_ext(X509 *x, int loc); +int X509_add_ext(X509 *x, X509_EXTENSION *ex, int loc); +void * X509_get_ext_d2i(X509 *x, int nid, int *crit, int *idx); + +int X509_CRL_get_ext_count(X509_CRL *x); +int X509_CRL_get_ext_by_NID(X509_CRL *x, int nid, int lastpos); +int X509_CRL_get_ext_by_OBJ(X509_CRL *x,ASN1_OBJECT *obj,int lastpos); +int X509_CRL_get_ext_by_critical(X509_CRL *x, int crit, int lastpos); +X509_EXTENSION *X509_CRL_get_ext(X509_CRL *x, int loc); +X509_EXTENSION *X509_CRL_delete_ext(X509_CRL *x, int loc); +int X509_CRL_add_ext(X509_CRL *x, X509_EXTENSION *ex, int loc); +void * X509_CRL_get_ext_d2i(X509_CRL *x, int nid, int *crit, int *idx); + +int X509_REVOKED_get_ext_count(X509_REVOKED *x); +int X509_REVOKED_get_ext_by_NID(X509_REVOKED *x, int nid, int lastpos); +int X509_REVOKED_get_ext_by_OBJ(X509_REVOKED *x,ASN1_OBJECT *obj,int lastpos); +int X509_REVOKED_get_ext_by_critical(X509_REVOKED *x, int crit, int lastpos); +X509_EXTENSION *X509_REVOKED_get_ext(X509_REVOKED *x, int loc); +X509_EXTENSION *X509_REVOKED_delete_ext(X509_REVOKED *x, int loc); +int X509_REVOKED_add_ext(X509_REVOKED *x, X509_EXTENSION *ex, int loc); +void * X509_REVOKED_get_ext_d2i(X509_REVOKED *x, int nid, int *crit, int *idx); + +X509_EXTENSION *X509_EXTENSION_create_by_NID(X509_EXTENSION **ex, + int nid, int crit, ASN1_OCTET_STRING *data); +X509_EXTENSION *X509_EXTENSION_create_by_OBJ(X509_EXTENSION **ex, + ASN1_OBJECT *obj,int crit,ASN1_OCTET_STRING *data); +int X509_EXTENSION_set_object(X509_EXTENSION *ex,ASN1_OBJECT *obj); +int X509_EXTENSION_set_critical(X509_EXTENSION *ex, int crit); +int X509_EXTENSION_set_data(X509_EXTENSION *ex, + ASN1_OCTET_STRING *data); +ASN1_OBJECT * X509_EXTENSION_get_object(X509_EXTENSION *ex); +ASN1_OCTET_STRING *X509_EXTENSION_get_data(X509_EXTENSION *ne); +int X509_EXTENSION_get_critical(X509_EXTENSION *ex); + +int X509at_get_attr_count(const STACK_OF(X509_ATTRIBUTE) *x); +int X509at_get_attr_by_NID(const STACK_OF(X509_ATTRIBUTE) *x, int nid, + int lastpos); +int X509at_get_attr_by_OBJ(const STACK_OF(X509_ATTRIBUTE) *sk, ASN1_OBJECT *obj, + int lastpos); +X509_ATTRIBUTE *X509at_get_attr(const STACK_OF(X509_ATTRIBUTE) *x, int loc); +X509_ATTRIBUTE *X509at_delete_attr(STACK_OF(X509_ATTRIBUTE) *x, int loc); +STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr(STACK_OF(X509_ATTRIBUTE) **x, + X509_ATTRIBUTE *attr); +STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_OBJ(STACK_OF(X509_ATTRIBUTE) **x, + ASN1_OBJECT *obj, int type, + unsigned char *bytes, int len); +STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_NID(STACK_OF(X509_ATTRIBUTE) **x, + int nid, int type, + unsigned char *bytes, int len); +STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_txt(STACK_OF(X509_ATTRIBUTE) **x, + char *attrname, int type, + unsigned char *bytes, int len); +X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_NID(X509_ATTRIBUTE **attr, int nid, + int atrtype, void *data, int len); +X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_OBJ(X509_ATTRIBUTE **attr, + ASN1_OBJECT *obj, int atrtype, void *data, int len); +X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_txt(X509_ATTRIBUTE **attr, + char *atrname, int type, unsigned char *bytes, int len); +int X509_ATTRIBUTE_set1_object(X509_ATTRIBUTE *attr, ASN1_OBJECT *obj); +int X509_ATTRIBUTE_set1_data(X509_ATTRIBUTE *attr, int attrtype, void *data, int len); +void *X509_ATTRIBUTE_get0_data(X509_ATTRIBUTE *attr, int idx, + int atrtype, void *data); +int X509_ATTRIBUTE_count(X509_ATTRIBUTE *attr); +ASN1_OBJECT *X509_ATTRIBUTE_get0_object(X509_ATTRIBUTE *attr); +ASN1_TYPE *X509_ATTRIBUTE_get0_type(X509_ATTRIBUTE *attr, int idx); + +int X509_verify_cert(X509_STORE_CTX *ctx); + +/* lookup a cert from a X509 STACK */ +X509 *X509_find_by_issuer_and_serial(STACK_OF(X509) *sk,X509_NAME *name, + ASN1_INTEGER *serial); +X509 *X509_find_by_subject(STACK_OF(X509) *sk,X509_NAME *name); + +int i2d_PBEPARAM(PBEPARAM *a, unsigned char **pp); +PBEPARAM *PBEPARAM_new(void); +PBEPARAM *d2i_PBEPARAM(PBEPARAM **a, unsigned char **pp, long length); +void PBEPARAM_free(PBEPARAM *a); +X509_ALGOR *PKCS5_pbe_set(int alg, int iter, unsigned char *salt, int saltlen); +X509_ALGOR *PKCS5_pbe2_set(const EVP_CIPHER *cipher, int iter, + unsigned char *salt, int saltlen); + +int i2d_PBKDF2PARAM(PBKDF2PARAM *a, unsigned char **pp); +PBKDF2PARAM *PBKDF2PARAM_new(void); +PBKDF2PARAM *d2i_PBKDF2PARAM(PBKDF2PARAM **a, unsigned char **pp, long length); +void PBKDF2PARAM_free(PBKDF2PARAM *a); + +int i2d_PBE2PARAM(PBE2PARAM *a, unsigned char **pp); +PBE2PARAM *PBE2PARAM_new(void); +PBE2PARAM *d2i_PBE2PARAM(PBE2PARAM **a, unsigned char **pp, long length); +void PBE2PARAM_free(PBE2PARAM *a); + +/* PKCS#8 utilities */ + +int i2d_PKCS8_PRIV_KEY_INFO(PKCS8_PRIV_KEY_INFO *a, unsigned char **pp); +PKCS8_PRIV_KEY_INFO *PKCS8_PRIV_KEY_INFO_new(void); +PKCS8_PRIV_KEY_INFO *d2i_PKCS8_PRIV_KEY_INFO(PKCS8_PRIV_KEY_INFO **a, + unsigned char **pp, long length); +void PKCS8_PRIV_KEY_INFO_free(PKCS8_PRIV_KEY_INFO *a); + +EVP_PKEY *EVP_PKCS82PKEY(PKCS8_PRIV_KEY_INFO *p8); +PKCS8_PRIV_KEY_INFO *EVP_PKEY2PKCS8(EVP_PKEY *pkey); +PKCS8_PRIV_KEY_INFO *EVP_PKEY2PKCS8_broken(EVP_PKEY *pkey, int broken); +PKCS8_PRIV_KEY_INFO *PKCS8_set_broken(PKCS8_PRIV_KEY_INFO *p8, int broken); + +int X509_check_trust(X509 *x, int id, int flags); +int X509_TRUST_get_count(void); +X509_TRUST * X509_TRUST_get0(int idx); +int X509_TRUST_get_by_id(int id); +int X509_TRUST_add(int id, int flags, int (*ck)(X509_TRUST *, X509 *, int), + char *name, int arg1, void *arg2); +void X509_TRUST_cleanup(void); +int X509_TRUST_get_flags(X509_TRUST *xp); +char *X509_TRUST_get0_name(X509_TRUST *xp); +int X509_TRUST_get_trust(X509_TRUST *xp); + +/* BEGIN ERROR CODES */ +/* The following lines are auto generated by the script mkerr.pl. Any changes + * made after this point may be overwritten when the script is next run. + */ + +/* Error codes for the X509 functions. */ + +/* Function codes. */ +#define X509_F_ADD_CERT_DIR 100 +#define X509_F_BY_FILE_CTRL 101 +#define X509_F_DIR_CTRL 102 +#define X509_F_GET_CERT_BY_SUBJECT 103 +#define X509_F_NETSCAPE_SPKI_B64_DECODE 129 +#define X509_F_NETSCAPE_SPKI_B64_ENCODE 130 +#define X509_F_X509V3_ADD_EXT 104 +#define X509_F_X509_ADD_ATTR 135 +#define X509_F_X509_ATTRIBUTE_CREATE_BY_NID 136 +#define X509_F_X509_ATTRIBUTE_CREATE_BY_OBJ 137 +#define X509_F_X509_ATTRIBUTE_CREATE_BY_TXT 140 +#define X509_F_X509_ATTRIBUTE_GET0_DATA 139 +#define X509_F_X509_ATTRIBUTE_SET1_DATA 138 +#define X509_F_X509_CHECK_PRIVATE_KEY 128 +#define X509_F_X509_EXTENSION_CREATE_BY_NID 108 +#define X509_F_X509_EXTENSION_CREATE_BY_OBJ 109 +#define X509_F_X509_GET_PUBKEY_PARAMETERS 110 +#define X509_F_X509_LOAD_CERT_CRL_FILE 132 +#define X509_F_X509_LOAD_CERT_FILE 111 +#define X509_F_X509_LOAD_CRL_FILE 112 +#define X509_F_X509_NAME_ADD_ENTRY 113 +#define X509_F_X509_NAME_ENTRY_CREATE_BY_NID 114 +#define X509_F_X509_NAME_ENTRY_CREATE_BY_TXT 131 +#define X509_F_X509_NAME_ENTRY_SET_OBJECT 115 +#define X509_F_X509_NAME_ONELINE 116 +#define X509_F_X509_NAME_PRINT 117 +#define X509_F_X509_PRINT_FP 118 +#define X509_F_X509_PUBKEY_GET 119 +#define X509_F_X509_PUBKEY_SET 120 +#define X509_F_X509_REQ_PRINT 121 +#define X509_F_X509_REQ_PRINT_FP 122 +#define X509_F_X509_REQ_TO_X509 123 +#define X509_F_X509_STORE_ADD_CERT 124 +#define X509_F_X509_STORE_ADD_CRL 125 +#define X509_F_X509_STORE_CTX_PURPOSE_INHERIT 134 +#define X509_F_X509_TO_X509_REQ 126 +#define X509_F_X509_TRUST_ADD 133 +#define X509_F_X509_VERIFY_CERT 127 + +/* Reason codes. */ +#define X509_R_BAD_X509_FILETYPE 100 +#define X509_R_BASE64_DECODE_ERROR 118 +#define X509_R_CANT_CHECK_DH_KEY 114 +#define X509_R_CERT_ALREADY_IN_HASH_TABLE 101 +#define X509_R_ERR_ASN1_LIB 102 +#define X509_R_INVALID_DIRECTORY 113 +#define X509_R_INVALID_FIELD_NAME 119 +#define X509_R_KEY_TYPE_MISMATCH 115 +#define X509_R_KEY_VALUES_MISMATCH 116 +#define X509_R_LOADING_CERT_DIR 103 +#define X509_R_LOADING_DEFAULTS 104 +#define X509_R_NO_CERT_SET_FOR_US_TO_VERIFY 105 +#define X509_R_SHOULD_RETRY 106 +#define X509_R_UNABLE_TO_FIND_PARAMETERS_IN_CHAIN 107 +#define X509_R_UNABLE_TO_GET_CERTS_PUBLIC_KEY 108 +#define X509_R_UNKNOWN_KEY_TYPE 117 +#define X509_R_UNKNOWN_NID 109 +#define X509_R_UNKNOWN_PURPOSE_ID 121 +#define X509_R_UNKNOWN_TRUST_ID 120 +#define X509_R_UNSUPPORTED_ALGORITHM 111 +#define X509_R_WRONG_LOOKUP_TYPE 112 +#define X509_R_WRONG_TYPE 122 + +#ifdef __cplusplus +} +#endif +#endif + diff --git a/libsecurity_apple_csp/open_ssl/openssl/x509_vfy.h b/libsecurity_apple_csp/open_ssl/openssl/x509_vfy.h new file mode 100644 index 00000000..7ddfde7b --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/openssl/x509_vfy.h @@ -0,0 +1,380 @@ +/* + * 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. + */ + + +/* crypto/x509/x509_vfy.h */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef HEADER_X509_H +#include +/* openssl/x509.h ends up #include-ing this file at about the only + * appropriate moment. */ +#endif + +#ifndef HEADER_X509_VFY_H +#define HEADER_X509_VFY_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +/* Outer object */ +typedef struct x509_hash_dir_st + { + int num_dirs; + char **dirs; + int *dirs_type; + int num_dirs_alloced; + } X509_HASH_DIR_CTX; + +typedef struct x509_file_st + { + int num_paths; /* number of paths to files or directories */ + int num_alloced; + char **paths; /* the list of paths or directories */ + int *path_type; + } X509_CERT_FILE_CTX; + +/*******************************/ +/* +SSL_CTX -> X509_STORE + -> X509_LOOKUP + ->X509_LOOKUP_METHOD + -> X509_LOOKUP + ->X509_LOOKUP_METHOD + +SSL -> X509_STORE_CTX + ->X509_STORE + +The X509_STORE holds the tables etc for verification stuff. +A X509_STORE_CTX is used while validating a single certificate. +The X509_STORE has X509_LOOKUPs for looking up certs. +The X509_STORE then calls a function to actually verify the +certificate chain. +*/ + +#define X509_LU_RETRY -1 +#define X509_LU_FAIL 0 +#define X509_LU_X509 1 +#define X509_LU_CRL 2 +#define X509_LU_PKEY 3 + +typedef struct x509_object_st + { + /* one of the above types */ + int type; + union { + char *ptr; + X509 *x509; + X509_CRL *crl; + EVP_PKEY *pkey; + } data; + } X509_OBJECT; + +typedef struct x509_lookup_st X509_LOOKUP; + +DECLARE_STACK_OF(X509_LOOKUP) + +/* This is a static that defines the function interface */ +typedef struct x509_lookup_method_st + { + const char *name; + int (*new_item)(X509_LOOKUP *ctx); + void (*free)(X509_LOOKUP *ctx); + int (*init)(X509_LOOKUP *ctx); + int (*shutdown)(X509_LOOKUP *ctx); + int (*ctrl)(X509_LOOKUP *ctx,int cmd,const char *argc,long argl, + char **ret); + int (*get_by_subject)(X509_LOOKUP *ctx,int type,X509_NAME *name, + X509_OBJECT *ret); + int (*get_by_issuer_serial)(X509_LOOKUP *ctx,int type,X509_NAME *name, + ASN1_INTEGER *serial,X509_OBJECT *ret); + int (*get_by_fingerprint)(X509_LOOKUP *ctx,int type, + unsigned char *bytes,int len, + X509_OBJECT *ret); + int (*get_by_alias)(X509_LOOKUP *ctx,int type,char *str,int len, + X509_OBJECT *ret); + } X509_LOOKUP_METHOD; + +typedef struct x509_store_state_st X509_STORE_CTX; + +/* This is used to hold everything. It is used for all certificate + * validation. Once we have a certificate chain, the 'verify' + * function is then called to actually check the cert chain. */ +typedef struct x509_store_st + { + /* The following is a cache of trusted certs */ + int cache; /* if true, stash any hits */ +#ifdef HEADER_LHASH_H + LHASH *certs; /* cached certs; */ +#else + char *certs; +#endif + + /* These are external lookup methods */ + STACK_OF(X509_LOOKUP) *get_cert_methods; + int (*verify)(X509_STORE_CTX *ctx); /* called to verify a certificate */ + int (*verify_cb)(int ok,X509_STORE_CTX *ctx); /* error callback */ + + CRYPTO_EX_DATA ex_data; + int references; + int depth; /* how deep to look (still unused -- X509_STORE_CTX's depth is used) */ + } X509_STORE; + +#define X509_STORE_set_depth(ctx,d) ((ctx)->depth=(d)) + +#define X509_STORE_set_verify_cb_func(ctx,func) ((ctx)->verify_cb=(func)) +#define X509_STORE_set_verify_func(ctx,func) ((ctx)->verify=(func)) + +/* This is the functions plus an instance of the local variables. */ +struct x509_lookup_st + { + int init; /* have we been started */ + int skip; /* don't use us. */ + X509_LOOKUP_METHOD *method; /* the functions */ + char *method_data; /* method data */ + + X509_STORE *store_ctx; /* who owns us */ + }; + +/* This is a temporary used when processing cert chains. Since the + * gathering of the cert chain can take some time (and have to be + * 'retried', this needs to be kept and passed around. */ +struct x509_store_state_st /* X509_STORE_CTX */ + { + X509_STORE *ctx; + int current_method; /* used when looking up certs */ + + /* The following are set by the caller */ + X509 *cert; /* The cert to check */ + STACK_OF(X509) *untrusted; /* chain of X509s - untrusted - passed in */ + int purpose; /* purpose to check untrusted certificates */ + int trust; /* trust setting to check */ + + /* The following is built up */ + int depth; /* how far to go looking up certs */ + int valid; /* if 0, rebuild chain */ + int last_untrusted; /* index of last untrusted cert */ + STACK_OF(X509) *chain; /* chain of X509s - built up and trusted */ + + /* When something goes wrong, this is why */ + int error_depth; + int error; + X509 *current_cert; + + CRYPTO_EX_DATA ex_data; + }; + +#define X509_STORE_CTX_set_depth(ctx,d) ((ctx)->depth=(d)) + +#define X509_STORE_CTX_set_app_data(ctx,data) \ + X509_STORE_CTX_set_ex_data(ctx,0,data) +#define X509_STORE_CTX_get_app_data(ctx) \ + X509_STORE_CTX_get_ex_data(ctx,0) + +#define X509_L_FILE_LOAD 1 +#define X509_L_ADD_DIR 2 + +#define X509_LOOKUP_load_file(x,name,type) \ + X509_LOOKUP_ctrl((x),X509_L_FILE_LOAD,(name),(long)(type),NULL) + +#define X509_LOOKUP_add_dir(x,name,type) \ + X509_LOOKUP_ctrl((x),X509_L_ADD_DIR,(name),(long)(type),NULL) + +#define X509_V_OK 0 +/* illegal error (for uninitialized values, to avoid X509_V_OK): 1 */ + +#define X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT 2 +#define X509_V_ERR_UNABLE_TO_GET_CRL 3 +#define X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE 4 +#define X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE 5 +#define X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY 6 +#define X509_V_ERR_CERT_SIGNATURE_FAILURE 7 +#define X509_V_ERR_CRL_SIGNATURE_FAILURE 8 +#define X509_V_ERR_CERT_NOT_YET_VALID 9 +#define X509_V_ERR_CERT_HAS_EXPIRED 10 +#define X509_V_ERR_CRL_NOT_YET_VALID 11 +#define X509_V_ERR_CRL_HAS_EXPIRED 12 +#define X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD 13 +#define X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD 14 +#define X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD 15 +#define X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD 16 +#define X509_V_ERR_OUT_OF_MEM 17 +#define X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT 18 +#define X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN 19 +#define X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY 20 +#define X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE 21 +#define X509_V_ERR_CERT_CHAIN_TOO_LONG 22 +#define X509_V_ERR_CERT_REVOKED 23 +#define X509_V_ERR_INVALID_CA 24 +#define X509_V_ERR_PATH_LENGTH_EXCEEDED 25 +#define X509_V_ERR_INVALID_PURPOSE 26 +#define X509_V_ERR_CERT_UNTRUSTED 27 +#define X509_V_ERR_CERT_REJECTED 28 + +/* The application is not happy */ +#define X509_V_ERR_APPLICATION_VERIFICATION 50 + + /* These functions are being redefined in another directory, + and clash when the linker is case-insensitive, so let's + hide them a little, by giving them an extra 'o' at the + beginning of the name... */ +#ifdef VMS +#undef X509v3_cleanup_extensions +#define X509v3_cleanup_extensions oX509v3_cleanup_extensions +#undef X509v3_add_extension +#define X509v3_add_extension oX509v3_add_extension +#undef X509v3_add_netscape_extensions +#define X509v3_add_netscape_extensions oX509v3_add_netscape_extensions +#undef X509v3_add_standard_extensions +#define X509v3_add_standard_extensions oX509v3_add_standard_extensions +#endif + +#ifdef HEADER_LHASH_H +X509_OBJECT *X509_OBJECT_retrieve_by_subject(LHASH *h,int type,X509_NAME *name); +#endif +void X509_OBJECT_up_ref_count(X509_OBJECT *a); +void X509_OBJECT_free_contents(X509_OBJECT *a); +X509_STORE *X509_STORE_new(void ); +void X509_STORE_free(X509_STORE *v); + +X509_STORE_CTX *X509_STORE_CTX_new(void); +void X509_STORE_CTX_free(X509_STORE_CTX *ctx); +void X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, + X509 *x509, STACK_OF(X509) *chain); +void X509_STORE_CTX_cleanup(X509_STORE_CTX *ctx); + +X509_LOOKUP *X509_STORE_add_lookup(X509_STORE *v, X509_LOOKUP_METHOD *m); + +X509_LOOKUP_METHOD *X509_LOOKUP_hash_dir(void); +X509_LOOKUP_METHOD *X509_LOOKUP_file(void); + +int X509_STORE_add_cert(X509_STORE *ctx, X509 *x); +int X509_STORE_add_crl(X509_STORE *ctx, X509_CRL *x); + +int X509_STORE_get_by_subject(X509_STORE_CTX *vs,int type,X509_NAME *name, + X509_OBJECT *ret); + +int X509_LOOKUP_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc, + long argl, char **ret); + +#ifndef NO_STDIO +int X509_load_cert_file(X509_LOOKUP *ctx, const char *file, int type); +int X509_load_crl_file(X509_LOOKUP *ctx, const char *file, int type); +int X509_load_cert_crl_file(X509_LOOKUP *ctx, const char *file, int type); +#endif + + +X509_LOOKUP *X509_LOOKUP_new(X509_LOOKUP_METHOD *method); +void X509_LOOKUP_free(X509_LOOKUP *ctx); +int X509_LOOKUP_init(X509_LOOKUP *ctx); +int X509_LOOKUP_by_subject(X509_LOOKUP *ctx, int type, X509_NAME *name, + X509_OBJECT *ret); +int X509_LOOKUP_by_issuer_serial(X509_LOOKUP *ctx, int type, X509_NAME *name, + ASN1_INTEGER *serial, X509_OBJECT *ret); +int X509_LOOKUP_by_fingerprint(X509_LOOKUP *ctx, int type, + unsigned char *bytes, int len, X509_OBJECT *ret); +int X509_LOOKUP_by_alias(X509_LOOKUP *ctx, int type, char *str, + int len, X509_OBJECT *ret); +int X509_LOOKUP_shutdown(X509_LOOKUP *ctx); + +#ifndef NO_STDIO +int X509_STORE_load_locations (X509_STORE *ctx, + const char *file, const char *dir); +int X509_STORE_set_default_paths(X509_STORE *ctx); +#endif + +int X509_STORE_CTX_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, + CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func); +int X509_STORE_CTX_set_ex_data(X509_STORE_CTX *ctx,int idx,void *data); +void * X509_STORE_CTX_get_ex_data(X509_STORE_CTX *ctx,int idx); +int X509_STORE_CTX_get_error(X509_STORE_CTX *ctx); +void X509_STORE_CTX_set_error(X509_STORE_CTX *ctx,int s); +int X509_STORE_CTX_get_error_depth(X509_STORE_CTX *ctx); +X509 * X509_STORE_CTX_get_current_cert(X509_STORE_CTX *ctx); +STACK_OF(X509) *X509_STORE_CTX_get_chain(X509_STORE_CTX *ctx); +STACK_OF(X509) *X509_STORE_CTX_get1_chain(X509_STORE_CTX *ctx); +void X509_STORE_CTX_set_cert(X509_STORE_CTX *c,X509 *x); +void X509_STORE_CTX_set_chain(X509_STORE_CTX *c,STACK_OF(X509) *sk); +int X509_STORE_CTX_set_purpose(X509_STORE_CTX *ctx, int purpose); +int X509_STORE_CTX_set_trust(X509_STORE_CTX *ctx, int trust); +int X509_STORE_CTX_purpose_inherit(X509_STORE_CTX *ctx, int def_purpose, + int purpose, int trust); + +#ifdef __cplusplus +} +#endif +#endif + diff --git a/libsecurity_apple_csp/open_ssl/opensslUtils/opensslAsn1.cpp b/libsecurity_apple_csp/open_ssl/opensslUtils/opensslAsn1.cpp new file mode 100644 index 00000000..7a211b90 --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/opensslUtils/opensslAsn1.cpp @@ -0,0 +1,1837 @@ +/* + * 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. + */ + + +/* + * opensslAsn1.h - ANS1 encode/decode of openssl object, libssnasn1 version + */ +#include "opensslAsn1.h" +#include "BinaryKey.h" +#include "AppleCSPUtils.h" +#include "opensshCoding.h" +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#define sslAsn1Debug(args...) secdebug("sslAsn1", ##args) + +#ifndef NDEBUG +/* set to 1 to see all ASN related errors */ +#define LOG_ASN_ERRORS 0 +#else +#define LOG_ASN_ERRORS 0 +#endif + +#if LOG_ASN_ERRORS +#include +#include + +static void logAsnErr( + const char *op, + PRErrorCode perr) +{ + printf("Error on %s: %s\n", op, SECErrorString(perr)); +} +#else +#define logAsnErr(op, perr) +#endif /* LOG_ASN_ERRORS */ + +/* CSSM_DATA --> BIGNUM */ +BIGNUM *cssmDataToBn( + const CSSM_DATA &cdata) +{ + BIGNUM *bn = BN_new(); + BIGNUM *rtn; + + rtn = BN_bin2bn(cdata.Data, cdata.Length, bn); + if(rtn == NULL) { + BN_free(bn); + CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR); + } + return bn; +} + +/* BIGNUM --> CSSM_DATA, mallocing from a SecNssCoder's PL_ArenaPool */ +void bnToCssmData( + const BIGNUM *bn, + CSSM_DATA &cdata, + SecNssCoder &coder) +{ + assert(bn != NULL); + unsigned numBytes = BN_num_bytes(bn); + cdata.Data = (uint8 *)coder.malloc(numBytes); + if(cdata.Data == NULL) { + CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR); + } + cdata.Length = numBytes; + BN_bn2bin(bn, cdata.Data); +} + +/* + * CSSM_DATA --> unsigned int + */ +unsigned cssmDataToInt( + const CSSM_DATA &cdata) +{ + if((cdata.Length == 0) || (cdata.Data == NULL)) { + return 0; + } + unsigned len = (unsigned)cdata.Length; + if(len > sizeof(int)) { + logAsnErr("cssmDataToInt: Length error (%u)", len); + CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_ALG_PARAMS); + } + + unsigned rtn = 0; + uint8 *cp = cdata.Data; + for(unsigned i=0; i CSSM_DATA, mallocing from an SecNssCoder + */ +void intToCssmData( + unsigned num, + CSSM_DATA &cdata, + SecNssCoder &coder) +{ + unsigned len = 0; + + if(num < 0x100) { + len = 1; + } + else if(num < 0x10000) { + len = 2; + } + else if(num < 0x1000000) { + len = 3; + } + else { + len = 4; + } + cdata.Data = (uint8 *)coder.malloc(len); + cdata.Length = len; + uint8 *cp = &cdata.Data[len - 1]; + for(unsigned i=0; i>= 8; + } +} + +/* + * Set up a encoded NULL for AlgorithmIdentifier.parameters, + * required for RSA + */ +static void nullAlgParams( + CSSM_X509_ALGORITHM_IDENTIFIER &algId) +{ + static const uint8 encNull[2] = { SEC_ASN1_NULL, 0 }; + CSSM_DATA encNullData; + encNullData.Data = (uint8 *)encNull; + encNullData.Length = 2; + + algId.parameters = encNullData; +} + +#pragma mark - +#pragma mark *** RSA key encode/decode *** + +/* + * DER encode/decode RSA keys in various formats. + * + * Public key, CSSM_KEYBLOB_RAW_FORMAT_PKCS1 + * -- compatible with BSAFE + * -- used for CSSM_KEYBLOB_RAW_FORMAT_DIGEST on both keys + */ +static CSSM_RETURN RSAPublicKeyDecodePKCS1( + SecNssCoder &coder, + RSA *openKey, + void *p, + size_t length) +{ + NSS_RSAPublicKeyPKCS1 nssPubKey; + + memset(&nssPubKey, 0, sizeof(nssPubKey)); + PRErrorCode perr = coder.decode(p, length, + kSecAsn1RSAPublicKeyPKCS1Template, &nssPubKey); + if(perr) { + logAsnErr("decode(RSAPublicKeyPKCS1)", perr); + return CSSMERR_CSP_INVALID_KEY; + } + + try { + openKey->n = cssmDataToBn(nssPubKey.modulus); + openKey->e = cssmDataToBn(nssPubKey.publicExponent); + } + catch(...) { + return CSSMERR_CSP_MEMORY_ERROR; + } + return 0; +} + +static CSSM_RETURN RSAPublicKeyEncodePKCS1( + SecNssCoder &coder, + RSA *openKey, + CssmOwnedData &encodedKey) +{ + /* convert to NSS_RSAPublicKeyPKCS1 */ + NSS_RSAPublicKeyPKCS1 nssPubKey; + + try { + bnToCssmData(openKey->n, nssPubKey.modulus, coder); + bnToCssmData(openKey->e, nssPubKey.publicExponent, coder); + } + catch(...) { + return CSSMERR_CSP_MEMORY_ERROR; + } + + PRErrorCode prtn; + prtn = SecNssEncodeItemOdata(&nssPubKey, + kSecAsn1RSAPublicKeyPKCS1Template, encodedKey); + if(prtn) { + return CSSMERR_CSP_MEMORY_ERROR; + } + return CSSM_OK; +} + +/* + * SubjectPublicKeyInfo, as used by openssl. + * The subjectPublicKey component is a PKCS1-style RSAPublicKey. + */ +static CSSM_RETURN RSAPublicKeyDecodeX509( + SecNssCoder &coder, + RSA *openKey, + void *p, + CSSM_SIZE length, + /* mallocd/returned encoded alg params for OAEP key */ + uint8 **algParams, + CSSM_SIZE *algParamLen) +{ + CSSM_X509_SUBJECT_PUBLIC_KEY_INFO nssPubKeyInfo; + PRErrorCode perr; + + memset(&nssPubKeyInfo, 0, sizeof(nssPubKeyInfo)); + perr = coder.decode(p, length, kSecAsn1SubjectPublicKeyInfoTemplate, + &nssPubKeyInfo); + if(perr) { + logAsnErr("decode(RSA SubjectPublicKeyInfo)", perr); + return CSSMERR_CSP_INVALID_KEY; + } + + /* verify alg identifier */ + const CSSM_OID *oid = &nssPubKeyInfo.algorithm.algorithm; + if(!cspCompareCssmData(oid, &CSSMOID_RSA)) { + if(!cspCompareCssmData(oid, &CSSMOID_RSAWithOAEP)) { + sslAsn1Debug("RSAPublicKeyDecodeX509: bad OID"); + return CSSMERR_CSP_INVALID_KEY; + } + if(nssPubKeyInfo.algorithm.parameters.Data != NULL) { + uint32 len = nssPubKeyInfo.algorithm.parameters.Length; + *algParams = (uint8 *)malloc(len); + memmove(*algParams, nssPubKeyInfo.algorithm.parameters.Data, len); + *algParamLen = len; + } + } + + /* decode the raw bits */ + CSSM_DATA *pubKey = &nssPubKeyInfo.subjectPublicKey; + /* decoded length was in bits */ + pubKey->Length = (pubKey->Length + 7) / 8; + return RSAPublicKeyDecodePKCS1(coder, openKey, pubKey->Data, + pubKey->Length); +} + +static CSSM_RETURN RSAPublicKeyEncodeX509( + SecNssCoder &coder, + RSA *openKey, + CssmOwnedData &encodedKey, + /* encoded alg params for OAEP key */ + uint8 *algParams, + uint32 algParamsLen) +{ + CssmAutoData aData(Allocator::standard()); + CSSM_RETURN crtn; + + /* First get an encoded PKCS1-style RSAPublicKey */ + crtn = RSAPublicKeyEncodePKCS1(coder, openKey, aData); + if(crtn) { + return crtn; + } + + /* + * That's the AsnBits subjectPublicKey component of a + * SubjectPublicKeyInfo + */ + CSSM_X509_SUBJECT_PUBLIC_KEY_INFO nssPubKeyInfo; + memset(&nssPubKeyInfo, 0, sizeof(nssPubKeyInfo)); + nssPubKeyInfo.subjectPublicKey.Data = (uint8 *)aData.data(); + nssPubKeyInfo.subjectPublicKey.Length = aData.length() * 8; + + CSSM_X509_ALGORITHM_IDENTIFIER &algId = nssPubKeyInfo.algorithm; + algId.algorithm = CSSMOID_RSA; + + if(algParams) { + algId.parameters.Data = (uint8 *)algParams; + algId.parameters.Length = algParamsLen; + } + else { + /* NULL algorithm parameters */ + nullAlgParams(algId); + } + + /* DER encode */ + PRErrorCode perr; + perr = SecNssEncodeItemOdata(&nssPubKeyInfo, + kSecAsn1SubjectPublicKeyInfoTemplate, encodedKey); + + if(perr) { + logAsnErr("encode(RSA SubjectPublicKeyInfo)", perr); + return CSSMERR_CSP_MEMORY_ERROR; + } + return CSSM_OK; +} + +/* + * RSA private key, PKCS1 format, used by openssl. + */ +static CSSM_RETURN RSAPrivateKeyDecodePKCS1( + SecNssCoder &coder, + RSA *openKey, + void *p, + size_t length) +{ + NSS_RSAPrivateKeyPKCS1 nssPrivKey; + PRErrorCode perr; + + memset(&nssPrivKey, 0, sizeof(nssPrivKey)); + perr = coder.decode(p, length, kSecAsn1RSAPrivateKeyPKCS1Template, &nssPrivKey); + if(perr) { + logAsnErr("decode(RSAPrivateKeyPKCS)", perr); + return CSSMERR_CSP_INVALID_KEY; + } + + /* convert nssPrivKey fields to RSA key fields */ + try { + openKey->version = cssmDataToInt(nssPrivKey.version); + openKey->n = cssmDataToBn(nssPrivKey.modulus); + openKey->e = cssmDataToBn(nssPrivKey.publicExponent); + openKey->d = cssmDataToBn(nssPrivKey.privateExponent); + openKey->p = cssmDataToBn(nssPrivKey.prime1); + openKey->q = cssmDataToBn(nssPrivKey.prime2); + openKey->dmp1 = cssmDataToBn(nssPrivKey.exponent1); + openKey->dmq1 = cssmDataToBn(nssPrivKey.exponent2); + openKey->iqmp = cssmDataToBn(nssPrivKey.coefficient); + } + catch(...) { + return CSSMERR_CSP_MEMORY_ERROR; + } + return 0; +} + +static CSSM_RETURN RSAPrivateKeyEncodePKCS1( + SecNssCoder &coder, + RSA *openKey, + CssmOwnedData &encodedKey) +{ + NSS_RSAPrivateKeyPKCS1 nssPrivKey; + PRErrorCode perr; + + /* convert to NSS_RSAPrivateKeyPKCS1 */ + try { + intToCssmData(openKey->version, nssPrivKey.version, coder); + bnToCssmData(openKey->n, nssPrivKey.modulus, coder); + bnToCssmData(openKey->e, nssPrivKey.publicExponent, coder); + bnToCssmData(openKey->d, nssPrivKey.privateExponent, coder); + bnToCssmData(openKey->p, nssPrivKey.prime1, coder); + bnToCssmData(openKey->q, nssPrivKey.prime2, coder); + bnToCssmData(openKey->dmp1, nssPrivKey.exponent1, coder); + bnToCssmData(openKey->dmq1, nssPrivKey.exponent2, coder); + bnToCssmData(openKey->iqmp, nssPrivKey.coefficient, coder); + } + catch(...) { + /* ? */ + return CSSMERR_CSP_MEMORY_ERROR; + } + + /* DER encode */ + perr = SecNssEncodeItemOdata(&nssPrivKey, kSecAsn1RSAPrivateKeyPKCS1Template, + encodedKey); + if(perr) { + logAsnErr("encode(RSAPrivateKeyPKCS1)", perr); + return CSSMERR_CSP_MEMORY_ERROR; + } + return CSSM_OK; +} + +/* + * RSA private key, PKCS8, compatible with BSAFE. + */ +static CSSM_RETURN RSAPrivateKeyDecodePKCS8( + SecNssCoder &coder, + RSA *openKey, + void *p, + CSSM_SIZE length, + /* mallocd/returned encoded alg params for OAEP key */ + uint8 **algParams, + CSSM_SIZE *algParamLen) +{ + NSS_PrivateKeyInfo nssPrivKeyInfo; + PRErrorCode perr; + + memset(&nssPrivKeyInfo, 0, sizeof(nssPrivKeyInfo)); + perr = coder.decode(p, length, kSecAsn1PrivateKeyInfoTemplate, &nssPrivKeyInfo); + if(perr) { + logAsnErr("decode(PrivateKeyInfo)", perr); + return CSSMERR_CSP_INVALID_KEY; + } + + /* verify alg identifier */ + const CSSM_OID *oid = &nssPrivKeyInfo.algorithm.algorithm; + if(!cspCompareCssmData(oid, &CSSMOID_RSA)) { + if(!cspCompareCssmData(oid, &CSSMOID_RSAWithOAEP)) { + sslAsn1Debug("RSAPrivateKeyDecodePKCS8: bad OID"); + return CSSMERR_CSP_INVALID_KEY; + } + if(nssPrivKeyInfo.algorithm.parameters.Data != NULL) { + uint32 len = nssPrivKeyInfo.algorithm.parameters.Length; + *algParams = (uint8 *)malloc(len); + memmove(*algParams, nssPrivKeyInfo.algorithm.parameters.Data, len); + *algParamLen = len; + } + } + + /* + * nssPrivKeyInfo.privateKey is an octet string which needs + * subsequent decoding + */ + CSSM_DATA *privKey = &nssPrivKeyInfo.privateKey; + return RSAPrivateKeyDecodePKCS1(coder, openKey, + privKey->Data, privKey->Length); +} + +static CSSM_RETURN RSAPrivateKeyEncodePKCS8( + SecNssCoder &coder, + RSA *openKey, + CssmOwnedData &encodedKey, + /* encoded alg params for OAEP key */ + uint8 *algParams, + uint32 algParamsLen) +{ + + /* First get PKCS1-style encoding */ + CssmAutoData aData(Allocator::standard()); + CSSM_RETURN crtn = RSAPrivateKeyEncodePKCS1(coder, openKey, aData); + if(crtn) { + return crtn; + } + + /* that encoding is the privateKey field of a NSS_PrivateKeyInfo */ + NSS_PrivateKeyInfo nssPrivKeyInfo; + memset(&nssPrivKeyInfo, 0, sizeof(nssPrivKeyInfo)); + nssPrivKeyInfo.privateKey.Data = (uint8 *)aData.data(); + nssPrivKeyInfo.privateKey.Length = aData.length(); + + CSSM_X509_ALGORITHM_IDENTIFIER &algId = nssPrivKeyInfo.algorithm; + algId.algorithm = CSSMOID_RSA; + + if(algParams) { + algId.parameters.Data = (uint8 *)algParams; + algId.parameters.Length = algParamsLen; + } + else { + /* NULL algorithm parameters */ + nullAlgParams(algId); + } + + /* FIXME : attributes? */ + + uint8 vers = 0; + nssPrivKeyInfo.version.Data = &vers; + nssPrivKeyInfo.version.Length = 1; + + /* DER encode */ + PRErrorCode perr; + perr = SecNssEncodeItemOdata(&nssPrivKeyInfo, + kSecAsn1PrivateKeyInfoTemplate, encodedKey); + + if(perr) { + logAsnErr("encode(RSA PrivateKeyInfo)", perr); + return CSSMERR_CSP_MEMORY_ERROR; + } + return CSSM_OK; +} + +CSSM_RETURN RSAPublicKeyDecode( + RSA *openKey, + CSSM_KEYBLOB_FORMAT format, + void *p, + size_t length) +{ + SecNssCoder coder; + + switch(format) { + case CSSM_KEYBLOB_RAW_FORMAT_PKCS1: + return RSAPublicKeyDecodePKCS1(coder, openKey, p, length); + case CSSM_KEYBLOB_RAW_FORMAT_X509: + return RSAPublicKeyDecodeX509(coder, openKey, p, length, NULL, NULL); + case CSSM_KEYBLOB_RAW_FORMAT_OPENSSH: + return RSAPublicKeyDecodeOpenSSH1(openKey, p, length); + case CSSM_KEYBLOB_RAW_FORMAT_OPENSSH2: + return RSAPublicKeyDecodeOpenSSH2(openKey, p, length); + default: + assert(0); + return CSSMERR_CSP_INTERNAL_ERROR; + } +} + +CSSM_RETURN RSAPublicKeyEncode( + RSA *openKey, + CSSM_KEYBLOB_FORMAT format, + const CssmData &descData, + CssmOwnedData &encodedKey) +{ + SecNssCoder coder; + + switch(format) { + case CSSM_KEYBLOB_RAW_FORMAT_PKCS1: + return RSAPublicKeyEncodePKCS1(coder, openKey, encodedKey); + case CSSM_KEYBLOB_RAW_FORMAT_X509: + return RSAPublicKeyEncodeX509(coder, openKey, encodedKey, NULL, 0); + case CSSM_KEYBLOB_RAW_FORMAT_OPENSSH: + return RSAPublicKeyEncodeOpenSSH1(openKey, descData, encodedKey); + case CSSM_KEYBLOB_RAW_FORMAT_OPENSSH2: + return RSAPublicKeyEncodeOpenSSH2(openKey, descData, encodedKey); + default: + assert(0); + return CSSMERR_CSP_INTERNAL_ERROR; + } +} + +CSSM_RETURN RSAPrivateKeyDecode( + RSA *openKey, + CSSM_KEYBLOB_FORMAT format, + void *p, + size_t length) +{ + SecNssCoder coder; + + switch(format) { + case CSSM_KEYBLOB_RAW_FORMAT_PKCS1: + return RSAPrivateKeyDecodePKCS1(coder, openKey, p, length); + case CSSM_KEYBLOB_RAW_FORMAT_PKCS8: + return RSAPrivateKeyDecodePKCS8(coder, openKey, p, length, NULL, NULL); + case CSSM_KEYBLOB_RAW_FORMAT_OPENSSH: + return RSAPrivateKeyDecodeOpenSSH1(openKey, p, length); + default: + assert(0); + return CSSMERR_CSP_INTERNAL_ERROR; + } +} + +CSSM_RETURN RSAPrivateKeyEncode( + RSA *openKey, + CSSM_KEYBLOB_FORMAT format, + const CssmData &descData, + CssmOwnedData &encodedKey) +{ + SecNssCoder coder; + + switch(format) { + case CSSM_KEYBLOB_RAW_FORMAT_PKCS1: + return RSAPrivateKeyEncodePKCS1(coder, openKey, encodedKey); + case CSSM_KEYBLOB_RAW_FORMAT_PKCS8: + return RSAPrivateKeyEncodePKCS8(coder, openKey, encodedKey, NULL, 0); + case CSSM_KEYBLOB_RAW_FORMAT_OPENSSH: + return RSAPrivateKeyEncodeOpenSSH1(openKey, descData, encodedKey); + default: + assert(0); + return CSSMERR_CSP_INTERNAL_ERROR; + } +} + +CSSM_RETURN RSAOAEPPrivateKeyEncode( + RSA *openKey, + const CSSM_DATA *label, + CssmOwnedData &encodedKey) +{ + SecNssCoder coder; + CSSM_DATA encodedParams = {0, NULL}; + /* TBD encode the label into a RSAES-OAEP-params */ + + return RSAPrivateKeyEncodePKCS8(coder, openKey, encodedKey, encodedParams.Data, encodedParams.Length); +} + +CSSM_RETURN RSAOAEPPublicKeyEncode( + RSA *openKey, + const CSSM_DATA *label, + CssmOwnedData &encodedKey) +{ + SecNssCoder coder; + CSSM_DATA encodedParams = {0, NULL}; + /* TBD encode the label into a RSAES-OAEP-params */ + + return RSAPublicKeyEncodeX509(coder, openKey, encodedKey, encodedParams.Data, encodedParams.Length); +} + +CSSM_RETURN RSAOAEPPublicKeyDecode( + RSA *openKey, + void *p, + size_t length, + /* mallocd and returned label */ + CSSM_DATA *label) +{ + SecNssCoder coder; + CSSM_RETURN crtn; + CSSM_DATA encodedParams = {0, NULL}; + + crtn = RSAPublicKeyDecodeX509(coder, openKey, p, length, &encodedParams.Data, + &encodedParams.Length); + if(crtn) { + return crtn; + } + + /* TBD - decode label from encoded alg params */ + label->Data = NULL; + label->Length = 0; + return CSSM_OK; +} + +CSSM_RETURN RSAOAEPPrivateKeyDecode( + RSA *openKey, + void *p, + size_t length, + /* mallocd and returned label */ + CSSM_DATA *label) +{ + SecNssCoder coder; + CSSM_RETURN crtn; + CSSM_DATA encodedParams = {0, NULL}; + + crtn = RSAPrivateKeyDecodePKCS8(coder, openKey, p, length, &encodedParams.Data, + &encodedParams.Length); + if(crtn) { + return crtn; + } + + /* TBD - decode label from encoded alg params */ + label->Data = NULL; + label->Length = 0; + return CSSM_OK; +} + +#pragma mark - +#pragma mark *** DSA key encode/decode *** + +/*** + *** DSA + ***/ + +/* NSS_DSAAlgorithmIdBSAFE <--> DSA->{p,g,q} */ +static void dsaToNssAlgIdBSAFE( + const DSA *openKey, + NSS_DSAAlgorithmIdBSAFE &algId, + SecNssCoder &coder) +{ + /* non-standard, BSAFE-specific OID */ + algId.algorithm = CSSMOID_DSA; // not mallocd + unsigned numBits = BN_num_bits(openKey->p); + intToCssmData(numBits, algId.params.keySizeInBits, coder); + bnToCssmData(openKey->p, algId.params.p, coder); + bnToCssmData(openKey->q, algId.params.q, coder); + bnToCssmData(openKey->g, algId.params.g, coder); +} + +static CSSM_RETURN nssAlgIdToDsaBSAFE( + NSS_DSAAlgorithmIdBSAFE &algId, + DSA *openKey) +{ + /* non-standard, BSAFE-specific OID */ + if(!cspCompareCssmData(&algId.algorithm, &CSSMOID_DSA)) { + sslAsn1Debug("nssAlgIdToDsaBSAFE: bad OID"); + return CSSMERR_CSP_INVALID_KEY; + } + openKey->p = cssmDataToBn(algId.params.p); + openKey->q = cssmDataToBn(algId.params.q); + openKey->g = cssmDataToBn(algId.params.g); + return CSSM_OK; +} + +/* NSS_DSAAlgorithmIdX509 <--> DSA->{p,g,q} */ +static void dsaToNssAlgIdX509( + const DSA *openKey, + NSS_DSAAlgorithmIdX509 &algId, + SecNssCoder &coder) +{ + algId.algorithm = CSSMOID_DSA_CMS; // not mallocd + bnToCssmData(openKey->p, algId.params->p, coder); + bnToCssmData(openKey->q, algId.params->q, coder); + bnToCssmData(openKey->g, algId.params->g, coder); +} + +static CSSM_RETURN nssAlgIdToDsaX509( + NSS_DSAAlgorithmIdX509 &algId, + DSA *openKey) +{ + if(!cspCompareCssmData(&algId.algorithm, &CSSMOID_DSA_CMS) && + !cspCompareCssmData(&algId.algorithm, &CSSMOID_DSA_JDK)) { + sslAsn1Debug("nssAlgIdToDsaX509: bad OID"); + return CSSMERR_CSP_INVALID_KEY; + } + /* these might be absent per CMS */ + if(algId.params == NULL) { + return CSSM_OK; + } + openKey->p = cssmDataToBn(algId.params->p); + openKey->q = cssmDataToBn(algId.params->q); + openKey->g = cssmDataToBn(algId.params->g); + return CSSM_OK; +} + +/* + * DSA public keys, FIPS186 format. + * Compatible with BSAFE. + */ +CSSM_RETURN DSAPublicKeyDecodeFIPS186( + SecNssCoder &coder, + DSA *openKey, + void *p, + unsigned length) +{ + NSS_DSAPublicKeyBSAFE nssPubKey; + PRErrorCode perr; + CSSM_RETURN crtn; + + memset(&nssPubKey, 0, sizeof(nssPubKey)); + perr = coder.decode(p, length, kSecAsn1DSAPublicKeyBSAFETemplate, + &nssPubKey); + if(perr) { + logAsnErr("decode(DSAPublicKeyBSAFE)", perr); + return CSSMERR_CSP_INVALID_KEY; + } + + /* BSAFE style DSA-specific alg params */ + NSS_DSAAlgorithmIdBSAFE &algId = nssPubKey.dsaAlg; + crtn = nssAlgIdToDsaBSAFE(algId, openKey); + if(crtn) { + return crtn; + } + + /* inside of nssPubKey.publicKey is the DER-encoding of a + * ASN Integer; decoded length was in bits */ + nssPubKey.publicKey.Length = (nssPubKey.publicKey.Length + 7) / 8; + CSSM_DATA pubKeyBytes; + perr = coder.decodeItem(nssPubKey.publicKey, + kSecAsn1UnsignedIntegerTemplate, + &pubKeyBytes); + if(perr) { + logAsnErr("decode(NSS_DSAPublicKeyBSAFE.publicKey)", perr); + return CSSMERR_CSP_INVALID_KEY; + } + openKey->pub_key = cssmDataToBn(pubKeyBytes); + + if(openKey->pub_key == NULL) { + return CSSMERR_CSP_INVALID_KEY; + } + return 0; +} + +CSSM_RETURN DSAPublicKeyEncodeFIPS186( + SecNssCoder &coder, + DSA *openKey, + CssmOwnedData &encodedKey) +{ + try { + /* convert to NSS_DSAPublicKeyBSAFE */ + NSS_DSAPublicKeyBSAFE nssPubKey; + memset(&nssPubKey, 0, sizeof(nssPubKey)); + dsaToNssAlgIdBSAFE(openKey, nssPubKey.dsaAlg, coder); + + /* + * publicKey is the DER-encoding of a ASN INTEGER wrapped in + * an AsnBits + */ + CSSM_DATA pubKeyRaw; + PRErrorCode perr; + bnToCssmData(openKey->pub_key, pubKeyRaw, coder); + perr = coder.encodeItem(&pubKeyRaw, kSecAsn1UnsignedIntegerTemplate, + nssPubKey.publicKey); + if(perr) { + logAsnErr("encodeItem(DSAPublicKeyBSAFE.publicKey)", perr); + return CSSMERR_CSP_MEMORY_ERROR; + } + nssPubKey.publicKey.Length *= 8; + + /* DER encode */ + SecNssEncodeItemOdata(&nssPubKey, kSecAsn1DSAPublicKeyBSAFETemplate, + encodedKey); + return CSSM_OK; + } + catch(...) { + /* ? */ + return CSSMERR_CSP_MEMORY_ERROR; + } +} + +/* + * DSA private keys, FIPS186 format. + * Compatible with BSAFE. + */ +CSSM_RETURN DSAPrivateKeyDecodeFIPS186( + SecNssCoder &coder, + DSA *openKey, + void *p, + unsigned length) +{ + NSS_DSAPrivateKeyBSAFE nssPrivKeyInfo; + PRErrorCode perr; + + memset(&nssPrivKeyInfo, 0, sizeof(nssPrivKeyInfo)); + perr = coder.decode(p, length, kSecAsn1DSAPrivateKeyBSAFETemplate, + &nssPrivKeyInfo); + if(perr) { + logAsnErr("decode(DSA PrivateKeyInfo)", perr); + return CSSMERR_CSP_INVALID_KEY; + } + + CSSM_RETURN crtn = nssAlgIdToDsaBSAFE(nssPrivKeyInfo.dsaAlg, openKey); + if(crtn) { + return crtn; + } + + /* nssPrivKeyInfo.privateKey is the DER-encoding of a + * DSAPrivateKeyOcts... */ + try { + PRErrorCode perr; + NSS_DSAPrivateKeyOcts keyOcts; + + perr = coder.decodeItem(nssPrivKeyInfo.privateKey, + kSecAsn1DSAPrivateKeyOctsTemplate, &keyOcts); + if(perr) { + logAsnErr("decode(DSA PrivateKeyInfoOcts)", perr); + return CSSMERR_CSP_INVALID_KEY; + } + + openKey->priv_key = cssmDataToBn(keyOcts.privateKey); + if(openKey->priv_key == NULL) { + return CSSMERR_CSP_INVALID_KEY; + } + return 0; + } + catch(...) { + return CSSMERR_CSP_INVALID_KEY; + } +} + +CSSM_RETURN DSAPrivateKeyEncodeFIPS186( + SecNssCoder &coder, + DSA *openKey, + CssmOwnedData &encodedKey) +{ + try { + /* First convert into a NSS_DSAPrivateKeyBSAFE */ + NSS_DSAPrivateKeyBSAFE nssPrivKey; + intToCssmData(openKey->version, nssPrivKey.version, coder); + dsaToNssAlgIdBSAFE(openKey, nssPrivKey.dsaAlg, coder); + + /* nssPrivKey.privateKey is the DER-encoding of one of these... */ + NSS_DSAPrivateKeyOcts privKeyOcts; + bnToCssmData(openKey->priv_key, privKeyOcts.privateKey, coder); + + /* DER encode the privateKey portion into arena pool memory + * into NSS_DSAPrivateKeyPKCS8.privateKey */ + coder.encodeItem(&privKeyOcts, kSecAsn1DSAPrivateKeyOctsTemplate, + nssPrivKey.privateKey); + + /* DER encode the whole thing */ + PRErrorCode perr; + perr = SecNssEncodeItemOdata(&nssPrivKey, + kSecAsn1DSAPrivateKeyBSAFETemplate, encodedKey); + return 0; + } + catch(...) { + /* ? */ + return CSSMERR_CSP_MEMORY_ERROR; + } +} + +/* + * DSA private keys, PKCS8/SMIME format. + */ +CSSM_RETURN DSAPrivateKeyDecodePKCS8( + SecNssCoder &coder, + DSA *openKey, + void *p, + unsigned length) +{ + NSS_DSAPrivateKeyPKCS8 nssPrivKeyInfo; + PRErrorCode perr; + + memset(&nssPrivKeyInfo, 0, sizeof(nssPrivKeyInfo)); + perr = coder.decode(p, length, kSecAsn1DSAPrivateKeyPKCS8Template, + &nssPrivKeyInfo); + if(perr) { + logAsnErr("decode(DSA NSS_DSAPrivateKeyPKCS8)", perr); + return CSSMERR_CSP_INVALID_KEY; + } + + CSSM_RETURN crtn = nssAlgIdToDsaX509(nssPrivKeyInfo.dsaAlg, openKey); + if(crtn) { + return crtn; + } + + /* + * Post-decode, nssPrivKeyInfo.privateKey is the DER-encoding of a + * an ASN integer. + */ + try { + PRErrorCode perr; + CSSM_DATA privKeyInt = {0, NULL}; + + perr = coder.decodeItem(nssPrivKeyInfo.privateKey, + kSecAsn1UnsignedIntegerTemplate, &privKeyInt); + if(perr) { + logAsnErr("decode(DSA nssPrivKeyInfo.privateKey)", perr); + return CSSMERR_CSP_INVALID_KEY; + } + + openKey->priv_key = cssmDataToBn(privKeyInt); + if(openKey->priv_key == NULL) { + return CSSMERR_CSP_INVALID_KEY; + } + return 0; + } + catch(...) { + return CSSMERR_CSP_INVALID_KEY; + } +} + +CSSM_RETURN DSAPrivateKeyEncodePKCS8( + SecNssCoder &coder, + DSA *openKey, + CssmOwnedData &encodedKey) +{ + try { + /* First convert into a NSS_DSAPrivateKeyPKCS8 */ + NSS_DSAPrivateKeyPKCS8 nssPrivKey; + NSS_DSAAlgParams algParams; + memset(&nssPrivKey, 0, sizeof(nssPrivKey)); + memset(&algParams, 0, sizeof(algParams)); + nssPrivKey.dsaAlg.params = &algParams; + intToCssmData(openKey->version, nssPrivKey.version, coder); + dsaToNssAlgIdX509(openKey, nssPrivKey.dsaAlg, coder); + + /* pre-encode, nssPrivKey.privateKey is the DER-encoding of + * an ASN integer... */ + CSSM_DATA privKeyInt; + bnToCssmData(openKey->priv_key, privKeyInt, coder); + + /* DER encode the privateKey portion into arena pool memory + * into NSS_DSAPrivateKeyPKCS8.privateKey */ + coder.encodeItem(&privKeyInt, kSecAsn1UnsignedIntegerTemplate, + nssPrivKey.privateKey); + + /* DER encode the whole thing */ + PRErrorCode perr; + perr = SecNssEncodeItemOdata(&nssPrivKey, + kSecAsn1DSAPrivateKeyPKCS8Template, encodedKey); + return 0; + } + catch(...) { + /* ? */ + return CSSMERR_CSP_MEMORY_ERROR; + } +} + +/* + * DSA public key, X509/openssl format. + */ +static CSSM_RETURN DSAPublicKeyDecodeX509( + SecNssCoder &coder, + DSA *openKey, + void *p, + size_t length) +{ + NSS_DSAPublicKeyX509 nssPubKey; + PRErrorCode perr; + CSSM_RETURN crtn; + + memset(&nssPubKey, 0, sizeof(nssPubKey)); + perr = coder.decode(p, length, kSecAsn1DSAPublicKeyX509Template, + &nssPubKey); + if(perr) { + logAsnErr("decode(DSAPublicKeyX509)", perr); + return CSSMERR_CSP_INVALID_KEY; + } + + /* X509 style DSA-specific alg params */ + NSS_DSAAlgorithmIdX509 &algId = nssPubKey.dsaAlg; + crtn = nssAlgIdToDsaX509(algId, openKey); + if(crtn) { + return crtn; + } + + /* inside of nssPubKey.publicKey is the DER-encoding of a + * ASN Integer; decoded length was in bits */ + nssPubKey.publicKey.Length = (nssPubKey.publicKey.Length + 7) / 8; + CSSM_DATA pubKeyBytes = {0, NULL}; + perr = coder.decodeItem(nssPubKey.publicKey, + kSecAsn1UnsignedIntegerTemplate, + &pubKeyBytes); + if(perr) { + logAsnErr("decode(NSS_DSAPublicKeyX509.publicKey)", perr); + return CSSMERR_CSP_INVALID_KEY; + } + openKey->pub_key = cssmDataToBn(pubKeyBytes); + + if(openKey->pub_key == NULL) { + return CSSMERR_CSP_INVALID_KEY; + } + return 0; +} + +static CSSM_RETURN DSAPublicKeyEncodeX509( + SecNssCoder &coder, + DSA *openKey, + CssmOwnedData &encodedKey) +{ + try { + /* convert to NSS_DSAPublicKeyX509 */ + NSS_DSAPublicKeyX509 nssPubKey; + NSS_DSAAlgParams algParams; + memset(&nssPubKey, 0, sizeof(nssPubKey)); + memset(&algParams, 0, sizeof(algParams)); + nssPubKey.dsaAlg.params = &algParams; + dsaToNssAlgIdX509(openKey, nssPubKey.dsaAlg, coder); + + /* + * publicKey is the DER-encoding of a ASN INTEGER wrapped in + * an AsnBits + */ + CSSM_DATA pubKeyRaw; + PRErrorCode perr; + bnToCssmData(openKey->pub_key, pubKeyRaw, coder); + perr = coder.encodeItem(&pubKeyRaw, kSecAsn1UnsignedIntegerTemplate, + nssPubKey.publicKey); + if(perr) { + logAsnErr("encodeItem(DSAPublicKeyX509.publicKey)", perr); + return CSSMERR_CSP_MEMORY_ERROR; + } + nssPubKey.publicKey.Length *= 8; + + /* DER encode */ + SecNssEncodeItemOdata(&nssPubKey, kSecAsn1DSAPublicKeyX509Template, + encodedKey); + return CSSM_OK; + } + catch(...) { + /* ? */ + return CSSMERR_CSP_MEMORY_ERROR; + } +} + +/* + * Encode public key portion only for calculating key digest. + * Note this works just fine on a partial DSA public key, i.e., + * A DSA public key's digest-capable blob is the same whether or + * not the DSA key has its DSA parameters p, q, and g. + */ +static CSSM_RETURN DSAPublicKeyEncodeHashable( + SecNssCoder &coder, + DSA *openKey, + CssmOwnedData &encodedKey) +{ + try { + /* + * publicKey is the DER-encoding of an ASN integer + */ + CSSM_DATA pubKey; + bnToCssmData(openKey->pub_key, pubKey, coder); + PRErrorCode perr; + + perr = SecNssEncodeItemOdata(&pubKey, kSecAsn1UnsignedIntegerTemplate, + encodedKey); + if(perr) { + logAsnErr("encode(DSAPubHashable)", perr); + return CSSMERR_CSP_MEMORY_ERROR; + } + return CSSM_OK; + } + catch(...) { + /* ? */ + return CSSMERR_CSP_MEMORY_ERROR; + } +} + +/* + * DSA private key, custom openssl format. + */ +static CSSM_RETURN DSAPrivateKeyDecodeOpenssl( + SecNssCoder &coder, + DSA *openKey, + void *p, + size_t length) +{ + NSS_DSAPrivateKeyOpenssl nssPrivKey; + PRErrorCode perr; + + memset(&nssPrivKey, 0, sizeof(nssPrivKey)); + perr = coder.decode(p, length, kSecAsn1DSAPrivateKeyOpensslTemplate, + &nssPrivKey); + if(perr) { + logAsnErr("decode(DSAPrivateKeyOpenssl)", perr); + return CSSMERR_CSP_INVALID_KEY; + } + + /* convert nssPrivKey fields to RSA key fields */ + try { + openKey->version = cssmDataToInt(nssPrivKey.version); + openKey->p = cssmDataToBn(nssPrivKey.p); + openKey->q = cssmDataToBn(nssPrivKey.q); + openKey->g = cssmDataToBn(nssPrivKey.g); + openKey->pub_key = cssmDataToBn(nssPrivKey.pub); + openKey->priv_key = cssmDataToBn(nssPrivKey.priv); + } + catch(...) { + return CSSMERR_CSP_MEMORY_ERROR; + } + return 0; +} + +static CSSM_RETURN DSAPrivateKeyEncodeOpenssl( + SecNssCoder &coder, + DSA *openKey, + CssmOwnedData &encodedKey) +{ + NSS_DSAPrivateKeyOpenssl nssPrivKey; + PRErrorCode perr; + + /* convert to NSS_DSAPrivateKeyOpenssl */ + try { + intToCssmData(openKey->version, nssPrivKey.version, coder); + bnToCssmData(openKey->p, nssPrivKey.p, coder); + bnToCssmData(openKey->q, nssPrivKey.q, coder); + bnToCssmData(openKey->g, nssPrivKey.g, coder); + bnToCssmData(openKey->pub_key, nssPrivKey.pub, coder); + bnToCssmData(openKey->priv_key, nssPrivKey.priv, coder); + } + catch(...) { + /* ? */ + return CSSMERR_CSP_MEMORY_ERROR; + } + + /* DER encode */ + perr = SecNssEncodeItemOdata(&nssPrivKey, kSecAsn1DSAPrivateKeyOpensslTemplate, + encodedKey); + if(perr) { + logAsnErr("encode(DSAPrivateKeyOpenssl)", perr); + return CSSMERR_CSP_MEMORY_ERROR; + } + return CSSM_OK; +} + +CSSM_RETURN DSAPublicKeyDecode( + DSA *openKey, + CSSM_KEYBLOB_FORMAT format, + void *p, + size_t length) +{ + SecNssCoder coder; + + switch(format) { + case CSSM_KEYBLOB_RAW_FORMAT_FIPS186: + return DSAPublicKeyDecodeFIPS186(coder, openKey, p, length); + case CSSM_KEYBLOB_RAW_FORMAT_X509: + return DSAPublicKeyDecodeX509(coder, openKey, p, length); + case CSSM_KEYBLOB_RAW_FORMAT_OPENSSH2: + return DSAPublicKeyDecodeOpenSSH2(openKey, p, length); + default: + assert(0); + return CSSMERR_CSP_INTERNAL_ERROR; + } +} + +CSSM_RETURN DSAPublicKeyEncode( + DSA *openKey, + CSSM_KEYBLOB_FORMAT format, + const CssmData &descData, + CssmOwnedData &encodedKey) +{ + SecNssCoder coder; + + switch(format) { + case CSSM_KEYBLOB_RAW_FORMAT_FIPS186: + return DSAPublicKeyEncodeFIPS186(coder, openKey, encodedKey); + case CSSM_KEYBLOB_RAW_FORMAT_X509: + return DSAPublicKeyEncodeX509(coder, openKey, encodedKey); + case CSSM_KEYBLOB_RAW_FORMAT_DIGEST: + return DSAPublicKeyEncodeHashable(coder, openKey, encodedKey); + case CSSM_KEYBLOB_RAW_FORMAT_OPENSSH2: + return DSAPublicKeyEncodeOpenSSH2(openKey, descData, encodedKey); + default: + assert(0); + return CSSMERR_CSP_INTERNAL_ERROR; + } +} + +CSSM_RETURN DSAPrivateKeyDecode( + DSA *openKey, + CSSM_KEYBLOB_FORMAT format, + void *p, + size_t length) +{ + SecNssCoder coder; + + switch(format) { + case CSSM_KEYBLOB_RAW_FORMAT_FIPS186: + return DSAPrivateKeyDecodeFIPS186(coder, openKey, p, length); + case CSSM_KEYBLOB_RAW_FORMAT_OPENSSL: + return DSAPrivateKeyDecodeOpenssl(coder, openKey, p, length); + case CSSM_KEYBLOB_RAW_FORMAT_PKCS8: + return DSAPrivateKeyDecodePKCS8(coder, openKey, p, length); + default: + assert(0); + return CSSMERR_CSP_INTERNAL_ERROR; + } +} + +CSSM_RETURN DSAPrivateKeyEncode( + DSA *openKey, + CSSM_KEYBLOB_FORMAT format, + const CssmData &descData, + CssmOwnedData &encodedKey) +{ + SecNssCoder coder; + + switch(format) { + case CSSM_KEYBLOB_RAW_FORMAT_FIPS186: + return DSAPrivateKeyEncodeFIPS186(coder, openKey, encodedKey); + case CSSM_KEYBLOB_RAW_FORMAT_OPENSSL: + return DSAPrivateKeyEncodeOpenssl(coder, openKey, encodedKey); + case CSSM_KEYBLOB_RAW_FORMAT_PKCS8: + return DSAPrivateKeyEncodePKCS8(coder, openKey, encodedKey); + default: + assert(0); + return CSSMERR_CSP_INTERNAL_ERROR; + } +} + +#pragma mark - +#pragma mark *** DSA Signature encode/decode *** + +CSSM_RETURN DSASigEncode( + DSA_SIG *openSig, + CssmOwnedData &encodedSig) +{ + /* temp allocs from this pool */ + SecNssCoder coder; + /* convert to NSS_DSASignature */ + NSS_DSASignature nssSig; + + try { + bnToCssmData(openSig->r, nssSig.r, coder); + bnToCssmData(openSig->s, nssSig.s, coder); + } + catch(...) { + /* ? */ + return CSSMERR_CSP_MEMORY_ERROR; + } + + PRErrorCode prtn = SecNssEncodeItemOdata(&nssSig, + kSecAsn1DSASignatureTemplate, encodedSig); + if(prtn) { + return CSSMERR_CSP_MEMORY_ERROR; + } + return CSSM_OK; +} + +CSSM_RETURN DSASigDecode( + DSA_SIG *openSig, + const void *p, + unsigned length) +{ + NSS_DSASignature nssSig; + SecNssCoder coder; + + memset(&nssSig, 0, sizeof(nssSig)); + PRErrorCode perr = coder.decode(p, length, + kSecAsn1DSASignatureTemplate, &nssSig); + if(perr) { + logAsnErr("decode(DSASigDecode)", perr); + return CSSMERR_CSP_INVALID_SIGNATURE; + } + + try { + openSig->r = cssmDataToBn(nssSig.r); + openSig->s = cssmDataToBn(nssSig.s); + } + catch(...) { + return CSSMERR_CSP_MEMORY_ERROR; + } + return 0; +} + +#pragma mark - +#pragma mark *** DSA Algorithm Parameters encode/decode *** + +CSSM_RETURN DSAEncodeAlgParams( + NSS_DSAAlgParams &algParams, + CssmOwnedData &encodedParams) +{ + PRErrorCode prtn = SecNssEncodeItemOdata(&algParams, + kSecAsn1DSAAlgParamsTemplate, encodedParams); + if(prtn) { + return CSSMERR_CSP_MEMORY_ERROR; + } + return CSSM_OK; +} + +CSSM_RETURN DSADecodeAlgParams( + NSS_DSAAlgParams &algParams, + const void *p, + unsigned len, + SecNssCoder &coder) +{ + + memset(&algParams, 0, sizeof(algParams)); + PRErrorCode perr = coder.decode(p, len, + kSecAsn1DSAAlgParamsTemplate, &algParams); + if(perr) { + logAsnErr("decode(DSAAlgParams)", perr); + return CSSMERR_CSP_INVALID_ATTR_ALG_PARAMS; + } + return CSSM_OK; +} + +#pragma mark - +#pragma mark *** Diffie-Hellman key encode/decode *** + +CSSM_RETURN DHPrivateKeyDecodePKCS3( + SecNssCoder &coder, + DH *openKey, + unsigned char *p, + unsigned length) +{ + NSS_DHPrivateKey nssPrivKey; + PRErrorCode perr; + + memset(&nssPrivKey, 0, sizeof(nssPrivKey)); + perr = coder.decode(p, length, kSecAsn1DHPrivateKeyTemplate, &nssPrivKey); + if(perr) { + logAsnErr("decode(DHPrivateKey)", perr); + return CSSMERR_CSP_INVALID_KEY; + } + + /* verify alg identifier */ + const CSSM_OID *oid = &nssPrivKey.dhOid; + if(!cspCompareCssmData(oid, &CSSMOID_DH)) { + sslAsn1Debug("DHPrivateKeyDecode: bad OID"); + return CSSMERR_CSP_ALGID_MISMATCH; + } + + NSS_DHParameter ¶ms = nssPrivKey.params; + + try { + openKey->priv_key = cssmDataToBn(nssPrivKey.secretPart); + openKey->p = cssmDataToBn(params.prime); + openKey->g = cssmDataToBn(params.base); + /* TBD - ignore privateValueLength for now */ + } + catch(...) { + /* FIXME - bad sig? memory? */ + return CSSMERR_CSP_MEMORY_ERROR; + } + return 0; +} + +CSSM_RETURN DHPrivateKeyEncodePKCS3( + SecNssCoder &coder, + DH *openKey, + CssmOwnedData &encodedKey) +{ + /* convert into a NSS_DHPrivateKey */ + NSS_DHPrivateKey nssPrivKey; + NSS_DHParameter ¶ms = nssPrivKey.params; + memset(&nssPrivKey, 0, sizeof(nssPrivKey)); + nssPrivKey.dhOid = CSSMOID_DH; + + + try { + bnToCssmData(openKey->priv_key, nssPrivKey.secretPart, coder); + bnToCssmData(openKey->p, params.prime, coder); + bnToCssmData(openKey->g, params.base, coder); + if(openKey->length) { + /* actually currently not supported in openssl... */ + intToCssmData(openKey->length, params.privateValueLength, coder); + } + } + catch(...) { + return CSSMERR_CSP_MEMORY_ERROR; + } + + /* DER encode */ + PRErrorCode perr; + perr = SecNssEncodeItemOdata(&nssPrivKey, kSecAsn1DHPrivateKeyTemplate, + encodedKey); + if(perr) { + logAsnErr("encode(DHPrivateKey)", perr); + return CSSMERR_CSP_MEMORY_ERROR; + } + return CSSM_OK; +} + +/* + * NSS_DHAlgorithmIdentifierX942 <--> DH + * NOTE this is incomplete. It's functional on decode, but we throw + * away everything except p and g. On encode, we put zeroes in + * all the fields we don't deal with. Thus the encode side will NOT be + * interoperable with other implementations. + */ +static void dhToNssAlgIdX942( + const DH *openKey, + NSS_DHAlgorithmIdentifierX942 &algId, + SecNssCoder &coder) +{ + /* + * When trying to encode a public key in X509 form, we may in + * fact have nothing here - public keys created and exported in + * PKCS3 have the pub_key value, and that's it. + */ + + memset(&algId, 0, sizeof(algId)); + algId.oid = CSSMOID_ANSI_DH_PUB_NUMBER; // not mallocd + NSS_DHDomainParamsX942 ¶ms = algId.params; + uint8 zero = 0; + CSSM_DATA czero = {1, &zero}; + if(openKey->p != NULL) { + bnToCssmData(openKey->p, params.p, coder); + } + else { + coder.allocCopyItem(czero, params.p); + } + if(openKey->g != NULL) { + bnToCssmData(openKey->g, params.g, coder); + } + else { + coder.allocCopyItem(czero, params.g); + } + /* and we never have a vali0d q */ + coder.allocCopyItem(czero, params.q); + +} + +static CSSM_RETURN nssAlgIdToDhX942( + NSS_DHAlgorithmIdentifierX942 &algId, + DH *openKey) +{ + if(!cspCompareCssmData(&algId.oid, &CSSMOID_ANSI_DH_PUB_NUMBER)) { + sslAsn1Debug("nssAlgIdToDhX942: bad OID"); + return CSSMERR_CSP_INVALID_KEY; + } + openKey->p = cssmDataToBn(algId.params.p); + openKey->g = cssmDataToBn(algId.params.g); + return CSSM_OK; +} + +CSSM_RETURN DHPrivateKeyDecodePKCS8( + SecNssCoder &coder, + DH *openKey, + unsigned char *p, + unsigned length) +{ + NSS_DHPrivateKeyPKCS8 nssPrivKey; + PRErrorCode perr; + + memset(&nssPrivKey, 0, sizeof(nssPrivKey)); + perr = coder.decode(p, length, kSecAsn1DHPrivateKeyPKCS8Template, + &nssPrivKey); + if(perr) { + logAsnErr("decode(DHPrivateKeyPKCS8)", perr); + return CSSMERR_CSP_INVALID_KEY; + } + + try { + CSSM_RETURN crtn = nssAlgIdToDhX942(nssPrivKey.algorithm, openKey); + if(crtn) { + return crtn; + } + + /* post-decode private key is a DER encoded integer */ + CSSM_DATA privKeyInt = {0, NULL}; + if(coder.decodeItem(nssPrivKey.privateKey, + kSecAsn1UnsignedIntegerTemplate, + &privKeyInt)) { + logAsnErr("decode(DHPrivateKeyPKCS8 privKey int)", perr); + return CSSMERR_CSP_INVALID_KEY; + } + + openKey->priv_key = cssmDataToBn(privKeyInt); + } + catch(...) { + /* FIXME - bad sig? memory? */ + return CSSMERR_CSP_MEMORY_ERROR; + } + return 0; +} + +CSSM_RETURN DHPrivateKeyEncodePKCS8( + SecNssCoder &coder, + DH *openKey, + CssmOwnedData &encodedKey) +{ + /* convert into a NSS_DHPrivateKeyPKCS8 */ + NSS_DHPrivateKeyPKCS8 nssPrivKey; + memset(&nssPrivKey, 0, sizeof(nssPrivKey)); + uint8 vers = 0; + nssPrivKey.version.Length = 1; + nssPrivKey.version.Data = &vers; + NSS_DHAlgorithmIdentifierX942 &alg = nssPrivKey.algorithm; + + try { + + dhToNssAlgIdX942(openKey, alg, coder); + /* pre-encode, nssPrivKey.privateKey is the DER-encoding of + * an ASN integer... */ + CSSM_DATA privKeyInt; + bnToCssmData(openKey->priv_key, privKeyInt, coder); + + /* DER encode the privateKey portion into arena pool memory + * into nssPrivKey.privateKey */ + coder.encodeItem(&privKeyInt, kSecAsn1UnsignedIntegerTemplate, + nssPrivKey.privateKey); + } + catch(...) { + return CSSMERR_CSP_MEMORY_ERROR; + } + + /* DER encode */ + PRErrorCode perr; + perr = SecNssEncodeItemOdata(&nssPrivKey, kSecAsn1DHPrivateKeyPKCS8Template, + encodedKey); + if(perr) { + logAsnErr("encode(DHPrivateKey)", perr); + return CSSMERR_CSP_MEMORY_ERROR; + } + return CSSM_OK; +} + +/* + * In the PKCS3 form, the public blob is simply the literal + * public key value, not DER encoded. + */ +static CSSM_RETURN DHPublicKeyDecodePKCS3( + DH *openKey, + SecNssCoder &coder, + unsigned char *p, + unsigned length) +{ + try { + CSSM_DATA pubKey = {(uint32)length, (uint8 *)p}; + openKey->pub_key = cssmDataToBn(pubKey); + return CSSM_OK; + } + catch(...) { + return CSSMERR_CSP_MEMORY_ERROR; + } +} + +static CSSM_RETURN DHPublicKeyEncodePKCS3( + DH *openKey, + SecNssCoder &coder, + CssmOwnedData &encodedKey) +{ + try { + CSSM_DATA pubKey; + bnToCssmData(openKey->pub_key, pubKey, coder); + encodedKey.copy(CssmData::overlay(pubKey)); + return CSSM_OK; + } + catch(...) { + return CSSMERR_CSP_MEMORY_ERROR; + } +} + +static CSSM_RETURN DHPublicKeyDecodeX509( + DH *openKey, + SecNssCoder &coder, + unsigned char *p, + unsigned length) +{ + NSS_DHPublicKeyX509 nssPubKey; + PRErrorCode perr; + + memset(&nssPubKey, 0, sizeof(nssPubKey)); + perr = coder.decode(p, length, kSecAsn1DHPublicKeyX509Template, + &nssPubKey); + if(perr) { + logAsnErr("decode(DHPublicKeyX509)", perr); + return CSSMERR_CSP_INVALID_KEY; + } + + try { + CSSM_RETURN crtn = nssAlgIdToDhX942(nssPubKey.algorithm, openKey); + if(crtn) { + return crtn; + } + + /* + * Post-decode public key length in bits + * Contents are pub_key as DER-encoded INTEGER + */ + CSSM_DATA &pubKey = nssPubKey.publicKey; + pubKey.Length = (pubKey.Length + 7) / 8; + CSSM_DATA pubKeyInt = {0, NULL}; + if(coder.decodeItem(pubKey, + kSecAsn1UnsignedIntegerTemplate, &pubKeyInt)) { + logAsnErr("decode(DHPublicKeyX509 pub key int)", perr); + return CSSMERR_CSP_INVALID_KEY; + } + openKey->pub_key = cssmDataToBn(pubKeyInt); + } + catch(...) { + /* FIXME - bad sig? memory? */ + return CSSMERR_CSP_MEMORY_ERROR; + } + return 0; +} + +static CSSM_RETURN DHPublicKeyEncodeX509( + DH *openKey, + SecNssCoder &coder, + CssmOwnedData &encodedKey) +{ + /* convert into a NSS_DHPublicKeyX509 */ + NSS_DHPublicKeyX509 nssPubKey; + memset(&nssPubKey, 0, sizeof(nssPubKey)); + NSS_DHAlgorithmIdentifierX942 &alg = nssPubKey.algorithm; + + try { + dhToNssAlgIdX942(openKey, alg, coder); + + /* encode pub_key as integer */ + CSSM_DATA pubKeyInt = {0, NULL}; + bnToCssmData(openKey->pub_key, pubKeyInt, coder); + coder.encodeItem(&pubKeyInt, kSecAsn1UnsignedIntegerTemplate, + nssPubKey.publicKey); + /* specify length in bits */ + nssPubKey.publicKey.Length *= 8; + } + catch(...) { + return CSSMERR_CSP_MEMORY_ERROR; + } + + /* DER encode */ + PRErrorCode perr; + perr = SecNssEncodeItemOdata(&nssPubKey, kSecAsn1DHPublicKeyX509Template, + encodedKey); + if(perr) { + logAsnErr("encode(DHPublicKeyX509)", perr); + return CSSMERR_CSP_MEMORY_ERROR; + } + return CSSM_OK; +} + +CSSM_RETURN DHPrivateKeyDecode( + DH *openKey, + CSSM_KEYBLOB_FORMAT format, + unsigned char *p, + unsigned length) +{ + SecNssCoder coder; + + switch(format) { + case CSSM_KEYBLOB_RAW_FORMAT_PKCS3: + return DHPrivateKeyDecodePKCS3(coder, openKey, p, length); + case CSSM_KEYBLOB_RAW_FORMAT_PKCS8: + return DHPrivateKeyDecodePKCS8(coder, openKey, p, length); + default: + assert(0); + return CSSMERR_CSP_INTERNAL_ERROR; + } +} + +CSSM_RETURN DHPrivateKeyEncode( + DH *openKey, + CSSM_KEYBLOB_FORMAT format, + CssmOwnedData &encodedKey) +{ + SecNssCoder coder; + + switch(format) { + case CSSM_KEYBLOB_RAW_FORMAT_PKCS3: + return DHPrivateKeyEncodePKCS3(coder, openKey, encodedKey); + case CSSM_KEYBLOB_RAW_FORMAT_PKCS8: + return DHPrivateKeyEncodePKCS8(coder, openKey, encodedKey); + default: + assert(0); + return CSSMERR_CSP_INTERNAL_ERROR; + } +} + +CSSM_RETURN DHPublicKeyDecode( + DH *openKey, + CSSM_KEYBLOB_FORMAT format, + unsigned char *p, + unsigned length) +{ + SecNssCoder coder; + + switch(format) { + case CSSM_KEYBLOB_RAW_FORMAT_PKCS3: + return DHPublicKeyDecodePKCS3(openKey, coder, p, length); + case CSSM_KEYBLOB_RAW_FORMAT_X509: + return DHPublicKeyDecodeX509(openKey, coder, p, length); + default: + assert(0); + return CSSMERR_CSP_INTERNAL_ERROR; + } +} + +CSSM_RETURN DHPublicKeyEncode( + DH *openKey, + CSSM_KEYBLOB_FORMAT format, + CssmOwnedData &encodedKey) +{ + SecNssCoder coder; + + switch(format) { + case CSSM_KEYBLOB_RAW_FORMAT_PKCS3: + return DHPublicKeyEncodePKCS3(openKey, coder, encodedKey); + case CSSM_KEYBLOB_RAW_FORMAT_X509: + return DHPublicKeyEncodeX509(openKey, coder, encodedKey); + default: + assert(0); + return CSSMERR_CSP_INTERNAL_ERROR; + } +} + +/* + * Encode/decode a NSS_DHParameterBlock. + */ +CSSM_RETURN DHParamBlockDecode( + const CSSM_DATA &encParam, + NSS_DHParameterBlock ¶mBlock, + SecNssCoder &coder) +{ + PRErrorCode perr; + + memset(¶mBlock, 0, sizeof(paramBlock)); + perr = coder.decodeItem(encParam, kSecAsn1DHParameterBlockTemplate, + ¶mBlock); + if(perr == 0) { + return CSSM_OK; + } + + /* + * CDSA Extension: the CDSA Algorithm Guide says that the D-H + * parameter block is supposed to be wrapped with its accompanying + * OID. However Openssl does not do this; it just exports + * an encoded DHParameter rather than a DHParameterBlock. + * For compatibility we'll try decoding the parameters as one + * of these. + */ + memset(¶mBlock, 0, sizeof(paramBlock)); + perr = coder.decodeItem(encParam, kSecAsn1DHParameterTemplate, + ¶mBlock.params); + if(perr == 0) { + return CSSM_OK; + } + return CSSMERR_CSP_INVALID_ATTR_ALG_PARAMS; +} + +#pragma mark - +#pragma mark *** Message Digest *** + +/* + * Given a message digest and associated algorithm, cook up a PKCS1-style + * DigestInfo and return its DER encoding. This is a necessary step for + * RSA signature (both generating and verifying) - the output of this + * routine is what gets encrypted during signing, and what is expected when + * verifying (i.e., decrypting the signature). + * + * A good guess for the length of the output digestInfo is the size of the + * key being used to sign/verify. The digest can never be larger than that. + */ +CSSM_RETURN generateDigestInfo( + const void *msgDigest, + size_t digestLen, + CSSM_ALGORITHMS digestAlg, // CSSM_ALGID_SHA1, etc. + CssmOwnedData &encodedInfo, + size_t maxEncodedSize) +{ + if(digestAlg == CSSM_ALGID_NONE) { + /* special case, no encode, just copy */ + encodedInfo.copy(msgDigest, digestLen); + return 0; + } + + NSS_DigestInfo digestInfo; + CSSM_X509_ALGORITHM_IDENTIFIER &algId = digestInfo.digestAlgorithm; + + memset(&digestInfo, 0, sizeof(digestInfo)); + switch(digestAlg) { + case CSSM_ALGID_MD5: + algId.algorithm = CSSMOID_MD5; + break; + case CSSM_ALGID_MD2: + algId.algorithm = CSSMOID_MD2; + break; + case CSSM_ALGID_SHA1: + algId.algorithm = CSSMOID_SHA1; + break; + case CSSM_ALGID_SHA224: + algId.algorithm = CSSMOID_SHA224; + break; + case CSSM_ALGID_SHA256: + algId.algorithm = CSSMOID_SHA256; + break; + case CSSM_ALGID_SHA384: + algId.algorithm = CSSMOID_SHA384; + break; + case CSSM_ALGID_SHA512: + algId.algorithm = CSSMOID_SHA512; + break; + default: + return CSSMERR_CSP_INVALID_ALGORITHM; + } + nullAlgParams(algId); + digestInfo.digest.Data = (uint8 *)msgDigest; + digestInfo.digest.Length = digestLen; + + /* DER encode */ + PRErrorCode perr; + perr = SecNssEncodeItemOdata(&digestInfo, kSecAsn1DigestInfoTemplate, + encodedInfo); + if(perr) { + logAsnErr("encode(digestInfo)", perr); + return CSSMERR_CSP_MEMORY_ERROR; + } + return CSSM_OK; +} + diff --git a/libsecurity_apple_csp/open_ssl/opensslUtils/opensslAsn1.h b/libsecurity_apple_csp/open_ssl/opensslUtils/opensslAsn1.h new file mode 100644 index 00000000..e52012f6 --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/opensslUtils/opensslAsn1.h @@ -0,0 +1,181 @@ +/* + * 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. + */ + + +/* + * opensslAsn1.h - ANS1 encode/decode of openssl object, libssnasn1 version + */ + +#ifndef _OPENSSL_ASN1_H_ +#define _OPENSSL_ASN1_H_ + + +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* CSSM_DATA --> BIGNUM */ +BIGNUM *cssmDataToBn( + const CSSM_DATA &cdata); + +/* BIGNUM --> CSSM_DATA, mallocing from a SecNssCoder's PL_ArenaPool */ +void bnToCssmData( + const BIGNUM *bn, + CSSM_DATA &cdata, + SecNssCoder &coder); + +/* CSSM_DATA --> unsigned int */ +unsigned cssmDataToInt( + const CSSM_DATA &cdata); + +/* unsigned int --> CSSM_DATA, mallocing from an SecNssCoder */ +void intToCssmData( + unsigned num, + CSSM_DATA &cdata, + SecNssCoder &coder); + +/* + * DER encode/decode RSA keys in various formats. + */ +CSSM_RETURN RSAPublicKeyDecode( + RSA *openKey, + CSSM_KEYBLOB_FORMAT format, + void *p, + size_t length); +CSSM_RETURN RSAPublicKeyEncode( + RSA *openKey, + CSSM_KEYBLOB_FORMAT format, + const CssmData &descData, + CssmOwnedData &encodedKey); +CSSM_RETURN RSAPrivateKeyDecode( + RSA *openKey, + CSSM_KEYBLOB_FORMAT format, + void *p, + size_t length); +CSSM_RETURN RSAPrivateKeyEncode( + RSA *openKey, + CSSM_KEYBLOB_FORMAT format, + const CssmData &descData, + CssmOwnedData &encodedKey); +CSSM_RETURN RSAOAEPPublicKeyDecode( + RSA *openKey, + void *p, + size_t length, + /* mallocd and returned label */ + CSSM_DATA *label); +CSSM_RETURN RSAOAEPPublicKeyEncode( + RSA *openKey, + const CSSM_DATA *label, + CssmOwnedData &encodedKey); +CSSM_RETURN RSAOAEPPrivateKeyDecode( + RSA *openKey, + void *p, + size_t length, + /* mallocd and returned label */ + CSSM_DATA *label); +CSSM_RETURN RSAOAEPPrivateKeyEncode( + RSA *openKey, + const CSSM_DATA *label, + CssmOwnedData &encodedKey); + +CSSM_RETURN generateDigestInfo( + const void *messageDigest, + size_t digestLen, + CSSM_ALGORITHMS digestAlg, // CSSM_ALGID_SHA1, etc. + CssmOwnedData &encodedInfo, + size_t maxEncodedSize); +CSSM_RETURN DSAPublicKeyDecode( + DSA *openKey, + CSSM_KEYBLOB_FORMAT format, + void *p, + size_t length); +CSSM_RETURN DSAPublicKeyEncode( + DSA *openKey, + CSSM_KEYBLOB_FORMAT format, + const CssmData &descData, + CssmOwnedData &encodedKey); +CSSM_RETURN DSAPrivateKeyDecode( + DSA *openKey, + CSSM_KEYBLOB_FORMAT format, + void *p, + size_t length); +CSSM_RETURN DSAPrivateKeyEncode( + DSA *openKey, + CSSM_KEYBLOB_FORMAT format, + const CssmData &descData, + CssmOwnedData &encodedKey); + +CSSM_RETURN DSASigEncode( + DSA_SIG *openSig, + CssmOwnedData &encodedSig); +CSSM_RETURN DSASigDecode( + DSA_SIG *openSig, + const void *p, + unsigned length); + +CSSM_RETURN DSAEncodeAlgParams( + NSS_DSAAlgParams &algParams, + CssmOwnedData &encodedParams); +CSSM_RETURN DSADecodeAlgParams( + NSS_DSAAlgParams &algParams, + const void *p, + unsigned len, + SecNssCoder &coder); + +CSSM_RETURN DHPrivateKeyDecode( + DH *openKey, + CSSM_KEYBLOB_FORMAT format, + unsigned char *p, + unsigned length); +CSSM_RETURN DHPrivateKeyEncode( + DH *openKey, + CSSM_KEYBLOB_FORMAT format, + CssmOwnedData &encodedKey); +CSSM_RETURN DHPublicKeyDecode( + DH *openKey, + CSSM_KEYBLOB_FORMAT format, + unsigned char *p, + unsigned length); +CSSM_RETURN DHPublicKeyEncode( + DH *openKey, + CSSM_KEYBLOB_FORMAT format, + CssmOwnedData &encodedKey); +CSSM_RETURN DHParamBlockDecode( + const CSSM_DATA &encParam, + NSS_DHParameterBlock ¶mBlock, + SecNssCoder &coder); + +CSSM_RETURN generateDigestInfo( + const void *msgDigest, + size_t digestLen, + CSSM_ALGORITHMS digestAlg, // CSSM_ALGID_SHA1, etc. + CssmOwnedData &encodedInfo, + size_t maxEncodedSize); + +#ifdef __cplusplus +} +#endif + +#endif /* _OPENSSL_ASN1_H_ */ diff --git a/libsecurity_apple_csp/open_ssl/opensslUtils/opensslUtils.cpp b/libsecurity_apple_csp/open_ssl/opensslUtils/opensslUtils.cpp new file mode 100644 index 00000000..1ebbce9a --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/opensslUtils/opensslUtils.cpp @@ -0,0 +1,231 @@ +/* + * 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. + */ + + +/* + * opensslUtils.h - Support for ssleay-derived crypto modules + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "opensslUtils.h" +#include +#include +#include + +#define sslUtilsDebug(args...) secdebug("sslUtils", ## args) + +openSslException::openSslException( + int irtn, + const char *op) + : mIrtn(irtn) +{ + if(op) { + char buf[300]; + ERR_error_string(irtn, buf); + sslUtilsDebug("%s: %s\n", op, buf); + } +} + +/* these are replacements for the ones in ssleay */ +#define DUMP_RAND_BYTES 0 + +static int randDex = 1; + +int RAND_bytes(unsigned char *buf,int num) +{ + try { + cspGetRandomBytes(buf, (unsigned)num); + } + catch(...) { + /* that can only mean Yarrow failure, which we really need to + * cut some slack for */ + Security::Syslog::error("Apple CSP: yarrow failure"); + for(int i=0; i + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Trivial exception class associated with an openssl error. + */ +class openSslException +{ +public: + openSslException( + int irtn, + const char *op = NULL); + ~openSslException() { } + int irtn() { return mIrtn; } +private: + int mIrtn; +}; + +/* Clear openssl error stack. */ +void clearOpensslErrors(); + +unsigned long logSslErrInfo(const char *op); + +void throwRsaDsa( + const char *op); + +/* + * given an openssl-style error, throw appropriate CssmError. + */ +void throwOpensslErr( + int irtn); + + +#ifdef __cplusplus +} +#endif + +#endif /* _OPENSSL_UTILS_H_ */ diff --git a/libsecurity_apple_csp/open_ssl/rsa/rsa_chk.c b/libsecurity_apple_csp/open_ssl/rsa/rsa_chk.c new file mode 100644 index 00000000..a68408ba --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/rsa/rsa_chk.c @@ -0,0 +1,202 @@ +/* + * 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. + */ + + +/* crypto/rsa/rsa_chk.c -*- Mode: C; c-file-style: "eay" -*- */ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ + +#include +#include +#include + + +int RSA_check_key(RSA *key) + { + BIGNUM *i, *j, *k, *l, *m; + BN_CTX *ctx; + int r; + int ret=1; + + i = BN_new(); + j = BN_new(); + k = BN_new(); + l = BN_new(); + m = BN_new(); + ctx = BN_CTX_new(); + if (i == NULL || j == NULL || k == NULL || l == NULL || + m == NULL || ctx == NULL) + { + ret = -1; + RSAerr(RSA_F_RSA_CHECK_KEY, ERR_R_MALLOC_FAILURE); + goto err; + } + + /* p prime? */ + r = BN_is_prime(key->p, BN_prime_checks, NULL, NULL, NULL); + if (r != 1) + { + ret = r; + if (r != 0) + goto err; + RSAerr(RSA_F_RSA_CHECK_KEY, RSA_R_P_NOT_PRIME); + } + + /* q prime? */ + r = BN_is_prime(key->q, BN_prime_checks, NULL, NULL, NULL); + if (r != 1) + { + ret = r; + if (r != 0) + goto err; + RSAerr(RSA_F_RSA_CHECK_KEY, RSA_R_Q_NOT_PRIME); + } + + /* n = p*q? */ + r = BN_mul(i, key->p, key->q, ctx); + if (!r) { ret = -1; goto err; } + + if (BN_cmp(i, key->n) != 0) + { + ret = 0; + RSAerr(RSA_F_RSA_CHECK_KEY, RSA_R_N_DOES_NOT_EQUAL_P_Q); + } + + /* d*e = 1 mod lcm(p-1,q-1)? */ + + r = BN_sub(i, key->p, BN_value_one()); + if (!r) { ret = -1; goto err; } + r = BN_sub(j, key->q, BN_value_one()); + if (!r) { ret = -1; goto err; } + + /* now compute k = lcm(i,j) */ + r = BN_mul(l, i, j, ctx); + if (!r) { ret = -1; goto err; } + r = BN_gcd(m, i, j, ctx); + if (!r) { ret = -1; goto err; } + r = BN_div(k, NULL, l, m, ctx); /* remainder is 0 */ + if (!r) { ret = -1; goto err; } + + r = BN_mod_mul(i, key->d, key->e, k, ctx); + if (!r) { ret = -1; goto err; } + + if (!BN_is_one(i)) + { + ret = 0; + RSAerr(RSA_F_RSA_CHECK_KEY, RSA_R_D_E_NOT_CONGRUENT_TO_1); + } + + if (key->dmp1 != NULL && key->dmq1 != NULL && key->iqmp != NULL) + { + /* dmp1 = d mod (p-1)? */ + r = BN_sub(i, key->p, BN_value_one()); + if (!r) { ret = -1; goto err; } + + r = BN_mod(j, key->d, i, ctx); + if (!r) { ret = -1; goto err; } + + if (BN_cmp(j, key->dmp1) != 0) + { + ret = 0; + RSAerr(RSA_F_RSA_CHECK_KEY, + RSA_R_DMP1_NOT_CONGRUENT_TO_D); + } + + /* dmq1 = d mod (q-1)? */ + r = BN_sub(i, key->q, BN_value_one()); + if (!r) { ret = -1; goto err; } + + r = BN_mod(j, key->d, i, ctx); + if (!r) { ret = -1; goto err; } + + if (BN_cmp(j, key->dmq1) != 0) + { + ret = 0; + RSAerr(RSA_F_RSA_CHECK_KEY, + RSA_R_DMQ1_NOT_CONGRUENT_TO_D); + } + + /* iqmp = q^-1 mod p? */ + if(!BN_mod_inverse(i, key->q, key->p, ctx)) + { + ret = -1; + goto err; + } + + if (BN_cmp(i, key->iqmp) != 0) + { + ret = 0; + RSAerr(RSA_F_RSA_CHECK_KEY, + RSA_R_IQMP_NOT_INVERSE_OF_Q); + } + } + + err: + if (i != NULL) BN_free(i); + if (j != NULL) BN_free(j); + if (k != NULL) BN_free(k); + if (l != NULL) BN_free(l); + if (m != NULL) BN_free(m); + if (ctx != NULL) BN_CTX_free(ctx); + return (ret); + } diff --git a/libsecurity_apple_csp/open_ssl/rsa/rsa_eay.c b/libsecurity_apple_csp/open_ssl/rsa/rsa_eay.c new file mode 100644 index 00000000..3f79f3ab --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/rsa/rsa_eay.c @@ -0,0 +1,514 @@ +/* + * 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. + */ + + +/* crypto/rsa/rsa_eay.c */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include +#include "cryptlib.h" +#include +#include +#include +#include + +#ifndef RSA_NULL + +static int RSA_eay_public_encrypt(int flen, unsigned char *from, + unsigned char *to, RSA *rsa,int padding); +static int RSA_eay_private_encrypt(int flen, unsigned char *from, + unsigned char *to, RSA *rsa,int padding); +static int RSA_eay_public_decrypt(int flen, unsigned char *from, + unsigned char *to, RSA *rsa,int padding); +static int RSA_eay_private_decrypt(int flen, unsigned char *from, + unsigned char *to, RSA *rsa,int padding); +static int RSA_eay_mod_exp(BIGNUM *r0, BIGNUM *i, RSA *rsa); +static int RSA_eay_init(RSA *rsa); +static int RSA_eay_finish(RSA *rsa); +static const RSA_METHOD rsa_pkcs1_eay_meth={ + "Eric Young's PKCS#1 RSA", + RSA_eay_public_encrypt, + RSA_eay_public_decrypt, + RSA_eay_private_encrypt, + RSA_eay_private_decrypt, + RSA_eay_mod_exp, + BN_mod_exp_mont, + RSA_eay_init, + RSA_eay_finish, + 0, + NULL, + }; + +const RSA_METHOD *RSA_PKCS1_SSLeay(void) + { + return(&rsa_pkcs1_eay_meth); + } + +static int RSA_eay_public_encrypt(int flen, unsigned char *from, + unsigned char *to, RSA *rsa, int padding) + { + BIGNUM f,ret; + int i,j,k,num=0,r= -1; + unsigned char *buf=NULL; + BN_CTX *ctx=NULL; + + BN_init(&f); + BN_init(&ret); + if ((ctx=BN_CTX_new()) == NULL) goto err; + num=BN_num_bytes(rsa->n); + if ((buf=(unsigned char *)Malloc(num)) == NULL) + { + RSAerr(RSA_F_RSA_EAY_PUBLIC_ENCRYPT,ERR_R_MALLOC_FAILURE); + goto err; + } + + switch (padding) + { + case RSA_PKCS1_PADDING: + i=RSA_padding_add_PKCS1_type_2(buf,num,from,flen); + break; +#ifndef _OPENSSL_APPLE_CDSA_ +#ifndef NO_SHA + case RSA_PKCS1_OAEP_PADDING: + i=RSA_padding_add_PKCS1_OAEP(buf,num,from,flen,NULL,0); + break; +#endif +#endif + case RSA_SSLV23_PADDING: + i=RSA_padding_add_SSLv23(buf,num,from,flen); + break; + case RSA_NO_PADDING: + i=RSA_padding_add_none(buf,num,from,flen); + break; + default: + RSAerr(RSA_F_RSA_EAY_PUBLIC_ENCRYPT,RSA_R_UNKNOWN_PADDING_TYPE); + goto err; + } + if (i <= 0) goto err; + + if (BN_bin2bn(buf,num,&f) == NULL) goto err; + + if ((rsa->_method_mod_n == NULL) && (rsa->flags & RSA_FLAG_CACHE_PUBLIC)) + { + if ((rsa->_method_mod_n=BN_MONT_CTX_new()) != NULL) + if (!BN_MONT_CTX_set(rsa->_method_mod_n,rsa->n,ctx)) + goto err; + } + + if (!rsa->meth->bn_mod_exp(&ret,&f,rsa->e,rsa->n,ctx, + rsa->_method_mod_n)) goto err; + + /* put in leading 0 bytes if the number is less than the + * length of the modulus */ + j=BN_num_bytes(&ret); + i=BN_bn2bin(&ret,&(to[num-j])); + for (k=0; k<(num-i); k++) + to[k]=0; + + r=num; +err: + if (ctx != NULL) BN_CTX_free(ctx); + BN_clear_free(&f); + BN_clear_free(&ret); + if (buf != NULL) + { + memset(buf,0,num); + Free(buf); + } + return(r); + } + +static int RSA_eay_private_encrypt(int flen, unsigned char *from, + unsigned char *to, RSA *rsa, int padding) + { + BIGNUM f,ret; + int i,j,k,num=0,r= -1; + unsigned char *buf=NULL; + BN_CTX *ctx=NULL; + + BN_init(&f); + BN_init(&ret); + + if ((ctx=BN_CTX_new()) == NULL) goto err; + num=BN_num_bytes(rsa->n); + if ((buf=(unsigned char *)Malloc(num)) == NULL) + { + RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT,ERR_R_MALLOC_FAILURE); + goto err; + } + + switch (padding) + { + case RSA_PKCS1_PADDING: + i=RSA_padding_add_PKCS1_type_1(buf,num,from,flen); + break; + case RSA_NO_PADDING: + i=RSA_padding_add_none(buf,num,from,flen); + break; + case RSA_SSLV23_PADDING: + default: + RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT,RSA_R_UNKNOWN_PADDING_TYPE); + goto err; + } + if (i <= 0) goto err; + + if (BN_bin2bn(buf,num,&f) == NULL) goto err; + + if ((rsa->flags & RSA_FLAG_BLINDING) && (RSA_get_thread_blinding_ptr(rsa) == NULL)) + RSA_blinding_on(rsa,ctx); + if (rsa->flags & RSA_FLAG_BLINDING) + if (!BN_BLINDING_convert(&f,RSA_get_thread_blinding_ptr(rsa),ctx)) goto err; + + if ( (rsa->flags & RSA_FLAG_EXT_PKEY) || + ((rsa->p != NULL) && + (rsa->q != NULL) && + (rsa->dmp1 != NULL) && + (rsa->dmq1 != NULL) && + (rsa->iqmp != NULL)) ) + { if (!rsa->meth->rsa_mod_exp(&ret,&f,rsa)) goto err; } + else + { + if (!rsa->meth->bn_mod_exp(&ret,&f,rsa->d,rsa->n,ctx,NULL)) goto err; + } + + if (rsa->flags & RSA_FLAG_BLINDING) + if (!BN_BLINDING_invert(&ret,RSA_get_thread_blinding_ptr(rsa),ctx)) goto err; + + /* put in leading 0 bytes if the number is less than the + * length of the modulus */ + j=BN_num_bytes(&ret); + i=BN_bn2bin(&ret,&(to[num-j])); + for (k=0; k<(num-i); k++) + to[k]=0; + + r=num; +err: + if (ctx != NULL) BN_CTX_free(ctx); + BN_clear_free(&ret); + BN_clear_free(&f); + if (buf != NULL) + { + memset(buf,0,num); + Free(buf); + } + return(r); + } + +static int RSA_eay_private_decrypt(int flen, unsigned char *from, + unsigned char *to, RSA *rsa, int padding) + { + BIGNUM f,ret; + int j,num=0,r= -1; + unsigned char *p; + unsigned char *buf=NULL; + BN_CTX *ctx=NULL; + + BN_init(&f); + BN_init(&ret); + ctx=BN_CTX_new(); + if (ctx == NULL) goto err; + + num=BN_num_bytes(rsa->n); + + if ((buf=(unsigned char *)Malloc(num)) == NULL) + { + RSAerr(RSA_F_RSA_EAY_PRIVATE_DECRYPT,ERR_R_MALLOC_FAILURE); + goto err; + } + + /* This check was for equality but PGP does evil things + * and chops off the top '0' bytes */ + if (flen > num) + { + RSAerr(RSA_F_RSA_EAY_PRIVATE_DECRYPT,RSA_R_DATA_GREATER_THAN_MOD_LEN); + goto err; + } + + /* make data into a big number */ + if (BN_bin2bn(from,(int)flen,&f) == NULL) goto err; + + if ((rsa->flags & RSA_FLAG_BLINDING) && (RSA_get_thread_blinding_ptr(rsa) == NULL)) + RSA_blinding_on(rsa,ctx); + if (rsa->flags & RSA_FLAG_BLINDING) + if (!BN_BLINDING_convert(&f,RSA_get_thread_blinding_ptr(rsa),ctx)) goto err; + + /* do the decrypt */ + if ( (rsa->flags & RSA_FLAG_EXT_PKEY) || + ((rsa->p != NULL) && + (rsa->q != NULL) && + (rsa->dmp1 != NULL) && + (rsa->dmq1 != NULL) && + (rsa->iqmp != NULL)) ) + { if (!rsa->meth->rsa_mod_exp(&ret,&f,rsa)) goto err; } + else + { + if (!rsa->meth->bn_mod_exp(&ret,&f,rsa->d,rsa->n,ctx,NULL)) + goto err; + } + + if (rsa->flags & RSA_FLAG_BLINDING) + if (!BN_BLINDING_invert(&ret,RSA_get_thread_blinding_ptr(rsa),ctx)) goto err; + + p=buf; + j=BN_bn2bin(&ret,p); /* j is only used with no-padding mode */ + + switch (padding) + { + case RSA_PKCS1_PADDING: + r=RSA_padding_check_PKCS1_type_2(to,num,buf,j,num); + break; +#ifndef _OPENSSL_APPLE_CDSA_ +#ifndef NO_SHA + case RSA_PKCS1_OAEP_PADDING: + r=RSA_padding_check_PKCS1_OAEP(to,num,buf,j,num,NULL,0); + break; +#endif +#endif + case RSA_SSLV23_PADDING: + r=RSA_padding_check_SSLv23(to,num,buf,j,num); + break; + case RSA_NO_PADDING: + r=RSA_padding_check_none(to,num,buf,j,num); + break; + default: + RSAerr(RSA_F_RSA_EAY_PRIVATE_DECRYPT,RSA_R_UNKNOWN_PADDING_TYPE); + goto err; + } + if (r < 0) + RSAerr(RSA_F_RSA_EAY_PRIVATE_DECRYPT,RSA_R_PADDING_CHECK_FAILED); + +err: + if (ctx != NULL) BN_CTX_free(ctx); + BN_clear_free(&f); + BN_clear_free(&ret); + if (buf != NULL) + { + memset(buf,0,num); + Free(buf); + } + return(r); + } + +static int RSA_eay_public_decrypt(int flen, unsigned char *from, + unsigned char *to, RSA *rsa, int padding) + { + BIGNUM f,ret; + int i,num=0,r= -1; + unsigned char *p; + unsigned char *buf=NULL; + BN_CTX *ctx=NULL; + + BN_init(&f); + BN_init(&ret); + ctx=BN_CTX_new(); + if (ctx == NULL) goto err; + + num=BN_num_bytes(rsa->n); + buf=(unsigned char *)Malloc(num); + if (buf == NULL) + { + RSAerr(RSA_F_RSA_EAY_PUBLIC_DECRYPT,ERR_R_MALLOC_FAILURE); + goto err; + } + + /* This check was for equality but PGP does evil things + * and chops off the top '0' bytes */ + if (flen > num) + { + RSAerr(RSA_F_RSA_EAY_PUBLIC_DECRYPT,RSA_R_DATA_GREATER_THAN_MOD_LEN); + goto err; + } + + if (BN_bin2bn(from,flen,&f) == NULL) goto err; + /* do the decrypt */ + if ((rsa->_method_mod_n == NULL) && (rsa->flags & RSA_FLAG_CACHE_PUBLIC)) + { + if ((rsa->_method_mod_n=BN_MONT_CTX_new()) != NULL) + if (!BN_MONT_CTX_set(rsa->_method_mod_n,rsa->n,ctx)) + goto err; + } + + if (!rsa->meth->bn_mod_exp(&ret,&f,rsa->e,rsa->n,ctx, + rsa->_method_mod_n)) goto err; + + p=buf; + i=BN_bn2bin(&ret,p); + + switch (padding) + { + case RSA_PKCS1_PADDING: + r=RSA_padding_check_PKCS1_type_1(to,num,buf,i,num); + break; + case RSA_NO_PADDING: + r=RSA_padding_check_none(to,num,buf,i,num); + break; + default: + RSAerr(RSA_F_RSA_EAY_PUBLIC_DECRYPT,RSA_R_UNKNOWN_PADDING_TYPE); + goto err; + } + if (r < 0) + RSAerr(RSA_F_RSA_EAY_PUBLIC_DECRYPT,RSA_R_PADDING_CHECK_FAILED); + +err: + if (ctx != NULL) BN_CTX_free(ctx); + BN_clear_free(&f); + BN_clear_free(&ret); + if (buf != NULL) + { + memset(buf,0,num); + Free(buf); + } + return(r); + } + +static int RSA_eay_mod_exp(BIGNUM *r0, BIGNUM *I, RSA *rsa) + { + BIGNUM r1,m1; + int ret=0; + BN_CTX *ctx; + + if ((ctx=BN_CTX_new()) == NULL) goto err; + BN_init(&m1); + BN_init(&r1); + + if (rsa->flags & RSA_FLAG_CACHE_PRIVATE) + { + if (rsa->_method_mod_p == NULL) + { + if ((rsa->_method_mod_p=BN_MONT_CTX_new()) != NULL) + if (!BN_MONT_CTX_set(rsa->_method_mod_p,rsa->p, + ctx)) + goto err; + } + if (rsa->_method_mod_q == NULL) + { + if ((rsa->_method_mod_q=BN_MONT_CTX_new()) != NULL) + if (!BN_MONT_CTX_set(rsa->_method_mod_q,rsa->q, + ctx)) + goto err; + } + } + + if (!BN_mod(&r1,I,rsa->q,ctx)) goto err; + if (!rsa->meth->bn_mod_exp(&m1,&r1,rsa->dmq1,rsa->q,ctx, + rsa->_method_mod_q)) goto err; + + if (!BN_mod(&r1,I,rsa->p,ctx)) goto err; + if (!rsa->meth->bn_mod_exp(r0,&r1,rsa->dmp1,rsa->p,ctx, + rsa->_method_mod_p)) goto err; + + if (!BN_sub(r0,r0,&m1)) goto err; + /* This will help stop the size of r0 increasing, which does + * affect the multiply if it optimised for a power of 2 size */ + if (r0->neg) + if (!BN_add(r0,r0,rsa->p)) goto err; + + if (!BN_mul(&r1,r0,rsa->iqmp,ctx)) goto err; + if (!BN_mod(r0,&r1,rsa->p,ctx)) goto err; + /* If p < q it is occasionally possible for the correction of + * adding 'p' if r0 is negative above to leave the result still + * negative. This can break the private key operations: the following + * second correction should *always* correct this rare occurrence. + * This will *never* happen with OpenSSL generated keys because + * they ensure p > q [steve] + */ + if (r0->neg) + if (!BN_add(r0,r0,rsa->p)) goto err; + if (!BN_mul(&r1,r0,rsa->q,ctx)) goto err; + if (!BN_add(r0,&r1,&m1)) goto err; + + ret=1; +err: + BN_clear_free(&m1); + BN_clear_free(&r1); + BN_CTX_free(ctx); + return(ret); + } + +static int RSA_eay_init(RSA *rsa) + { + rsa->flags|=RSA_FLAG_CACHE_PUBLIC|RSA_FLAG_CACHE_PRIVATE; + return(1); + } + +static int RSA_eay_finish(RSA *rsa) + { + if (rsa->_method_mod_n != NULL) + BN_MONT_CTX_free(rsa->_method_mod_n); + if (rsa->_method_mod_p != NULL) + BN_MONT_CTX_free(rsa->_method_mod_p); + if (rsa->_method_mod_q != NULL) + BN_MONT_CTX_free(rsa->_method_mod_q); + return(1); + } + +#endif diff --git a/libsecurity_apple_csp/open_ssl/rsa/rsa_err.c b/libsecurity_apple_csp/open_ssl/rsa/rsa_err.c new file mode 100644 index 00000000..17db7db3 --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/rsa/rsa_err.c @@ -0,0 +1,166 @@ +/* + * 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. + */ + + +/* crypto/rsa/rsa_err.c */ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +/* NOTE: this file was auto generated by the mkerr.pl script: any changes + * made to it will be overwritten when the script next updates this file, + * only reason strings will be preserved. + */ + +#include +#include +#include + +/* BEGIN ERROR CODES */ +#ifndef NO_ERR +static ERR_STRING_DATA RSA_str_functs[]= + { +{ERR_PACK(0,RSA_F_MEMORY_LOCK,0), "MEMORY_LOCK"}, +{ERR_PACK(0,RSA_F_RSA_CHECK_KEY,0), "RSA_check_key"}, +{ERR_PACK(0,RSA_F_RSA_EAY_PRIVATE_DECRYPT,0), "RSA_EAY_PRIVATE_DECRYPT"}, +{ERR_PACK(0,RSA_F_RSA_EAY_PRIVATE_ENCRYPT,0), "RSA_EAY_PRIVATE_ENCRYPT"}, +{ERR_PACK(0,RSA_F_RSA_EAY_PUBLIC_DECRYPT,0), "RSA_EAY_PUBLIC_DECRYPT"}, +{ERR_PACK(0,RSA_F_RSA_EAY_PUBLIC_ENCRYPT,0), "RSA_EAY_PUBLIC_ENCRYPT"}, +{ERR_PACK(0,RSA_F_RSA_GENERATE_KEY,0), "RSA_generate_key"}, +{ERR_PACK(0,RSA_F_RSA_NEW_METHOD,0), "RSA_new_method"}, +{ERR_PACK(0,RSA_F_RSA_NULL,0), "RSA_NULL"}, +{ERR_PACK(0,RSA_F_RSA_PADDING_ADD_NONE,0), "RSA_padding_add_none"}, +{ERR_PACK(0,RSA_F_RSA_PADDING_ADD_PKCS1_OAEP,0), "RSA_padding_add_PKCS1_OAEP"}, +{ERR_PACK(0,RSA_F_RSA_PADDING_ADD_PKCS1_TYPE_1,0), "RSA_padding_add_PKCS1_type_1"}, +{ERR_PACK(0,RSA_F_RSA_PADDING_ADD_PKCS1_TYPE_2,0), "RSA_padding_add_PKCS1_type_2"}, +{ERR_PACK(0,RSA_F_RSA_PADDING_ADD_SSLV23,0), "RSA_padding_add_SSLv23"}, +{ERR_PACK(0,RSA_F_RSA_PADDING_CHECK_NONE,0), "RSA_padding_check_none"}, +{ERR_PACK(0,RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP,0), "RSA_padding_check_PKCS1_OAEP"}, +{ERR_PACK(0,RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_1,0), "RSA_padding_check_PKCS1_type_1"}, +{ERR_PACK(0,RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_2,0), "RSA_padding_check_PKCS1_type_2"}, +{ERR_PACK(0,RSA_F_RSA_PADDING_CHECK_SSLV23,0), "RSA_padding_check_SSLv23"}, +{ERR_PACK(0,RSA_F_RSA_PRINT,0), "RSA_print"}, +{ERR_PACK(0,RSA_F_RSA_PRINT_FP,0), "RSA_print_fp"}, +{ERR_PACK(0,RSA_F_RSA_SIGN,0), "RSA_sign"}, +{ERR_PACK(0,RSA_F_RSA_SIGN_ASN1_OCTET_STRING,0), "RSA_sign_ASN1_OCTET_STRING"}, +{ERR_PACK(0,RSA_F_RSA_VERIFY,0), "RSA_verify"}, +{ERR_PACK(0,RSA_F_RSA_VERIFY_ASN1_OCTET_STRING,0), "RSA_verify_ASN1_OCTET_STRING"}, +{0,NULL} + }; + +static ERR_STRING_DATA RSA_str_reasons[]= + { +{RSA_R_ALGORITHM_MISMATCH ,"algorithm mismatch"}, +{RSA_R_BAD_E_VALUE ,"bad e value"}, +{RSA_R_BAD_FIXED_HEADER_DECRYPT ,"bad fixed header decrypt"}, +{RSA_R_BAD_PAD_BYTE_COUNT ,"bad pad byte count"}, +{RSA_R_BAD_SIGNATURE ,"bad signature"}, +{RSA_R_BLOCK_TYPE_IS_NOT_01 ,"block type is not 01"}, +{RSA_R_BLOCK_TYPE_IS_NOT_02 ,"block type is not 02"}, +{RSA_R_DATA_GREATER_THAN_MOD_LEN ,"data greater than mod len"}, +{RSA_R_DATA_TOO_LARGE ,"data too large"}, +{RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE ,"data too large for key size"}, +{RSA_R_DATA_TOO_SMALL ,"data too small"}, +{RSA_R_DATA_TOO_SMALL_FOR_KEY_SIZE ,"data too small for key size"}, +{RSA_R_DIGEST_TOO_BIG_FOR_RSA_KEY ,"digest too big for rsa key"}, +{RSA_R_DMP1_NOT_CONGRUENT_TO_D ,"dmp1 not congruent to d"}, +{RSA_R_DMQ1_NOT_CONGRUENT_TO_D ,"dmq1 not congruent to d"}, +{RSA_R_D_E_NOT_CONGRUENT_TO_1 ,"d e not congruent to 1"}, +{RSA_R_INVALID_MESSAGE_LENGTH ,"invalid message length"}, +{RSA_R_IQMP_NOT_INVERSE_OF_Q ,"iqmp not inverse of q"}, +{RSA_R_KEY_SIZE_TOO_SMALL ,"key size too small"}, +{RSA_R_NULL_BEFORE_BLOCK_MISSING ,"null before block missing"}, +{RSA_R_N_DOES_NOT_EQUAL_P_Q ,"n does not equal p q"}, +{RSA_R_OAEP_DECODING_ERROR ,"oaep decoding error"}, +{RSA_R_PADDING_CHECK_FAILED ,"padding check failed"}, +{RSA_R_P_NOT_PRIME ,"p not prime"}, +{RSA_R_Q_NOT_PRIME ,"q not prime"}, +{RSA_R_RSA_OPERATIONS_NOT_SUPPORTED ,"rsa operations not supported"}, +{RSA_R_SSLV3_ROLLBACK_ATTACK ,"sslv3 rollback attack"}, +{RSA_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD,"the asn1 object identifier is not known for this md"}, +{RSA_R_UNKNOWN_ALGORITHM_TYPE ,"unknown algorithm type"}, +{RSA_R_UNKNOWN_PADDING_TYPE ,"unknown padding type"}, +{RSA_R_WRONG_SIGNATURE_LENGTH ,"wrong signature length"}, +{0,NULL} + }; + +#endif + +void ERR_load_RSA_strings(void) + { + static int init=1; + + if (init) + { + init=0; +#ifndef NO_ERR + ERR_load_strings(ERR_LIB_RSA,RSA_str_functs); + ERR_load_strings(ERR_LIB_RSA,RSA_str_reasons); +#endif + + } + } diff --git a/libsecurity_apple_csp/open_ssl/rsa/rsa_gen.c b/libsecurity_apple_csp/open_ssl/rsa/rsa_gen.c new file mode 100644 index 00000000..23ab1977 --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/rsa/rsa_gen.c @@ -0,0 +1,216 @@ +/* + * 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. + */ + + +/* crypto/rsa/rsa_gen.c */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include +#include +#include "cryptlib.h" +#include +#include + +RSA *RSA_generate_key(int bits, unsigned long e_value, + void (*callback)(int,int,void *), void *cb_arg) + { + RSA *rsa=NULL; + BIGNUM *r0=NULL,*r1=NULL,*r2=NULL,*r3=NULL,*tmp; + int bitsp,bitsq,ok= -1,n=0; + unsigned i; + BN_CTX *ctx=NULL,*ctx2=NULL; + + ctx=BN_CTX_new(); + if (ctx == NULL) goto err; + ctx2=BN_CTX_new(); + if (ctx2 == NULL) goto err; + BN_CTX_start(ctx); + r0 = BN_CTX_get(ctx); + r1 = BN_CTX_get(ctx); + r2 = BN_CTX_get(ctx); + r3 = BN_CTX_get(ctx); + if (r3 == NULL) goto err; + + bitsp=(bits+1)/2; + bitsq=bits-bitsp; + rsa=RSA_new(); + if (rsa == NULL) goto err; + + /* set e */ + rsa->e=BN_new(); + if (rsa->e == NULL) goto err; + +#if 1 + /* The problem is when building with 8, 16, or 32 BN_ULONG, + * unsigned long can be larger */ + for (i=0; ie,i); + } +#else + if (!BN_set_word(rsa->e,e_value)) goto err; +#endif + + /* generate p and q */ + for (;;) + { + rsa->p=BN_generate_prime(NULL,bitsp,0,NULL,NULL,callback,cb_arg); + if (rsa->p == NULL) goto err; + if (!BN_sub(r2,rsa->p,BN_value_one())) goto err; + if (!BN_gcd(r1,r2,rsa->e,ctx)) goto err; + if (BN_is_one(r1)) break; + if (callback != NULL) callback(2,n++,cb_arg); + BN_free(rsa->p); + } + if (callback != NULL) callback(3,0,cb_arg); + for (;;) + { + rsa->q=BN_generate_prime(NULL,bitsq,0,NULL,NULL,callback,cb_arg); + if (rsa->q == NULL) goto err; + if (!BN_sub(r2,rsa->q,BN_value_one())) goto err; + if (!BN_gcd(r1,r2,rsa->e,ctx)) goto err; + if (BN_is_one(r1) && (BN_cmp(rsa->p,rsa->q) != 0)) + break; + if (callback != NULL) callback(2,n++,cb_arg); + BN_free(rsa->q); + } + if (callback != NULL) callback(3,1,cb_arg); + if (BN_cmp(rsa->p,rsa->q) < 0) + { + tmp=rsa->p; + rsa->p=rsa->q; + rsa->q=tmp; + } + + /* calculate n */ + rsa->n=BN_new(); + if (rsa->n == NULL) goto err; + if (!BN_mul(rsa->n,rsa->p,rsa->q,ctx)) goto err; + + /* calculate d */ + if (!BN_sub(r1,rsa->p,BN_value_one())) goto err; /* p-1 */ + if (!BN_sub(r2,rsa->q,BN_value_one())) goto err; /* q-1 */ + if (!BN_mul(r0,r1,r2,ctx)) goto err; /* (p-1)(q-1) */ + +/* should not be needed, since gcd(p-1,e) == 1 and gcd(q-1,e) == 1 */ +/* for (;;) + { + if (!BN_gcd(r3,r0,rsa->e,ctx)) goto err; + if (BN_is_one(r3)) break; + + if (1) + { + if (!BN_add_word(rsa->e,2L)) goto err; + continue; + } + RSAerr(RSA_F_RSA_GENERATE_KEY,RSA_R_BAD_E_VALUE); + goto err; + } +*/ + rsa->d=BN_mod_inverse(NULL,rsa->e,r0,ctx2); /* d */ + if (rsa->d == NULL) goto err; + + /* calculate d mod (p-1) */ + rsa->dmp1=BN_new(); + if (rsa->dmp1 == NULL) goto err; + if (!BN_mod(rsa->dmp1,rsa->d,r1,ctx)) goto err; + + /* calculate d mod (q-1) */ + rsa->dmq1=BN_new(); + if (rsa->dmq1 == NULL) goto err; + if (!BN_mod(rsa->dmq1,rsa->d,r2,ctx)) goto err; + + /* calculate inverse of q mod p */ + rsa->iqmp=BN_mod_inverse(NULL,rsa->q,rsa->p,ctx2); + if (rsa->iqmp == NULL) goto err; + + ok=1; +err: + if (ok == -1) + { + RSAerr(RSA_F_RSA_GENERATE_KEY,ERR_LIB_BN); + ok=0; + } + BN_CTX_end(ctx); + BN_CTX_free(ctx); + BN_CTX_free(ctx2); + + if (!ok) + { + if (rsa != NULL) RSA_free(rsa); + return(NULL); + } + else + return(rsa); + } + diff --git a/libsecurity_apple_csp/open_ssl/rsa/rsa_lib.c b/libsecurity_apple_csp/open_ssl/rsa/rsa_lib.c new file mode 100644 index 00000000..733cbf17 --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/rsa/rsa_lib.c @@ -0,0 +1,453 @@ +/* + * 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. + */ + + +/* crypto/rsa/rsa_lib.c */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include +#include +#include "cryptlib.h" +#include +#include +#include +#include + +const char *RSA_version="RSA" OPENSSL_VERSION_PTEXT; + +static const RSA_METHOD *default_RSA_meth=NULL; +static int rsa_meth_num=0; +static STACK_OF(CRYPTO_EX_DATA_FUNCS) *rsa_meth=NULL; + +RSA *RSA_new(void) + { + return(RSA_new_method(NULL)); + } + +void RSA_set_default_method(const RSA_METHOD *meth) + { + default_RSA_meth=meth; + } + +const RSA_METHOD *RSA_get_default_method(void) +{ + return default_RSA_meth; +} + +const RSA_METHOD *RSA_get_method(RSA *rsa) +{ + return rsa->meth; +} + +const RSA_METHOD *RSA_set_method(RSA *rsa, const RSA_METHOD *meth) +{ + const RSA_METHOD *mtmp; + mtmp = rsa->meth; + if (mtmp->finish) mtmp->finish(rsa); + rsa->meth = meth; + if (meth->init) meth->init(rsa); + return mtmp; +} + +RSA *RSA_new_method(const RSA_METHOD *meth) + { + RSA *ret; + + if (default_RSA_meth == NULL) + { +#ifdef RSA_NULL + default_RSA_meth=RSA_null_method(); +#else +#ifdef RSAref + default_RSA_meth=RSA_PKCS1_RSAref(); +#else + default_RSA_meth=RSA_PKCS1_SSLeay(); +#endif +#endif + } + ret=(RSA *)Malloc(sizeof(RSA)); + if (ret == NULL) + { + RSAerr(RSA_F_RSA_NEW_METHOD,ERR_R_MALLOC_FAILURE); + return(NULL); + } + + if (meth == NULL) + ret->meth=default_RSA_meth; + else + ret->meth=meth; + + ret->pad=0; + ret->version=0; + ret->n=NULL; + ret->e=NULL; + ret->d=NULL; + ret->p=NULL; + ret->q=NULL; + ret->dmp1=NULL; + ret->dmq1=NULL; + ret->iqmp=NULL; + ret->references=1; + ret->_method_mod_n=NULL; + ret->_method_mod_p=NULL; + ret->_method_mod_q=NULL; + + // make blinding per thread + ret->num_blinding_threads = 0; + pthread_mutex_init(&ret->blinding_mutex, NULL); + ret->blinding_array = NULL; + + ret->bignum_data=NULL; + ret->flags=ret->meth->flags; + if ((ret->meth->init != NULL) && !ret->meth->init(ret)) + { + Free(ret); + ret=NULL; + } + else + CRYPTO_new_ex_data(rsa_meth,ret,&ret->ex_data); + return(ret); + } + +void RSA_free(RSA *r) + { + int i; + + if (r == NULL) return; + + i=CRYPTO_add(&r->references,-1,CRYPTO_LOCK_RSA); +#ifdef REF_PRINT + REF_PRINT("RSA",r); +#endif + if (i > 0) return; +#ifdef REF_CHECK + if (i < 0) + { + fprintf(stderr,"RSA_free, bad reference count\n"); + abort(); + } +#endif + + CRYPTO_free_ex_data(rsa_meth,r,&r->ex_data); + + if (r->meth->finish != NULL) + r->meth->finish(r); + + if (r->n != NULL) BN_clear_free(r->n); + if (r->e != NULL) BN_clear_free(r->e); + if (r->d != NULL) BN_clear_free(r->d); + if (r->p != NULL) BN_clear_free(r->p); + if (r->q != NULL) BN_clear_free(r->q); + if (r->dmp1 != NULL) BN_clear_free(r->dmp1); + if (r->dmq1 != NULL) BN_clear_free(r->dmq1); + if (r->iqmp != NULL) BN_clear_free(r->iqmp); + RSA_free_thread_blinding_ptr(r); + if (r->bignum_data != NULL) Free_locked(r->bignum_data); + Free(r); + } + +int RSA_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, + CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func) + { + rsa_meth_num++; + return(CRYPTO_get_ex_new_index(rsa_meth_num-1, + &rsa_meth,argl,argp,new_func,dup_func,free_func)); + } + +int RSA_set_ex_data(RSA *r, int idx, void *arg) + { + return(CRYPTO_set_ex_data(&r->ex_data,idx,arg)); + } + +void *RSA_get_ex_data(RSA *r, int idx) + { + return(CRYPTO_get_ex_data(&r->ex_data,idx)); + } + +int RSA_size(RSA *r) + { + return(BN_num_bytes(r->n)); + } + +int RSA_public_encrypt(int flen, unsigned char *from, unsigned char *to, + RSA *rsa, int padding) + { + return(rsa->meth->rsa_pub_enc(flen, from, to, rsa, padding)); + } + +int RSA_private_encrypt(int flen, unsigned char *from, unsigned char *to, + RSA *rsa, int padding) + { + return(rsa->meth->rsa_priv_enc(flen, from, to, rsa, padding)); + } + +int RSA_private_decrypt(int flen, unsigned char *from, unsigned char *to, + RSA *rsa, int padding) + { + return(rsa->meth->rsa_priv_dec(flen, from, to, rsa, padding)); + } + +int RSA_public_decrypt(int flen, unsigned char *from, unsigned char *to, + RSA *rsa, int padding) + { + return(rsa->meth->rsa_pub_dec(flen, from, to, rsa, padding)); + } + +int RSA_flags(RSA *r) + { + return((r == NULL)?0:r->meth->flags); + } + +void RSA_blinding_off(RSA *rsa) + { + RSA_free_thread_blinding_ptr(rsa); + rsa->flags&= ~RSA_FLAG_BLINDING; + } + +int RSA_blinding_on(RSA *rsa, BN_CTX *p_ctx) + { + BIGNUM *A,*Ai; + BN_CTX *ctx; + int ret=0; + + if (p_ctx == NULL) + { + if ((ctx=BN_CTX_new()) == NULL) goto err; + } + else + ctx=p_ctx; + + RSA_free_thread_blinding_ptr(rsa); + + BN_CTX_start(ctx); + A = BN_CTX_get(ctx); + if (!BN_rand(A,BN_num_bits(rsa->n)-1,1,0)) goto err; + if ((Ai=BN_mod_inverse(NULL,A,rsa->n,ctx)) == NULL) goto err; + + if (!rsa->meth->bn_mod_exp(A,A,rsa->e,rsa->n,ctx,rsa->_method_mod_n)) + goto err; + RSA_set_thread_blinding_ptr(rsa, BN_BLINDING_new(A,Ai,rsa->n)); + rsa->flags|=RSA_FLAG_BLINDING; + BN_free(Ai); + ret=1; +err: + BN_CTX_end(ctx); + if (ctx != p_ctx) BN_CTX_free(ctx); + return(ret); + } + +int RSA_memory_lock(RSA *r) + { + int i,j,k,off; + char *p; + BIGNUM *bn,**t[6],*b; + BN_ULONG *ul; + + if (r->d == NULL) return(1); + t[0]= &r->d; + t[1]= &r->p; + t[2]= &r->q; + t[3]= &r->dmp1; + t[4]= &r->dmq1; + t[5]= &r->iqmp; + k=sizeof(BIGNUM)*6; + off=k/sizeof(BN_ULONG)+1; + j=1; + for (i=0; i<6; i++) + j+= (*t[i])->top; + if ((p=Malloc_locked((off+j)*sizeof(BN_ULONG))) == NULL) + { + RSAerr(RSA_F_MEMORY_LOCK,ERR_R_MALLOC_FAILURE); + return(0); + } + bn=(BIGNUM *)p; + ul=(BN_ULONG *)&(p[off]); + for (i=0; i<6; i++) + { + b= *(t[i]); + *(t[i])= &(bn[i]); + memcpy((char *)&(bn[i]),(char *)b,sizeof(BIGNUM)); + bn[i].flags=BN_FLG_STATIC_DATA; + bn[i].d=ul; + memcpy((char *)ul,b->d,sizeof(BN_ULONG)*b->top); + ul+=b->top; + BN_clear_free(b); + } + + /* I should fix this so it can still be done */ + r->flags&= ~(RSA_FLAG_CACHE_PRIVATE|RSA_FLAG_CACHE_PUBLIC); + + r->bignum_data=p; + return(1); + } + +struct BN_BLINDING_STRUCT +{ + pthread_t thread_ID; + BN_BLINDING* blinding; +}; + + + +static struct BN_BLINDING_STRUCT* RSA_get_blinding_struct(RSA *r) +{ + // look for storage for the current thread + pthread_t current = pthread_self(); + + int i; + for (i = 0; i < r->num_blinding_threads; ++i) + { + if (pthread_equal(current, r->blinding_array[i].thread_ID)) // do we have storage for this thread? + { + return &(r->blinding_array[i]); + break; + } + } + + return NULL; +} + +typedef struct BN_BLINDING_STRUCT BN_BLINDING_STRUCT; + + +BN_BLINDING* RSA_get_thread_blinding_ptr(RSA *r) +{ + // lock down the structure + pthread_mutex_lock(&r->blinding_mutex); + + BN_BLINDING* result = NULL; + BN_BLINDING_STRUCT *st = RSA_get_blinding_struct(r); + if (st != NULL) + { + result = st->blinding; + } + + pthread_mutex_unlock(&r->blinding_mutex); + + return result; +} + + + +void RSA_set_thread_blinding_ptr(RSA *r, BN_BLINDING* bnb) +{ + // lock down the structure + pthread_mutex_lock(&r->blinding_mutex); + + // see if there is an existing record for this thread + BN_BLINDING_STRUCT *st = RSA_get_blinding_struct(r); + if (st == NULL) + { + // add a new blinding struct + int last_member = r->num_blinding_threads; + r->num_blinding_threads += 1; + r->blinding_array = (BN_BLINDING_STRUCT*) realloc(r->blinding_array, sizeof(BN_BLINDING_STRUCT) * r->num_blinding_threads); + st = &r->blinding_array[last_member]; + } + + st->thread_ID = pthread_self(); + st->blinding = bnb; + + pthread_mutex_unlock(&r->blinding_mutex); +} + + + +void RSA_free_thread_blinding_ptr(RSA *r) +{ + // look for storage for the current thread + pthread_t current = pthread_self(); + + int i; + for (i = 0; i < r->num_blinding_threads; ++i) + { + if (pthread_equal(current, r->blinding_array[i].thread_ID)) // do we have storage for this thread? + { + BN_BLINDING_free(r->blinding_array[i].blinding); + + int new_count = r->num_blinding_threads - 1; + if (new_count == 0) + { + // no more thread storage, just blow our array away + free(r->blinding_array); + r->blinding_array = NULL; + r->num_blinding_threads = 0; + } + else + { + r->blinding_array[i] = r->blinding_array[new_count]; + r->num_blinding_threads = new_count; + } + break; + } + } +} diff --git a/libsecurity_apple_csp/open_ssl/rsa/rsa_none.c b/libsecurity_apple_csp/open_ssl/rsa/rsa_none.c new file mode 100644 index 00000000..d340c8f3 --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/rsa/rsa_none.c @@ -0,0 +1,116 @@ +/* + * 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. + */ + + +/* crypto/rsa/rsa_none.c */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include +#include "cryptlib.h" +#include +#include +#include + +int RSA_padding_add_none(unsigned char *to, int tlen, unsigned char *from, + int flen) + { + if (flen > tlen) + { + RSAerr(RSA_F_RSA_PADDING_ADD_NONE,RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE); + return(0); + } + + if (flen < tlen) + { + RSAerr(RSA_F_RSA_PADDING_ADD_NONE,RSA_R_DATA_TOO_SMALL_FOR_KEY_SIZE); + return(0); + } + + memcpy(to,from,(unsigned int)flen); + return(1); + } + +int RSA_padding_check_none(unsigned char *to, int tlen, unsigned char *from, + int flen, int num) + { + + if (flen > tlen) + { + RSAerr(RSA_F_RSA_PADDING_CHECK_NONE,RSA_R_DATA_TOO_LARGE); + return(-1); + } + + memset(to,0,tlen-flen); + memcpy(to+tlen-flen,from,flen); + return(tlen); + } + diff --git a/libsecurity_apple_csp/open_ssl/rsa/rsa_null.c b/libsecurity_apple_csp/open_ssl/rsa/rsa_null.c new file mode 100644 index 00000000..f3268fa8 --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/rsa/rsa_null.c @@ -0,0 +1,167 @@ +/* + * 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. + */ + + +/* rsa_null.c */ +/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL + * project 1999. + */ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include +#include "cryptlib.h" +#include +#include +#include + +/* This is a dummy RSA implementation that just returns errors when called. + * It is designed to allow some RSA functions to work while stopping those + * covered by the RSA patent. That is RSA, encryption, decryption, signing + * and verify is not allowed but RSA key generation, key checking and other + * operations (like storing RSA keys) are permitted. + */ + +static int RSA_null_public_encrypt(int flen, unsigned char *from, + unsigned char *to, RSA *rsa,int padding); +static int RSA_null_private_encrypt(int flen, unsigned char *from, + unsigned char *to, RSA *rsa,int padding); +static int RSA_null_public_decrypt(int flen, unsigned char *from, + unsigned char *to, RSA *rsa,int padding); +static int RSA_null_private_decrypt(int flen, unsigned char *from, + unsigned char *to, RSA *rsa,int padding); +#if 0 /* not currently used */ +static int RSA_null_mod_exp(BIGNUM *r0, BIGNUM *i, RSA *rsa); +#endif +static int RSA_null_init(RSA *rsa); +static int RSA_null_finish(RSA *rsa); +static const RSA_METHOD rsa_null_meth={ + "Null RSA", + RSA_null_public_encrypt, + RSA_null_public_decrypt, + RSA_null_private_encrypt, + RSA_null_private_decrypt, + NULL, NULL, + RSA_null_init, + RSA_null_finish, + 0, + NULL, + }; + +const RSA_METHOD *RSA_null_method(void) + { + return(&rsa_null_meth); + } + +static int RSA_null_public_encrypt(int flen, unsigned char *from, + unsigned char *to, RSA *rsa, int padding) + { + RSAerr(RSA_F_RSA_NULL, RSA_R_RSA_OPERATIONS_NOT_SUPPORTED); + return -1; + } + +static int RSA_null_private_encrypt(int flen, unsigned char *from, + unsigned char *to, RSA *rsa, int padding) + { + RSAerr(RSA_F_RSA_NULL, RSA_R_RSA_OPERATIONS_NOT_SUPPORTED); + return -1; + } + +static int RSA_null_private_decrypt(int flen, unsigned char *from, + unsigned char *to, RSA *rsa, int padding) + { + RSAerr(RSA_F_RSA_NULL, RSA_R_RSA_OPERATIONS_NOT_SUPPORTED); + return -1; + } + +static int RSA_null_public_decrypt(int flen, unsigned char *from, + unsigned char *to, RSA *rsa, int padding) + { + RSAerr(RSA_F_RSA_NULL, RSA_R_RSA_OPERATIONS_NOT_SUPPORTED); + return -1; + } + +#if 0 /* not currently used */ +static int RSA_null_mod_exp(BIGNUM *r0, BIGNUM *I, RSA *rsa) + { + RSAerr(RSA_F_RSA_NULL, RSA_R_RSA_OPERATIONS_NOT_SUPPORTED); + return -1; + } +#endif + +static int RSA_null_init(RSA *rsa) + { + return(1); + } + +static int RSA_null_finish(RSA *rsa) + { + return(1); + } + + diff --git a/libsecurity_apple_csp/open_ssl/rsa/rsa_pk1.c b/libsecurity_apple_csp/open_ssl/rsa/rsa_pk1.c new file mode 100644 index 00000000..98fc3c88 --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/rsa/rsa_pk1.c @@ -0,0 +1,242 @@ +/* + * 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. + */ + + +/* crypto/rsa/rsa_pk1.c */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include +#include "cryptlib.h" +#include +#include +#include + +int RSA_padding_add_PKCS1_type_1(unsigned char *to, int tlen, + unsigned char *from, int flen) + { + int j; + unsigned char *p; + + if (flen > (tlen-11)) + { + RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_TYPE_1,RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE); + return(0); + } + + p=(unsigned char *)to; + + *(p++)=0; + *(p++)=1; /* Private Key BT (Block Type) */ + + /* pad out with 0xff data */ + j=tlen-3-flen; + memset(p,0xff,j); + p+=j; + *(p++)='\0'; + memcpy(p,from,(unsigned int)flen); + return(1); + } + +int RSA_padding_check_PKCS1_type_1(unsigned char *to, int tlen, + unsigned char *from, int flen, int num) + { + int i,j; + unsigned char *p; + + p=from; + if ((num != (flen+1)) || (*(p++) != 01)) + { + RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_1,RSA_R_BLOCK_TYPE_IS_NOT_01); + return(-1); + } + + /* scan over padding data */ + j=flen-1; /* one for type. */ + for (i=0; i tlen) + { + RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_1,RSA_R_DATA_TOO_LARGE); + return(-1); + } + memcpy(to,p,(unsigned int)j); + + return(j); + } + +int RSA_padding_add_PKCS1_type_2(unsigned char *to, int tlen, + unsigned char *from, int flen) + { + int i,j; + unsigned char *p; + + if (flen > (tlen-11)) + { + RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_TYPE_2,RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE); + return(0); + } + + p=(unsigned char *)to; + + *(p++)=0; + *(p++)=2; /* Public Key BT (Block Type) */ + + /* pad out with non-zero random data */ + j=tlen-3-flen; + + if (RAND_bytes(p,j) <= 0) + return(0); + for (i=0; i tlen) + { + RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_2,RSA_R_DATA_TOO_LARGE); + return(-1); + } + memcpy(to,p,(unsigned int)j); + + return(j); + } + diff --git a/libsecurity_apple_csp/open_ssl/rsa/rsa_saos.c b/libsecurity_apple_csp/open_ssl/rsa/rsa_saos.c new file mode 100644 index 00000000..82d4c617 --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/rsa/rsa_saos.c @@ -0,0 +1,162 @@ +/* + * 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. + */ + + +/* crypto/rsa/rsa_saos.c */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include +#include "cryptlib.h" +#include +#include +#include +#include + +int RSA_sign_ASN1_OCTET_STRING(int type, unsigned char *m, unsigned int m_len, + unsigned char *sigret, unsigned int *siglen, RSA *rsa) + { + ASN1_OCTET_STRING sig; + int i,j,ret=1; + unsigned char *p,*s; + + sig.type=V_ASN1_OCTET_STRING; + sig.length=m_len; + sig.data=m; + + i=i2d_ASN1_OCTET_STRING(&sig,NULL); + j=RSA_size(rsa); + if ((i-RSA_PKCS1_PADDING) > j) + { + RSAerr(RSA_F_RSA_SIGN_ASN1_OCTET_STRING,RSA_R_DIGEST_TOO_BIG_FOR_RSA_KEY); + return(0); + } + s=(unsigned char *)Malloc((unsigned int)j+1); + if (s == NULL) + { + RSAerr(RSA_F_RSA_SIGN_ASN1_OCTET_STRING,ERR_R_MALLOC_FAILURE); + return(0); + } + p=s; + i2d_ASN1_OCTET_STRING(&sig,&p); + i=RSA_private_encrypt(i,s,sigret,rsa,RSA_PKCS1_PADDING); + if (i <= 0) + ret=0; + else + *siglen=i; + + memset(s,0,(unsigned int)j+1); + Free(s); + return(ret); + } + +int RSA_verify_ASN1_OCTET_STRING(int dtype, unsigned char *m, + unsigned int m_len, unsigned char *sigbuf, unsigned int siglen, + RSA *rsa) + { + int i,ret=0; + unsigned char *p,*s; + ASN1_OCTET_STRING *sig=NULL; + + if (siglen != (unsigned int)RSA_size(rsa)) + { + RSAerr(RSA_F_RSA_VERIFY_ASN1_OCTET_STRING,RSA_R_WRONG_SIGNATURE_LENGTH); + return(0); + } + + s=(unsigned char *)Malloc((unsigned int)siglen); + if (s == NULL) + { + RSAerr(RSA_F_RSA_VERIFY_ASN1_OCTET_STRING,ERR_R_MALLOC_FAILURE); + goto err; + } + i=RSA_public_decrypt((int)siglen,sigbuf,s,rsa,RSA_PKCS1_PADDING); + + if (i <= 0) goto err; + + p=s; + sig=d2i_ASN1_OCTET_STRING(NULL,&p,(long)i); + if (sig == NULL) goto err; + + if ( ((unsigned int)sig->length != m_len) || + (memcmp(m,sig->data,m_len) != 0)) + { + RSAerr(RSA_F_RSA_VERIFY_ASN1_OCTET_STRING,RSA_R_BAD_SIGNATURE); + } + else + ret=1; +err: + if (sig != NULL) M_ASN1_OCTET_STRING_free(sig); + memset(s,0,(unsigned int)siglen); + Free(s); + return(ret); + } + diff --git a/libsecurity_apple_csp/open_ssl/rsa/rsa_sign.c b/libsecurity_apple_csp/open_ssl/rsa/rsa_sign.c new file mode 100644 index 00000000..ebfd14f5 --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/rsa/rsa_sign.c @@ -0,0 +1,239 @@ +/* + * 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. + */ + + +/* crypto/rsa/rsa_sign.c */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include +#include "cryptlib.h" +#include +#include +#include +#include + +/* Size of an SSL signature: MD5+SHA1 */ +#define SSL_SIG_LENGTH 36 + +int RSA_sign(int type, unsigned char *m, unsigned int m_len, + unsigned char *sigret, unsigned int *siglen, RSA *rsa) + { + X509_SIG sig; + ASN1_TYPE parameter; + int i,j,ret=1; + unsigned char *p,*s = NULL; + X509_ALGOR algor; + ASN1_OCTET_STRING digest; + if(rsa->flags & RSA_FLAG_SIGN_VER) + return rsa->meth->rsa_sign(type, m, m_len, sigret, siglen, rsa); + /* Special case: SSL signature, just check the length */ + if(type == NID_md5_sha1) { + if(m_len != SSL_SIG_LENGTH) { + RSAerr(RSA_F_RSA_SIGN,RSA_R_INVALID_MESSAGE_LENGTH); + return(0); + } + i = SSL_SIG_LENGTH; + s = m; + } else { + sig.algor= &algor; + sig.algor->algorithm=OBJ_nid2obj(type); + if (sig.algor->algorithm == NULL) + { + RSAerr(RSA_F_RSA_SIGN,RSA_R_UNKNOWN_ALGORITHM_TYPE); + return(0); + } + if (sig.algor->algorithm->length == 0) + { + RSAerr(RSA_F_RSA_SIGN,RSA_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD); + return(0); + } + parameter.type=V_ASN1_NULL; + parameter.value.ptr=NULL; + sig.algor->parameter= ¶meter; + + sig.digest= &digest; + sig.digest->data=m; + sig.digest->length=m_len; + + i=i2d_X509_SIG(&sig,NULL); + } + j=RSA_size(rsa); + if ((i-RSA_PKCS1_PADDING) > j) + { + RSAerr(RSA_F_RSA_SIGN,RSA_R_DIGEST_TOO_BIG_FOR_RSA_KEY); + return(0); + } + if(type != NID_md5_sha1) { + s=(unsigned char *)Malloc((unsigned int)j+1); + if (s == NULL) + { + RSAerr(RSA_F_RSA_SIGN,ERR_R_MALLOC_FAILURE); + return(0); + } + p=s; + i2d_X509_SIG(&sig,&p); + } + i=RSA_private_encrypt(i,s,sigret,rsa,RSA_PKCS1_PADDING); + if (i <= 0) + ret=0; + else + *siglen=i; + + if(type != NID_md5_sha1) { + memset(s,0,(unsigned int)j+1); + Free(s); + } + return(ret); + } + +int RSA_verify(int dtype, unsigned char *m, unsigned int m_len, + unsigned char *sigbuf, unsigned int siglen, RSA *rsa) + { + int i,ret=0,sigtype; + unsigned char *p,*s; + X509_SIG *sig=NULL; + + if (siglen != (unsigned int)RSA_size(rsa)) + { + RSAerr(RSA_F_RSA_VERIFY,RSA_R_WRONG_SIGNATURE_LENGTH); + return(0); + } + + if(rsa->flags & RSA_FLAG_SIGN_VER) + return rsa->meth->rsa_verify(dtype, m, m_len, sigbuf, siglen, rsa); + + s=(unsigned char *)Malloc((unsigned int)siglen); + if (s == NULL) + { + RSAerr(RSA_F_RSA_VERIFY,ERR_R_MALLOC_FAILURE); + goto err; + } + if((dtype == NID_md5_sha1) && (m_len != SSL_SIG_LENGTH) ) { + RSAerr(RSA_F_RSA_VERIFY,RSA_R_INVALID_MESSAGE_LENGTH); + return(0); + } + i=RSA_public_decrypt((int)siglen,sigbuf,s,rsa,RSA_PKCS1_PADDING); + + if (i <= 0) goto err; + + /* Special case: SSL signature */ + if(dtype == NID_md5_sha1) { + if((i != SSL_SIG_LENGTH) || memcmp(s, m, SSL_SIG_LENGTH)) + RSAerr(RSA_F_RSA_VERIFY,RSA_R_BAD_SIGNATURE); + else ret = 1; + } else { + p=s; + sig=d2i_X509_SIG(NULL,&p,(long)i); + + if (sig == NULL) goto err; + sigtype=OBJ_obj2nid(sig->algor->algorithm); + + + #ifdef RSA_DEBUG + /* put a backward compatibility flag in EAY */ + fprintf(stderr,"in(%s) expect(%s)\n",OBJ_nid2ln(sigtype), + OBJ_nid2ln(dtype)); + #endif + if (sigtype != dtype) + { + if (((dtype == NID_md5) && + (sigtype == NID_md5WithRSAEncryption)) || + ((dtype == NID_md2) && + (sigtype == NID_md2WithRSAEncryption))) + { + /* ok, we will let it through */ + #if !defined(NO_STDIO) && !defined(WIN16) + fprintf(stderr,"signature has problems, re-make with post SSLeay045\n"); + #endif + } + else + { + RSAerr(RSA_F_RSA_VERIFY, + RSA_R_ALGORITHM_MISMATCH); + goto err; + } + } + if ( ((unsigned int)sig->digest->length != m_len) || + (memcmp(m,sig->digest->data,m_len) != 0)) + { + RSAerr(RSA_F_RSA_VERIFY,RSA_R_BAD_SIGNATURE); + } + else + ret=1; + } +err: + if (sig != NULL) X509_SIG_free(sig); + memset(s,0,(unsigned int)siglen); + Free(s); + return(ret); + } + diff --git a/libsecurity_apple_csp/open_ssl/rsa/rsa_ssl.c b/libsecurity_apple_csp/open_ssl/rsa/rsa_ssl.c new file mode 100644 index 00000000..3b5ca851 --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/rsa/rsa_ssl.c @@ -0,0 +1,177 @@ +/* + * 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. + */ + + +/* crypto/rsa/rsa_ssl.c */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include +#include "cryptlib.h" +#include +#include +#include + +int RSA_padding_add_SSLv23(unsigned char *to, int tlen, unsigned char *from, + int flen) + { + int i,j; + unsigned char *p; + + if (flen > (tlen-11)) + { + RSAerr(RSA_F_RSA_PADDING_ADD_SSLV23,RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE); + return(0); + } + + p=(unsigned char *)to; + + *(p++)=0; + *(p++)=2; /* Public Key BT (Block Type) */ + + /* pad out with non-zero random data */ + j=tlen-3-8-flen; + + if (RAND_bytes(p,j) <= 0) + return(0); + for (i=0; i tlen) + { + RSAerr(RSA_F_RSA_PADDING_CHECK_SSLV23,RSA_R_DATA_TOO_LARGE); + return(-1); + } + memcpy(to,p,(unsigned int)j); + + return(j); + } + diff --git a/libsecurity_apple_csp/open_ssl/stack/stack.c b/libsecurity_apple_csp/open_ssl/stack/stack.c new file mode 100644 index 00000000..d62120c7 --- /dev/null +++ b/libsecurity_apple_csp/open_ssl/stack/stack.c @@ -0,0 +1,329 @@ +/* + * 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. + */ + + +/* crypto/stack/stack.c */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +/* Code for stacks + * Author - Eric Young v 1.0 + * 1.2 eay 12-Mar-97 - Modified sk_find so that it _DOES_ return the + * lowest index for the searched item. + * + * 1.1 eay - Take from netdb and added to SSLeay + * + * 1.0 eay - First version 29/07/92 + */ +#include +#include "cryptlib.h" +#include + +#undef MIN_NODES +#define MIN_NODES 4 + +const char *STACK_version="Stack" OPENSSL_VERSION_PTEXT; + +#define FP_ICC (int (*)(const void *,const void *)) +#include + +int (*sk_set_cmp_func(STACK *sk, int (*c)()))(void) + { + int (*old)()=sk->comp; + + if (sk->comp != c) + sk->sorted=0; + sk->comp=c; + + return old; + } + +STACK *sk_dup(STACK *sk) + { + STACK *ret; + char **s; + + if ((ret=sk_new(sk->comp)) == NULL) goto err; + s=(char **)Realloc((char *)ret->data, + (unsigned int)sizeof(char *)*sk->num_alloc); + if (s == NULL) goto err; + ret->data=s; + + ret->num=sk->num; + memcpy(ret->data,sk->data,sizeof(char *)*sk->num); + ret->sorted=sk->sorted; + ret->num_alloc=sk->num_alloc; + ret->comp=sk->comp; + return(ret); +err: + return(NULL); + } + +STACK *sk_new(int (*c)()) + { + STACK *ret; + int i; + + if ((ret=(STACK *)Malloc(sizeof(STACK))) == NULL) + goto err0; + if ((ret->data=(char **)Malloc(sizeof(char *)*MIN_NODES)) == NULL) + goto err1; + for (i=0; idata[i]=NULL; + ret->comp=c; + ret->num_alloc=MIN_NODES; + ret->num=0; + ret->sorted=0; + return(ret); +err1: + Free(ret); +err0: + return(NULL); + } + +int sk_insert(STACK *st, char *data, int loc) + { + char **s; + + if(st == NULL) return 0; + if (st->num_alloc <= st->num+1) + { + s=(char **)Realloc((char *)st->data, + (unsigned int)sizeof(char *)*st->num_alloc*2); + if (s == NULL) + return(0); + st->data=s; + st->num_alloc*=2; + } + if ((loc >= (int)st->num) || (loc < 0)) + st->data[st->num]=data; + else + { + int i; + char **f,**t; + + f=(char **)st->data; + t=(char **)&(st->data[1]); + for (i=st->num; i>=loc; i--) + t[i]=f[i]; + +#ifdef undef /* no memmove on sunos :-( */ + memmove( (char *)&(st->data[loc+1]), + (char *)&(st->data[loc]), + sizeof(char *)*(st->num-loc)); +#endif + st->data[loc]=data; + } + st->num++; + st->sorted=0; + return(st->num); + } + +char *sk_delete_ptr(STACK *st, char *p) + { + int i; + + for (i=0; inum; i++) + if (st->data[i] == p) + return(sk_delete(st,i)); + return(NULL); + } + +char *sk_delete(STACK *st, int loc) + { + char *ret; + int i,j; + + if ((st == NULL) || (st->num == 0) || (loc < 0) + || (loc >= st->num)) return(NULL); + + ret=st->data[loc]; + if (loc != st->num-1) + { + j=st->num-1; + for (i=loc; idata[i]=st->data[i+1]; + /* In theory memcpy is not safe for this + * memcpy( &(st->data[loc]), + * &(st->data[loc+1]), + * sizeof(char *)*(st->num-loc-1)); + */ + } + st->num--; + return(ret); + } + +int sk_find(STACK *st, char *data) + { + char **r; + int i; + int (*comp_func)(); + if(st == NULL) return -1; + + if (st->comp == NULL) + { + for (i=0; inum; i++) + if (st->data[i] == data) + return(i); + return(-1); + } + sk_sort(st); + if (data == NULL) return(-1); + comp_func=(int (*)())st->comp; + r=(char **)bsearch(&data,(char *)st->data, + st->num,sizeof(char *),FP_ICC comp_func); + if (r == NULL) return(-1); + i=(int)(r-st->data); + for ( ; i>0; i--) + if ((*st->comp)(&(st->data[i-1]),&data) < 0) + break; + return(i); + } + +int sk_push(STACK *st, char *data) + { + return(sk_insert(st,data,st->num)); + } + +int sk_unshift(STACK *st, char *data) + { + return(sk_insert(st,data,0)); + } + +char *sk_shift(STACK *st) + { + if (st == NULL) return(NULL); + if (st->num <= 0) return(NULL); + return(sk_delete(st,0)); + } + +char *sk_pop(STACK *st) + { + if (st == NULL) return(NULL); + if (st->num <= 0) return(NULL); + return(sk_delete(st,st->num-1)); + } + +void sk_zero(STACK *st) + { + if (st == NULL) return; + if (st->num <= 0) return; + memset((char *)st->data,0,sizeof(st->data)*st->num); + st->num=0; + } + +void sk_pop_free(STACK *st, void (*func)()) + { + int i; + + if (st == NULL) return; + for (i=0; inum; i++) + if (st->data[i] != NULL) + func(st->data[i]); + sk_free(st); + } + +void sk_free(STACK *st) + { + if (st == NULL) return; + if (st->data != NULL) Free(st->data); + Free(st); + } + +int sk_num(STACK *st) +{ + if(st == NULL) return -1; + return st->num; +} + +char *sk_value(STACK *st, int i) +{ + if(st == NULL) return NULL; + return st->data[i]; +} + +char *sk_set(STACK *st, int i, char *value) +{ + if(st == NULL) return NULL; + return (st->data[i] = value); +} + +void sk_sort(STACK *st) + { + if (!st->sorted) + { + int (*comp_func)(); + + comp_func=(int (*)())st->comp; + qsort(st->data,st->num,sizeof(char *),FP_ICC comp_func); + st->sorted=1; + } + } diff --git a/libsecurity_apple_csp/tests/t-dsa.cpp b/libsecurity_apple_csp/tests/t-dsa.cpp new file mode 100644 index 00000000..47d20b31 --- /dev/null +++ b/libsecurity_apple_csp/tests/t-dsa.cpp @@ -0,0 +1,143 @@ +/* + * 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 +#include +#include + + +B_ALGORITHM_METHOD *chooser[] = { + &AM_DSA_KEY_GEN, + &AM_DSA_PARAM_GEN, + &AM_SHA_RANDOM, + NULL +}; + +void dumpItem(ITEM &item, const char *name); + +unsigned char seed[] = { 17, 205, 99, 13, 6, 199 }; + + +#define check(expr) \ + if (status = (expr)) { printf("error %d at %d\n", status, __LINE__); abort(); } else /* ok */ + +int main(int argc, char *argv[]) +{ + int status; + + int keySize = argv[1] ? atoi(argv[1]) : 512; + printf("Key size = %d bits\n", keySize); + + B_ALGORITHM_OBJ pGen = NULL; + check(B_CreateAlgorithmObject(&pGen)); + B_DSA_PARAM_GEN_PARAMS gParams; + gParams.primeBits = keySize; + check(B_SetAlgorithmInfo(pGen, AI_DSAParamGen, POINTER(&gParams))); + + B_ALGORITHM_OBJ random = NULL; check(B_CreateAlgorithmObject(&random)); + check(B_SetAlgorithmInfo(random, AI_X962Random_V0, NULL)); + check(B_RandomInit(random, chooser, NULL)); + check(B_RandomUpdate(random, seed, sizeof(seed), NULL)); + + check(B_GenerateInit(pGen, chooser, NULL)); + B_ALGORITHM_OBJ result = NULL; + check(B_CreateAlgorithmObject(&result)); + printf("Generating DSA parameters\n"); + check(B_GenerateParameters(pGen, result, random, NULL)); + printf("DSA generate complete, writing...\n"); + + A_DSA_PARAMS *dParams; + memset(&dParams, 0, sizeof(dParams)); + check(B_GetAlgorithmInfo((POINTER *)&dParams, result, AI_DSAKeyGen)); + dumpItem(dParams->prime, "prime"); + dumpItem(dParams->subPrime, "subprime"); + dumpItem(dParams->base, "base"); + +#if 0 + B_KEY_OBJ pubKey = NULL; check(B_CreateKeyObject(&pubKey)); + B_KEY_OBJ privKey = NULL; check(B_CreateKeyObject(&privKey)); + + B_ALGORITHM_OBJ gen = NULL; check(B_CreateAlgorithmObject(&gen)); + A_RSA_KEY_GEN_PARAMS args; + args.modulusBits = keySize; + args.publicExponent.data = exponent; + args.publicExponent.len = sizeof(exponent); + check(B_SetAlgorithmInfo(gen, AI_RSAStrongKeyGen, POINTER(&args))); + check(B_GenerateInit(gen, chooser, NULL)); + check(B_GenerateKeypair(gen, pubKey, privKey, random, NULL)); + + B_ALGORITHM_OBJ enc = NULL; check(B_CreateAlgorithmObject(&enc)); + check(B_SetAlgorithmInfo(enc, AI_PKCS_RSAPublic, NULL)); + check(B_EncryptInit(enc, pubKey, chooser, NULL)); + unsigned int inLen; + check(B_EncryptUpdate(enc, crypt, &inLen, sizeof(crypt), + POINTER(in), sizeof(in), random, NULL)); + printf("EncryptUpdate output = %u\n", inLen); + check(B_EncryptFinal(enc, crypt, &inLen, sizeof(crypt), random, NULL)); + printf("EncryptFinal output=%u\n", inLen); + + B_ALGORITHM_OBJ dec = NULL; check(B_CreateAlgorithmObject(&dec)); + check(B_SetAlgorithmInfo(dec, AI_PKCS_RSAPrivate, NULL)); + check(B_DecryptInit(dec, privKey, chooser, NULL)); + unsigned int outLen, outLen2; + check(B_DecryptUpdate(dec, out, &outLen, sizeof(out), + crypt, inLen, random, NULL)); + printf("DecryptUpdate output = %u\n", outLen); + check(B_DecryptFinal(dec, out2, &outLen2, sizeof(out2), random, NULL)); + printf("DecryptFinal output=%u %s\n", outLen2, (char*)out2); + B_DestroyKeyObject(&pubKey); + B_DestroyKeyObject(&privKey); +#endif + + exit(0); +} + +void dumpItem(ITEM &item, const char *name) +{ + printf("%s [%d] ", name, item.len); + for (unsigned char *p = item.data; p < item.data + item.len; p++) + printf("%2.2x", *p); + printf("\n"); +} + + + + + +void T_free(POINTER p) +{ free(p); } + +POINTER T_malloc(unsigned int size) +{ return (POINTER)malloc(size); } + +POINTER T_realloc(POINTER p, unsigned int size) +{ return (POINTER)realloc(p, size); } + +int T_memcmp(POINTER p1, POINTER p2, unsigned int size) +{ return memcmp(p1, p2, size); } +void T_memcpy(POINTER p1, POINTER p2, unsigned int size) +{ memcpy(p1, p2, size); } +void T_memmove(POINTER p1, POINTER p2, unsigned int size) +{ memmove(p1, p2, size); } +void T_memset(POINTER p1, int size, unsigned int val) +{ memset(p1, size, val); } +extern "C" int T_GetDynamicList() +{ printf("GetDynamicList!\n"); abort(); } diff --git a/libsecurity_apple_csp/tests/t-rsa.cpp b/libsecurity_apple_csp/tests/t-rsa.cpp new file mode 100644 index 00000000..950c647e --- /dev/null +++ b/libsecurity_apple_csp/tests/t-rsa.cpp @@ -0,0 +1,129 @@ +/* + * 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 +#include +#include + + +B_ALGORITHM_METHOD *chooser[] = { + &AM_SHA_RANDOM, + &AM_RSA_KEY_GEN, + &AM_RSA_STRONG_KEY_GEN, + &AM_RSA_ENCRYPT, + &AM_RSA_DECRYPT, + &AM_RSA_CRT_ENCRYPT, + &AM_RSA_CRT_DECRYPT, + NULL +}; + + +char in[] = "something wicked this way comes, " + "and it's a private key!"; +unsigned char crypt[1024]; +unsigned char out[1024], out2[1024]; + +unsigned char seed[] = { 17, 22, 99, 205, 3 }; + +unsigned char exponent[] = { 1, 0, 1 }; + +#define check(expr) \ + if (status = (expr)) { printf("error %d at %d\n", status, __LINE__); abort(); } else /* ok */ + +int main(int argc, char *argv[]) +{ + int status; + + int keySize = argv[1] ? atoi(argv[1]) : 512; + printf("Key size = %d bits\n", keySize); + + B_KEY_OBJ pubKey = NULL; check(B_CreateKeyObject(&pubKey)); + B_KEY_OBJ privKey = NULL; check(B_CreateKeyObject(&privKey)); + + B_ALGORITHM_OBJ random = NULL; check(B_CreateAlgorithmObject(&random)); + check(B_SetAlgorithmInfo(random, AI_X962Random_V0, NULL)); + check(B_RandomInit(random, chooser, NULL)); + check(B_RandomUpdate(random, seed, sizeof(seed), NULL)); + for (int n = 0; n < 5; n++) { + unsigned char buf[4]; + check(B_GenerateRandomBytes(random, + POINTER(buf), sizeof(buf), NULL)); + printf("Randoms = "); + for (int n = 0; n < sizeof(buf); n++) + printf("%2.2x", buf[n]); + printf("\n"); + } + + B_ALGORITHM_OBJ gen = NULL; check(B_CreateAlgorithmObject(&gen)); + A_RSA_KEY_GEN_PARAMS args; + args.modulusBits = keySize; + args.publicExponent.data = exponent; + args.publicExponent.len = sizeof(exponent); + check(B_SetAlgorithmInfo(gen, AI_RSAStrongKeyGen, POINTER(&args))); + check(B_GenerateInit(gen, chooser, NULL)); + check(B_GenerateKeypair(gen, pubKey, privKey, random, NULL)); + + B_ALGORITHM_OBJ enc = NULL; check(B_CreateAlgorithmObject(&enc)); + check(B_SetAlgorithmInfo(enc, AI_PKCS_RSAPublic, NULL)); + check(B_EncryptInit(enc, pubKey, chooser, NULL)); + unsigned int inLen; + check(B_EncryptUpdate(enc, crypt, &inLen, sizeof(crypt), + POINTER(in), sizeof(in), random, NULL)); + printf("EncryptUpdate output = %u\n", inLen); + check(B_EncryptFinal(enc, crypt, &inLen, sizeof(crypt), random, NULL)); + printf("EncryptFinal output=%u\n", inLen); + + B_ALGORITHM_OBJ dec = NULL; check(B_CreateAlgorithmObject(&dec)); + check(B_SetAlgorithmInfo(dec, AI_PKCS_RSAPrivate, NULL)); + check(B_DecryptInit(dec, privKey, chooser, NULL)); + unsigned int outLen, outLen2; + check(B_DecryptUpdate(dec, out, &outLen, sizeof(out), + crypt, inLen, random, NULL)); + printf("DecryptUpdate output = %u\n", outLen); + check(B_DecryptFinal(dec, out2, &outLen2, sizeof(out2), random, NULL)); + printf("DecryptFinal output=%u %s\n", outLen2, (char*)out2); + + + B_DestroyKeyObject(&pubKey); + B_DestroyKeyObject(&privKey); + B_DestroyAlgorithmObject(&random); + exit(0); +} + +void T_free(POINTER p) +{ free(p); } + +POINTER T_malloc(unsigned int size) +{ return (POINTER)malloc(size); } + +POINTER T_realloc(POINTER p, unsigned int size) +{ return (POINTER)realloc(p, size); } + +int T_memcmp(POINTER p1, POINTER p2, unsigned int size) +{ return memcmp(p1, p2, size); } +void T_memcpy(POINTER p1, POINTER p2, unsigned int size) +{ memcpy(p1, p2, size); } +void T_memmove(POINTER p1, POINTER p2, unsigned int size) +{ memmove(p1, p2, size); } +void T_memset(POINTER p1, int size, unsigned int val) +{ memset(p1, size, val); } +extern "C" int T_GetDynamicList() +{ printf("GetDynamicList!\n"); abort(); } diff --git a/libsecurity_apple_csp/tests/t.cpp b/libsecurity_apple_csp/tests/t.cpp new file mode 100644 index 00000000..3ed1c7f4 --- /dev/null +++ b/libsecurity_apple_csp/tests/t.cpp @@ -0,0 +1,113 @@ +/* + * 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 +#include +#include + + +B_ALGORITHM_METHOD *chooser[] = { + &AM_SHA, + &AM_SHA_RANDOM, + NULL +}; + +void dumpItem(ITEM &item, const char *name); + +unsigned char seed[] = { 17, 205, 99, 13, 6, 199 }; +char data[] = "These are the times that try men's souls."; + + +#define check(expr) \ + if (status = (expr)) { printf("error %d at %d\n", status, __LINE__); abort(); } else /* ok */ + +int main(int argc, char *argv[]) +{ + int status; + + ITEM key; + key.data = (unsigned char *)"Walla Walla Washington! Yeah, yeah, yeah!"; + key.len = strlen((const char *)key.data); + B_KEY_OBJ bsKey = NULL; + check(B_CreateKeyObject(&bsKey)); + check(B_SetKeyInfo(bsKey, KI_Item, POINTER(&key))); + + B_ALGORITHM_OBJ macAlg = NULL; + check(B_CreateAlgorithmObject(&macAlg)); + B_DIGEST_SPECIFIER macSpec; + macSpec.digestInfoType = AI_SHA1; + macSpec.digestInfoParams = NULL_PTR; + check(B_SetAlgorithmInfo(macAlg, AI_HMAC, POINTER(&macSpec))); + + check(B_DigestInit(macAlg, bsKey, chooser, NULL)); + check(B_DigestUpdate(macAlg, + POINTER(data), sizeof(data), NULL)); + char mac[128]; + unsigned int length; + check(B_DigestFinal(macAlg, POINTER(mac), &length, sizeof(mac), + NULL)); + ITEM macItem; macItem.data = POINTER(mac); macItem.len = length; + dumpItem(macItem, "MAC"); + + check(B_DigestUpdate(macAlg, POINTER(data), 10, NULL)); + check(B_DigestUpdate(macAlg, + POINTER(data+10), sizeof(data)-10, NULL)); + check(B_DigestFinal(macAlg, POINTER(mac), &length, sizeof(mac), + NULL)); + macItem.data = POINTER(mac); macItem.len = length; + dumpItem(macItem, "MAC"); + + printf("Done.\n"); + + exit(0); +} + +void dumpItem(ITEM &item, const char *name) +{ + printf("%s [%d] ", name, item.len); + for (unsigned char *p = item.data; p < item.data + item.len; p++) + printf("%2.2x", *p); + printf("\n"); +} + + + + + +void T_free(POINTER p) +{ free(p); } + +POINTER T_malloc(unsigned int size) +{ return (POINTER)malloc(size); } + +POINTER T_realloc(POINTER p, unsigned int size) +{ return (POINTER)realloc(p, size); } + +int T_memcmp(POINTER p1, POINTER p2, unsigned int size) +{ return memcmp(p1, p2, size); } +void T_memcpy(POINTER p1, POINTER p2, unsigned int size) +{ memcpy(p1, p2, size); } +void T_memmove(POINTER p1, POINTER p2, unsigned int size) +{ memmove(p1, p2, size); } +void T_memset(POINTER p1, int size, unsigned int val) +{ memset(p1, size, val); } +extern "C" int T_GetDynamicList() +{ printf("GetDynamicList!\n"); abort(); } diff --git a/libsecurity_apple_cspdl/Info-security_apple_cspdl.plist b/libsecurity_apple_cspdl/Info-security_apple_cspdl.plist new file mode 100644 index 00000000..0c67376e --- /dev/null +++ b/libsecurity_apple_cspdl/Info-security_apple_cspdl.plist @@ -0,0 +1,5 @@ + + + + + diff --git a/libsecurity_apple_cspdl/lib/AppleCSPDLBuiltin.cpp b/libsecurity_apple_cspdl/lib/AppleCSPDLBuiltin.cpp new file mode 100644 index 00000000..ca98a901 --- /dev/null +++ b/libsecurity_apple_cspdl/lib/AppleCSPDLBuiltin.cpp @@ -0,0 +1,32 @@ +/* + * 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 obtai +n + * 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. + */ + + +// +// Produce the "genuine plugin version" of the AppleCSPDL +// +#include + + +// +// Create the plugin object and generate the C layer hookup +// +static ModuleNexus plugin; + +#define SPINAME(s) s ## __apple_cspdl +#include diff --git a/libsecurity_apple_cspdl/lib/AppleCSPDLPlugin.cpp b/libsecurity_apple_cspdl/lib/AppleCSPDLPlugin.cpp new file mode 100644 index 00000000..3727274e --- /dev/null +++ b/libsecurity_apple_cspdl/lib/AppleCSPDLPlugin.cpp @@ -0,0 +1,31 @@ +/* + * 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 obtai +n + * 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. + */ + + +// +// Produce the "genuine plugin version" of the Apple "file DL" +// +#include + + +// +// Create the plugin object and generate the C layer hookup +// +ModuleNexus plugin; + +#include diff --git a/libsecurity_apple_cspdl/lib/CSPDLDatabase.cpp b/libsecurity_apple_cspdl/lib/CSPDLDatabase.cpp new file mode 100644 index 00000000..219b4881 --- /dev/null +++ b/libsecurity_apple_cspdl/lib/CSPDLDatabase.cpp @@ -0,0 +1,36 @@ +/* + * 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. + */ + + +// +// CSPDLDatabase.cpp - Description t.b.d. +// +#include "CSPDLDatabase.h" +#include +#include +#include +#include +#include + +// +// CSPDLDatabaseManager implementation +// +Database * +CSPDLDatabaseManager::make(const DbName &inDbName) +{ + CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR); +} diff --git a/libsecurity_apple_cspdl/lib/CSPDLDatabase.h b/libsecurity_apple_cspdl/lib/CSPDLDatabase.h new file mode 100644 index 00000000..499cebc8 --- /dev/null +++ b/libsecurity_apple_cspdl/lib/CSPDLDatabase.h @@ -0,0 +1,40 @@ +/* + * 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. + */ + + +// +// CSPDLDatabase.h - Description t.b.d. +// +#ifndef _H_CSPDLDATABASE +#define _H_CSPDLDATABASE + +#include +#include +#include +#include +#include + +// +// CSPDLDatabaseManager +// +class CSPDLDatabaseManager : public DatabaseManager +{ +public: + Database *make(const DbName &inDbName); +}; + +#endif //_H_CSPDLDATABASE diff --git a/libsecurity_apple_cspdl/lib/CSPDLPlugin.cpp b/libsecurity_apple_cspdl/lib/CSPDLPlugin.cpp new file mode 100644 index 00000000..f101211d --- /dev/null +++ b/libsecurity_apple_cspdl/lib/CSPDLPlugin.cpp @@ -0,0 +1,78 @@ +/* + * 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. + */ + + +// +// CSPDLPlugin.cpp - File Based CSP/DL plug-in module. +// +#include "CSPDLPlugin.h" + +#include "SSCSPSession.h" +#include "SSDLSession.h" + + +// +// Make and break the plugin object +// +CSPDLPlugin::CSPDLPlugin() + : mRawCsp(gGuidAppleCSP) +{ +} + +CSPDLPlugin::~CSPDLPlugin() +{ +} + + +// +// Create a new plugin session, our way +// +PluginSession * +CSPDLPlugin::makeSession(CSSM_MODULE_HANDLE handle, + const CSSM_VERSION &version, + uint32 subserviceId, + CSSM_SERVICE_TYPE subserviceType, + CSSM_ATTACH_FLAGS attachFlags, + const CSSM_UPCALLS &upcalls) +{ + switch (subserviceType) + { + case CSSM_SERVICE_CSP: + return new SSCSPSession(handle, + *this, + version, + subserviceId, + subserviceType, + attachFlags, + upcalls, + mSSCSPDLSession, + mRawCsp); + case CSSM_SERVICE_DL: + return new SSDLSession(handle, + *this, + version, + subserviceId, + subserviceType, + attachFlags, + upcalls, + mDatabaseManager, + mSSCSPDLSession); + default: + CssmError::throwMe(CSSMERR_CSSM_INVALID_SERVICE_MASK); + return 0; // placebo + } +} diff --git a/libsecurity_apple_cspdl/lib/CSPDLPlugin.h b/libsecurity_apple_cspdl/lib/CSPDLPlugin.h new file mode 100644 index 00000000..9fd62d43 --- /dev/null +++ b/libsecurity_apple_cspdl/lib/CSPDLPlugin.h @@ -0,0 +1,56 @@ +/* + * 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. + */ + + +// +// CSPDLCSPDL.h - File Based CSP/DL plug-in module. +// +#ifndef _H_CSPDLPLUGIN +#define _H_CSPDLPLUGIN + +#include "SSCSPDLSession.h" +#include "CSPDLDatabase.h" +#include "SSFactory.h" +#include +#include + +class SSCSPSession; + +class CSPDLPlugin : public CssmPlugin +{ + NOCOPY(CSPDLPlugin) +public: + CSPDLPlugin(); + ~CSPDLPlugin(); + + PluginSession *makeSession(CSSM_MODULE_HANDLE handle, + const CSSM_VERSION &version, + uint32 subserviceId, + CSSM_SERVICE_TYPE subserviceType, + CSSM_ATTACH_FLAGS attachFlags, + const CSSM_UPCALLS &upcalls); +private: + friend class SSCSPSession; + friend class SSCSPDLSession; + SSCSPDLSession mSSCSPDLSession; + CSPDLDatabaseManager mDatabaseManager; + SSFactory mSSFactory; + CssmClient::CSP mRawCsp; // raw (nonsecure) CSP connection +}; + + +#endif //_H_CSPDLPLUGIN diff --git a/libsecurity_apple_cspdl/lib/SSCSPDLSession.cpp b/libsecurity_apple_cspdl/lib/SSCSPDLSession.cpp new file mode 100644 index 00000000..00a867ec --- /dev/null +++ b/libsecurity_apple_cspdl/lib/SSCSPDLSession.cpp @@ -0,0 +1,208 @@ +/* + * Copyright (c) 2000-2001,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. + */ + + +// +// SSCSPDLSession.cpp - Security Server CSP/DL session. +// +#include "SSCSPDLSession.h" + +#include "CSPDLPlugin.h" +#include "SSKey.h" + + +#ifndef SECURITYSERVER_ACL_EDITS + +#include +#include +#include +#include + +// +// ClientSessionKey - Lightweight wrapper for a KeyHandle that is also an CssmClient::AclBearer +// +class ClientSessionKey: public CssmClient::AclBearer +{ +public: + ClientSessionKey(SecurityServer::ClientSession &clientSession, SecurityServer::KeyHandle keyHandle); + ~ClientSessionKey(); + + // Acl manipulation + virtual void getAcl(AutoAclEntryInfoList &aclInfos, + const char *selectionTag = NULL) const; + virtual void changeAcl(const CSSM_ACL_EDIT &aclEdit, + const CSSM_ACCESS_CREDENTIALS *cred = NULL); + + // Acl owner manipulation + virtual void getOwner(AutoAclOwnerPrototype &owner) const; + virtual void changeOwner(const CSSM_ACL_OWNER_PROTOTYPE &newOwner, + const CSSM_ACCESS_CREDENTIALS *cred = NULL); + + +private: + SecurityServer::ClientSession &mClientSession; + SecurityServer::KeyHandle mKeyHandle; +}; + +#endif //!SECURITYSERVER_ACL_EDITS + + +using namespace SecurityServer; + +// +// SSCSPDLSession -- Security Server CSP session +// +SSCSPDLSession::SSCSPDLSession() +{ +} + + +// +// Reference Key management +// +void +SSCSPDLSession::makeReferenceKey(SSCSPSession &session, KeyHandle inKeyHandle, + CssmKey &outKey, SSDatabase &inSSDatabase, + uint32 inKeyAttr, const CssmData *inKeyLabel) +{ + new SSKey(session, inKeyHandle, outKey, inSSDatabase, inKeyAttr, + inKeyLabel); +} + +SSKey & +SSCSPDLSession::lookupKey(const CssmKey &inKey) +{ + /* for now we only allow ref keys */ + if(inKey.blobType() != CSSM_KEYBLOB_REFERENCE) { + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY); + } + + /* fetch key (this is just mapping the value in inKey.KeyData to an SSKey) */ + SSKey &theKey = find(inKey); + + #ifdef someday + /* + * Make sure caller hasn't changed any crucial header fields. + * Some fields were changed by makeReferenceKey, so make a local copy.... + */ + CSSM_KEYHEADER localHdr = cssmKey.KeyHeader; + get binKey-like thing from SSKey, maybe SSKey should keep a copy of + hdr...but that's' not supersecure....; + + localHdr.BlobType = binKey->mKeyHeader.BlobType; + localHdr.Format = binKey->mKeyHeader.Format; + if(memcmp(&localHdr, &binKey->mKeyHeader, sizeof(CSSM_KEYHEADER))) { + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_REFERENCE); + } + #endif + return theKey; +} + +// Notification we receive when the acl on a key has changed. We should write it back to disk if it's persistent. +void +SSCSPDLSession::didChangeKeyAcl(SecurityServer::ClientSession &clientSession, + KeyHandle keyHandle, CSSM_ACL_AUTHORIZATION_TAG tag) +{ + SSKey *theKey = NULL; + + { + // Lookup the SSKey for the KeyHandle + StLock _(mKeyMapLock); + KeyMap::const_iterator it; + KeyMap::const_iterator end = mKeyMap.end(); + for (it = mKeyMap.begin(); it != end; ++it) + { + SSKey *aKey = dynamic_cast(it->second); + if (aKey->optionalKeyHandle() == keyHandle) + { + // Write the key to disk if it's persistent. + theKey = aKey; + break; + } + } + } + + if (theKey) + { + theKey->didChangeAcl(); + } + else + { + // @@@ Should we really throw here or just continue without updating the ACL? In reality this should never happen, so let's at least log it and throw. + secdebug("keyacl", "SSCSPDLSession::didChangeKeyAcl() keyHandle: %lu not found in map", keyHandle); + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_REFERENCE); + } +} + +void +SSCSPDLSession::didChangeKeyAclCallback(void *context, SecurityServer::ClientSession &clientSession, + SecurityServer::KeyHandle key, CSSM_ACL_AUTHORIZATION_TAG tag) +{ + reinterpret_cast(context)->didChangeKeyAcl(clientSession, key, tag); +} + +#ifndef SECURITYSERVER_ACL_EDITS +// +// ClientSessionKey - Lightweight wrapper for a KeyHandle that is also an CssmClient::AclBearer +// +ClientSessionKey::ClientSessionKey(ClientSession &clientSession, SecurityServer::KeyHandle keyHandle) : + mClientSession(clientSession), + mKeyHandle(keyHandle) +{ +} + +ClientSessionKey::~ClientSessionKey() +{ +} + +void +ClientSessionKey::getAcl(AutoAclEntryInfoList &aclInfos, + const char *selectionTag) const +{ + secdebug("keyacl", "ClientSessionKey::getAcl() keyHandle: %u", mKeyHandle); + aclInfos.allocator(mClientSession.returnAllocator); + mClientSession.getKeyAcl(mKeyHandle, selectionTag, + *static_cast(aclInfos), + *reinterpret_cast(static_cast(aclInfos))); +} + +void +ClientSessionKey::changeAcl(const CSSM_ACL_EDIT &aclEdit, + const CSSM_ACCESS_CREDENTIALS *cred) +{ + secdebug("keyacl", "ClientSessionKey::changeAcl() keyHandle: %u", mKeyHandle); + mClientSession.changeKeyAcl(mKeyHandle, AccessCredentials::overlay(*cred), AclEdit::overlay(aclEdit)); +} + +void +ClientSessionKey::getOwner(AutoAclOwnerPrototype &owner) const +{ + secdebug("keyacl", "ClientSessionKey::getOwner() keyHandle: %u", mKeyHandle); + owner.allocator(mClientSession.returnAllocator); + mClientSession.getKeyOwner(mKeyHandle, + *reinterpret_cast(static_cast(owner))); +} + +void +ClientSessionKey::changeOwner(const CSSM_ACL_OWNER_PROTOTYPE &newOwner, + const CSSM_ACCESS_CREDENTIALS *cred) +{ + secdebug("keyacl", "ClientSessionKey::changeOwner() keyHandle: %u", mKeyHandle); + mClientSession.changeKeyOwner(mKeyHandle, AccessCredentials::overlay(*cred), AclOwnerPrototype::overlay(newOwner)); +} + +#endif // !SECURITYSERVER_ACL_EDITS diff --git a/libsecurity_apple_cspdl/lib/SSCSPDLSession.h b/libsecurity_apple_cspdl/lib/SSCSPDLSession.h new file mode 100644 index 00000000..f8c942ab --- /dev/null +++ b/libsecurity_apple_cspdl/lib/SSCSPDLSession.h @@ -0,0 +1,55 @@ +/* + * 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. + */ + + +// +// SSCSPDLSession.h - File Based CSP/DL plug-in module. +// +#ifndef _H_SSCSPDLSESSION +#define _H_SSCSPDLSESSION + +#include +#include + + +class CSPDLPlugin; +class SSFactory; +class SSCSPSession; +class SSDatabase; +class SSKey; + +class SSCSPDLSession: public KeyPool +{ +public: + SSCSPDLSession(); + + void makeReferenceKey(SSCSPSession &session, + SecurityServer::KeyHandle inKeyHandle, + CssmKey &outKey, SSDatabase &inSSDatabase, + uint32 inKeyAttr, const CssmData *inKeyLabel); + SSKey &lookupKey(const CssmKey &inKey); + + /* Notification we receive when a key's acl has been modified. */ + void didChangeKeyAcl(SecurityServer::ClientSession &clientSession, + SecurityServer::KeyHandle keyHandle, CSSM_ACL_AUTHORIZATION_TAG tag); + + static void didChangeKeyAclCallback(void *context, SecurityServer::ClientSession &clientSession, + SecurityServer::KeyHandle keyHandle, CSSM_ACL_AUTHORIZATION_TAG tag); +}; + + +#endif // _H_SSCSPDLSESSION diff --git a/libsecurity_apple_cspdl/lib/SSCSPSession.cpp b/libsecurity_apple_cspdl/lib/SSCSPSession.cpp new file mode 100644 index 00000000..650e1d84 --- /dev/null +++ b/libsecurity_apple_cspdl/lib/SSCSPSession.cpp @@ -0,0 +1,608 @@ +/* + * 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. + */ + + +// +// SSCSPSession.cpp - Security Server CSP session. +// +#include "SSCSPSession.h" + +#include "CSPDLPlugin.h" +#include "SSDatabase.h" +#include "SSDLSession.h" +#include "SSKey.h" +#include +#include + +using namespace std; +using namespace SecurityServer; + +// +// SSCSPSession -- Security Server CSP session +// +SSCSPSession::SSCSPSession(CSSM_MODULE_HANDLE handle, + CSPDLPlugin &plug, + const CSSM_VERSION &version, + uint32 subserviceId, + CSSM_SERVICE_TYPE subserviceType, + CSSM_ATTACH_FLAGS attachFlags, + const CSSM_UPCALLS &upcalls, + SSCSPDLSession &ssCSPDLSession, + CssmClient::CSP &rawCsp) +: CSPFullPluginSession(handle, plug, version, subserviceId, subserviceType, + attachFlags, upcalls), + mSSCSPDLSession(ssCSPDLSession), + mSSFactory(plug.mSSFactory), + mRawCsp(rawCsp), + mClientSession(Allocator::standard(), *this) +{ + mClientSession.registerForAclEdits(SSCSPDLSession::didChangeKeyAclCallback, &mSSCSPDLSession); +} + +// +// Called at (CSSM) context create time. This is ignored; we do a full +// context setup later, at setupContext time. +// +CSPFullPluginSession::CSPContext * +SSCSPSession::contextCreate(CSSM_CC_HANDLE handle, const Context &context) +{ + return NULL; +} + + +// +// Called by CSPFullPluginSession when an op is actually commencing. +// Context can safely assumed to be fully formed and stable for the +// duration of the op; thus we wait until now to set up our +// CSPContext as appropriate to the op. +// +void +SSCSPSession::setupContext(CSPContext * &cspCtx, + const Context &context, + bool encoding) +{ + // note we skip this if this CSPContext is being reused + if (cspCtx == NULL) + { + + if (mSSFactory.setup(*this, cspCtx, context, encoding)) + return; + +#if 0 + if (mBSafe4Factory.setup(*this, cspCtx, context)) + return; + + if (mCryptKitFactory.setup(*this, cspCtx, context)) + return; +#endif + + CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM); + } +} + + +// +// DL interaction +// +SSDatabase +SSCSPSession::getDatabase(const Context &context) +{ + return getDatabase(context.get(CSSM_ATTRIBUTE_DL_DB_HANDLE)); +} + +SSDatabase +SSCSPSession::getDatabase(CSSM_DL_DB_HANDLE *aDLDbHandle) +{ + if (aDLDbHandle) + return findSession(aDLDbHandle->DLHandle).findDbHandle(aDLDbHandle->DBHandle); + else + return SSDatabase(); +} + + +// +// Reference Key management +// +void +SSCSPSession::makeReferenceKey(KeyHandle inKeyHandle, CssmKey &ioKey, SSDatabase &inSSDatabase, + uint32 inKeyAttr, const CssmData *inKeyLabel) +{ + return mSSCSPDLSession.makeReferenceKey(*this, inKeyHandle, ioKey, inSSDatabase, inKeyAttr, inKeyLabel); +} + +SSKey & +SSCSPSession::lookupKey(const CssmKey &inKey) +{ + return mSSCSPDLSession.lookupKey(inKey); +} + + +// +// Key creating and handeling members +// +void +SSCSPSession::WrapKey(CSSM_CC_HANDLE CCHandle, + const Context &context, + const AccessCredentials &AccessCred, + const CssmKey &Key, + const CssmData *DescriptiveData, + CssmKey &WrappedKey, + CSSM_PRIVILEGE Privilege) +{ + // @@@ Deal with permanent keys + const CssmKey *keyInContext = + context.get(CSSM_ATTRIBUTE_KEY); + + KeyHandle contextKeyHandle = (keyInContext + ? lookupKey(*keyInContext).keyHandle() + : noKey); + clientSession().wrapKey(context, contextKeyHandle, + lookupKey(Key).keyHandle(), &AccessCred, + DescriptiveData, WrappedKey, *this); +} + +void +SSCSPSession::UnwrapKey(CSSM_CC_HANDLE CCHandle, + const Context &context, + const CssmKey *PublicKey, + const CssmWrappedKey &WrappedKey, + uint32 KeyUsage, + uint32 KeyAttr, + const CssmData *KeyLabel, + const CSSM_RESOURCE_CONTROL_CONTEXT *CredAndAclEntry, + CssmKey &UnwrappedKey, + CssmData &DescriptiveData, + CSSM_PRIVILEGE Privilege) +{ + SSDatabase database = getDatabase(context); + validateKeyAttr(KeyAttr); + const AccessCredentials *cred = NULL; + const AclEntryInput *owner = NULL; + if (CredAndAclEntry) + { + cred = AccessCredentials::overlay(CredAndAclEntry->AccessCred); + owner = &AclEntryInput::overlay(CredAndAclEntry->InitialAclEntry); + } + + KeyHandle publicKey = noKey; + if (PublicKey) + { + if (PublicKey->blobType() == CSSM_KEYBLOB_RAW) + { + // @@@ We need to unwrap the publicKey into the SecurityServer + // before continuing + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY); + } + else + publicKey = lookupKey(*PublicKey).keyHandle(); + } + + // @@@ Deal with permanent keys + const CssmKey *keyInContext = + context.get(CSSM_ATTRIBUTE_KEY); + + KeyHandle contextKeyHandle = + keyInContext ? lookupKey(*keyInContext).keyHandle() : noKey; + + KeyHandle unwrappedKeyHandle; + clientSession().unwrapKey(database.dbHandle(), context, contextKeyHandle, + publicKey, WrappedKey, KeyUsage, KeyAttr, + cred, owner, DescriptiveData, unwrappedKeyHandle, + UnwrappedKey.header(), *this); + makeReferenceKey(unwrappedKeyHandle, UnwrappedKey, database, KeyAttr, + KeyLabel); +} + +void +SSCSPSession::DeriveKey(CSSM_CC_HANDLE ccHandle, + const Context &context, + CssmData ¶m, + uint32 keyUsage, + uint32 keyAttr, + const CssmData *keyLabel, + const CSSM_RESOURCE_CONTROL_CONTEXT *credAndAclEntry, + CssmKey &derivedKey) +{ + SSDatabase database = getDatabase(context); + validateKeyAttr(keyAttr); + const AccessCredentials *cred = NULL; + const AclEntryInput *owner = NULL; + if (credAndAclEntry) + { + cred = AccessCredentials::overlay(credAndAclEntry->AccessCred); + owner = &AclEntryInput::overlay(credAndAclEntry->InitialAclEntry); + } + + /* optional BaseKey */ + const CssmKey *keyInContext = + context.get(CSSM_ATTRIBUTE_KEY); + KeyHandle contextKeyHandle = + keyInContext ? lookupKey(*keyInContext).keyHandle() : noKey; + KeyHandle keyHandle; + switch(context.algorithm()) { + case CSSM_ALGID_KEYCHAIN_KEY: + { + // special interpretation: take DLDBHandle -> DbHandle from params + clientSession().extractMasterKey(database.dbHandle(), context, + getDatabase(param.interpretedAs(CSSMERR_CSP_INVALID_ATTR_DL_DB_HANDLE)).dbHandle(), + keyUsage, keyAttr, cred, owner, keyHandle, derivedKey.header()); + } + break; + default: + clientSession().deriveKey(database.dbHandle(), context, contextKeyHandle, keyUsage, + keyAttr, param, cred, owner, keyHandle, derivedKey.header()); + break; + } + makeReferenceKey(keyHandle, derivedKey, database, keyAttr, keyLabel); +} + +void +SSCSPSession::GenerateKey(CSSM_CC_HANDLE ccHandle, + const Context &context, + uint32 keyUsage, + uint32 keyAttr, + const CssmData *keyLabel, + const CSSM_RESOURCE_CONTROL_CONTEXT *credAndAclEntry, + CssmKey &key, + CSSM_PRIVILEGE privilege) +{ + SSDatabase database = getDatabase(context); + validateKeyAttr(keyAttr); + const AccessCredentials *cred = NULL; + const AclEntryInput *owner = NULL; + if (credAndAclEntry) + { + cred = AccessCredentials::overlay(credAndAclEntry->AccessCred); + owner = &AclEntryInput::overlay(credAndAclEntry->InitialAclEntry); + } + + KeyHandle keyHandle; + clientSession().generateKey(database.dbHandle(), context, keyUsage, + keyAttr, cred, owner, keyHandle, key.header()); + makeReferenceKey(keyHandle, key, database, keyAttr, keyLabel); +} + +void +SSCSPSession::GenerateKeyPair(CSSM_CC_HANDLE ccHandle, + const Context &context, + uint32 publicKeyUsage, + uint32 publicKeyAttr, + const CssmData *publicKeyLabel, + CssmKey &publicKey, + uint32 privateKeyUsage, + uint32 privateKeyAttr, + const CssmData *privateKeyLabel, + const CSSM_RESOURCE_CONTROL_CONTEXT *credAndAclEntry, + CssmKey &privateKey, + CSSM_PRIVILEGE privilege) +{ + SSDatabase database = getDatabase(context); + validateKeyAttr(publicKeyAttr); + validateKeyAttr(privateKeyAttr); + const AccessCredentials *cred = NULL; + const AclEntryInput *owner = NULL; + if (credAndAclEntry) + { + cred = AccessCredentials::overlay(credAndAclEntry->AccessCred); + owner = &AclEntryInput::overlay(credAndAclEntry->InitialAclEntry); + } + + /* + * Public keys must be extractable in the clear - that's the Apple + * policy. The raw CSP is unable to enforce the extractable + * bit since it always sees that as true (it's managed and forced + * true by the SecurityServer). So... + */ + if(!(publicKeyAttr & CSSM_KEYATTR_EXTRACTABLE)) { + CssmError::throwMe(CSSMERR_CSP_INVALID_KEYATTR_MASK); + } + KeyHandle pubKeyHandle, privKeyHandle; + clientSession().generateKey(database.dbHandle(), context, + publicKeyUsage, publicKeyAttr, + privateKeyUsage, privateKeyAttr, + cred, owner, + pubKeyHandle, publicKey.header(), + privKeyHandle, privateKey.header()); + makeReferenceKey(privKeyHandle, privateKey, database, privateKeyAttr, + privateKeyLabel); + // @@@ What if this throws, we need to free privateKey. + makeReferenceKey(pubKeyHandle, publicKey, database, publicKeyAttr, + publicKeyLabel); +} + +void +SSCSPSession::ObtainPrivateKeyFromPublicKey(const CssmKey &PublicKey, + CssmKey &PrivateKey) +{ + unimplemented(); +} + +void +SSCSPSession::QueryKeySizeInBits(CSSM_CC_HANDLE CCHandle, + const Context &Context, + const CssmKey &Key, + CSSM_KEY_SIZE &KeySize) +{ + unimplemented(); +} + +void +SSCSPSession::FreeKey(const AccessCredentials *accessCred, + CssmKey &ioKey, CSSM_BOOL deleteKey) +{ + if (ioKey.blobType() == CSSM_KEYBLOB_REFERENCE) + { + // @@@ Note that this means that detaching a session should free + // all keys ascociated with it or else... + // -- or else what? + // exactly! + + // @@@ There are thread safety issues when deleting a key that is + // in use by another thread, but the answer to that is: Don't do + // that! + + // Find the key in the map. Tell tell the key to free itself + // (when the auto_ptr deletes the key it removes itself from the map). + secdebug("freeKey", "CSPDL FreeKey"); + auto_ptr ssKey(&mSSCSPDLSession.find(ioKey)); + ssKey->free(accessCred, ioKey, deleteKey); + } + else + { + CSPFullPluginSession::FreeKey(accessCred, ioKey, deleteKey); + } +} + + +// +// Generation stuff. +// +void +SSCSPSession::GenerateRandom(CSSM_CC_HANDLE ccHandle, + const Context &context, + CssmData &randomNumber) +{ + checkOperation(context.type(), CSSM_ALGCLASS_RANDOMGEN); + // if (context.algorithm() != @@@) CssmError::throwMe(ALGORITHM_NOT_SUPPORTED); + uint32 needed = context.getInt(CSSM_ATTRIBUTE_OUTPUT_SIZE, CSSMERR_CSP_MISSING_ATTR_OUTPUT_SIZE); + + // @@@ What about the seed? + if (randomNumber.length()) + { + if (randomNumber.length() < needed) + CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR); + clientSession().generateRandom(context, randomNumber); + } + else + { + randomNumber.Data = alloc(needed); + try + { + clientSession().generateRandom(context, randomNumber); + } + catch(...) + { + free(randomNumber.Data); + randomNumber.Data = NULL; + throw; + } + } +} + +// +// Login/Logout and token operational maintainance. These mean little +// without support by the actual implementation, but we can help... +// @@@ Should this be in CSP[non-Full]PluginSession? +// +void +SSCSPSession::Login(const AccessCredentials &AccessCred, + const CssmData *LoginName, + const void *Reserved) +{ + // @@@ Do a login to the securityServer making keys persistant until it + // goes away + unimplemented(); +} + +void +SSCSPSession::Logout() +{ + unimplemented(); +} + +void +SSCSPSession::VerifyDevice(const CssmData &DeviceCert) +{ + CssmError::throwMe(CSSMERR_CSP_DEVICE_VERIFY_FAILED); +} + +void +SSCSPSession::GetOperationalStatistics(CSPOperationalStatistics &statistics) +{ + unimplemented(); +} + + +// +// Utterly miscellaneous, rarely used, strange functions +// +void +SSCSPSession::RetrieveCounter(CssmData &Counter) +{ + unimplemented(); +} + +void +SSCSPSession::RetrieveUniqueId(CssmData &UniqueID) +{ + unimplemented(); +} + +void +SSCSPSession::GetTimeValue(CSSM_ALGORITHMS TimeAlgorithm, CssmData &TimeData) +{ + unimplemented(); +} + + +// +// ACL retrieval and change operations +// +void +SSCSPSession::GetKeyOwner(const CssmKey &Key, + CSSM_ACL_OWNER_PROTOTYPE &Owner) +{ + lookupKey(Key).getOwner(Owner, *this); +} + +void +SSCSPSession::ChangeKeyOwner(const AccessCredentials &AccessCred, + const CssmKey &Key, + const CSSM_ACL_OWNER_PROTOTYPE &NewOwner) +{ + lookupKey(Key).changeOwner(AccessCred, + AclOwnerPrototype::overlay(NewOwner)); +} + +void +SSCSPSession::GetKeyAcl(const CssmKey &Key, + const CSSM_STRING *SelectionTag, + uint32 &NumberOfAclInfos, + CSSM_ACL_ENTRY_INFO_PTR &AclInfos) +{ + lookupKey(Key).getAcl(reinterpret_cast(SelectionTag), + NumberOfAclInfos, + reinterpret_cast(AclInfos), *this); +} + +void +SSCSPSession::ChangeKeyAcl(const AccessCredentials &AccessCred, + const CSSM_ACL_EDIT &AclEdit, + const CssmKey &Key) +{ + lookupKey(Key).changeAcl(AccessCred, AclEdit::overlay(AclEdit)); +} + +void +SSCSPSession::GetLoginOwner(CSSM_ACL_OWNER_PROTOTYPE &Owner) +{ + unimplemented(); +} + +void +SSCSPSession::ChangeLoginOwner(const AccessCredentials &AccessCred, + const CSSM_ACL_OWNER_PROTOTYPE &NewOwner) +{ + unimplemented(); +} + +void +SSCSPSession::GetLoginAcl(const CSSM_STRING *SelectionTag, + uint32 &NumberOfAclInfos, + CSSM_ACL_ENTRY_INFO_PTR &AclInfos) +{ + unimplemented(); +} + +void +SSCSPSession::ChangeLoginAcl(const AccessCredentials &AccessCred, + const CSSM_ACL_EDIT &AclEdit) +{ + unimplemented(); +} + + + +// +// Passthroughs +// +void +SSCSPSession::PassThrough(CSSM_CC_HANDLE CCHandle, + const Context &context, + uint32 passThroughId, + const void *inData, + void **outData) +{ + checkOperation(context.type(), CSSM_ALGCLASS_NONE); + switch (passThroughId) { + case CSSM_APPLESCPDL_CSP_GET_KEYHANDLE: + { + // inData unused, must be NULL + if (inData) + CssmError::throwMe(CSSM_ERRCODE_INVALID_INPUT_POINTER); + + // outData required, must be pointer-to-pointer-to-KeyHandle + KeyHandle &result = Required(reinterpret_cast(outData)); + + // we'll take the key from the context + const CssmKey &key = + context.get(CSSM_ATTRIBUTE_KEY, CSSMERR_CSP_MISSING_ATTR_KEY); + + // all ready + result = lookupKey(key).keyHandle(); + break; + } + case CSSM_APPLECSP_KEYDIGEST: + { + // inData unused, must be NULL + if (inData) + CssmError::throwMe(CSSM_ERRCODE_INVALID_INPUT_POINTER); + + // outData required + Required(outData); + + // take the key from the context, convert to KeyHandle + const CssmKey &key = + context.get(CSSM_ATTRIBUTE_KEY, CSSMERR_CSP_MISSING_ATTR_KEY); + KeyHandle keyHandle = lookupKey(key).keyHandle(); + + // allocate digest holder on app's behalf + CSSM_DATA *digest = alloc(sizeof(CSSM_DATA)); + digest->Data = NULL; + digest->Length = 0; + + // go + try { + clientSession().getKeyDigest(keyHandle, CssmData::overlay(*digest)); + } + catch(...) { + free(digest); + throw; + } + *outData = digest; + break; + } + + default: + CssmError::throwMe(CSSM_ERRCODE_INVALID_PASSTHROUGH_ID); + } +} + +/* Validate requested key attr flags for newly generated keys */ +void SSCSPSession::validateKeyAttr(uint32 reqKeyAttr) +{ + if(reqKeyAttr & (CSSM_KEYATTR_RETURN_DATA)) { + /* CSPDL only supports reference keys */ + CssmError::throwMe(CSSMERR_CSP_UNSUPPORTED_KEYATTR_MASK); + } + if(reqKeyAttr & (CSSM_KEYATTR_ALWAYS_SENSITIVE | + CSSM_KEYATTR_NEVER_EXTRACTABLE)) { + /* invalid for any CSP */ + CssmError::throwMe(CSSMERR_CSP_INVALID_KEYATTR_MASK); + } + /* There may be more, but we'll leave it to SS and CSP to decide */ +} diff --git a/libsecurity_apple_cspdl/lib/SSCSPSession.h b/libsecurity_apple_cspdl/lib/SSCSPSession.h new file mode 100644 index 00000000..ff27dbbd --- /dev/null +++ b/libsecurity_apple_cspdl/lib/SSCSPSession.h @@ -0,0 +1,174 @@ +/* + * 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. + */ + + +// +// SSDLSession.h - CSP session for security server CSP/DL. +// +#ifndef _H_SSCSPSESSION +#define _H_SSCSPSESSION + +#include "SSCSPDLSession.h" + +#include +#include + + +class CSPDLPlugin; +class SSFactory; +class SSDatabase; +class SSKey; + +class SSCSPSession : public CSPFullPluginSession +{ +public: + SSCSPDLSession &mSSCSPDLSession; + SSFactory &mSSFactory; + CssmClient::CSP &mRawCsp; + + SSCSPSession(CSSM_MODULE_HANDLE handle, + CSPDLPlugin &plug, + const CSSM_VERSION &version, + uint32 subserviceId, + CSSM_SERVICE_TYPE subserviceType, + CSSM_ATTACH_FLAGS attachFlags, + const CSSM_UPCALLS &upcalls, + SSCSPDLSession &ssCSPDLSession, + CssmClient::CSP &rawCsp); + + SecurityServer::ClientSession &clientSession() + { return mClientSession; } + + CSPContext *contextCreate(CSSM_CC_HANDLE handle, const Context &context); +#if 0 + void contextUpdate(CSSM_CC_HANDLE handle, const Context &context, + PluginContext *ctx); + void contextDelete(CSSM_CC_HANDLE handle, const Context &context, + PluginContext *ctx); +#endif + + void setupContext(CSPContext * &ctx, const Context &context, + bool encoding); + + SSDatabase getDatabase(CSSM_DL_DB_HANDLE *aDLDbHandle); + SSDatabase getDatabase(const Context &context); + + void makeReferenceKey(SecurityServer::KeyHandle inKeyHandle, + CssmKey &outKey, SSDatabase &inSSDatabase, + uint32 inKeyAttr, const CssmData *inKeyLabel); + SSKey &lookupKey(const CssmKey &inKey); + + void WrapKey(CSSM_CC_HANDLE CCHandle, + const Context &Context, + const AccessCredentials &AccessCred, + const CssmKey &Key, + const CssmData *DescriptiveData, + CssmKey &WrappedKey, + CSSM_PRIVILEGE Privilege); + void UnwrapKey(CSSM_CC_HANDLE CCHandle, + const Context &Context, + const CssmKey *PublicKey, + const CssmKey &WrappedKey, + uint32 KeyUsage, + uint32 KeyAttr, + const CssmData *KeyLabel, + const CSSM_RESOURCE_CONTROL_CONTEXT *CredAndAclEntry, + CssmKey &UnwrappedKey, + CssmData &DescriptiveData, + CSSM_PRIVILEGE Privilege); + void DeriveKey(CSSM_CC_HANDLE CCHandle, + const Context &Context, + CssmData &Param, + uint32 KeyUsage, + uint32 KeyAttr, + const CssmData *KeyLabel, + const CSSM_RESOURCE_CONTROL_CONTEXT *CredAndAclEntry, + CssmKey &DerivedKey); + void GenerateKey(CSSM_CC_HANDLE ccHandle, + const Context &context, + uint32 keyUsage, + uint32 keyAttr, + const CssmData *keyLabel, + const CSSM_RESOURCE_CONTROL_CONTEXT *credAndAclEntry, + CssmKey &key, + CSSM_PRIVILEGE privilege); + void GenerateKeyPair(CSSM_CC_HANDLE ccHandle, + const Context &context, + uint32 publicKeyUsage, + uint32 publicKeyAttr, + const CssmData *publicKeyLabel, + CssmKey &publicKey, + uint32 privateKeyUsage, + uint32 privateKeyAttr, + const CssmData *privateKeyLabel, + const CSSM_RESOURCE_CONTROL_CONTEXT *credAndAclEntry, + CssmKey &privateKey, + CSSM_PRIVILEGE privilege); + void ObtainPrivateKeyFromPublicKey(const CssmKey &PublicKey, + CssmKey &PrivateKey); + void QueryKeySizeInBits(CSSM_CC_HANDLE CCHandle, + const Context &Context, + const CssmKey &Key, + CSSM_KEY_SIZE &KeySize); + void FreeKey(const AccessCredentials *AccessCred, + CssmKey &key, CSSM_BOOL Delete); + void GenerateRandom(CSSM_CC_HANDLE ccHandle, + const Context &context, + CssmData &randomNumber); + void Login(const AccessCredentials &AccessCred, + const CssmData *LoginName, + const void *Reserved); + void Logout(); + void VerifyDevice(const CssmData &DeviceCert); + void GetOperationalStatistics(CSPOperationalStatistics &statistics); + void RetrieveCounter(CssmData &Counter); + void RetrieveUniqueId(CssmData &UniqueID); + void GetTimeValue(CSSM_ALGORITHMS TimeAlgorithm, CssmData &TimeData); + void GetKeyOwner(const CssmKey &Key, + CSSM_ACL_OWNER_PROTOTYPE &Owner); + void ChangeKeyOwner(const AccessCredentials &AccessCred, + const CssmKey &Key, + const CSSM_ACL_OWNER_PROTOTYPE &NewOwner); + void GetKeyAcl(const CssmKey &Key, + const CSSM_STRING *SelectionTag, + uint32 &NumberOfAclInfos, + CSSM_ACL_ENTRY_INFO_PTR &AclInfos); + void ChangeKeyAcl(const AccessCredentials &AccessCred, + const CSSM_ACL_EDIT &AclEdit, + const CssmKey &Key); + void GetLoginOwner(CSSM_ACL_OWNER_PROTOTYPE &Owner); + void ChangeLoginOwner(const AccessCredentials &AccessCred, + const CSSM_ACL_OWNER_PROTOTYPE &NewOwner); + void GetLoginAcl(const CSSM_STRING *SelectionTag, + uint32 &NumberOfAclInfos, + CSSM_ACL_ENTRY_INFO_PTR &AclInfos); + void ChangeLoginAcl(const AccessCredentials &AccessCred, + const CSSM_ACL_EDIT &AclEdit); + void PassThrough(CSSM_CC_HANDLE CCHandle, + const Context &Context, + uint32 PassThroughId, + const void *InData, + void **OutData); +private: + /* Validate requested key attr flags for newly generated keys */ + void validateKeyAttr(uint32 reqKeyAttr); + + SecurityServer::ClientSession mClientSession; +}; + + +#endif // _H_SSCSPSESSION diff --git a/libsecurity_apple_cspdl/lib/SSContext.cpp b/libsecurity_apple_cspdl/lib/SSContext.cpp new file mode 100644 index 00000000..0acbe52a --- /dev/null +++ b/libsecurity_apple_cspdl/lib/SSContext.cpp @@ -0,0 +1,622 @@ +/* + * 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. + */ + + +// +// SSContext - cryptographic contexts for the security server +// +#include "SSContext.h" + +#include "SSCSPSession.h" +#include "SSKey.h" +#include + +#define ssCryptDebug(args...) secdebug("ssCrypt", ## args) + +using namespace SecurityServer; + +// +// SSContext +// +SSContext::SSContext(SSCSPSession &session) +: mSession(session), mContext(NULL) +{ +} + +void SSContext::clearOutBuf() +{ + if(mOutBuf.Data) { + mSession.free(mOutBuf.Data); + mOutBuf.clear(); + } +} + +void SSContext::copyOutBuf(CssmData &out) +{ + if(out.length() < mOutBuf.length()) { + CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR); + } + memmove(out.Data, mOutBuf.Data, mOutBuf.Length); + out.Length = mOutBuf.Length; + clearOutBuf(); +} + +void +SSContext::init(const Context &context, + bool /* encoding */) // @@@ should be removed from API since it's already in mDirection +{ + mContext = &context; + clearOutBuf(); +} + +SecurityServer::ClientSession & +SSContext::clientSession() +{ + return mSession.clientSession(); +} + + +// +// SSRandomContext -- Context for GenerateRandom operations +// +SSRandomContext::SSRandomContext(SSCSPSession &session) : SSContext(session) {} + +void +SSRandomContext::init(const Context &context, bool encoding) +{ + SSContext::init(context, encoding); + + // set/freeze output size + mOutSize = context.getInt(CSSM_ATTRIBUTE_OUTPUT_SIZE, CSSMERR_CSP_MISSING_ATTR_OUTPUT_SIZE); + +#if 0 + // seed the PRNG (if specified) + if (const CssmCryptoData *seed = context.get(CSSM_ATTRIBUTE_SEED)) { + const CssmData &seedValue = (*seed)(); + clientSession().seedRandom(seedValue); + } +#endif +} + +size_t +SSRandomContext::outputSize(bool final, size_t inSize) +{ + return mOutSize; +} + +void +SSRandomContext::final(CssmData &out) +{ + clientSession().generateRandom(*mContext, out); +} + + +// signature contexts +SSSignatureContext::SSSignatureContext(SSCSPSession &session) + : SSContext(session), + mKeyHandle(noKey), + mNullDigest(NULL), + mDigest(NULL) +{ + /* nothing else for now */ +} + +SSSignatureContext::~SSSignatureContext() +{ + delete mNullDigest; + delete mDigest; +} + +void SSSignatureContext::init(const Context &context, bool signing) +{ + SSContext::init(context, signing); + + /* reusable: skip everything except resetting digest state */ + if((mNullDigest != NULL) || (mDigest != NULL)) { + if(mNullDigest != NULL) { + mNullDigest->digestInit(); + } + return; + } + + /* snag key from context */ + const CssmKey &keyInContext = + context.get(CSSM_ATTRIBUTE_KEY, + CSSMERR_CSP_MISSING_ATTR_KEY); + mKeyHandle = mSession.lookupKey(keyInContext).keyHandle(); + + /* get digest alg and sig alg from Context.algorithm */ + switch(context.algorithm()) { + /*** DSA ***/ + case CSSM_ALGID_SHA1WithDSA: + mDigestAlg = CSSM_ALGID_SHA1; + mSigAlg = CSSM_ALGID_DSA; + break; + case CSSM_ALGID_DSA: // Raw + mDigestAlg = CSSM_ALGID_NONE; + mSigAlg = CSSM_ALGID_DSA; + break; + /*** RSA ***/ + case CSSM_ALGID_SHA1WithRSA: + mDigestAlg = CSSM_ALGID_SHA1; + mSigAlg = CSSM_ALGID_RSA; + break; + case CSSM_ALGID_MD5WithRSA: + mDigestAlg = CSSM_ALGID_MD5; + mSigAlg = CSSM_ALGID_RSA; + break; + case CSSM_ALGID_MD2WithRSA: + mDigestAlg = CSSM_ALGID_MD2; + mSigAlg = CSSM_ALGID_RSA; + break; + case CSSM_ALGID_SHA256WithRSA: + mDigestAlg = CSSM_ALGID_SHA256; + mSigAlg = CSSM_ALGID_RSA; + break; + case CSSM_ALGID_SHA224WithRSA: + mDigestAlg = CSSM_ALGID_SHA224; + mSigAlg = CSSM_ALGID_RSA; + break; + case CSSM_ALGID_SHA384WithRSA: + mDigestAlg = CSSM_ALGID_SHA384; + mSigAlg = CSSM_ALGID_RSA; + break; + case CSSM_ALGID_SHA512WithRSA: + mDigestAlg = CSSM_ALGID_SHA512; + mSigAlg = CSSM_ALGID_RSA; + break; + case CSSM_ALGID_RSA: // Raw + mDigestAlg = CSSM_ALGID_NONE; + mSigAlg = CSSM_ALGID_RSA; + break; + /*** FEE ***/ + case CSSM_ALGID_FEE_SHA1: + mDigestAlg = CSSM_ALGID_SHA1; + mSigAlg = CSSM_ALGID_FEE; + break; + case CSSM_ALGID_FEE_MD5: + mDigestAlg = CSSM_ALGID_MD5; + mSigAlg = CSSM_ALGID_FEE; + break; + case CSSM_ALGID_FEE: // Raw + mDigestAlg = CSSM_ALGID_NONE; + mSigAlg = CSSM_ALGID_FEE; + break; + /*** ECDSA ***/ + case CSSM_ALGID_SHA1WithECDSA: + mDigestAlg = CSSM_ALGID_SHA1; + mSigAlg = CSSM_ALGID_ECDSA; + break; + case CSSM_ALGID_SHA224WithECDSA: + mDigestAlg = CSSM_ALGID_SHA224; + mSigAlg = CSSM_ALGID_ECDSA; + break; + case CSSM_ALGID_SHA256WithECDSA: + mDigestAlg = CSSM_ALGID_SHA256; + mSigAlg = CSSM_ALGID_ECDSA; + break; + case CSSM_ALGID_SHA384WithECDSA: + mDigestAlg = CSSM_ALGID_SHA384; + mSigAlg = CSSM_ALGID_ECDSA; + break; + case CSSM_ALGID_SHA512WithECDSA: + mDigestAlg = CSSM_ALGID_SHA512; + mSigAlg = CSSM_ALGID_ECDSA; + break; + case CSSM_ALGID_ECDSA: // Raw + mDigestAlg = CSSM_ALGID_NONE; + mSigAlg = CSSM_ALGID_ECDSA; + break; + default: + CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM); + } + + /* set up mNullDigest or mDigest */ + if(mDigestAlg == CSSM_ALGID_NONE) { + mNullDigest = new NullDigest(); + } + else { + mDigest = new CssmClient::Digest(mSession.mRawCsp, mDigestAlg); + } +} + +/* + * for raw sign/verify - optionally called after init. + * Note that in init (in this case), we set mDigestAlg to ALGID_NONE and set up + * a NullDigest. We now overwrite mDigestAlg, and we'll useÊthis + * new value when we do the actual sign/vfy. + */ +void SSSignatureContext::setDigestAlgorithm(CSSM_ALGORITHMS digestAlg) +{ + mDigestAlg = digestAlg; +} + +void SSSignatureContext::update(const CssmData &data) +{ + /* Note that for this context, we really can not deal with an out-of-sequence + * update --> final(true, 0) --> update since we lose the pending digest state + * when we perform the implied final() during outputSize(true, 0). */ + assert(mOutBuf.Data == NULL); + + /* add incoming data to digest or accumulator */ + if(mNullDigest) { + mNullDigest->digestUpdate(data.data(), data.length()); + } + else { + mDigest->digest(data); + } +} + +size_t SSSignatureContext::outputSize(bool final, size_t inSize) +{ + if(!final) { + ssCryptDebug("===sig outputSize !final\n"); + return 0; + } + if(!encoding()) { + ssCryptDebug("===sig outputSize final, !encoding\n"); + /* don't see why this is even called... */ + return 0; + } + if(inSize == 0) { + /* + * This is the implied signal to go for it. Note that in this case, + * we can not go back and re-do the op in case of an unexpected + * sequence of update/outputSize(final, 0)/final - we lose the digest + * state. Perhaps we should save the digest...? But still it would + * be impossible to do another update. + */ + clearOutBuf(); + sign(mOutBuf); + ssCryptDebug("===sig outputSize(pre-op) %u", (unsigned)mOutBuf.Length); + return (size_t)mOutBuf.Length; + } + else { + /* out-of-band case, ask CSP via SS */ + uint32 outSize = clientSession().getOutputSize(*mContext, + mKeyHandle, + /* FIXME - what to use for inSize here - we don't want to + * interrogate mDigest, as that would result in another RPC... + * and signature size is not related to input size...right? */ + inSize, + true); + ssCryptDebug("===sig outputSize(RPC) %u", (unsigned)outSize); + return (size_t)outSize; + } +} + +/* sign */ + +/* first the common routine shared by final and outputSize */ +void SSSignatureContext::sign(CssmData &sig) +{ + /* we have to pass down a modified Context, thus.... */ + Context tempContext = *mContext; + tempContext.AlgorithmType = mSigAlg; + + if(mNullDigest) { + CssmData dData(const_cast(mNullDigest->digestPtr()), + mNullDigest->digestSizeInBytes()); + clientSession().generateSignature(tempContext, + mKeyHandle, + dData, + sig, + mDigestAlg); + } + else { + CssmAutoData d (mDigest->allocator ()); + d.set((*mDigest) ()); + + clientSession().generateSignature(tempContext, + mKeyHandle, + d, + sig, + mDigestAlg); + } +} + +/* this is the one called by CSPFullPluginSession */ +void SSSignatureContext::final(CssmData &sig) +{ + if(mOutBuf.Data) { + /* normal final case in which the actual RPC via SS was done in the + * previous outputSize() call. */ + ssCryptDebug("===final via pre-op and copy"); + copyOutBuf(sig); + return; + } + + ssCryptDebug("===final via RPC"); + sign(sig); +} + +/* verify */ +void +SSSignatureContext::final(const CssmData &sig) +{ + /* we have to pass down a modified Context, thus.... */ + Context tempContext = *mContext; + tempContext.AlgorithmType = mSigAlg; + + if(mNullDigest) { + CssmData dData(const_cast(mNullDigest->digestPtr()), + mNullDigest->digestSizeInBytes()); + clientSession().verifySignature(tempContext, + mKeyHandle, + dData, + sig, + mDigestAlg); + } + else { + CssmData digst = (*mDigest)(); + try { + clientSession().verifySignature(tempContext, + mKeyHandle, + digst, + sig, + mDigestAlg); + } + catch (...) { + mDigest->allocator().free(digst.Data); + throw; + } + mDigest->allocator().free(digst.Data); + } +} + + +// +// SSCryptContext -- Context for Encrypt and Decrypt operations +// +SSCryptContext::SSCryptContext(SSCSPSession &session) + : SSContext(session), mKeyHandle(noKey) +{ + /* nothing for now */ +} + + +SSCryptContext::~SSCryptContext() +{ + /* nothing for now */ +} + +void +SSCryptContext::init(const Context &context, bool encoding) +{ + ssCryptDebug("===init"); + SSContext::init(context, encoding); + + /* reusable; reset accumulator */ + mNullDigest.digestInit(); + + const CssmKey &keyInContext = + context.get(CSSM_ATTRIBUTE_KEY, + CSSMERR_CSP_MISSING_ATTR_KEY); + mKeyHandle = mSession.lookupKey(keyInContext).keyHandle(); +} + +size_t +SSCryptContext::inputSize(size_t outSize) +{ + ssCryptDebug("===inputSize outSize=%u", (unsigned)outSize); + return UINT_MAX; +} + +size_t +SSCryptContext::outputSize(bool final, size_t inSize) +{ + ssCryptDebug("===outputSize final %d inSize=%u", final, (unsigned)inSize); + if(!final) { + /* we buffer until final; no intermediate output */ + return 0; + } + size_t inBufSize = mNullDigest.digestSizeInBytes(); + if(inSize == 0) { + /* This is the implied signal to go for it */ + clearOutBuf(); + if(inBufSize == 0) { + return 0; + } + const CssmData in(const_cast(mNullDigest.digestPtr()), inBufSize); + if (encoding()) { + clientSession().encrypt(*mContext, mKeyHandle, in, mOutBuf); + } + else { + clientSession().decrypt(*mContext, mKeyHandle, in, mOutBuf); + } + /* leave the accumulator as is in case of unexpected sequence */ + ssCryptDebug(" ===outSize(pre-op) %u", (unsigned)mOutBuf.Length); + return mOutBuf.Length; + } + else { + /* out-of-band case, ask CSP via SS */ + uint32 outSize = clientSession().getOutputSize(*mContext, + mKeyHandle, + inBufSize + inSize, + encoding()); + ssCryptDebug(" ===outSize(RPC) %u", (unsigned)outSize); + return (size_t)outSize; + } +} + +void +SSCryptContext::minimumProgress(size_t &in, size_t &out) +{ + in = 1; + out = 0; +} + +void +SSCryptContext::update(void *inp, size_t &inSize, void *outp, size_t &outSize) +{ + ssCryptDebug("===update inSize=%u", (unsigned)inSize); + /* add incoming data to accumulator */ + mNullDigest.digestUpdate(inp, inSize); + outSize = 0; + clearOutBuf(); +} + +void +SSCryptContext::final(CssmData &out) +{ + if(mOutBuf.Data != NULL) { + /* normal final case in which the actual RPC via SS was done in the + * previous outputSize() call. A memcpy is needed here because + * CSPFullPluginSession has just allocated the buf size we need. */ + ssCryptDebug("===final via pre-op and copy"); + copyOutBuf(out); + return; + } + + /* when is this path taken...? */ + ssCryptDebug("===final via RPC"); + size_t inSize = mNullDigest.digestSizeInBytes(); + if(!inSize) return; + + const CssmData in(const_cast(mNullDigest.digestPtr()), inSize); + IFDEBUG(unsigned origOutSize = out.length()); + if (encoding()) { + clientSession().encrypt(*mContext, mKeyHandle, in, out); + } + else { + clientSession().decrypt(*mContext, mKeyHandle, in, out); + } + assert(out.length() <= origOutSize); + mNullDigest.digestInit(); +} + +// Digest, using raw CSP +SSDigestContext::SSDigestContext(SSCSPSession &session) + : SSContext(session), mDigest(NULL) +{ + +} + +SSDigestContext::~SSDigestContext() +{ + delete mDigest; +} + +void SSDigestContext::init(const Context &context, bool encoding) +{ + CSSM_ALGORITHMS alg; + + SSContext::init(context, encoding); + alg = context.algorithm(); + mDigest = new CssmClient::Digest(mSession.mRawCsp, alg); +} + +void SSDigestContext::update(const CssmData &data) +{ + mDigest->digest(data); +} + +void SSDigestContext::final(CssmData &out) +{ + (*mDigest)(out); +} + +size_t SSDigestContext::outputSize(bool final, size_t inSize) +{ + if(!final) { + return 0; + } + else { + return (size_t)mDigest->getOutputSize(inSize); + } +} + +// MACContext - common class for MAC generate, verify +SSMACContext::SSMACContext(SSCSPSession &session) + : SSContext(session), mKeyHandle(noKey) +{ + +} + +void SSMACContext::init(const Context &context, bool encoding) +{ + SSContext::init(context, encoding); + + /* reusable; reset accumulator */ + mNullDigest.digestInit(); + + /* snag key from context */ + const CssmKey &keyInContext = + context.get(CSSM_ATTRIBUTE_KEY, + CSSMERR_CSP_MISSING_ATTR_KEY); + mKeyHandle = mSession.lookupKey(keyInContext).keyHandle(); +} + +void SSMACContext::update(const CssmData &data) +{ + /* add incoming data to accumulator */ + mNullDigest.digestUpdate(data.data(), data.length()); +} + +size_t SSMACContext::outputSize(bool final, size_t inSize) +{ + if(!final) { + ssCryptDebug("===mac outputSize !final\n"); + return 0; + } + if(!encoding()) { + ssCryptDebug("===mac outputSize final, !encoding\n"); + /* don't see why this is even called... */ + return 0; + } + if(inSize == 0) { + /* + * This is the implied signal to go for it. + */ + clearOutBuf(); + genMac(mOutBuf); + ssCryptDebug("===mac outputSize(pre-op) %u", (unsigned)mOutBuf.Length); + return (size_t)mOutBuf.Length; + } + else { + /* out-of-band case, ask CSP via SS */ + uint32 outSize = clientSession().getOutputSize(*mContext, + mKeyHandle, + inSize + mNullDigest.digestSizeInBytes(), + true); + ssCryptDebug("===mac outputSize(RPC) %u", (unsigned)outSize); + return (size_t)outSize; + } +} + +/* generate */ + +/* first the common routine used by final() and outputSize() */ +void SSMACContext::genMac(CssmData &mac) +{ + CssmData allData(const_cast(mNullDigest.digestPtr()), + mNullDigest.digestSizeInBytes()); + clientSession().generateMac(*mContext, mKeyHandle, allData, mac); +} + +void SSMACContext::final(CssmData &mac) +{ + genMac(mac); +} + +/* verify */ +void SSMACContext::final(const CssmData &mac) +{ + CssmData allData(const_cast(mNullDigest.digestPtr()), + mNullDigest.digestSizeInBytes()); + clientSession().verifyMac(*mContext, mKeyHandle, allData, mac); +} diff --git a/libsecurity_apple_cspdl/lib/SSContext.h b/libsecurity_apple_cspdl/lib/SSContext.h new file mode 100644 index 00000000..c7e1354f --- /dev/null +++ b/libsecurity_apple_cspdl/lib/SSContext.h @@ -0,0 +1,168 @@ +/* + * 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. + */ + + +// +// SSContext.h - Security Server contexts +// +#ifndef _H_SS_CONTEXT +#define _H_SS_CONTEXT + +#include +#include +#include +#include + +// +// Parent class for all CSPContexts implemented in this CSP. Currently the +// only thing we add is a reference to our creator's session. +// +class SSCSPSession; +class SSKey; + +class SSContext : public CSPFullPluginSession::CSPContext +{ +public: + SSContext(SSCSPSession &session); + ~SSContext() { clearOutBuf(); } + virtual void init(const Context &context, bool encoding); + +protected: + SecurityServer::ClientSession &clientSession(); + SSCSPSession &mSession; + + // mOutBuf provides a holding tank for implied final() operations + // resulting from an outputSize(true, 0). This form of outputSize() + // is understood to only occur just prior to the final() call. To avoid + // an extra RPC (just to perform the outputSize(), most subclasses of + // SSContext actually perform the final() operation at this time, + // storing the result in mOutBuf. At final(), mOutBuf() is just copied + // to the caller's supplied output buffer. + CssmData mOutBuf; + + // We remember a pointer to the passed in context and assume it will + // remain a valid from init(), update() all the way though the call to + // final(). + const Context *mContext; + + void clearOutBuf(); + void copyOutBuf(CssmData &out); +}; + +// context for signature (sign and verify) +class SSSignatureContext : public SSContext +{ +public: + SSSignatureContext(SSCSPSession &session); + ~SSSignatureContext(); + virtual void init(const Context &context, bool signing); + virtual void update(const CssmData &data); + virtual size_t outputSize(bool final, size_t inSize); + + /* sign */ + void sign(CssmData &sig); + virtual void final(CssmData &out); + + /* verify */ + virtual void final(const CssmData &in); + + /* for raw sign/verify - optionally called after init */ + virtual void setDigestAlgorithm(CSSM_ALGORITHMS digestAlg); + +private: + /* stash the context's key for final sign/verify */ + SecurityServer::KeyHandle mKeyHandle; + + /* alg-dependent, calculated at init time */ + CSSM_ALGORITHMS mSigAlg; // raw signature alg + CSSM_ALGORITHMS mDigestAlg; // digest + CSSM_ALGORITHMS mOrigAlg; // caller's context alg + + /* exactly one of these is used to collect updates */ + NullDigest *mNullDigest; + CssmClient::Digest *mDigest; +}; + +// Context for GenerateRandom operations +class SSRandomContext : public SSContext +{ +public: + SSRandomContext(SSCSPSession &session); + virtual void init(const Context &context, bool); + virtual size_t outputSize(bool final, size_t inSize); + virtual void final(CssmData &out); + +private: + uint32 mOutSize; // spec'd in context at init() time +}; + +// Context for Encrypt and Decrypt operations +class SSCryptContext : public SSContext +{ +public: + SSCryptContext(SSCSPSession &session); + ~SSCryptContext(); + virtual void init(const Context &context, bool encoding); + virtual size_t inputSize(size_t outSize); + virtual size_t outputSize(bool final, size_t inSize); + virtual void minimumProgress(size_t &in, size_t &out); + virtual void update(void *inp, size_t &inSize, void *outp, + size_t &outSize); + virtual void final(CssmData &out); + +private: + SecurityServer::KeyHandle mKeyHandle; + NullDigest mNullDigest; // accumulator +}; + +// Digest, using raw CSP +class SSDigestContext : public SSContext +{ +public: + SSDigestContext(SSCSPSession &session); + ~SSDigestContext(); + virtual void init(const Context &context, bool); + virtual void update(const CssmData &data); + virtual void final(CssmData &out); + virtual size_t outputSize(bool final, size_t inSize); + +private: + CssmClient::Digest *mDigest; +}; + +// common class for MAC generate, verify +class SSMACContext : public SSContext +{ +public: + SSMACContext(SSCSPSession &session); + virtual void init(const Context &context, bool); + virtual void update(const CssmData &data); + virtual size_t outputSize(bool final, size_t inSize); + + /* sign */ + void genMac(CssmData &mac); + virtual void final(CssmData &out); + /* verify */ + virtual void final(const CssmData &in); + +private: + SecurityServer::KeyHandle mKeyHandle; + NullDigest mNullDigest; // accumulator +}; + + +#endif // _H_SS_CONTEXT diff --git a/libsecurity_apple_cspdl/lib/SSDLSession.cpp b/libsecurity_apple_cspdl/lib/SSDLSession.cpp new file mode 100644 index 00000000..a91e55e5 --- /dev/null +++ b/libsecurity_apple_cspdl/lib/SSDLSession.cpp @@ -0,0 +1,1437 @@ +/* + * 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. + */ + + +// +// SSDLSession.h - DL session for security server CSP/DL. +// +#include "SSDLSession.h" + +#include "CSPDLPlugin.h" +#include "SSKey.h" +#include +#include + +using namespace CssmClient; +using namespace SecurityServer; +using namespace std; + +// +// SSDLSession -- Security Server DL session +// +SSDLSession::SSDLSession(CSSM_MODULE_HANDLE handle, + CSPDLPlugin &plug, + const CSSM_VERSION &version, + uint32 subserviceId, + CSSM_SERVICE_TYPE subserviceType, + CSSM_ATTACH_FLAGS attachFlags, + const CSSM_UPCALLS &upcalls, + DatabaseManager &databaseManager, + SSCSPDLSession &ssCSPDLSession) +: DLPluginSession(handle, plug, version, subserviceId, subserviceType, + attachFlags, upcalls, databaseManager), + mSSCSPDLSession(ssCSPDLSession), + mDL(Module(gGuidAppleFileDL, Cssm::standard())), + mClientSession(Allocator::standard(), static_cast(*this)) +{ + mClientSession.registerForAclEdits(SSCSPDLSession::didChangeKeyAclCallback, &mSSCSPDLSession); + // @@@ mDL.allocator(*static_cast(this)); + mDL->allocator(allocator()); + mDL->version(version); + mDL->subserviceId(subserviceId); + mDL->flags(attachFlags); + // fprintf(stderr, "%p: Created %p\n", pthread_self(), this); +} + +SSDLSession::~SSDLSession() +{ + // @@@ What about a catch? + StLock _1(mSSUniqueRecordLock); + mSSUniqueRecordMap.clear(); + + StLock _2(mDbHandleLock); + DbHandleMap::iterator end = mDbHandleMap.end(); + for (DbHandleMap::iterator it = mDbHandleMap.begin(); it != end; ++it) + it->second->close(); + + mDbHandleMap.clear(); + mDL->detach(); +} + +// Utility functions +void +SSDLSession::GetDbNames(CSSM_NAME_LIST_PTR &outNameList) +{ + // @@@ Fix client lib + CSSM_DL_GetDbNames(mDL->handle(), &outNameList); +} + + +void +SSDLSession::FreeNameList(CSSM_NAME_LIST &inNameList) +{ + // @@@ Fix client lib + CSSM_DL_FreeNameList(mDL->handle(), &inNameList); +} + + +void +SSDLSession::DbDelete(const char *inDbName, + const CSSM_NET_ADDRESS *inDbLocation, + const AccessCredentials *inAccessCred) +{ + SSDatabase db(mClientSession, mDL, inDbName, inDbLocation); + db->accessCredentials(inAccessCred); + db->deleteDb(); +} + +// DbContext creation and destruction. +void +SSDLSession::DbCreate(const char *inDbName, + const CSSM_NET_ADDRESS *inDbLocation, + const CSSM_DBINFO &inDBInfo, + CSSM_DB_ACCESS_TYPE inAccessRequest, + const CSSM_RESOURCE_CONTROL_CONTEXT *inCredAndAclEntry, + const void *inOpenParameters, + CSSM_DB_HANDLE &outDbHandle) +{ + SSDatabase db(mClientSession, mDL, inDbName, inDbLocation); + db->dbInfo(&inDBInfo); + db->accessRequest(inAccessRequest); + db->resourceControlContext(inCredAndAclEntry); + db->openParameters(inOpenParameters); + db->create(DLDbIdentifier(CssmSubserviceUid(plugin.myGuid(), &version(), subserviceId(), + CSSM_SERVICE_DL | CSSM_SERVICE_CSP), + inDbName, inDbLocation)); + db->dbInfo(NULL); + outDbHandle = makeDbHandle(db); + // fprintf(stderr, "%p %p was created for %s in session %p\n", pthread_self(), (void*) outDbHandle, inDbName, this); +} + +void +SSDLSession::CreateWithBlob(const char *DbName, + const CSSM_NET_ADDRESS *DbLocation, + const CSSM_DBINFO &DBInfo, + CSSM_DB_ACCESS_TYPE AccessRequest, + const void *OpenParameters, + const CSSM_DATA &blob, + CSSM_DB_HANDLE &DbHandle) +{ + SSDatabase db(mClientSession, mDL, DbName, DbLocation); + db->dbInfo(&DBInfo); + db->accessRequest(AccessRequest); + db->resourceControlContext(NULL); + db->openParameters(OpenParameters); + db->createWithBlob(DLDbIdentifier(CssmSubserviceUid(plugin.myGuid(), &version(), subserviceId(), + CSSM_SERVICE_DL | CSSM_SERVICE_CSP), + DbName, DbLocation), + blob); + db->dbInfo(NULL); + DbHandle = makeDbHandle(db); + // fprintf(stderr, "%p %p was created with a blob in session %p\n", pthread_self(), (void*) DbHandle, this); +} + +void +SSDLSession::DbOpen(const char *inDbName, + const CSSM_NET_ADDRESS *inDbLocation, + CSSM_DB_ACCESS_TYPE inAccessRequest, + const AccessCredentials *inAccessCred, + const void *inOpenParameters, + CSSM_DB_HANDLE &outDbHandle) +{ + SSDatabase db(mClientSession, mDL, inDbName, inDbLocation); + db->accessRequest(inAccessRequest); + db->accessCredentials(inAccessCred); + db->openParameters(inOpenParameters); + db->open(DLDbIdentifier(CssmSubserviceUid(plugin.myGuid(), &version(), subserviceId(), + CSSM_SERVICE_DL | CSSM_SERVICE_CSP), + inDbName, inDbLocation)); + outDbHandle = makeDbHandle(db); + // fprintf(stderr, "%p %p was opened for %s in session %p\n", pthread_self(), (void*) outDbHandle, inDbName, this); +} + +// Operations using DbContext instances. +void +SSDLSession::DbClose(CSSM_DB_HANDLE inDbHandle) +{ + killDbHandle(inDbHandle)->close(); +} + +void +SSDLSession::CreateRelation(CSSM_DB_HANDLE inDbHandle, + CSSM_DB_RECORDTYPE inRelationID, + const char *inRelationName, + uint32 inNumberOfAttributes, + const CSSM_DB_SCHEMA_ATTRIBUTE_INFO *inAttributeInfo, + uint32 inNumberOfIndexes, + const CSSM_DB_SCHEMA_INDEX_INFO &inIndexInfo) +{ + SSDatabase db = findDbHandle(inDbHandle); + // @@@ Fix inAttributeInfo and inIndexInfo arguments (might be NULL if NumberOf = 0) + db->createRelation(inRelationID, inRelationName, + inNumberOfAttributes, inAttributeInfo, + inNumberOfIndexes, &inIndexInfo); +} + +void +SSDLSession::DestroyRelation(CSSM_DB_HANDLE inDbHandle, + CSSM_DB_RECORDTYPE inRelationID) +{ + // @@@ Check credentials. + SSDatabase db = findDbHandle(inDbHandle); + db->destroyRelation(inRelationID); +} + +void +SSDLSession::Authenticate(CSSM_DB_HANDLE inDbHandle, + CSSM_DB_ACCESS_TYPE inAccessRequest, + const AccessCredentials &inAccessCred) +{ + SSDatabase db = findDbHandle(inDbHandle); + db->authenticate(inAccessRequest, &inAccessCred); +} + + +void +SSDLSession::GetDbAcl(CSSM_DB_HANDLE inDbHandle, + const CSSM_STRING *inSelectionTag, + uint32 &outNumberOfAclInfos, + CSSM_ACL_ENTRY_INFO_PTR &outAclInfos) +{ + SSDatabase db = findDbHandle(inDbHandle); + mClientSession.getDbAcl(db->dbHandle(), + inSelectionTag ? *inSelectionTag : NULL, + outNumberOfAclInfos, AclEntryInfo::overlayVar(outAclInfos), allocator()); +} + +void +SSDLSession::ChangeDbAcl(CSSM_DB_HANDLE inDbHandle, + const AccessCredentials &inAccessCred, + const CSSM_ACL_EDIT &inAclEdit) +{ + SSDatabase db = findDbHandle(inDbHandle); + mClientSession.changeDbAcl(db->dbHandle(), inAccessCred, AclEdit::overlay(inAclEdit)); +} + +void +SSDLSession::GetDbOwner(CSSM_DB_HANDLE inDbHandle, + CSSM_ACL_OWNER_PROTOTYPE &outOwner) +{ + SSDatabase db = findDbHandle(inDbHandle); + mClientSession.getDbOwner(db->dbHandle(), + AclOwnerPrototype::overlay(outOwner), allocator()); +} + +void +SSDLSession::ChangeDbOwner(CSSM_DB_HANDLE inDbHandle, + const AccessCredentials &inAccessCred, + const CSSM_ACL_OWNER_PROTOTYPE &inNewOwner) +{ + SSDatabase db = findDbHandle(inDbHandle); + mClientSession.changeDbOwner(db->dbHandle(), inAccessCred, + AclOwnerPrototype::overlay(inNewOwner)); +} + +void +SSDLSession::GetDbNameFromHandle(CSSM_DB_HANDLE inDbHandle, + char **outDbName) +{ + SSDatabase db = findDbHandle(inDbHandle); + // @@@ Fix this functions signature. + db->name(*outDbName); +} + +void +SSDLSession::DataInsert(CSSM_DB_HANDLE inDbHandle, + CSSM_DB_RECORDTYPE inRecordType, + const CSSM_DB_RECORD_ATTRIBUTE_DATA *inAttributes, + const CssmData *inData, + CSSM_DB_UNIQUE_RECORD_PTR &outUniqueId) +{ + SSDatabase db = findDbHandle(inDbHandle); + // @@@ Fix client lib. + SSUniqueRecord uniqueId = db->insert(inRecordType, inAttributes, inData, true); // @@@ Fix me + outUniqueId = makeSSUniqueRecord(uniqueId); + // @@@ If this is a key do the right thing. +} + +void +SSDLSession::DataDelete(CSSM_DB_HANDLE inDbHandle, + const CSSM_DB_UNIQUE_RECORD &inUniqueRecordIdentifier) +{ + SSDatabase db = findDbHandle(inDbHandle); + SSUniqueRecord uniqueId = findSSUniqueRecord(inUniqueRecordIdentifier); + uniqueId->deleteRecord(); + // @@@ If this is a key do the right thing. +} + + +void +SSDLSession::DataModify(CSSM_DB_HANDLE inDbHandle, + CSSM_DB_RECORDTYPE inRecordType, + CSSM_DB_UNIQUE_RECORD &inoutUniqueRecordIdentifier, + const CSSM_DB_RECORD_ATTRIBUTE_DATA *inAttributesToBeModified, + const CssmData *inDataToBeModified, + CSSM_DB_MODIFY_MODE inModifyMode) +{ + SSDatabase db = findDbHandle(inDbHandle); + SSUniqueRecord uniqueId = findSSUniqueRecord(inoutUniqueRecordIdentifier); + uniqueId->modify(inRecordType, inAttributesToBeModified, inDataToBeModified, inModifyMode); + // @@@ If this is a key do the right thing. +} + +CSSM_HANDLE +SSDLSession::DataGetFirst(CSSM_DB_HANDLE inDbHandle, + const CssmQuery *inQuery, + CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR inoutAttributes, + CssmData *inoutData, + CSSM_DB_UNIQUE_RECORD_PTR &outUniqueRecord) +{ + SSDatabase db = findDbHandle(inDbHandle); + CSSM_HANDLE resultsHandle = CSSM_INVALID_HANDLE; + SSUniqueRecord uniqueId(db); + + // 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; + CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR pAttributes; + if (inoutAttributes) + pAttributes = inoutAttributes; + else + { + pAttributes = &attributes; + memset(pAttributes, 0, sizeof(attributes)); + } + + // Retrive the record. + CSSM_RETURN result = CSSM_DL_DataGetFirst(db->handle(), inQuery, &resultsHandle, + pAttributes, inoutData, uniqueId); + if (result) + { + if (result == CSSMERR_DL_ENDOFDATA) + return CSSM_INVALID_HANDLE; + + CssmError::throwMe(result); + } + + uniqueId->activate(); + + // If we the client didn't ask for data then it doesn't matter + // if this record is a key or not, just return it. + if (inoutData) + { + if (pAttributes->DataRecordType == CSSM_DL_DB_RECORD_PUBLIC_KEY + || pAttributes->DataRecordType == CSSM_DL_DB_RECORD_PRIVATE_KEY + || pAttributes->DataRecordType == CSSM_DL_DB_RECORD_SYMMETRIC_KEY) + { + // This record is a key, do the right thing (tm). + // Allocate storage for the key. + CssmKey *outKey = DatabaseSession::alloc(); + new SSKey(*this, *outKey, db, uniqueId, pAttributes->DataRecordType, *inoutData); + + // Free the data we retrived (keyblob) + allocator().free(inoutData->Data); + + // Set the length and data on the data we return to the client + inoutData->Length = sizeof(*outKey); + inoutData->Data = reinterpret_cast(outKey); + } + } + + outUniqueRecord = makeSSUniqueRecord(uniqueId); + return resultsHandle; +} + +bool +SSDLSession::DataGetNext(CSSM_DB_HANDLE inDbHandle, + CSSM_HANDLE inResultsHandle, + CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR inoutAttributes, + CssmData *inoutData, + CSSM_DB_UNIQUE_RECORD_PTR &outUniqueRecord) +{ + // @@@ If this is a key do the right thing. + SSDatabase db = findDbHandle(inDbHandle); + SSUniqueRecord uniqueId(db); + + // 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; + CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR pAttributes; + if (inoutAttributes) + pAttributes = inoutAttributes; + else + { + pAttributes = &attributes; + memset(pAttributes, 0, sizeof(attributes)); + } + + CSSM_RETURN result = CSSM_DL_DataGetNext(db->handle(), inResultsHandle, + inoutAttributes, inoutData, uniqueId); + if (result) + { + if (result == CSSMERR_DL_ENDOFDATA) + return false; + + CssmError::throwMe(result); + } + + uniqueId->activate(); + + // If we the client didn't ask for data then it doesn't matter + // if this record is a key or not, just return it. + if (inoutData) + { + if (pAttributes->DataRecordType == CSSM_DL_DB_RECORD_PUBLIC_KEY + || pAttributes->DataRecordType == CSSM_DL_DB_RECORD_PRIVATE_KEY + || pAttributes->DataRecordType == CSSM_DL_DB_RECORD_SYMMETRIC_KEY) + { + // This record is a key, do the right thing (tm). + // Allocate storage for the key. + CssmKey *outKey = DatabaseSession::alloc(); + new SSKey(*this, *outKey, db, uniqueId, pAttributes->DataRecordType, *inoutData); + + // Free the data we retrived (keyblob) + allocator().free(inoutData->Data); + + // Set the length and data on the data we return to the client + inoutData->Length = sizeof(*outKey); + inoutData->Data = reinterpret_cast(outKey); + } + } + + outUniqueRecord = makeSSUniqueRecord(uniqueId); + + return true; +} + +void +SSDLSession::DataAbortQuery(CSSM_DB_HANDLE inDbHandle, + CSSM_HANDLE inResultsHandle) +{ + // @@@ If this is a key do the right thing. + SSDatabase db = findDbHandle(inDbHandle); + CSSM_RETURN result = CSSM_DL_DataAbortQuery(db->handle(), inResultsHandle); + if (result) + CssmError::throwMe(result); +} + +void +SSDLSession::DataGetFromUniqueRecordId(CSSM_DB_HANDLE inDbHandle, + const CSSM_DB_UNIQUE_RECORD &inUniqueRecord, + CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR inoutAttributes, + CssmData *inoutData) +{ + 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; + CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR pAttributes; + if (inoutAttributes) + pAttributes = inoutAttributes; + else + { + pAttributes = &attributes; + memset(pAttributes, 0, sizeof(attributes)); + } + + CSSM_RETURN result = CSSM_DL_DataGetFromUniqueRecordId(db->handle(), + uniqueId, pAttributes, inoutData); + if (result) + CssmError::throwMe(result); + + if (inoutData) + { + if (pAttributes->DataRecordType == CSSM_DL_DB_RECORD_PUBLIC_KEY + || pAttributes->DataRecordType == CSSM_DL_DB_RECORD_PRIVATE_KEY + || pAttributes->DataRecordType == CSSM_DL_DB_RECORD_SYMMETRIC_KEY) + { + // This record is a key, do the right thing (tm). + // Allocate storage for the key. + CssmKey *outKey = DatabaseSession::alloc(); + new SSKey(*this, *outKey, db, uniqueId, pAttributes->DataRecordType, *inoutData); + + // Free the data we retrived (keyblob) + allocator().free(inoutData->Data); + + // Set the length and data on the data we return to the client + inoutData->Length = sizeof(*outKey); + inoutData->Data = reinterpret_cast(outKey); + } + } +} + +void +SSDLSession::FreeUniqueRecord(CSSM_DB_HANDLE inDbHandle, + CSSM_DB_UNIQUE_RECORD &inUniqueRecordIdentifier) +{ + killSSUniqueRecord(inUniqueRecordIdentifier); +} + +static const uint32 kGenericAttributeNames[] = +{ + 'cdat', 'mdat', 'desc', 'icmt', 'crtr', 'type', 'scrp', 7, 8, 'invi', 'nega', 'cusi', 'prot', 'acct', 'svce', + 'gena' +}; + +const uint32 kNumGenericAttributes = sizeof (kGenericAttributeNames) / sizeof (uint32); + +static const uint32 kApplesharePasswordNames[] = +{ + 'cdat', 'mdat', 'desc', 'icmt', 'crtr', 'type', 'scrp', 7, 8, 'invi', 'nega', 'cusi', 'prot', 'acct', 'vlme', + 'srvr', 'ptcl', 'addr', 'ssig' +}; + +const uint32 kNumApplesharePasswordAttributes = sizeof (kApplesharePasswordNames) / sizeof (uint32); + +static const uint32 kInternetPasswordNames[] = +{ + 'cdat', 'mdat', 'desc', 'icmt', 'crtr', 'type', 'scrp', 7, 8, 'invi', 'nega', 'cusi', 'prot', 'acct', 'sdmn', + 'srvr', 'ptcl', 'atyp', 'port', 'path' +}; + +const uint32 kNumInternetPasswordAttributes = sizeof (kInternetPasswordNames) / sizeof (uint32); + +const uint32 kKeyAttributeNames[] = +{ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26 +}; + +const uint32 kNumKeyAttributes = sizeof (kKeyAttributeNames) / sizeof (uint32); + +const uint32 kCertificateAttributeNames[] = +{ + 'ctyp', 'cenc', 'labl', 'alis', 'subj', 'issu', 'snbr', 'skid', 'hpky' +}; + +const uint32 kNumCertificateAttributes = sizeof (kCertificateAttributeNames) / sizeof (uint32); + +const unsigned kSymmetricKeyLabel = 6; // record id for the symmetric key +const unsigned kLabelSize = 20; +const unsigned kNumSymmetricAttributes = 27; // number of attributes to request + +static void appendUInt32ToData (const uint32 value, CssmDataContainer &data) +{ + data.append (CssmPolyData (uint32 (htonl (value)))); +} + +static inline uint32 GetUInt32AtFinger (uint8 *&finger) +{ + uint32 a = ((finger[0] << 24) | (finger[1] << 16) | (finger[2] << 8) | finger[3]); + finger += sizeof (uint32); + return a; +} + +void +SSDLSession::unwrapAttributesAndData (uint32 &numAttributes, + CSSM_DB_ATTRIBUTE_DATA_PTR &attributes, + CSSM_DATA &data, + CSSM_DATA &input) +{ + // 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) + { + attributes[i].Info.AttributeNameFormat = GetUInt32AtFinger (finger); + 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; + for (j = 0; j < attributes[i].NumberOfValues; ++j) + { + attributes[i].Value[j].Length = GetUInt32AtFinger (finger); + if (attributes[i].Value[j].Length != 0) + { + // sanity check what we are about to do + if (finger > maximum || finger + attributes[i].Value[j].Length > maximum) + { + CssmError::throwMe (CSSM_ERRCODE_INVALID_POINTER); + } + + attributes[i].Value[j].Data = (uint8*) allocator ().malloc (attributes[i].Value[j].Length); + + switch (attributes[i].Info.AttributeFormat) + { + default: + { + memmove (attributes[i].Value[j].Data, finger, attributes[i].Value[j].Length); + 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; + uint32 numValues = attributes[i].Value[j].Length / sizeof (UInt32); + while (numValues--) + { + *d++ = GetUInt32AtFinger (finger); + } + break; + } + } + } + else + { + attributes[i].Value[j].Data = NULL; + } + } + } + + // get the data + data.Length = GetUInt32AtFinger (finger); + if (data.Length != 0) + { + // sanity check the pointer + if (finger + data.Length > maximum) + { + CssmError::throwMe (CSSM_ERRCODE_INVALID_POINTER); + } + + data.Data = (uint8*) allocator ().malloc (data.Length); + memmove (data.Data, finger, data.Length); + finger += data.Length; + } + else + { + data.Data = NULL; + } +} + +void +SSDLSession::getWrappedAttributesAndData (SSDatabase &db, + CSSM_DB_RECORDTYPE recordType, + CSSM_DB_UNIQUE_RECORD_PTR recordPtr, + CssmDataContainer &output, + CSSM_DATA *dataBlob) +{ + // figure out which attributes to use + const uint32* attributeNameArray; + uint32 numAttributeNames; + + switch (recordType) + { + case CSSM_DL_DB_RECORD_GENERIC_PASSWORD: + { + attributeNameArray = kGenericAttributeNames; + 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: + { + attributeNameArray = kKeyAttributeNames; + numAttributeNames = kNumKeyAttributes; + break; + } + + default: + { + 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; + for (i = 0; i < numAttributeNames; ++i) + { + 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 (), + recordPtr, + &attrData, + &data); + if (result != 0) + { + 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) + { + appendUInt32ToData (attributes[i].Info.AttributeNameFormat, output); + 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) + { + appendUInt32ToData (attributes[i].Value[j].Length, output); + if (attributes[i].Value[j].Length != 0) + { + switch (attributes[i].Info.AttributeFormat) + { + default: + { + output.append (CssmPolyData (attributes[i].Value[j])); + break; + } + + case CSSM_DB_ATTRIBUTE_FORMAT_SINT32: + case CSSM_DB_ATTRIBUTE_FORMAT_UINT32: + { + uint32 n = htonl (*(uint32*) attributes[i].Value[j].Data); + CSSM_DATA d; + d.Length = sizeof (uint32); + d.Data = (uint8*) &n; + output.append (CssmPolyData (d)); + break; + } + } + } + } + } + + // write the length of the data + appendUInt32ToData (data.Length, output); + + // write the data itself + if (data.Length != 0) + { + output.append (CssmPolyData (data)); + } + + // clean up + for (i = 0; i < numAttributeNames; ++i) + { + unsigned j; + for (j = 0; j < attributes[i].NumberOfValues; ++j) + { + 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) + { + dataBlob->Data = data.Data; + dataBlob->Length = data.Length; + data.Data = NULL; + data.Length = 0; + } +} + +void +SSDLSession::getUniqueIdForSymmetricKey (SSDatabase &db, CSSM_DATA &label, + CSSM_DB_UNIQUE_RECORD_PTR &uniqueRecord) +{ + // set up a query to get the key + CSSM_SELECTION_PREDICATE predicate; + predicate.DbOperator = CSSM_DB_EQUAL; + predicate.Attribute.Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER; + predicate.Attribute.Info.Label.AttributeID = kSymmetricKeyLabel; + predicate.Attribute.Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_BLOB; + predicate.Attribute.NumberOfValues = 1; + // the label of the corresponding key is the first 20 bytes of the blob we returned + predicate.Attribute.Value = &label; + + CSSM_QUERY query; + query.RecordType = CSSM_DL_DB_RECORD_SYMMETRIC_KEY; + 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, + &uniqueRecord); + if (result) + { + CssmError::throwMe (result); + } + + // clean up + CSSM_DL_DataAbortQuery (db->handle (), handle); +} + +void +SSDLSession::getCorrespondingSymmetricKey (SSDatabase &db, CSSM_DATA &labelData, CssmDataContainer &data) +{ + // get the unique ID + CSSM_DB_UNIQUE_RECORD_PTR uniqueRecord; + getUniqueIdForSymmetricKey (db, labelData, uniqueRecord); + + // 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); +} + +void SSDLSession::doGetWithoutEncryption (SSDatabase &db, const void *inInputParams, void **outOutputParams) +{ + 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); + } + + // 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 (data.Length, output); + output.append (CssmPolyData (data)); + + // figure out what we need to do with the key blob + CssmDataContainer key; + switch (params->attributes->DataRecordType) + { + case CSSM_DL_DB_RECORD_GENERIC_PASSWORD: + case CSSM_DL_DB_RECORD_INTERNET_PASSWORD: + case CSSM_DL_DB_RECORD_APPLESHARE_PASSWORD: + { + // the label is the first kLabelSize bytes of the resultant data blob + CSSM_DATA label = {kLabelSize, blobData.Data}; + + // get the key + getCorrespondingSymmetricKey (db, label, key); + } + break; + + default: + { + break; + } + } + + + // write out the length of the key blob + appendUInt32ToData (key.Length, output); + + if (key.Length != 0) + { + // write the key + output.append (CssmPolyData (key)); + } + + // copy out the results + outputData->Data = output.Data; + output.Data = NULL; + outputData->Length = output.Length; + output.Length = 0; +} + +void +SSDLSession::cleanupAttributes (uint32 numAttributes, CSSM_DB_ATTRIBUTE_DATA_PTR attributes) +{ + unsigned i; + for (i = 0; i < numAttributes; ++i) + { + unsigned j; + for (j = 0; j < attributes[i].NumberOfValues; ++j) + { + free (attributes[i].Value[j].Data); + } + + free (attributes[i].Value); + } + + free (attributes); +} + +void +SSDLSession::doModifyWithoutEncryption (SSDatabase &db, const void* inInputParams, void** outOutputParams) +{ + 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; + data.Length = GetUInt32AtFinger (finger); + data.Data = finger; + if (data.Length + sizeof (UInt32) > params->data->Length) + { + 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: + case CSSM_DL_DB_RECORD_INTERNET_PASSWORD: + case CSSM_DL_DB_RECORD_APPLESHARE_PASSWORD: + { + // read off the data so that we can update the key + CssmDataContainer oldData; + result = CSSM_DL_DataGetFromUniqueRecordId (db->handle(), + uniqueIDPtr, + NULL, + &oldData); + if (result) + { + 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, + attrDataPtr, + &keyBlob, + modifyMode); + + // clean up + CSSM_DL_FreeUniqueRecord (db->handle (), recordID); + + cleanupAttributes (numKeyAttributes, keyAttributes); + break; + } + + default: + { + break; + } + } + + // save off the new data + result = CSSM_DL_DataModify(db->handle(), + params->recordType, + uniqueIDPtr, + &attrData, + &dataBlob, + params->modifyMode); + + // clean up + cleanupAttributes (numAttributes, attributes); + + if (result) + { + CssmError::throwMe(result); + } + +} + +void +SSDLSession::doInsertWithoutEncryption (SSDatabase &db, const void* inInputParams, void** outOutputParams) +{ + CSSM_RETURN result; + + 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, + &attrData, + &dataBlob, + uniqueID); + + // cleanup + allocator ().free (dataBlob.Data); + cleanupAttributes (numAttributes, attributes); + + // 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); + } + + // Get the key data for this insert + data.Length = GetUInt32AtFinger (finger); + if (data.Length != 0) + { + data.Data = finger; + + // parse the key data blob + 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 the key data into the symmetric key table + CSSM_DB_UNIQUE_RECORD_PTR uniqueRecord; + result = CSSM_DL_DataInsert (db->handle(), CSSM_DL_DB_RECORD_SYMMETRIC_KEY, &attrData, &dataBlob, + &uniqueRecord); + if (result) + { + CssmError::throwMe (result); + } + + // clean up after inserting the key + CSSM_DL_FreeUniqueRecord (db->handle (), uniqueRecord); + allocator ().free (dataBlob.Data); + cleanupAttributes (numAttributes, attributes); + } +} + +void +SSDLSession::doConvertRecordIdentifier (SSDatabase &db, const void *inInputParams, void **outOutputParams) +{ + SSUniqueRecord uniqueId (db); + + // clone the unique record + CSSM_DB_UNIQUE_RECORD_PTR clone = (CSSM_DB_UNIQUE_RECORD_PTR) allocator ().malloc (sizeof (CSSM_DB_UNIQUE_RECORD)); + *clone = *(CSSM_DB_UNIQUE_RECORD_PTR) inInputParams; + + // 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; +} + +void +SSDLSession::PassThrough(CSSM_DB_HANDLE inDbHandle, + uint32 inPassThroughId, + const void *inInputParams, + void **outOutputParams) +{ + if (inPassThroughId == CSSM_APPLECSPDL_DB_CREATE_WITH_BLOB) + { + CSSM_APPLE_CSPDL_DB_CREATE_WITH_BLOB_PARAMETERS* params = (CSSM_APPLE_CSPDL_DB_CREATE_WITH_BLOB_PARAMETERS*) inInputParams; + CreateWithBlob(params->dbName, params->dbLocation, *params->dbInfo, params->accessRequest, params->openParameters, *params->blob, + * (CSSM_DB_HANDLE*) outOutputParams); + return; + } + + SSDatabase db = findDbHandle(inDbHandle); + switch (inPassThroughId) + { + case CSSM_APPLECSPDL_DB_LOCK: + db->lock(); + break; + case CSSM_APPLECSPDL_DB_UNLOCK: + if (inInputParams) + db->unlock(*reinterpret_cast(inInputParams)); + else + db->unlock(); + break; + case CSSM_APPLECSPDL_DB_GET_SETTINGS: + { + if (!outOutputParams) + CssmError::throwMe(CSSM_ERRCODE_INVALID_OUTPUT_POINTER); + + CSSM_APPLECSPDL_DB_SETTINGS_PARAMETERS_PTR params = + DatabaseSession::alloc(); + try + { + uint32 idleTimeout; + bool lockOnSleep; + db->getSettings(idleTimeout, lockOnSleep); + params->idleTimeout = idleTimeout; + params->lockOnSleep = lockOnSleep; + } + catch(...) + { + allocator().free(params); + throw; + } + *reinterpret_cast(outOutputParams) = params; + break; + } + case CSSM_APPLECSPDL_DB_SET_SETTINGS: + { + if (!inInputParams) + CssmError::throwMe(CSSM_ERRCODE_INVALID_INPUT_POINTER); + + const CSSM_APPLECSPDL_DB_SETTINGS_PARAMETERS *params = + reinterpret_cast(inInputParams); + db->setSettings(params->idleTimeout, params->lockOnSleep); + break; + } + case CSSM_APPLECSPDL_DB_IS_LOCKED: + { + if (!outOutputParams) + CssmError::throwMe(CSSM_ERRCODE_INVALID_OUTPUT_POINTER); + + CSSM_APPLECSPDL_DB_IS_LOCKED_PARAMETERS_PTR params = + DatabaseSession::alloc(); + try + { + params->isLocked = db->isLocked(); + } + catch(...) + { + allocator().free(params); + throw; + } + *reinterpret_cast(outOutputParams) = params; + break; + } + case CSSM_APPLECSPDL_DB_CHANGE_PASSWORD: + { + if (!inInputParams) + CssmError::throwMe(CSSM_ERRCODE_INVALID_INPUT_POINTER); + + const CSSM_APPLECSPDL_DB_CHANGE_PASSWORD_PARAMETERS *params = + reinterpret_cast(inInputParams); + db->changePassphrase(params->accessCredentials); + break; + } + case CSSM_APPLECSPDL_DB_GET_HANDLE: + { + using SecurityServer::DbHandle; + Required(outOutputParams, CSSM_ERRCODE_INVALID_OUTPUT_POINTER); + *reinterpret_cast(outOutputParams) = db->handle(); + break; + } + case CSSM_APPLECSPDL_CSP_RECODE: + { + if (!inInputParams) + CssmError::throwMe(CSSM_ERRCODE_INVALID_INPUT_POINTER); + + const CSSM_APPLECSPDL_RECODE_PARAMETERS *params = + reinterpret_cast(inInputParams); + + db->recode(CssmData::overlay(params->dbBlob), + CssmData::overlay(params->extraData)); + break; + } + case CSSM_APPLECSPDL_DB_GET_RECORD_IDENTIFIER: + { + SSUniqueRecord uniqueID = findSSUniqueRecord(*(CSSM_DB_UNIQUE_RECORD_PTR) inInputParams); + db->getRecordIdentifier(uniqueID, *reinterpret_cast(outOutputParams)); + break; + } + case CSSM_APPLECSPDL_DB_COPY_BLOB: + { + // make the output parameters + db->copyBlob(*reinterpret_cast(outOutputParams)); + break; + } + case CSSM_APPLECSPDL_DB_INSERT_WITHOUT_ENCRYPTION: + { + doInsertWithoutEncryption (db, inInputParams, outOutputParams); + break; + } + case CSSM_APPLECSPDL_DB_MODIFY_WITHOUT_ENCRYPTION: + { + doModifyWithoutEncryption (db, inInputParams, outOutputParams); + break; + } + case CSSM_APPLECSPDL_DB_GET_WITHOUT_ENCRYPTION: + { + doGetWithoutEncryption (db, inInputParams, outOutputParams); + break; + } + case CSSM_APPLECSPDL_DB_CONVERT_RECORD_IDENTIFIER: + { + doConvertRecordIdentifier (db, inInputParams, outOutputParams); + break; + } + default: + { + CSSM_RETURN result = CSSM_DL_PassThrough(db->handle(), inPassThroughId, inInputParams, outOutputParams); + if (result) + CssmError::throwMe(result); + break; + } + } +} + +CSSM_DB_HANDLE +SSDLSession::makeDbHandle(SSDatabase &inDb) +{ + StLock _(mDbHandleLock); + CSSM_DB_HANDLE aDbHandle = inDb->handle().DBHandle; + IFDEBUG(bool inserted =) mDbHandleMap.insert(DbHandleMap::value_type(aDbHandle, inDb)).second; + assert(inserted); + // fprintf(stderr, "%p Added %p to %p\n", pthread_self(), (void*) aDbHandle, (void*) this); + return aDbHandle; +} + +SSDatabase +SSDLSession::killDbHandle(CSSM_DB_HANDLE inDbHandle) +{ + StLock _(mDbHandleLock); + DbHandleMap::iterator it = mDbHandleMap.find(inDbHandle); + if (it == mDbHandleMap.end()) + { + // 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); + return db; +} + +SSDatabase +SSDLSession::findDbHandle(CSSM_DB_HANDLE inDbHandle) +{ + StLock _(mDbHandleLock); + // fprintf(stderr, "%p Looking for %p in %p\n", pthread_self(), (void*) inDbHandle, (void*) this); + DbHandleMap::iterator it = mDbHandleMap.find(inDbHandle); + if (it == mDbHandleMap.end()) + { + // fprintf(stderr, "%p Can't find %p in %p\n", pthread_self(), (void*) inDbHandle, this); + DbHandleMap::iterator it = mDbHandleMap.begin(); + while (it != mDbHandleMap.end()) + { + // fprintf(stderr, "\t%p\n", (void*) it->first); + it++; + } + + CssmError::throwMe(CSSMERR_DL_INVALID_DB_HANDLE); + } + + return it->second; +} + +CSSM_DB_UNIQUE_RECORD_PTR +SSDLSession::makeSSUniqueRecord(SSUniqueRecord &uniqueId) +{ + StLock _(mSSUniqueRecordLock); + CSSM_HANDLE ref = CSSM_HANDLE(static_cast(uniqueId)); + IFDEBUG(bool inserted =) mSSUniqueRecordMap.insert(SSUniqueRecordMap::value_type(ref, uniqueId)).second; + assert(inserted); + return createUniqueRecord(ref); +} + +SSUniqueRecord +SSDLSession::killSSUniqueRecord(CSSM_DB_UNIQUE_RECORD &inUniqueRecord) +{ + CSSM_HANDLE ref = parseUniqueRecord(inUniqueRecord); + StLock _(mSSUniqueRecordLock); + SSUniqueRecordMap::iterator it = mSSUniqueRecordMap.find(ref); + if (it == mSSUniqueRecordMap.end()) + CssmError::throwMe(CSSMERR_DL_INVALID_RECORD_UID); + + SSUniqueRecord uniqueRecord = it->second; + mSSUniqueRecordMap.erase(it); + freeUniqueRecord(inUniqueRecord); + return uniqueRecord; +} + +SSUniqueRecord +SSDLSession::findSSUniqueRecord(const CSSM_DB_UNIQUE_RECORD &inUniqueRecord) +{ + CSSM_HANDLE ref = parseUniqueRecord(inUniqueRecord); + StLock _(mSSUniqueRecordLock); + SSUniqueRecordMap::iterator it = mSSUniqueRecordMap.find(ref); + if (it == mSSUniqueRecordMap.end()) + CssmError::throwMe(CSSMERR_DL_INVALID_RECORD_UID); + + return it->second; +} + +CSSM_DB_UNIQUE_RECORD_PTR +SSDLSession::createUniqueRecord(CSSM_HANDLE ref) +{ + CSSM_DB_UNIQUE_RECORD *aUniqueRecord = DatabaseSession::alloc(); + memset(aUniqueRecord, 0, sizeof(CSSM_DB_UNIQUE_RECORD)); + aUniqueRecord->RecordIdentifier.Length = sizeof(CSSM_HANDLE); + try + { + aUniqueRecord->RecordIdentifier.Data = DatabaseSession::alloc(sizeof(CSSM_HANDLE)); + *reinterpret_cast(aUniqueRecord->RecordIdentifier.Data) = ref; + } + catch(...) + { + free(aUniqueRecord); + throw; + } + + return aUniqueRecord; +} + +CSSM_HANDLE +SSDLSession::parseUniqueRecord(const CSSM_DB_UNIQUE_RECORD &inUniqueRecord) +{ + if (inUniqueRecord.RecordIdentifier.Length != sizeof(CSSM_HANDLE)) + CssmError::throwMe(CSSMERR_DL_INVALID_RECORD_UID); + + return *reinterpret_cast(inUniqueRecord.RecordIdentifier.Data); +} + +void +SSDLSession::freeUniqueRecord(CSSM_DB_UNIQUE_RECORD &inUniqueRecord) +{ + if (inUniqueRecord.RecordIdentifier.Length != 0 + && inUniqueRecord.RecordIdentifier.Data != NULL) + { + inUniqueRecord.RecordIdentifier.Length = 0; + allocator().free(inUniqueRecord.RecordIdentifier.Data); + } + allocator().free(&inUniqueRecord); +} diff --git a/libsecurity_apple_cspdl/lib/SSDLSession.h b/libsecurity_apple_cspdl/lib/SSDLSession.h new file mode 100644 index 00000000..a053a362 --- /dev/null +++ b/libsecurity_apple_cspdl/lib/SSDLSession.h @@ -0,0 +1,194 @@ +/* + * 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. + */ + + +// +// SSDLSession.h - DL session for security server CSP/DL. +// +#ifndef _H_SSDLSESSION +#define _H_SSDLSESSION + +#include + +#include "SSDatabase.h" + +class CSPDLPlugin; +class SSCSPDLSession; + +class SSDLSession : public DLPluginSession +{ +public: + SSCSPDLSession &mSSCSPDLSession; + + SSDLSession(CSSM_MODULE_HANDLE handle, + CSPDLPlugin &plug, + const CSSM_VERSION &version, + uint32 subserviceId, + CSSM_SERVICE_TYPE subserviceType, + CSSM_ATTACH_FLAGS attachFlags, + const CSSM_UPCALLS &upcalls, + DatabaseManager &databaseManager, + SSCSPDLSession &ssCSPDLSession); + ~SSDLSession(); + + SecurityServer::ClientSession &clientSession() + { return mClientSession; } + void GetDbNames(CSSM_NAME_LIST_PTR &NameList); + void FreeNameList(CSSM_NAME_LIST &NameList); + void DbDelete(const char *DbName, + const CSSM_NET_ADDRESS *DbLocation, + const AccessCredentials *AccessCred); + void DbCreate(const char *DbName, + const CSSM_NET_ADDRESS *DbLocation, + const CSSM_DBINFO &DBInfo, + CSSM_DB_ACCESS_TYPE AccessRequest, + const CSSM_RESOURCE_CONTROL_CONTEXT *CredAndAclEntry, + const void *OpenParameters, + CSSM_DB_HANDLE &DbHandle); + void CreateWithBlob(const char *DbName, + const CSSM_NET_ADDRESS *DbLocation, + const CSSM_DBINFO &DBInfo, + CSSM_DB_ACCESS_TYPE AccessRequest, + const void *OpenParameters, + const CSSM_DATA &blob, + CSSM_DB_HANDLE &DbHandle); + void DbOpen(const char *DbName, + const CSSM_NET_ADDRESS *DbLocation, + CSSM_DB_ACCESS_TYPE AccessRequest, + const AccessCredentials *AccessCred, + const void *OpenParameters, + CSSM_DB_HANDLE &DbHandle); + void DbClose(CSSM_DB_HANDLE DBHandle); + void CreateRelation(CSSM_DB_HANDLE DBHandle, + CSSM_DB_RECORDTYPE RelationID, + const char *RelationName, + uint32 NumberOfAttributes, + const CSSM_DB_SCHEMA_ATTRIBUTE_INFO *pAttributeInfo, + uint32 NumberOfIndexes, + const CSSM_DB_SCHEMA_INDEX_INFO &pIndexInfo); + void DestroyRelation(CSSM_DB_HANDLE DBHandle, + CSSM_DB_RECORDTYPE RelationID); + + void Authenticate(CSSM_DB_HANDLE DBHandle, + CSSM_DB_ACCESS_TYPE AccessRequest, + const AccessCredentials &AccessCred); + void GetDbAcl(CSSM_DB_HANDLE DBHandle, + const CSSM_STRING *SelectionTag, + uint32 &NumberOfAclInfos, + CSSM_ACL_ENTRY_INFO_PTR &AclInfos); + void ChangeDbAcl(CSSM_DB_HANDLE DBHandle, + const AccessCredentials &AccessCred, + const CSSM_ACL_EDIT &AclEdit); + void GetDbOwner(CSSM_DB_HANDLE DBHandle, + CSSM_ACL_OWNER_PROTOTYPE &Owner); + void ChangeDbOwner(CSSM_DB_HANDLE DBHandle, + const AccessCredentials &AccessCred, + const CSSM_ACL_OWNER_PROTOTYPE &NewOwner); + void GetDbNameFromHandle(CSSM_DB_HANDLE DBHandle, + char **DbName); + void DataInsert(CSSM_DB_HANDLE DBHandle, + CSSM_DB_RECORDTYPE RecordType, + const CSSM_DB_RECORD_ATTRIBUTE_DATA *Attributes, + const CssmData *Data, + CSSM_DB_UNIQUE_RECORD_PTR &UniqueId); + void DataDelete(CSSM_DB_HANDLE DBHandle, + const CSSM_DB_UNIQUE_RECORD &UniqueRecordIdentifier); + void DataModify(CSSM_DB_HANDLE DBHandle, + CSSM_DB_RECORDTYPE RecordType, + CSSM_DB_UNIQUE_RECORD &UniqueRecordIdentifier, + const CSSM_DB_RECORD_ATTRIBUTE_DATA *AttributesToBeModified, + const CssmData *DataToBeModified, + CSSM_DB_MODIFY_MODE ModifyMode); + CSSM_HANDLE DataGetFirst(CSSM_DB_HANDLE DBHandle, + const CssmQuery *Query, + CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR Attributes, + CssmData *Data, + CSSM_DB_UNIQUE_RECORD_PTR &UniqueId); + bool DataGetNext(CSSM_DB_HANDLE DBHandle, + CSSM_HANDLE ResultsHandle, + CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR Attributes, + CssmData *Data, + CSSM_DB_UNIQUE_RECORD_PTR &UniqueId); + void DataAbortQuery(CSSM_DB_HANDLE DBHandle, + CSSM_HANDLE ResultsHandle); + void DataGetFromUniqueRecordId(CSSM_DB_HANDLE DBHandle, + const CSSM_DB_UNIQUE_RECORD &UniqueRecord, + CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR Attributes, + CssmData *Data); + void FreeUniqueRecord(CSSM_DB_HANDLE DBHandle, + CSSM_DB_UNIQUE_RECORD &UniqueRecord); + void PassThrough(CSSM_DB_HANDLE DBHandle, + uint32 PassThroughId, + const void *InputParams, + void **OutputParams); + + Allocator &allocator() { return *static_cast(this); } + + SSDatabase findDbHandle(CSSM_DB_HANDLE inDbHandle); +protected: + CSSM_DB_HANDLE makeDbHandle(SSDatabase &inDb); + SSDatabase killDbHandle(CSSM_DB_HANDLE inDbHandle); + + CSSM_DB_ATTRIBUTE_DATA_PTR reconstructRecordFromBlob (const CSSM_DATA& blob, + CssmDataContainer &recordData, + uint32 &numAttributes); + + void getWrappedAttributesAndData (SSDatabase &db, + CSSM_DB_RECORDTYPE recordType, + CSSM_DB_UNIQUE_RECORD_PTR recordPtr, + CssmDataContainer &output, + CSSM_DATA *blobData); + + void unwrapAttributesAndData (uint32 &numAttributes, + CSSM_DB_ATTRIBUTE_DATA_PTR &attributes, + CSSM_DATA &data, + CSSM_DATA &input); + + void cleanupAttributes (uint32 numAttributes, CSSM_DB_ATTRIBUTE_DATA_PTR attributes); + + void getUniqueIdForSymmetricKey (SSDatabase &db, CSSM_DATA &label, + CSSM_DB_UNIQUE_RECORD_PTR &uniqueRecord); + + void getCorrespondingSymmetricKey (SSDatabase &db, CSSM_DATA& label, CssmDataContainer &key); + + void doGetWithoutEncryption (SSDatabase &db, const void* inInputParams, void **outOutputParams); + void doModifyWithoutEncryption (SSDatabase &db, const void* inInputParams, void **outOutputParams); + void doInsertWithoutEncryption (SSDatabase &db, const void* inInputParams, void** outOutputParams); + void doConvertRecordIdentifier (SSDatabase &db, const void* inInputParams, void **outOutputParams); + + Mutex mDbHandleLock; + typedef map DbHandleMap; + DbHandleMap mDbHandleMap; + + CSSM_DB_UNIQUE_RECORD_PTR makeSSUniqueRecord(SSUniqueRecord &uniqueId); + SSUniqueRecord killSSUniqueRecord(CSSM_DB_UNIQUE_RECORD &inUniqueRecord); + SSUniqueRecord findSSUniqueRecord(const CSSM_DB_UNIQUE_RECORD &inUniqueRecord); + + CSSM_DB_UNIQUE_RECORD_PTR createUniqueRecord(CSSM_HANDLE ref); + CSSM_HANDLE parseUniqueRecord(const CSSM_DB_UNIQUE_RECORD &inUniqueRecord); + void freeUniqueRecord(CSSM_DB_UNIQUE_RECORD &inUniqueRecord); + + Mutex mSSUniqueRecordLock; + typedef map SSUniqueRecordMap; + SSUniqueRecordMap mSSUniqueRecordMap; + + CssmClient::DL mDL; + SecurityServer::ClientSession mClientSession; +}; + + +#endif // _H_SSDLSESSION diff --git a/libsecurity_apple_cspdl/lib/SSDatabase.cpp b/libsecurity_apple_cspdl/lib/SSDatabase.cpp new file mode 100644 index 00000000..34ff89fd --- /dev/null +++ b/libsecurity_apple_cspdl/lib/SSDatabase.cpp @@ -0,0 +1,439 @@ +/* + * 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. + */ + + +// +// SSDatabase.cpp - Security Server database object +// +#include "SSDatabase.h" + +#include + +using namespace CssmClient; +using namespace SecurityServer; + +const char *const SSDatabaseImpl::DBBlobRelationName = "DBBlob"; + + +SSDatabaseImpl::SSDatabaseImpl(ClientSession &inClientSession, const CssmClient::DL &dl, + const char *inDbName, const CSSM_NET_ADDRESS *inDbLocation) + : Db::Impl(dl, inDbName, inDbLocation), mClientSession(inClientSession), mSSDbHandle(noDb) +{ +} + +SSDatabaseImpl::~SSDatabaseImpl() +{ + if (mSSDbHandle != noDb) + mClientSession.releaseDb(mSSDbHandle); +} + +SSUniqueRecord +SSDatabaseImpl::insert(CSSM_DB_RECORDTYPE recordType, + const CSSM_DB_RECORD_ATTRIBUTE_DATA *attributes, + const CSSM_DATA *data, bool) +{ + SSUniqueRecord uniqueId(SSDatabase(this)); + check(CSSM_DL_DataInsert(handle(), recordType, + attributes, + data, uniqueId)); + // Activate uniqueId so CSSM_DL_FreeUniqueRecord() gets called when it goes out of scope. + uniqueId->activate(); + return uniqueId; +} + +void +SSDatabaseImpl::authenticate(CSSM_DB_ACCESS_TYPE inAccessRequest, + const CSSM_ACCESS_CREDENTIALS *inAccessCredentials) +{ + mClientSession.authenticateDb(dbHandle(), inAccessRequest, + AccessCredentials::overlay(inAccessCredentials)); +} + +void +SSDatabaseImpl::lock() +{ + mClientSession.lock(dbHandle()); + +} + +void +SSDatabaseImpl::unlock() +{ + mClientSession.unlock(dbHandle()); +} + +void +SSDatabaseImpl::unlock(const CSSM_DATA &password) +{ + mClientSession.unlock(dbHandle(), CssmData::overlay(password)); +} + +void +SSDatabaseImpl::getSettings(uint32 &outIdleTimeout, bool &outLockOnSleep) +{ + DBParameters parameters; + mClientSession.getDbParameters(dbHandle(), parameters); + outIdleTimeout = parameters.idleTimeout; + outLockOnSleep = parameters.lockOnSleep; +} + +void +SSDatabaseImpl::setSettings(uint32 inIdleTimeout, bool inLockOnSleep) +{ + DBParameters parameters; + parameters.idleTimeout = inIdleTimeout; + parameters.lockOnSleep = inLockOnSleep; + mClientSession.setDbParameters(dbHandle(), parameters); + + // Reencode the db blob. + CssmDataContainer dbb(allocator()); + mClientSession.encodeDb(mSSDbHandle, dbb, allocator()); + getDbBlobId()->modify(DBBlobRelationID, NULL, &dbb, CSSM_DB_MODIFY_ATTRIBUTE_NONE); +} + +bool +SSDatabaseImpl::isLocked() +{ + return mClientSession.isLocked(dbHandle()); +} + +void +SSDatabaseImpl::changePassphrase(const CSSM_ACCESS_CREDENTIALS *cred) +{ + mClientSession.changePassphrase(dbHandle(), AccessCredentials::overlay(cred)); + + // Reencode the db blob. + CssmDataContainer dbb(allocator()); + mClientSession.encodeDb(mSSDbHandle, dbb, allocator()); + getDbBlobId()->modify(DBBlobRelationID, NULL, &dbb, CSSM_DB_MODIFY_ATTRIBUTE_NONE); +} + +DbHandle +SSDatabaseImpl::dbHandle() +{ + activate(); + if (mForked()) { + // re-establish the dbHandle with the SecurityServer + CssmDataContainer dbb(allocator()); + getDbBlobId(&dbb); + mSSDbHandle = mClientSession.decodeDb(mIdentifier, + AccessCredentials::overlay(accessCredentials()), dbb); + } + return mSSDbHandle; +} + +void +SSDatabaseImpl::commonCreate(const DLDbIdentifier &dlDbIdentifier, bool &autoCommit) +{ + mIdentifier = dlDbIdentifier; + // Set to false if autocommit should remain off after the create. + autoCommit = true; + + // OpenParameters to use + CSSM_APPLEDL_OPEN_PARAMETERS newOpenParameters = + { + sizeof(CSSM_APPLEDL_OPEN_PARAMETERS), + CSSM_APPLEDL_OPEN_PARAMETERS_VERSION, + CSSM_FALSE, // do not auto-commit + 0 // mask - do not use following fields + }; + + // Get the original openParameters and apply them to the ones we + // are passing in. + const CSSM_APPLEDL_OPEN_PARAMETERS *inOpenParameters = + reinterpret_cast(openParameters()); + if (inOpenParameters) + { + switch (inOpenParameters->version) + { + case 1: + if (inOpenParameters->length < sizeof(CSSM_APPLEDL_OPEN_PARAMETERS)) + CssmError::throwMe(CSSMERR_APPLEDL_INVALID_OPEN_PARAMETERS); + + newOpenParameters.mask = inOpenParameters->mask; + newOpenParameters.mode = inOpenParameters->mode; + /*DROPTHROUGH*/ + case 0: + //if (inOpenParameters->length < sizeof(CSSM_APPLEDL_OPEN_PARAMETERS_V0)) + // CssmError::throwMe(CSSMERR_APPLEDL_INVALID_OPEN_PARAMETERS); + + // This will determine whether we leave autocommit off or not. + autoCommit = inOpenParameters->autoCommit == CSSM_FALSE ? false : true; + break; + + default: + CssmError::throwMe(CSSMERR_APPLEDL_INVALID_OPEN_PARAMETERS); + } + } + + // Use the new openParameters + openParameters(&newOpenParameters); + try + { + DbImpl::create(); + // Restore the original openparameters again. + openParameters(inOpenParameters); + } + catch (...) + { + // Make sure restore the original openparameters again even if + // create throws. + openParameters(inOpenParameters); + throw; + } + + // @@@ The CSSM_DB_SCHEMA_ATTRIBUTE_INFO and CSSM_DB_SCHEMA_INDEX_INFO + // arguments should be optional. + createRelation(DBBlobRelationID, DBBlobRelationName, + 0, (CSSM_DB_SCHEMA_ATTRIBUTE_INFO *)42, + 0, (CSSM_DB_SCHEMA_INDEX_INFO *)42); + + // @@@ Only iff not already in mDbInfo + createRelation(CSSM_DL_DB_RECORD_PUBLIC_KEY, "CSSM_DL_DB_RECORD_PUBLIC_KEY", + KeySchema::KeySchemaAttributeCount, KeySchema::KeySchemaAttributeList, + KeySchema::KeySchemaIndexCount, KeySchema::KeySchemaIndexList); + + // @@@ Only iff not already in mDbInfo + createRelation(CSSM_DL_DB_RECORD_PRIVATE_KEY, "CSSM_DL_DB_RECORD_PRIVATE_KEY", + KeySchema::KeySchemaAttributeCount, KeySchema::KeySchemaAttributeList, + KeySchema::KeySchemaIndexCount, KeySchema::KeySchemaIndexList); + + // @@@ Only iff not already in mDbInfo + createRelation(CSSM_DL_DB_RECORD_SYMMETRIC_KEY, "CSSM_DL_DB_RECORD_SYMMETRIC_KEY", + KeySchema::KeySchemaAttributeCount, KeySchema::KeySchemaAttributeList, + KeySchema::KeySchemaIndexCount, KeySchema::KeySchemaIndexList); +} + +void +SSDatabaseImpl::create(const DLDbIdentifier &dlDbIdentifier) +{ + try + { + bool autoCommit; + commonCreate(dlDbIdentifier, autoCommit); + + DBParameters dbParameters; + memset(&dbParameters, 0, sizeof(DBParameters)); + dbParameters.idleTimeout = kDefaultIdleTimeout; + dbParameters.lockOnSleep = kDefaultLockOnSleep; + + const AccessCredentials *cred = NULL; + const AclEntryInput *owner = NULL; + if (resourceControlContext()) + { + cred = AccessCredentials::overlay(resourceControlContext()->AccessCred); + owner = &AclEntryInput::overlay(resourceControlContext()->InitialAclEntry); + } + mSSDbHandle = mClientSession.createDb(dlDbIdentifier, cred, owner, dbParameters); + CssmDataContainer dbb(allocator()); + mClientSession.encodeDb(mSSDbHandle, dbb, allocator()); + Db::Impl::insert(DBBlobRelationID, NULL, &dbb); + if (autoCommit) + { + passThrough(CSSM_APPLEFILEDL_COMMIT, NULL); + passThrough(CSSM_APPLEFILEDL_TOGGLE_AUTOCOMMIT, + reinterpret_cast(1)); + } + } + catch(CssmError e) + { + if (e.error != CSSMERR_DL_DATASTORE_ALREADY_EXISTS) + { + DbImpl::deleteDb(); + } + throw; + } + catch(...) + { + DbImpl::deleteDb(); + throw; + } +} + +void +SSDatabaseImpl::createWithBlob(const DLDbIdentifier &dlDbIdentifier, const CSSM_DATA &blob) +{ + try + { + bool autoCommit; + commonCreate(dlDbIdentifier, autoCommit); + Db::Impl::insert(DBBlobRelationID, NULL, &blob); + if (autoCommit) + { + passThrough(CSSM_APPLEFILEDL_COMMIT, NULL); + passThrough(CSSM_APPLEFILEDL_TOGGLE_AUTOCOMMIT, + reinterpret_cast(1)); + } + } + catch(...) + { + DbImpl::deleteDb(); + throw; + } +} + +void +SSDatabaseImpl::open(const DLDbIdentifier &dlDbIdentifier) +{ + mIdentifier = dlDbIdentifier; + Db::Impl::open(); + + CssmDataContainer dbb(allocator()); + getDbBlobId(&dbb); + + mSSDbHandle = mClientSession.decodeDb(dlDbIdentifier, AccessCredentials::overlay(accessCredentials()), dbb); +} + +void +SSDatabaseImpl::recode(const CssmData &data, const CssmData &extraData) +{ + // Start a transaction (Implies activate()). + passThrough(CSSM_APPLEFILEDL_TOGGLE_AUTOCOMMIT, 0); + + try + { + CssmDataContainer dbb(allocator()); + // Make sure mSSDbHandle is valid. + CssmClient::DbUniqueRecord dbBlobId = getDbBlobId(&dbb); + if (mForked()) { + // re-establish the dbHandle with the SecurityServer + mSSDbHandle = mClientSession.decodeDb(mIdentifier, + AccessCredentials::overlay(accessCredentials()), dbb); + } + dbb.clear(); + + DbHandle successfulHdl = mClientSession.authenticateDbsForSync(data, extraData); + + // Create a newDbHandle using the master secrets from the dbBlob we are + // recoding to. + SecurityServer::DbHandle clonedDbHandle = + mClientSession.recodeDbForSync(successfulHdl, mSSDbHandle); + + // @@@ If the dbb changed since we fetched it we should abort or + // retry the operation here. + + // Recode all keys + DbCursor cursor(SSDatabase(this)); + cursor->recordType(CSSM_DL_DB_RECORD_ALL_KEYS); + CssmDataContainer keyBlob(allocator()); + CssmClient::DbUniqueRecord keyBlobId; + DbAttributes attributes; + while (cursor->next(&attributes, &keyBlob, keyBlobId)) + { + // Decode the old key + CssmKey::Header header; + KeyHandle keyHandle = + mClientSession.decodeKey(mSSDbHandle, keyBlob, header); + // Recode the key + CssmDataContainer newKeyBlob(mClientSession.returnAllocator); + mClientSession.recodeKey(mSSDbHandle, keyHandle, clonedDbHandle, + newKeyBlob); + mClientSession.releaseKey(keyHandle); + // Write the recoded key blob to the database + keyBlobId->modify(attributes.recordType(), NULL, &newKeyBlob, + CSSM_DB_MODIFY_ATTRIBUTE_NONE); + } + + // Commit the new blob to securityd, reencode the db blob, release the + // cloned db handle and commit the new blob to the db. + mClientSession.commitDbForSync(mSSDbHandle, clonedDbHandle, + dbb, allocator()); + dbBlobId->modify(DBBlobRelationID, NULL, &dbb, + CSSM_DB_MODIFY_ATTRIBUTE_NONE); + + // Commit the transaction to the db + passThrough(CSSM_APPLEFILEDL_COMMIT, NULL); + passThrough(CSSM_APPLEFILEDL_TOGGLE_AUTOCOMMIT, + reinterpret_cast(1)); + } + catch (...) + { + // Something went wrong rollback the transaction + passThrough(CSSM_APPLEFILEDL_ROLLBACK, NULL); + passThrough(CSSM_APPLEFILEDL_TOGGLE_AUTOCOMMIT, + reinterpret_cast(1)); + throw; + } +} + +void SSDatabaseImpl::getRecordIdentifier(CSSM_DB_UNIQUE_RECORD_PTR uniqueRecord, CSSM_DATA &recordID) +{ + // the unique ID is composed of three uint32s (plus one filler word). Pull + // them out and byte swap them + recordID.Length = sizeof (uint32) * kNumIDWords; + recordID.Data = (uint8*) allocator().malloc(recordID.Length); + + // copy the data + uint32* dest = (uint32*) recordID.Data; + uint32* src = (uint32*) uniqueRecord->RecordIdentifier.Data; + + dest[0] = htonl (src[0]); + dest[1] = htonl (src[1]); + dest[2] = htonl (src[2]); + dest[3] = 0; +} + +void SSDatabaseImpl::copyBlob(CSSM_DATA &data) +{ + // get the blob from the database + CssmDataContainer dbb(allocator()); + getDbBlobId(&dbb); + + // copy the data back + data.Data = dbb.Data; + data.Length = dbb.Length; + + // zap the return structure so that we don't get zapped when dbb goes out of scope... + dbb.Data = NULL; + dbb.Length = 0; +} + +DbUniqueRecordImpl * +SSDatabaseImpl::newDbUniqueRecord() +{ + return new SSUniqueRecordImpl(SSDatabase(this)); +} + +CssmClient::DbUniqueRecord +SSDatabaseImpl::getDbBlobId(CssmDataContainer *dbb) +{ + CssmClient::DbUniqueRecord dbBlobId; + + DbCursor cursor(SSDatabase(this)); + cursor->recordType(DBBlobRelationID); + if (!cursor->next(NULL, dbb, dbBlobId)) + CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT); + + return dbBlobId; +} + + + +SSUniqueRecordImpl::SSUniqueRecordImpl(const SSDatabase &db) +: DbUniqueRecord::Impl(db) +{ +} + +SSUniqueRecordImpl::~SSUniqueRecordImpl() +{ +} + +SSDatabase +SSUniqueRecordImpl::database() const +{ + return parent(); +} diff --git a/libsecurity_apple_cspdl/lib/SSDatabase.h b/libsecurity_apple_cspdl/lib/SSDatabase.h new file mode 100644 index 00000000..ba22a0b6 --- /dev/null +++ b/libsecurity_apple_cspdl/lib/SSDatabase.h @@ -0,0 +1,142 @@ +/* + * 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. + */ + + +// +// SSDatabase.h - Security Server database object +// +#ifndef _H_SSDATABASE_ +#define _H_SSDATABASE_ + +#include +#include +#include + +class SSCSPDLSession; +class SSUniqueRecord; + +// +// Protected please ignore this class unless subclassing SSDatabase. +// +class SSDatabase; + +class SSDatabaseImpl : public CssmClient::DbImpl +{ +public: + static const char *const DBBlobRelationName; + static const CSSM_DB_RECORDTYPE DBBlobRelationID = + CSSM_DB_RECORDTYPE_APP_DEFINED_START + 0x8000; + +public: + SSDatabaseImpl(SecurityServer::ClientSession &inClientSession, + const CssmClient::DL &dl, + const char *inDbName, const CSSM_NET_ADDRESS *inDbLocation); + virtual ~SSDatabaseImpl(); + + void create(const DLDbIdentifier &dlDbIdentifier); + void createWithBlob(const DLDbIdentifier &dlDbIdentifier, const CSSM_DATA &blob); + void open(const DLDbIdentifier &dlDbIdentifier); + SSUniqueRecord insert(CSSM_DB_RECORDTYPE recordType, + const CSSM_DB_RECORD_ATTRIBUTE_DATA *attributes, + const CSSM_DATA *data, bool); + void authenticate(CSSM_DB_ACCESS_TYPE inAccessRequest, + const CSSM_ACCESS_CREDENTIALS *inAccessCredentials); + + // Passthrough functions (only implemented by AppleCSPDL). + void lock(); + void unlock(); + void unlock(const CSSM_DATA &password); + void getSettings(uint32 &outIdleTimeout, bool &outLockOnSleep); + void setSettings(uint32 inIdleTimeout, bool inLockOnSleep); + bool isLocked(); + void changePassphrase(const CSSM_ACCESS_CREDENTIALS *cred); + void recode(const CssmData &data, const CssmData &extraData); + // DbUniqueRecordMaker + CssmClient::DbUniqueRecordImpl *newDbUniqueRecord(); + + // New methods not inherited from DbImpl + SecurityServer::DbHandle dbHandle(); + + void getRecordIdentifier(const CSSM_DB_UNIQUE_RECORD_PTR uniqueRecord, CSSM_DATA &data); + void copyBlob(CSSM_DATA &blob); + +protected: + CssmClient::DbUniqueRecord getDbBlobId(CssmDataContainer *dbb = NULL); + void commonCreate (const DLDbIdentifier &dlDbIdentifier, bool &autocommit); + +private: + // 5 minute default autolock time + static const uint32 kDefaultIdleTimeout = 5 * 60; + static const uint8 kDefaultLockOnSleep = true; + static const unsigned kNumIDWords = 4; + + DLDbIdentifier mIdentifier; + UnixPlusPlus::ForkMonitor mForked; + + SecurityServer::ClientSession &mClientSession; + SecurityServer::DbHandle mSSDbHandle; +}; + + +// +// SSDatabase -- A Security Server aware Db object. +// +class SSDatabase : public CssmClient::Db +{ +public: + typedef SSDatabaseImpl Impl; + + explicit SSDatabase(SSDatabaseImpl *impl) : CssmClient::Db(impl) {} + SSDatabase() : CssmClient::Db(NULL) {} + SSDatabase(SecurityServer::ClientSession &inClientSession, + const CssmClient::DL &dl, + const char *inDbName, const CSSM_NET_ADDRESS *inDbLocation) + : CssmClient::Db(new SSDatabaseImpl(inClientSession, dl, inDbName, inDbLocation)) {} + + SSDatabaseImpl *operator ->() const { return &impl(); } + SSDatabaseImpl &operator *() const { return impl(); } + + // For convinience only + SecurityServer::DbHandle dbHandle() { return (*this) ? (*this)->dbHandle() : SecurityServer::noDb; } +}; + + +class SSUniqueRecordImpl : public CssmClient::DbUniqueRecordImpl +{ +public: + SSUniqueRecordImpl(const SSDatabase &db); + virtual ~SSUniqueRecordImpl(); + + SSDatabase database() const; +}; + + +class SSUniqueRecord : public CssmClient::DbUniqueRecord +{ +public: + typedef SSUniqueRecordImpl Impl; + + explicit SSUniqueRecord(SSUniqueRecordImpl *impl) : CssmClient::DbUniqueRecord(impl) {} + SSUniqueRecord() : CssmClient::DbUniqueRecord(NULL) {} + SSUniqueRecord(const SSDatabase &db) : CssmClient::DbUniqueRecord(new SSUniqueRecordImpl(db)) {} + + SSUniqueRecordImpl *operator ->() const { return &impl(); } + SSUniqueRecordImpl &operator *() const { return impl(); } +}; + + +#endif // _H_SSDATABASE_ diff --git a/libsecurity_apple_cspdl/lib/SSFactory.cpp b/libsecurity_apple_cspdl/lib/SSFactory.cpp new file mode 100644 index 00000000..93f0dcaa --- /dev/null +++ b/libsecurity_apple_cspdl/lib/SSFactory.cpp @@ -0,0 +1,82 @@ +/* + * 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. + */ + + +// +// SSFactory -- The factory for Security Server context objects +// +#include "SSFactory.h" + +#include "SSContext.h" + + +// +// SSFactory -- The factory for Security Server context objects +// +bool SSFactory::setup(SSCSPSession &session, CSPFullPluginSession::CSPContext * &cspCtx, + const Context &context, bool encoding) +{ + if (cspCtx) + return false; // not ours or already set + + switch (context.type()) + { + case CSSM_ALGCLASS_SIGNATURE: + cspCtx = new SSSignatureContext(session); + return true; + case CSSM_ALGCLASS_MAC: + cspCtx = new SSMACContext(session); + return true; + case CSSM_ALGCLASS_DIGEST: + cspCtx = new SSDigestContext(session); + return true; + case CSSM_ALGCLASS_SYMMETRIC: + case CSSM_ALGCLASS_ASYMMETRIC: + cspCtx = new SSCryptContext(session); // @@@ Could also be wrap/unwrap + return true; + case CSSM_ALGCLASS_RANDOMGEN: + cspCtx = new SSRandomContext(session); // @@@ Should go. + return true; + } + + return false; + +#if 0 + /* FIXME - qualify by ALGCLASS as well to avoid MAC */ + switch (context.algorithm()) { + case CSSM_ALGID_MD5: + cspCtx = new MD5Context(session); + return true; + case CSSM_ALGID_SHA1: + cspCtx = new SHA1Context(session); + return true; + } + return false; + + if (ctx) + CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR); // won't support re-definition + switch (context.algorithm()) { + case CSSM_ALGID_ROTTY_ROT_16: + ctx = new SSContext(16); + return true; + case CSSM_ALGID_ROTTY_ROT_37: + ctx = new SSContext(37); + return true; + } +#endif + return false; +} diff --git a/libsecurity_apple_cspdl/lib/SSFactory.h b/libsecurity_apple_cspdl/lib/SSFactory.h new file mode 100644 index 00000000..8fadae8b --- /dev/null +++ b/libsecurity_apple_cspdl/lib/SSFactory.h @@ -0,0 +1,39 @@ +/* + * 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. + */ + + +// +// SSAlgorithms.h - Description t.b.d. +// +#ifndef _H_SS_ALGORITHMS +#define _H_SS_ALGORITHMS + +#include + +/* Can't include CSPDLPlugin.h due to circular dependency */ +class SSCSPSession; + +// no longer a subclass of AlgorithmFactory due to +// differing setup() methods +class SSFactory +{ +public: + bool setup(SSCSPSession &session, CSPFullPluginSession::CSPContext * &ctx, + const Context &context, bool encoding); +}; + +#endif // _H_SS_ALGORITHMS diff --git a/libsecurity_apple_cspdl/lib/SSKey.cpp b/libsecurity_apple_cspdl/lib/SSKey.cpp new file mode 100644 index 00000000..6400b629 --- /dev/null +++ b/libsecurity_apple_cspdl/lib/SSKey.cpp @@ -0,0 +1,347 @@ +/* + * Copyright (c) 2000-2001,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. + */ + + +// +// SSKey - reference keys for the security server +// +#include "SSKey.h" + +#include "SSCSPSession.h" +#include "SSCSPDLSession.h" +#include "SSDatabase.h" +#include "SSDLSession.h" +#include +#include + +using namespace CssmClient; +using namespace SecurityServer; + +// Constructor for a Security Server generated key. +SSKey::SSKey(SSCSPSession &session, KeyHandle keyHandle, CssmKey &ioKey, + SSDatabase &inSSDatabase, uint32 inKeyAttr, + const CssmData *inKeyLabel) +: ReferencedKey(session.mSSCSPDLSession), +mAllocator(session), mKeyHandle(keyHandle), +mClientSession(session.clientSession()) +{ + CssmKey::Header &header = ioKey.header(); + if (inKeyAttr & CSSM_KEYATTR_PERMANENT) + { + if (!inSSDatabase) + CssmError::throwMe(CSSMERR_CSP_MISSING_ATTR_DL_DB_HANDLE); + + // EncodeKey and store it in the db. + CssmDataContainer blob(mAllocator); + clientSession().encodeKey(keyHandle, blob); + + assert(header.HeaderVersion == CSSM_KEYHEADER_VERSION); + switch (header.KeyClass) + { + case CSSM_KEYCLASS_PUBLIC_KEY: + mRecordType = CSSM_DL_DB_RECORD_PUBLIC_KEY; + break; + case CSSM_KEYCLASS_PRIVATE_KEY: + mRecordType = CSSM_DL_DB_RECORD_PRIVATE_KEY; + break; + case CSSM_KEYCLASS_SESSION_KEY: + mRecordType = CSSM_DL_DB_RECORD_SYMMETRIC_KEY; + break; + default: + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY); + } + + CssmData label; + if (inKeyLabel) + label = *inKeyLabel; + + CssmData none; + // We store the keys real CSP guid on disk + CssmGuidData creatorGuid(header.CspId); + CssmDateData startDate(header.StartDate); + CssmDateData endDate(header.EndDate); + + DbAttributes attributes(inSSDatabase); + attributes.recordType(mRecordType); + attributes.add(KeySchema::KeyClass, mRecordType); + attributes.add(KeySchema::PrintName, label); + attributes.add(KeySchema::Alias, none); + attributes.add(KeySchema::Permanent, + header.attribute(CSSM_KEYATTR_PERMANENT)); + attributes.add(KeySchema::Private, + header.attribute(CSSM_KEYATTR_PRIVATE)); + attributes.add(KeySchema::Modifiable, + header.attribute(CSSM_KEYATTR_MODIFIABLE)); + attributes.add(KeySchema::Label, label); + attributes.add(KeySchema::ApplicationTag, none); + attributes.add(KeySchema::KeyCreator, creatorGuid); + attributes.add(KeySchema::KeyType, header.AlgorithmId); + attributes.add(KeySchema::KeySizeInBits, header.LogicalKeySizeInBits); + // @@@ Get the real effective key size. + attributes.add(KeySchema::EffectiveKeySize, header.LogicalKeySizeInBits); + attributes.add(KeySchema::StartDate, startDate); + attributes.add(KeySchema::EndDate, endDate); + attributes.add(KeySchema::Sensitive, + header.attribute(CSSM_KEYATTR_SENSITIVE)); + attributes.add(KeySchema::AlwaysSensitive, + header.attribute(CSSM_KEYATTR_ALWAYS_SENSITIVE)); + attributes.add(KeySchema::Extractable, + header.attribute(CSSM_KEYATTR_EXTRACTABLE)); + attributes.add(KeySchema::NeverExtractable, + header.attribute(CSSM_KEYATTR_NEVER_EXTRACTABLE)); + attributes.add(KeySchema::Encrypt, + header.useFor(CSSM_KEYUSE_ANY | CSSM_KEYUSE_ENCRYPT)); + attributes.add(KeySchema::Decrypt, + header.useFor(CSSM_KEYUSE_ANY | CSSM_KEYUSE_DECRYPT)); + attributes.add(KeySchema::Derive, + header.useFor(CSSM_KEYUSE_ANY | CSSM_KEYUSE_DERIVE)); + attributes.add(KeySchema::Sign, + header.useFor(CSSM_KEYUSE_ANY | CSSM_KEYUSE_SIGN)); + attributes.add(KeySchema::Verify, + header.useFor(CSSM_KEYUSE_ANY | CSSM_KEYUSE_VERIFY)); + attributes.add(KeySchema::SignRecover, + header.useFor(CSSM_KEYUSE_ANY + | CSSM_KEYUSE_SIGN_RECOVER)); + attributes.add(KeySchema::VerifyRecover, + header.useFor(CSSM_KEYUSE_ANY + | CSSM_KEYUSE_VERIFY_RECOVER)); + attributes.add(KeySchema::Wrap, + header.useFor(CSSM_KEYUSE_ANY | CSSM_KEYUSE_WRAP)); + attributes.add(KeySchema::Unwrap, + header.useFor(CSSM_KEYUSE_ANY | CSSM_KEYUSE_UNWRAP)); + + // @@@ Fixme + mUniqueId = inSSDatabase->insert(mRecordType, &attributes, &blob, + true); + } + + header.cspGuid(session.plugin.myGuid()); // Set the csp guid to me. + makeReferenceKey(mAllocator, keyReference(), ioKey); +} + +// Constructor for a key retrived from a Db. +SSKey::SSKey(SSDLSession &session, CssmKey &ioKey, SSDatabase &inSSDatabase, + const SSUniqueRecord &uniqueId, CSSM_DB_RECORDTYPE recordType, + CssmData &keyBlob) +: ReferencedKey(session.mSSCSPDLSession), +mAllocator(session.allocator()), mKeyHandle(noKey), mUniqueId(uniqueId), +mRecordType(recordType), +mClientSession(session.clientSession()) +{ + CssmKey::Header &header = ioKey.header(); + memset(&header, 0, sizeof(header)); // Clear key header + + if (!mUniqueId || !mUniqueId->database()) + CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR); + + header.HeaderVersion = CSSM_KEYHEADER_VERSION; + switch (mRecordType) + { + case CSSM_DL_DB_RECORD_PUBLIC_KEY: + header.KeyClass = CSSM_KEYCLASS_PUBLIC_KEY; + break; + case CSSM_DL_DB_RECORD_PRIVATE_KEY: + header.KeyClass = CSSM_KEYCLASS_PRIVATE_KEY; + break; + case CSSM_DL_DB_RECORD_SYMMETRIC_KEY: + header.KeyClass = CSSM_KEYCLASS_SESSION_KEY; + break; + default: + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY); + } + + DbAttributes attributes(mUniqueId->database()); + attributes.recordType(mRecordType); + attributes.add(KeySchema::KeyClass); // 0 + attributes.add(KeySchema::Permanent); // 1 + attributes.add(KeySchema::Private); // 2 + attributes.add(KeySchema::Modifiable); // 3 + attributes.add(KeySchema::KeyCreator); // 4 + attributes.add(KeySchema::KeyType); // 5 + attributes.add(KeySchema::KeySizeInBits); // 6 + attributes.add(KeySchema::StartDate); // 7 + attributes.add(KeySchema::EndDate); // 8 + attributes.add(KeySchema::Sensitive); // 9 + attributes.add(KeySchema::AlwaysSensitive); // 10 + attributes.add(KeySchema::Extractable); // 11 + attributes.add(KeySchema::NeverExtractable); // 12 + attributes.add(KeySchema::Encrypt); // 13 + attributes.add(KeySchema::Decrypt); // 14 + attributes.add(KeySchema::Derive); // 15 + attributes.add(KeySchema::Sign); // 16 + attributes.add(KeySchema::Verify); // 17 + attributes.add(KeySchema::SignRecover); // 18 + attributes.add(KeySchema::VerifyRecover); // 19 + attributes.add(KeySchema::Wrap); // 20 + attributes.add(KeySchema::Unwrap); // 21 + + mUniqueId->get(&attributes, NULL); + + // Assert that the mRecordType matches the KeyClass attribute. + if (mRecordType != uint32(attributes[0])) + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY); + + header.AlgorithmId = attributes[5]; // KeyType + header.LogicalKeySizeInBits = attributes[6]; // KeySizeInBits + + if (attributes[1]) header.setAttribute(CSSM_KEYATTR_PERMANENT); + if (attributes[2]) header.setAttribute(CSSM_KEYATTR_PRIVATE); + if (attributes[3]) header.setAttribute(CSSM_KEYATTR_MODIFIABLE); + if (attributes[9]) header.setAttribute(CSSM_KEYATTR_SENSITIVE); + if (attributes[11]) header.setAttribute(CSSM_KEYATTR_EXTRACTABLE); + if (attributes[10]) header.setAttribute(CSSM_KEYATTR_ALWAYS_SENSITIVE); + if (attributes[12]) header.setAttribute(CSSM_KEYATTR_NEVER_EXTRACTABLE); + + if (attributes[13]) header.usage(CSSM_KEYUSE_ENCRYPT); + if (attributes[14]) header.usage(CSSM_KEYUSE_DECRYPT); + if (attributes[15]) header.usage(CSSM_KEYUSE_DERIVE); + if (attributes[16]) header.usage(CSSM_KEYUSE_SIGN); + if (attributes[17]) header.usage(CSSM_KEYUSE_VERIFY); + if (attributes[18]) header.usage(CSSM_KEYUSE_SIGN_RECOVER); + if (attributes[19]) header.usage(CSSM_KEYUSE_VERIFY_RECOVER); + if (attributes[20]) header.usage(CSSM_KEYUSE_WRAP); + if (attributes[21]) header.usage(CSSM_KEYUSE_UNWRAP); + + // If all usages are allowed set usage to CSSM_KEYUSE_ANY + if (header.usage() == (CSSM_KEYUSE_ENCRYPT | CSSM_KEYUSE_DECRYPT + | CSSM_KEYUSE_DERIVE | CSSM_KEYUSE_SIGN + | CSSM_KEYUSE_VERIFY | CSSM_KEYUSE_SIGN_RECOVER + | CSSM_KEYUSE_VERIFY_RECOVER | CSSM_KEYUSE_WRAP + | CSSM_KEYUSE_UNWRAP)) + header.usage(CSSM_KEYUSE_ANY); + + if (!attributes[7].size() || !attributes[8].size()) + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY); + + header.StartDate = attributes[7].at(0); + header.EndDate = attributes[8].at(0); + + makeReferenceKey(mAllocator, keyReference(), ioKey); + header.cspGuid(session.plugin.myGuid()); // Set the csp guid to me. +} + +SSKey::~SSKey() +{ + if (mKeyHandle != noKey) + clientSession().releaseKey(mKeyHandle); +} + +void +SSKey::free(const AccessCredentials *accessCred, CssmKey &ioKey, + CSSM_BOOL deleteKey) +{ + freeReferenceKey(mAllocator, ioKey); + if (deleteKey) + { + if (!mUniqueId || !mUniqueId->database()) + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY); + + // @@@ Evaluate accessCred against Db acl. + // What should we do with accessCred? Reauthenticate + // mUniqueId->database()? + mUniqueId->deleteRecord(); + } + + if (mKeyHandle != noKey) + { + clientSession().releaseKey(mKeyHandle); + mKeyHandle = noKey; + } +} + +SecurityServer::ClientSession & +SSKey::clientSession() +{ + return mClientSession; +} + +KeyHandle SSKey::optionalKeyHandle() const +{ + return mKeyHandle; +} + +KeyHandle +SSKey::keyHandle() +{ + if (mKeyHandle == noKey) + { + // Deal with uninstantiated keys. + if (!mUniqueId || !mUniqueId->database()) + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY); + + CssmDataContainer blob(mAllocator); + mUniqueId->get(NULL, &blob); + CssmKey::Header dummyHeader; // @@@ Unused + mKeyHandle = + clientSession().decodeKey(mUniqueId->database().dbHandle(), blob, + dummyHeader); + + // @@@ Check decoded header against returned header + } + + return mKeyHandle; +} + +// +// ACL retrieval and change operations +// +void +SSKey::getOwner(CSSM_ACL_OWNER_PROTOTYPE &owner, Allocator &allocator) +{ + clientSession().getKeyOwner(keyHandle(), AclOwnerPrototype::overlay(owner), + allocator); +} + +void +SSKey::changeOwner(const AccessCredentials &accessCred, + const AclOwnerPrototype &newOwner) +{ + clientSession().changeKeyOwner(keyHandle(), accessCred, newOwner); + didChangeAcl(); +} + +void +SSKey::getAcl(const char *selectionTag, uint32 &numberOfAclInfos, + AclEntryInfo *&aclInfos, Allocator &allocator) +{ + clientSession().getKeyAcl(keyHandle(), selectionTag, numberOfAclInfos, + aclInfos, allocator); +} + +void +SSKey::changeAcl(const AccessCredentials &accessCred, const AclEdit &aclEdit) +{ + clientSession().changeKeyAcl(keyHandle(), accessCred, aclEdit); + didChangeAcl(); +} + +void +SSKey::didChangeAcl() +{ + if (mUniqueId == true) + { + secdebug("keyacl", "SSKey::didChangeAcl() keyHandle: %lu updating DL entry", mKeyHandle); + // The key is persistent, make the change on disk. + CssmDataContainer keyBlob(mAllocator); + clientSession().encodeKey(keyHandle(), keyBlob); + mUniqueId->modify(mRecordType, NULL, &keyBlob, CSSM_DB_MODIFY_ATTRIBUTE_NONE); + } + else + { + secdebug("keyacl", "SSKey::didChangeAcl() keyHandle: %lu transient key no update done", mKeyHandle); + } +} diff --git a/libsecurity_apple_cspdl/lib/SSKey.h b/libsecurity_apple_cspdl/lib/SSKey.h new file mode 100644 index 00000000..03d5447d --- /dev/null +++ b/libsecurity_apple_cspdl/lib/SSKey.h @@ -0,0 +1,87 @@ +/* + * 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. + */ + + +// +// SSKey.h - CSP-wide SSKey base class +// +#ifndef _H_SSKEY_ +#define _H_SSKEY_ + +#include + +#include "SSDatabase.h" + +#include +#include + +namespace Security +{ + +class CssmKey; + +} // end namespace Security + +class SSCSPSession; +class SSCSPDLSession; +class SSDLSession; + +class SSKey : public ReferencedKey +{ +public: + SSKey(SSCSPSession &session, SecurityServer::KeyHandle keyHandle, + CssmKey &ioKey, SSDatabase &inSSDatabase, uint32 inKeyAttr, + const CssmData *inKeyLabel); + SSKey(SSDLSession &session, CssmKey &ioKey, SSDatabase &inSSDatabase, + const SSUniqueRecord &uniqueId, CSSM_DB_RECORDTYPE recordType, + CssmData &keyBlob); + + virtual ~SSKey(); + void free(const AccessCredentials *accessCred, CssmKey &ioKey, + CSSM_BOOL deleteKey); + + SecurityServer::ClientSession &clientSession(); + + /* Might return SecurityServer::noKey if the key has not yet been instantiated. */ + SecurityServer::KeyHandle optionalKeyHandle() const; + + /* Will instantiate the key if needed. */ + SecurityServer::KeyHandle keyHandle(); + + // ACL retrieval and change operations + void getOwner(CSSM_ACL_OWNER_PROTOTYPE &owner, Allocator &allocator); + void changeOwner(const AccessCredentials &accessCred, + const AclOwnerPrototype &newOwner); + void getAcl(const char *selectionTag, uint32 &numberOfAclInfos, + AclEntryInfo *&aclInfos, Allocator &allocator); + void changeAcl(const AccessCredentials &accessCred, + const AclEdit &aclEdit); + + // Reencode and write to disk if we are a persistant key. + void didChangeAcl(); + +private: + Allocator &mAllocator; + SecurityServer::KeyHandle mKeyHandle; + SSDatabase mSSDatabase; + SSUniqueRecord mUniqueId; + CSSM_DB_RECORDTYPE mRecordType; + SecurityServer::ClientSession &mClientSession; +}; + + +#endif // _H_SSKEY_ diff --git a/libsecurity_apple_cspdl/libsecurity_apple_cspdl.xcodeproj/project.pbxproj b/libsecurity_apple_cspdl/libsecurity_apple_cspdl.xcodeproj/project.pbxproj new file mode 100644 index 00000000..090b2ba2 --- /dev/null +++ b/libsecurity_apple_cspdl/libsecurity_apple_cspdl.xcodeproj/project.pbxproj @@ -0,0 +1,335 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 4C6AA9E30535FDA6006E3284 /* CSPDLDatabase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C6AA9D00535FDA6006E3284 /* CSPDLDatabase.cpp */; }; + 4C6AA9E40535FDA6006E3284 /* CSPDLDatabase.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C6AA9D10535FDA6006E3284 /* CSPDLDatabase.h */; }; + 4C6AA9E50535FDA6006E3284 /* CSPDLPlugin.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C6AA9D20535FDA6006E3284 /* CSPDLPlugin.cpp */; }; + 4C6AA9E60535FDA6006E3284 /* CSPDLPlugin.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C6AA9D30535FDA6006E3284 /* CSPDLPlugin.h */; }; + 4C6AA9E70535FDA6006E3284 /* SSContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C6AA9D40535FDA6006E3284 /* SSContext.cpp */; }; + 4C6AA9E80535FDA6006E3284 /* SSContext.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C6AA9D50535FDA6006E3284 /* SSContext.h */; }; + 4C6AA9E90535FDA6006E3284 /* SSCSPDLSession.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C6AA9D60535FDA6006E3284 /* SSCSPDLSession.cpp */; }; + 4C6AA9EA0535FDA6006E3284 /* SSCSPDLSession.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C6AA9D70535FDA6006E3284 /* SSCSPDLSession.h */; }; + 4C6AA9EB0535FDA6006E3284 /* SSCSPSession.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C6AA9D80535FDA6006E3284 /* SSCSPSession.cpp */; }; + 4C6AA9EC0535FDA6006E3284 /* SSCSPSession.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C6AA9D90535FDA6006E3284 /* SSCSPSession.h */; }; + 4C6AA9ED0535FDA6006E3284 /* SSDatabase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C6AA9DA0535FDA6006E3284 /* SSDatabase.cpp */; }; + 4C6AA9EE0535FDA6006E3284 /* SSDatabase.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C6AA9DB0535FDA6006E3284 /* SSDatabase.h */; }; + 4C6AA9EF0535FDA6006E3284 /* SSDLSession.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C6AA9DC0535FDA6006E3284 /* SSDLSession.cpp */; }; + 4C6AA9F00535FDA6006E3284 /* SSDLSession.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C6AA9DD0535FDA6006E3284 /* SSDLSession.h */; }; + 4C6AA9F10535FDA6006E3284 /* SSFactory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C6AA9DE0535FDA6006E3284 /* SSFactory.cpp */; }; + 4C6AA9F20535FDA6006E3284 /* SSFactory.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C6AA9DF0535FDA6006E3284 /* SSFactory.h */; }; + 4C6AA9F30535FDA6006E3284 /* SSKey.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C6AA9E00535FDA6006E3284 /* SSKey.cpp */; }; + 4C6AA9F40535FDA6006E3284 /* SSKey.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C6AA9E10535FDA6006E3284 /* SSKey.h */; }; + C2196B5D053B598C005808D4 /* AppleCSPDLBuiltin.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2196B5C053B598C005808D4 /* AppleCSPDLBuiltin.cpp */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 182BB348146F10F6000BF1F3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 184460D8146E7DF300B12992 /* libsecurity_cdsa_plugin.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = C2C38A530535EDE600D7421F; + remoteInfo = libsecurity_cdsa_plugin_generate; + }; + 184460DD146E7DF300B12992 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 184460D8146E7DF300B12992 /* libsecurity_cdsa_plugin.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 4CA1FEBE052A3C8100F22E42; + remoteInfo = libsecurity_cdsa_plugin; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 184460CC146E7B7B00B12992 /* base.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = base.xcconfig; sourceTree = ""; }; + 184460CD146E7B7B00B12992 /* debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = debug.xcconfig; sourceTree = ""; }; + 184460CE146E7B7B00B12992 /* lib.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = lib.xcconfig; sourceTree = ""; }; + 184460CF146E7B7B00B12992 /* release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = release.xcconfig; sourceTree = ""; }; + 184460D8146E7DF300B12992 /* libsecurity_cdsa_plugin.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libsecurity_cdsa_plugin.xcodeproj; path = ../libsecurity_cdsa_plugin/libsecurity_cdsa_plugin.xcodeproj; sourceTree = ""; }; + 4094B0AB057EA69D00B44BCC /* cspdl_common.mdsinfo */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.xml; path = cspdl_common.mdsinfo; sourceTree = ""; }; + 4094B0AC057EA69D00B44BCC /* cspdl_csp_capabilities.mdsinfo */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.xml; path = cspdl_csp_capabilities.mdsinfo; sourceTree = ""; }; + 4094B0AD057EA69D00B44BCC /* cspdl_csp_primary.mdsinfo */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.xml; path = cspdl_csp_primary.mdsinfo; sourceTree = ""; }; + 4094B0AE057EA69D00B44BCC /* cspdl_dl_primary.mdsinfo */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.xml; path = cspdl_dl_primary.mdsinfo; sourceTree = ""; }; + 4C6AA9CF0535FDA6006E3284 /* AppleCSPDLPlugin.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = AppleCSPDLPlugin.cpp; sourceTree = ""; }; + 4C6AA9D00535FDA6006E3284 /* CSPDLDatabase.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = CSPDLDatabase.cpp; sourceTree = ""; }; + 4C6AA9D10535FDA6006E3284 /* CSPDLDatabase.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = CSPDLDatabase.h; sourceTree = ""; }; + 4C6AA9D20535FDA6006E3284 /* CSPDLPlugin.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = CSPDLPlugin.cpp; sourceTree = ""; }; + 4C6AA9D30535FDA6006E3284 /* CSPDLPlugin.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = CSPDLPlugin.h; sourceTree = ""; }; + 4C6AA9D40535FDA6006E3284 /* SSContext.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SSContext.cpp; sourceTree = ""; }; + 4C6AA9D50535FDA6006E3284 /* SSContext.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SSContext.h; sourceTree = ""; }; + 4C6AA9D60535FDA6006E3284 /* SSCSPDLSession.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SSCSPDLSession.cpp; sourceTree = ""; }; + 4C6AA9D70535FDA6006E3284 /* SSCSPDLSession.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SSCSPDLSession.h; sourceTree = ""; }; + 4C6AA9D80535FDA6006E3284 /* SSCSPSession.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SSCSPSession.cpp; sourceTree = ""; }; + 4C6AA9D90535FDA6006E3284 /* SSCSPSession.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SSCSPSession.h; sourceTree = ""; }; + 4C6AA9DA0535FDA6006E3284 /* SSDatabase.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SSDatabase.cpp; sourceTree = ""; }; + 4C6AA9DB0535FDA6006E3284 /* SSDatabase.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SSDatabase.h; sourceTree = ""; }; + 4C6AA9DC0535FDA6006E3284 /* SSDLSession.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SSDLSession.cpp; sourceTree = ""; }; + 4C6AA9DD0535FDA6006E3284 /* SSDLSession.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SSDLSession.h; sourceTree = ""; }; + 4C6AA9DE0535FDA6006E3284 /* SSFactory.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SSFactory.cpp; sourceTree = ""; }; + 4C6AA9DF0535FDA6006E3284 /* SSFactory.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SSFactory.h; sourceTree = ""; }; + 4C6AA9E00535FDA6006E3284 /* SSKey.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SSKey.cpp; sourceTree = ""; }; + 4C6AA9E10535FDA6006E3284 /* SSKey.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SSKey.h; sourceTree = ""; }; + 4CA1FEBE052A3C8100F22E42 /* libsecurity_apple_cspdl.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libsecurity_apple_cspdl.a; sourceTree = BUILT_PRODUCTS_DIR; }; + C2196B5C053B598C005808D4 /* AppleCSPDLBuiltin.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = AppleCSPDLBuiltin.cpp; path = lib/AppleCSPDLBuiltin.cpp; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 4CA1FEBB052A3C8100F22E42 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 184460CB146E7B7B00B12992 /* config */ = { + isa = PBXGroup; + children = ( + 184460CC146E7B7B00B12992 /* base.xcconfig */, + 184460CD146E7B7B00B12992 /* debug.xcconfig */, + 184460CE146E7B7B00B12992 /* lib.xcconfig */, + 184460CF146E7B7B00B12992 /* release.xcconfig */, + ); + name = config; + path = ../config; + sourceTree = ""; + }; + 184460D9146E7DF300B12992 /* Products */ = { + isa = PBXGroup; + children = ( + 184460DE146E7DF300B12992 /* libsecurity_cdsa_plugin.a */, + ); + name = Products; + sourceTree = ""; + }; + 4094B0AA057EA69D00B44BCC /* mds */ = { + isa = PBXGroup; + children = ( + 4094B0AB057EA69D00B44BCC /* cspdl_common.mdsinfo */, + 4094B0AC057EA69D00B44BCC /* cspdl_csp_capabilities.mdsinfo */, + 4094B0AD057EA69D00B44BCC /* cspdl_csp_primary.mdsinfo */, + 4094B0AE057EA69D00B44BCC /* cspdl_dl_primary.mdsinfo */, + ); + path = mds; + sourceTree = SOURCE_ROOT; + }; + 4C6AA9CE0535FDA6006E3284 /* lib */ = { + isa = PBXGroup; + children = ( + 4C6AA9CF0535FDA6006E3284 /* AppleCSPDLPlugin.cpp */, + 4C6AA9D00535FDA6006E3284 /* CSPDLDatabase.cpp */, + 4C6AA9D10535FDA6006E3284 /* CSPDLDatabase.h */, + 4C6AA9D20535FDA6006E3284 /* CSPDLPlugin.cpp */, + 4C6AA9D30535FDA6006E3284 /* CSPDLPlugin.h */, + 4C6AA9D40535FDA6006E3284 /* SSContext.cpp */, + 4C6AA9D50535FDA6006E3284 /* SSContext.h */, + 4C6AA9D60535FDA6006E3284 /* SSCSPDLSession.cpp */, + 4C6AA9D70535FDA6006E3284 /* SSCSPDLSession.h */, + 4C6AA9D80535FDA6006E3284 /* SSCSPSession.cpp */, + 4C6AA9D90535FDA6006E3284 /* SSCSPSession.h */, + 4C6AA9DA0535FDA6006E3284 /* SSDatabase.cpp */, + 4C6AA9DB0535FDA6006E3284 /* SSDatabase.h */, + 4C6AA9DC0535FDA6006E3284 /* SSDLSession.cpp */, + 4C6AA9DD0535FDA6006E3284 /* SSDLSession.h */, + 4C6AA9DE0535FDA6006E3284 /* SSFactory.cpp */, + 4C6AA9DF0535FDA6006E3284 /* SSFactory.h */, + 4C6AA9E00535FDA6006E3284 /* SSKey.cpp */, + 4C6AA9E10535FDA6006E3284 /* SSKey.h */, + ); + path = lib; + sourceTree = ""; + }; + 4CA1FEA7052A3C3800F22E42 = { + isa = PBXGroup; + children = ( + 184460D8146E7DF300B12992 /* libsecurity_cdsa_plugin.xcodeproj */, + 4C6AA9CE0535FDA6006E3284 /* lib */, + 184460CB146E7B7B00B12992 /* config */, + 4094B0AA057EA69D00B44BCC /* mds */, + 4CA1FEBF052A3C8100F22E42 /* Products */, + C2196B5C053B598C005808D4 /* AppleCSPDLBuiltin.cpp */, + ); + sourceTree = ""; + }; + 4CA1FEBF052A3C8100F22E42 /* Products */ = { + isa = PBXGroup; + children = ( + 4CA1FEBE052A3C8100F22E42 /* libsecurity_apple_cspdl.a */, + ); + name = Products; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 4CA1FEB9052A3C8100F22E42 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 4C6AA9E40535FDA6006E3284 /* CSPDLDatabase.h in Headers */, + 4C6AA9E60535FDA6006E3284 /* CSPDLPlugin.h in Headers */, + 4C6AA9E80535FDA6006E3284 /* SSContext.h in Headers */, + 4C6AA9EA0535FDA6006E3284 /* SSCSPDLSession.h in Headers */, + 4C6AA9EC0535FDA6006E3284 /* SSCSPSession.h in Headers */, + 4C6AA9EE0535FDA6006E3284 /* SSDatabase.h in Headers */, + 4C6AA9F00535FDA6006E3284 /* SSDLSession.h in Headers */, + 4C6AA9F20535FDA6006E3284 /* SSFactory.h in Headers */, + 4C6AA9F40535FDA6006E3284 /* SSKey.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 4CA1FEBD052A3C8100F22E42 /* libsecurity_apple_cspdl */ = { + isa = PBXNativeTarget; + buildConfigurationList = C27AD2630987FCDC001272E0 /* Build configuration list for PBXNativeTarget "libsecurity_apple_cspdl" */; + buildPhases = ( + 4CA1FEB9052A3C8100F22E42 /* Headers */, + 4CA1FEBA052A3C8100F22E42 /* Sources */, + 4CA1FEBB052A3C8100F22E42 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + 182BB349146F10F6000BF1F3 /* PBXTargetDependency */, + ); + name = libsecurity_apple_cspdl; + productInstallPath = /usr/local/lib; + productName = libsecurity_apple_cspdl; + productReference = 4CA1FEBE052A3C8100F22E42 /* libsecurity_apple_cspdl.a */; + productType = "com.apple.product-type.library.static"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 4CA1FEAB052A3C3800F22E42 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0420; + }; + buildConfigurationList = C27AD26A0987FCDC001272E0 /* Build configuration list for PBXProject "libsecurity_apple_cspdl" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 1; + knownRegions = ( + English, + Japanese, + French, + German, + ); + mainGroup = 4CA1FEA7052A3C3800F22E42; + productRefGroup = 4CA1FEBF052A3C8100F22E42 /* Products */; + projectDirPath = ""; + projectReferences = ( + { + ProductGroup = 184460D9146E7DF300B12992 /* Products */; + ProjectRef = 184460D8146E7DF300B12992 /* libsecurity_cdsa_plugin.xcodeproj */; + }, + ); + projectRoot = ""; + targets = ( + 4CA1FEBD052A3C8100F22E42 /* libsecurity_apple_cspdl */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXReferenceProxy section */ + 184460DE146E7DF300B12992 /* libsecurity_cdsa_plugin.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libsecurity_cdsa_plugin.a; + remoteRef = 184460DD146E7DF300B12992 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; +/* End PBXReferenceProxy section */ + +/* Begin PBXSourcesBuildPhase section */ + 4CA1FEBA052A3C8100F22E42 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4C6AA9E30535FDA6006E3284 /* CSPDLDatabase.cpp in Sources */, + 4C6AA9E50535FDA6006E3284 /* CSPDLPlugin.cpp in Sources */, + 4C6AA9E70535FDA6006E3284 /* SSContext.cpp in Sources */, + 4C6AA9E90535FDA6006E3284 /* SSCSPDLSession.cpp in Sources */, + 4C6AA9EB0535FDA6006E3284 /* SSCSPSession.cpp in Sources */, + 4C6AA9ED0535FDA6006E3284 /* SSDatabase.cpp in Sources */, + 4C6AA9EF0535FDA6006E3284 /* SSDLSession.cpp in Sources */, + 4C6AA9F10535FDA6006E3284 /* SSFactory.cpp in Sources */, + 4C6AA9F30535FDA6006E3284 /* SSKey.cpp in Sources */, + C2196B5D053B598C005808D4 /* AppleCSPDLBuiltin.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 182BB349146F10F6000BF1F3 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = libsecurity_cdsa_plugin_generate; + targetProxy = 182BB348146F10F6000BF1F3 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + C27AD2640987FCDC001272E0 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 184460CD146E7B7B00B12992 /* debug.xcconfig */; + buildSettings = { + }; + name = Debug; + }; + C27AD2690987FCDC001272E0 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 184460CF146E7B7B00B12992 /* release.xcconfig */; + buildSettings = { + }; + name = Release; + }; + C27AD26B0987FCDC001272E0 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 184460CE146E7B7B00B12992 /* lib.xcconfig */; + buildSettings = { + }; + name = Debug; + }; + C27AD2700987FCDC001272E0 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 184460CE146E7B7B00B12992 /* lib.xcconfig */; + buildSettings = { + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + C27AD2630987FCDC001272E0 /* Build configuration list for PBXNativeTarget "libsecurity_apple_cspdl" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C27AD2640987FCDC001272E0 /* Debug */, + C27AD2690987FCDC001272E0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C27AD26A0987FCDC001272E0 /* Build configuration list for PBXProject "libsecurity_apple_cspdl" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C27AD26B0987FCDC001272E0 /* Debug */, + C27AD2700987FCDC001272E0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 4CA1FEAB052A3C3800F22E42 /* Project object */; +} diff --git a/libsecurity_apple_cspdl/mds/cspdl_common.mdsinfo b/libsecurity_apple_cspdl/mds/cspdl_common.mdsinfo new file mode 100644 index 00000000..b73d72e5 --- /dev/null +++ b/libsecurity_apple_cspdl/mds/cspdl_common.mdsinfo @@ -0,0 +1,30 @@ + + + + + BuiltIn + + CDSAVersion + 2.0 + Desc + Apple built-in CSPDL + DynamicFlag + + MdsFileDescription + Built-in CSPDL Common info + MdsFileType + PluginCommon + ModuleID + {87191ca3-0fc9-11d4-849a-000502b52122} + ModuleName + AppleCSPDL + MultiThreadFlag + + ProductVersion + 1.0 + ServiceMask + CSSM_SERVICE_CSP | CSSM_SERVICE_DL + Path + *AppleCSPDL + + diff --git a/libsecurity_apple_cspdl/mds/cspdl_csp_capabilities.mdsinfo b/libsecurity_apple_cspdl/mds/cspdl_csp_capabilities.mdsinfo new file mode 100644 index 00000000..d4dd6b26 --- /dev/null +++ b/libsecurity_apple_cspdl/mds/cspdl_csp_capabilities.mdsinfo @@ -0,0 +1,18 @@ + + + + + Capabilities + file:csp_capabilities_common.mds + MdsFileDescription + Built-in CSPDL CSP Capabilities + MdsFileType + PluginSpecific + MdsRecordType + MDS_CDSADIR_CSP_CAPABILITY_RECORDTYPE + ModuleID + {87191ca3-0fc9-11d4-849a-000502b52122} + SSID + 0 + + diff --git a/libsecurity_apple_cspdl/mds/cspdl_csp_primary.mdsinfo b/libsecurity_apple_cspdl/mds/cspdl_csp_primary.mdsinfo new file mode 100644 index 00000000..bf75fc69 --- /dev/null +++ b/libsecurity_apple_cspdl/mds/cspdl_csp_primary.mdsinfo @@ -0,0 +1,61 @@ + + + + + AclSubjectTypes + + CSSM_ACL_SUBJECT_TYPE_PASSWORD + CSSM_ACL_SUBJECT_TYPE_PROTECTED_PASSWORD + CSSM_ACL_SUBJECT_TYPE_PUBLIC_KEY + CSSM_ACL_SUBJECT_TYPE_CODE_SIGNATURE + CSSM_ACL_SUBJECT_TYPE_KEYCHAIN_PROMPT + + AuthTags + + CSSM_ACL_AUTHORIZATION_ANY + + CspCustomFlags + 0 + CspFlags + CSSM_CSP_STORES_PRIVATE_KEYS | CSSM_CSP_STORES_PUBLIC_KEYS | CSSM_CSP_STORES_SESSION_KEYS + CspType + CSSM_CSP_SOFTWARE + MdsFileDescription + Built-in CSPDL CSP Primary info + MdsFileType + PluginSpecific + MdsRecordType + MDS_CDSADIR_CSP_PRIMARY_RECORDTYPE + ModuleID + {87191ca3-0fc9-11d4-849a-000502b52122} + ModuleName + AppleCSPDL + ProductVersion + 1.0 + SSID + 0 + SampleTypes + + CSSM_SAMPLE_TYPE_PASSWORD + CSSM_SAMPLE_TYPE_HASHED_PASSWORD + CSSM_SAMPLE_TYPE_PROTECTED_PASSWORD + CSSM_SAMPLE_TYPE_PROMPTED_PASSWORD + CSSM_SAMPLE_TYPE_SIGNED_NONCE + CSSM_SAMPLE_TYPE_SIGNED_SECRET + CSSM_SAMPLE_TYPE_BIOMETRIC + CSSM_SAMPLE_TYPE_PROTECTED_BIOMETRIC + CSSM_SAMPLE_TYPE_PROMPTED_BIOMETRIC + CSSM_SAMPLE_TYPE_THRESHOLD + CSSM_SAMPLE_TYPE_KEYCHAIN_PROMPT + CSSM_SAMPLE_TYPE_KEYCHAIN_LOCK + CSSM_SAMPLE_TYPE_KEYCHAIN_CHANGE_LOCK + CSSM_SAMPLE_TYPE_PROCESS + CSSM_SAMPLE_TYPE_COMMENT + CSSM_SAMPLE_TYPE_RETRY_ID + + UseeTags + + Vendor + Apple Computer, Inc. + + diff --git a/libsecurity_apple_cspdl/mds/cspdl_dl_primary.mdsinfo b/libsecurity_apple_cspdl/mds/cspdl_dl_primary.mdsinfo new file mode 100644 index 00000000..5d803313 --- /dev/null +++ b/libsecurity_apple_cspdl/mds/cspdl_dl_primary.mdsinfo @@ -0,0 +1,73 @@ + + + + + AclSubjectTypes + + CSSM_ACL_SUBJECT_TYPE_PASSWORD + CSSM_ACL_SUBJECT_TYPE_PROTECTED_PASSWORD + CSSM_ACL_SUBJECT_TYPE_PUBLIC_KEY + CSSM_ACL_SUBJECT_TYPE_CODE_SIGNATURE + CSSM_ACL_SUBJECT_TYPE_KEYCHAIN_PROMPT + + AuthTags + + CSSM_ACL_AUTHORIZATION_ANY + + ConjunctiveOps + + CSSM_DB_NONE + CSSM_DB_AND + CSSM_DB_OR + + DLType + CSSM_DL_FFS + MdsFileDescription + Built-in CSPDL DL Primary info + MdsFileType + PluginSpecific + MdsRecordType + MDS_CDSADIR_DL_PRIMARY_RECORDTYPE + ModuleID + {87191ca3-0fc9-11d4-849a-000502b52122} + ModuleName + AppleCSPDL + ProductVersion + 1.0 + QueryLimitsFlag + 0 + RelationalOps + + CSSM_DB_EQUAL + CSSM_DB_LESS_THAN + CSSM_DB_GREATER_THAN + CSSM_DB_CONTAINS_FINAL_SUBSTRING + CSSM_DB_CONTAINS_INITIAL_SUBSTRING + CSSM_DB_CONTAINS + + + SSID + 0 + SampleTypes + + CSSM_SAMPLE_TYPE_PASSWORD + CSSM_SAMPLE_TYPE_HASHED_PASSWORD + CSSM_SAMPLE_TYPE_PROTECTED_PASSWORD + CSSM_SAMPLE_TYPE_PROMPTED_PASSWORD + CSSM_SAMPLE_TYPE_SIGNED_NONCE + CSSM_SAMPLE_TYPE_SIGNED_SECRET + CSSM_SAMPLE_TYPE_BIOMETRIC + CSSM_SAMPLE_TYPE_PROTECTED_BIOMETRIC + CSSM_SAMPLE_TYPE_PROMPTED_BIOMETRIC + CSSM_SAMPLE_TYPE_THRESHOLD + CSSM_SAMPLE_TYPE_KEYCHAIN_PROMPT + CSSM_SAMPLE_TYPE_KEYCHAIN_LOCK + CSSM_SAMPLE_TYPE_KEYCHAIN_CHANGE_LOCK + CSSM_SAMPLE_TYPE_PROCESS + CSSM_SAMPLE_TYPE_COMMENT + CSSM_SAMPLE_TYPE_RETRY_ID + + Vendor + Apple Computer, Inc. + + diff --git a/libsecurity_apple_file_dl/Info-security_apple_file_dl.plist b/libsecurity_apple_file_dl/Info-security_apple_file_dl.plist new file mode 100644 index 00000000..0c67376e --- /dev/null +++ b/libsecurity_apple_file_dl/Info-security_apple_file_dl.plist @@ -0,0 +1,5 @@ + + + + + diff --git a/libsecurity_apple_file_dl/TODO b/libsecurity_apple_file_dl/TODO new file mode 100644 index 00000000..e8f49125 --- /dev/null +++ b/libsecurity_apple_file_dl/TODO @@ -0,0 +1,49 @@ +* Make the pAttributeInfo and pIndexInfo arguments to CSSM_DL_CreateRelation optional (DONE). + +* Enhance POD wrappers and use them everywhere (DONE for insert still needs work for get). + +* Implement Indexes + +* Implement unique index checks for dataInsert and dataModify + +* Add unique index info to UNIQUE_RECORD structures. + +* Implement KEY items (AppleCSPDL). + +* Clean up usage of ReadSection::at(uint32) vs. ReadSection::operator[](uint32) + +* Fix AtomicFile for NFS and ASIP (Use alternative locking mechanism). + +* Implement ACL evaluation for Db access. + +* Implement ACL APIs. + +* Make DbModifier thread safe again. + +* Cleanup Query objects when DbContext is destroyed (register them with the context). + +* What if we open a DB that is being created? Currently we get back DL_DATABASE_CORRUPT + should this become DL_DATABASE_DOES_NOT_EXIST? + +* When using CssmOid attribute names make sure to deep copy the CssmOids data (DONE). + +* Implement SelectionPredicates completely + To make DataGetFirst and DataGetNext actually work (DONE). + +* Implement CreateRelation (DONE) + +* Implement DataModify (DONE, now with correct semantics -- CB) + +* In DataModify, check that RecordType matches that in the UniqueRecordId. + +* Store index data when creating tables and databases. + +* Add write buffering in AtomicFile to increase performance; flush buffer before seek. + +* Make sure that automatically-assigned attribute ids don't shadow ones passed in explicitly. + +* Performance: Avoid reconstructing DbVersion after a write (w/o a schema change) when we + could derive it from the DbModifier. Only if version is as expected (i.e. no other writes + in the meantime) + +* Add fsync() to make sure AtomicFile is written before rename. diff --git a/libsecurity_apple_file_dl/doc/FORMAT b/libsecurity_apple_file_dl/doc/FORMAT new file mode 100644 index 00000000..bae9292f --- /dev/null +++ b/libsecurity_apple_file_dl/doc/FORMAT @@ -0,0 +1,153 @@ +Some notes of the format of DL files: + + + +DL file format: + +All offsets are relative to the start of the section they are in. +All fileds are uint32 (4 bytes) unless otherwise specified. All other fields are aligned on 4 bytes boundries. + +Header Section + Magic + File Format Version Number + Auth Section Offset + Schema Section Offset + +Auth Section + Auth Info Size + Auth Info Data + +Schema Section # This section is always read entirely into memory + Schema Section Size (uint32) + Tables + Table Count (uint32) + Table Offset 0 # Relative to start of Schema Section + Table Offset 1 + ... + Table Offset N + +# Information about parsing modules is read directly from the meta tables +Table Section + Table Section Size + Table ID (uint32) + Records Count # Number of Records in record section. + Record 0 Offset # Relative to start of Table Section. + Index SubSection Offset # Relative to start of Table Section + Head of Free List # Table Section relative first free + # recordNumber slot (with bit 0 set) + # Or 0 if there are no free records + Record Number Count # Start of range of unused record numbers + Record 0 offset # Relative to start of Table Section. + Record 1 offset + Record 2 freelist # If Bit zero is set this is Table Section + # relative offset to next free recordNumber + # 0 indicates the last free record slot. + ... + Record n offset + Record + Record Size # Rounded up to nearest mulitple of 4 + Record Number + Creation File Version + Record Version + Data Size + SemanticInformation + Attribute 0 Offset + Attribute 1 Offset + Attribute 2 Offset + ... + Attribute m Offset + Data + Data + Attribute 0 + Size + Data + Attribute 1 + Value + ... + Attribute m + Value Count + Value 0 + Value 1 + ... + Value p + Record + ... + Record + Index SubSection + Index SubSection Size + Index TOC # This is part of the Schema + Record Type + Attribute Type + Index Offset + Index 1 + Index Size + Index Offsets + Index Offset Count + Index Data 1 Offset + Index Data 2 Offset + ... + Index Data m OFFSET + Index Data + Index Data 1 + Record Offset + Attribute Size + Attribute Data + Index Data 2 + ... + Index Data N + Index 2 + ... + Index n + +Version Section # Maintained by AtomicFile code + 4 byte version number + +old Schema Section # This section is always read entirely into memory + Schema Section Size (uint32) + Releations + Relation Count (uint32) + Relation + Relation ID (uint32) + Record Section Offset + Relation Name Size + Relation Name Data + Attributes + Attribute Count (uint32) + Attribute + Releation ID (uint32) + Attribute ID (uint32) + Attribute Format (uint32) + Attribute Name Format (uint32) + Attribute Name Size + Attribute Name Data + Attribute Name ID Size + Attribute Name ID Data + ParsingModule + Parsion Module Present (bool) + Module ID (GUID) + SSID (uint32) + SubService Type (uint32) + Addin Version Major (uint32) + Addin Version Minor (uint32) + Attribute + ... + Attribute + Indexes + Index Count (uint32) + Index + Relation ID (uint32) + Index ID (uint32) + Index Type (uint32) + Indexed Data Location (uint32) + Index Attribute Count (uint32) + Attribute ID (uint32) + Attribute ID (uint32) + ... + Attribute ID (uint32) + Index + ... + Index + Relation + ... + Relation + diff --git a/libsecurity_apple_file_dl/doc/ISSUES b/libsecurity_apple_file_dl/doc/ISSUES new file mode 100644 index 00000000..4dd01a31 --- /dev/null +++ b/libsecurity_apple_file_dl/doc/ISSUES @@ -0,0 +1,61 @@ +ISSUES with cdsa verson 2 Datastore Library + +DL_DataGetFromUniqueRecordId + +* Which value of CSSM_QUERYFLAGS should this call assume? In other words if fetching the Data of a Key item should this call return a reference key or a raw key. + +* What if the record has been modified by another caller since it was last retrieved. This call should be able to update the CSSM_UNIQUE_RECORD_PTR passed in. Or otherwise indicate that the record that a particular attribute is being requested for has changed. + +DL_DbCreate v/s DL_CreateRelation + +* Why not change CSSM_DBINFO to use the same data structures as DL_CreateRelation does. Currently CSSM_DBINFO uses CSSM_DB_RECORD_ATTRIBUTE_INFO, CSSM_DB_RECORD_INDEX_INFO and CSSM_DB_PARSING_MODULE_INFO the first 2 contains less information than the CSSM_DB_SCHEMA_ATTRIBUTE_INFO and CSSM_DB_SCHEMA_INDEX_INFO fields used by DL_CreateRelation. There is no equivalent for the information provided at Database creation time containd in the CSSM_DB_PARSING_MODULE_INFO inside the CSSM_DBINFO. + +I purpose we change everything to using the same data structures (CSSM_DB_SCHEMA_ATTRIBUTE_INFO and CSSM_DB_SCHEMA_INDEX_INFO since they are richer). This would make the CSSM_DB_RECORD_ATTRIBUTE_INFO structure obsolete. + +Also note that CSSM_DB_SCHEMA_ATTRIBUTE_INFO does not contain an CSSM_DB_ATTRIBUTE_NAME_FORMAT field and neither should the CSSM_DB_SCHEMA_ATTRIBUTE_INFO relation since each attribute will have the 3 types of names given at creation time. The CSSM_DB_ATTRIBUTE_NAME_FORMAT need only be used to retrieve an attribute using a particular name format. + +DL_DataGetFirst + +* CSSM_SELECTION_PREDICATE (which is part of CSSM_QUERY) contains a CSSM_DB_ATTRIBUTE_DATA. What are the intended semantics for a CSSM_SELECTION_PREDICATE containing a CSSM_DB_ATTRIBUTE_DATA with NumberOfValues not equal to 1? + +DL_DataGetFirst, DL_DataGetNext and DL_DataGetFromUniqueRecordId + +* The AttributeFormat specified when retrieving an attribute must match that in the schema. + -or- +* When retrieving an attribute the AttributeFormat for that attribute is returned. + +From the description of these calls it is not clear which of the two options above is the intended one. I vote for the second option. + +DL_DataInsert and DL_DataModify + +* The AttributeFormat specified when specifying an attribute must match that in the schema otherwise CSSMERR_DL_INCOMPATIBLE_FIELD_FORMAT is returned. + +This should be a added to the description of these calls. + +DL_DataDelete + +* From the description of this function it would seem that is does an implicit CSSM_DL_FreeUniqueRecord(). Is this correct? + + +General + +* What is the difference between a single valued and multi-valued attribute? How do you indicate that an attribute is to be multi-valued? + +These terms are used in the description of DL_DataModify and in other places. However there is nothing in the schema to indicate whether an attribute is single valued or multi valued. If an attribute has one value and DL_DataModify is called with the CSSM_DB_MODIFY_ATTRIBUTE_ADD ModifyMode it is unclear whether the current value should be replaced with a new one or the passed in value should be added to the values of the attribute (bring the NumberOfValues for that attribute up to 2). + +How is this supposed to (or intended to) work? + +Error codes + +* When for example passing a value for a CSSM_DB_ATTRIBUTE_FORMAT or CSSM_DB_ATTRIBUTE_FORMAT_UINT32 with a length other than 1 2 or 4 we need an error code to indicate this. I suggest something like: + + #define CSSMERR_DL_INVALID_VALUE (CSSM_DL_BASE_DL_ERROR + 47) + + A value specified for an attribute was not of the correct form. + + +New Issues: + +Page 471: +CSSM_DB_CONJUNCTIVE +What is the intented semantic of CSSM_DB_NONE? It only makes sense when a single SelectionPredicate is specified in which case using either CSSM_DB_AND or CSSM_DB_OR would do just fine instead. diff --git a/libsecurity_apple_file_dl/lib/AppleDLBuiltin.cpp b/libsecurity_apple_file_dl/lib/AppleDLBuiltin.cpp new file mode 100644 index 00000000..1c022fc2 --- /dev/null +++ b/libsecurity_apple_file_dl/lib/AppleDLBuiltin.cpp @@ -0,0 +1,32 @@ +/* + * 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 obtai +n + * 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. + */ + + +// +// Produce the "genuine plugin version" of the Apple "file DL" +// +#include + + +// +// Create the plugin object and generate the C layer hookup +// +static ModuleNexus plugin; + +#define SPINAME(s) s ## __apple_file_dl +#include diff --git a/libsecurity_apple_file_dl/lib/AppleDLPlugin.cpp b/libsecurity_apple_file_dl/lib/AppleDLPlugin.cpp new file mode 100644 index 00000000..3425ef45 --- /dev/null +++ b/libsecurity_apple_file_dl/lib/AppleDLPlugin.cpp @@ -0,0 +1,31 @@ +/* + * 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 obtai +n + * 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. + */ + + +// +// Produce the "genuine plugin version" of the Apple "file DL" +// +#include + + +// +// Create the plugin object and generate the C layer hookup +// +ModuleNexus plugin; + +#include diff --git a/libsecurity_apple_file_dl/lib/AppleFileDL.cpp b/libsecurity_apple_file_dl/lib/AppleFileDL.cpp new file mode 100644 index 00000000..be3e9020 --- /dev/null +++ b/libsecurity_apple_file_dl/lib/AppleFileDL.cpp @@ -0,0 +1,81 @@ +/* + * 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. + */ + + +// +// AppleFileDL.cpp - File Based DL plug-in module. +// +#include "AppleFileDL.h" + +#include + + +// Names and IDs of tables used in a DL database + +static const AppleDatabaseTableName kTableNames[] = { + { CSSM_DL_DB_SCHEMA_INFO, "CSSM_DL_DB_SCHEMA_INFO" }, + { CSSM_DL_DB_SCHEMA_ATTRIBUTES, "CSSM_DL_DB_SCHEMA_ATTRIBUTES" }, + { CSSM_DL_DB_SCHEMA_INDEXES, "CSSM_DL_DB_SCHEMA_INDEXES" }, + { CSSM_DL_DB_SCHEMA_PARSING_MODULE, "CSSM_DL_DB_SCHEMA_PARSING_MODULE" }, + { CSSM_DL_DB_RECORD_CERT, "CSSM_DL_DB_RECORD_CERT" }, + { CSSM_DL_DB_RECORD_CRL, "CSSM_DL_DB_RECORD_CRL" }, + { CSSM_DL_DB_RECORD_POLICY, "CSSM_DL_DB_RECORD_POLICY" }, + { CSSM_DL_DB_RECORD_GENERIC, "CSSM_DL_DB_RECORD_GENERIC" }, + { CSSM_DL_DB_RECORD_PUBLIC_KEY, "CSSM_DL_DB_RECORD_PUBLIC_KEY" }, + { CSSM_DL_DB_RECORD_PRIVATE_KEY, "CSSM_DL_DB_RECORD_PRIVATE_KEY" }, + { CSSM_DL_DB_RECORD_SYMMETRIC_KEY, "CSSM_DL_DB_RECORD_SYMMETRIC_KEY" }, + { ~0UL, NULL } +}; + +// +// Make and break the plugin object +// +AppleFileDL::AppleFileDL() + : mDatabaseManager(kTableNames) +{ +} + +AppleFileDL::~AppleFileDL() +{ +} + + +// +// Create a new plugin session, our way +// +PluginSession *AppleFileDL::makeSession(CSSM_MODULE_HANDLE handle, + const CSSM_VERSION &version, + uint32 subserviceId, + CSSM_SERVICE_TYPE subserviceType, + CSSM_ATTACH_FLAGS attachFlags, + const CSSM_UPCALLS &upcalls) +{ + switch (subserviceType) { + case CSSM_SERVICE_DL: + return new DLPluginSession(handle, + *this, + version, + subserviceId, + subserviceType, + attachFlags, + upcalls, + mDatabaseManager); + default: + CssmError::throwMe(CSSMERR_CSSM_INVALID_SERVICE_MASK); + return 0; // placebo + } +} diff --git a/libsecurity_apple_file_dl/lib/AppleFileDL.h b/libsecurity_apple_file_dl/lib/AppleFileDL.h new file mode 100644 index 00000000..a18d31ef --- /dev/null +++ b/libsecurity_apple_file_dl/lib/AppleFileDL.h @@ -0,0 +1,46 @@ +/* + * 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. + */ + + +// +// AppleFileDL.h - File Based DL plug-in module. +// +#ifndef _H_APPLEFILEDL +#define _H_APPLEFILEDL + +#include +#include + +class AppleFileDL : public CssmPlugin +{ + NOCOPY(AppleFileDL) +public: + AppleFileDL(); + ~AppleFileDL(); + + PluginSession *makeSession(CSSM_MODULE_HANDLE handle, + const CSSM_VERSION &version, + uint32 subserviceId, + CSSM_SERVICE_TYPE subserviceType, + CSSM_ATTACH_FLAGS attachFlags, + const CSSM_UPCALLS &upcalls); +private: + AppleDatabaseManager mDatabaseManager; +}; + + +#endif //_H_APPLEFILEDL diff --git a/libsecurity_apple_file_dl/libsecurity_apple_file_dl.xcodeproj/project.pbxproj b/libsecurity_apple_file_dl/libsecurity_apple_file_dl.xcodeproj/project.pbxproj new file mode 100644 index 00000000..b176ae52 --- /dev/null +++ b/libsecurity_apple_file_dl/libsecurity_apple_file_dl.xcodeproj/project.pbxproj @@ -0,0 +1,264 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + C2196B69053B59D4005808D4 /* AppleDLBuiltin.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2196B68053B59D4005808D4 /* AppleDLBuiltin.cpp */; }; + C28436E00534880F000AE0FC /* AppleFileDL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C28436DD0534880F000AE0FC /* AppleFileDL.cpp */; }; + C28436E10534880F000AE0FC /* AppleFileDL.h in Headers */ = {isa = PBXBuildFile; fileRef = C28436DE0534880F000AE0FC /* AppleFileDL.h */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 182BB34C146F1102000BF1F3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 184460F4146E818D00B12992 /* libsecurity_cdsa_plugin.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = C2C38A530535EDE600D7421F; + remoteInfo = libsecurity_cdsa_plugin_generate; + }; + 184460F9146E818D00B12992 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 184460F4146E818D00B12992 /* libsecurity_cdsa_plugin.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 4CA1FEBE052A3C8100F22E42; + remoteInfo = libsecurity_cdsa_plugin; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 184460E6146E808700B12992 /* base.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = base.xcconfig; sourceTree = ""; }; + 184460E7146E808700B12992 /* debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = debug.xcconfig; sourceTree = ""; }; + 184460E8146E808700B12992 /* lib.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = lib.xcconfig; sourceTree = ""; }; + 184460E9146E808700B12992 /* release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = release.xcconfig; sourceTree = ""; }; + 184460F4146E818D00B12992 /* libsecurity_cdsa_plugin.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libsecurity_cdsa_plugin.xcodeproj; path = ../libsecurity_cdsa_plugin/libsecurity_cdsa_plugin.xcodeproj; sourceTree = ""; }; + 4094B099057EA68B00B44BCC /* dl_common.mdsinfo */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.xml; path = dl_common.mdsinfo; sourceTree = ""; }; + 4094B09A057EA68B00B44BCC /* dl_primary.mdsinfo */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.xml; path = dl_primary.mdsinfo; sourceTree = ""; }; + 4CA1FEBE052A3C8100F22E42 /* libsecurity_apple_file_dl.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libsecurity_apple_file_dl.a; sourceTree = BUILT_PRODUCTS_DIR; }; + C2196B68053B59D4005808D4 /* AppleDLBuiltin.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = AppleDLBuiltin.cpp; path = lib/AppleDLBuiltin.cpp; sourceTree = ""; }; + C28436DC0534880F000AE0FC /* AppleDLPlugin.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = AppleDLPlugin.cpp; sourceTree = ""; }; + C28436DD0534880F000AE0FC /* AppleFileDL.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = AppleFileDL.cpp; sourceTree = ""; }; + C28436DE0534880F000AE0FC /* AppleFileDL.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = AppleFileDL.h; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 4CA1FEBB052A3C8100F22E42 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 184460E5146E808700B12992 /* config */ = { + isa = PBXGroup; + children = ( + 184460E6146E808700B12992 /* base.xcconfig */, + 184460E7146E808700B12992 /* debug.xcconfig */, + 184460E8146E808700B12992 /* lib.xcconfig */, + 184460E9146E808700B12992 /* release.xcconfig */, + ); + name = config; + path = ../config; + sourceTree = ""; + }; + 184460F5146E818D00B12992 /* Products */ = { + isa = PBXGroup; + children = ( + 184460FA146E818D00B12992 /* libsecurity_cdsa_plugin.a */, + ); + name = Products; + sourceTree = ""; + }; + 4094B098057EA68B00B44BCC /* mds */ = { + isa = PBXGroup; + children = ( + 4094B099057EA68B00B44BCC /* dl_common.mdsinfo */, + 4094B09A057EA68B00B44BCC /* dl_primary.mdsinfo */, + ); + path = mds; + sourceTree = ""; + }; + 4CA1FEA7052A3C3800F22E42 = { + isa = PBXGroup; + children = ( + 184460F4146E818D00B12992 /* libsecurity_cdsa_plugin.xcodeproj */, + C28436DB0534880F000AE0FC /* lib */, + 184460E5146E808700B12992 /* config */, + C2196B68053B59D4005808D4 /* AppleDLBuiltin.cpp */, + 4094B098057EA68B00B44BCC /* mds */, + 4CA1FEBF052A3C8100F22E42 /* Products */, + ); + sourceTree = ""; + }; + 4CA1FEBF052A3C8100F22E42 /* Products */ = { + isa = PBXGroup; + children = ( + 4CA1FEBE052A3C8100F22E42 /* libsecurity_apple_file_dl.a */, + ); + name = Products; + sourceTree = ""; + }; + C28436DB0534880F000AE0FC /* lib */ = { + isa = PBXGroup; + children = ( + C28436DC0534880F000AE0FC /* AppleDLPlugin.cpp */, + C28436DD0534880F000AE0FC /* AppleFileDL.cpp */, + C28436DE0534880F000AE0FC /* AppleFileDL.h */, + ); + path = lib; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 4CA1FEB9052A3C8100F22E42 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + C28436E10534880F000AE0FC /* AppleFileDL.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 4CA1FEBD052A3C8100F22E42 /* libsecurity_apple_file_dl */ = { + isa = PBXNativeTarget; + buildConfigurationList = C27AD2770987FCDC001272E0 /* Build configuration list for PBXNativeTarget "libsecurity_apple_file_dl" */; + buildPhases = ( + 4CA1FEB9052A3C8100F22E42 /* Headers */, + 4CA1FEBA052A3C8100F22E42 /* Sources */, + 4CA1FEBB052A3C8100F22E42 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + 182BB34D146F1102000BF1F3 /* PBXTargetDependency */, + ); + name = libsecurity_apple_file_dl; + productInstallPath = /usr/local/lib; + productName = libsecurity_apple_file_dl; + productReference = 4CA1FEBE052A3C8100F22E42 /* libsecurity_apple_file_dl.a */; + productType = "com.apple.product-type.library.static"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 4CA1FEAB052A3C3800F22E42 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0420; + }; + buildConfigurationList = C27AD27B0987FCDC001272E0 /* Build configuration list for PBXProject "libsecurity_apple_file_dl" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 1; + knownRegions = ( + en, + ); + mainGroup = 4CA1FEA7052A3C3800F22E42; + productRefGroup = 4CA1FEBF052A3C8100F22E42 /* Products */; + projectDirPath = ""; + projectReferences = ( + { + ProductGroup = 184460F5146E818D00B12992 /* Products */; + ProjectRef = 184460F4146E818D00B12992 /* libsecurity_cdsa_plugin.xcodeproj */; + }, + ); + projectRoot = ""; + targets = ( + 4CA1FEBD052A3C8100F22E42 /* libsecurity_apple_file_dl */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXReferenceProxy section */ + 184460FA146E818D00B12992 /* libsecurity_cdsa_plugin.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libsecurity_cdsa_plugin.a; + remoteRef = 184460F9146E818D00B12992 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; +/* End PBXReferenceProxy section */ + +/* Begin PBXSourcesBuildPhase section */ + 4CA1FEBA052A3C8100F22E42 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + C28436E00534880F000AE0FC /* AppleFileDL.cpp in Sources */, + C2196B69053B59D4005808D4 /* AppleDLBuiltin.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 182BB34D146F1102000BF1F3 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = libsecurity_cdsa_plugin_generate; + targetProxy = 182BB34C146F1102000BF1F3 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + C27AD2780987FCDC001272E0 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 184460E7146E808700B12992 /* debug.xcconfig */; + buildSettings = { + }; + name = Debug; + }; + C27AD27A0987FCDC001272E0 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 184460E9146E808700B12992 /* release.xcconfig */; + buildSettings = { + }; + name = Release; + }; + C27AD27C0987FCDC001272E0 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 184460E8146E808700B12992 /* lib.xcconfig */; + buildSettings = { + }; + name = Debug; + }; + C27AD27E0987FCDC001272E0 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 184460E8146E808700B12992 /* lib.xcconfig */; + buildSettings = { + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + C27AD2770987FCDC001272E0 /* Build configuration list for PBXNativeTarget "libsecurity_apple_file_dl" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C27AD2780987FCDC001272E0 /* Debug */, + C27AD27A0987FCDC001272E0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C27AD27B0987FCDC001272E0 /* Build configuration list for PBXProject "libsecurity_apple_file_dl" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C27AD27C0987FCDC001272E0 /* Debug */, + C27AD27E0987FCDC001272E0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 4CA1FEAB052A3C3800F22E42 /* Project object */; +} diff --git a/libsecurity_apple_file_dl/mds/dl_common.mdsinfo b/libsecurity_apple_file_dl/mds/dl_common.mdsinfo new file mode 100644 index 00000000..f11cadbe --- /dev/null +++ b/libsecurity_apple_file_dl/mds/dl_common.mdsinfo @@ -0,0 +1,30 @@ + + + + + BuiltIn + + CDSAVersion + 2.0 + Desc + Apple built-in DL + DynamicFlag + + MdsFileDescription + Built-in DL Common info + MdsFileType + PluginCommon + ModuleID + {87191ca1-0fc9-11d4-849a-000502b52122} + ModuleName + AppleDL + MultiThreadFlag + + ProductVersion + 1.0 + ServiceMask + CSSM_SERVICE_DL + Path + *AppleDL + + diff --git a/libsecurity_apple_file_dl/mds/dl_primary.mdsinfo b/libsecurity_apple_file_dl/mds/dl_primary.mdsinfo new file mode 100644 index 00000000..344f4532 --- /dev/null +++ b/libsecurity_apple_file_dl/mds/dl_primary.mdsinfo @@ -0,0 +1,48 @@ + + + + + AclSubjectTypes + + AuthTags + + ConjunctiveOps + + CSSM_DB_NONE + CSSM_DB_AND + CSSM_DB_OR + + DLType + CSSM_DL_FFS + MdsFileDescription + Built-in DL Primary info + MdsFileType + PluginSpecific + MdsRecordType + MDS_CDSADIR_DL_PRIMARY_RECORDTYPE + ModuleID + {87191ca1-0fc9-11d4-849a-000502b52122} + ModuleName + AppleDL + ProductVersion + 1.0 + QueryLimitsFlag + 0 + RelationalOps + + CSSM_DB_EQUAL + CSSM_DB_LESS_THAN + CSSM_DB_GREATER_THAN + CSSM_DB_NOT_EQUAL + CSSM_DB_CONTAINS + CSSM_DB_CONTAINS_INITIAL_SUBSTRING + CSSM_DB_CONTAINS_FINAL_SUBSTRING + + SSID + 0 + SampleTypes + + Vendor + Apple Computer, Inc. + + diff --git a/libsecurity_apple_x509_cl/Info-plugin_apple_x509_cl.plist b/libsecurity_apple_x509_cl/Info-plugin_apple_x509_cl.plist new file mode 100644 index 00000000..d3d56e9e --- /dev/null +++ b/libsecurity_apple_x509_cl/Info-plugin_apple_x509_cl.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + apple_x509_cl + CFBundleIconFile + + CFBundleIdentifier + + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + + CFBundlePackageType + BNDL + CFBundleShortVersionString + + CFBundleSignature + ???? + CFBundleVersion + 1 + + diff --git a/libsecurity_apple_x509_cl/Info-security_apple_x509_cl.plist b/libsecurity_apple_x509_cl/Info-security_apple_x509_cl.plist new file mode 100644 index 00000000..0c67376e --- /dev/null +++ b/libsecurity_apple_x509_cl/Info-security_apple_x509_cl.plist @@ -0,0 +1,5 @@ + + + + + diff --git a/libsecurity_apple_x509_cl/TODO b/libsecurity_apple_x509_cl/TODO new file mode 100644 index 00000000..de81bb21 --- /dev/null +++ b/libsecurity_apple_x509_cl/TODO @@ -0,0 +1 @@ +Things TODO in AppleX509CL diff --git a/libsecurity_apple_x509_cl/lib/AppleX509CL.cpp b/libsecurity_apple_x509_cl/lib/AppleX509CL.cpp new file mode 100644 index 00000000..15a693b9 --- /dev/null +++ b/libsecurity_apple_x509_cl/lib/AppleX509CL.cpp @@ -0,0 +1,63 @@ +/* + * 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. + */ + + +// +// AppleX509CL.cpp - File Based X.509 Certificate Library plug-in module. +// +#include "AppleX509CL.h" + +#include "AppleX509CLSession.h" + + +// +// Make and break the plugin object +// +AppleX509CL::AppleX509CL() +{ +} + +AppleX509CL::~AppleX509CL() +{ +} + + +// +// Create a new plugin session, our way +// +PluginSession *AppleX509CL::makeSession( + CSSM_MODULE_HANDLE handle, + const CSSM_VERSION &version, + uint32 subserviceId, + CSSM_SERVICE_TYPE subserviceType, + CSSM_ATTACH_FLAGS attachFlags, + const CSSM_UPCALLS &upcalls) +{ + switch (subserviceType) { + case CSSM_SERVICE_CL: + return new AppleX509CLSession(handle, + *this, + version, + subserviceId, + subserviceType, + attachFlags, + upcalls); + default: + CssmError::throwMe(CSSMERR_CSSM_INVALID_SERVICE_MASK); + return 0; // placebo + } +} diff --git a/libsecurity_apple_x509_cl/lib/AppleX509CL.h b/libsecurity_apple_x509_cl/lib/AppleX509CL.h new file mode 100644 index 00000000..426fdd4f --- /dev/null +++ b/libsecurity_apple_x509_cl/lib/AppleX509CL.h @@ -0,0 +1,48 @@ +/* + * 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. + */ + + +// +// AppleX509CL.h - File Based CSP/DL plug-in module. +// +#ifndef _H_APPLEX509CL +#define _H_APPLEX509CL + +#include +#include + +class AppleX509CL : public CssmPlugin +{ +public: + AppleX509CL(); + ~AppleX509CL(); + + PluginSession *makeSession( + CSSM_MODULE_HANDLE handle, + const CSSM_VERSION &version, + uint32 subserviceId, + CSSM_SERVICE_TYPE subserviceType, + CSSM_ATTACH_FLAGS attachFlags, + const CSSM_UPCALLS &upcalls); +private: + // Don't copy AppleX509CL + AppleX509CL(const AppleX509CL&); + void operator=(const AppleX509CL&); +}; + + +#endif //_H_APPLEX509CL diff --git a/libsecurity_apple_x509_cl/lib/AppleX509CLBuiltin.cpp b/libsecurity_apple_x509_cl/lib/AppleX509CLBuiltin.cpp new file mode 100644 index 00000000..eff07ff6 --- /dev/null +++ b/libsecurity_apple_x509_cl/lib/AppleX509CLBuiltin.cpp @@ -0,0 +1,32 @@ +/* + * 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 obtai +n + * 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. + */ + + +// +// Produce the SPI wrapper for building the "plugin" into CSSM +// +#include + + +// +// Create the plugin object and generate the C layer hookup +// +static ModuleNexus plugin; + +#define SPINAME(s) s ## __apple_x509_cl +#include diff --git a/libsecurity_apple_x509_cl/lib/AppleX509CLPlugin.cpp b/libsecurity_apple_x509_cl/lib/AppleX509CLPlugin.cpp new file mode 100644 index 00000000..b233f89b --- /dev/null +++ b/libsecurity_apple_x509_cl/lib/AppleX509CLPlugin.cpp @@ -0,0 +1,31 @@ +/* + * 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 obtai +n + * 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. + */ + + +// +// Produce the "genuine plugin version" of the Apple X509 CL +// +#include + + +// +// Create the plugin object and generate the C layer hookup +// +ModuleNexus plugin; + +#include diff --git a/libsecurity_apple_x509_cl/lib/AppleX509CLSession.cpp b/libsecurity_apple_x509_cl/lib/AppleX509CLSession.cpp new file mode 100644 index 00000000..3793da9f --- /dev/null +++ b/libsecurity_apple_x509_cl/lib/AppleX509CLSession.cpp @@ -0,0 +1,87 @@ +/* + * 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. + */ + + +/* + * AppleX509CLSession.cpp - general CL session support + */ + +#include "AppleX509CLSession.h" +#include + +AppleX509CLSession::AppleX509CLSession( + CSSM_MODULE_HANDLE theHandle, + CssmPlugin &plug, + const CSSM_VERSION &version, + uint32 subserviceId, + CSSM_SERVICE_TYPE subserviceType, + CSSM_ATTACH_FLAGS attachFlags, + const CSSM_UPCALLS &upcalls) + : CLPluginSession(theHandle, plug, version, subserviceId, + subserviceType,attachFlags, upcalls) +{ +} + +AppleX509CLSession::~AppleX509CLSession() +{ + /* free leftover contents of cache and query maps */ + CLCachedEntry *cachedCert = cacheMap.removeFirstEntry(); + while(cachedCert != NULL) { + secdebug("clDetach", "CL detach: deleting a cached Cert\n"); + delete cachedCert; + cachedCert = cacheMap.removeFirstEntry(); + } + CLQuery *query = queryMap.removeFirstEntry(); + while(query != NULL) { + secdebug("clDetach", "CL detach: deleting a cached query\n"); + delete query; + query = queryMap.removeFirstEntry(); + } +} + +CLCachedCert * +AppleX509CLSession::lookupCachedCert(CSSM_HANDLE handle) +{ + CLCachedEntry *entry = cacheMap.lookupEntry(handle); + if(entry != NULL) { + /* + * we rely on this dynamic cast to detect a bogus lookup + * of a cert via a CRL's handle + */ + return dynamic_cast(entry); + } + else { + return NULL; + } +} + +CLCachedCRL * +AppleX509CLSession::lookupCachedCRL(CSSM_HANDLE handle) +{ + CLCachedEntry *entry = cacheMap.lookupEntry(handle); + if(entry != NULL) { + /* + * we rely on this dynamic cast to detect a bogus lookup + * of a CRL via a cert's handle + */ + return dynamic_cast(entry); + } + else { + return NULL; + } +} + diff --git a/libsecurity_apple_x509_cl/lib/AppleX509CLSession.h b/libsecurity_apple_x509_cl/lib/AppleX509CLSession.h new file mode 100644 index 00000000..2ba29639 --- /dev/null +++ b/libsecurity_apple_x509_cl/lib/AppleX509CLSession.h @@ -0,0 +1,321 @@ +/* + * 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. + */ + + +// +// AppleX509CLSession.h - general CL session functions. +// +#ifndef _H_APPLEX509CLSESSION +#define _H_APPLEX509CLSESSION + +#include +#include "CLCachedEntry.h" +#include "DecodedCert.h" +#include "LockedMap.h" +#include +#include + +class AppleX509CLSession : public CLPluginSession { + +public: + + AppleX509CLSession( + CSSM_MODULE_HANDLE theHandle, + CssmPlugin &plug, + const CSSM_VERSION &version, + uint32 subserviceId, + CSSM_SERVICE_TYPE subserviceType, + CSSM_ATTACH_FLAGS attachFlags, + const CSSM_UPCALLS &upcalls); + + ~AppleX509CLSession(); + +// ==================================================================== +// Cert Interpretation +// ==================================================================== + + void CertDescribeFormat( + uint32 &NumberOfFields, + CSSM_OID_PTR &OidList); + +// Non-cached + + void CertGetAllFields( + const CssmData &Cert, + uint32 &NumberOfFields, + CSSM_FIELD_PTR &CertFields); + + CSSM_HANDLE CertGetFirstFieldValue( + const CssmData &Cert, + const CssmData &CertField, + uint32 &NumberOfMatchedFields, + CSSM_DATA_PTR &Value); + + bool CertGetNextFieldValue( + CSSM_HANDLE ResultsHandle, + CSSM_DATA_PTR &Value); + + +// Cached + + void CertCache( + const CssmData &Cert, + CSSM_HANDLE &CertHandle); + + CSSM_HANDLE CertGetFirstCachedFieldValue( + CSSM_HANDLE CertHandle, + const CssmData &CertField, + uint32 &NumberOfMatchedFields, + CSSM_DATA_PTR &Value); + + bool CertGetNextCachedFieldValue( + CSSM_HANDLE ResultsHandle, + CSSM_DATA_PTR &Value); + + void CertAbortCache( + CSSM_HANDLE CertHandle); + + void CertAbortQuery( + CSSM_HANDLE ResultsHandle); + + + +// Templates + + void CertCreateTemplate( + uint32 NumberOfFields, + const CSSM_FIELD CertFields[], + CssmData &CertTemplate); + + void CertGetAllTemplateFields( + const CssmData &CertTemplate, + uint32 &NumberOfFields, + CSSM_FIELD_PTR &CertFields); + + +// Memory + + void FreeFields( + uint32 NumberOfFields, + CSSM_FIELD_PTR &FieldArray); + void FreeFieldValue( + const CssmData &CertOrCrlOid, + CssmData &Value); + +// Key + + void CertGetKeyInfo( + const CssmData &Cert, + CSSM_KEY_PTR &Key); + +// ==================================================================== +// CRL Interpretation +// ==================================================================== + +// Non-cached + + void CrlDescribeFormat( + uint32 &NumberOfFields, + CSSM_OID_PTR &OidList); + + void CrlGetAllFields( + const CssmData &Crl, + uint32 &NumberOfCrlFields, + CSSM_FIELD_PTR &CrlFields); + + CSSM_HANDLE CrlGetFirstFieldValue( + const CssmData &Crl, + const CssmData &CrlField, + uint32 &NumberOfMatchedFields, + CSSM_DATA_PTR &Value); + + bool CrlGetNextFieldValue( + CSSM_HANDLE ResultsHandle, + CSSM_DATA_PTR &Value); + + void IsCertInCrl( + const CssmData &Cert, + const CssmData &Crl, + CSSM_BOOL &CertFound); + + +// Cached + + void CrlCache( + const CssmData &Crl, + CSSM_HANDLE &CrlHandle); + + void CrlGetAllCachedRecordFields(CSSM_HANDLE CrlHandle, + const CssmData &CrlRecordIndex, + uint32 &NumberOfFields, + CSSM_FIELD_PTR &CrlFields); + + CSSM_HANDLE CrlGetFirstCachedFieldValue( + CSSM_HANDLE CrlHandle, + const CssmData *CrlRecordIndex, + const CssmData &CrlField, + uint32 &NumberOfMatchedFields, + CSSM_DATA_PTR &Value); + + bool CrlGetNextCachedFieldValue( + CSSM_HANDLE ResultsHandle, + CSSM_DATA_PTR &Value); + + void IsCertInCachedCrl( + const CssmData &Cert, + CSSM_HANDLE CrlHandle, + CSSM_BOOL &CertFound, + CssmData &CrlRecordIndex); + + void CrlAbortCache( + CSSM_HANDLE CrlHandle); + + void CrlAbortQuery( + CSSM_HANDLE ResultsHandle); + + +// Template + + void CrlCreateTemplate( + uint32 NumberOfFields, + const CSSM_FIELD *CrlTemplate, + CssmData &NewCrl); + + void CrlSetFields( + uint32 NumberOfFields, + const CSSM_FIELD *CrlTemplate, + const CssmData &OldCrl, + CssmData &ModifiedCrl); + + void CrlAddCert( + CSSM_CC_HANDLE CCHandle, + const CssmData &Cert, + uint32 NumberOfFields, + const CSSM_FIELD CrlEntryFields[], + const CssmData &OldCrl, + CssmData &NewCrl); + + void CrlRemoveCert( + const CssmData &Cert, + const CssmData &OldCrl, + CssmData &NewCrl); + +// ==================================================================== +// Verify/Sign +// ==================================================================== + +// Certs + + void CertVerifyWithKey( + CSSM_CC_HANDLE CCHandle, + const CssmData &CertToBeVerified); + + void CertVerify( + CSSM_CC_HANDLE CCHandle, + const CssmData &CertToBeVerified, + const CssmData *SignerCert, + const CSSM_FIELD *VerifyScope, + uint32 ScopeSize); + + void CertSign( + CSSM_CC_HANDLE CCHandle, + const CssmData &CertTemplate, + const CSSM_FIELD *SignScope, + uint32 ScopeSize, + CssmData &SignedCert); + +// Cert Groups + + void CertGroupFromVerifiedBundle( + CSSM_CC_HANDLE CCHandle, + const CSSM_CERT_BUNDLE &CertBundle, + const CssmData *SignerCert, + CSSM_CERTGROUP_PTR &CertGroup); + + void CertGroupToSignedBundle( + CSSM_CC_HANDLE CCHandle, + const CSSM_CERTGROUP &CertGroupToBundle, + const CSSM_CERT_BUNDLE_HEADER *BundleInfo, + CssmData &SignedBundle); + +// CRLs + + void CrlVerifyWithKey( + CSSM_CC_HANDLE CCHandle, + const CssmData &CrlToBeVerified); + + void CrlVerify( + CSSM_CC_HANDLE CCHandle, + const CssmData &CrlToBeVerified, + const CssmData *SignerCert, + const CSSM_FIELD *VerifyScope, + uint32 ScopeSize); + + void CrlSign( + CSSM_CC_HANDLE CCHandle, + const CssmData &UnsignedCrl, + const CSSM_FIELD *SignScope, + uint32 ScopeSize, + CssmData &SignedCrl); + +// ==================================================================== +// Module Specific Pass-Through +// ==================================================================== + + void PassThrough( + CSSM_CC_HANDLE CCHandle, + uint32 PassThroughId, + const void *InputParams, + void **OutputParams); + +private: + /* routines in Session_Cert.cpp */ + void getAllParsedCertFields( + const DecodedCert &cert, + uint32 &NumberOfFields, // RETURNED + CSSM_FIELD_PTR &CertFields); // RETURNED + + /* routines in Session_Crypto.cpp */ + void signData( + CSSM_CC_HANDLE ccHand, + const CssmData &tbs, + CssmOwnedData &sig); // mallocd and returned + void verifyData( + CSSM_CC_HANDLE ccHand, + const CssmData &tbs, + const CssmData &sig); + + /* routines in Session_CSR.cpp */ + void generateCsr( + CSSM_CC_HANDLE CCHandle, + const CSSM_APPLE_CL_CSR_REQUEST *csrReq, + CSSM_DATA_PTR &csrPtr); + void verifyCsr( + const CSSM_DATA *csrPtr); + + /* + * Maps of cached certs, CRLs, and active queries + * This one holds cached certs and CRLs. + */ + LockedMap cacheMap; + LockedMap queryMap; + + CLCachedCert *lookupCachedCert(CSSM_HANDLE handle); + CLCachedCRL *lookupCachedCRL(CSSM_HANDLE handle); +}; + +#endif //_H_APPLEX509CLSESSION diff --git a/libsecurity_apple_x509_cl/lib/CLCachedEntry.cpp b/libsecurity_apple_x509_cl/lib/CLCachedEntry.cpp new file mode 100644 index 00000000..2508b8c9 --- /dev/null +++ b/libsecurity_apple_x509_cl/lib/CLCachedEntry.cpp @@ -0,0 +1,67 @@ +/* + * 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. + */ + + +/* + * CLCachedEntry.cpp - classes representing cached certs and CRLs. + * + * Created 9/1/2000 by Doug Mitchell. + * Copyright (c) 2000 by Apple Computer. + */ + +#include "CLCachedEntry.h" + +/* + * CLCachedEntry base class constructor. Only job here is to cook up + * a handle. + */ +CLCachedEntry::CLCachedEntry() +{ + mHandle = reinterpret_cast(this); +} + +CLCachedCert::~CLCachedCert() +{ + delete &mCert; +} + +CLCachedCRL::~CLCachedCRL() +{ + delete &mCrl; +} + +CLQuery::CLQuery( + CLQueryType type, + const CssmOid &oid, + unsigned numFields, + bool isFromCache, + CSSM_HANDLE cachedObj) : + mQueryType(type), + mFieldId(Allocator::standard()), + mNextIndex(1), + mNumFields(numFields), + mFromCache(isFromCache), + mCachedObject(cachedObj) +{ + mFieldId.copy(oid); + mHandle = reinterpret_cast(this); +} + +CLQuery::~CLQuery() +{ + /* mFieldId auto frees */ +} diff --git a/libsecurity_apple_x509_cl/lib/CLCachedEntry.h b/libsecurity_apple_x509_cl/lib/CLCachedEntry.h new file mode 100644 index 00000000..a0e7ee7a --- /dev/null +++ b/libsecurity_apple_x509_cl/lib/CLCachedEntry.h @@ -0,0 +1,130 @@ +/* + * 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. + */ + + +/* + * CLCachedEntry.h - classes representing cached certs and CRLs. + * + * Created 9/1/2000 by Doug Mitchell. + * Copyright (c) 2000 by Apple Computer. + */ + +#ifndef _APPLE_X509_CL_CACHED_ENTRY_H_ +#define _APPLE_X509_CL_CACHED_ENTRY_H_ + +#include +#include +#include +#include "DecodedCert.h" +#include "DecodedCrl.h" + +/* + * There is one of these per active cached object (cert or CRL). + * AppleX509CLSession keeps a map of these in cacheMap. + */ +class CLCachedEntry +{ +public: + CLCachedEntry(); + virtual ~CLCachedEntry() { } + CSSM_HANDLE handle() { return mHandle; } +private: + CSSM_HANDLE mHandle; +}; + +class CLCachedCert : public CLCachedEntry +{ +public: + CLCachedCert( + DecodedCert &c) : mCert(c) { } + ~CLCachedCert(); + DecodedCert &cert() { return mCert; } +private: + /* decoded NSS format */ + DecodedCert &mCert; +}; + +class CLCachedCRL : public CLCachedEntry +{ +public: + CLCachedCRL( + DecodedCrl &c) : mCrl(c) { } + ~CLCachedCRL(); + DecodedCrl &crl() { return mCrl; } +private: + /* decoded NSS format */ + DecodedCrl &mCrl; +}; + +/* + * An active query, always associated with a CLCachedEntry. + * AppleX509CLSession keeps a map of these in queryMap. + * + * In the case of a CLCachedEntry created by an explicit {Cert,CRL}Cache op, + * there can be multiple queries active for a given cached cert. In + * the *GetFirst*FieldValue case, there is a one-to-one relationship between + * the CLQUery and its associated cached object. + * + * Out of paranoia in the {Cert,CRL}Cache case, we store the handle of + * the associated cached object, not a ref to the object, in case the + * cached object has been deleted via *AbortCache. We could ref count, + * but that would require a lock in CLCachedEntry...looking up an object + * in the session's cache map should not be too expensive. + */ + +typedef enum { + CLQ_Cert = 1, + CLQ_CRL +} CLQueryType; + +class CLQuery +{ +public: + CLQuery( + CLQueryType type, + const CssmOid &oid, + unsigned numFields, + bool isFromCache, + CSSM_HANDLE cachedObj); + + ~CLQuery(); + + /* + * Accessors - all member variables are invariant after creation, except + * for nextIndex which can only increment + */ + CLQueryType queryType() { return mQueryType; } + const CssmOid &fieldId() { return mFieldId; } + unsigned nextIndex() { return mNextIndex; } + void incrementIndex(){ mNextIndex++; } + unsigned numFields() { return mNumFields; } + bool fromCache() { return mFromCache; } + CSSM_HANDLE cachedObject() { return mCachedObject; } + CSSM_HANDLE handle() { return mHandle;} + +private: + CLQueryType mQueryType; + CssmAutoData mFieldId; // thing we're searching for - may be empty + unsigned mNextIndex; // index of next find op + unsigned mNumFields; // total available + bool mFromCache; // true : via CertGetFirstCachedFieldValue + // false : via CertGetFirstFieldValue + CSSM_HANDLE mCachedObject; // of our associated cached cert/CRL + CSSM_HANDLE mHandle; // ours +}; + +#endif /* _APPLE_X509_CL_CACHED_ENTRY_H_ */ diff --git a/libsecurity_apple_x509_cl/lib/CLCertExtensions.cpp b/libsecurity_apple_x509_cl/lib/CLCertExtensions.cpp new file mode 100644 index 00000000..1c19b74b --- /dev/null +++ b/libsecurity_apple_x509_cl/lib/CLCertExtensions.cpp @@ -0,0 +1,1265 @@ +/* + * Copyright (c) 2000-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. + */ + + +/* + * CLCertExtensions.cpp - extensions support. A major component of DecodedCert. + * + */ + +#include "DecodedCert.h" +#include "cldebugging.h" +#include "CLCertExtensions.h" +#include "CLFieldsCommon.h" +#include "clNssUtils.h" +#include "clNameUtils.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/*** + *** get/set/free functions called out from CertFields.cpp + ***/ + +/*** + *** KeyUsage + *** CDSA format CE_KeyUsage + *** NSS format CSSM_DATA, length 2 + *** OID CSSMOID_KeyUsage + ***/ + +void setFieldKeyUsage( + DecodedItem &cert, + const CssmData &fieldValue) +{ + CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, + false); + CE_KeyUsage *cdsaObj = (CE_KeyUsage *)cssmExt->value.parsedValue; + + /* Alloc an NSS-style key usage in cert.coder's memory */ + SecNssCoder &coder = cert.coder(); + CSSM_DATA *nssObj = (CSSM_DATA *)coder.malloc(sizeof(CSSM_DATA)); + coder.allocItem(*nssObj, 2); + + /* cdsaObj --> nssObj */ + nssObj->Data[0] = (*cdsaObj) >> 8; + nssObj->Data[1] = *cdsaObj; + + /* Adjust length for BIT STRING encoding */ + clCssmBitStringToNss(*nssObj); + + /* add to mExtensions */ + cert.addExtension(nssObj, cssmExt->extnId, cssmExt->critical, false, + kSecAsn1KeyUsageTemplate); +} + + +bool getFieldKeyUsage( + DecodedItem &cert, + unsigned index, // which occurrence (0 = first) + uint32 &numFields, // RETURNED + CssmOwnedData &fieldValue) +{ + const DecodedExten *decodedExt; + CSSM_DATA *nssObj; + CE_KeyUsage *cdsaObj; + bool brtn; + + brtn = cert.GetExtenTop( + index, + numFields, + fieldValue.allocator, + CSSMOID_KeyUsage, + nssObj, + cdsaObj, + decodedExt); + if(!brtn) { + return false; + } + + /* make a copy - can't modify length in place */ + CSSM_DATA bitString = *nssObj; + clNssBitStringToCssm(bitString); + unsigned toCopy = bitString.Length; + if(toCopy > 2) { + /* I hope I never see this... */ + clErrorLog("getFieldKeyUsage: KeyUsage larger than 2 bytes!"); + toCopy = 2; + } + unsigned char bits[2] = {0, 0}; + memmove(bits, bitString.Data, toCopy); + *cdsaObj = (((unsigned)bits[0]) << 8) | bits[1]; + + /* pass back to caller */ + getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue); + return true; +} + +/*** + *** Basic Constraints + *** CDSA format: CE_BasicConstraints + *** NSS format CE_BasicConstraints + *** OID CSSMOID_BasicConstraints + ***/ + +void setFieldBasicConstraints( + DecodedItem &cert, + const CssmData &fieldValue) +{ + CSSM_X509_EXTENSION_PTR cssmExt = + verifySetFreeExtension(fieldValue, false); + CE_BasicConstraints *cdsaObj = + (CE_BasicConstraints *)cssmExt->value.parsedValue; + + /* Alloc an NSS-style BasicConstraints in cert.coder's memory */ + SecNssCoder &coder = cert.coder(); + NSS_BasicConstraints *nssObj = + (NSS_BasicConstraints *)coder.malloc(sizeof(NSS_BasicConstraints)); + memset(nssObj, 0, sizeof(*nssObj)); + + /* cdsaObj --> nssObj */ + ArenaAllocator arenaAlloc(coder); + clCssmBoolToNss(cdsaObj->cA, nssObj->cA, arenaAlloc); + if(cdsaObj->pathLenConstraintPresent) { + clIntToData(cdsaObj->pathLenConstraint, + nssObj->pathLenConstraint, arenaAlloc); + } + + /* add to mExtensions */ + cert.addExtension(nssObj, cssmExt->extnId, cssmExt->critical, false, + kSecAsn1BasicConstraintsTemplate); +} + + +bool getFieldBasicConstraints( + DecodedItem &cert, + unsigned index, // which occurrence (0 = first) + uint32 &numFields, // RETURNED + CssmOwnedData &fieldValue) +{ + const DecodedExten *decodedExt; + NSS_BasicConstraints *nssObj; + CE_BasicConstraints *cdsaObj; + bool brtn; + + brtn = cert.GetExtenTop( + index, + numFields, + fieldValue.allocator, + CSSMOID_BasicConstraints, + nssObj, + cdsaObj, + decodedExt); + if(!brtn) { + return false; + } + + if(nssObj->cA.Data == NULL) { + /* default */ + cdsaObj->cA = CSSM_FALSE; + } + else { + cdsaObj->cA = clNssBoolToCssm(nssObj->cA); + } + if(nssObj->pathLenConstraint.Data == NULL) { + /* optional */ + cdsaObj->pathLenConstraintPresent = CSSM_FALSE; + cdsaObj->pathLenConstraint = 0; + } + else { + cdsaObj->pathLenConstraintPresent = CSSM_TRUE; + cdsaObj->pathLenConstraint = clDataToInt(nssObj->pathLenConstraint); + } + + /* pass back to caller */ + getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue); + return true; +} + +/*** + *** Extended Key Usage + *** CDSA format: CE_ExtendedKeyUsage + *** NSS format: NSS_ExtKeyUsage + *** OID CSSMOID_ExtendedKeyUsage + ***/ +void setFieldExtKeyUsage( + DecodedItem &cert, + const CssmData &fieldValue) +{ + CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, + false); + CE_ExtendedKeyUsage *cdsaObj = + (CE_ExtendedKeyUsage *)cssmExt->value.parsedValue; + + SecNssCoder &coder = cert.coder(); + NSS_ExtKeyUsage *nssObj = + (NSS_ExtKeyUsage *)coder.malloc(sizeof(NSS_ExtKeyUsage)); + memset(nssObj, 0, sizeof(*nssObj)); + if(cdsaObj->numPurposes != 0) { + nssObj->purposes = + (CSSM_OID **)clNssNullArray(cdsaObj->numPurposes, coder); + } + + /* cdsaObj --> nssObj, one 'purpose' (OID) at a time */ + for(unsigned dex=0; dexnumPurposes; dex++) { + nssObj->purposes[dex] = (CSSM_OID *)coder.malloc(sizeof(CSSM_OID)); + coder.allocCopyItem(cdsaObj->purposes[dex], + *nssObj->purposes[dex]); + } + + /* add to mExtensions */ + cert.addExtension(nssObj, cssmExt->extnId, cssmExt->critical, false, + kSecAsn1ExtKeyUsageTemplate); +} + +bool getFieldExtKeyUsage( + DecodedItem &cert, + unsigned index, // which occurrence (0 = first) + uint32 &numFields, // RETURNED + CssmOwnedData &fieldValue) +{ + const DecodedExten *decodedExt; + NSS_ExtKeyUsage *nssObj; + CE_ExtendedKeyUsage *cdsaObj; + bool brtn; + Allocator &alloc = fieldValue.allocator; + + brtn = cert.GetExtenTop( + index, + numFields, + alloc, + CSSMOID_ExtendedKeyUsage, + nssObj, + cdsaObj, + decodedExt); + if(!brtn) { + return false; + } + + /* nssObj --> cdsaObj, one purpose at a time */ + unsigned numPurposes = clNssArraySize((const void **)nssObj->purposes); + cdsaObj->numPurposes = numPurposes; + if(numPurposes) { + unsigned len = numPurposes * sizeof(CSSM_OID); + cdsaObj->purposes = (CSSM_OID_PTR)alloc.malloc(len); + memset(cdsaObj->purposes, 0, len); + } + for(unsigned dex=0; dexpurposes[dex], cdsaObj->purposes[dex]); + } + + getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue); + return true; +} + +void freeFieldExtKeyUsage( + CssmOwnedData &fieldValue) +{ + CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, false); + Allocator &alloc = fieldValue.allocator; + CE_ExtendedKeyUsage *cdsaObj = + (CE_ExtendedKeyUsage *)cssmExt->value.parsedValue; + unsigned oidDex; + for(oidDex=0; oidDexnumPurposes; oidDex++) { + alloc.free(cdsaObj->purposes[oidDex].Data); + } + alloc.free(cdsaObj->purposes); + freeFieldExtenCommon(cssmExt, alloc); // frees extnId, parsedValue, BERvalue +} + +/*** + *** Subject Key Identifier + *** CDSA format: CE_SubjectKeyID, which is just a CSSM_DATA + *** OID CSSMOID_SubjectKeyIdentifier + ***/ + +void setFieldSubjectKeyId( + DecodedItem &cert, + const CssmData &fieldValue) +{ + CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, + false); + CE_SubjectKeyID *cdsaObj = (CE_SubjectKeyID *)cssmExt->value.parsedValue; + SecNssCoder &coder = cert.coder(); + CSSM_DATA *nssObj = (CSSM_DATA *)coder.malloc(sizeof(CSSM_DATA)); + coder.allocCopyItem(*cdsaObj, *nssObj); + + /* add to mExtensions */ + cert.addExtension(nssObj, cssmExt->extnId, cssmExt->critical, false, + kSecAsn1SubjectKeyIdTemplate); +} + +bool getFieldSubjectKeyId( + DecodedItem &cert, + unsigned index, // which occurrence (0 = first) + uint32 &numFields, // RETURNED + CssmOwnedData &fieldValue) +{ + const DecodedExten *decodedExt; + CSSM_DATA *nssObj; + CE_SubjectKeyID *cdsaObj; + bool brtn; + Allocator &alloc = fieldValue.allocator; + + brtn = cert.GetExtenTop( + index, + numFields, + alloc, + CSSMOID_SubjectKeyIdentifier, + nssObj, + cdsaObj, + decodedExt); + if(!brtn) { + return false; + } + + /* if this fails, we're out of sync with nssExtenInfo[] in + * CLFieldsCommon.cpp */ + assert(nssObj != NULL); + clAllocCopyData(alloc, *nssObj, *cdsaObj); + getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue); + return true; +} + +void freeFieldSubjectKeyId ( + CssmOwnedData &fieldValue) +{ + CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, false); + Allocator &alloc = fieldValue.allocator; + CE_SubjectKeyID *cdsaObj = (CE_SubjectKeyID *)cssmExt->value.parsedValue; + alloc.free(cdsaObj->Data); + freeFieldExtenCommon(cssmExt, alloc); // frees extnId, parsedValue, BERvalue +} + +/*** + *** Authority Key Identifier + *** CDSA format: CE_AuthorityKeyID + *** NSS format: NSS_AuthorityKeyId + *** OID CSSMOID_AuthorityKeyIdentifier + ***/ + +void setFieldAuthorityKeyId( + DecodedItem &cert, + const CssmData &fieldValue) +{ + CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, + false); + CE_AuthorityKeyID *cdsaObj = + (CE_AuthorityKeyID *)cssmExt->value.parsedValue; + + /* Alloc an NSS-style AuthorityKeyId in cert.coder's memory */ + SecNssCoder &coder = cert.coder(); + NSS_AuthorityKeyId *nssObj = + (NSS_AuthorityKeyId *)coder.malloc(sizeof(NSS_AuthorityKeyId)); + memset(nssObj, 0, sizeof(*nssObj)); + + /* convert caller's CDSA-style CE_AuthorityKeyID to NSS */ + CL_cssmAuthorityKeyIdToNss(*cdsaObj, *nssObj, coder); + + /* add to mExtensions */ + cert.addExtension(nssObj, cssmExt->extnId, cssmExt->critical, false, + kSecAsn1AuthorityKeyIdTemplate); +} + +bool getFieldAuthorityKeyId( + DecodedItem &cert, + unsigned index, // which occurrence (0 = first) + uint32 &numFields, // RETURNED + CssmOwnedData &fieldValue) +{ + const DecodedExten *decodedExt; + NSS_AuthorityKeyId *nssObj; + CE_AuthorityKeyID *cdsaObj; + bool brtn; + Allocator &alloc = fieldValue.allocator; + + brtn = cert.GetExtenTop( + index, + numFields, + alloc, + CSSMOID_AuthorityKeyIdentifier, + nssObj, + cdsaObj, + decodedExt); + if(!brtn) { + return false; + } + assert(nssObj != NULL); + + /* nssObj --> cdsaObj */ + CL_nssAuthorityKeyIdToCssm(*nssObj, *cdsaObj, cert.coder(), alloc); + + getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue); + return true; +} + +void freeFieldAuthorityKeyId ( + CssmOwnedData &fieldValue) +{ + CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, false); + Allocator &alloc = fieldValue.allocator; + CE_AuthorityKeyID *cdsaObj = (CE_AuthorityKeyID *)cssmExt->value.parsedValue; + CL_freeAuthorityKeyId(*cdsaObj, alloc); + freeFieldExtenCommon(cssmExt, alloc); // frees extnId, parsedValue, BERvalue +} + +/*** + *** Subject/Issuer alternate name + *** CDSA Format: CE_GeneralNames + *** NSS format: NSS_GeneralNames + *** OID: CSSMOID_SubjectAltName, CSSMOID_IssuerAltName + ***/ +void setFieldSubjIssuerAltName( + DecodedItem &cert, + const CssmData &fieldValue) +{ + CSSM_X509_EXTENSION_PTR cssmExt = + verifySetFreeExtension(fieldValue, false); + CE_GeneralNames *cdsaObj = (CE_GeneralNames *)cssmExt->value.parsedValue; + + /* Alloc an NSS-style GeneralNames in cert.coder's memory */ + SecNssCoder &coder = cert.coder(); + NSS_GeneralNames *nssObj = + (NSS_GeneralNames *)coder.malloc(sizeof(NSS_GeneralNames)); + memset(nssObj, 0, sizeof(*nssObj)); + + /* cdsaObj --> nssObj */ + CL_cssmGeneralNamesToNss(*cdsaObj, *nssObj, coder); + + /* add to mExtensions */ + cert.addExtension(nssObj, cssmExt->extnId, cssmExt->critical, false, + kSecAsn1GeneralNamesTemplate); +} + +bool getFieldSubjAltName( + DecodedItem &cert, + unsigned index, // which occurrence (0 = first) + uint32 &numFields, // RETURNED + CssmOwnedData &fieldValue) +{ + const DecodedExten *decodedExt; + NSS_GeneralNames *nssObj; + CE_GeneralNames *cdsaObj; + bool brtn; + + brtn = cert.GetExtenTop( + index, + numFields, + fieldValue.allocator, + CSSMOID_SubjectAltName, + nssObj, + cdsaObj, + decodedExt); + if(!brtn) { + return false; + } + CL_nssGeneralNamesToCssm(*nssObj, *cdsaObj, + cert.coder(), fieldValue.allocator); + getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue); + return true; +} + +bool getFieldIssuerAltName( + DecodedItem &cert, + unsigned index, // which occurrence (0 = first) + uint32 &numFields, // RETURNED + CssmOwnedData &fieldValue) +{ + const DecodedExten *decodedExt; + NSS_GeneralNames *nssObj; + CE_GeneralNames *cdsaObj; + bool brtn; + + brtn = cert.GetExtenTop( + index, + numFields, + fieldValue.allocator, + CSSMOID_IssuerAltName, + nssObj, + cdsaObj, + decodedExt); + if(!brtn) { + return false; + } + CL_nssGeneralNamesToCssm(*nssObj, *cdsaObj, + cert.coder(), fieldValue.allocator); + getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue); + return true; +} + +void freeFieldSubjIssuerAltName ( + CssmOwnedData &fieldValue) +{ + CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, false); + Allocator &alloc = fieldValue.allocator; + CE_GeneralNames *cdsaObj = (CE_GeneralNames *)cssmExt->value.parsedValue; + CL_freeCssmGeneralNames(cdsaObj, alloc); + freeFieldExtenCommon(cssmExt, alloc); // frees extnId, parsedValue, BERvalue +} + +/*** + *** Certificate Policies + *** CDSA Format: CE_CertPolicies + *** NSS format : NSS_CertPolicies + *** OID: CSSMOID_CertificatePolicies + ***/ + +#define MAX_IA5_NAME_SIZE 1024 + +void setFieldCertPolicies( + DecodedItem &cert, + const CssmData &fieldValue) +{ + CSSM_X509_EXTENSION_PTR cssmExt = + verifySetFreeExtension(fieldValue, false); + SecNssCoder &coder = cert.coder(); + NSS_CertPolicies *nssObj = + (NSS_CertPolicies *)coder.malloc(sizeof(NSS_CertPolicies)); + memset(nssObj, 0, sizeof(NSS_CertPolicies)); + CE_CertPolicies *cdsaObj = + (CE_CertPolicies *)cssmExt->value.parsedValue; + + if(cdsaObj->numPolicies) { + nssObj->policies = + (NSS_PolicyInformation **)clNssNullArray( + cdsaObj->numPolicies, coder); + } + for(unsigned polDex=0; polDexnumPolicies; polDex++) { + CE_PolicyInformation *cPolInfo = &cdsaObj->policies[polDex]; + NSS_PolicyInformation *nPolInfo = (NSS_PolicyInformation *) + coder.malloc(sizeof(NSS_PolicyInformation)); + memset(nPolInfo, 0, sizeof(*nPolInfo)); + nssObj->policies[polDex] = nPolInfo; + + coder.allocCopyItem(cPolInfo->certPolicyId, nPolInfo->certPolicyId); + + unsigned numQual = cPolInfo->numPolicyQualifiers; + if(numQual != 0) { + nPolInfo->policyQualifiers = + (NSS_PolicyQualifierInfo **)clNssNullArray(numQual, + coder); + } + for(unsigned qualDex=0; qualDexpolicyQualifiers[qualDex]; + NSS_PolicyQualifierInfo *nQualInfo = + (NSS_PolicyQualifierInfo *)coder.malloc( + sizeof(NSS_PolicyQualifierInfo)); + memset(nQualInfo, 0, sizeof(NSS_PolicyQualifierInfo)); + nPolInfo->policyQualifiers[qualDex] = nQualInfo; + + /* + * OK we're at the lowest level. + * policyQualifierId == id_qt_cps: qualifier is + * an IA5 string, incoming data is its contents. + * Else incoming data is an encoded blob we pass on directly. + */ + coder.allocCopyItem(cQualInfo->policyQualifierId, + nQualInfo->policyQualifierId); + + if(clCompareCssmData(&cQualInfo->policyQualifierId, + &CSSMOID_QT_CPS)) { + if(coder.encodeItem(&cQualInfo->qualifier, + kSecAsn1IA5StringTemplate, + nQualInfo->qualifier)) { + clErrorLog("setFieldCertPOlicies: IA5 encode error\n"); + CssmError::throwMe(CSSMERR_CL_MEMORY_ERROR); + } + } + else { + /* uninterpreted, copy over directly */ + coder.allocCopyItem(cQualInfo->qualifier, + nQualInfo->qualifier); + } + } /* for each qualifier */ + } /* for each policy */ + + /* add to mExtensions */ + cert.addExtension(nssObj, cssmExt->extnId, cssmExt->critical, false, + kSecAsn1CertPoliciesTemplate); +} + +bool getFieldCertPolicies( + DecodedItem &cert, + unsigned index, // which occurrence (0 = first) + uint32 &numFields, // RETURNED + CssmOwnedData &fieldValue) +{ + const DecodedExten *decodedExt; + NSS_CertPolicies *nssObj; + CE_CertPolicies *cdsaObj; + bool brtn; + Allocator &alloc = fieldValue.allocator; + brtn = cert.GetExtenTop( + index, + numFields, + fieldValue.allocator, + CSSMOID_CertificatePolicies, + nssObj, + cdsaObj, + decodedExt); + if(!brtn) { + return false; + } + assert(nssObj != NULL); + + memset(cdsaObj, 0, sizeof(*cdsaObj)); + cdsaObj->numPolicies = + clNssArraySize((const void **)nssObj->policies); + unsigned sz = cdsaObj->numPolicies * sizeof(CE_PolicyInformation); + if(sz) { + cdsaObj->policies = (CE_PolicyInformation *)alloc.malloc(sz); + memset(cdsaObj->policies, 0, sz); + } + + for(unsigned polDex=0; polDexnumPolicies; polDex++) { + CE_PolicyInformation *cPolInfo = &cdsaObj->policies[polDex]; + NSS_PolicyInformation *nPolInfo = nssObj->policies[polDex]; + clAllocCopyData(alloc, nPolInfo->certPolicyId, + cPolInfo->certPolicyId); + if(nPolInfo->policyQualifiers == NULL) { + continue; + } + + cPolInfo->numPolicyQualifiers = + clNssArraySize((const void **)nPolInfo->policyQualifiers); + sz = cPolInfo->numPolicyQualifiers * + sizeof(CE_PolicyQualifierInfo); + cPolInfo->policyQualifiers = (CE_PolicyQualifierInfo *) + alloc.malloc(sz); + memset(cPolInfo->policyQualifiers, 0, sz); + + for(unsigned qualDex=0; qualDexnumPolicyQualifiers; + qualDex++) { + NSS_PolicyQualifierInfo *nQualInfo = + nPolInfo->policyQualifiers[qualDex]; + CE_PolicyQualifierInfo *cQualInfo = + &cPolInfo->policyQualifiers[qualDex]; + + /* + * leaf. + * policyQualifierId == CSSMOID_QT_CPS : + * IA5String - decode and return contents. + * Else return whole thing. + */ + clAllocCopyData(alloc, nQualInfo->policyQualifierId, + cQualInfo->policyQualifierId); + CSSM_DATA toCopy = nQualInfo->qualifier; + if(clCompareCssmData(&nQualInfo->policyQualifierId, + &CSSMOID_QT_CPS)) { + /* decode as IA5String to temp memory */ + toCopy.Data = NULL; + toCopy.Length = 0; + if(cert.coder().decodeItem(nQualInfo->qualifier, + kSecAsn1IA5StringTemplate, + &toCopy)) { + clErrorLog("***getCertPolicies: bad IA5String!\n"); + CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT); + } + } + /* else copy out nQualInfo->qualifier */ + clAllocCopyData(alloc, toCopy, cQualInfo->qualifier); + } /* for each qualifier */ + } /* for each policy info */ + getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue); + return true; +} + +void freeFieldCertPolicies ( + CssmOwnedData &fieldValue) +{ + CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, false); + Allocator &alloc = fieldValue.allocator; + CE_CertPolicies *cdsaObj = (CE_CertPolicies *)cssmExt->value.parsedValue; + for(unsigned polDex=0; polDexnumPolicies; polDex++) { + CE_PolicyInformation *cPolInfo = &cdsaObj->policies[polDex]; + alloc.free(cPolInfo->certPolicyId.Data); + for(unsigned qualDex=0; + qualDexnumPolicyQualifiers; + qualDex++) { + CE_PolicyQualifierInfo *cQualInfo = + &cPolInfo->policyQualifiers[qualDex]; + alloc.free(cQualInfo->policyQualifierId.Data); + alloc.free(cQualInfo->qualifier.Data); + } + alloc.free(cPolInfo->policyQualifiers); + } + alloc.free(cdsaObj->policies); + freeFieldExtenCommon(cssmExt, alloc); // frees extnId, parsedValue, + // BERvalue +} + +/*** + *** Netscape cert type + *** CDSA Format: CE_NetscapeCertType (a uint16) + *** NSS format CSSM_DATA, length 2 + *** OID: CSSMOID_NetscapeCertType + ***/ +void setFieldNetscapeCertType( + DecodedItem &cert, + const CssmData &fieldValue) +{ + CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, + false); + CE_NetscapeCertType *cdsaObj = + (CE_NetscapeCertType *)cssmExt->value.parsedValue; + + /* Alloc an NSS-style key usage in cert.coder's memory */ + SecNssCoder &coder = cert.coder(); + CSSM_DATA *nssObj = (CSSM_DATA *)coder.malloc(sizeof(CSSM_DATA)); + coder.allocItem(*nssObj, 2); + + /* cdsaObj --> nssObj */ + nssObj->Data[0] = (*cdsaObj) >> 8; + nssObj->Data[1] = *cdsaObj; + + /* Adjust length for BIT STRING encoding */ + clCssmBitStringToNss(*nssObj); + + /* add to mExtensions */ + cert.addExtension(nssObj, cssmExt->extnId, cssmExt->critical, false, + kSecAsn1NetscapeCertTypeTemplate); +} + +bool getFieldNetscapeCertType( + DecodedItem &cert, + unsigned index, // which occurrence (0 = first) + uint32 &numFields, // RETURNED + CssmOwnedData &fieldValue) +{ + const DecodedExten *decodedExt; + CSSM_DATA *nssObj; + CE_NetscapeCertType *cdsaObj; + bool brtn; + + brtn = cert.GetExtenTop( + index, + numFields, + fieldValue.allocator, + CSSMOID_NetscapeCertType, + nssObj, + cdsaObj, + decodedExt); + if(!brtn) { + return false; + } + + /* make a copy - can't modify length in place */ + CSSM_DATA bitString = *nssObj; + clNssBitStringToCssm(bitString); + unsigned toCopy = bitString.Length; + if(toCopy > 2) { + /* I hope I never see this... */ + clErrorLog("getFieldKeyUsage: CertType larger than 2 bytes!"); + toCopy = 2; + } + unsigned char bits[2] = {0, 0}; + memmove(bits, bitString.Data, toCopy); + *cdsaObj = (((unsigned)bits[0]) << 8) | bits[1]; + + /* pass back to caller */ + getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue); + return true; +} + +/*** + *** CRL Distribution points + *** CDSA Format: CE_CRLDistPointsSyntax + *** NSS format: NSS_CRLDistributionPoints + *** OID: CSSMOID_CrlDistributionPoints + ***/ +void setFieldCrlDistPoints( + DecodedItem &cert, + const CssmData &fieldValue) +{ + CSSM_X509_EXTENSION_PTR cssmExt = + verifySetFreeExtension(fieldValue, false); + CE_CRLDistPointsSyntax *cdsaObj = + (CE_CRLDistPointsSyntax *)cssmExt->value.parsedValue; + SecNssCoder &coder = cert.coder(); + NSS_CRLDistributionPoints *nssObj = + (NSS_CRLDistributionPoints *)coder.malloc( + sizeof(NSS_CRLDistributionPoints)); + + CL_cssmDistPointsToNss(*cdsaObj, *nssObj, coder); + cert.addExtension(nssObj, cssmExt->extnId, cssmExt->critical, false, + kSecAsn1CRLDistributionPointsTemplate); +} + +bool getFieldCrlDistPoints( + DecodedItem &cert, + unsigned index, // which occurrence (0 = first) + uint32 &numFields, // RETURNED + CssmOwnedData &fieldValue) +{ + const DecodedExten *decodedExt; + NSS_CRLDistributionPoints *nssObj; + CE_CRLDistPointsSyntax *cdsaObj; + bool brtn; + Allocator &alloc = fieldValue.allocator; + + brtn = cert.GetExtenTop( + index, + numFields, + alloc, + CSSMOID_CrlDistributionPoints, + nssObj, + cdsaObj, + decodedExt); + if(!brtn) { + return false; + } + assert(nssObj != NULL); + CL_nssDistPointsToCssm(*nssObj, *cdsaObj, cert.coder(), alloc); + getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue); + return true; +} + +void freeFieldCrlDistPoints ( + CssmOwnedData &fieldValue) +{ + CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, false); + Allocator &alloc = fieldValue.allocator; + CE_CRLDistPointsSyntax *cdsaObj = + (CE_CRLDistPointsSyntax *)cssmExt->value.parsedValue; + CL_freeCssmDistPoints(cdsaObj, alloc); + freeFieldExtenCommon(cssmExt, alloc); // frees extnId, parsedValue, BERvalue +} + +/*** + *** {Subject,Authority}InfoAccess + *** + *** CDSA Format: CE_AuthorityInfoAccess + *** NSS format: NSS_AuthorityInfoAccess + *** OID: CSSMOID_AuthorityInfoAccess, CSSMOID_SubjectInfoAccess + ***/ +void setFieldAuthInfoAccess( + DecodedItem &cert, + const CssmData &fieldValue) +{ + CSSM_X509_EXTENSION_PTR cssmExt = + verifySetFreeExtension(fieldValue, false); + CE_AuthorityInfoAccess *cdsaObj = + (CE_AuthorityInfoAccess *)cssmExt->value.parsedValue; + SecNssCoder &coder = cert.coder(); + NSS_AuthorityInfoAccess *nssObj = + (NSS_AuthorityInfoAccess *)coder.malloc( + sizeof(NSS_AuthorityInfoAccess)); + + CL_cssmInfoAccessToNss(*cdsaObj, *nssObj, coder); + cert.addExtension(nssObj, cssmExt->extnId, cssmExt->critical, false, + kSecAsn1AuthorityInfoAccessTemplate); +} + +bool getFieldAuthInfoAccess( + DecodedItem &cert, + unsigned index, // which occurrence (0 = first) + uint32 &numFields, // RETURNED + CssmOwnedData &fieldValue) +{ + const DecodedExten *decodedExt; + NSS_AuthorityInfoAccess *nssObj; + CE_AuthorityInfoAccess *cdsaObj; + bool brtn; + Allocator &alloc = fieldValue.allocator; + + brtn = cert.GetExtenTop( + index, + numFields, + alloc, + CSSMOID_AuthorityInfoAccess, + nssObj, + cdsaObj, + decodedExt); + if(!brtn) { + return false; + } + assert(nssObj != NULL); + CL_infoAccessToCssm(*nssObj, *cdsaObj, cert.coder(), alloc); + getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue); + return true; +} + +bool getFieldSubjInfoAccess( + DecodedItem &cert, + unsigned index, // which occurrence (0 = first) + uint32 &numFields, // RETURNED + CssmOwnedData &fieldValue) +{ + const DecodedExten *decodedExt; + NSS_AuthorityInfoAccess *nssObj; + CE_AuthorityInfoAccess *cdsaObj; + bool brtn; + Allocator &alloc = fieldValue.allocator; + + brtn = cert.GetExtenTop( + index, + numFields, + alloc, + CSSMOID_SubjectInfoAccess, + nssObj, + cdsaObj, + decodedExt); + if(!brtn) { + return false; + } + assert(nssObj != NULL); + CL_infoAccessToCssm(*nssObj, *cdsaObj, cert.coder(), alloc); + getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue); + return true; +} + +void freeFieldInfoAccess ( + CssmOwnedData &fieldValue) +{ + CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, false); + Allocator &alloc = fieldValue.allocator; + CE_AuthorityInfoAccess *cdsaObj = + (CE_AuthorityInfoAccess *)cssmExt->value.parsedValue; + CL_freeInfoAccess(*cdsaObj, alloc); + freeFieldExtenCommon(cssmExt, alloc); // frees extnId, parsedValue, BERvalue + +} + +/*** + *** Qualfied Cert Statements + *** + *** CDSA Format: CE_QC_Statements + *** NSS format: NSS_QC_Statements + *** OID: CSSMOID_QC_Statements + ***/ +void setFieldQualCertStatements( + DecodedItem &cert, + const CssmData &fieldValue) +{ + CSSM_X509_EXTENSION_PTR cssmExt = + verifySetFreeExtension(fieldValue, false); + CE_QC_Statements *cdsaObj = + (CE_QC_Statements *)cssmExt->value.parsedValue; + SecNssCoder &coder = cert.coder(); + NSS_QC_Statements *nssObj = + (NSS_QC_Statements *)coder.malloc( + sizeof(NSS_QC_Statements)); + + CL_cssmQualCertStatementsToNss(*cdsaObj, *nssObj, coder); + cert.addExtension(nssObj, cssmExt->extnId, cssmExt->critical, false, + kSecAsn1QC_StatementsTemplate); +} + +bool getFieldQualCertStatements( + DecodedItem &cert, + unsigned index, // which occurrence (0 = first) + uint32 &numFields, // RETURNED + CssmOwnedData &fieldValue) +{ + const DecodedExten *decodedExt; + NSS_QC_Statements *nssObj; + CE_QC_Statements *cdsaObj; + bool brtn; + Allocator &alloc = fieldValue.allocator; + + brtn = cert.GetExtenTop( + index, + numFields, + alloc, + CSSMOID_QC_Statements, + nssObj, + cdsaObj, + decodedExt); + if(!brtn) { + return false; + } + assert(nssObj != NULL); + CL_qualCertStatementsToCssm(*nssObj, *cdsaObj, cert.coder(), alloc); + getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue); + return true; +} + +void freeFieldQualCertStatements( + CssmOwnedData &fieldValue) +{ + CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, false); + Allocator &alloc = fieldValue.allocator; + CE_QC_Statements *cdsaObj = + (CE_QC_Statements *)cssmExt->value.parsedValue; + CL_freeQualCertStatements(*cdsaObj, alloc); + freeFieldExtenCommon(cssmExt, alloc); // frees extnId, parsedValue, BERvalue +} + +/*** + *** Name Constraints + *** CDSA Format: CE_NameConstraints + *** NSS format: NSS_NameConstraints + *** OID: CSSMOID_NameConstraints + ***/ +void setFieldNameConstraints( + DecodedItem &cert, + const CssmData &fieldValue) +{ + CSSM_X509_EXTENSION_PTR cssmExt = + verifySetFreeExtension(fieldValue, false); + CE_NameConstraints *cdsaObj = + (CE_NameConstraints *)cssmExt->value.parsedValue; + SecNssCoder &coder = cert.coder(); + NSS_NameConstraints *nssObj = + (NSS_NameConstraints *)coder.malloc( + sizeof(NSS_NameConstraints)); + CL_cssmNameConstraintsToNss(*cdsaObj, *nssObj, coder); + cert.addExtension(nssObj, cssmExt->extnId, cssmExt->critical, false, + kSecAsn1NameConstraintsTemplate); +} + +bool getFieldNameConstraints( + DecodedItem &cert, + unsigned index, // which occurrence (0 = first) + uint32 &numFields, // RETURNED + CssmOwnedData &fieldValue) +{ + const DecodedExten *decodedExt; + NSS_NameConstraints *nssObj; + CE_NameConstraints *cdsaObj; + bool brtn; + Allocator &alloc = fieldValue.allocator; + + brtn = cert.GetExtenTop( + index, + numFields, + alloc, + CSSMOID_NameConstraints, + nssObj, + cdsaObj, + decodedExt); + if(!brtn) { + return false; + } + assert(nssObj != NULL); + CL_nssNameConstraintsToCssm(*nssObj, *cdsaObj, cert.coder(), alloc); + getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue); + return true; +} + +void freeFieldNameConstraints ( + CssmOwnedData &fieldValue) +{ + CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, false); + Allocator &alloc = fieldValue.allocator; + CE_NameConstraints *cdsaObj = + (CE_NameConstraints *)cssmExt->value.parsedValue; + CL_freeCssmNameConstraints(cdsaObj, alloc); + freeFieldExtenCommon(cssmExt, alloc); // frees extnId, parsedValue, BERvalue +} + +/*** + *** Policy Mappings + *** CDSA Format: CE_PolicyMappings + *** NSS format: NSS_PolicyMappings + *** OID: CSSMOID_PolicyMappings + ***/ +void setFieldPolicyMappings( + DecodedItem &cert, + const CssmData &fieldValue) +{ + CSSM_X509_EXTENSION_PTR cssmExt = + verifySetFreeExtension(fieldValue, false); + CE_PolicyMappings *cdsaObj = + (CE_PolicyMappings *)cssmExt->value.parsedValue; + SecNssCoder &coder = cert.coder(); + NSS_PolicyMappings *nssObj = + (NSS_PolicyMappings *)coder.malloc( + sizeof(NSS_PolicyMappings)); + CL_cssmPolicyMappingsToNss(*cdsaObj, *nssObj, coder); + cert.addExtension(nssObj, cssmExt->extnId, cssmExt->critical, false, + kSecAsn1PolicyMappingsTemplate); +} + +bool getFieldPolicyMappings( + DecodedItem &cert, + unsigned index, // which occurrence (0 = first) + uint32 &numFields, // RETURNED + CssmOwnedData &fieldValue) +{ + const DecodedExten *decodedExt; + NSS_PolicyMappings *nssObj; + CE_PolicyMappings *cdsaObj; + bool brtn; + Allocator &alloc = fieldValue.allocator; + + brtn = cert.GetExtenTop( + index, + numFields, + alloc, + CSSMOID_PolicyMappings, + nssObj, + cdsaObj, + decodedExt); + if(!brtn) { + return false; + } + assert(nssObj != NULL); + CL_nssPolicyMappingsToCssm(*nssObj, *cdsaObj, cert.coder(), alloc); + getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue); + return true; +} + +void freeFieldPolicyMappings ( + CssmOwnedData &fieldValue) +{ + CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, false); + Allocator &alloc = fieldValue.allocator; + CE_PolicyMappings *cdsaObj = + (CE_PolicyMappings *)cssmExt->value.parsedValue; + CL_freeCssmPolicyMappings(cdsaObj, alloc); + freeFieldExtenCommon(cssmExt, alloc); // frees extnId, parsedValue, BERvalue +} + +/*** + *** Policy Constraints + *** CDSA Format: CE_PolicyConstraints + *** NSS format: NSS_PolicyConstraints + *** OID: CSSMOID_PolicyConstraints + ***/ +void setFieldPolicyConstraints( + DecodedItem &cert, + const CssmData &fieldValue) +{ + CSSM_X509_EXTENSION_PTR cssmExt = + verifySetFreeExtension(fieldValue, false); + CE_PolicyConstraints *cdsaObj = + (CE_PolicyConstraints *)cssmExt->value.parsedValue; + SecNssCoder &coder = cert.coder(); + NSS_PolicyConstraints *nssObj = + (NSS_PolicyConstraints *)coder.malloc( + sizeof(NSS_PolicyConstraints)); + CL_cssmPolicyConstraintsToNss(cdsaObj, nssObj, coder); + cert.addExtension(nssObj, cssmExt->extnId, cssmExt->critical, false, + kSecAsn1PolicyConstraintsTemplate); +} + +bool getFieldPolicyConstraints( + DecodedItem &cert, + unsigned index, // which occurrence (0 = first) + uint32 &numFields, // RETURNED + CssmOwnedData &fieldValue) +{ + const DecodedExten *decodedExt; + NSS_PolicyConstraints *nssObj; + CE_PolicyConstraints *cdsaObj; + bool brtn; + Allocator &alloc = fieldValue.allocator; + + brtn = cert.GetExtenTop( + index, + numFields, + alloc, + CSSMOID_PolicyConstraints, + nssObj, + cdsaObj, + decodedExt); + if(!brtn) { + return false; + } + assert(nssObj != NULL); + CL_nssPolicyConstraintsToCssm(nssObj, cdsaObj, cert.coder(), alloc); + getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue); + return true; +} + +void freeFieldPolicyConstraints ( + CssmOwnedData &fieldValue) +{ + CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, false); + Allocator &alloc = fieldValue.allocator; + CE_PolicyConstraints *cdsaObj = + (CE_PolicyConstraints *)cssmExt->value.parsedValue; + CL_freeCssmPolicyConstraints(cdsaObj, alloc); + freeFieldExtenCommon(cssmExt, alloc); // frees extnId, parsedValue, BERvalue +} + +/*** + *** Inhibit Any Policy + *** CDSA Format: CE_InhibitAnyPolicy (an integer) + *** NSS format: CSSM_DATA, sizeof(uint32) + *** OID: CSSMOID_InhibitAnyPolicy + ***/ +void setFieldInhibitAnyPolicy( + DecodedItem &cert, + const CssmData &fieldValue) +{ + CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, + false); + CE_InhibitAnyPolicy *cdsaObj = + (CE_InhibitAnyPolicy *)cssmExt->value.parsedValue; + + /* Alloc in cert.coder's memory */ + SecNssCoder &coder = cert.coder(); + CSSM_DATA *nssObj = (CSSM_DATA *)coder.malloc(sizeof(CSSM_DATA)); + coder.allocItem(*nssObj, sizeof(uint32)); + + /* cdsaObj --> nssObj */ + nssObj->Data[0] = (*cdsaObj) >> 24; + nssObj->Data[1] = (*cdsaObj) >> 16; + nssObj->Data[2] = (*cdsaObj) >> 8; + nssObj->Data[3] = *cdsaObj; + + /* add to mExtensions */ + cert.addExtension(nssObj, cssmExt->extnId, cssmExt->critical, false, + kSecAsn1IntegerTemplate); +} + +bool getFieldInhibitAnyPolicy( + DecodedItem &cert, + unsigned index, // which occurrence (0 = first) + uint32 &numFields, // RETURNED + CssmOwnedData &fieldValue) +{ + const DecodedExten *decodedExt; + CSSM_DATA *nssObj; + CE_InhibitAnyPolicy *cdsaObj; + bool brtn; + + brtn = cert.GetExtenTop( + index, + numFields, + fieldValue.allocator, + CSSMOID_InhibitAnyPolicy, + nssObj, + cdsaObj, + decodedExt); + if(!brtn) { + return false; + } + + *cdsaObj = *(nssObj->Data); //%%%FIXME check this + + /* pass back to caller */ + getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue); + return true; +} + diff --git a/libsecurity_apple_x509_cl/lib/CLCertExtensions.h b/libsecurity_apple_x509_cl/lib/CLCertExtensions.h new file mode 100644 index 00000000..272a22e0 --- /dev/null +++ b/libsecurity_apple_x509_cl/lib/CLCertExtensions.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2000-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. + */ + + +/* + * CLCertExtensions.h - extern declarations of get/set/free functions implemented in + * CertExtensions,cpp and used only in CertFields.cpp. + */ + +#ifndef _CL_CERT_EXTENSIONS_H_ +#define _CL_CERT_EXTENSIONS_H_ + +#include "DecodedCert.h" +#include "CLFieldsCommon.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Functions to map OID --> {get,set,free}field + */ +getItemFieldFcn getFieldKeyUsage, getFieldBasicConstraints, + getFieldExtKeyUsage, + getFieldSubjectKeyId, getFieldAuthorityKeyId, getFieldSubjAltName, + getFieldIssuerAltName, + getFieldCertPolicies, getFieldNetscapeCertType, getFieldCrlDistPoints, + getFieldAuthInfoAccess, getFieldSubjInfoAccess, getFieldUnknownExt, + getFieldQualCertStatements, + getFieldNameConstraints, getFieldPolicyMappings, getFieldPolicyConstraints, + getFieldInhibitAnyPolicy; +setItemFieldFcn setFieldKeyUsage, setFieldBasicConstraints, + setFieldExtKeyUsage, + setFieldSubjectKeyId, setFieldAuthorityKeyId, setFieldSubjIssuerAltName, + setFieldCertPolicies, setFieldNetscapeCertType, setFieldCrlDistPoints, + setFieldAuthInfoAccess, setFieldUnknownExt, setFieldQualCertStatements, + setFieldNameConstraints, setFieldPolicyMappings, setFieldPolicyConstraints, + setFieldInhibitAnyPolicy; +freeFieldFcn freeFieldExtKeyUsage, freeFieldSubjectKeyId, + freeFieldAuthorityKeyId, freeFieldSubjIssuerAltName, + freeFieldCertPolicies, + freeFieldCrlDistPoints, freeFieldInfoAccess, freeFieldUnknownExt, + freeFieldQualCertStatements, + freeFieldNameConstraints, freeFieldPolicyMappings, freeFieldPolicyConstraints; + +#ifdef __cplusplus +} +#endif + +#endif /* _CERT_EXTENSIONS_H_*/ diff --git a/libsecurity_apple_x509_cl/lib/CLCrlExtensions.cpp b/libsecurity_apple_x509_cl/lib/CLCrlExtensions.cpp new file mode 100644 index 00000000..0519aeaf --- /dev/null +++ b/libsecurity_apple_x509_cl/lib/CLCrlExtensions.cpp @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2000-2002 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. + */ + + +/* + * CLCrlExtensions.cpp - CRL extensions support. + */ + +#include "DecodedCrl.h" +#include "CLCrlExtensions.h" +#include "CLCertExtensions.h" +#include "clNssUtils.h" +#include "clNameUtils.h" +#include "CLFieldsCommon.h" +#include +#include +#include +#include +#include + +#include + +/*** + *** get/set/free functions called out from CrlFields.cpp + ***/ +/*** + *** CrlNumber , DeltaCRL + *** CDSA format CE_CrlNumber (a uint32) + *** NSS format CSSM_DATA, length 4 + *** OID CSSMOID_CrlNumber, CSSMOID_DeltaCrlIndicator + ***/ + +/* set function for both */ +void setFieldCrlNumber( + DecodedItem &crl, + const CssmData &fieldValue) +{ + CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, + false); + CE_CrlNumber *cdsaObj = (CE_CrlNumber *)cssmExt->value.parsedValue; + + /* CSSM_DATA and its contents in crl.coder's memory */ + ArenaAllocator alloc(crl.coder()); + CSSM_DATA_PTR nssVal = (CSSM_DATA_PTR)alloc.malloc(sizeof(CSSM_DATA)); + clIntToData(*cdsaObj, *nssVal, alloc); + + /* add to mExtensions */ + crl.addExtension(nssVal, cssmExt->extnId, cssmExt->critical, false, + kSecAsn1IntegerTemplate); +} + + +bool getFieldCrlCommon( + DecodedItem &crl, + const CSSM_OID &fieldId, // identifies extension we seek + unsigned index, // which occurrence (0 = first) + uint32 &numFields, // RETURNED + CssmOwnedData &fieldValue) +{ + const DecodedExten *decodedExt; + CSSM_DATA *nssObj; + CE_CrlNumber *cdsaObj; + bool brtn; + + brtn = crl.GetExtenTop( + index, + numFields, + fieldValue.allocator, + fieldId, + nssObj, + cdsaObj, + decodedExt); + if(!brtn) { + return false; + } + *cdsaObj = clDataToInt(*nssObj, CSSMERR_CL_INVALID_CRL_POINTER); + + /* pass back to caller */ + getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue); + return true; +} + +bool getFieldCrlNumber( + DecodedItem &crl, + unsigned index, // which occurrence (0 = first) + uint32 &numFields, // RETURNED + CssmOwnedData &fieldValue) +{ + return getFieldCrlCommon(crl, CSSMOID_CrlNumber, index, numFields, + fieldValue); +} + +bool getFieldDeltaCrl( + DecodedItem &crl, + unsigned index, // which occurrence (0 = first) + uint32 &numFields, // RETURNED + CssmOwnedData &fieldValue) +{ + return getFieldCrlCommon(crl, CSSMOID_DeltaCrlIndicator, index, + numFields, fieldValue); +} + +void freeFieldIssuingDistPoint ( + CssmOwnedData &fieldValue) +{ + CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, false); + Allocator &alloc = fieldValue.allocator; + CE_IssuingDistributionPoint *cdsaObj = + (CE_IssuingDistributionPoint *)cssmExt->value.parsedValue; + CL_freeCssmIssuingDistPoint(cdsaObj, alloc); + freeFieldExtenCommon(cssmExt, alloc); // frees extnId, parsedValue, BERvalue +} + +void freeFieldCrlDistributionPoints ( + CssmOwnedData &fieldValue) +{ + CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, false); + Allocator &alloc = fieldValue.allocator; + CE_CRLDistPointsSyntax *cdsaObj = + (CE_CRLDistPointsSyntax *)cssmExt->value.parsedValue; + CL_freeCssmDistPoints(cdsaObj, alloc); + freeFieldExtenCommon(cssmExt, alloc); // frees extnId, parsedValue, BERvalue +} + +/* HoldInstructionCode - CSSM_OID */ +/* InvalidityDate - CSSM_DATA */ +void freeFieldOidOrData ( + CssmOwnedData &fieldValue) +{ + CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, false); + Allocator &alloc = fieldValue.allocator; + CSSM_DATA *cdsaObj = + (CSSM_DATA *)cssmExt->value.parsedValue; + if(cdsaObj) { + alloc.free(cdsaObj->Data); + } + freeFieldExtenCommon(cssmExt, alloc); // frees extnId, parsedValue, BERvalue +} + diff --git a/libsecurity_apple_x509_cl/lib/CLCrlExtensions.h b/libsecurity_apple_x509_cl/lib/CLCrlExtensions.h new file mode 100644 index 00000000..6c1c4d66 --- /dev/null +++ b/libsecurity_apple_x509_cl/lib/CLCrlExtensions.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2002 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. + */ + + +/* + * CLCrlExtensions.h - extern declarations of get/set/free functions + * implemented in CLCrlExtensions.cpp and used + * only in CrlFields.cpp. + * + * Created 9/8/2000 by Doug Mitchell. + * Copyright (c) 2000 by Apple Computer. + */ + +#ifndef _CL_CRL_EXTENSIONS_H_ +#define _CL_CRL_EXTENSIONS_H_ + +#include "DecodedCrl.h" +#include "CLCertExtensions.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Functions to map OID --> {get,set,free}field + */ +getItemFieldFcn getFieldCrlNumber, getFieldDeltaCrl; +setItemFieldFcn setFieldCrlNumber; +freeFieldFcn freeFieldIssuingDistPoint, freeFieldOidOrData, freeFieldCrlDistributionPoints; + +#ifdef __cplusplus +} +#endif + +#endif /* _CL_CRL_EXTENSIONS_H_*/ diff --git a/libsecurity_apple_x509_cl/lib/CLFieldsCommon.cpp b/libsecurity_apple_x509_cl/lib/CLFieldsCommon.cpp new file mode 100644 index 00000000..f507a236 --- /dev/null +++ b/libsecurity_apple_x509_cl/lib/CLFieldsCommon.cpp @@ -0,0 +1,502 @@ +/* + * Copyright (c) 2002-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. + */ + + +/* + * CLFieldsCommon.h - get/set/free routines common to certs and CRLs + */ + +#include "CLFieldsCommon.h" +#include "clNameUtils.h" +#include "clNssUtils.h" +#include "AppleX509CLSession.h" +#include +#include +#include +#include +#include + +/* + * Table to map an OID to the info needed to decode the + * associated extension + */ +typedef struct { + const CSSM_OID &oid; + unsigned nssObjLen; + const SecAsn1Template *templ; +} NssExtenInfo; + +static const NssExtenInfo nssExtenInfo[] = { + { CSSMOID_KeyUsage, + sizeof(CSSM_DATA), + kSecAsn1KeyUsageTemplate }, + { CSSMOID_BasicConstraints, + sizeof(NSS_BasicConstraints), + kSecAsn1BasicConstraintsTemplate }, + { CSSMOID_ExtendedKeyUsage, + sizeof(NSS_ExtKeyUsage), + kSecAsn1ExtKeyUsageTemplate }, + { CSSMOID_SubjectKeyIdentifier, + sizeof(CSSM_DATA), + kSecAsn1SubjectKeyIdTemplate }, + { CSSMOID_AuthorityKeyIdentifier, + sizeof(NSS_AuthorityKeyId), + kSecAsn1AuthorityKeyIdTemplate }, + { CSSMOID_SubjectAltName, + sizeof(NSS_GeneralNames), + kSecAsn1GeneralNamesTemplate }, + { CSSMOID_IssuerAltName, + sizeof(NSS_GeneralNames), + kSecAsn1GeneralNamesTemplate }, + { CSSMOID_CertificatePolicies, + sizeof(NSS_CertPolicies), + kSecAsn1CertPoliciesTemplate }, + { CSSMOID_NetscapeCertType, + sizeof(CSSM_DATA), + kSecAsn1NetscapeCertTypeTemplate }, + { CSSMOID_CrlDistributionPoints, + sizeof(NSS_CRLDistributionPoints), + kSecAsn1CRLDistributionPointsTemplate }, + { CSSMOID_CertIssuer, + sizeof(NSS_GeneralNames), + kSecAsn1GeneralNamesTemplate }, + { CSSMOID_AuthorityInfoAccess, + sizeof(NSS_AuthorityInfoAccess), + kSecAsn1AuthorityInfoAccessTemplate }, + { CSSMOID_SubjectInfoAccess, + sizeof(NSS_AuthorityInfoAccess), + kSecAsn1AuthorityInfoAccessTemplate }, + /* CRL extensions */ + { CSSMOID_CrlNumber, + sizeof(CSSM_DATA), + kSecAsn1IntegerTemplate }, + { CSSMOID_IssuingDistributionPoint, + sizeof(NSS_IssuingDistributionPoint), + kSecAsn1IssuingDistributionPointTemplate }, + { CSSMOID_HoldInstructionCode, + sizeof(CSSM_OID), + kSecAsn1ObjectIDTemplate }, + { CSSMOID_CrlReason, + sizeof(CSSM_DATA), + kSecAsn1EnumeratedTemplate }, + { CSSMOID_DeltaCrlIndicator, + sizeof(CSSM_DATA), + kSecAsn1IntegerTemplate }, + { CSSMOID_InvalidityDate, + sizeof(CSSM_DATA), + kSecAsn1GeneralizedTimeTemplate }, + { CSSMOID_QC_Statements, + sizeof(NSS_QC_Statements), + kSecAsn1QC_StatementsTemplate }, + { CSSMOID_NameConstraints, + sizeof(NSS_NameConstraints), + kSecAsn1NameConstraintsTemplate }, + { CSSMOID_PolicyMappings, + sizeof(NSS_PolicyMappings), + kSecAsn1PolicyMappingsTemplate }, + { CSSMOID_PolicyConstraints, + sizeof(NSS_PolicyConstraints), + kSecAsn1PolicyConstraintsTemplate }, + { CSSMOID_InhibitAnyPolicy, + sizeof(CSSM_DATA), + kSecAsn1IntegerTemplate }, +}; + +#define NUM_NSS_EXTEN_INFOS (sizeof(nssExtenInfo) / sizeof(nssExtenInfo[0])) + +/* + * Returns true if we find the OID. + */ +bool clOidToNssInfo( + const CSSM_OID &oid, + unsigned &nssObjLen, // RETURNED + const SecAsn1Template *&templ) // RETURNED +{ + for(unsigned dex=0; dex(fieldValue.data()); + if(berEncoded) { + if(cssmExt->BERvalue.Data == NULL) { + CssmError::throwMe(CSSMERR_CL_INVALID_FIELD_POINTER); + } + } + else { + if(cssmExt->value.parsedValue == NULL) { + CssmError::throwMe(CSSMERR_CL_INVALID_FIELD_POINTER); + } + } + return cssmExt; +} + +/* + * Common free code for all extensions. Extension-specific code must + * free anything beyond cdsaExt->Value.parsedValue, then we free everything + * else (except the extension struct itself, which is freed by + * DecodedCert::freeCertFieldData()). + * The value union may contain a parsed value, or a CSSM_X509EXT_TAGandVALUE; + * wed ont' care, we just free it. + */ +void freeFieldExtenCommon( + CSSM_X509_EXTENSION_PTR exten, + Allocator &alloc) +{ + alloc.free(exten->extnId.Data); + alloc.free(exten->BERvalue.Data); // may be NULL + alloc.free(exten->value.parsedValue); // may be NULL +} + +/* + * One common free for extensions whose parsed value doesn't go any deeper + * than cssmExt->value.parsedValue. + */ +void freeFieldSimpleExtension ( + CssmOwnedData &fieldValue) +{ + CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, + false); + freeFieldExtenCommon(cssmExt, fieldValue.allocator); +} + + +/*** + *** Common code for get/set subject/issuer name (C struct version) + *** Format = CSSM_X509_NAME + *** class Name from sm_x501if + ***/ +bool getField_RDN_NSS ( + const NSS_Name &nssName, + CssmOwnedData &fieldValue) // RETURNED +{ + /* alloc top-level CSSM_X509_NAME */ + Allocator &alloc = fieldValue.allocator; + fieldValue.malloc(sizeof(CSSM_X509_NAME)); + CSSM_X509_NAME_PTR cssmName = (CSSM_X509_NAME_PTR)fieldValue.data(); + + CL_nssNameToCssm(nssName, *cssmName, alloc); + return true; +} + +void freeField_RDN ( + CssmOwnedData &fieldValue) +{ + if(fieldValue.data() == NULL) { + return; + } + if(fieldValue.length() != sizeof(CSSM_X509_NAME)) { + CssmError::throwMe(CSSMERR_CL_INVALID_FIELD_POINTER); + } + Allocator &alloc = fieldValue.allocator; + CSSM_X509_NAME_PTR x509Name = (CSSM_X509_NAME_PTR)fieldValue.data(); + CL_freeX509Name(x509Name, alloc); + + /* top-level x509Name pointer freed by freeCertFieldData() */ +} + +/*** + *** Common code for Issuer Name, Subject Name (normalized and encoded + *** version) + *** Format = CSSM_DATA containing the DER encoding of the normalized name + ***/ +bool getField_normRDN_NSS ( + const CSSM_DATA &derName, + uint32 &numFields, // RETURNED (if successful, 0 or 1) + CssmOwnedData &fieldValue) // RETURNED +{ + if(derName.Data == NULL) { + /* This can happen during CertGetAllTemplateFields() because + * the normalized fields are only set up during cert/CRL decode */ + return false; + } + + /* + * First make a temp decoded copy which we'll be manipulating. + */ + SecNssCoder coder; + NSS_Name decodedName; + + memset(&decodedName, 0, sizeof(decodedName)); + PRErrorCode prtn = coder.decodeItem(derName, kSecAsn1NameTemplate, &decodedName); + if(prtn) { + /* + * Actually should never happen since this same bag of bits successfully + * decoded when the cert as a whole was decoded... + */ + clErrorLog("getField_normRDN decode error\n"); + CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT); + + } + + /* normalize */ + CL_normalizeX509NameNSS(decodedName, coder); + + /* encode result */ + prtn = SecNssEncodeItemOdata(&decodedName, kSecAsn1NameTemplate, fieldValue); + if(prtn) { + clErrorLog("getField_normRDN encode error\n"); + CssmError::throwMe(CSSMERR_CL_INTERNAL_ERROR); + } + numFields = 1; + return true; +} + +/*** + *** Common code for Time fields - Validity not before, Not After, + *** This Update, Next Update + *** Format: CSSM_X509_TIME + ***/ +bool getField_TimeNSS ( + const NSS_Time &nssTime, + unsigned index, // which occurrence (0 = first) + uint32 &numFields, // RETURNED + CssmOwnedData &fieldValue) // RETURNED +{ + if(!tbsGetCheck(nssTime.item.Data, index)) { + return false; + } + Allocator &alloc = fieldValue.allocator; + fieldValue.malloc(sizeof(CSSM_X509_TIME)); + CSSM_X509_TIME *cssmTime = + (CSSM_X509_TIME *)fieldValue.data(); + if(CL_nssTimeToCssm(nssTime, *cssmTime, alloc)) { + numFields = 1; + return true; + } + else { + return false; + } +} + +void setField_TimeNSS ( + const CssmData &fieldValue, + NSS_Time &nssTime, + SecNssCoder &coder) +{ + CSSM_X509_TIME *cssmTime = + (CSSM_X509_TIME *)fieldValue.data(); + CL_cssmTimeToNss(*cssmTime, nssTime, coder); +} + +void freeField_Time ( + CssmOwnedData &fieldValue) +{ + CSSM_X509_TIME *cssmTime = (CSSM_X509_TIME *)fieldValue.data(); + if(cssmTime == NULL) { + return; + } + if(fieldValue.length() != sizeof(CSSM_X509_TIME)) { + CssmError::throwMe(CSSMERR_CL_INVALID_FIELD_POINTER); + } + CL_freeCssmTime(cssmTime, fieldValue.allocator); +} + +/*** + *** TBS AlgId, Signature AlgId + *** Format = CSSM_X509_ALGORITHM_IDENTIFIER + ***/ +void getField_AlgIdNSS ( + const CSSM_X509_ALGORITHM_IDENTIFIER &srcAlgId, + CssmOwnedData &fieldValue) // RETURNED +{ + Allocator &alloc = fieldValue.allocator; + fieldValue.malloc(sizeof(CSSM_X509_ALGORITHM_IDENTIFIER)); + CSSM_X509_ALGORITHM_IDENTIFIER *destAlgId = + (CSSM_X509_ALGORITHM_IDENTIFIER *)fieldValue.data(); + CL_copyAlgId(srcAlgId, *destAlgId, alloc); +} + +void setField_AlgIdNSS ( + const CssmData &fieldValue, + CSSM_X509_ALGORITHM_IDENTIFIER &dstAlgId, + SecNssCoder &coder) +{ + CSSM_X509_ALGORITHM_IDENTIFIER *srcAlgId = + (CSSM_X509_ALGORITHM_IDENTIFIER *)fieldValue.data(); + /* allocator for this coder */ + ArenaAllocator areanAlloc(coder); + CL_copyAlgId(*srcAlgId, dstAlgId, areanAlloc); +} + +void freeField_AlgId ( + CssmOwnedData &fieldValue) +{ + CSSM_X509_ALGORITHM_IDENTIFIER *cssmAlgId = + (CSSM_X509_ALGORITHM_IDENTIFIER *)fieldValue.data(); + if(cssmAlgId == NULL) { + return; + } + if(fieldValue.length() != sizeof(CSSM_X509_ALGORITHM_IDENTIFIER)) { + CssmError::throwMe(CSSMERR_CL_INVALID_FIELD_POINTER); + } + Allocator &alloc = fieldValue.allocator; + alloc.free(cssmAlgId->algorithm.Data); + alloc.free(cssmAlgId->parameters.Data); + memset(cssmAlgId, 0, sizeof(CSSM_X509_ALGORITHM_IDENTIFIER)); +} + +/* + * Routines for common validity checking for certificateToSign fields. + * + * Call from setField*: verify field isn't already set, optionally validate + * input length + */ +void tbsSetCheck( + void *fieldToSet, + const CssmData &fieldValue, + uint32 expLength, + const char *op) +{ + if(fieldToSet != NULL) { + /* can't add another */ + clErrorLog("setField(%s): field already set", op); + CssmError::throwMe(CSSMERR_CL_INVALID_NUMBER_OF_FIELDS); + } + if((expLength != 0) && (fieldValue.length() != expLength)) { + clErrorLog("setField(%s): bad length : exp %d got %d", + op, (int)expLength, (int)fieldValue.length()); + CssmError::throwMe(CSSMERR_CL_INVALID_FIELD_POINTER); + } +} + +/* + * Call from getField* for unique fields - detect missing field or + * index out of bounds. + */ +bool tbsGetCheck( + const void *requiredField, + uint32 reqIndex) +{ + if((requiredField == NULL) || (reqIndex != 0)) { + return false; + } + else { + return true; + } +} + +/*** + *** unknown extensions + *** CDSA format: raw bytes in a CSSM_DATA. This data is the BER-encoding of + *** some extension struct we don't know about. + *** NSS format CSSM_DATA + *** OID CSSMOID_X509V3CertificateExtensionCStruct + ***/ + +void setFieldUnknownExt( + DecodedItem &cert, + const CssmData &fieldValue) +{ + CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, true); + SecNssCoder &coder = cert.coder(); + CSSM_DATA *rawExtn = (CSSM_DATA *)coder.malloc(sizeof(CSSM_DATA)); + coder.allocCopyItem(cssmExt->BERvalue, *rawExtn); + cert.addExtension(NULL, cssmExt->extnId, cssmExt->critical, + true, NULL /* no template */, rawExtn); +} + +bool getFieldUnknownExt( + DecodedItem &cert, + unsigned index, // which occurrence (0 = first) + uint32 &numFields, // RETURNED + CssmOwnedData &fieldValue) +{ + uint8 noOidDataLikeThis[2] = {1, 2}; // a dummy argument + CSSM_OID noOidLikeThis = {2, noOidDataLikeThis}; + const DecodedExten *decodedExt = + cert.DecodedItem::findDecodedExt(noOidLikeThis, + true, index, numFields); + if(decodedExt == NULL) { + return false; + } + getFieldExtenCommon(NULL, *decodedExt, fieldValue); + return true; +} + +void freeFieldUnknownExt ( + CssmOwnedData &fieldValue) +{ + CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, true); + Allocator &alloc = fieldValue.allocator; + freeFieldExtenCommon(cssmExt, alloc); // frees extnId, parsedValue, BERvalue +} + +/* setField for read-only OIDs (i.e., the ones in cert/CRL, not TBS) */ +void setField_ReadOnly ( + DecodedItem &item, + const CssmData &fieldValue) +{ + clErrorLog("Attempt to set a read-only field"); + CssmError::throwMe(CSSMERR_CL_UNKNOWN_TAG); +} + +bool getField_Unimplemented ( + DecodedItem &item, + unsigned index, // which occurrence (0 = first) + uint32 &numFields, // RETURNED + CssmOwnedData &fieldValue) // RETURNED +{ + clErrorLog("Attempt to get an unimplemented field"); + CssmError::throwMe(CSSMERR_CL_UNKNOWN_TAG); +} + + + diff --git a/libsecurity_apple_x509_cl/lib/CLFieldsCommon.h b/libsecurity_apple_x509_cl/lib/CLFieldsCommon.h new file mode 100644 index 00000000..5a403894 --- /dev/null +++ b/libsecurity_apple_x509_cl/lib/CLFieldsCommon.h @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2000-2002 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. + */ + + +/* + * CLFieldsCommon.h - get/set/free routines common to certs and CRLs + */ + +#ifndef _CL_FIELDS_COMMON_H_ +#define _CL_FIELDS_COMMON_H_ + +#include +#include + +#include "DecodedItem.h" + +#include + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * As of the NSS conversion, getField ops do NOT take a const + * DecodedItem argument since many of them use the DecodedItem's + * SecNssCoder for intermediate ops. + */ +typedef bool (getItemFieldFcn) ( + DecodedItem &item, + unsigned index, // which occurrence (0 = first) + uint32 &numFields, // RETURNED + CssmOwnedData &fieldValue); // RETURNED +typedef void (setItemFieldFcn) ( + DecodedItem &item, + const CssmData &fieldValue); +typedef void (freeFieldFcn) ( + CssmOwnedData &fieldValue); + +bool clOidToNssInfo( + const CSSM_OID &oid, + unsigned &nssObjLen, // RETURNED + const SecAsn1Template *&templ); // RETURNED + +/* + * Routines for common validity checking for certificateToSign fields. + * + * Call from setField*: verify field isn't already set, optionally validate + * input length + */ +void tbsSetCheck( + void *fieldToSet, + const CssmData &fieldValue, + uint32 expLength, + const char *op); + +/* + * Call from getField* for unique fields - detect missing field or + * index out of bounds. + */ +bool tbsGetCheck( + const void *requiredField, + uint32 reqIndex); + +/* common extension get/set/free */ +void getFieldExtenCommon( + void *cdsaObj, // e.g. CE_KeyUsage + // CSSM_DATA_PTR for berEncoded + const DecodedExten &decodedExt, + CssmOwnedData &fieldValue); + +CSSM_X509_EXTENSION_PTR verifySetFreeExtension( + const CssmData &fieldValue, + bool berEncoded); // false: value in value.parsedValue + // true : value in BERValue +void freeFieldExtenCommon( + CSSM_X509_EXTENSION_PTR exten, + Allocator &alloc); + +/* + * Common code for get/set subject/issuer name (C struct version) + */ +bool getField_RDN_NSS ( + const NSS_Name &nssName, + CssmOwnedData &fieldValue); // RETURNED + +void freeField_RDN ( + CssmOwnedData &fieldValue); + +/* get normalized RDN */ +bool getField_normRDN_NSS ( + const CSSM_DATA &derName, + uint32 &numFields, // RETURNED (if successful, 0 or 1) + CssmOwnedData &fieldValue); // RETURNED + +/* + * Common code for Time fields - Validity not before/after, this/next update + * Format: CSSM_X509_TIME + */ +void freeField_Time ( + CssmOwnedData &fieldValue); + +bool getField_TimeNSS ( + const NSS_Time &derTime, + unsigned index, // which occurrence (0 = first) + uint32 &numFields, // RETURNED + CssmOwnedData &fieldValue); // RETURNED +void setField_TimeNSS ( + const CssmData &fieldValue, + NSS_Time &nssTime, + SecNssCoder &coder); + +void getField_AlgIdNSS ( + const CSSM_X509_ALGORITHM_IDENTIFIER &srcAlgId, + CssmOwnedData &fieldValue); // RETURNED +void setField_AlgIdNSS ( + const CssmData &fieldValue, + CSSM_X509_ALGORITHM_IDENTIFIER &dstAlgId, + SecNssCoder &coder); + +void freeField_AlgId ( + CssmOwnedData &fieldValue); + +getItemFieldFcn getFieldUnknownExt, getField_Unimplemented; +setItemFieldFcn setFieldUnknownExt, setField_ReadOnly; +freeFieldFcn freeFieldUnknownExt, freeFieldSimpleExtension; + +#ifdef __cplusplus +} +#endif + +#endif /* _CL_FIELDS_COMMON_H_ */ diff --git a/libsecurity_apple_x509_cl/lib/CSPAttacher.cpp b/libsecurity_apple_x509_cl/lib/CSPAttacher.cpp new file mode 100644 index 00000000..b2e12a55 --- /dev/null +++ b/libsecurity_apple_x509_cl/lib/CSPAttacher.cpp @@ -0,0 +1,180 @@ +/* + * 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. + */ + + +/* + * CSPAttacher.cpp - process-wide class which loads and attaches to CSP at most + * once, and detaches and unloads the CSP when this code is + * unloaded. + */ + +#include "CSPAttacher.h" +#include "cldebugging.h" +#include +#include +#include +#include +#include +#include +#include + +class CSPAttacher +{ +public: + CSPAttacher() : + mCspHand(CSSM_INVALID_HANDLE), + mCspDlHand(CSSM_INVALID_HANDLE) + { } + ~CSPAttacher(); + CSSM_CSP_HANDLE getCspHand(bool bareCsp); + +private: + /* connection to CSP and CSPDL, evaluated lazily */ + CSSM_HANDLE mCspHand; + CSSM_HANDLE mCspDlHand; + Mutex mLock; +}; + +/* the single global thing */ +static ModuleNexus cspAttacher; + +static void *CL_malloc( + CSSM_SIZE size, + void *allocref) +{ + return Allocator::standard().malloc(size); +} + +static void CL_free( + void *memblock, + void *allocref) +{ + Allocator::standard().free(memblock); +} + +static void *CL_realloc( + void *memblock, + CSSM_SIZE size, + void *allocref) +{ + return Allocator::standard().realloc(memblock, size); +} + +static void *CL_calloc( + uint32 num, + CSSM_SIZE size, + void *allocref) +{ + return Allocator::standard().calloc(num, size); +} + +static const CSSM_API_MEMORY_FUNCS CL_memFuncs = { + CL_malloc, + CL_free, + CL_realloc, + CL_calloc, + NULL + }; + + +/* + * This only gets called when cspAttacher get deleted, i.e., when this code + * is actually unloaded from the process's address space. + */ +CSPAttacher::~CSPAttacher() +{ + StLock _(mLock); + + if(mCspHand != CSSM_INVALID_HANDLE) { + CSSM_ModuleDetach(mCspHand); + CSSM_ModuleUnload(&gGuidAppleCSP, NULL, NULL); + } + if(mCspDlHand != CSSM_INVALID_HANDLE) { + CSSM_ModuleDetach(mCspDlHand); + CSSM_ModuleUnload(&gGuidAppleCSPDL, NULL, NULL); + } +} + +CSSM_CSP_HANDLE CSPAttacher::getCspHand(bool bareCsp) +{ + const char *modName; + CSSM_RETURN crtn; + const CSSM_GUID *guid; + CSSM_VERSION vers = {2, 0}; + StLock _(mLock); + CSSM_CSP_HANDLE cspHand; + + if(bareCsp) { + if(mCspHand != CSSM_INVALID_HANDLE) { + /* already connected */ + return mCspHand; + } + guid = &gGuidAppleCSP; + modName = "AppleCSP"; + } + else { + if(mCspDlHand != CSSM_INVALID_HANDLE) { + /* already connected */ + return mCspDlHand; + } + guid = &gGuidAppleCSPDL; + modName = "AppleCSPDL"; + } + crtn = CSSM_ModuleLoad(guid, + CSSM_KEY_HIERARCHY_NONE, + NULL, // eventHandler + NULL); // AppNotifyCallbackCtx + if(crtn) { + clErrorLog("AppleX509CLSession::cspAttach: error (%d) loading %s", + (int)crtn, modName); + CssmError::throwMe(crtn); + } + crtn = CSSM_ModuleAttach (guid, + &vers, + &CL_memFuncs, // memFuncs + 0, // SubserviceID + CSSM_SERVICE_CSP, // SubserviceFlags + 0, // AttachFlags + CSSM_KEY_HIERARCHY_NONE, + NULL, // FunctionTable + 0, // NumFuncTable + NULL, // reserved + &cspHand); + if(crtn) { + clErrorLog("AppleX509CLSession::cspAttach: error (%d) attaching to %s", + (int)crtn, modName); + CssmError::throwMe(crtn); + } + if(bareCsp) { + mCspHand = cspHand; + } + else { + mCspDlHand = cspHand; + } + return cspHand; +} + +/* + * Just one public function - "give me a CSP handle". + * bareCsp true: AppleCSP + * bareCsp false: AppleCSPDL + */ +CSSM_CSP_HANDLE getGlobalCspHand(bool bareCsp) +{ + return cspAttacher().getCspHand(bareCsp); +} + diff --git a/libsecurity_apple_x509_cl/lib/CSPAttacher.h b/libsecurity_apple_x509_cl/lib/CSPAttacher.h new file mode 100644 index 00000000..31223bdf --- /dev/null +++ b/libsecurity_apple_x509_cl/lib/CSPAttacher.h @@ -0,0 +1,47 @@ +/* + * 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. + */ + + +/* + * CSPAttacher.h - process-wide class which loads and attaches to CSP at most + * once, and detaches and unloads the CSP when this code is + * unloaded. + */ + +#ifndef _CSP_ATTACHER_H_ +#define _CSP_ATTACHER_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Just one public function - "give me a CSP handle". + * bareCsp true : AppleCSP + * bareCsp false: AppleCSPDL + * + * Throws a CssmError on failure. + */ +extern CSSM_CSP_HANDLE getGlobalCspHand(bool bareCsp); + +#ifdef __cplusplus +} +#endif + +#endif /* _CSP_ATTACHER_H_ */ diff --git a/libsecurity_apple_x509_cl/lib/CertFields.cpp b/libsecurity_apple_x509_cl/lib/CertFields.cpp new file mode 100644 index 00000000..d034f0e8 --- /dev/null +++ b/libsecurity_apple_x509_cl/lib/CertFields.cpp @@ -0,0 +1,860 @@ +/* + * 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. + */ + + +/* + * 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. + */ + +#include "DecodedCert.h" +#include "cldebugging.h" +#include "CLCertExtensions.h" +#include "clNssUtils.h" +#include "clNameUtils.h" +#include "CLFieldsCommon.h" +#include +#include +#include + +/*** + *** Version + *** Format = DER-encoded int (max of four bytes in this case) + ***/ +static bool getField_Version ( + DecodedItem &item, + unsigned index, // which occurrence (0 = first) + uint32 &numFields, // RETURNED + CssmOwnedData &fieldValue) // RETURNED +{ + const DecodedCert &cert = dynamic_cast(item); + const CSSM_DATA &vers = cert.mCert.tbs.version; + if(!tbsGetCheck(vers.Data, index)) { + /* not present, optional */ + return false; + } + fieldValue.copy(vers.Data, vers.Length); + numFields = 1; + return true; +} + +static void setField_Version ( + DecodedItem &item, + const CssmData &fieldValue) +{ + DecodedCert &cert = dynamic_cast(item); + CSSM_DATA &vers = cert.mCert.tbs.version; + tbsSetCheck(vers.Data, fieldValue, 0, "version"); + cert.coder().allocCopyItem(fieldValue, vers); +} + + +#if this_is_a_template +/*** + *** Version + *** Format = DER-encoded int (always four bytes in this case) + ***/ +static bool getField_Version ( + DecodedItem &item, + unsigned index, // which occurrence (0 = first) + uint32 &numFields, // RETURNED + CssmOwnedData &fieldValue) // RETURNED +{ + const DecodedCert &cert = dynamic_cast(item); + tbsGetCheck(cert.certificateToSign->version, index); +} +static void setField_Version ( + DecodedItem &item, + const CssmData &fieldValue) +{ + DecodedCert &cert = dynamic_cast(item); + tbsSetCheck(cert.certificateToSign->version, fieldValue, sizeof(uint32), + "version"); + +} +static void freeField_Version ( + CssmOwnedData &fieldValue) +{ +} +#endif + +/*** + *** Serial Number + *** Format = DER-encoded int, variable length + ***/ +static bool getField_SerialNumber ( + DecodedItem &item, + unsigned index, // which occurrence (0 = first) + uint32 &numFields, // RETURNED + CssmOwnedData &fieldValue) // RETURNED +{ + const DecodedCert &cert = dynamic_cast(item); + const CSSM_DATA &sn = cert.mCert.tbs.serialNumber; + if(!tbsGetCheck(sn.Data, index)) { + return false; + } + fieldValue.copy(sn.Data, sn.Length); + numFields = 1; + return true; +} + +static void setField_SerialNumber ( + DecodedItem &item, + const CssmData &fieldValue) +{ + DecodedCert &cert = dynamic_cast(item); + CSSM_DATA &sn = cert.mCert.tbs.serialNumber; + tbsSetCheck(sn.Data, fieldValue, 0, "SerialNumber"); + cert.coder().allocCopyItem(fieldValue, sn); +} + +/*** issuer/subject + *** Format = CSSM_X509_NAME + *** class Name from sm_x501if + ***/ +static bool getField_Issuer ( + DecodedItem &item, + unsigned index, // which occurrence (0 = first) + uint32 &numFields, // RETURNED + CssmOwnedData &fieldValue) // RETURNED +{ + if(index != 0) { + return false; + } + + bool brtn; + + const DecodedCert &cert = dynamic_cast(item); + try { + brtn = getField_RDN_NSS(cert.mCert.tbs.issuer, fieldValue); + if(brtn) { + numFields = 1; + } + } + catch (...) { + freeField_RDN(fieldValue); + throw; + } + return brtn; +} + +static void setField_Issuer ( + DecodedItem &item, + const CssmData &fieldValue) +{ + DecodedCert &cert = dynamic_cast(item); + const CSSM_X509_NAME *cssmName = (const CSSM_X509_NAME *)fieldValue.Data; + NSS_Name &nssName = cert.mCert.tbs.issuer; + tbsSetCheck(nssName.rdns, fieldValue, sizeof(CSSM_X509_NAME), + "IssuerName"); + CL_cssmNameToNss(*cssmName, nssName, cert.coder()); +} + +/*** subject ***/ +static bool getField_Subject ( + DecodedItem &item, + unsigned index, // which occurrence (0 = first) + uint32 &numFields, // RETURNED + CssmOwnedData &fieldValue) // RETURNED +{ + if(index != 0) { + return false; + } + + bool brtn; + + const DecodedCert &cert = dynamic_cast(item); + try { + brtn = getField_RDN_NSS(cert.mCert.tbs.subject, fieldValue); + if(brtn) { + numFields = 1; + } + } + catch (...) { + freeField_RDN(fieldValue); + throw; + } + return brtn; +} + +static void setField_Subject ( + DecodedItem &item, + const CssmData &fieldValue) +{ + DecodedCert &cert = dynamic_cast(item); + const CSSM_X509_NAME *cssmName = (const CSSM_X509_NAME *)fieldValue.Data; + NSS_Name &nssName = cert.mCert.tbs.subject; + tbsSetCheck(nssName.rdns, fieldValue, sizeof(CSSM_X509_NAME), + "SubjectName"); + CL_cssmNameToNss(*cssmName, nssName, cert.coder()); +} + +/*** + *** Issuer Name, Subject Name (normalized and encoded version) + *** Format = CSSM_DATA containing the DER encoding of the normalized name + ***/ +static bool getFieldSubjectNorm( + DecodedItem &item, + unsigned index, // which occurrence (0 = first) + uint32 &numFields, // RETURNED + CssmOwnedData &fieldValue) // RETURNED +{ + if(index != 0) { + return false; + } + const DecodedCert &cert = dynamic_cast(item); + return getField_normRDN_NSS(cert.mCert.tbs.derSubject, numFields, + fieldValue); +} + +static bool getFieldIssuerNorm( + DecodedItem &item, + unsigned index, // which occurrence (0 = first) + uint32 &numFields, // RETURNED + CssmOwnedData &fieldValue) // RETURNED +{ + if(index != 0) { + return false; + } + const DecodedCert &cert = dynamic_cast(item); + return getField_normRDN_NSS(cert.mCert.tbs.derIssuer, numFields, fieldValue); +} + +/*** + *** Issuer Name, Subject Name (encoded, NON-normalized version) + *** Format = CSSM_DATA containing the DER encoding of the name + ***/ +static bool getFieldSubjectStd( + DecodedItem &item, + unsigned index, // which occurrence (0 = first) + uint32 &numFields, // RETURNED + CssmOwnedData &fieldValue) // RETURNED +{ + if(index != 0) { + return false; + } + const DecodedCert &cert = dynamic_cast(item); + fieldValue.copy(cert.mCert.tbs.derSubject); + numFields = 1; + return true; +} + +static bool getFieldIssuerStd( + DecodedItem &item, + unsigned index, // which occurrence (0 = first) + uint32 &numFields, // RETURNED + CssmOwnedData &fieldValue) // RETURNED +{ + if(index != 0) { + return false; + } + const DecodedCert &cert = dynamic_cast(item); + fieldValue.copy(cert.mCert.tbs.derIssuer); + numFields = 1; + return true; +} + +/*** + *** TBS AlgId, Signature AlgId + *** Format = CSSM_X509_ALGORITHM_IDENTIFIER + ***/ +/* TBS AlgId */ +static bool getField_TbsAlgId ( + DecodedItem &item, + unsigned index, // which occurrence (0 = first) + uint32 &numFields, // RETURNED + CssmOwnedData &fieldValue) // RETURNED +{ + const DecodedCert &cert = dynamic_cast(item); + const CSSM_X509_ALGORITHM_IDENTIFIER &srcAlgId = cert.mCert.tbs.signature; + if(!tbsGetCheck(srcAlgId.algorithm.Data, index)) { + return false; + } + getField_AlgIdNSS(srcAlgId, fieldValue); + numFields = 1; + return true; +} + +static void setField_TbsAlgId ( + DecodedItem &item, + const CssmData &fieldValue) +{ + DecodedCert &cert = dynamic_cast(item); + CSSM_X509_ALGORITHM_IDENTIFIER &dstAlgId = cert.mCert.tbs.signature; + tbsSetCheck(dstAlgId.algorithm.Data, fieldValue, + sizeof(CSSM_X509_ALGORITHM_IDENTIFIER), "TBS_AlgId"); + setField_AlgIdNSS(fieldValue, dstAlgId, cert.coder()); +} + +/* Cert AlgId - read only */ +static bool getField_CertAlgId ( + DecodedItem &item, + unsigned index, // which occurrence (0 = first) + uint32 &numFields, // RETURNED + CssmOwnedData &fieldValue) // RETURNED +{ + const DecodedCert &cert = dynamic_cast(item); + const CSSM_X509_ALGORITHM_IDENTIFIER &srcAlgId = cert.mCert.signatureAlgorithm; + if(!tbsGetCheck(srcAlgId.algorithm.Data, index)) { + return false; + } + getField_AlgIdNSS(srcAlgId, fieldValue); + numFields = 1; + return true; +} + +/*** + *** Validity not before, not after + *** Format: CSSM_X509_TIME + ***/ + +/*** not before ***/ +static bool getField_NotBefore ( + DecodedItem &item, + unsigned index, // which occurrence (0 = first) + uint32 &numFields, // RETURNED + CssmOwnedData &fieldValue) // RETURNED +{ + const DecodedCert &cert = dynamic_cast(item); + const NSS_Time &srcTime = cert.mCert.tbs.validity.notBefore; + return getField_TimeNSS(srcTime, index, numFields, fieldValue); +} + +static void setField_NotBefore ( + DecodedItem &item, + const CssmData &fieldValue) +{ + DecodedCert &cert = dynamic_cast(item); + NSS_Time &dstTime = cert.mCert.tbs.validity.notBefore; + tbsSetCheck(dstTime.item.Data, fieldValue, + sizeof(CSSM_X509_TIME), "NotBefore"); + setField_TimeNSS(fieldValue, dstTime, cert.coder()); +} + +/*** not after ***/ +static bool getField_NotAfter ( + DecodedItem &item, + unsigned index, // which occurrence (0 = first) + uint32 &numFields, // RETURNED + CssmOwnedData &fieldValue) // RETURNED +{ + const DecodedCert &cert = dynamic_cast(item); + const NSS_Time &srcTime = cert.mCert.tbs.validity.notAfter; + return getField_TimeNSS(srcTime, index, numFields, fieldValue); +} + +static void setField_NotAfter ( + DecodedItem &item, + const CssmData &fieldValue) +{ + DecodedCert &cert = dynamic_cast(item); + NSS_Time &dstTime = cert.mCert.tbs.validity.notAfter; + tbsSetCheck(dstTime.item.Data, fieldValue, + sizeof(CSSM_X509_TIME), "NotAfter"); + setField_TimeNSS(fieldValue, dstTime, cert.coder()); +} + +/*** + *** Subject/issuer unique ID + *** Format: Raw bytes. It's stored in the cert as an ASN bit string; the decoded + *** bytes are present at this level (i.e., not tag and length in the bytes). + *** NOTE: this is not quite accurate in that we only provide byte-aligned size, + *** not bit-aligned. This field is rarely if ever used so I think it's O, but + *** beware. + ***/ +static bool getField_SubjectUniqueId ( + DecodedItem &item, + unsigned index, // which occurrence (0 = first) + uint32 &numFields, // RETURNED + CssmOwnedData &fieldValue) // RETURNED +{ + const DecodedCert &cert = dynamic_cast(item); + const CSSM_DATA &srcBits = cert.mCert.tbs.subjectID; + if(!tbsGetCheck(srcBits.Data, index)) { + return false; + } + + /* That CSSM_DATA is a decoded BITSTRING; its length is in bits */ + CSSM_DATA tmp = srcBits; + tmp.Length = (tmp.Length + 7) / 8; + fieldValue.copy(tmp.Data, tmp.Length); + numFields = 1; + return true; +} + +static void setField_SubjectUniqueId ( + DecodedItem &item, + const CssmData &fieldValue) +{ + DecodedCert &cert = dynamic_cast(item); + CSSM_DATA &dstBits = cert.mCert.tbs.subjectID; + tbsSetCheck(dstBits.Data, fieldValue, 0, "SubjectUniqueID"); + cert.coder().allocCopyItem(fieldValue, dstBits); + dstBits.Length *= 8; +} + +static bool getField_IssuerUniqueId ( + DecodedItem &item, + unsigned index, // which occurrence (0 = first) + uint32 &numFields, // RETURNED + CssmOwnedData &fieldValue) // RETURNED +{ + const DecodedCert &cert = dynamic_cast(item); + const CSSM_DATA &srcBits = cert.mCert.tbs.issuerID; + if(!tbsGetCheck(srcBits.Data, index)) { + return false; + } + + /* That CSSM_DATA is a decoded BITSTRING; its length is in bits */ + CSSM_DATA tmp = srcBits; + tmp.Length = (tmp.Length + 7) / 8; + fieldValue.copy(tmp.Data, tmp.Length); + numFields = 1; + return true; +} + +static void setField_IssuerUniqueId ( + DecodedItem &item, + const CssmData &fieldValue) +{ + DecodedCert &cert = dynamic_cast(item); + CSSM_DATA &dstBits = cert.mCert.tbs.issuerID; + tbsSetCheck(dstBits.Data, fieldValue, 0, "IssuerUniqueID"); + cert.coder().allocCopyItem(fieldValue, dstBits); + dstBits.Length *= 8; +} + +/*** + *** Public key info + *** Format = CSSM_X509_SUBJECT_PUBLIC_KEY_INFO + ***/ +static bool getField_PublicKeyInfo ( + DecodedItem &item, + unsigned index, // which occurrence (0 = first) + uint32 &numFields, // RETURNED + CssmOwnedData &fieldValue) // RETURNED +{ + const DecodedCert &cert = dynamic_cast(item); + const CSSM_X509_SUBJECT_PUBLIC_KEY_INFO &srcInfo = + cert.mCert.tbs.subjectPublicKeyInfo; + if(!tbsGetCheck(srcInfo.subjectPublicKey.Data, index)) { + return false; + } + + Allocator &alloc = fieldValue.allocator; + fieldValue.malloc(sizeof(CSSM_X509_SUBJECT_PUBLIC_KEY_INFO)); + CSSM_X509_SUBJECT_PUBLIC_KEY_INFO *dstInfo = + (CSSM_X509_SUBJECT_PUBLIC_KEY_INFO *)fieldValue.data(); + + CL_copySubjPubKeyInfo(srcInfo, true, // length in bits here + *dstInfo, false, // length in bytes + alloc); + + numFields = 1; + return true; +} + +static void setField_PublicKeyInfo ( + DecodedItem &item, + const CssmData &fieldValue) +{ + DecodedCert &cert = dynamic_cast(item); + CSSM_X509_SUBJECT_PUBLIC_KEY_INFO &dstKeyInfo = + cert.mCert.tbs.subjectPublicKeyInfo; + tbsSetCheck(dstKeyInfo.subjectPublicKey.Data, fieldValue, + sizeof(CSSM_X509_SUBJECT_PUBLIC_KEY_INFO), "PubKeyInfo"); + + CSSM_X509_SUBJECT_PUBLIC_KEY_INFO *srcKeyInfo = + (CSSM_X509_SUBJECT_PUBLIC_KEY_INFO *)fieldValue.Data; + if((srcKeyInfo->subjectPublicKey.Data == NULL) || + (srcKeyInfo->subjectPublicKey.Length == 0)) { + CssmError::throwMe(CSSMERR_CL_INVALID_FIELD_POINTER); + } + + ArenaAllocator arenaAlloc(cert.coder()); + CL_copySubjPubKeyInfo(*srcKeyInfo, false, // length in bytes here + dstKeyInfo, true, // length in bits + arenaAlloc); +} + +static void freeField_PublicKeyInfo ( + CssmOwnedData &fieldValue) +{ + CSSM_X509_SUBJECT_PUBLIC_KEY_INFO *cssmKeyInfo = + (CSSM_X509_SUBJECT_PUBLIC_KEY_INFO *)fieldValue.data(); + if(cssmKeyInfo == NULL) { + return; + } + Allocator &alloc = fieldValue.allocator; + CL_freeCssmAlgId(&cssmKeyInfo->algorithm, alloc); + alloc.free(cssmKeyInfo->subjectPublicKey.Data); + memset(cssmKeyInfo, 0, sizeof(CSSM_X509_SUBJECT_PUBLIC_KEY_INFO));} + +/*** + *** key info from CSSM_KEY + *** Format = CSSM_KEY + ***/ +static bool getField_PublicKeyStruct ( + DecodedItem &item, + unsigned index, // which occurrence (0 = first) + uint32 &numFields, // RETURNED + CssmOwnedData &fieldValue) // RETURNED +{ + const DecodedCert &cert = dynamic_cast(item); + if(!tbsGetCheck(cert.mCert.tbs.subjectPublicKeyInfo.subjectPublicKey.Data, + index)) { + return false; + } + CSSM_KEY_PTR cssmKey = cert.extractCSSMKey(fieldValue.allocator); + fieldValue.set(reinterpret_cast(cssmKey), sizeof(CSSM_KEY)); + numFields = 1; + return true; +} + +static void setField_PublicKeyStruct ( + DecodedItem &item, + const CssmData &fieldValue) +{ + DecodedCert &cert = dynamic_cast(item); + CSSM_X509_SUBJECT_PUBLIC_KEY_INFO &dstKeyInfo = + cert.mCert.tbs.subjectPublicKeyInfo; + tbsSetCheck(dstKeyInfo.subjectPublicKey.Data, fieldValue, + sizeof(CSSM_KEY), "PubKeyStruct"); + + CSSM_KEY_PTR cssmKey = (CSSM_KEY_PTR)fieldValue.data(); + if((cssmKey->KeyData.Data == NULL) || + (cssmKey->KeyData.Data == 0)) { + CssmError::throwMe(CSSMERR_CL_INVALID_FIELD_POINTER); + } + CL_CSSMKeyToSubjPubKeyInfoNSS(*cssmKey, dstKeyInfo, cert.coder()); +} + +static void freeField_PublicKeyStruct ( + CssmOwnedData &fieldValue) +{ + CSSM_KEY_PTR cssmKey = (CSSM_KEY_PTR)fieldValue.data(); + CL_freeCSSMKey(cssmKey, fieldValue.allocator, false); +} + +/*** + *** Signature + *** Format = raw bytes + *** read-only + ***/ +static bool getField_Signature ( + DecodedItem &item, + unsigned index, // which occurrence (0 = first) + uint32 &numFields, // RETURNED + CssmOwnedData &fieldValue) // RETURNED +{ + const DecodedCert &cert = dynamic_cast(item); + const CSSM_DATA &sigBits = cert.mCert.signature; + if(!tbsGetCheck(sigBits.Data, index)) { + return false; + } + fieldValue.copy(sigBits.Data, (sigBits.Length + 7) / 8); + numFields = 1; + return true; +} + +/*** + *** end of field-specific triplets + ***/ + +/* + * Table to map OID to {get,set,free}field + */ +typedef struct { + const CSSM_OID *fieldId; + getItemFieldFcn *getFcn; + setItemFieldFcn *setFcn; + freeFieldFcn *freeFcn; // OPTIONAL - NULL means just free the + // top-level data +} oidToFieldFuncs; + +static const oidToFieldFuncs fieldFuncTable[] = { + { &CSSMOID_X509V1Version, + &getField_Version, &setField_Version, NULL }, + { &CSSMOID_X509V1SerialNumber, + &getField_SerialNumber, &setField_SerialNumber, NULL }, + { &CSSMOID_X509V1IssuerNameCStruct, + &getField_Issuer, &setField_Issuer, &freeField_RDN }, + { &CSSMOID_X509V1SubjectNameCStruct, + &getField_Subject, &setField_Subject, &freeField_RDN }, + { &CSSMOID_X509V1SignatureAlgorithmTBS, + &getField_TbsAlgId, &setField_TbsAlgId, &freeField_AlgId }, + { &CSSMOID_X509V1SignatureAlgorithm, + &getField_CertAlgId, &setField_ReadOnly, &freeField_AlgId }, + { &CSSMOID_X509V1ValidityNotBefore, + &getField_NotBefore, &setField_NotBefore, &freeField_Time }, + { &CSSMOID_X509V1ValidityNotAfter, + &getField_NotAfter, &setField_NotAfter, &freeField_Time }, + { &CSSMOID_X509V1CertificateIssuerUniqueId, + &getField_IssuerUniqueId, &setField_IssuerUniqueId, NULL }, + { &CSSMOID_X509V1CertificateSubjectUniqueId, + &getField_SubjectUniqueId, &setField_SubjectUniqueId, NULL }, + { &CSSMOID_X509V1SubjectPublicKeyCStruct, + &getField_PublicKeyInfo, &setField_PublicKeyInfo, &freeField_PublicKeyInfo }, + { &CSSMOID_CSSMKeyStruct, + &getField_PublicKeyStruct, &setField_PublicKeyStruct, + &freeField_PublicKeyStruct }, + { &CSSMOID_X509V1Signature, + &getField_Signature, &setField_ReadOnly, NULL }, + { &CSSMOID_X509V1IssuerName, + getFieldIssuerNorm, &setField_ReadOnly, NULL }, + { &CSSMOID_X509V1SubjectName, + getFieldSubjectNorm, &setField_ReadOnly, NULL }, + { &CSSMOID_X509V1IssuerNameStd, + getFieldIssuerStd, &setField_ReadOnly, NULL }, + { &CSSMOID_X509V1SubjectNameStd, + getFieldSubjectStd, &setField_ReadOnly, NULL }, + + /* + * Extensions, implemented in CLCertExtensions.cpp + * When adding new ones, also add to: + * -- clOidToNssInfo() in CLFieldsCommon.cpp + * -- get/set/free functions in CLCertExtensions.{cpp,h} + */ + { &CSSMOID_KeyUsage, &getFieldKeyUsage, &setFieldKeyUsage, + &freeFieldSimpleExtension }, + { &CSSMOID_BasicConstraints, &getFieldBasicConstraints, + &setFieldBasicConstraints, &freeFieldSimpleExtension }, + { &CSSMOID_ExtendedKeyUsage, &getFieldExtKeyUsage, + &setFieldExtKeyUsage, &freeFieldExtKeyUsage } , + { &CSSMOID_SubjectKeyIdentifier, &getFieldSubjectKeyId, + &setFieldSubjectKeyId, &freeFieldSubjectKeyId } , + { &CSSMOID_AuthorityKeyIdentifier, &getFieldAuthorityKeyId, + &setFieldAuthorityKeyId, &freeFieldAuthorityKeyId } , + { &CSSMOID_SubjectAltName, &getFieldSubjAltName, + &setFieldSubjIssuerAltName, &freeFieldSubjIssuerAltName } , + { &CSSMOID_IssuerAltName, &getFieldIssuerAltName, + &setFieldSubjIssuerAltName, &freeFieldSubjIssuerAltName } , + { &CSSMOID_CertificatePolicies, &getFieldCertPolicies, + &setFieldCertPolicies, &freeFieldCertPolicies } , + { &CSSMOID_NetscapeCertType, &getFieldNetscapeCertType, + &setFieldNetscapeCertType, &freeFieldSimpleExtension } , + { &CSSMOID_CrlDistributionPoints, &getFieldCrlDistPoints, + &setFieldCrlDistPoints, &freeFieldCrlDistPoints }, + { &CSSMOID_X509V3CertificateExtensionCStruct, &getFieldUnknownExt, + &setFieldUnknownExt, &freeFieldUnknownExt }, + { &CSSMOID_AuthorityInfoAccess, &getFieldAuthInfoAccess, + &setFieldAuthInfoAccess, &freeFieldInfoAccess }, + { &CSSMOID_SubjectInfoAccess, &getFieldSubjInfoAccess, + &setFieldAuthInfoAccess, &freeFieldInfoAccess }, + { &CSSMOID_QC_Statements, &getFieldQualCertStatements, + &setFieldQualCertStatements, &freeFieldQualCertStatements }, + + { &CSSMOID_NameConstraints, &getFieldNameConstraints, + &setFieldNameConstraints, &freeFieldNameConstraints }, + { &CSSMOID_PolicyMappings, &getFieldPolicyMappings, + &setFieldPolicyMappings, &freeFieldPolicyMappings }, + { &CSSMOID_PolicyConstraints, &getFieldPolicyConstraints, + &setFieldPolicyConstraints, &freeFieldPolicyConstraints }, + { &CSSMOID_InhibitAnyPolicy, &getFieldInhibitAnyPolicy, + &setFieldInhibitAnyPolicy, &freeFieldSimpleExtension }, + +}; + +#define NUM_KNOWN_FIELDS (sizeof(fieldFuncTable) / sizeof(oidToFieldFuncs)) +#define NUM_STD_CERT_FIELDS 17 /* not including extensions */ + +/* map an OID to an oidToFieldFuncs */ +static const oidToFieldFuncs *oidToFields( + const CssmOid &fieldId) +{ + const oidToFieldFuncs *fieldTable = fieldFuncTable; + for(unsigned i=0; ifieldId)) { + return fieldTable; + } + fieldTable++; + } + CssmError::throwMe(CSSMERR_CL_UNKNOWN_TAG); +} + + +/*** + *** Public functions + ***/ + +/* + * Obtain the index'th occurrence of field specified by fieldId in specified cert. + * Format of the returned field depends on fieldId. + * Returns total number of fieldId fields in the cert if index is 0. + * FieldValue assumed to be empty on entry. + * Returns true if specified field was found, else returns false. + */ +bool DecodedCert::getCertFieldData( + const CssmOid &fieldId, // which field + unsigned index, // which occurrence (0 = first) + uint32 &numFields, // RETURNED + CssmOwnedData &fieldValue) // RETURNED +{ + switch(mState) { + case IS_Empty: + case IS_Building: + clErrorLog("DecodedCert::getCertField: can't parse undecoded cert!"); + CssmError::throwMe(CSSMERR_CL_INTERNAL_ERROR); + case IS_DecodedAll: + case IS_DecodedTBS: + break; + } + const oidToFieldFuncs *fieldFuncs = oidToFields(fieldId); + return fieldFuncs->getFcn(*this, index, numFields, fieldValue); +} + +/* + * Set the field specified by fieldId in the specified Cert. + * Note no index - individual field routines either append (for extensions) + * or if field already set ::throwMe(for all others) + */ +void DecodedCert::setCertField( + const CssmOid &fieldId, // which field + const CssmData &fieldValue) +{ + switch(mState) { + case IS_Empty: // first time thru + mState = IS_Building; + break; + case IS_Building: // subsequent passes + break; + case IS_DecodedAll: + case IS_DecodedTBS: + clErrorLog("DecodedCert::setCertField: can't build on a decoded cert!"); + CssmError::throwMe(CSSMERR_CL_INTERNAL_ERROR); + } + if((fieldValue.data() == NULL) || (fieldValue.length() == 0)) { + CssmError::throwMe(CSSMERR_CL_INVALID_FIELD_POINTER); + } + const oidToFieldFuncs *fieldFuncs = oidToFields(fieldId); + const CssmData &value = CssmData::overlay(fieldValue); + fieldFuncs->setFcn(*this, value); +} + +/* + * Free the fieldId-specific data referred to by fieldValue->Data. + */ +void DecodedCert::freeCertFieldData( + const CssmOid &fieldId, + CssmOwnedData &fieldValue) +{ + if((fieldValue.data() == NULL) || (fieldValue.length() == 0)) { + CssmError::throwMe(CSSM_ERRCODE_INVALID_FIELD_POINTER); + } + const oidToFieldFuncs *fieldFuncs = oidToFields(fieldId); + if(fieldFuncs->freeFcn != NULL) { + /* optional - simple cases handled below */ + fieldFuncs->freeFcn(fieldValue); + } + fieldValue.reset(); + fieldValue.release(); + +} + + +/* + * Common means to get all fields from a decoded cert. Used in + * CertGetAllTemplateFields and CertGetAllFields. + */ +void DecodedCert::getAllParsedCertFields( + uint32 &NumberOfFields, // RETURNED + CSSM_FIELD_PTR &CertFields) // RETURNED +{ + /* this is the max - some might be missing */ + uint32 maxFields = NUM_STD_CERT_FIELDS + mDecodedExtensions.numExtensions(); + CSSM_FIELD_PTR outFields = (CSSM_FIELD_PTR)mAlloc.malloc(maxFields * sizeof(CSSM_FIELD)); + + /* + * We'll be copying oids and values for fields we find into + * outFields; current number of valid fields found in numOutFields. + */ + memset(outFields, 0, maxFields * sizeof(CSSM_FIELD)); + uint32 numOutFields = 0; + CSSM_FIELD_PTR currOutField; + uint32 currOidDex; + const CSSM_OID *currOid; + CssmAutoData aData(mAlloc); // for malloc/copy of outgoing data + + /* query for each OID we know about */ + for(currOidDex=0; currOidDexfieldId; + uint32 numFields; // for THIS oid + + /* + * Return false if field not there, which is not an error here. + * Actual exceptions are fatal. + */ + if(!fieldFuncs->getFcn(*this, + 0, // index - looking for first one + numFields, + aData)) { + continue; + } + + /* got some data for this oid - copy it and oid to outgoing CertFields */ + assert(numOutFields < maxFields); + currOutField = &outFields[numOutFields]; + currOutField->FieldValue = aData.release(); + aData.copy(*currOid); + currOutField->FieldOid = aData.release(); + numOutFields++; + + /* if more fields are available for this OID, snag them too */ + for(uint32 fieldDex=1; fieldDexgetFcn(*this, + fieldDex, + numFields, // shouldn't change + aData); + if(!brtn) { + clErrorLog("getAllParsedCertFields: index screwup"); + CssmError::throwMe(CSSMERR_CL_INTERNAL_ERROR); + } + assert(numOutFields < maxFields); + currOutField = &outFields[numOutFields]; + currOutField->FieldValue = aData.release(); + aData.copy(*currOid); + currOutField->FieldOid = aData.release(); + numOutFields++; + } /* multiple fields for currOid */ + } /* for each known OID */ + + NumberOfFields = numOutFields; + CertFields = outFields; +} + +void +DecodedCert::describeFormat( + Allocator &alloc, + uint32 &NumberOfFields, + CSSM_OID_PTR &OidList) +{ + /* malloc in app's space, do deep copy (including ->Data) */ + CSSM_OID_PTR oidList = (CSSM_OID_PTR)alloc.malloc( + NUM_KNOWN_FIELDS * sizeof(CSSM_OID)); + memset(oidList, 0, NUM_KNOWN_FIELDS * sizeof(CSSM_OID)); + for(unsigned i=0; i +#include "cldebugging.h" +#include "CLCrlExtensions.h" +#include "CLCertExtensions.h" +#include "CLFieldsCommon.h" +#include "clNssUtils.h" +#include "clNameUtils.h" +#include +#include +#include +#include +#include + +static void CL_freeCssmExtensions( + CSSM_X509_EXTENSIONS &extens, + Allocator &alloc); + +/*** + *** Version + *** Format = DER-encoded int (max of four bytes in this case) + ***/ +static bool getField_Version ( + DecodedItem &item, + unsigned index, // which occurrence (0 = first) + uint32 &numFields, // RETURNED + CssmOwnedData &fieldValue) // RETURNED +{ + const DecodedCrl &crl = dynamic_cast(item); + const CSSM_DATA &vers = crl.mCrl.tbs.version; + if(!tbsGetCheck(vers.Data, index)) { + /* not present, optional */ + return false; + } + fieldValue.copy(vers.Data, vers.Length); + numFields = 1; + return true; +} + +static void setField_Version ( + DecodedItem &item, + const CssmData &fieldValue) +{ + DecodedCrl &crl = dynamic_cast(item); + CSSM_DATA &vers = crl.mCrl.tbs.version; + tbsSetCheck(vers.Data, fieldValue, 0, "version"); + crl.coder().allocCopyItem(fieldValue, vers); +} + +/*** issuer + *** Format = CSSM_X509_NAME + *** class Name from sm_x501if + ***/ +static bool getField_Issuer ( + DecodedItem &item, + unsigned index, // which occurrence (0 = first) + uint32 &numFields, // RETURNED + CssmOwnedData &fieldValue) // RETURNED +{ + if(index != 0) { + return false; + } + + bool brtn; + + const DecodedCrl &crl = dynamic_cast(item); + try { + brtn = getField_RDN_NSS(crl.mCrl.tbs.issuer, fieldValue); + if(brtn) { + numFields = 1; + } + } + catch (...) { + freeField_RDN(fieldValue); + throw; + } + return brtn; +} + +static void setField_Issuer ( + DecodedItem &item, + const CssmData &fieldValue) +{ + DecodedCrl &crl = dynamic_cast(item); + const CSSM_X509_NAME *cssmName = (const CSSM_X509_NAME *)fieldValue.Data; + NSS_Name &nssName = crl.mCrl.tbs.issuer; + tbsSetCheck(nssName.rdns, fieldValue, sizeof(CSSM_X509_NAME), + "IssuerName"); + CL_cssmNameToNss(*cssmName, nssName, crl.coder()); +} + +/*** + *** This/Next update + *** Format: CSSM_X509_TIME + ***/ +static bool getField_ThisUpdate ( + DecodedItem &item, + unsigned index, // which occurrence (0 = first) + uint32 &numFields, // RETURNED + CssmOwnedData &fieldValue) // RETURNED +{ + const DecodedCrl &crl = dynamic_cast(item); + const NSS_Time &srcTime = crl.mCrl.tbs.thisUpdate; + return getField_TimeNSS(srcTime, index, numFields, fieldValue); +} + +static void setField_ThisUpdate ( + DecodedItem &item, + const CssmData &fieldValue) +{ + DecodedCrl &crl = dynamic_cast(item); + NSS_Time &dstTime = crl.mCrl.tbs.thisUpdate; + tbsSetCheck(dstTime.item.Data, fieldValue, + sizeof(CSSM_X509_TIME), "NotBefore"); + setField_TimeNSS(fieldValue, dstTime, crl.coder()); +} + +static bool getField_NextUpdate ( + DecodedItem &item, + unsigned index, // which occurrence (0 = first) + uint32 &numFields, // RETURNED + CssmOwnedData &fieldValue) // RETURNED +{ + const DecodedCrl &crl = dynamic_cast(item); + const NSS_Time &srcTime = crl.mCrl.tbs.nextUpdate; + return getField_TimeNSS(srcTime, index, numFields, fieldValue); +} + +static void setField_NextUpdate ( + DecodedItem &item, + const CssmData &fieldValue) +{ + DecodedCrl &crl = dynamic_cast(item); + NSS_Time &dstTime = crl.mCrl.tbs.nextUpdate; + tbsSetCheck(dstTime.item.Data, fieldValue, + sizeof(CSSM_X509_TIME), "NotBefore"); + setField_TimeNSS(fieldValue, dstTime, crl.coder()); +} + +/*** + *** Issuer Name (normalized and encoded version) + *** Format = CSSM_DATA containing the DER encoding of the normalized name + ***/ +static bool getFieldIssuerNorm( + DecodedItem &item, + unsigned index, // which occurrence (0 = first) + uint32 &numFields, // RETURNED + CssmOwnedData &fieldValue) // RETURNED +{ + if(index != 0) { + return false; + } + const DecodedCrl &crl = dynamic_cast(item); + return getField_normRDN_NSS(crl.mCrl.tbs.derIssuer, numFields, + fieldValue); +} + +/*** + *** TBS AlgId + *** Format = CSSM_X509_ALGORITHM_IDENTIFIER + ***/ +static bool getField_CrlTbsAlgId ( + DecodedItem &item, + unsigned index, // which occurrence (0 = first) + uint32 &numFields, // RETURNED + CssmOwnedData &fieldValue) // RETURNED +{ + const DecodedCrl &crl = dynamic_cast(item); + const CSSM_X509_ALGORITHM_IDENTIFIER &srcAlgId = + crl.mCrl.signatureAlgorithm; + if(!tbsGetCheck(srcAlgId.algorithm.Data, index)) { + return false; + } + getField_AlgIdNSS(srcAlgId, fieldValue); + numFields = 1; + return true; +} + +/* + * Support for entries in revocation list + */ +static void nssRevokedEntryToCssm( + NSS_RevokedCert &nssEntry, + CSSM_X509_REVOKED_CERT_ENTRY &cssmEntry, + Allocator &alloc) +{ + clAllocCopyData(alloc, nssEntry.userCertificate, cssmEntry.certificateSerialNumber); + CL_nssTimeToCssm(nssEntry.revocationDate, cssmEntry.revocationDate, alloc); + + /* CSSM_X509_EXTENSIONS extensions */ + NSS_CertExtension **nssExtens = nssEntry.extensions; + if(nssExtens == NULL) { + /* done */ + return; + } + + /* + * First we have to decode the NSS-style Extensions into a + * DecodedExtensions object. For cert- and CRL-wide extensions, this + * is done at the construction of Decoded{Cert,Crl}. However for + * per-CRL-entry entensions, this is (currently) the only place + * this decoding is done. + */ + SecNssCoder coder; + DecodedExtensions decodedExtens(coder, alloc); + decodedExtens.decodeFromNss(nssExtens); + + /* convert to CDSA style */ + decodedExtens.convertToCdsa(cssmEntry.extensions, alloc); +} + +static void freeCssmEntry( + CSSM_X509_REVOKED_CERT_ENTRY_PTR cssmEntry, + Allocator &alloc) +{ + if(cssmEntry == NULL) { + return; + } + if(cssmEntry->certificateSerialNumber.Data) { + alloc.free(cssmEntry->certificateSerialNumber.Data); + cssmEntry->certificateSerialNumber.Data = NULL; + cssmEntry->certificateSerialNumber.Length = 0; + } + CL_freeCssmTime(&cssmEntry->revocationDate, alloc); + + /* CSSM_X509_EXTENSIONS extensions */ + CL_freeCssmExtensions(cssmEntry->extensions, alloc); + + memset(cssmEntry, 0, sizeof(CSSM_X509_REVOKED_CERT_ENTRY)); +} + +static void nssRevokedListToCssm( + NSS_RevokedCert **nssList, // may be NULL + CSSM_X509_REVOKED_CERT_LIST_PTR cssmList, + Allocator &alloc) +{ + unsigned numEntries = clNssArraySize((const void **)nssList); + cssmList->numberOfRevokedCertEntries = numEntries; + if(numEntries == 0) { + cssmList->revokedCertEntry = NULL; + return; + } + cssmList->revokedCertEntry = (CSSM_X509_REVOKED_CERT_ENTRY_PTR)alloc.malloc( + sizeof(CSSM_X509_REVOKED_CERT_ENTRY) * numEntries); + memset(cssmList->revokedCertEntry, 0, + sizeof(CSSM_X509_REVOKED_CERT_ENTRY) * numEntries); + for(unsigned dex=0; dexrevokedCertEntry[dex]; + nssRevokedEntryToCssm(*nssEntry, *cssmEntry, alloc); + } +} + + +static void freeCssmRevokedList( + CSSM_X509_REVOKED_CERT_LIST_PTR cssmList, + Allocator &alloc) +{ + if(cssmList == NULL) { + return; + } + for(unsigned dex=0; dexnumberOfRevokedCertEntries; dex++) { + CSSM_X509_REVOKED_CERT_ENTRY_PTR cssmEntry = + &cssmList->revokedCertEntry[dex]; + freeCssmEntry(cssmEntry, alloc); + } + if(cssmList->revokedCertEntry) { + alloc.free(cssmList->revokedCertEntry); + } + memset(cssmList, 0, sizeof(CSSM_X509_REVOKED_CERT_LIST)); +} + +/*** + *** SignedCRL + *** Format: CSSM_X509_SIGNED_CRL (the whole enchilada, parsed) + ***/ +static bool getField_SignedCrl ( + DecodedItem &item, + unsigned index, // which occurrence (0 = first) + uint32 &numFields, // RETURNED + CssmOwnedData &fieldValue) // RETURNED +{ + Allocator &alloc = fieldValue.allocator; + + const DecodedCrl &nssCrl = dynamic_cast(item); + const NSS_TBSCrl &nssTbs = nssCrl.mCrl.tbs; + fieldValue.malloc(sizeof(CSSM_X509_SIGNED_CRL)); + CSSM_X509_SIGNED_CRL &cssmCrl = *((CSSM_X509_SIGNED_CRL *)fieldValue.data()); + + memset(&cssmCrl, 0, sizeof(CSSM_X509_SIGNED_CRL)); + CSSM_X509_TBS_CERTLIST &cssmTbs = cssmCrl.tbsCertList; + + /* version */ + clAllocCopyData(alloc, nssTbs.version, cssmTbs.version); + + /* CSSM_X509_ALGORITHM_IDENTIFIER signature - in TBS and CRL */ + CL_copyAlgId(nssTbs.signature, cssmTbs.signature, alloc); + CL_copyAlgId(nssCrl.mCrl.signatureAlgorithm, + cssmCrl.signature.algorithmIdentifier, alloc); + + /* CSSM_X509_NAME issuer */ + CL_nssNameToCssm(nssTbs.issuer, cssmTbs.issuer, alloc); + + /* CSSM_X509_TIME thisUpdate, nextUpdate */ + CL_nssTimeToCssm(nssTbs.thisUpdate, cssmTbs.thisUpdate, alloc); + CL_nssTimeToCssm(nssTbs.nextUpdate, cssmTbs.nextUpdate, alloc); + + /* CSSM_X509_REVOKED_CERT_LIST_PTR revokedCertificates */ + if(nssTbs.revokedCerts != NULL) { + cssmTbs.revokedCertificates = (CSSM_X509_REVOKED_CERT_LIST_PTR) + alloc.malloc(sizeof(CSSM_X509_REVOKED_CERT_LIST)); + memset(cssmTbs.revokedCertificates, 0, sizeof(CSSM_X509_REVOKED_CERT_LIST)); + nssRevokedListToCssm(nssTbs.revokedCerts, + cssmTbs.revokedCertificates, alloc); + } + + /* CSSM_X509_EXTENSIONS extensions */ + const DecodedExtensions &decodedExtens = nssCrl.decodedExtens(); + decodedExtens.convertToCdsa(cssmTbs.extensions, alloc); + + /* raw signature - stored in bits - note signature.algId set above */ + CSSM_DATA nssSig = nssCrl.mCrl.signature; + nssSig.Length = (nssSig.Length + 7) / 8; + clAllocCopyData(alloc, nssSig, cssmCrl.signature.encrypted); + numFields = 1; + return true; +} + +static void setField_SignedCrl ( + DecodedItem &item, + const CssmData &fieldValue) +{ + /* TBD - writing CRLs not supported now */ + CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); +} + +void freeField_SignedCrl ( + CssmOwnedData &fieldValue) +{ + CSSM_X509_SIGNED_CRL *cssmCrl = + (CSSM_X509_SIGNED_CRL *)fieldValue.data(); + + if(cssmCrl == NULL) { + return; + } + if(fieldValue.length() != sizeof(CSSM_X509_SIGNED_CRL)) { + CssmError::throwMe(CSSMERR_CL_INVALID_FIELD_POINTER); + } + Allocator &alloc = fieldValue.allocator; + CSSM_X509_TBS_CERTLIST_PTR cssmTbs = &cssmCrl->tbsCertList; + if(cssmTbs == NULL) { + CssmError::throwMe(CSSMERR_CL_INVALID_FIELD_POINTER); + } + + /* run down the fields */ + if(cssmTbs->version.Data) { + alloc.free(cssmTbs->version.Data); + } + + /* CSSM_X509_ALGORITHM_IDENTIFIER signature - in TBS and CRL */ + CL_freeCssmAlgId(&cssmTbs->signature, alloc); + CL_freeCssmAlgId(&cssmCrl->signature.algorithmIdentifier, alloc); + + /* issuer, thisUpdate, nextUpdate */ + CL_freeX509Name(&cssmTbs->issuer, alloc); + CL_freeCssmTime(&cssmTbs->thisUpdate, alloc); + CL_freeCssmTime(&cssmTbs->nextUpdate, alloc); + + /* CSSM_X509_REVOKED_CERT_LIST_PTR revokedCertificates */ + freeCssmRevokedList(cssmTbs->revokedCertificates, alloc); + alloc.free(cssmTbs->revokedCertificates); + + /* CSSM_X509_EXTENSIONS extensions */ + CL_freeCssmExtensions(cssmTbs->extensions, alloc); + + /* raw signature - note signature.algId freed above */ + alloc.free(cssmCrl->signature.encrypted.Data); + + memset(cssmCrl, 0, sizeof(CSSM_X509_SIGNED_CRL)); +} + +/* + * Table to map OID to {get,set,free}field + */ +typedef struct { + const CSSM_OID *fieldId; + getItemFieldFcn *getFcn; + setItemFieldFcn *setFcn; + freeFieldFcn *freeFcn; // OPTIONAL - NULL means just free the + // top-level data +} oidToFieldFuncs; + + +static const oidToFieldFuncs crlFieldTable[] = { + /* this first one, which returns everything in a parsed format, + * is intended to be normally the only field used */ + { &CSSMOID_X509V2CRLSignedCrlCStruct, + &getField_SignedCrl, &setField_SignedCrl, &freeField_SignedCrl }, + { &CSSMOID_X509V2CRLVersion, + &getField_Version, &setField_Version, NULL }, + { &CSSMOID_X509V1CRLIssuerNameCStruct, + &getField_Issuer, &setField_Issuer, &freeField_RDN }, + { &CSSMOID_X509V1CRLThisUpdate, + &getField_ThisUpdate, &setField_ThisUpdate, &freeField_Time }, + { &CSSMOID_X509V1CRLNextUpdate, + &getField_NextUpdate, &setField_NextUpdate, &freeField_Time }, + { &CSSMOID_X509V1IssuerName, + getFieldIssuerNorm, &setField_ReadOnly, NULL }, + { &CSSMOID_X509V1SignatureAlgorithmTBS, + &getField_CrlTbsAlgId, &setField_ReadOnly, &freeField_AlgId }, + // ...etc.. + /* + * Extensions, implemented in CrlExtensions.cpp + * When adding new ones, also add to: + * -- clOidToNssInfo() in CLFieldsCommon.cpp + * -- get/set/free functions in CrlExtensions.{cpp,h} + * -- DecodedExten::parse in DecodedExtensions.cpp + */ + { &CSSMOID_CrlNumber, + &getFieldCrlNumber, &setFieldCrlNumber, freeFieldSimpleExtension }, + { &CSSMOID_DeltaCrlIndicator, + &getFieldDeltaCrl, &setFieldCrlNumber, freeFieldSimpleExtension }, + { &CSSMOID_CertIssuer, // get/set not implemented + &getField_Unimplemented, &setField_ReadOnly, + &freeFieldSubjIssuerAltName}, + { &CSSMOID_CrlReason, // get/set not implemented + &getField_Unimplemented, &setField_ReadOnly, + freeFieldSimpleExtension}, + { &CSSMOID_IssuingDistributionPoint, // get/set not implemented + &getField_Unimplemented, &setField_ReadOnly, + &freeFieldIssuingDistPoint}, + { &CSSMOID_HoldInstructionCode, // get/set not implemented + &getField_Unimplemented, &setField_ReadOnly, + &freeFieldOidOrData}, + { &CSSMOID_InvalidityDate, // get/set not implemented + &getField_Unimplemented, &setField_ReadOnly, + &freeFieldOidOrData}, + + /* in common with CertExtensions */ + { &CSSMOID_AuthorityKeyIdentifier, &getFieldAuthorityKeyId, + &setFieldAuthorityKeyId, &freeFieldAuthorityKeyId } , + { &CSSMOID_X509V3CertificateExtensionCStruct, &getFieldUnknownExt, + &setFieldUnknownExt, &freeFieldUnknownExt }, + { &CSSMOID_SubjectAltName, &getFieldSubjAltName, + &setFieldSubjIssuerAltName, &freeFieldSubjIssuerAltName } , + { &CSSMOID_IssuerAltName, &getFieldIssuerAltName, + &setFieldSubjIssuerAltName, &freeFieldSubjIssuerAltName } , + + { &CSSMOID_CrlDistributionPoints, // get/set not implemented + &getField_Unimplemented, &setField_ReadOnly, + &freeFieldCrlDistributionPoints}, + // etc.. +}; + +#define NUM_KNOWN_FIELDS (sizeof(crlFieldTable) / sizeof(oidToFieldFuncs)) +#define NUM_STD_CRL_FIELDS 2 /* TBD not including extensions */ + +/* map an OID to an oidToFieldFuncs */ +static const oidToFieldFuncs *oidToFields( + const CssmOid &fieldId) +{ + const oidToFieldFuncs *fieldTable = crlFieldTable; + for(unsigned i=0; ifieldId)) { + return fieldTable; + } + fieldTable++; + } + CssmError::throwMe(CSSMERR_CL_UNKNOWN_TAG); +} + +/* + * Common routine to free OID-specific field data. Used in the + * public DecodedCrl::freeCrlFieldData and when freeing + * extensions in a CSSM_X509_TBS_CERTLIST. + */ +static void CL_freeCrlFieldData( + const CssmOid &fieldId, + CssmOwnedData &fieldValue, + bool reset = true) +{ + if((fieldValue.data() == NULL) || (fieldValue.length() == 0)) { + CssmError::throwMe(CSSM_ERRCODE_INVALID_FIELD_POINTER); + } + const oidToFieldFuncs *fieldFuncs = oidToFields(fieldId); + if(fieldFuncs->freeFcn != NULL) { + /* optional - simple cases handled below */ + fieldFuncs->freeFcn(fieldValue); + } + if(reset) { + fieldValue.reset(); + fieldValue.release(); + } +} + +/* + * Common routime to free a CSSM_X509_EXTENSIONS. Used to free + * CSSM_X509_TBS_CERTLIST.extensions and + * CSSM_X509_REVOKED_CERT_ENTRY.extensions. + * We just cook up a CssmOid and a CssmOwnedData for each extension + * and pass to CL_freeCrlFieldData(). + */ +static void CL_freeCssmExtensions( + CSSM_X509_EXTENSIONS &extens, + Allocator &alloc) +{ + for(uint32 dex=0; dexformat) { + case CSSM_X509_DATAFORMAT_ENCODED: + fieldOid = &CSSMOID_X509V3CertificateExtensionCStruct; + break; + case CSSM_X509_DATAFORMAT_PARSED: + case CSSM_X509_DATAFORMAT_PAIR: + fieldOid = &exten->extnId; + break; + default: + clErrorLog("CL_freeCssmExtensions: bad exten->format (%d)", + (int)exten->format); + CssmError::throwMe(CSSMERR_CL_INVALID_FIELD_POINTER); + } + + const CssmOid &fieldId = CssmOid::overlay(*fieldOid); + + if (exten->extnId.Data != NULL) // if this is null, something threw when it was instantiated + { + CssmData cData((uint8 *)exten, sizeof(CSSM_X509_EXTENSION)); + CssmRemoteData fieldValue(alloc, cData); + CL_freeCrlFieldData(fieldId, fieldValue, false); + fieldValue.release(); // but no free (via reset() */ + } + } + alloc.free(extens.extensions); + memset(&extens, 0, sizeof(CSSM_X509_EXTENSIONS)); +} + + + +/*** + *** Public functions + ***/ + +/* + * Obtain the index'th occurrence of field specified by fieldId in specified cert. + * Format of the returned field depends on fieldId. + * Returns total number of fieldId fields in the cert if index is 0. + * FieldValue assumed to be empty on entry. + * Returns true if specified field was found, else returns false. + */ +bool DecodedCrl::getCrlFieldData( + const CssmOid &fieldId, // which field + unsigned index, // which occurrence (0 = first) + uint32 &numFields, // RETURNED + CssmOwnedData &fieldValue) // RETURNED +{ + switch(mState) { + case IS_Empty: + case IS_Building: + clErrorLog("DecodedCrl::getCrlField: can't parse undecoded CRL!"); + CssmError::throwMe(CSSMERR_CL_INTERNAL_ERROR); + case IS_DecodedAll: + case IS_DecodedTBS: + break; + } + const oidToFieldFuncs *fieldFuncs = oidToFields(fieldId); + return fieldFuncs->getFcn(*this, index, numFields, fieldValue); +} + +/* + * Set the field specified by fieldId in the specified Cert. + * Note no index - individual field routines either append (for extensions) + * or if field already set ::throwMe(for all others) + */ +void DecodedCrl::setCrlField( + const CssmOid &fieldId, // which field + const CssmData &fieldValue) +{ + switch(mState) { + case IS_Empty: // first time thru + mState = IS_Building; + break; + case IS_Building: // subsequent passes + break; + case IS_DecodedAll: + case IS_DecodedTBS: + clErrorLog("DecodedCrl::setCrlField: can't build on a decoded CRL!"); + CssmError::throwMe(CSSMERR_CL_INTERNAL_ERROR); + } + if((fieldValue.data() == NULL) || (fieldValue.length() == 0)) { + CssmError::throwMe(CSSMERR_CL_INVALID_FIELD_POINTER); + } + const oidToFieldFuncs *fieldFuncs = oidToFields(fieldId); + const CssmData &value = CssmData::overlay(fieldValue); + fieldFuncs->setFcn(*this, value); +} + +/* + * Free the fieldId-specific data referred to by fieldValue->Data. + * No state from DecodedCrl needed; use the routine shared with + * CL_freeCssmExtensions(). + */ +void DecodedCrl::freeCrlFieldData( + const CssmOid &fieldId, + CssmOwnedData &fieldValue) +{ + CL_freeCrlFieldData(fieldId, fieldValue); +} + + +/* + * Common means to get all fields from a decoded CRL. Used in + * CrlGetAllTemplateFields and CrlGetAllFields. + */ +void DecodedCrl::getAllParsedCrlFields( + uint32 &NumberOfFields, // RETURNED + CSSM_FIELD_PTR &CrlFields) // RETURNED +{ + /* this is the max - some might be missing */ + uint32 maxFields = NUM_STD_CRL_FIELDS + mDecodedExtensions.numExtensions(); + CSSM_FIELD_PTR outFields = (CSSM_FIELD_PTR)mAlloc.malloc( + maxFields * sizeof(CSSM_FIELD)); + + /* + * We'll be copying oids and values for fields we find into + * outFields; current number of valid fields found in numOutFields. + */ + memset(outFields, 0, maxFields * sizeof(CSSM_FIELD)); + uint32 numOutFields = 0; + CSSM_FIELD_PTR currOutField; + uint32 currOidDex; + const CSSM_OID *currOid; + CssmAutoData aData(mAlloc); // for malloc/copy of outgoing data + + /* query for each OID we know about */ + for(currOidDex=0; currOidDexfieldId; + uint32 numFields; // for THIS oid + + /* + * Return false if field not there, which is not an error here. + * Actual exceptions are fatal. + */ + if(!fieldFuncs->getFcn(*this, + 0, // index - looking for first one + numFields, + aData)) { + continue; + } + + /* got some data for this oid - copy it and oid to outgoing CrlFields */ + assert(numOutFields < maxFields); + currOutField = &outFields[numOutFields]; + currOutField->FieldValue = aData.release(); + aData.copy(*currOid); + currOutField->FieldOid = aData.release(); + numOutFields++; + + /* if more fields are available for this OID, snag them too */ + for(uint32 fieldDex=1; fieldDexgetFcn(*this, + fieldDex, + numFields, // shouldn't change + aData); + if(!brtn) { + clErrorLog("getAllParsedCrlFields: index screwup"); + CssmError::throwMe(CSSMERR_CL_INTERNAL_ERROR); + } + assert(numOutFields < maxFields); + currOutField = &outFields[numOutFields]; + currOutField->FieldValue = aData.release(); + aData.copy(*currOid); + currOutField->FieldOid = aData.release(); + numOutFields++; + } /* multiple fields for currOid */ + } /* for each known OID */ + + NumberOfFields = numOutFields; + CrlFields = outFields; +} + +void +DecodedCrl::describeFormat( + Allocator &alloc, + uint32 &NumberOfFields, + CSSM_OID_PTR &OidList) +{ + /* malloc in app's space, do deep copy (including ->Data) */ + CSSM_OID_PTR oidList = (CSSM_OID_PTR)alloc.malloc( + NUM_KNOWN_FIELDS * sizeof(CSSM_OID)); + memset(oidList, 0, NUM_KNOWN_FIELDS * sizeof(CSSM_OID)); + for(unsigned i=0; i +#include + +DecodedCert::DecodedCert( + AppleX509CLSession &session) + : DecodedItem(session) +{ + memset(&mCert, 0, sizeof(mCert)); +} + +/* one-shot constructor, decoding from DER-encoded data */ +DecodedCert::DecodedCert( + AppleX509CLSession &session, + const CssmData &encodedCert) + : DecodedItem(session) +{ + memset(&mCert, 0, sizeof(mCert)); + PRErrorCode prtn = mCoder.decode(encodedCert.data(), encodedCert.length(), + kSecAsn1SignedCertTemplate, &mCert); + if(prtn) { + CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT); + } + mDecodedExtensions.decodeFromNss(mCert.tbs.extensions); + mState = IS_DecodedAll; +} + +DecodedCert::~DecodedCert() +{ +} + +/* decode TBSCert and its extensions */ +void DecodedCert::decodeTbs( + const CssmData &encodedTbs) +{ + assert(mState == IS_Empty); + + memset(&mCert, 0, sizeof(mCert)); + PRErrorCode prtn = mCoder.decode(encodedTbs.data(), encodedTbs.length(), + kSecAsn1TBSCertificateTemplate, &mCert.tbs); + if(prtn) { + CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT); + } + mDecodedExtensions.decodeFromNss(mCert.tbs.extensions); + mState = IS_DecodedTBS; +} + +void DecodedCert::encodeExtensions() +{ + NSS_TBSCertificate &tbs = mCert.tbs; + assert(mState == IS_Building); + assert(tbs.extensions == NULL); + + if(mDecodedExtensions.numExtensions() == 0) { + /* no extensions, no error */ + return; + } + mDecodedExtensions.encodeToNss(tbs.extensions); +} + +/* + * FIXME : how to determine max encoding size at run time!? + */ +#define MAX_TEMPLATE_SIZE (8 * 1024) + +/* encode TBS component; only called from CertCreateTemplate */ +void DecodedCert::encodeTbs( + CssmOwnedData &encodedTbs) +{ + encodeExtensions(); + assert(mState == IS_Building); + + /* enforce required fields - could go deeper, maybe we should */ + NSS_TBSCertificate &tbs = mCert.tbs; + if((tbs.signature.algorithm.Data == NULL) || + (tbs.issuer.rdns == NULL) || + (tbs.subject.rdns == NULL) || + (tbs.subjectPublicKeyInfo.subjectPublicKey.Data == NULL)) { + clErrorLog("DecodedCert::encodeTbs: incomplete TBS"); + /* an odd, undocumented error return */ + CssmError::throwMe(CSSMERR_CL_NO_FIELD_VALUES); + } + + PRErrorCode prtn; + prtn = SecNssEncodeItemOdata(&tbs, kSecAsn1TBSCertificateTemplate, + encodedTbs); + if(prtn) { + CssmError::throwMe(CSSMERR_CL_MEMORY_ERROR); + } +} + +/* + * Cook up CSSM_KEYUSE, gleaning as much as possible from + * (optional) extensions. If no applicable extensions available, + * we'll just return CSSM_KEYUSE_ANY. + * + * Note that the standard KeyUsage flags involving 'signing' translate + * to verify since we're only dealing with public keys. + */ +CSSM_KEYUSE DecodedCert::inferKeyUsage() const +{ + CSSM_KEYUSE keyUse = 0; + const DecodedExten *decodedExten; + uint32 numFields; + + /* Basic KeyUsage */ + decodedExten = DecodedItem::findDecodedExt(CSSMOID_KeyUsage, false, + 0, numFields); + if(decodedExten) { + CSSM_DATA *ku = (CSSM_DATA *)decodedExten->nssObj(); + assert(ku != NULL); + CE_KeyUsage kuse = clBitStringToKeyUsage(*ku); + if(kuse & CE_KU_DigitalSignature) { + keyUse |= CSSM_KEYUSE_VERIFY; + } + if(kuse & CE_KU_NonRepudiation) { + keyUse |= CSSM_KEYUSE_VERIFY; + } + if(kuse & CE_KU_KeyEncipherment) { + keyUse |= CSSM_KEYUSE_WRAP; + } + if(kuse & CE_KU_KeyAgreement) { + keyUse |= CSSM_KEYUSE_DERIVE; + } + if(kuse & CE_KU_KeyCertSign) { + keyUse |= CSSM_KEYUSE_VERIFY; + } + if(kuse & CE_KU_CRLSign) { + keyUse |= CSSM_KEYUSE_VERIFY; + } + if(kuse & CE_KU_DataEncipherment) { + keyUse |= CSSM_KEYUSE_ENCRYPT; + } + } + + /* Extended key usage */ + decodedExten = DecodedItem::findDecodedExt(CSSMOID_ExtendedKeyUsage, + false, 0, numFields); + if(decodedExten) { + NSS_ExtKeyUsage *euse = (NSS_ExtKeyUsage *)decodedExten->nssObj(); + assert(euse != NULL); + unsigned numUses = clNssArraySize((const void **)euse->purposes); + for(unsigned dex=0; dexpurposes[dex]; + if(clCompareCssmData(thisUse, &CSSMOID_ExtendedKeyUsageAny)) { + /* we're done */ + keyUse = CSSM_KEYUSE_ANY; + break; + } + else if(clCompareCssmData(thisUse, &CSSMOID_ServerAuth)) { + keyUse |= (CSSM_KEYUSE_VERIFY | CSSM_KEYUSE_ENCRYPT | CSSM_KEYUSE_DERIVE); + } + else if(clCompareCssmData(thisUse, &CSSMOID_ClientAuth)) { + keyUse |= (CSSM_KEYUSE_VERIFY | CSSM_KEYUSE_ENCRYPT | CSSM_KEYUSE_DERIVE); + } + else if(clCompareCssmData(thisUse, &CSSMOID_ExtendedUseCodeSigning)) { + keyUse |= CSSM_KEYUSE_VERIFY; + } + else if(clCompareCssmData(thisUse, &CSSMOID_EmailProtection)) { + keyUse |= + (CSSM_KEYUSE_VERIFY | CSSM_KEYUSE_WRAP | CSSM_KEYUSE_DERIVE); + } + else if(clCompareCssmData(thisUse, &CSSMOID_TimeStamping)) { + keyUse |= CSSM_KEYUSE_VERIFY; + } + else if(clCompareCssmData(thisUse, &CSSMOID_OCSPSigning)) { + keyUse |= CSSM_KEYUSE_VERIFY; + } + else if(clCompareCssmData(thisUse, &CSSMOID_APPLE_EKU_SYSTEM_IDENTITY)) { + /* system identity - fairly liberal: CMS as well as SSL */ + keyUse |= + (CSSM_KEYUSE_VERIFY | CSSM_KEYUSE_WRAP | CSSM_KEYUSE_ENCRYPT); + } + else if(clCompareCssmData(thisUse, &CSSMOID_KERBv5_PKINIT_KP_CLIENT_AUTH)) { + /* + * Kerberos PKINIT client: + * -- KDC verifies client signature in a CMS msg in AS-REQ + * -- KDC encrypts for client in a CMS msg in AS-REP + */ + keyUse |= (CSSM_KEYUSE_VERIFY | CSSM_KEYUSE_WRAP); + } + else if(clCompareCssmData(thisUse, &CSSMOID_KERBv5_PKINIT_KP_KDC)) { + /* + * Kerberos PKINIT server: + * -- client verifies KDC signature in a CMS msg in AS-REP + */ + keyUse |= CSSM_KEYUSE_VERIFY; + } + } + } + + /* NetscapeCertType */ + decodedExten = DecodedItem::findDecodedExt(CSSMOID_NetscapeCertType, + false, 0, numFields); + if(decodedExten) { + /* nssObj() is a CSSM_DATA ptr, whose Data points to the bits we want */ + CSSM_DATA *nctData = (CSSM_DATA *)decodedExten->nssObj(); + if((nctData != NULL) && (nctData->Length > 0)) { + CE_NetscapeCertType nct = ((uint16)nctData->Data[0]) << 8; + if(nctData->Length > 1) { + nct |= nctData->Data[1]; + } + + /* All this usage bits imply signature verify capability */ + if(nct & (CE_NCT_SSL_Client | CE_NCT_SSL_Server | CE_NCT_SMIME | CE_NCT_ObjSign | + CE_NCT_SSL_CA | CE_NCT_SMIME_CA | CE_NCT_ObjSignCA)) { + keyUse |= CSSM_KEYUSE_VERIFY; + } + } + } + if(keyUse == 0) { + /* Nothing found; take the default. */ + keyUse = CSSM_KEYUSE_ANY; + } + return keyUse; +} + +/* + * Obtain a CSSM_KEY from a decoded cert, inferring as much as we can + * from required fields (subjectPublicKeyInfo) and extensions (for + * KeyUse). + */ +CSSM_KEY_PTR DecodedCert::extractCSSMKey( + Allocator &alloc) const +{ + const CSSM_X509_SUBJECT_PUBLIC_KEY_INFO &keyInfo = + mCert.tbs.subjectPublicKeyInfo; + return CL_extractCSSMKeyNSS(keyInfo, alloc, this); +} + diff --git a/libsecurity_apple_x509_cl/lib/DecodedCert.h b/libsecurity_apple_x509_cl/lib/DecodedCert.h new file mode 100644 index 00000000..cb3a7663 --- /dev/null +++ b/libsecurity_apple_x509_cl/lib/DecodedCert.h @@ -0,0 +1,119 @@ +/* + * 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. + */ + + +/* + * 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. + * + * See DecodedItem.h for details on the care and feeding of this + * module. + */ + +#ifndef _DECODED_CERT_H_ +#define _DECODED_CERT_H_ + +#include +#include + +#include "DecodedItem.h" +#include +#include + +class DecodedCert : public DecodedItem +{ + NOCOPY(DecodedCert) +public: + /* construct empty cert, no decoded extensions */ + DecodedCert( + AppleX509CLSession &session); + + /* one-shot constructor, decoding from DER-encoded data */ + DecodedCert( + AppleX509CLSession &session, + const CssmData &encodedCert); + + ~DecodedCert(); + + void encodeExtensions(); + + /* decode TBSCert and its extensions */ + void decodeTbs( + const CssmData &encodedTbs); + + /* encode TBSCert and its extensions */ + void encodeTbs( + CssmOwnedData &encodedTbs); + + /*** + *** field accessors (in CertFields.cpp) + ***/ + + /* + * Obtain the index'th occurrence of field specified by fieldId. + * Format of the returned field depends on fieldId. + * Returns total number of fieldId fields in the cert if index is 0. + * Returns true if specified field was found, else returns false. + */ + bool getCertFieldData( + const CssmOid &fieldId, // which field + unsigned index, // which occurrence (0 = first) + uint32 &numFields, // RETURNED + CssmOwnedData &fieldValue); // RETURNED + + /* + * Set the field specified by fieldId in TBS. + * Note no index - individual field routines either append (for extensions) + * or throw if field already set (for all others) + */ + void setCertField( + const CssmOid &fieldId, // which field + const CssmData &fieldValue); + + /* + * Free the fieldId-specific data referred to by fieldValue.get().data(). + */ + static void freeCertFieldData( + const CssmOid &fieldId, + CssmOwnedData &fieldValue); + + void getAllParsedCertFields( + uint32 &NumberOfFields, // RETURNED + CSSM_FIELD_PTR &CertFields); // RETURNED + + static void describeFormat( + Allocator &alloc, + uint32 &NumberOfFields, + CSSM_OID_PTR &OidList); + + /* + * Obtain a CSSM_KEY from a decoded cert, inferring as much as we can + * from required fields (subjectPublicKeyInfo) and extensions (for + * KeyUse). + */ + CSSM_KEY_PTR extractCSSMKey( + Allocator &alloc) const; + + CSSM_KEYUSE inferKeyUsage() const; + + NSS_Certificate mCert; +}; + +#endif /* _DECODED_CERT_H_ */ diff --git a/libsecurity_apple_x509_cl/lib/DecodedCrl.cpp b/libsecurity_apple_x509_cl/lib/DecodedCrl.cpp new file mode 100644 index 00000000..7f68bcb5 --- /dev/null +++ b/libsecurity_apple_x509_cl/lib/DecodedCrl.cpp @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2002 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. + */ + + +/* + * 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" +#include "cldebugging.h" +#include "AppleX509CLSession.h" +#include "CSPAttacher.h" +#include + +DecodedCrl::DecodedCrl( + AppleX509CLSession &session) + : DecodedItem(session) +{ + memset(&mCrl, 0, sizeof(mCrl)); +} + +/* one-shot constructor, decoding from DER-encoded data */ +DecodedCrl::DecodedCrl( + AppleX509CLSession &session, + const CssmData &encodedCrl) + : DecodedItem(session) +{ + memset(&mCrl, 0, sizeof(mCrl)); + PRErrorCode prtn = mCoder.decode(encodedCrl.data(), encodedCrl.length(), + kSecAsn1SignedCrlTemplate, &mCrl); + if(prtn) { + CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT); + } + mDecodedExtensions.decodeFromNss(mCrl.tbs.extensions); + mState = IS_DecodedAll; +} + +DecodedCrl::~DecodedCrl() +{ +} + +/* decode mCrl.tbs and its extensions */ +void DecodedCrl::decodeCts( + const CssmData &encodedCts) +{ + assert(mState == IS_Empty); + memset(&mCrl, 0, sizeof(mCrl)); + PRErrorCode prtn = mCoder.decode(encodedCts.data(), encodedCts.length(), + kSecAsn1TBSCrlTemplate, &mCrl.tbs); + if(prtn) { + CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT); + } + mDecodedExtensions.decodeFromNss(mCrl.tbs.extensions); + mState = IS_DecodedTBS; +} + +void DecodedCrl::encodeExtensions() +{ + NSS_TBSCrl &tbs = mCrl.tbs; + assert(mState == IS_Building); + assert(tbs.extensions == NULL); + + if(mDecodedExtensions.numExtensions() == 0) { + /* no extensions, no error */ + return; + } + mDecodedExtensions.encodeToNss(tbs.extensions); +} + +/* + * FIXME : how to determine max encoding size at run time!? + */ +#define MAX_TEMPLATE_SIZE (16 * 1024) + +/* encode TBS component; only called from CrlCreateTemplate */ +void DecodedCrl::encodeCts( + CssmOwnedData &encodedCts) +{ + encodeExtensions(); + assert(mState == IS_Building); + + /* enforce required fields - could go deeper, maybe we should */ + NSS_TBSCrl &tbs = mCrl.tbs; + if((tbs.signature.algorithm.Data == NULL) || + (tbs.issuer.rdns == NULL)) { + clErrorLog("DecodedCrl::encodeTbs: incomplete TBS"); + /* an odd, undocumented error return */ + CssmError::throwMe(CSSMERR_CL_NO_FIELD_VALUES); + } + + PRErrorCode prtn; + prtn = SecNssEncodeItemOdata(&tbs, kSecAsn1TBSCrlTemplate, + encodedCts); + if(prtn) { + CssmError::throwMe(CSSMERR_CL_MEMORY_ERROR); + } +} + diff --git a/libsecurity_apple_x509_cl/lib/DecodedCrl.h b/libsecurity_apple_x509_cl/lib/DecodedCrl.h new file mode 100644 index 00000000..5e889294 --- /dev/null +++ b/libsecurity_apple_x509_cl/lib/DecodedCrl.h @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2002 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. + */ + + +/* + * 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. + */ + +#ifndef _DECODED_CRL_H_ +#define _DECODED_CRL_H_ + +#include +#include + +#include "DecodedItem.h" +#include + +class DecodedCrl : /* for now public CertificateList, */ public DecodedItem +{ + NOCOPY(DecodedCrl) +public: + /* construct empty CRL, no decoded extensions */ + DecodedCrl( + AppleX509CLSession &session); + + /* one-shot constructor, decoding from DER-encoded data */ + DecodedCrl( + AppleX509CLSession &session, + const CssmData &encodedCrl); + + ~DecodedCrl(); + + /* decode CRLToSign and its extensions */ + void decodeCts( + const CssmData &encodedCTS); + + /* encode TBSCert and its extensions */ + void encodeExtensions(); + void encodeCts( + CssmOwnedData &encodedTbs); + + /*** + *** field accessors (in CrlFields.cpp) + ***/ + + /* + * Obtain the index'th occurrence of field specified by fieldId. + * Format of the returned field depends on fieldId. + * Returns total number of fieldId fields in the cert if index is 0. + * Returns true if specified field was found, else returns false. + */ + bool getCrlFieldData( + const CssmOid &fieldId, // which field + unsigned index, // which occurrence (0 = first) + uint32 &numFields, // RETURNED + CssmOwnedData &fieldValue); // RETURNED + + /* + * Set the field specified by fieldId in TBS. + * Note no index - individual field routines either append (for extensions) + * or throw if field already set (for all others) + */ + void setCrlField( + const CssmOid &fieldId, // which field + const CssmData &fieldValue); + + /* + * Free the fieldId-specific data referred to by fieldValue.get().data(). + */ + static void freeCrlFieldData( + const CssmOid &fieldId, + CssmOwnedData &fieldValue); + + void getAllParsedCrlFields( + uint32 &NumberOfFields, // RETURNED + CSSM_FIELD_PTR &CertFields); // RETURNED + + static void describeFormat( + Allocator &alloc, + uint32 &NumberOfFields, + CSSM_OID_PTR &OidList); + + NSS_Crl mCrl; + +}; + +#endif /* _DECODED_CRL_H_ */ diff --git a/libsecurity_apple_x509_cl/lib/DecodedExtensions.cpp b/libsecurity_apple_x509_cl/lib/DecodedExtensions.cpp new file mode 100644 index 00000000..92b6cf26 --- /dev/null +++ b/libsecurity_apple_x509_cl/lib/DecodedExtensions.cpp @@ -0,0 +1,527 @@ +/* + * Copyright (c) 2002 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. + */ + + +/* + * DecodedItem.cpp - class representing the common portions of + * NSS-format decoded certs and CRLs, with extensions parsed and + * decoded (still in NSS format). + */ + +#include "DecodedItem.h" +#include "cldebugging.h" +#include "AppleX509CLSession.h" +#include "CSPAttacher.h" +#include "CLFieldsCommon.h" +#include "clNssUtils.h" +#include "clNameUtils.h" +#include +#include + +#define MIN_EXTENSIONS 4 // initial size of *mExtensions + +DecodedExten::DecodedExten( + const CSSM_OID &extnId, // copied + bool critical, + void *nssObj, // NSS_KeyUsage, NSS_BasicConstraints, + // etc. NOT COPIED, exists in same + // memory space as coder + bool berEncoded, // indicates unknown extension which we + // do not BER-decode when parsing a cert + const SecAsn1Template *templ, // to decode/encode if !berEncoded + SecNssCoder &coder, // all local allocs from here + const CSSM_DATA *rawExtn) // NSS_CertExtension.value, copied to + // mRawExtn + : mCritical(critical), + mNssObj(nssObj), + mBerEncoded(berEncoded), + mTempl(templ), + mCoder(coder), + mRawExtn(NULL) +{ + coder.allocCopyItem(extnId, mExtnId); + if(rawExtn) { + mRawExtn = (CSSM_DATA *)coder.malloc(sizeof(CSSM_DATA)); + coder.allocCopyItem(*rawExtn, *mRawExtn); + } +} + +DecodedExten::~DecodedExten() +{ + /* the only stuff we allocated was in the coder pool and will be freed + * when coder is freed */ +} + +/* + * Given a fully encoded BER object, create a CSSM_X509EXT_TAGandVALUE + * representing it. We malloc the CSSM_X509EXT_TAGandVALUE itself using + * specified allocator, but the referent (in CSSM_X509EXT_TAGandVALUE.value) + * merely points to data inside the berValue. + */ +CSSM_X509EXT_TAGandVALUE *DecodedExten::createTagAndValue( + const CSSM_DATA &berValue, + Allocator &alloc) const +{ + if((berValue.Data == NULL) || (berValue.Length == 0)) { + return NULL; + } + CSSM_X509EXT_TAGandVALUE *tv = (CSSM_X509EXT_TAGandVALUE *) + alloc.malloc(sizeof(CSSM_X509EXT_TAGandVALUE)); + tv->type = berValue.Data[0]; + + /* + * length of length is variable; ASN spec says it can actually be up to + * 127 bytes, but we only have room for 32 bits! + */ + const uint8 *lp = berValue.Data + 1; + uint8 len1 = *lp; + if((len1 & 0x80) == 0) { + /* short form */ + tv->value.Length = len1; + tv->value.Data = const_cast(lp + 1); + return tv; + } + + unsigned numLenBytes = len1 & 0x7f; + if(numLenBytes > 4) { + clErrorLog("createTagAndValue: impossible length of length (%u)\n", numLenBytes); + alloc.free(tv); + CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT); + } + + uint32 len = 0; + lp++; // points to first length byte + for(uint32 dex=0; dexvalue.Length = len; + tv->value.Data = const_cast(lp); + return tv; +} + +/* + * Convert this extension to a CSSM_X509_EXTENSION, in the specified + * (app-level) alloc space, after its contents have + * been converted to a native CDSA object (CE_KeyUsage, etc.). + */ +void DecodedExten::convertToCdsa( + void *cdsaObj, // e.g. CE_KeyUsage + // CSSM_DATA_PTR for berEncoded + CSSM_X509_EXTENSION_PTR cssmExt, // contents RETURNED + Allocator &alloc) const +{ + clAllocCopyData(alloc, mExtnId, cssmExt->extnId); + cssmExt->critical = mCritical ? CSSM_TRUE : CSSM_FALSE; + + /* + * in either case copy the raw extension data if we have it (we may not + * have it if this was created via setField). + */ + if(mRawExtn) { + clAllocCopyData(alloc, *mRawExtn, cssmExt->BERvalue); + } + else { + cssmExt->BERvalue.Data = NULL; + cssmExt->BERvalue.Length = 0; + } + if(mBerEncoded) { + /* an extension we never parsed or understood */ + assert(cdsaObj == NULL); + cssmExt->format = CSSM_X509_DATAFORMAT_ENCODED; + cssmExt->value.tagAndValue = createTagAndValue(cssmExt->BERvalue, alloc); + } + else { + /* caller sees parsed version plus raw BER-encoded bytes */ + assert(cdsaObj != NULL); + cssmExt->format = CSSM_X509_DATAFORMAT_PARSED; + /* in app alloc's space, mallocd by getField*() */ + cssmExt->value.parsedValue = cdsaObj; + } +} + +/* + * Convert a DecodedExten to a CSSM_X509_EXTENSION. This includes + * the mapping of the extnId to a known CDSA type and type and doing the + * actual NSS-to-CDSA conversion. At the time this function is + * called, the DecodedExten either has a valid mNssObj, or it's an + * unknown extension type in which case mNssObj is an AsnOcts containing + * the opaquely DER-encoded extension value. + * + * Currently only used when decoding a CRL and converting it en masse + * to CDSA. + */ +template +void nssToCssm( + const DecodedExten &decodedExt, + NssType *&nssObj, // RETURNED + CdsaType *&cdsaObj, // mallocd and RETURNED + Allocator &alloc) +{ + nssObj = (NssType *)(decodedExt.nssObj()); + assert(nssObj != NULL); + cdsaObj = (CdsaType *)alloc.malloc(sizeof(CdsaType)); + memset(cdsaObj, 0, sizeof(CdsaType)); +} + +void DecodedExten::parse( + CSSM_X509_EXTENSION_PTR cssmExt, // mallocd by caller, RETURNED + Allocator &alloc) const +{ + void *vCdsaObj = NULL; + if(mBerEncoded) { + /* non-understood extension */ + convertToCdsa(NULL, cssmExt, alloc); + return; + } + if(clCompareCssmData(&mExtnId, &CSSMOID_AuthorityKeyIdentifier)) { + CE_AuthorityKeyID *cdsaObj; + NSS_AuthorityKeyId *nssObj; + nssToCssm( + *this, + nssObj, + cdsaObj, + alloc); + CL_nssAuthorityKeyIdToCssm(*nssObj, *cdsaObj, mCoder, alloc); + vCdsaObj = cdsaObj; + } + /* same encoding (uint32) for all of these: */ + else if(clCompareCssmData(&mExtnId, &CSSMOID_CrlNumber) || + clCompareCssmData(&mExtnId, &CSSMOID_DeltaCrlIndicator) || + clCompareCssmData(&mExtnId, &CSSMOID_CrlReason)) { + CE_CrlNumber *cdsaObj; + CSSM_DATA *nssObj; + nssToCssm( + *this, + nssObj, + cdsaObj, + alloc); + CSSM_RETURN toThrow; + if(clCompareCssmData(&mExtnId, &CSSMOID_CrlReason)) { + toThrow = CSSMERR_CL_INVALID_CRL_POINTER; + } + else { + /* tolerate crlNumber > 4 bytes */ + toThrow = CSSM_OK; + } + *cdsaObj = clDataToInt(*nssObj, toThrow); + vCdsaObj = cdsaObj; + } + /* same encoding (GeneralNames) for all of these: */ + else if(clCompareCssmData(&mExtnId, &CSSMOID_IssuerAltName) || + clCompareCssmData(&mExtnId, &CSSMOID_SubjectAltName) || + clCompareCssmData(&mExtnId, &CSSMOID_CertIssuer)) { + CE_GeneralNames *cdsaObj; + NSS_GeneralNames *nssObj; + nssToCssm( + *this, + nssObj, + cdsaObj, + alloc); + CL_nssGeneralNamesToCssm(*nssObj, *cdsaObj, mCoder, alloc); + vCdsaObj = cdsaObj; + } + else if(clCompareCssmData(&mExtnId, &CSSMOID_IssuingDistributionPoint)) { + CE_IssuingDistributionPoint *cdsaObj; + NSS_IssuingDistributionPoint *nssObj; + nssToCssm( + *this, + nssObj, + cdsaObj, + alloc); + CL_nssIssuingDistPointToCssm(nssObj, cdsaObj, mCoder, alloc); + vCdsaObj = cdsaObj; + } + /* + CrashTracer: [USER] 48 crashes in WebProcess at ... + This code should not normally be executed, since it seems from RFC5280 that + CSSMOID_IssuingDistributionPoint is the correct extension to use. + */ + else if(clCompareCssmData(&mExtnId, &CSSMOID_CrlDistributionPoints)) { + CE_CRLDistPointsSyntax *cdsaObj; + NSS_CRLDistributionPoints *nssObj; + nssToCssm( + *this, + nssObj, + cdsaObj, + alloc); + CL_nssDistPointsToCssm((const NSS_CRLDistributionPoints&)*nssObj, *cdsaObj, mCoder, alloc); + vCdsaObj = cdsaObj; + } + /* + * cert entry extensions + */ + else if(clCompareCssmData(&mExtnId, &CSSMOID_HoldInstructionCode)) { + /* value is just an OID */ + CSSM_OID *cdsaObj; + CSSM_DATA *nssObj; + nssToCssm( + *this, + nssObj, + cdsaObj, + alloc); + clAllocCopyData(alloc, *nssObj, *cdsaObj); + vCdsaObj = cdsaObj; + } + else if(clCompareCssmData(&mExtnId, &CSSMOID_InvalidityDate)) { + /* GeneralizedTime */ + CSSM_DATA *cdsaObj; + CSSM_DATA *nssObj; + nssToCssm( + *this, + nssObj, + cdsaObj, + alloc); + clAllocCopyData(alloc, *nssObj, *cdsaObj); + vCdsaObj = cdsaObj; + } + else { + /* if we get here, this routine is not keeping up with + * clOidToNssInfo() */ + // assert(0); + CssmError::throwMe(CSSMERR_CL_INTERNAL_ERROR); + } + convertToCdsa(vCdsaObj, cssmExt, alloc); +} + + +#pragma mark ------ DecodedExtensions ------ + +/* + * A variable-size array of DecodedExtens. + * Used for storing cert and CRL extensions as well as per-CRL-entry + * extensions. + */ +DecodedExtensions::DecodedExtensions( + SecNssCoder &coder, + Allocator &alloc) + : mCoder(coder), + mAlloc(alloc), + mExtensions(NULL), + mNumExtensions(0), + mSizeofExtensions(0) +{ + +} + +DecodedExtensions::~DecodedExtensions() +{ + for(unsigned i=0; iextnId, cook up an appropriate + * NSS-specific type (NSS_KeyUsage, etc.); + */ + CSSM_DATA &rawExtn = nssExten->value; + bool berEncoded = false; + bool found; // we understand this OID + unsigned nssObjLen; // size of associated NSS object + const SecAsn1Template *templ = NULL; // template for decoding + void *nssObj = NULL; // decode destination + found = clOidToNssInfo(nssExten->extnId, nssObjLen, templ); + if(!found) { + /* + * We don't know how to deal with this. + */ + berEncoded = true; + } + else { + /* + * Create NSS-style object specific to this extension, just + * by knowing its length and ASN template. + * Decode the extensions's extnValue into that object. We don't + * have to know what kind of object it is anymore. + */ + assert(templ != NULL); + nssObj = mCoder.malloc(nssObjLen); + memset(nssObj, 0, nssObjLen); + PRErrorCode prtn; + prtn = mCoder.decodeItem(rawExtn, templ, nssObj); + if(prtn) { + /* + * FIXME - what do we do here? For now flag it + * as an non-understood extension... + */ + clErrorLog("decodeExtensions: extension decode error\n"); + nssObj = NULL; + berEncoded = true; + } + } + if((nssObj != NULL) || berEncoded) { + /* append if the decode was successful */ + addExtension(nssExten->extnId, + clNssBoolToCssm(nssExten->critical), + nssObj, + berEncoded, + templ, + &rawExtn); + } + } +} + +/* + * Encode into a NSS-style Extensions. + * + * Each extension object, currently stored as some AsnType subclass, + * is BER-encoded and the result is stored as an octet string + * (AsnOcts) in a new Extension object in the TBS. + * + * Called from {Crl,Cert}CreateTemplate via encode{Tbs,Cts}(). + */ +void DecodedExtensions::encodeToNss( + NSS_CertExtension **&extensions) +{ + assert(extensions == NULL); + + if(mNumExtensions == 0) { + /* no extensions, no error */ + return; + } + + /* malloc a NULL_terminated array of NSS_CertExtension pointers */ + unsigned len = (mNumExtensions + 1) * sizeof(NSS_CertExtension *); + extensions = (NSS_CertExtension **)mCoder.malloc(len); + memset(extensions, 0, len); + + /* grind thru our DecodedExtens, creating an NSS_CertExtension for + * each one */ + for(unsigned extenDex=0; extenDexberEncoded()) { + /* unknown extension type, it's already encoded */ + const CSSM_DATA *srcBer = (const CSSM_DATA *)decodedExt->rawExtn(); + assert(srcBer != NULL); + mCoder.allocCopyItem(*srcBer, thisNssExten->value); + } + else { + PRErrorCode prtn; + prtn = mCoder.encodeItem(decodedExt->nssObj(), + decodedExt->templ(), thisNssExten->value); + if(prtn) { + clErrorLog("encodeToNss: extension encode error"); + CssmError::throwMe(CSSMERR_CL_INTERNAL_ERROR); + } + } + ArenaAllocator arenaAlloc(mCoder); + if(decodedExt->critical()) { + /* optional, default false */ + clCssmBoolToNss(CSSM_TRUE, thisNssExten->critical, arenaAlloc); + } + mCoder.allocCopyItem(decodedExt->extnId(), thisNssExten->extnId); + } +} + +/* add/retrieve entries */ +void DecodedExtensions::addExtension( + const CSSM_OID &extnId, // copied + bool critical, + void *nssObj, // NSS_KeyUsage, NSS_BasicConstraints, + // etc. NOT COPIED, exists in same + // memory space as coder + bool berEncoded, // indicates unknown extension which we + // do not BER-decode when parsing a cert + const SecAsn1Template *templ, // required if !berEncoded + const CSSM_DATA *rawExtn) // NSS_CertExtension.value, copied, + // optional (not present during a + // SetField op) +{ + if(mNumExtensions == mSizeofExtensions) { + /* expand by doubling, or initial malloc */ + mSizeofExtensions = mNumExtensions ? + (2 * mNumExtensions) : MIN_EXTENSIONS; + mExtensions = (DecodedExten **)mAlloc.realloc( + mExtensions, mSizeofExtensions * sizeof(DecodedExten)); + } + mExtensions[mNumExtensions++] = new DecodedExten(extnId, + critical, nssObj, berEncoded, templ, mCoder, rawExtn); +} + +const DecodedExten *DecodedExtensions::getExtension( + unsigned extenDex) const +{ + assert(extenDex < mNumExtensions); + return mExtensions[extenDex]; +} + +/* Convert to CSSM_X509_EXTENSIONS */ +/* Currently only used when decoding a CRL and converting it en masse + * to CDSA */ +void DecodedExtensions::convertToCdsa( + CSSM_X509_EXTENSIONS &cssmExtens, + Allocator &alloc) const +{ + memset(&cssmExtens, 0, sizeof(cssmExtens)); + if(mNumExtensions == 0) { + return; + } + cssmExtens.extensions = (CSSM_X509_EXTENSION_PTR)alloc.malloc( + sizeof(CSSM_X509_EXTENSION) * mNumExtensions); + memset(cssmExtens.extensions, 0, + sizeof(CSSM_X509_EXTENSION) * mNumExtensions); + cssmExtens.numberOfExtensions = mNumExtensions; + for(unsigned dex=0; dexparse(&cssmExtens.extensions[dex], alloc); + } + catch(...) { + /* FIXME - what now? */ + clFieldLog("DecodedExtensions:convertToCdsa: extension " + "decode error"); + } + } +} + diff --git a/libsecurity_apple_x509_cl/lib/DecodedExtensions.h b/libsecurity_apple_x509_cl/lib/DecodedExtensions.h new file mode 100644 index 00000000..8841115b --- /dev/null +++ b/libsecurity_apple_x509_cl/lib/DecodedExtensions.h @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2000-2002 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. + */ + + +/* + * DecodedExtensions.h - Intermediate representation of extensions. + */ + +#ifndef _DECODED_EXTENSIONS_H_ +#define _DECODED_EXTENSIONS_H_ + +#include +#include + +#include +#include + +#include "cldebugging.h" + +class DecodedExten +{ + NOCOPY(DecodedExten) +public: + + /* member variables only set on construct */ + DecodedExten( + const CSSM_OID &extnId, // copied + bool critical, + void *nssObj, // NSS_KeyUsage, NSS_BasicConstraints, + // etc. NOT COPIED, exists in same + // memory space as coder + bool berEncoded, // indicates unknown extension + // which we do not BER-decode + // when parsing a cert + const SecAsn1Template *templ, // to decode/encode if !berEncoded + SecNssCoder &coder, // all local allocs from here + const CSSM_DATA *rawExtn=NULL); // NSS_CertExtension.value, copied to + // mRawExtn, optional (not present + // during a SetField op) + ~DecodedExten(); + + /* + * Convert this extension to a CSSM_X509_EXTENSION, after its contents + * have been converted to a native CDSA object (CE_KeyUsage, etc.). + * This is the final step of a getField op involving an extension. + */ + void convertToCdsa( + void *cdsaObj, // e.g. CE_KeyUsage + // CSSM_DATA_PTR for berEncoded + CSSM_X509_EXTENSION_PTR cssmExt, // contents mallocd in alloc's space + // and RETURNED + Allocator &alloc) const; + + /* + * Convert a DecodedExten to a CSSM_X509_EXTENSION. This includes + * the mapping of the extnId to a known CDSA type and type and doing the + * actual NSS-to-CDSA conversion. + */ + void parse( + CSSM_X509_EXTENSION_PTR cssmExt, // mallocd by caller, contents + // mallocd in alloc's space, + // RETURNED + Allocator &alloc) const; + + const CSSM_OID &extnId() const { return mExtnId; } + bool critical() const { return mCritical; } + void *nssObj() const { return mNssObj; } + bool berEncoded() const { return mBerEncoded; } + const SecAsn1Template *templ() const { return mTempl; } + CSSM_DATA *rawExtn() const { return mRawExtn; } +private: + CSSM_X509EXT_TAGandVALUE *createTagAndValue( + const CSSM_DATA &berValue, + Allocator &alloc) const; + + CSSM_OID mExtnId; + bool mCritical; + void *mNssObj; // NSS_KeyUsage, NSS_BasicConstraints, etc. + bool mBerEncoded; // indicates unknown extension which we + // do not BER-decode when parsing a cert + const SecAsn1Template *mTempl; + // used for decode/encode + SecNssCoder &mCoder; + CSSM_DATA *mRawExtn; // optional BER-encoded extension data, not + // present if created via SetField() +}; + +/* + * A variable-size array of DecodedExtens. + * Used for storing cert and CRL extensions as well as per-CRL-entry + * extensions. + */ +class DecodedExtensions +{ + NOCOPY(DecodedExtensions) +public: + DecodedExtensions( + SecNssCoder &coder, // for local allocs + Allocator &alloc); // for user space (copyout) allocs + ~DecodedExtensions(); + + /* Initialize by decoding an NSS-style NSS_CertExtension array */ + void decodeFromNss( + NSS_CertExtension **extensions); + + /* Encode into a NSS-style NSS_CertExtension array, allocating + * both the array pointers and the NSS_Extension elements themselves */ + void encodeToNss( + NSS_CertExtension **&extensions); + + /* add/retrieve entries */ + void addExtension( + const CSSM_OID &extnId, // copied + bool critical, + void *nssObj, // NSS_BasicConstraints, + // etc. NOT COPIED, exists in same + // memory space as coder + bool berEncoded, // indicates unknown extension + // which we do not BER-decode + // when parsing a cert + const SecAsn1Template *templ, // required if !berEncoded + const CSSM_DATA *rawExtn=NULL); // NSS_CertExtension.value, copied, + // optional (not present during a + // SetField op) + const DecodedExten *getExtension( + unsigned extenDex) const; + + /* + * Convert to CSSM_X509_EXTENSIONS, including conversion to + * native CDSA C structs. Only used on CRL side, on a getField + * returning the entire parsed CRL. */ + void convertToCdsa( + CSSM_X509_EXTENSIONS &cssmExtens, + Allocator &alloc) const; + + unsigned numExtensions() const { return mNumExtensions; } + +private: + SecNssCoder &mCoder; + Allocator &mAlloc; + DecodedExten **mExtensions; + unsigned mNumExtensions; // # valid DecodedExtens + unsigned mSizeofExtensions; // mallocd size in mExtensions +}; + +#endif /* _DECODED_EXTENSIONS_H_ */ diff --git a/libsecurity_apple_x509_cl/lib/DecodedItem.cpp b/libsecurity_apple_x509_cl/lib/DecodedItem.cpp new file mode 100644 index 00000000..17ba9869 --- /dev/null +++ b/libsecurity_apple_x509_cl/lib/DecodedItem.cpp @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2002 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. + */ + + +/* + * DecodedItem.cpp - class representing the common portions of NSS-style + * certs and CRLs, with extensions parsed and decoded (still in NSS + * format). + */ + +#include "DecodedItem.h" +#include "cldebugging.h" +#include "AppleX509CLSession.h" +#include "CSPAttacher.h" +#include "CLFieldsCommon.h" +#include "clNssUtils.h" +#include + + +DecodedItem::DecodedItem( + AppleX509CLSession &session) + : mState(IS_Empty), + mAlloc(session), + mSession(session), + mDecodedExtensions(mCoder, session) +{ +} + +DecodedItem::~DecodedItem() +{ + /* nothing for now */ +} + +/* + * Search for DecodedExten by AsnOid or "any unknown extension". + * Called from getField*() and inferKeyUsage. + * Returns NULL if specified extension not found. + */ +const DecodedExten *DecodedItem::findDecodedExt( + const CSSM_OID &extnId, // for known extensions + bool unknown, // otherwise + uint32 index, + uint32 &numFields) const +{ + unsigned dex; + const DecodedExten *rtnExt = NULL; + unsigned found = 0; + + for(dex=0; dexberEncoded() && + (clCompareCssmData(&decodedExt->extnId(), &extnId)) + ) || + (unknown && decodedExt->berEncoded()) + ) { + + if(found++ == index) { + /* the one we want */ + rtnExt = decodedExt; + } + if((rtnExt != NULL) && (index != 0)) { + /* only determine numFields on search for first one */ + break; + } + } + } + if(rtnExt != NULL) { + /* sucessful return */ + if(index == 0) { + numFields = found; + } + return rtnExt; + } + else { + return NULL; + } +} + diff --git a/libsecurity_apple_x509_cl/lib/DecodedItem.h b/libsecurity_apple_x509_cl/lib/DecodedItem.h new file mode 100644 index 00000000..c6295a01 --- /dev/null +++ b/libsecurity_apple_x509_cl/lib/DecodedItem.h @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2000-2002 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. + */ + + +/* + * DecodedItem.h - class representing the common portions of NSS-format + * decoded certs and CRLs, with extensions parsed and decoded (still in + * NSS format). + * + * When a DecodedItem (cert or CRL) is quiescent and cached in the CL + * (either by an explicit cache call like CSSM_CL_CertCache or + * CSSM_CL_CrlCache(), or during a succession of GetFirst/GetNext field + * ops), the item is stored in the CL in what we call NSS form. NSS is + * the module we use to perform DER encoding and decoding; NSS form + * refers to structs defining Certs, CRLs, and extensions which are + * directly encodable and decodable by the NSS library. NSS structs are + * similar to their CDSA counterparts, sometimes identical, usually + * subtly different (due to requirements of the NSS module). + * + * Decoding a cert or a CRL: + * ------------------------- + * + * When an app decodes a cert or CRL for any reason, the following phases + * are executed: + * + * PHASE I + * ------- + * + * Basic BER-decode if the incoming CSSM_DATA blob. This happens in the + * constructors for DecodedCert and DecodedCrl. A modified/restricted + * version of this occurs in DecodedCert::decodeTbs(), which is used + * during a CSSM_CL_CertGetAllTemplateFields() call. + * + * PHASE II + * -------- + * + * Extensions are converted from untyped blobs - which is how they look + * after PHASE I - to NSS-style C structs. This is done by examining + * the ExtnId of each cert's or CRL's extensions and doing a BER decode + * specific to that extension type. This is performed in + * DecodedExtensions.decodeFromNss() which is called immediately after + * the top-level decode performed in PHASE I. + * + * It is at this point that a cert or CRL can be cached in the CL's + * cacheMap or queryMap (see AppleX509CLSession.{h,cpp}. We call this + * state "NSS Form". + * + * PHASE III (CRLs only) + * -------------------- + * + * This occurs when an app is actually fetching a full CRL in + * CDSA form. Individual entries in a CRL's revocation list also + * contain per-entry extension lists. These are converted from + * untyped blobs to meaningful NSS-style extension structs as + * in PHASE II prior to the conversion to CDSA form in PHASE IV. + * + * PHASE IV + * --------- + * + * This occurs when an app is actually fetching fields in CDSA form. + * This involves converting objects from NSS form to CDSA form + * (if necessary) and copying to the session allocator's memory space. + * + * The rationale behind this phased approach - in particular, the + * reason that in-memory items are stored in NSS form - is that this + * minimizes the number of copies between the intiial parse of a cert + * or CRL and the final GetField op. Since a GetField op inherently + * requires a copy (from internal memory to the session allocator's + * space), and conversion from NSS to CDSA form is basically a bunch of + * copies as well, we might as well just stop with the item in CRL + * format as soon as PHASE II is complete. Note that completion of + * PHASE II is in fact required before caching a cert since that enables + * us to have access to extension-specific info while a cert is + * cached. The KeyUsage and ExtendedKeyUsage extensions are used in + * this manner to get key info from a TBS cert. + * + * + * Creating and encoding a cert: + * ----------------------------- + * + * Creating a cert (creating CRLs is not supported in this release) + * follows more or less the reverse procedure, as follows: + * + * PHASE I + * ------- + * + * During a CSSM_CL_CertCreateTemplate() op, all fields which the + * app wishes to specify are passed into the CL in CDSA form. These + * fields are converted to NSS form in a temporary DecodedCert. This + * includes extensions (in NSS form). + * + * PHASE II + * -------- + * + * Extensions in NSS form are encoded and bundled up into the final, + * BER-encode ready NSS_CertExtension array form. This occurs + * in DecodedCert::encodeExtensions(), called from the top of + * DecodedCert::encodeTbs(). We're still processing an app's + * CSSM_CL_CertCreateTemplate() call at this point. + * + * PHASE III + * --------- + * + * Final DER-encoding of a TBS cert is performed in + * DecodedCert::encodeTbs(). The resulting CSSM_DATA is + * passed back to the app as what CDSA calls a template. + * This completes the CSSM_CL_CertCreateTemplate() call. + * + * PHASE IV + * -------- + * + * The TBS cert blob is signed and the resulting DER-encoded + * cert is passed back to the app. + */ + +#ifndef _DECODED_ITEM_H_ +#define _DECODED_ITEM_H_ + +#include +#include + +#include "cldebugging.h" +#include "DecodedExtensions.h" +#include + +/* state of a DecodedItem */ +typedef enum { + IS_Empty, + IS_DecodedAll, // can't set fields in this state + IS_DecodedTBS, // ditto + IS_Building // in the process of setting fields +} ItemState; + + +class AppleX509CLSession; + +class DecodedItem +{ +public: + DecodedItem( + AppleX509CLSession &session); + + virtual ~DecodedItem(); + + SecNssCoder &coder() { return mCoder; } + + static void describeFormat( + Allocator &alloc, + uint32 &NumberOfFields, + CSSM_OID_PTR &OidList); + +public: + /*** + *** Extensions support + ***/ + + /* called from decodeExtensions and setField* */ + void addExtension( + void *nssThing, // e.g. NSS_KeyUsage + const CSSM_OID &extnId, + bool critical, + bool berEncoded, + const SecAsn1Template *templ, // to decode/encode if !berEncoded + const CSSM_DATA *rawExtn=NULL) // Extension.extnValue, copied, only for + // setField*() + { mDecodedExtensions.addExtension(extnId, critical, nssThing, + berEncoded, templ, rawExtn); + } + + const DecodedExten *findDecodedExt( + const CSSM_OID &extnId, // for known extensions + bool unknown, // otherwise + uint32 index, + uint32 &numFields) const; + + const DecodedExtensions &decodedExtens() const + { return mDecodedExtensions; } + + /* + * Common code for get extension field routines. + * Given an OID identifying an extension and an index, see if + * we have the specified extension in mDecodedExtensions and + * return the NSS and CDSA style objects as well as the + * DecodedExten. + */ + template + bool GetExtenTop( + unsigned index, // which occurrence (0 = first) + uint32 &numFields, // RETURNED + Allocator &alloc, + const CSSM_OID &fieldId, // identifies extension we seek + NssType *&nssObj, // RETURNED + CdsaType *&cdsaObj, // mallocd and RETURNED + const DecodedExten *&decodedExt) const // RETURNED + { + /* See if we have one of these in our list of DecodedExtens */ + decodedExt = findDecodedExt(fieldId, false, index, numFields); + if(decodedExt == NULL) { + return false; + } + nssObj = (NssType *)decodedExt->nssObj(); + cdsaObj = (CdsaType *)alloc.malloc(sizeof(CdsaType)); + memset(cdsaObj, 0, sizeof(CdsaType)); + return true; + } + +protected: + ItemState mState; + Allocator &mAlloc; + SecNssCoder mCoder; // from which all local allocs come + AppleX509CLSession &mSession; + DecodedExtensions mDecodedExtensions; + +}; + + +#endif /* _DECODED_ITEM_H_ */ diff --git a/libsecurity_apple_x509_cl/lib/LockedMap.h b/libsecurity_apple_x509_cl/lib/LockedMap.h new file mode 100644 index 00000000..03da5fc1 --- /dev/null +++ b/libsecurity_apple_x509_cl/lib/LockedMap.h @@ -0,0 +1,93 @@ +/* + * 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. + */ + + +/* + * LockedMap.h - STL-style map with attached Mutex + * + * Created 9/1/2000 by Doug Mitchell. + * Copyright (c) 2000 by Apple Computer. + */ + +#ifndef _LOCKED_MAP_H_ +#define _LOCKED_MAP_H_ + +#include +#include + +template +class LockedMap +{ +private: + typedef std::map MapType; + MapType mMap; + Mutex mMapLock; + + /* low-level lookup, cacheMapLock held on entry and exit */ + ValueType + *lookupEntryLocked(KeyType key) + { + // don't create new entry if desired entry isn't there + typename MapType::iterator it = mMap.find(key); + if(it == mMap.end()) { + return NULL; + } + return it->second; + } + +public: + /* high level maintenance */ + void + addEntry(ValueType &value, KeyType key) + { + StLock _(mMapLock); + mMap[key] = &value; + } + + ValueType + *lookupEntry(KeyType key) + { + StLock _(mMapLock); + return lookupEntryLocked(key); + } + + void + removeEntry(KeyType key) + { + StLock _(mMapLock); + + ValueType *value = lookupEntryLocked(key); + if(value != NULL) { + mMap.erase(key); + } + } + + ValueType + *removeFirstEntry() + { + StLock _(mMapLock); + typename MapType::iterator it = mMap.begin(); + if(it == mMap.end()) { + return NULL; + } + ValueType *rtn = it->second; + mMap.erase(it->first); + return rtn; + } +}; + +#endif /* _LOCKED_MAP_H_ */ diff --git a/libsecurity_apple_x509_cl/lib/Session_CRL.cpp b/libsecurity_apple_x509_cl/lib/Session_CRL.cpp new file mode 100644 index 00000000..47b6c8a8 --- /dev/null +++ b/libsecurity_apple_x509_cl/lib/Session_CRL.cpp @@ -0,0 +1,436 @@ +/* + * 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. + */ + + +// +// Apple X.509 CRL-related session functions. +// + +#include "AppleX509CLSession.h" +#include "clNssUtils.h" +#include "clNameUtils.h" + +void +AppleX509CLSession::CrlDescribeFormat( + uint32 &NumberOfFields, + CSSM_OID_PTR &OidList) +{ + DecodedCrl::describeFormat(*this, NumberOfFields, OidList); +} + + +void +AppleX509CLSession::CrlGetAllFields( + const CssmData &Crl, + uint32 &NumberOfCrlFields, + CSSM_FIELD_PTR &CrlFields) +{ + class DecodedCrl decodedCrl(*this, Crl); + decodedCrl.getAllParsedCrlFields(NumberOfCrlFields, CrlFields); +} + + +CSSM_HANDLE +AppleX509CLSession::CrlGetFirstFieldValue( + const CssmData &Crl, + const CssmData &CrlField, + uint32 &NumberOfMatchedFields, + CSSM_DATA_PTR &Value) +{ + NumberOfMatchedFields = 0; + Value = NULL; + CssmAutoData aData(*this); + + DecodedCrl *decodedCrl = new DecodedCrl(*this, Crl); + uint32 numMatches; + + /* this returns false if field not there, throws on bad OID */ + bool brtn; + try { + brtn = decodedCrl->getCrlFieldData(CrlField, + 0, // index + numMatches, + aData); + } + catch (...) { + delete decodedCrl; + throw; + } + if(!brtn) { + delete decodedCrl; + return CSSM_INVALID_HANDLE; + } + + /* cook up a CLCachedCRL, stash it in cache */ + CLCachedCRL *cachedCrl = new CLCachedCRL(*decodedCrl); + cacheMap.addEntry(*cachedCrl, cachedCrl->handle()); + + /* cook up a CLQuery, stash it */ + CLQuery *query = new CLQuery( + CLQ_CRL, + CrlField, + numMatches, + false, // isFromCache + cachedCrl->handle()); + queryMap.addEntry(*query, query->handle()); + + /* success - copy field data to outgoing Value */ + Value = (CSSM_DATA_PTR)malloc(sizeof(CSSM_DATA)); + *Value = aData.release(); + NumberOfMatchedFields = numMatches; + return query->handle(); +} + + +bool +AppleX509CLSession::CrlGetNextFieldValue( + CSSM_HANDLE ResultsHandle, + CSSM_DATA_PTR &Value) +{ + /* fetch & validate the query */ + CLQuery *query = queryMap.lookupEntry(ResultsHandle); + if(query == NULL) { + CssmError::throwMe(CSSMERR_CL_INVALID_RESULTS_HANDLE); + } + if(query->queryType() != CLQ_CRL) { + clErrorLog("CrlGetNextFieldValue: bad queryType (%d)", + (int)query->queryType()); + CssmError::throwMe(CSSMERR_CL_INVALID_RESULTS_HANDLE); + } + if(query->nextIndex() >= query->numFields()) { + return false; + } + + /* fetch the associated cached CRL */ + CLCachedCRL *cachedCrl = lookupCachedCRL(query->cachedObject()); + uint32 dummy; + CssmAutoData aData(*this); + if(!cachedCrl->crl().getCrlFieldData(query->fieldId(), + query->nextIndex(), + dummy, + aData)) { + return false; + } + + /* success - copy field data to outgoing Value */ + Value = (CSSM_DATA_PTR)malloc(sizeof(CSSM_DATA)); + *Value = aData.release(); + query->incrementIndex(); + return true; +} + + +void +AppleX509CLSession::IsCertInCrl( + const CssmData &Cert, + const CssmData &Crl, + CSSM_BOOL &CertFound) +{ + /* + * Decode the two entities. Note that doing it this way incurs + * the unnecessary (for our purposes) overhead of decoding + * extensions, but doing it this way is so spiffy that I can't + * resist. + */ + DecodedCert decodedCert(*this, Cert); + DecodedCrl decodedCrl(*this, Crl); + + NSS_TBSCertificate &tbsCert = decodedCert.mCert.tbs; + NSS_TBSCrl &tbsCrl = decodedCrl.mCrl.tbs; + + /* trivial case - empty CRL */ + unsigned numCrlEntries = + clNssArraySize((const void **)tbsCrl.revokedCerts); + if(numCrlEntries == 0) { + clFieldLog("IsCertInCrl: empty CRL"); + CertFound = CSSM_FALSE; + return; + } + + /* + * Get normalized and encoded versions of issuer names. + * Since the decoded entities are local, we can normalize in place. + */ + CssmAutoData encCertIssuer(*this); + CssmAutoData encCrlIssuer(*this); + try { + /* snag a handy temp allocator */ + SecNssCoder &coder = decodedCert.coder(); + CL_normalizeX509NameNSS(tbsCert.issuer, coder); + PRErrorCode prtn = SecNssEncodeItemOdata(&tbsCert.issuer, + kSecAsn1NameTemplate, encCertIssuer); + if(prtn) { + CssmError::throwMe(CSSMERR_CL_MEMORY_ERROR); + } + + CL_normalizeX509NameNSS(tbsCrl.issuer, coder); + prtn = SecNssEncodeItemOdata(&tbsCrl.issuer, + kSecAsn1NameTemplate, encCrlIssuer); + if(prtn) { + CssmError::throwMe(CSSMERR_CL_MEMORY_ERROR); + } + } + catch(...) { + clFieldLog("IsCertInCrl: normalize failure"); + throw; + } + + /* issuer names match? */ + CertFound = CSSM_FALSE; + if(encCertIssuer.get() != encCrlIssuer.get()) { + clFieldLog("IsCertInCrl: issuer name mismatch"); + return; + } + + /* is this cert's serial number in the CRL? */ + CSSM_DATA &certSerial = tbsCert.serialNumber; + for(unsigned dex=0; dexuserCertificate; + if(clCompareCssmData(&certSerial, &revokedSerial)) { + /* success */ + CertFound = CSSM_TRUE; + break; + } + } +} + +#pragma mark --- Cached --- + +void +AppleX509CLSession::CrlCache( + const CssmData &Crl, + CSSM_HANDLE &CrlHandle) +{ + DecodedCrl *decodedCrl = new DecodedCrl(*this, Crl); + + /* cook up a CLCachedCRL, stash it in cache */ + CLCachedCRL *cachedCrl = new CLCachedCRL(*decodedCrl); + cacheMap.addEntry(*cachedCrl, cachedCrl->handle()); + CrlHandle = cachedCrl->handle(); +} + +/* + * FIXME - CrlRecordIndex not supported, it'll require mods to + * the DecodedCrl::getCrlFieldData mechanism + */ +CSSM_HANDLE +AppleX509CLSession::CrlGetFirstCachedFieldValue( + CSSM_HANDLE CrlHandle, + const CssmData *CrlRecordIndex, + const CssmData &CrlField, + uint32 &NumberOfMatchedFields, + CSSM_DATA_PTR &Value) +{ + if(CrlRecordIndex != NULL) { + /* not yet */ + CssmError::throwMe(CSSMERR_CL_INVALID_CRL_INDEX); + } + + /* fetch the associated cached CRL */ + CLCachedCRL *cachedCrl = lookupCachedCRL(CrlHandle); + if(cachedCrl == NULL) { + CssmError::throwMe(CSSMERR_CL_INVALID_CACHE_HANDLE); + } + + CssmAutoData aData(*this); + uint32 numMatches; + + /* this returns false if field not there, throws on bad OID */ + if(!cachedCrl->crl().getCrlFieldData(CrlField, + 0, // index + numMatches, + aData)) { + return CSSM_INVALID_HANDLE; + } + + /* cook up a CLQuery, stash it */ + CLQuery *query = new CLQuery( + CLQ_CRL, + CrlField, + numMatches, + true, // isFromCache + cachedCrl->handle()); + queryMap.addEntry(*query, query->handle()); + + /* success - copy field data to outgoing Value */ + Value = (CSSM_DATA_PTR)malloc(sizeof(CSSM_DATA)); + *Value = aData.release(); + NumberOfMatchedFields = numMatches; + return query->handle(); +} + + +bool +AppleX509CLSession::CrlGetNextCachedFieldValue( + CSSM_HANDLE ResultsHandle, + CSSM_DATA_PTR &Value) +{ + /* Identical to, so just call... */ + return CrlGetNextFieldValue(ResultsHandle, Value); +} + + +void +AppleX509CLSession::IsCertInCachedCrl( + const CssmData &Cert, + CSSM_HANDLE CrlHandle, + CSSM_BOOL &CertFound, + CssmData &CrlRecordIndex) +{ + unimplemented(); +} + + +void +AppleX509CLSession::CrlAbortCache( + CSSM_HANDLE CrlHandle) +{ + /* fetch the associated cached CRL, remove from map, delete it */ + CLCachedCRL *cachedCrl = lookupCachedCRL(CrlHandle); + if(cachedCrl == NULL) { + CssmError::throwMe(CSSMERR_CL_INVALID_CACHE_HANDLE); + } + cacheMap.removeEntry(cachedCrl->handle()); + delete cachedCrl; +} + + +void +AppleX509CLSession::CrlAbortQuery( + CSSM_HANDLE ResultsHandle) +{ + /* fetch & validate the query */ + CLQuery *query = queryMap.lookupEntry(ResultsHandle); + if(query == NULL) { + CssmError::throwMe(CSSMERR_CL_INVALID_RESULTS_HANDLE); + } + if(query->queryType() != CLQ_CRL) { + clErrorLog("CrlAbortQuery: bad queryType (%d)", (int)query->queryType()); + CssmError::throwMe(CSSMERR_CL_INVALID_RESULTS_HANDLE); + } + + if(!query->fromCache()) { + /* the associated cached CRL was created just for this query; dispose */ + CLCachedCRL *cachedCrl = lookupCachedCRL(query->cachedObject()); + if(cachedCrl == NULL) { + /* should never happen */ + CssmError::throwMe(CSSMERR_CL_INTERNAL_ERROR); + } + cacheMap.removeEntry(cachedCrl->handle()); + delete cachedCrl; + } + queryMap.removeEntry(query->handle()); + delete query; +} + +#pragma mark --- Template --- + +void +AppleX509CLSession::CrlCreateTemplate( + uint32 NumberOfFields, + const CSSM_FIELD *CrlTemplate, + CssmData &NewCrl) +{ + unimplemented(); +} + + +void +AppleX509CLSession::CrlSetFields( + uint32 NumberOfFields, + const CSSM_FIELD *CrlTemplate, + const CssmData &OldCrl, + CssmData &ModifiedCrl) +{ + unimplemented(); +} + + +void +AppleX509CLSession::CrlAddCert( + CSSM_CC_HANDLE CCHandle, + const CssmData &Cert, + uint32 NumberOfFields, + const CSSM_FIELD CrlEntryFields[], + const CssmData &OldCrl, + CssmData &NewCrl) +{ + unimplemented(); +} + + +void +AppleX509CLSession::CrlRemoveCert( + const CssmData &Cert, + const CssmData &OldCrl, + CssmData &NewCrl) +{ + unimplemented(); +} + + +void +AppleX509CLSession::CrlGetAllCachedRecordFields( + CSSM_HANDLE CrlHandle, + const CssmData &CrlRecordIndex, + uint32 &NumberOfFields, + CSSM_FIELD_PTR &CrlFields) +{ + unimplemented(); +} + +/* + * These are functionally identical to the corresponding + * Cert functions. + */ +void +AppleX509CLSession::CrlVerifyWithKey( + CSSM_CC_HANDLE CCHandle, + const CssmData &CrlToBeVerified) +{ + CertVerifyWithKey(CCHandle, CrlToBeVerified); +} + + +void +AppleX509CLSession::CrlVerify( + CSSM_CC_HANDLE CCHandle, + const CssmData &CrlToBeVerified, + const CssmData *SignerCert, + const CSSM_FIELD *VerifyScope, + uint32 ScopeSize) +{ + CertVerify(CCHandle, CrlToBeVerified, SignerCert, VerifyScope, + ScopeSize); +} + +void +AppleX509CLSession::CrlSign( + CSSM_CC_HANDLE CCHandle, + const CssmData &UnsignedCrl, + const CSSM_FIELD *SignScope, + uint32 ScopeSize, + CssmData &SignedCrl) +{ + unimplemented(); +} + + + + diff --git a/libsecurity_apple_x509_cl/lib/Session_CSR.cpp b/libsecurity_apple_x509_cl/lib/Session_CSR.cpp new file mode 100644 index 00000000..d5a03848 --- /dev/null +++ b/libsecurity_apple_x509_cl/lib/Session_CSR.cpp @@ -0,0 +1,225 @@ +/* + * 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. + */ + + +// +// Session_CSP.cpp - CSR-related session functions. +// + +#include "AppleX509CLSession.h" +#include "DecodedCert.h" +#include "clNameUtils.h" +#include "clNssUtils.h" +#include "cldebugging.h" +#include "CSPAttacher.h" +#include "clNssUtils.h" +#include +#include +#include +#include +#include + +/* + * Generate a DER-encoded CSR. + */ +void AppleX509CLSession::generateCsr( + CSSM_CC_HANDLE CCHandle, + const CSSM_APPLE_CL_CSR_REQUEST *csrReq, + CSSM_DATA_PTR &csrPtr) +{ + /* + * We use the full NSSCertRequest here; we encode the + * NSSCertRequestInfo component separately to calculate + * its signature, then we encode the whole NSSCertRequest + * after dropping in the signature and SignatureAlgorithmIdentifier. + */ + NSSCertRequest certReq; + NSSCertRequestInfo &reqInfo = certReq.reqInfo; + PRErrorCode prtn; + + memset(&certReq, 0, sizeof(certReq)); + + /* + * Step 1: convert CSSM_APPLE_CL_CSR_REQUEST to CertificationRequestInfo. + * All allocs via local arena pool. + */ + SecNssCoder coder; + ArenaAllocator alloc(coder); + clIntToData(0, reqInfo.version, alloc); + + /* subject Name, required */ + if(csrReq->subjectNameX509 == NULL) { + CssmError::throwMe(CSSMERR_CL_INVALID_POINTER); + } + CL_cssmNameToNss(*csrReq->subjectNameX509, reqInfo.subject, coder); + + /* key --> CSSM_X509_SUBJECT_PUBLIC_KEY_INFO */ + CL_CSSMKeyToSubjPubKeyInfoNSS(*csrReq->subjectPublicKey, + reqInfo.subjectPublicKeyInfo, coder); + + /* attributes - see sm_x501if - we support one, CSSMOID_ChallengePassword, + * as a printable string */ + if(csrReq->challengeString) { + /* alloc a NULL_terminated array of NSS_Attribute pointers */ + reqInfo.attributes = (NSS_Attribute **)coder.malloc(2 * sizeof(NSS_Attribute *)); + reqInfo.attributes[1] = NULL; + + /* alloc one NSS_Attribute */ + reqInfo.attributes[0] = (NSS_Attribute *)coder.malloc(sizeof(NSS_Attribute)); + NSS_Attribute *attr = reqInfo.attributes[0]; + memset(attr, 0, sizeof(NSS_Attribute)); + + /* NULL_terminated array of attrValues */ + attr->attrValue = (CSSM_DATA **)coder.malloc(2 * sizeof(CSSM_DATA *)); + attr->attrValue[1] = NULL; + + /* one value - we're almost there */ + attr->attrValue[0] = (CSSM_DATA *)coder.malloc(sizeof(CSSM_DATA)); + + /* attrType is an OID, temp, use static OID */ + attr->attrType = CSSMOID_ChallengePassword; + + /* one value, spec'd as AsnAny, we have to encode first. */ + CSSM_DATA strData; + strData.Data = (uint8 *)csrReq->challengeString; + strData.Length = strlen(csrReq->challengeString); + prtn = coder.encodeItem(&strData, kSecAsn1PrintableStringTemplate, + *attr->attrValue[0]); + if(prtn) { + clErrorLog("generateCsr: error encoding challengeString\n"); + CssmError::throwMe(CSSMERR_CL_MEMORY_ERROR); + } + } + + /* + * Step 2: DER-encode the NSSCertRequestInfo prior to signing. + */ + CSSM_DATA encReqInfo; + prtn = coder.encodeItem(&reqInfo, kSecAsn1CertRequestInfoTemplate, encReqInfo); + if(prtn) { + clErrorLog("generateCsr: error encoding CertRequestInfo\n"); + CssmError::throwMe(CSSMERR_CL_MEMORY_ERROR); + } + + /* + * Step 3: sign the encoded NSSCertRequestInfo. + */ + CssmAutoData sig(*this); + CssmData &infoData = CssmData::overlay(encReqInfo); + signData(CCHandle, infoData, sig); + + /* + * Step 4: finish up NSSCertRequest - signatureAlgorithm, signature + */ + certReq.signatureAlgorithm.algorithm = csrReq->signatureOid; + /* FIXME - for now assume NULL alg params */ + CL_nullAlgParams(certReq.signatureAlgorithm); + certReq.signature.Data = (uint8 *)sig.data(); + certReq.signature.Length = sig.length() * 8; + + /* + * Step 5: DER-encode the finished NSSCertRequest into app space. + */ + CssmAutoData encCsr(*this); + prtn = SecNssEncodeItemOdata(&certReq, kSecAsn1CertRequestTemplate, encCsr); + if(prtn) { + clErrorLog("generateCsr: error encoding CertRequestInfo\n"); + CssmError::throwMe(CSSMERR_CL_MEMORY_ERROR); + } + + /* TBD - enc64 the result, when we have this much working */ + csrPtr = (CSSM_DATA_PTR)malloc(sizeof(CSSM_DATA)); + csrPtr->Data = (uint8 *)encCsr.data(); + csrPtr->Length = encCsr.length(); + encCsr.release(); +} + +/* + * Verify CSR with its own public key. + */ +void AppleX509CLSession::verifyCsr( + const CSSM_DATA *csrPtr) +{ + /* + * 1. Extract the public key from the CSR. We do this by decoding + * the whole thing and getting a CSSM_KEY from the + * SubjectPublicKeyInfo. + */ + NSSCertRequest certReq; + SecNssCoder coder; + PRErrorCode prtn; + + memset(&certReq, 0, sizeof(certReq)); + prtn = coder.decodeItem(*csrPtr, kSecAsn1CertRequestTemplate, &certReq); + if(prtn) { + CssmError::throwMe(CSSMERR_CL_INVALID_DATA); + } + + NSSCertRequestInfo &reqInfo = certReq.reqInfo; + CSSM_KEY_PTR cssmKey = CL_extractCSSMKeyNSS(reqInfo.subjectPublicKeyInfo, + *this, // alloc + NULL); // no DecodedCert + + /* + * 2. Obtain signature algorithm and parameters. + */ + CSSM_X509_ALGORITHM_IDENTIFIER sigAlgId = certReq.signatureAlgorithm; + CSSM_ALGORITHMS vfyAlg = CL_oidToAlg(sigAlgId.algorithm); + + /* + * Handle CSSMOID_ECDSA_WithSpecified, which requires additional + * decode to get the digest algorithm. + */ + if(vfyAlg == CSSM_ALGID_ECDSA_SPECIFIED) { + vfyAlg = CL_nssDecodeECDSASigAlgParams(sigAlgId.parameters, coder); + } + + /* + * 3. Extract the raw bits to be verified and the signature. We + * decode the CSR as a CertificationRequestSigned for this, which + * avoids the decode of the CertificationRequestInfo. + */ + NSS_SignedCertRequest certReqSigned; + memset(&certReqSigned, 0, sizeof(certReqSigned)); + prtn = coder.decodeItem(*csrPtr, kSecAsn1SignedCertRequestTemplate, &certReqSigned); + if(prtn) { + CssmError::throwMe(CSSMERR_CL_INVALID_DATA); + } + + CSSM_DATA sigBytes = certReqSigned.signature; + sigBytes.Length = (sigBytes.Length + 7 ) / 8; + CssmData &sigCdata = CssmData::overlay(sigBytes); + CssmData &toVerify = CssmData::overlay(certReqSigned.certRequestBlob); + + /* + * 4. Attach to CSP, cook up signature context, verify signature. + */ + CSSM_CSP_HANDLE cspHand = getGlobalCspHand(true); + CSSM_RETURN crtn; + CSSM_CC_HANDLE ccHand; + crtn = CSSM_CSP_CreateSignatureContext(cspHand, + vfyAlg, + NULL, // Access Creds + cssmKey, + &ccHand); + if(crtn) { + CssmError::throwMe(crtn); + } + verifyData(ccHand, toVerify, sigCdata); + CL_freeCSSMKey(cssmKey, *this); +} + diff --git a/libsecurity_apple_x509_cl/lib/Session_Cert.cpp b/libsecurity_apple_x509_cl/lib/Session_Cert.cpp new file mode 100644 index 00000000..baef2332 --- /dev/null +++ b/libsecurity_apple_x509_cl/lib/Session_Cert.cpp @@ -0,0 +1,411 @@ +/* + * 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. + */ + + +// +// Session_Cert.cpp - cert-related session functions. +// + +#include "AppleX509CLSession.h" +#include "DecodedCert.h" +#include "DecodedCrl.h" +#include "CLCachedEntry.h" +#include "cldebugging.h" +#include + +void +AppleX509CLSession::CertDescribeFormat( + uint32 &NumberOfFields, + CSSM_OID_PTR &OidList) +{ + DecodedCert::describeFormat(*this, NumberOfFields, OidList); +} + +void +AppleX509CLSession::CertGetAllFields( + const CssmData &Cert, + uint32 &NumberOfFields, + CSSM_FIELD_PTR &CertFields) +{ + DecodedCert decodedCert(*this, Cert); + decodedCert.getAllParsedCertFields(NumberOfFields, CertFields); +} + + +CSSM_HANDLE +AppleX509CLSession::CertGetFirstFieldValue( + const CssmData &EncodedCert, + const CssmData &CertField, + uint32 &NumberOfMatchedFields, + CSSM_DATA_PTR &Value) +{ + NumberOfMatchedFields = 0; + Value = NULL; + CssmAutoData aData(*this); + + DecodedCert *decodedCert = new DecodedCert(*this, EncodedCert); + uint32 numMatches; + + /* this returns false if field not there, throws on bad OID */ + bool brtn; + try { + brtn = decodedCert->getCertFieldData(CertField, + 0, // index + numMatches, + aData); + } + catch (...) { + delete decodedCert; + throw; + } + if(!brtn) { + delete decodedCert; + return CSSM_INVALID_HANDLE; + } + + /* cook up a CLCachedCert, stash it in cache */ + CLCachedCert *cachedCert = new CLCachedCert(*decodedCert); + cacheMap.addEntry(*cachedCert, cachedCert->handle()); + + /* cook up a CLQuery, stash it */ + CLQuery *query = new CLQuery( + CLQ_Cert, + CertField, + numMatches, + false, // isFromCache + cachedCert->handle()); + queryMap.addEntry(*query, query->handle()); + + /* success - copy field data to outgoing Value */ + Value = (CSSM_DATA_PTR)malloc(sizeof(CSSM_DATA)); + *Value = aData.release(); + NumberOfMatchedFields = numMatches; + return query->handle(); +} + + +bool +AppleX509CLSession::CertGetNextFieldValue( + CSSM_HANDLE ResultsHandle, + CSSM_DATA_PTR &Value) +{ + /* fetch & validate the query */ + CLQuery *query = queryMap.lookupEntry(ResultsHandle); + if(query == NULL) { + CssmError::throwMe(CSSMERR_CL_INVALID_RESULTS_HANDLE); + } + if(query->queryType() != CLQ_Cert) { + clErrorLog("CertGetNextFieldValue: bad queryType (%d)", (int)query->queryType()); + CssmError::throwMe(CSSMERR_CL_INVALID_RESULTS_HANDLE); + } + if(query->nextIndex() >= query->numFields()) { + return false; + } + + /* fetch the associated cached cert */ + CLCachedCert *cachedCert = lookupCachedCert(query->cachedObject()); + uint32 dummy; + CssmAutoData aData(*this); + if(!cachedCert->cert().getCertFieldData(query->fieldId(), + query->nextIndex(), + dummy, + aData)) { + return false; + } + + /* success - copy field data to outgoing Value */ + Value = (CSSM_DATA_PTR)malloc(sizeof(CSSM_DATA)); + *Value = aData.release(); + query->incrementIndex(); + return true; +} + +void +AppleX509CLSession::CertCache( + const CssmData &EncodedCert, + CSSM_HANDLE &CertHandle) +{ + DecodedCert *decodedCert = new DecodedCert(*this, EncodedCert); + + /* cook up a CLCachedCert, stash it in cache */ + CLCachedCert *cachedCert = new CLCachedCert(*decodedCert); + cacheMap.addEntry(*cachedCert, cachedCert->handle()); + CertHandle = cachedCert->handle(); +} + +CSSM_HANDLE +AppleX509CLSession::CertGetFirstCachedFieldValue( + CSSM_HANDLE CertHandle, + const CssmData &CertField, + uint32 &NumberOfMatchedFields, + CSSM_DATA_PTR &Value) +{ + /* fetch the associated cached cert */ + CLCachedCert *cachedCert = lookupCachedCert(CertHandle); + if(cachedCert == NULL) { + CssmError::throwMe(CSSMERR_CL_INVALID_CACHE_HANDLE); + } + + CssmAutoData aData(*this); + uint32 numMatches; + + /* this returns false if field not there, throws on bad OID */ + if(!cachedCert->cert().getCertFieldData(CertField, + 0, // index + numMatches, + aData)) { + return CSSM_INVALID_HANDLE; + } + + /* cook up a CLQuery, stash it */ + CLQuery *query = new CLQuery( + CLQ_Cert, + CertField, + numMatches, + true, // isFromCache + cachedCert->handle()); + queryMap.addEntry(*query, query->handle()); + + /* success - copy field data to outgoing Value */ + Value = (CSSM_DATA_PTR)malloc(sizeof(CSSM_DATA)); + *Value = aData.release(); + NumberOfMatchedFields = numMatches; + return query->handle(); +} + + +bool +AppleX509CLSession::CertGetNextCachedFieldValue( + CSSM_HANDLE ResultsHandle, + CSSM_DATA_PTR &Value) +{ + /* Identical to, so just call... */ + return CertGetNextFieldValue(ResultsHandle, Value); +} + +void +AppleX509CLSession::CertAbortCache( + CSSM_HANDLE CertHandle) +{ + /* fetch the associated cached cert, remove from map, delete it */ + CLCachedCert *cachedCert = lookupCachedCert(CertHandle); + if(cachedCert == NULL) { + clErrorLog("CertAbortCache: cachedCert not found"); + CssmError::throwMe(CSSMERR_CL_INVALID_CACHE_HANDLE); + } + cacheMap.removeEntry(cachedCert->handle()); + delete cachedCert; +} + +/* + * Abort either type of cert field query (cache based or non-cache based) + */ +void +AppleX509CLSession::CertAbortQuery( + CSSM_HANDLE ResultsHandle) +{ + /* fetch & validate the query */ + CLQuery *query = queryMap.lookupEntry(ResultsHandle); + if(query == NULL) { + CssmError::throwMe(CSSMERR_CL_INVALID_RESULTS_HANDLE); + } + if(query->queryType() != CLQ_Cert) { + clErrorLog("CertAbortQuery: bad queryType (%d)", (int)query->queryType()); + CssmError::throwMe(CSSMERR_CL_INVALID_RESULTS_HANDLE); + } + + if(!query->fromCache()) { + /* the associated cached cert was created just for this query; dispose */ + CLCachedCert *cachedCert = lookupCachedCert(query->cachedObject()); + if(cachedCert == NULL) { + /* should never happen */ + clErrorLog("CertAbortQuery: cachedCert not found"); + CssmError::throwMe(CSSMERR_CL_INTERNAL_ERROR); + } + cacheMap.removeEntry(cachedCert->handle()); + delete cachedCert; + } + queryMap.removeEntry(query->handle()); + delete query; +} + +void +AppleX509CLSession::CertCreateTemplate( + uint32 NumberOfFields, + const CSSM_FIELD CertFields[], + CssmData &CertTemplate) +{ + /* cook up an empty Cert */ + DecodedCert cert(*this); + + /* grind thru specified fields; exceptions are fatal */ + for(uint32 dex=0; dexFieldOid; + + /* oid-specific handling of value */ + /* BUG - the CssmRemoteData constructor clears the referent, + * iff the referent is a CSSSM_DATA (as opposed to a CssmData). + */ + CssmData &cData = CssmData::overlay(thisField->FieldValue); + CssmRemoteData rData(*this, cData); + try { + DecodedCert::freeCertFieldData(CssmOid::overlay(*thisOid), rData); + } + catch(...) { + /* CRL field? */ + DecodedCrl::freeCrlFieldData(CssmOid::overlay(*thisOid), rData); + } + /* and the oid itself */ + free(thisOid->Data); + thisOid->Data = NULL; + thisOid->Length = 0; + } + free(FieldArray); +} + +void +AppleX509CLSession::FreeFieldValue( + const CssmData &CertOrCrlOid, + CssmData &Value) +{ + CssmRemoteData cd(*this, Value); + try { + DecodedCert::freeCertFieldData(CertOrCrlOid, cd); + } + catch(...) { + /* CRL field? */ + DecodedCrl::freeCrlFieldData(CertOrCrlOid, cd); + } + free(&Value); +} + +void +AppleX509CLSession::CertGroupFromVerifiedBundle( + CSSM_CC_HANDLE CCHandle, + const CSSM_CERT_BUNDLE &CertBundle, + const CssmData *SignerCert, + CSSM_CERTGROUP_PTR &CertGroup) +{ + unimplemented(); +} + +void +AppleX509CLSession::CertGroupToSignedBundle( + CSSM_CC_HANDLE CCHandle, + const CSSM_CERTGROUP &CertGroupToBundle, + const CSSM_CERT_BUNDLE_HEADER *BundleInfo, + CssmData &SignedBundle) +{ + unimplemented(); +} + +void +AppleX509CLSession::PassThrough( + CSSM_CC_HANDLE CCHandle, + uint32 PassThroughId, + const void *InputParams, + void **OutputParams) +{ + switch(PassThroughId) { + case CSSM_APPLEX509CL_OBTAIN_CSR: + { + /* + * Create a Cert Signing Request (CSR). + * Input is a CSSM_APPLE_CL_CSR_REQUEST. + * Output is a PEM-encoded CertSigningRequest (NSS type + * NSS_SignedCertRequest from pkcs10). + */ + if(InputParams == NULL) { + CssmError::throwMe(CSSMERR_CL_INVALID_INPUT_POINTER); + } + if(OutputParams == NULL) { + CssmError::throwMe(CSSMERR_CL_INVALID_OUTPUT_POINTER); + } + CSSM_APPLE_CL_CSR_REQUEST *csrReq = + (CSSM_APPLE_CL_CSR_REQUEST *)InputParams; + if((csrReq->subjectNameX509 == NULL) || + (csrReq->signatureOid.Data == NULL) || + (csrReq->subjectPublicKey == NULL) || + (csrReq->subjectPrivateKey == NULL)) { + CssmError::throwMe(CSSMERR_CL_INVALID_INPUT_POINTER); + } + CSSM_DATA_PTR csrPtr = NULL; + generateCsr(CCHandle, csrReq, csrPtr); + *OutputParams = csrPtr; + break; + } + case CSSM_APPLEX509CL_VERIFY_CSR: + { + /* + * Perform signature verify of a CSR. + * Input: CSSM_DATA referring to a DER-encoded CSR. + * Output: Nothing, throws CSSMERR_CL_VERIFICATION_FAILURE + * on failure. + */ + if(InputParams == NULL) { + CssmError::throwMe(CSSMERR_CL_INVALID_INPUT_POINTER); + } + const CSSM_DATA *csrPtr = (const CSSM_DATA *)InputParams; + verifyCsr(csrPtr); + break; + } + default: + CssmError::throwMe(CSSMERR_CL_INVALID_PASSTHROUGH_ID); + } +} + diff --git a/libsecurity_apple_x509_cl/lib/Session_Crypto.cpp b/libsecurity_apple_x509_cl/lib/Session_Crypto.cpp new file mode 100644 index 00000000..5b545825 --- /dev/null +++ b/libsecurity_apple_x509_cl/lib/Session_Crypto.cpp @@ -0,0 +1,367 @@ +/* + * 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. + */ + + +/* + * Session_Crypto.cpp: CL session functions: sign, verify, CSSM_KEY extraction. + * + * Created 9/1/2000 by Doug Mitchell. + * Copyright (c) 2000 by Apple Computer. + */ + +#include "AppleX509CLSession.h" +#include "DecodedCert.h" +#include "cldebugging.h" +#include "CSPAttacher.h" +#include "clNssUtils.h" +#include +#include +#include +#include + +/* + * Given a DER-encoded cert, obtain a fully usable CSSM_KEY representing + * the cert's public key. + */ +void +AppleX509CLSession::CertGetKeyInfo( + const CssmData &Cert, + CSSM_KEY_PTR &Key) +{ + DecodedCert decodedCert(*this, Cert); + Key = decodedCert.extractCSSMKey(*this); +} + +/* + * Given a DER-encoded cert and a fully specified crypto context, verify + * cert's TBS and signature. + */ +void +AppleX509CLSession::CertVerifyWithKey( + CSSM_CC_HANDLE CCHandle, + const CssmData &CertToBeVerified) +{ + CssmAutoData tbs(*this); + CssmAutoData algId(*this); + CssmAutoData sig(*this); + CL_certCrlDecodeComponents(CertToBeVerified, tbs, algId, sig); + verifyData(CCHandle, tbs, sig); +} + +/* + * Verify a DER-encoded cert, obtaining crypto context from either + * caller-specified context or by inference from SignerCert. + */ +void +AppleX509CLSession::CertVerify( + CSSM_CC_HANDLE CCHandle, + const CssmData &CertToBeVerified, + const CssmData *SignerCert, + const CSSM_FIELD *VerifyScope, + uint32 ScopeSize) +{ + if((VerifyScope != NULL) || (ScopeSize != 0)) { + CssmError::throwMe(CSSMERR_CL_SCOPE_NOT_SUPPORTED); + } + if((CCHandle == CSSM_INVALID_HANDLE) && (SignerCert == NULL)) { + /* need one or the other */ + CssmError::throwMe(CSSMERR_CL_INVALID_CONTEXT_HANDLE); + } + + /* get top-level components */ + CssmAutoData tbs(*this); // in DER format + CssmAutoData algId(*this); // in DER format + CssmAutoData sig(*this); // in DER format + CL_certCrlDecodeComponents(CertToBeVerified, tbs, algId, sig); + + /* these must be explicitly freed upon exit */ + CSSM_KEY_PTR signerPubKey = NULL; + CSSM_CONTEXT_PTR context = NULL; + CSSM_CSP_HANDLE cspHand = CSSM_INVALID_HANDLE; + CSSM_CC_HANDLE ourCcHand = CSSM_INVALID_HANDLE; + + /* SignerCert optional; if present, obtain its subject key */ + if(SignerCert != NULL) { + CertGetKeyInfo(*SignerCert, signerPubKey); + } + + /* signerPubKey must be explicitly freed in any case */ + try { + if(CCHandle != CSSM_INVALID_HANDLE) { + /* + * We'll use this CCHandle for the sig verify, but + * make sure it matches possible incoming SignerCert parameters + */ + if(SignerCert != NULL) { + CSSM_RETURN crtn; + + /* extract signer's public key as a CSSM_KEY from context */ + crtn = CSSM_GetContext(CCHandle, &context); + if(crtn) { + CssmError::throwMe(CSSMERR_CL_INVALID_CONTEXT_HANDLE); + } + CSSM_CONTEXT_ATTRIBUTE_PTR attr; + crtn = CSSM_GetContextAttribute(context, + CSSM_ATTRIBUTE_KEY, + &attr); + if(crtn) { + clErrorLog("CertVerify: valid CCHandle but no key!\n"); + CssmError::throwMe(CSSMERR_CL_INVALID_CONTEXT_HANDLE); + } + /* require match */ + assert(signerPubKey != NULL); + CSSM_KEY_PTR contextPubKey = attr->Attribute.Key; + if(contextPubKey->KeyHeader.AlgorithmId != + signerPubKey->KeyHeader.AlgorithmId) { + clErrorLog("CertVerify: AlgorithmId mismatch!\n"); + CssmError::throwMe(CSSMERR_CL_INVALID_CONTEXT_HANDLE); + } + + /* TBD - check key size, when we have a CSP which can report it */ + /* TBD - anything else? */ + } /* verifying multiple contexts */ + /* OK to use CCHandle as is for verify context */ + } /* valid CCHandle */ + else { + /* + * All we have is signer cert. We already have its public key; + * get signature alg from CertToBeVerified's Cert.algID, which + * we currently have in DER form. Decode it into temp memory. + */ + assert(SignerCert != NULL); + assert(signerPubKey != NULL); + + CSSM_X509_ALGORITHM_IDENTIFIER cssmAlgId; + SecNssCoder coder; + PRErrorCode prtn; + + CssmData &algIdData = algId.get(); + memset(&cssmAlgId, 0, sizeof(cssmAlgId)); + prtn = coder.decode(algIdData.data(), algIdData.length(), + kSecAsn1AlgorithmIDTemplate, &cssmAlgId); + if(prtn) { + CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT); + } + + CSSM_ALGORITHMS vfyAlg = CL_oidToAlg(cssmAlgId.algorithm); + + /* + * Handle CSSMOID_ECDSA_WithSpecified, which requires additional + * decode to get the digest algorithm. + */ + if(vfyAlg == CSSM_ALGID_ECDSA_SPECIFIED) { + vfyAlg = CL_nssDecodeECDSASigAlgParams(cssmAlgId.parameters, coder); + } + + /* attach to CSP, cook up a context */ + cspHand = getGlobalCspHand(true); + CSSM_RETURN crtn; + crtn = CSSM_CSP_CreateSignatureContext(cspHand, + vfyAlg, + NULL, // Access Creds + signerPubKey, + &ourCcHand); + CCHandle = ourCcHand; + } /* inferring sig verify context from SignerCert */ + verifyData(CCHandle, tbs, sig); + } + catch(...) { + /* FIXME - isn't there a better way to do this? Save the + * exception as a CSSM_RETURN and throw it if nonzero later? + */ + if(context != NULL) { + CSSM_FreeContext(context); + } + CL_freeCSSMKey(signerPubKey, *this); + if(ourCcHand != CSSM_INVALID_HANDLE) { + CSSM_DeleteContext(ourCcHand); + } + throw; + } + if(context != NULL) { + CSSM_FreeContext(context); + } + CL_freeCSSMKey(signerPubKey, *this); + if(ourCcHand != CSSM_INVALID_HANDLE) { + CSSM_DeleteContext(ourCcHand); + } +} + +/* + * Given a DER-encoded TBSCert and a fully specified crypto context, + * sign the TBSCert and return the resulting DER-encoded Cert. + */ +void +AppleX509CLSession::CertSign( + CSSM_CC_HANDLE CCHandle, + const CssmData &CertTemplate, + const CSSM_FIELD *SignScope, + uint32 ScopeSize, + CssmData &SignedCert) +{ + if((SignScope != NULL) || (ScopeSize != 0)) { + CssmError::throwMe(CSSMERR_CL_SCOPE_NOT_SUPPORTED); + } + if(CCHandle == CSSM_INVALID_HANDLE) { + CssmError::throwMe(CSSMERR_CL_INVALID_CONTEXT_HANDLE); + } + + /* cook up algId from context->(signing key, sig algorithm) */ + CSSM_CONTEXT_PTR context = NULL; // must be freed + CSSM_RETURN crtn; + crtn = CSSM_GetContext(CCHandle, &context); + if(crtn) { + CssmError::throwMe(CSSMERR_CL_INVALID_CONTEXT_HANDLE); + } + CSSM_CONTEXT_ATTRIBUTE_PTR attr; // not freed + crtn = CSSM_GetContextAttribute(context, + CSSM_ATTRIBUTE_KEY, + &attr); + if(crtn) { + clErrorLog("CertSign: valid CCHandle but no signing key!\n"); + CssmError::throwMe(CSSMERR_CL_INVALID_CONTEXT_HANDLE); + } + CSSM_KEY_PTR signingKey = attr->Attribute.Key; + if(signingKey == NULL) { + clErrorLog("CertSign: valid CCHandle, NULL signing key!\n"); + CssmError::throwMe(CSSMERR_CL_INVALID_CONTEXT_HANDLE); + } + + CssmAutoData encAlgId(*this); + CssmAutoData rawSig(*this); + CssmAutoData fullCert(*this); + try { + /* + * FIXME: we really should break up the template and ensure that its + * signature algId matches the one we're signing with, or just use + * that algId here....for now, this is up to the app to make sure. + */ + + /* temp allocs/encode into here */ + SecNssCoder coder; + + /* CSSM alg --> CSSM_X509_ALGORITHM_IDENTIFIER */ + /*** + *** Note: some ECDSA implementations use CSSMOID_ECDSA_WithSpecified for + *** the algorithm followed by an encoded digest algorithm. We'll handle + *** that on *decode* but we're going to do it the sensible way - with + *** one unique OID to specify the whole thing (e.g. CSSMOID_ECDSA_WithSHA512 + *** which we get from cssmAlgToOid()) unless we're forced to do + *** otherwise by cranky servers. + ***/ + CSSM_X509_ALGORITHM_IDENTIFIER algId; + memset(&algId, 0, sizeof(algId)); + const CSSM_OID *oid = cssmAlgToOid(context->AlgorithmType); + + if(oid == NULL) { + clErrorLog("CertSIgn: unknown alg (%u)\n", + (unsigned)context->AlgorithmType); + CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT); + } + algId.algorithm = *oid; + + /* NULL params - skip for ECDSA */ + switch(context->AlgorithmType) { + case CSSM_ALGID_SHA1WithECDSA: + case CSSM_ALGID_SHA224WithECDSA: + case CSSM_ALGID_SHA256WithECDSA: + case CSSM_ALGID_SHA384WithECDSA: + case CSSM_ALGID_SHA512WithECDSA: + case CSSM_ALGID_ECDSA_SPECIFIED: + break; + default: + CL_nullAlgParams(algId); + break; + } + /* DER-encode the algID */ + PRErrorCode prtn; + prtn = SecNssEncodeItemOdata(&algId, kSecAsn1AlgorithmIDTemplate, + encAlgId); + if(prtn) { + CssmError::throwMe(CSSMERR_CL_MEMORY_ERROR); + } + + /* sign TBS --> rawSig */ + signData(CCHandle, CertTemplate, rawSig); + /* put it all together */ + CL_certEncodeComponents(CertTemplate, encAlgId, rawSig, fullCert); + } + catch (...) { + CSSM_FreeContext(context); + throw; + } + CSSM_FreeContext(context); + SignedCert = fullCert.release(); +} + +/*** Private functions ***/ + +/* + * Sign a CssmData with the specified signing context. Used for + * signing both certs and CRLs; this routine doesn't know anything + * about either one. + */ +void +AppleX509CLSession::signData( + CSSM_CC_HANDLE ccHand, + const CssmData &tbs, + CssmOwnedData &sig) // mallocd and returned +{ + CSSM_RETURN crtn; + CssmData cSig; + + crtn = CSSM_SignData( + ccHand, + &tbs, + 1, // DataBufCount + CSSM_ALGID_NONE, // DigestAlgorithm, + &cSig); + if(crtn) { + clErrorLog("AppleX509CLSession::CSSM_SignData: %ld\n", (long)crtn); + CssmError::throwMe(crtn); + } + sig.set(cSig); +} + +/* + * Verify a block of data given a crypto context and a signature. + * Used for verifying certs and CRLs. Returns a CSSM_RETURN (callers + * always need to clean up after calling us). + */ +void AppleX509CLSession::verifyData( + CSSM_CC_HANDLE ccHand, + const CssmData &tbs, + const CssmData &sig) +{ + CSSM_RETURN crtn; + + crtn = CSSM_VerifyData(ccHand, + &tbs, + 1, + CSSM_ALGID_NONE, // Digest alg + &sig); + if(crtn) { + if(crtn == CSSMERR_CSP_VERIFY_FAILED) { + /* CSP and CL report this differently */ + CssmError::throwMe(CSSMERR_CL_VERIFICATION_FAILURE); + } + else { + CssmError::throwMe(crtn); + } + } +} + diff --git a/libsecurity_apple_x509_cl/lib/clNameUtils.cpp b/libsecurity_apple_x509_cl/lib/clNameUtils.cpp new file mode 100644 index 00000000..27f9e501 --- /dev/null +++ b/libsecurity_apple_x509_cl/lib/clNameUtils.cpp @@ -0,0 +1,747 @@ +/* + * 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. + */ + +/* + * clNameUtils.cpp - support for Name, GeneralizedName, all sorts of names + */ + +#include "clNameUtils.h" +#include "clNssUtils.h" +#include "cldebugging.h" +#include + +#pragma mark ----- NSS_Name <--> CSSM_X509_NAME ----- + +/* + * NSS_ATV --> CSSM_X509_TYPE_VALUE_PAIR + */ + +void CL_nssAtvToCssm( + const NSS_ATV &nssObj, + CSSM_X509_TYPE_VALUE_PAIR &cssmObj, + Allocator &alloc) +{ + /* tag and decoded data */ + cssmObj.valueType = nssObj.value.tag; + clAllocCopyData(alloc, nssObj.value.item, cssmObj.value); + /* the OID */ + clAllocCopyData(alloc, nssObj.type, cssmObj.type); +} + +/* NSS_RDN --> CSSM_X509_RDN */ +void CL_nssRdnToCssm( + const NSS_RDN &nssObj, + CSSM_X509_RDN &cssmObj, + Allocator &alloc, + SecNssCoder &coder) // conversion requires further decoding +{ + memset(&cssmObj, 0, sizeof(cssmObj)); + unsigned numAtvs = clNssArraySize((const void **)nssObj.atvs); + if(numAtvs == 0) { + return; + } + + size_t len = numAtvs * sizeof(CSSM_X509_TYPE_VALUE_PAIR); + cssmObj.AttributeTypeAndValue = + (CSSM_X509_TYPE_VALUE_PAIR_PTR)alloc.malloc(len); + cssmObj.numberOfPairs = numAtvs; + CSSM_X509_TYPE_VALUE_PAIR_PTR cssmAtvs = cssmObj.AttributeTypeAndValue; + memset(cssmAtvs, 0, len); + + for(unsigned dex=0; dex CSSM_X509_NAME */ +void CL_nssNameToCssm( + const NSS_Name &nssObj, + CSSM_X509_NAME &cssmObj, + Allocator &alloc) +{ + memset(&cssmObj, 0, sizeof(cssmObj)); + unsigned numRdns = clNssArraySize((const void **)nssObj.rdns); + if(numRdns == 0) { + /* not technically an error */ + return; + } + + size_t len = numRdns * sizeof(CSSM_X509_RDN); + cssmObj.RelativeDistinguishedName = (CSSM_X509_RDN_PTR)alloc.malloc(len); + cssmObj.numberOfRDNs = numRdns; + CSSM_X509_RDN_PTR cssmRdns = cssmObj.RelativeDistinguishedName; + memset(cssmRdns, 0, len); + + SecNssCoder coder; // conversion requires further decoding + + for(unsigned dex=0; dex NSS_ATV + */ +void CL_cssmAtvToNss( + const CSSM_X509_TYPE_VALUE_PAIR &cssmObj, + NSS_ATV &nssObj, + SecNssCoder &coder) +{ + memset(&nssObj, 0, sizeof(nssObj)); + + /* copy the OID */ + coder.allocCopyItem(cssmObj.type, nssObj.type); + + /* tag and value */ + nssObj.value.tag = cssmObj.valueType; + coder.allocCopyItem(cssmObj.value, nssObj.value.item); +} + +/* CSSM_X509_RDN --> NSS_RDN */ +void CL_cssmRdnToNss( + const CSSM_X509_RDN &cssmObj, + NSS_RDN &nssObj, + SecNssCoder &coder) +{ + memset(&nssObj, 0, sizeof(nssObj)); + + /* alloc NULL-terminated array of ATV pointers */ + unsigned numAtvs = cssmObj.numberOfPairs; + unsigned size = (numAtvs + 1) * sizeof(void *); + nssObj.atvs = (NSS_ATV **)coder.malloc(size); + memset(nssObj.atvs, 0, size); + + /* grind thru the elements */ + for(unsigned atvDex=0; atvDex NSS_Name */ +void CL_cssmNameToNss( + const CSSM_X509_NAME &cssmObj, + NSS_Name &nssObj, + SecNssCoder &coder) +{ + memset(&nssObj, 0, sizeof(nssObj)); + + /* alloc NULL-terminated array of RDN pointers */ + unsigned numRdns = cssmObj.numberOfRDNs; + nssObj.rdns = (NSS_RDN **)clNssNullArray(numRdns, coder); + + /* grind thru the elements */ + for(unsigned rdnDex=0; rdnDexatvs); + if(numAttrs == 0) { + clFieldLog("clNormalizeX509Name: zero numAttrs at index %d", rdnDex); + continue; + } + + /* descend into array of attribute/values */ + for(unsigned attrDex=0; attrDexatvs[attrDex]; + assert(attr != NULL); + + /* + * 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) { + /* skip it */ + continue; + } + + /* normalize */ + char *strPtr = (char *)attrVal.item.Data; + int newLen = attrVal.item.Length; + CL_normalizeString(strPtr, newLen); + + /* possible length adjustment */ + attrVal.item.Length = newLen; + } /* for each attribute/value */ + } /* for each RDN */ +} + +#pragma mark ----- CE_GeneralNames <--> NSS_GeneralNames ----- + +void CL_nssGeneralNameToCssm( + NSS_GeneralName &nssObj, + CE_GeneralName &cdsaObj, + SecNssCoder &coder, // for temp decoding + Allocator &alloc) // destination +{ + memset(&cdsaObj, 0, sizeof(cdsaObj)); + PRErrorCode prtn; + + /* for caller's CE_GeneralName */ + CSSM_BOOL berEncoded = CSSM_FALSE; + CE_GeneralNameType cdsaTag; + + /* + * At this point, depending on the decoded object's tag, we either + * have the final bytes to copy out, or we need to decode further. + * After this switch, if doCopy is true, give the caller a copy + * of nssObj.item. + */ + bool doCopy = true; + switch(nssObj.tag) { + case NGT_OtherName: // ASN_ANY -> CE_OtherName + { + cdsaTag = GNT_OtherName; + + /* decode to coder memory */ + CE_OtherName *nssOther = + (CE_OtherName *)coder.malloc(sizeof(CE_OtherName)); + memset(nssOther, 0, sizeof(CE_OtherName)); + prtn = coder.decodeItem(nssObj.item, + kSecAsn1GenNameOtherNameTemplate, + nssOther); + if(prtn) { + clErrorLog("CL_nssGeneralNameToCssm: error decoding " + "OtherName\n"); + CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT); + } + + /* copy out to caller */ + clAllocData(alloc, cdsaObj.name, sizeof(CE_OtherName)); + clCopyOtherName(*nssOther, *((CE_OtherName *)cdsaObj.name.Data), + alloc); + doCopy = false; + break; + } + case NGT_RFC822Name: // IA5String, done + cdsaTag = GNT_RFC822Name; + break; + case NGT_DNSName: // IA5String + cdsaTag = GNT_DNSName; + break; + case NGT_X400Address: // ASY_ANY, leave alone + cdsaTag = GNT_X400Address; + berEncoded = CSSM_TRUE; + break; + case NGT_DirectoryName: // ASN_ANY --> NSS_Name + { + cdsaTag = GNT_DirectoryName; + + /* Decode to coder memory */ + NSS_Name *nssName = (NSS_Name *)coder.malloc(sizeof(NSS_Name)); + memset(nssName, 0, sizeof(NSS_Name)); + prtn = coder.decodeItem(nssObj.item, kSecAsn1NameTemplate, nssName); + if(prtn) { + clErrorLog("CL_nssGeneralNameToCssm: error decoding " + "NSS_Name\n"); + CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT); + } + + /* convert & copy out to caller */ + clAllocData(alloc, cdsaObj.name, sizeof(CSSM_X509_NAME)); + CL_nssNameToCssm(*nssName, + *((CSSM_X509_NAME *)cdsaObj.name.Data), alloc); + doCopy = false; + break; + } + case NGT_EdiPartyName: // ASN_ANY, leave alone + cdsaTag = GNT_EdiPartyName; + berEncoded = CSSM_TRUE; + break; + case NGT_URI: // IA5String + cdsaTag = GNT_URI; + break; + case NGT_IPAddress: // OCTET_STRING + cdsaTag = GNT_IPAddress; + break; + case NGT_RegisteredID: // OID + cdsaTag = GNT_RegisteredID; + break; + default: + clErrorLog("CL_nssGeneralNameToCssm: bad name tag\n"); + CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT); + } + + cdsaObj.nameType = cdsaTag; + cdsaObj.berEncoded = berEncoded; + if(doCopy) { + clAllocCopyData(alloc, nssObj.item, cdsaObj.name); + } +} + +void CL_nssGeneralNamesToCssm( + const NSS_GeneralNames &nssObj, + CE_GeneralNames &cdsaObj, + SecNssCoder &coder, // for temp decoding + Allocator &alloc) // destination +{ + memset(&cdsaObj, 0, sizeof(cdsaObj)); + unsigned numNames = clNssArraySize((const void **)nssObj.names); + if(numNames == 0) { + return; + } + + /* + * Decode each name element, currently a raw ASN_ANY blob. + * Then convert each result into CDSA form. + * This array of (NSS_GeneralName)s is temporary, it doesn't + * persist outside of this routine other than the fact that it's + * mallocd by the coder arena pool. + */ + NSS_GeneralName *names = + (NSS_GeneralName *)coder.malloc(sizeof(NSS_GeneralName) * numNames); + memset(names, 0, sizeof(NSS_GeneralName) * numNames); + cdsaObj.generalName = (CE_GeneralName *)alloc.malloc( + sizeof(CE_GeneralName) * numNames); + cdsaObj.numNames = numNames; + + for(unsigned dex=0; dexnumNames; i++) { + CL_freeCssmGeneralName(cdsaObj->generalName[i], alloc); + } + if(cdsaObj->numNames) { + memset(cdsaObj->generalName, 0, cdsaObj->numNames * sizeof(CE_GeneralName)); + alloc.free(cdsaObj->generalName); + } + memset(cdsaObj, 0, sizeof(CE_GeneralNames)); +} + +void CL_freeCssmDistPointName( + CE_DistributionPointName *cssmDpn, + Allocator &alloc) +{ + if(cssmDpn == NULL) { + return; + } + switch(cssmDpn->nameType) { + case CE_CDNT_FullName: + CL_freeCssmGeneralNames(cssmDpn->dpn.fullName, alloc); + alloc.free(cssmDpn->dpn.fullName); + break; + case CE_CDNT_NameRelativeToCrlIssuer: + CL_freeX509Rdn(cssmDpn->dpn.rdn, alloc); + alloc.free(cssmDpn->dpn.rdn); + break; + } + memset(cssmDpn, 0, sizeof(*cssmDpn)); +} + +void CL_freeCssmDistPoints( + CE_CRLDistPointsSyntax *cssmDps, + Allocator &alloc) +{ + if(cssmDps == NULL) { + return; + } + for(unsigned dex=0; dexnumDistPoints; dex++) { + CE_CRLDistributionPoint *cssmDp = &cssmDps->distPoints[dex]; + if(cssmDp->distPointName) { + CL_freeCssmDistPointName(cssmDp->distPointName, alloc); + alloc.free(cssmDp->distPointName); + } + if(cssmDp->crlIssuer) { + CL_freeCssmGeneralNames(cssmDp->crlIssuer, alloc); + alloc.free(cssmDp->crlIssuer); + } + } + memset(cssmDps->distPoints, 0, + cssmDps->numDistPoints * sizeof(CE_CRLDistributionPoint)); + alloc.free(cssmDps->distPoints); + memset(cssmDps, 0, sizeof(*cssmDps)); +} + +/* free contents of an CSSM_X509_NAME */ +void CL_freeX509Name( + CSSM_X509_NAME_PTR x509Name, + Allocator &alloc) +{ + if(x509Name == NULL) { + return; + } + for(unsigned rdnDex=0; rdnDexnumberOfRDNs; rdnDex++) { + CSSM_X509_RDN_PTR rdn = &x509Name->RelativeDistinguishedName[rdnDex]; + CL_freeX509Rdn(rdn, alloc); + } + alloc.free(x509Name->RelativeDistinguishedName); + memset(x509Name, 0, sizeof(CSSM_X509_NAME)); +} + +void CL_freeX509Rdn( + CSSM_X509_RDN_PTR rdn, + Allocator &alloc) +{ + if(rdn == NULL) { + return; + } + for(unsigned atvDex=0; atvDexnumberOfPairs; atvDex++) { + CSSM_X509_TYPE_VALUE_PAIR_PTR atv = + &rdn->AttributeTypeAndValue[atvDex]; + alloc.free(atv->type.Data); + alloc.free(atv->value.Data); + memset(atv, 0, sizeof(CSSM_X509_TYPE_VALUE_PAIR)); + } + alloc.free(rdn->AttributeTypeAndValue); + memset(rdn, 0, sizeof(CSSM_X509_RDN)); +} + +void CL_freeOtherName( + CE_OtherName *cssmOther, + Allocator &alloc) +{ + if(cssmOther == NULL) { + return; + } + alloc.free(cssmOther->typeId.Data); + alloc.free(cssmOther->value.Data); + memset(cssmOther, 0, sizeof(*cssmOther)); +} + +void CL_freeCssmIssuingDistPoint( + CE_IssuingDistributionPoint *cssmIdp, + Allocator &alloc) +{ + CL_freeCssmDistPointName(cssmIdp->distPointName, alloc); +} + diff --git a/libsecurity_apple_x509_cl/lib/clNameUtils.h b/libsecurity_apple_x509_cl/lib/clNameUtils.h new file mode 100644 index 00000000..e9ffbff1 --- /dev/null +++ b/libsecurity_apple_x509_cl/lib/clNameUtils.h @@ -0,0 +1,124 @@ +/* + * 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. + */ + +/* + * clNameUtils.h - support for Name, GeneralizedName, all sorts of names + */ + +#ifndef _CL_NAME_UTILS_H_ +#define _CL_NAME_UTILS_H_ + +#include +#include +#include +#include +#include +#include + +void CL_nssAtvToCssm( + const NSS_ATV &nssObj, + CSSM_X509_TYPE_VALUE_PAIR &cssmObj, + Allocator &alloc + #if !NSS_TAGGED_ITEMS + , SecNssCoder &coder + #endif + ); +void CL_nssRdnToCssm( + const NSS_RDN &nssObj, + CSSM_X509_RDN &cssmObj, + Allocator &alloc, + SecNssCoder &coder); +void CL_nssNameToCssm( + const NSS_Name &nssObj, + CSSM_X509_NAME &cssmObj, + Allocator &alloc); + +void CL_cssmAtvToNss( + const CSSM_X509_TYPE_VALUE_PAIR &cssmObj, + NSS_ATV &nssObj, + SecNssCoder &coder); +void CL_cssmRdnToNss( + const CSSM_X509_RDN &cssmObj, + NSS_RDN &nssObj, + SecNssCoder &coder); +void CL_cssmNameToNss( + const CSSM_X509_NAME &cssmObj, + NSS_Name &nssObj, + SecNssCoder &coder); + +void CL_normalizeString( + char *strPtr, + int &strLen); // IN/OUT +void CL_normalizeX509NameNSS( + NSS_Name &nssName, + SecNssCoder &coder); + +void CL_nssGeneralNameToCssm( + NSS_GeneralName &nssObj, + CE_GeneralName &cdsaObj, + SecNssCoder &coder, // for temp decoding + Allocator &alloc); // destination + +void CL_nssGeneralNamesToCssm( + const NSS_GeneralNames &nssObj, + CE_GeneralNames &cdsaObj, + SecNssCoder &coder, // for temp decoding + Allocator &alloc); // destination +void CL_cssmGeneralNameToNss( + CE_GeneralName &cdsaObj, + NSS_GeneralName &nssObj, // actually an NSSTaggedItem + SecNssCoder &coder); // for temp decoding +void CL_cssmGeneralNamesToNss( + const CE_GeneralNames &cdsaObj, + NSS_GeneralNames &nssObj, + SecNssCoder &coder); + +void clCopyOtherName( + const CE_OtherName &src, + CE_OtherName &dst, + Allocator &alloc); + +void CL_freeAuthorityKeyId( + CE_AuthorityKeyID &cdsaObj, + Allocator &alloc); +void CL_freeCssmGeneralName( + CE_GeneralName &genName, + Allocator &alloc); +void CL_freeCssmGeneralNames( + CE_GeneralNames *cdsaObj, + Allocator &alloc); +void CL_freeCssmDistPointName( + CE_DistributionPointName *cssmDpn, + Allocator &alloc); +void CL_freeCssmDistPoints( + CE_CRLDistPointsSyntax *cssmDps, + Allocator &alloc); +void CL_freeX509Name( + CSSM_X509_NAME_PTR x509Name, + Allocator &alloc); +void CL_freeX509Rdn( + CSSM_X509_RDN_PTR rdn, + Allocator &alloc); +void CL_freeOtherName( + CE_OtherName *cssmOther, + Allocator &alloc); +void CL_freeCssmIssuingDistPoint( + CE_IssuingDistributionPoint *cssmIdp, + Allocator &alloc); + + +#endif /* _CL_NAME_UTILS_H_ */ diff --git a/libsecurity_apple_x509_cl/lib/clNssUtils.cpp b/libsecurity_apple_x509_cl/lib/clNssUtils.cpp new file mode 100644 index 00000000..d4a9ddd0 --- /dev/null +++ b/libsecurity_apple_x509_cl/lib/clNssUtils.cpp @@ -0,0 +1,1386 @@ +/* + * 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. + */ + +/* + * clNssUtils.cpp - support for libnssasn1-based ASN1 encode/decode + */ + +#include "clNssUtils.h" +#include "clNameUtils.h" +#include "CSPAttacher.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#pragma mark ----- ArenaAllocator ----- + +/* + * Avoid inlining this for debuggability + */ +void *ArenaAllocator::malloc(size_t len) throw(std::bad_alloc) +{ + try { + return mCoder.malloc(len); + } + catch (...) { + throw std::bad_alloc(); + } +} + +/* intentionally not implemented, should never be called */ +void ArenaAllocator::free(void *p) throw() +{ + throw std::bad_alloc(); +} + +void *ArenaAllocator::realloc(void *p, size_t len) throw(std::bad_alloc) +{ + throw std::bad_alloc(); +} + +#pragma mark ----- Malloc/Copy/Compare CSSM_DATA ----- + +/* + * Misc. alloc/copy with arbitrary Allocator + */ +/* malloc d.Data, set d.Length */ +void clAllocData( + Allocator &alloc, + CSSM_DATA &dst, + size_t len) +{ + if(len == 0) { + dst.Data = NULL; + } + else { + dst.Data = (uint8 *)alloc.malloc(len); + } + dst.Length = len; +} + +/* malloc and copy */ +void clAllocCopyData( + Allocator &alloc, + const CSSM_DATA &src, + CSSM_DATA &dst) +{ + clAllocData(alloc, dst, src.Length); + if(dst.Length != 0) { + memmove(dst.Data, src.Data, src.Length); + } +} + +/* + * Compare two CSSM_DATAs (or two CSSM_OIDs), return true if identical. + */ +bool clCompareCssmData( + 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; + } +} + +#pragma mark ----- CSSM_DATA <--> uint32 ----- + +uint32 clDataToInt( + const CSSM_DATA &cdata, + CSSM_RETURN toThrow) /* = CSSMERR_CL_INVALID_CERT_POINTER */ +{ + if((cdata.Length == 0) || (cdata.Data == NULL)) { + return 0; + } + uint32 len = cdata.Length; + if(len > sizeof(uint32)) { + if(toThrow == 0) { + /* tolerate this */ + len = sizeof(uint32); + } + else { + CssmError::throwMe(toThrow); + } + } + + uint32 rtn = 0; + uint8 *cp = cdata.Data; + for(uint32 i=0; i>= 8; + } +} + +#pragma mark ----- CSSM_BOOL <--> CSSM_DATA ----- +/* + * A Bool is encoded as one byte of either 0 or 0xff + * Default of NSS boolean not present is false + */ +CSSM_BOOL clNssBoolToCssm( + const CSSM_DATA &nssBool) +{ + if((nssBool.Data != NULL) && (nssBool.Data[0] == 0xff)) { + return CSSM_TRUE; + } + else { + return CSSM_FALSE; + } +} + +void clCssmBoolToNss( + CSSM_BOOL cBool, + CSSM_DATA &nssBool, + Allocator &alloc) +{ + uint32 num = cBool ? 0xff : 0; + clIntToData(num, nssBool, alloc); +} + +#pragma mark ----- Bit String manipulation ----- + +/* + * Adjust the length of a CSSM_DATA representing a pre-encoded + * bit string. On entry the length field is the number of bytes + * of data; en exit, the number if bits. Trailing zero bits + * are counted as unused (which is how KeyUsage and NetscapeCertType + * extensions are encoded). + */ +void clCssmBitStringToNss( + CSSM_DATA &b) +{ + int numBits = b.Length * 8; + + /* start at end of bit array, scanning backwards looking + * for the first set bit */ + bool foundSet = false; + for(int dex=b.Length-1; dex>=0; dex--) { + unsigned bitMask = 0x01; + uint8 byte = b.Data[dex]; + for(unsigned bdex=0; bdex<8; bdex++) { + if(byte & bitMask) { + foundSet = true; + break; + } + else { + bitMask <<= 1; + numBits--; + } + } + if(foundSet) { + break; + } + } + /* !foundSet --> numBits = 0 */ + assert(((numBits > 0) & foundSet) || ((numBits == 0) && !foundSet)); + b.Length = (uint32)numBits; +} + +/* + * On entry, Length is bit count; on exit, a byte count. + * The job here is to ensure that bits marked as "unused" in the + * BER encoding are cleared. Encoding rules say they are undefined in + * the actual encoding. + */ +void clNssBitStringToCssm( + CSSM_DATA &b) +{ + uint32 byteCount = (b.Length + 7) / 8; + unsigned partialBits = b.Length & 0x7; + b.Length = byteCount; + if(partialBits == 0) { + return; + } + + /* mask off unused bits */ + unsigned unusedBits = 8 - partialBits; + uint8 *bp = b.Data + b.Length - 1; + /* mask = (2 ** unusedBits) - 1 */ + unsigned mask = (1 << unusedBits) - 1; + *bp &= ~mask; +} + +#pragma mark ----- NSS array manipulation ----- +/* + * How many items in a NULL-terminated array of pointers? + */ +unsigned clNssArraySize( + const void **array) +{ + unsigned count = 0; + if (array) { + while (*array++) { + count++; + } + } + return count; +} + +/* malloc a NULL-ed array of pointers of size num+1 */ +void **clNssNullArray( + uint32 num, + SecNssCoder &coder) +{ + unsigned len = (num + 1) * sizeof(void *); + void **p = (void **)coder.malloc(len); + memset(p, 0, len); + return p; +} + +/* + * GIven a CSSM_DATA containing a decoded BIT_STRING, + * convert to a KeyUsage. + */ +CE_KeyUsage clBitStringToKeyUsage( + const CSSM_DATA &cdata) +{ + unsigned toCopy = (cdata.Length + 7) / 8; + if(toCopy > 2) { + /* I hope I never see this... */ + clErrorLog("clBitStringToKeyUsage: KeyUsage larger than 2 bytes!"); + toCopy = 2; + } + unsigned char bits[2] = {0, 0}; + memmove(bits, cdata.Data, toCopy); + CE_KeyUsage usage = (((unsigned)bits[0]) << 8) | bits[1]; + return usage; +} + +CSSM_ALGORITHMS CL_oidToAlg( + const CSSM_OID &oid) +{ + CSSM_ALGORITHMS alg; + bool found = cssmOidToAlg(&oid, &alg); + if(!found) { + clErrorLog("CL_oidToAlg: unknown alg\n"); + CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT); + } + return alg; +} + +#pragma mark ----- copy CSSM_X509_ALGORITHM_IDENTIFIER ----- + +/* + * Copy CSSM_X509_ALGORITHM_IDENTIFIER, same format (NSS and CSSM). + */ +void CL_copyAlgId( + const CSSM_X509_ALGORITHM_IDENTIFIER &srcAlgId, + CSSM_X509_ALGORITHM_IDENTIFIER &dstAlgId, + Allocator &alloc) +{ + clAllocCopyData(alloc, srcAlgId.algorithm, dstAlgId.algorithm); + clAllocCopyData(alloc, srcAlgId.parameters, dstAlgId.parameters); +} + +void CL_freeCssmAlgId( + CSSM_X509_ALGORITHM_IDENTIFIER *cdsaObj, // optional + Allocator &alloc) +{ + if(cdsaObj == NULL) { + return; + } + alloc.free(cdsaObj->algorithm.Data); + alloc.free(cdsaObj->parameters.Data); + memset(cdsaObj, 0, sizeof(CSSM_X509_ALGORITHM_IDENTIFIER)); +} + + +#pragma mark ----- CSSM_X509_TIME <--> NSS format ----- + +/* + * Map the tag associated with a choice of DirectoryString elements to + * a template array for encoding/decoding that string type. + * Contrary to RFC2459, we allow the IA5String type, which is actually + * used in the real world (cf. the email address in Thawte's serverbasic + * cert). + */ + +/* The template chooser does the work here */ + +bool CL_nssTimeToCssm( + const NSS_TaggedItem &nssTime, + CSSM_X509_TIME &cssmObj, + Allocator &alloc) +{ + cssmObj.timeType = nssTime.tag; + clAllocCopyData(alloc, nssTime.item, cssmObj.time); + return true; +} + +/* + * CSSM time to NSS time. + */ +void CL_cssmTimeToNss( + const CSSM_X509_TIME &cssmTime, + NSS_TaggedItem &nssTime, + SecNssCoder &coder) +{ + nssTime.tag = cssmTime.timeType; + coder.allocCopyItem(cssmTime.time, nssTime.item); +} + +void CL_freeCssmTime( + CSSM_X509_TIME *cssmTime, + Allocator &alloc) +{ + if(cssmTime == NULL) { + return; + } + if(cssmTime->time.Data) { + alloc.free(cssmTime->time.Data); + } + memset(cssmTime, 0, sizeof(CSSM_X509_TIME)); +} + + +#pragma mark ----- CSSM_X509_SUBJECT_PUBLIC_KEY_INFO <--> CSSM_KEY ----- + +/* + * Copy a CSSM_X509_SUBJECT_PUBLIC_KEY_INFO. + * + * Same format (NSS and CSSM), EXCEPT: + * + * Objects which have just been NSS decoded or are about to be + * NSS encoded have the subjectPublicKey.Length field in BITS + * since this field is wrapped in a BIT STRING upon encoding. + * + * Caller tells us which format (bits or bytes) + * to use for each of {src, dst}. + */ +void CL_copySubjPubKeyInfo( + const CSSM_X509_SUBJECT_PUBLIC_KEY_INFO &srcInfo, + bool srcInBits, + CSSM_X509_SUBJECT_PUBLIC_KEY_INFO &dstInfo, + bool dstInBits, + Allocator &alloc) +{ + CL_copyAlgId(srcInfo.algorithm, dstInfo.algorithm, alloc); + + CSSM_DATA srcKey = srcInfo.subjectPublicKey; + if(srcInBits) { + srcKey.Length = (srcKey.Length + 7) / 8; + } + clAllocCopyData(alloc, srcKey, dstInfo.subjectPublicKey); + if(dstInBits) { + dstInfo.subjectPublicKey.Length *= 8; + } +} + +/* + * Obtain a CSSM_KEY from a CSSM_X509_SUBJECT_PUBLIC_KEY_INFO, + * inferring as much as we can from required fields + * (CSSM_X509_SUBJECT_PUBLIC_KEY_INFO) and extensions (for + * KeyUse, obtained from the optional DecodedCert). + */ +CSSM_KEY_PTR CL_extractCSSMKeyNSS( + const CSSM_X509_SUBJECT_PUBLIC_KEY_INFO &keyInfo, + Allocator &alloc, + const DecodedCert *decodedCert) // optional +{ + CSSM_KEY_PTR cssmKey = (CSSM_KEY_PTR) alloc.malloc(sizeof(CSSM_KEY)); + memset(cssmKey, 0, sizeof(CSSM_KEY)); + CSSM_KEYHEADER &hdr = cssmKey->KeyHeader; + CssmRemoteData keyData(alloc, cssmKey->KeyData); + + hdr.HeaderVersion = CSSM_KEYHEADER_VERSION; + /* CspId blank */ + hdr.BlobType = CSSM_KEYBLOB_RAW; + hdr.AlgorithmId = CL_oidToAlg(keyInfo.algorithm.algorithm); + hdr.KeyAttr = CSSM_KEYATTR_MODIFIABLE | CSSM_KEYATTR_EXTRACTABLE; + + /* + * Format inferred from AlgorithmId. I have never seen these defined + * anywhere, e.g., what's the format of an RSA public key in a cert? + * X509 certainly doesn't say. However. the following two cases are + * known to be correct. + */ + switch(hdr.AlgorithmId) { + case CSSM_ALGID_RSA: + hdr.Format = CSSM_KEYBLOB_RAW_FORMAT_PKCS1; + break; + case CSSM_ALGID_DSA: + case CSSM_ALGID_ECDSA: + case CSSM_ALGID_DH: + case CSSM_ALGMODE_PKCS1_EME_OAEP: + hdr.Format = CSSM_KEYBLOB_RAW_FORMAT_X509; + break; + case CSSM_ALGID_FEE: + /* CSSM_KEYBLOB_RAW_FORMAT_NONE --> DER encoded */ + hdr.Format = CSSM_KEYBLOB_RAW_FORMAT_NONE; + break; + default: + /* punt */ + hdr.Format = CSSM_KEYBLOB_RAW_FORMAT_NONE; + } + hdr.KeyClass = CSSM_KEYCLASS_PUBLIC_KEY; + + /* KeyUsage inferred from extensions */ + if(decodedCert) { + hdr.KeyUsage = decodedCert->inferKeyUsage(); + } + else { + hdr.KeyUsage = CSSM_KEYUSE_ANY; + } + + /* start/end date unknown, leave zero */ + hdr.WrapAlgorithmId = CSSM_ALGID_NONE; + hdr.WrapMode = CSSM_ALGMODE_NONE; + + switch(hdr.AlgorithmId) { + case CSSM_ALGID_DSA: + case CSSM_ALGID_ECDSA: + case CSSM_ALGID_DH: + case CSSM_ALGMODE_PKCS1_EME_OAEP: + { + /* + * Just encode the whole subject public key info blob. + * NOTE we're assuming that the keyInfo.subjectPublicKey + * field is in the NSS_native BITSTRING format, i.e., + * its Length field is in bits and we don't have to adjust. + */ + PRErrorCode prtn = SecNssEncodeItemOdata(&keyInfo, + kSecAsn1SubjectPublicKeyInfoTemplate, keyData); + if(prtn) { + clErrorLog("extractCSSMKey: error on reencode\n"); + CssmError::throwMe(CSSMERR_CL_MEMORY_ERROR); + } + break; + } + default: + /* + * RSA, FEE for now. + * keyInfo.subjectPublicKey (in BITS) ==> KeyData + */ + keyData.copy(keyInfo.subjectPublicKey.Data, + (keyInfo.subjectPublicKey.Length + 7) / 8); + } + + /* + * LogicalKeySizeInBits - ask the CSP + */ + CSSM_CSP_HANDLE cspHand = getGlobalCspHand(true); + CSSM_KEY_SIZE keySize; + CSSM_RETURN crtn; + crtn = CSSM_QueryKeySizeInBits(cspHand, CSSM_INVALID_HANDLE, cssmKey, + &keySize); + switch(crtn) { + default: + CssmError::throwMe(crtn); + case CSSMERR_CSP_APPLE_PUBLIC_KEY_INCOMPLETE: + /* + * This is how the CSP indicates a "partial" public key, + * with a valid public key value but no alg-specific + * parameters (currently, DSA only). + */ + hdr.KeyAttr |= CSSM_KEYATTR_PARTIAL; + /* and drop thru */ + case CSSM_OK: + cssmKey->KeyHeader.LogicalKeySizeInBits = + keySize.LogicalKeySizeInBits; + break; + } + + keyData.release(); + return cssmKey; +} + +/* + * Set up a encoded NULL for CSSM_X509_ALGORITHM_IDENTIFIER.parameters. + */ +void CL_nullAlgParams( + CSSM_X509_ALGORITHM_IDENTIFIER &algId) +{ + static const uint8 encNull[2] = { SEC_ASN1_NULL, 0 }; + CSSM_DATA encNullData; + encNullData.Data = (uint8 *)encNull; + encNullData.Length = 2; + + algId.parameters = encNullData; +} + +/* + * Convert a CSSM_KEY to a CSSM_X509_SUBJECT_PUBLIC_KEY_INFO. The + * CSSM key must be in raw format and with a specific blob format. + * -- RSA keys have to be CSSM_KEYBLOB_RAW_FORMAT_PKCS1 + * -- DSA keys have to be CSSM_KEYBLOB_RAW_FORMAT_X509 + * -- ECDSA keys have to be CSSM_KEYBLOB_RAW_FORMAT_X509 + */ +void CL_CSSMKeyToSubjPubKeyInfoNSS( + const CSSM_KEY &cssmKey, + CSSM_X509_SUBJECT_PUBLIC_KEY_INFO &nssKeyInfo, + SecNssCoder &coder) +{ + const CSSM_KEYHEADER &hdr = cssmKey.KeyHeader; + if(hdr.BlobType != CSSM_KEYBLOB_RAW) { + clErrorLog("CL SetField: must specify RAW key blob\n"); + CssmError::throwMe(CSSMERR_CSP_KEY_BLOB_TYPE_INCORRECT); + } + memset(&nssKeyInfo, 0, sizeof(nssKeyInfo)); + + /* algorithm and format dependent from here... */ + switch(hdr.AlgorithmId) { + case CSSM_ALGID_RSA: + if(hdr.Format != CSSM_KEYBLOB_RAW_FORMAT_PKCS1) { + clErrorLog("CL SetField: RSA key must be in PKCS1 format\n"); + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_FORMAT); + } + /* and fall thru */ + default: + { + /* Key header's algorithm --> OID */ + const CSSM_OID *oid = cssmAlgToOid(hdr.AlgorithmId); + if(oid == NULL) { + clErrorLog("CL SetField: Unknown key algorithm\n"); + CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM); + } + CSSM_X509_ALGORITHM_IDENTIFIER &algId = nssKeyInfo.algorithm; + coder.allocCopyItem(*oid, algId.algorithm); + + /* NULL algorithm parameters, always in this case */ + CL_nullAlgParams(algId); + + /* Copy key bits, destination is a BIT STRING */ + coder.allocCopyItem(cssmKey.KeyData, nssKeyInfo.subjectPublicKey); + nssKeyInfo.subjectPublicKey.Length *= 8; + break; + } + case CSSM_ALGID_DSA: + case CSSM_ALGID_ECDSA: + if(hdr.Format != CSSM_KEYBLOB_RAW_FORMAT_X509) { + clErrorLog("CL SetField: DSA/ECDSA key must be in X509 format\n"); + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_FORMAT); + } + + /* + * All we do is decode the whole key blob into the + * SubjectPublicKeyInfo. + */ + if(coder.decodeItem(cssmKey.KeyData, + kSecAsn1SubjectPublicKeyInfoTemplate, + &nssKeyInfo)) { + clErrorLog("CL SetField: Error decoding DSA public key\n"); + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_FORMAT); + } + break; + } +} + +void CL_freeCSSMKey( + CSSM_KEY_PTR cssmKey, + Allocator &alloc, + bool freeTop) +{ + if(cssmKey == NULL) { + return; + } + alloc.free(cssmKey->KeyData.Data); + memset(cssmKey, 0, sizeof(CSSM_KEY)); + if(freeTop) { + alloc.free(cssmKey); + } +} + +#pragma mark ----- CE_AuthorityKeyID <--> NSS_AuthorityKeyId ----- + +void CL_cssmAuthorityKeyIdToNss( + const CE_AuthorityKeyID &cdsaObj, + NSS_AuthorityKeyId &nssObj, + SecNssCoder &coder) +{ + memset(&nssObj, 0, sizeof(nssObj)); + if(cdsaObj.keyIdentifierPresent) { + nssObj.keyIdentifier = (CSSM_DATA_PTR)coder.malloc(sizeof(CSSM_DATA)); + coder.allocCopyItem(cdsaObj.keyIdentifier, *nssObj.keyIdentifier); + } + if(cdsaObj.generalNamesPresent ) { + /* GeneralNames, the hard one */ + CL_cssmGeneralNamesToNss(*cdsaObj.generalNames, + nssObj.genNames, coder); + } + if(cdsaObj.serialNumberPresent) { + coder.allocCopyItem(cdsaObj.serialNumber,nssObj.serialNumber); + } +} + +void CL_nssAuthorityKeyIdToCssm( + const NSS_AuthorityKeyId &nssObj, + CE_AuthorityKeyID &cdsaObj, + SecNssCoder &coder, // for temp decoding + Allocator &alloc) +{ + if(nssObj.keyIdentifier != NULL) { + cdsaObj.keyIdentifierPresent = CSSM_TRUE; + clAllocCopyData(alloc, *nssObj.keyIdentifier, cdsaObj.keyIdentifier); + } + if(nssObj.genNames.names != NULL) { + /* GeneralNames, the hard one */ + cdsaObj.generalNamesPresent = CSSM_TRUE; + cdsaObj.generalNames = + (CE_GeneralNames *)alloc.malloc(sizeof(CE_GeneralNames)); + CL_nssGeneralNamesToCssm(nssObj.genNames, + *cdsaObj.generalNames, + coder, + alloc); + } + if(nssObj.serialNumber.Data != NULL) { + cdsaObj.serialNumberPresent = CSSM_TRUE; + clAllocCopyData(alloc, nssObj.serialNumber, cdsaObj.serialNumber); + } +} + +#pragma mark ----- CE_AuthorityInfoAccess <--> NSS_AuthorityInfoAccess ----- + +void CL_cssmInfoAccessToNss( + const CE_AuthorityInfoAccess &cdsaObj, + NSS_AuthorityInfoAccess &nssObj, + SecNssCoder &coder) +{ + memset(&nssObj, 0, sizeof(nssObj)); + uint32 numDescs = cdsaObj.numAccessDescriptions; + nssObj.accessDescriptions = (NSS_AccessDescription **)clNssNullArray(numDescs, coder); + + for(unsigned dex=0; dex(); + CE_AccessDescription *src = &cdsaObj.accessDescriptions[dex]; + NSS_AccessDescription *dst = nssObj.accessDescriptions[dex]; + coder.allocCopyItem(src->accessMethod, dst->accessMethod); + + /* Convert general name, then encode it into destination */ + NSS_GeneralName nssGenName; + CL_cssmGeneralNameToNss(src->accessLocation, nssGenName, coder); + PRErrorCode prtn = coder.encodeItem(&nssGenName, kSecAsn1GeneralNameTemplate, + dst->encodedAccessLocation); + if(prtn) { + clErrorLog("CL_cssmInfoAccessToNss: encode error\n"); + CssmError::throwMe(CSSMERR_CL_MEMORY_ERROR); + } + } +} + +void CL_infoAccessToCssm( + const NSS_AuthorityInfoAccess &nssObj, + CE_AuthorityInfoAccess &cdsaObj, + SecNssCoder &coder, // for temp decoding + Allocator &alloc) +{ + memset(&cdsaObj, 0, sizeof(cdsaObj)); + unsigned numDescs = clNssArraySize((const void **)nssObj.accessDescriptions); + if(numDescs == 0) { + return; + } + cdsaObj.accessDescriptions = (CE_AccessDescription *)alloc.malloc( + numDescs * sizeof(CE_AccessDescription)); + cdsaObj.numAccessDescriptions = numDescs; + for(unsigned dex=0; dexaccessMethod, dst->accessMethod); + + /* decode the general name */ + NSS_GeneralName nssGenName; + memset(&nssGenName, 0, sizeof(nssGenName)); + PRErrorCode prtn = coder.decodeItem(src->encodedAccessLocation, + kSecAsn1GeneralNameTemplate, &nssGenName); + if(prtn) { + clErrorLog("***Error decoding NSS_AuthorityInfoAccess.accessLocation\n"); + CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT); + } + + /* then convert the result to CSSM */ + CL_nssGeneralNameToCssm(nssGenName, dst->accessLocation, coder, alloc); + } +} + +void CL_freeInfoAccess( + CE_AuthorityInfoAccess &cssmInfo, + Allocator &alloc) +{ + uint32 numDescs = cssmInfo.numAccessDescriptions; + for(unsigned dex=0; dexaccessMethod.Data); + CL_freeCssmGeneralName(dst->accessLocation, alloc); + } + alloc.free(cssmInfo.accessDescriptions); +} + + +#pragma mark ----- CE_QC_Statements <--> NSS_QC_Statements ----- + +void CL_cssmQualCertStatementsToNss( + const CE_QC_Statements &cdsaObj, + NSS_QC_Statements &nssObj, + SecNssCoder &coder) +{ + memset(&nssObj, 0, sizeof(nssObj)); + uint32 numQcs = cdsaObj.numQCStatements; + nssObj.qcStatements = + (NSS_QC_Statement **)clNssNullArray(numQcs, coder); + for(uint32 dex=0; dexstatementId, dst->statementId); + if(src->semanticsInfo) { + if(src->otherInfo) { + /* this is either/or, not both */ + CssmError::throwMe(CSSMERR_CL_INVALID_FIELD_POINTER); + } + + /* encode this CE_SemanticsInformation */ + CE_SemanticsInformation *srcSI = src->semanticsInfo; + NSS_SemanticsInformation dstSI; + memset(&dstSI, 0, sizeof(dstSI)); + if(srcSI->semanticsIdentifier) { + dstSI.semanticsIdentifier = (CSSM_DATA_PTR)coder.malloc(sizeof(CSSM_DATA)); + coder.allocCopyItem(*srcSI->semanticsIdentifier, + *dstSI.semanticsIdentifier); + } + if(srcSI->nameRegistrationAuthorities) { + dstSI.nameRegistrationAuthorities = + (NSS_GeneralNames *)coder.malloc(sizeof(NSS_GeneralNames)); + CL_cssmGeneralNamesToNss(*srcSI->nameRegistrationAuthorities, + *dstSI.nameRegistrationAuthorities, coder); + } + PRErrorCode prtn = coder.encodeItem(&dstSI, kSecAsn1SemanticsInformationTemplate, + dst->info); + if(prtn) { + clErrorLog("CL_cssmQualCertStatementsToNss: encode error\n"); + CssmError::throwMe(CSSMERR_CL_MEMORY_ERROR); + } + + } + if(src->otherInfo) { + /* drop in as ASN_ANY */ + coder.allocCopyItem(*src->otherInfo, dst->info); + } + } +} + +void CL_qualCertStatementsToCssm( + const NSS_QC_Statements &nssObj, + CE_QC_Statements &cdsaObj, + SecNssCoder &coder, // for temp decoding + Allocator &alloc) +{ + memset(&cdsaObj, 0, sizeof(cdsaObj)); + unsigned numQcs = clNssArraySize((const void **)nssObj.qcStatements); + if(numQcs == 0) { + return; + } + cdsaObj.qcStatements = (CE_QC_Statement *)alloc.malloc( + numQcs * sizeof(CE_AccessDescription)); + cdsaObj.numQCStatements = numQcs; + for(unsigned dex=0; dexstatementId, dst->statementId); + + /* + * Whether the optional info is a SemanticsInformation or is uninterpreted + * DER data depends on statementId. + */ + if(src->info.Data) { + if(clCompareCssmData(&src->statementId, &CSSMOID_OID_QCS_SYNTAX_V2)) { + NSS_SemanticsInformation srcSI; + memset(&srcSI, 0, sizeof(srcSI)); + + /* decode info as a NSS_SemanticsInformation */ + PRErrorCode prtn = coder.decodeItem(src->info, + kSecAsn1SemanticsInformationTemplate, &srcSI); + if(prtn) { + clErrorLog("***Error decoding CE_SemanticsInformation\n"); + CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT); + } + + /* NSS_SemanticsInformation --> CE_SemanticsInformation */ + dst->semanticsInfo = + (CE_SemanticsInformation *)alloc.malloc(sizeof(CE_SemanticsInformation)); + CE_SemanticsInformation *dstSI = dst->semanticsInfo; + memset(dstSI, 0, sizeof(*dstSI)); + if(srcSI.semanticsIdentifier) { + dstSI->semanticsIdentifier = (CSSM_OID *)alloc.malloc(sizeof(CSSM_OID)); + clAllocCopyData(alloc, *srcSI.semanticsIdentifier, *dstSI->semanticsIdentifier); + } + if(srcSI.nameRegistrationAuthorities) { + dstSI->nameRegistrationAuthorities = + (CE_NameRegistrationAuthorities *)alloc.malloc( + sizeof(CE_NameRegistrationAuthorities)); + CL_nssGeneralNamesToCssm(*srcSI.nameRegistrationAuthorities, + *dstSI->nameRegistrationAuthorities, + coder, + alloc); + } + } + else { + dst->otherInfo = (CSSM_DATA_PTR)alloc.malloc(sizeof(CSSM_DATA)); + clAllocCopyData(alloc, src->info, *dst->otherInfo); + } + } + } +} + +void CL_freeQualCertStatements( + CE_QC_Statements &cssmQCs, + Allocator &alloc) +{ + uint32 numQCs = cssmQCs.numQCStatements; + for(unsigned dex=0; dexstatementId.Data); + if(dst->semanticsInfo) { + CE_SemanticsInformation *si = dst->semanticsInfo; + if(si->semanticsIdentifier) { + alloc.free(si->semanticsIdentifier->Data); + alloc.free(si->semanticsIdentifier); + } + if(si->nameRegistrationAuthorities) { + CL_freeCssmGeneralNames(si->nameRegistrationAuthorities, alloc); + alloc.free(si->nameRegistrationAuthorities); + } + alloc.free(si); + } + if(dst->otherInfo) { + alloc.free(dst->otherInfo->Data); + alloc.free(dst->otherInfo); + } + } + alloc.free(cssmQCs.qcStatements); +} + +#pragma mark ----- decode/encode CE_DistributionPointName ----- + +/* This is always a DER-encoded blob at the NSS level */ +void CL_decodeDistributionPointName( + const CSSM_DATA &nssBlob, + CE_DistributionPointName &cssmDpn, + SecNssCoder &coder, + Allocator &alloc) +{ + memset(&cssmDpn, 0, sizeof(CE_DistributionPointName)); + if(nssBlob.Length == 0) { + clErrorLog("***CL_decodeDistributionPointName: bad PointName\n"); + CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT); + } + unsigned char tag = nssBlob.Data[0] & SEC_ASN1_TAGNUM_MASK; + switch(tag) { + case NSS_DIST_POINT_FULL_NAME_TAG: + { + /* decode to temp coder memory */ + NSS_GeneralNames gnames; + gnames.names = NULL; + if(coder.decodeItem(nssBlob, kSecAsn1DistPointFullNameTemplate, + &gnames)) { + clErrorLog("***Error decoding DistPointFullName\n"); + CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT); + } + + cssmDpn.nameType = CE_CDNT_FullName; + cssmDpn.dpn.fullName = (CE_GeneralNames *)alloc.malloc( + sizeof(CE_GeneralNames)); + + /* copy out to caller */ + CL_nssGeneralNamesToCssm(gnames, + *cssmDpn.dpn.fullName, coder, alloc); + break; + } + case NSS_DIST_POINT_RDN_TAG: + { + /* decode to temp coder memory */ + NSS_RDN rdn; + memset(&rdn, 0, sizeof(rdn)); + if(coder.decodeItem(nssBlob, kSecAsn1DistPointRDNTemplate, + &rdn)) { + clErrorLog("***Error decoding DistPointRDN\n"); + CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT); + } + + cssmDpn.nameType = CE_CDNT_NameRelativeToCrlIssuer; + cssmDpn.dpn.rdn = (CSSM_X509_RDN_PTR)alloc.malloc( + sizeof(CSSM_X509_RDN)); + + /* copy out to caller */ + CL_nssRdnToCssm(rdn, *cssmDpn.dpn.rdn, alloc, coder); + break; + } + default: + clErrorLog("***Bad CE_DistributionPointName tag\n"); + CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT); + } +} + +void CL_encodeDistributionPointName( + CE_DistributionPointName &cpoint, + CSSM_DATA &npoint, + SecNssCoder &coder) +{ + const SecAsn1Template *templ = NULL; + NSS_GeneralNames gnames; + NSS_RDN rdn; + void *encodeSrc = NULL; + + /* + * Our job is to convert one of two incoming aggregate types + * into NSS format, then encode the result into npoint. + */ + switch(cpoint.nameType) { + case CE_CDNT_FullName: + CL_cssmGeneralNamesToNss(*cpoint.dpn.fullName, + gnames, coder); + encodeSrc = &gnames; + templ = kSecAsn1DistPointFullNameTemplate; + break; + + case CE_CDNT_NameRelativeToCrlIssuer: + CL_cssmRdnToNss(*cpoint.dpn.rdn, rdn, coder); + encodeSrc = &rdn; + templ = kSecAsn1DistPointRDNTemplate; + break; + default: + clErrorLog("CL_encodeDistributionPointName: bad nameType\n"); + CssmError::throwMe(CSSMERR_CL_UNKNOWN_TAG); + } + if(coder.encodeItem(encodeSrc, templ, npoint)) { + clErrorLog("CL_encodeDistributionPointName: encode error\n"); + CssmError::throwMe(CSSMERR_CL_MEMORY_ERROR); + } +} + + +#pragma mark --- CE_CRLDistPointsSyntax <--> NSS_CRLDistributionPoints --- + +void CL_cssmDistPointsToNss( + const CE_CRLDistPointsSyntax &cdsaObj, + NSS_CRLDistributionPoints &nssObj, + SecNssCoder &coder) +{ + memset(&nssObj, 0, sizeof(nssObj)); + unsigned numPoints = cdsaObj.numDistPoints; + if(numPoints == 0) { + return; + } + nssObj.distPoints = + (NSS_DistributionPoint **)clNssNullArray(numPoints, coder); + for(unsigned dex=0; dexdistPointName) { + /* encode and drop into ASN_ANY slot */ + npoint->distPointName = (CSSM_DATA *) + coder.malloc(sizeof(CSSM_DATA)); + CL_encodeDistributionPointName(*cpoint->distPointName, + *npoint->distPointName, coder); + + } + + if(cpoint->reasonsPresent) { + /* bit string, presumed max length 8 bits */ + coder.allocItem(npoint->reasons, 1); + npoint->reasons.Data[0] = cpoint->reasons; + /* adjust for bit string length */ + npoint->reasons.Length = 8; + } + + if(cpoint->crlIssuer) { + CL_cssmGeneralNamesToNss(*cpoint->crlIssuer, + npoint->crlIssuer, coder); + } + } +} + +void CL_nssDistPointsToCssm( + const NSS_CRLDistributionPoints &nssObj, + CE_CRLDistPointsSyntax &cdsaObj, + SecNssCoder &coder, // for temp decoding + Allocator &alloc) +{ + memset(&cdsaObj, 0, sizeof(cdsaObj)); + unsigned numPoints = clNssArraySize((const void **)nssObj.distPoints); + if(numPoints == 0) { + return; + } + + unsigned len = sizeof(CE_CRLDistributionPoint) * numPoints; + cdsaObj.distPoints = (CE_CRLDistributionPoint *)alloc.malloc(len); + memset(cdsaObj.distPoints, 0, len); + cdsaObj.numDistPoints = numPoints; + + for(unsigned dex=0; dex 8) { + clErrorLog("***CL_nssDistPointsToCssm: Malformed reasons\n"); + CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT); + } + cpoint.reasonsPresent = CSSM_TRUE; + if(npoint.reasons.Length != 0) { + cpoint.reasons = npoint.reasons.Data[0]; + } + } + + if(npoint.crlIssuer.names != NULL) { + /* Cook up a new CE_GeneralNames */ + cpoint.crlIssuer = + (CE_GeneralNames *)alloc.malloc(sizeof(CE_GeneralNames)); + CL_nssGeneralNamesToCssm(npoint.crlIssuer, *cpoint.crlIssuer, + coder, alloc); + } + } +} + +#pragma mark ----- IssuingDistributionPoint ----- + +void CL_nssIssuingDistPointToCssm( + NSS_IssuingDistributionPoint *nssIdp, + CE_IssuingDistributionPoint *cssmIdp, + SecNssCoder &coder, + Allocator &alloc) +{ + /* All fields optional */ + memset(cssmIdp, 0, sizeof(*cssmIdp)); + if(nssIdp->distPointName) { + CE_DistributionPointName *cssmDp = (CE_DistributionPointName *) + alloc.malloc(sizeof(CE_DistributionPointName)); + + /* + * This one is currently still encoded; we have to peek + * at its tag and decode accordingly. + */ + CL_decodeDistributionPointName(*nssIdp->distPointName, + *cssmDp, coder, alloc); + cssmIdp->distPointName = cssmDp; + } + if(nssIdp->onlyUserCerts) { + cssmIdp->onlyUserCertsPresent = CSSM_TRUE; + cssmIdp->onlyUserCerts = clNssBoolToCssm(*nssIdp->onlyUserCerts); + } + if(nssIdp->onlyCACerts) { + cssmIdp->onlyCACertsPresent = CSSM_TRUE; + cssmIdp->onlyCACerts = clNssBoolToCssm(*nssIdp->onlyCACerts); + } + if(nssIdp->onlySomeReasons) { + cssmIdp->onlySomeReasonsPresent = CSSM_TRUE; + if(nssIdp->onlySomeReasons->Length > 0) { + cssmIdp->onlySomeReasons = *nssIdp->onlySomeReasons->Data; + } + else { + cssmIdp->onlySomeReasons = 0; + } + } + if(nssIdp->indirectCRL) { + cssmIdp->indirectCrlPresent = CSSM_TRUE; + cssmIdp->indirectCrl = clNssBoolToCssm(*nssIdp->indirectCRL); + } +} + +#pragma mark --- CE_NameConstraints <--> NSS_NameConstraints --- + +void CL_cssmNameConstraintsToNss( + const CE_NameConstraints &cdsaObj, + NSS_NameConstraints &nssObj, + SecNssCoder &coder) +{ + //%%%FIXME tba +} + +void CL_nssNameConstraintsToCssm( + const NSS_NameConstraints &nssObj, + CE_NameConstraints &cdsaObj, + SecNssCoder &coder, // for temp decoding + Allocator &alloc) +{ + //%%%FIXME tba +} + +void CL_freeCssmNameConstraints( + CE_NameConstraints *cssmNcs, + Allocator &alloc) +{ + if(cssmNcs == NULL) { + return; + } +//%%%FIXME need to add a CL_freeCssmGeneralSubtrees function to clNameUtils{.h,.cpp} +#if 0 + switch(cssmDpn->nameType) { + case CE_CDNT_FullName: + CL_freeCssmGeneralNames(cssmDpn->dpn.fullName, alloc); + alloc.free(cssmDpn->dpn.fullName); + break; + case CE_CDNT_NameRelativeToCrlIssuer: + CL_freeX509Rdn(cssmDpn->dpn.rdn, alloc); + alloc.free(cssmDpn->dpn.rdn); + break; + } +#endif + memset(cssmNcs, 0, sizeof(*cssmNcs)); +} + +#pragma mark --- CE_PolicyMappings <--> NSS_PolicyMappings --- + +void CL_cssmPolicyMappingsToNss( + const CE_PolicyMappings &cdsaObj, + NSS_PolicyMappings &nssObj, + SecNssCoder &coder) +{ + //%%%FIXME tba +} + +void CL_nssPolicyMappingsToCssm( + const NSS_PolicyMappings &nssObj, + CE_PolicyMappings &cdsaObj, + SecNssCoder &coder, // for temp decoding + Allocator &alloc) +{ + //%%%FIXME tba +} + +void CL_freeCssmPolicyMappings( + CE_PolicyMappings *cssmPms, + Allocator &alloc) +{ + if(cssmPms == NULL) { + return; + } + //%%%FIXME tba + + memset(cssmPms, 0, sizeof(*cssmPms)); +} + +#pragma mark --- CE_PolicyConstraints <--> NSS_PolicyConstraints --- + +void CL_cssmPolicyConstraintsToNss( + const CE_PolicyConstraints *cdsaObj, + NSS_PolicyConstraints *nssObj, + SecNssCoder &coder) +{ + //%%%FIXME tba +} + +void CL_nssPolicyConstraintsToCssm( + const NSS_PolicyConstraints *nssObj, + CE_PolicyConstraints *cdsaObj, + SecNssCoder &coder, // for temp decoding + Allocator &alloc) +{ + memset(cdsaObj, 0, sizeof(*cdsaObj)); + if(nssObj->requireExplicitPolicy.Data) { + cdsaObj->requireExplicitPolicyPresent = CSSM_TRUE; + cdsaObj->inhibitPolicyMapping = clDataToInt( + nssObj->requireExplicitPolicy, 0); + } + if(nssObj->inhibitPolicyMapping.Data) { + cdsaObj->inhibitPolicyMappingPresent = CSSM_TRUE; + cdsaObj->inhibitPolicyMapping = clDataToInt( + nssObj->inhibitPolicyMapping, 0); + } +} + +void CL_freeCssmPolicyConstraints( + CE_PolicyConstraints *cssmPcs, + Allocator &alloc) +{ + if(cssmPcs == NULL) { + return; + } + + memset(cssmPcs, 0, sizeof(*cssmPcs)); +} + + +#pragma mark ----- ECDSA_SigAlgParams support ----- + +/* + * Some implementations use a two-OID mechanism to specify ECDSA signature + * algorithm with a digest of other than SHA1. This is really not necessary; + * we use the single-OID method (e.g. CSSMOID_ECDSA_WithSHA512) when + * encoding, but we have to accomodate externally generated items with + * the two-OID method. This routine decodes the digest OID and infers a + * CSSM_ALGORITHMS from it. + * Throws CSSMERR_CL_UNKNOWN_FORMAT on any error. + */ +CSSM_ALGORITHMS CL_nssDecodeECDSASigAlgParams( + const CSSM_DATA &encParams, + SecNssCoder &coder) +{ + CSSM_X509_ALGORITHM_IDENTIFIER algParams; + memset(&algParams, 0, sizeof(algParams)); + PRErrorCode prtn = coder.decodeItem(encParams, kSecAsn1AlgorithmIDTemplate, &algParams); + if(prtn) { + clErrorLog("CL_nssDecodeECDSASigAlgParams: error decoding CSSM_X509_ALGORITHM_IDENTIFIER\n"); + CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT); + } + + /* get the digest algorithm, convert to ECDSA w/digest OID */ + CSSM_ALGORITHMS digestAlg = CL_oidToAlg(algParams.algorithm); + switch(digestAlg) { + case CSSM_ALGID_SHA1: + return CSSM_ALGID_SHA1WithECDSA; + case CSSM_ALGID_SHA224: + return CSSM_ALGID_SHA224WithECDSA; + case CSSM_ALGID_SHA256: + return CSSM_ALGID_SHA256WithECDSA; + case CSSM_ALGID_SHA384: + return CSSM_ALGID_SHA384WithECDSA; + case CSSM_ALGID_SHA512: + return CSSM_ALGID_SHA512WithECDSA; + default: + clErrorLog("CL_nssDecodeECDSASigAlgParams: unknown digest algorithm\n"); + CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT); + } +} + +#pragma mark ----- Top-level Cert/CRL encode and decode ----- + +/* + * To ensure a secure means of signing and verifying TBSCert blobs, we + * provide these functions to encode and decode just the top-level + * elements of a certificate. Unfortunately there is no guarantee + * that when you decode and re-encode a TBSCert blob, you get the + * same thing you started with (although with DER rules, as opposed + * to BER rules, you should). Thus when signing, we sign the TBSCert + * and encode the signed cert here without ever decoding the TBSCert (or, + * at least, without using the decoded version to get the encoded TBS blob). + */ + +void CL_certCrlDecodeComponents( + const CssmData &signedItem, // DER-encoded cert or CRL + CssmOwnedData &tbsBlob, // still DER-encoded + CssmOwnedData &algId, // ditto + CssmOwnedData &rawSig) // raw bits (not an encoded AsnBits) +{ + /* BER-decode into temp memory */ + NSS_SignedCertOrCRL nssObj; + SecNssCoder coder; + PRErrorCode prtn; + + memset(&nssObj, 0, sizeof(nssObj)); + prtn = coder.decode(signedItem.data(), signedItem.length(), + kSecAsn1SignedCertOrCRLTemplate, &nssObj); + if(prtn) { + CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT); + } + + /* tbsBlob and algId are raw ASN_ANY including tags, which we pass + * back to caller intact */ + tbsBlob.copy(nssObj.tbsBlob.Data, nssObj.tbsBlob.Length); + algId.copy(nssObj.signatureAlgorithm.Data, + nssObj.signatureAlgorithm.Length); + + /* signature is a bit string which we do in fact decode */ + rawSig.copy(nssObj.signature.Data, + (nssObj.signature.Length + 7) / 8); +} + + +/* + * Given pre-DER-encoded blobs, do the final encode step for a signed cert. + */ +void +CL_certEncodeComponents( + const CssmData &TBSCert, // DER-encoded + const CssmData &algId, // ditto + const CssmData &rawSig, // raw bits, not encoded + CssmOwnedData &signedCert) // DER-encoded +{ + NSS_SignedCertOrCRL nssObj; + nssObj.tbsBlob.Data = TBSCert.Data; + nssObj.tbsBlob.Length = TBSCert.Length; + nssObj.signatureAlgorithm.Data = algId.Data; + nssObj.signatureAlgorithm.Length = algId.Length; + nssObj.signature.Data = rawSig.Data; + nssObj.signature.Length = rawSig.Length * 8; // BIT STRING + + PRErrorCode prtn; + + prtn = SecNssEncodeItemOdata(&nssObj, + kSecAsn1SignedCertOrCRLTemplate,signedCert); + if(prtn) { + CssmError::throwMe(CSSMERR_CL_MEMORY_ERROR); + } + +} diff --git a/libsecurity_apple_x509_cl/lib/clNssUtils.h b/libsecurity_apple_x509_cl/lib/clNssUtils.h new file mode 100644 index 00000000..541cb518 --- /dev/null +++ b/libsecurity_apple_x509_cl/lib/clNssUtils.h @@ -0,0 +1,273 @@ +/* + * 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. + */ + +/* + * clNssUtils.h - support for libnssasn1-based ASN1 encode/decode + */ + +#ifndef _CL_NSS_UTILS_H_ +#define _CL_NSS_UTILS_H_ + +#include +#include +#include +#include +#include "DecodedCert.h" + +/* + * A Allocator which is actually based upon a PLArenaPool. This only + * mallocs, it doesn't have a free - all memory allocated with this + * object is freed when the SecNssCoder associated with this object is + * freed. It's used to malloc the fields in DecodedCert.mCert and + * DecodedCrl.mCrl. + */ +class ArenaAllocator : public Security::Allocator +{ + NOCOPY(ArenaAllocator) +public: + ArenaAllocator(SecNssCoder &coder) + : mCoder(coder) { } + ~ArenaAllocator() { } + void *malloc(size_t) throw(std::bad_alloc) ; + void free(void *) throw() ; + void *realloc(void *, size_t) throw(std::bad_alloc); +private: + SecNssCoder &mCoder; +}; + +/* + * Misc. alloc/copy with arbitrary Allocator + */ + +/* malloc d.Data, set d.Length */ +void clAllocData( + Allocator &alloc, + CSSM_DATA &dst, + size_t len); + +/* malloc and copy */ +void clAllocCopyData( + Allocator &alloc, + const CSSM_DATA &src, + CSSM_DATA &dst); + +/* return true if two CSSM_DATAs (or two CSSM_OIDs) compare equal */ +bool clCompareCssmData( + const CSSM_DATA *data1, + const CSSM_DATA *data2); + +/* + * CSSM_DATA --> uint32 + */ +uint32 clDataToInt( + const CSSM_DATA &cdata, + CSSM_RETURN toThrow = CSSMERR_CL_INVALID_CERT_POINTER); +void clIntToData( + uint32 num, + CSSM_DATA &cdata, + Allocator &alloc); + +/* CSSM_BOOL <--> CSSM_DATA */ +CSSM_BOOL clNssBoolToCssm( + const CSSM_DATA &nssBool); +void clCssmBoolToNss( + CSSM_BOOL cBool, + CSSM_DATA &nssBool, + Allocator &alloc); + +/* Bit String */ +void clCssmBitStringToNss( + CSSM_DATA &b); +void clNssBitStringToCssm( + CSSM_DATA &b); + +/* How many items in a NULL-terminated array of pointers? */ +unsigned clNssArraySize( + const void **array); + +/* malloc a NULL-ed array of pointers of size num+1 */ +void **clNssNullArray( + uint32 num, + SecNssCoder &coder); + +CE_KeyUsage clBitStringToKeyUsage( + const CSSM_DATA &cdata); + +CSSM_ALGORITHMS CL_oidToAlg( + const CSSM_OID &oid); + +void CL_copyAlgId( + const CSSM_X509_ALGORITHM_IDENTIFIER &srcAlgId, + CSSM_X509_ALGORITHM_IDENTIFIER &destAlgId, + Allocator &alloc); +void CL_freeCssmAlgId( + CSSM_X509_ALGORITHM_IDENTIFIER *cdsaObj, // optional + Allocator &alloc); + + +bool CL_nssTimeToCssm( + const NSS_Time &derTime, + CSSM_X509_TIME &cssmObj, + Allocator &alloc); +void CL_cssmTimeToNss( + const CSSM_X509_TIME &cssmTime, + NSS_Time &nssTime, + SecNssCoder &coder); +void CL_freeCssmTime( + CSSM_X509_TIME *cssmTime, + Allocator &alloc); + +void CL_nullAlgParams( + CSSM_X509_ALGORITHM_IDENTIFIER &algId); + +void CL_copySubjPubKeyInfo( + const CSSM_X509_SUBJECT_PUBLIC_KEY_INFO &srcInfo, + bool srcInBits, + CSSM_X509_SUBJECT_PUBLIC_KEY_INFO &dstInfo, + bool dstInBits, + Allocator &alloc); +CSSM_KEY_PTR CL_extractCSSMKeyNSS( + const CSSM_X509_SUBJECT_PUBLIC_KEY_INFO &keyInfo, + Allocator &alloc, + const DecodedCert *decodedCert); // optional +void CL_CSSMKeyToSubjPubKeyInfoNSS( + const CSSM_KEY &cssmKey, + CSSM_X509_SUBJECT_PUBLIC_KEY_INFO &nssKeyInfo, + SecNssCoder &coder); +void CL_freeCSSMKey( + CSSM_KEY_PTR cssmKey, + Allocator &alloc, + bool freeTop = true); // delete the actual key + // as well as contents + +void CL_cssmAuthorityKeyIdToNss( + const CE_AuthorityKeyID &cdsaObj, + NSS_AuthorityKeyId &nssObj, + SecNssCoder &coder); +void CL_nssAuthorityKeyIdToCssm( + const NSS_AuthorityKeyId &nssObj, + CE_AuthorityKeyID &cdsaObj, + SecNssCoder &coder, // for temp decoding + Allocator &alloc); + +void CL_cssmInfoAccessToNss( + const CE_AuthorityInfoAccess &cdsaObj, + NSS_AuthorityInfoAccess &nssObj, + SecNssCoder &coder); +void CL_infoAccessToCssm( + const NSS_AuthorityInfoAccess &nssObj, + CE_AuthorityInfoAccess &cdsaObj, + SecNssCoder &coder, // for temp decoding + Allocator &alloc); +void CL_freeInfoAccess( + CE_AuthorityInfoAccess &cssmInfo, + Allocator &alloc); + +void CL_cssmQualCertStatementsToNss( + const CE_QC_Statements &cdsaObj, + NSS_QC_Statements &nssObj, + SecNssCoder &coder); +void CL_qualCertStatementsToCssm( + const NSS_QC_Statements &nssObj, + CE_QC_Statements &cdsaObj, + SecNssCoder &coder, // for temp decoding + Allocator &alloc); +void CL_freeQualCertStatements( + CE_QC_Statements &cssmQCs, + Allocator &alloc); + +void CL_decodeDistributionPointName( + const CSSM_DATA &nssBlob, + CE_DistributionPointName &cssmDpn, + SecNssCoder &coder, + Allocator &alloc); +void CL_encodeDistributionPointName( + CE_DistributionPointName &cpoint, + CSSM_DATA &npoint, + SecNssCoder &coder); +void CL_cssmDistPointsToNss( + const CE_CRLDistPointsSyntax &cdsaObj, + NSS_CRLDistributionPoints &nssObj, + SecNssCoder &coder); +void CL_nssDistPointsToCssm( + const NSS_CRLDistributionPoints &nssObj, + CE_CRLDistPointsSyntax &cdsaObj, + SecNssCoder &coder, // for temp decoding + Allocator &alloc); + +void CL_nssIssuingDistPointToCssm( + NSS_IssuingDistributionPoint *nssIdp, + CE_IssuingDistributionPoint *cssmIdp, + SecNssCoder &coder, + Allocator &alloc); + +void CL_cssmNameConstraintsToNss( + const CE_NameConstraints &cdsaObj, + NSS_NameConstraints &nssObj, + SecNssCoder &coder); +void CL_nssNameConstraintsToCssm( + const NSS_NameConstraints &nssObj, + CE_NameConstraints &cdsaObj, + SecNssCoder &coder, // for temp decoding + Allocator &alloc); +void CL_freeCssmNameConstraints( + CE_NameConstraints *cssmNcs, + Allocator &alloc); + +void CL_cssmPolicyMappingsToNss( + const CE_PolicyMappings &cdsaObj, + NSS_PolicyMappings &nssObj, + SecNssCoder &coder); +void CL_nssPolicyMappingsToCssm( + const NSS_PolicyMappings &nssObj, + CE_PolicyMappings &cdsaObj, + SecNssCoder &coder, // for temp decoding + Allocator &alloc); +void CL_freeCssmPolicyMappings( + CE_PolicyMappings *cssmPms, + Allocator &alloc); + +void CL_cssmPolicyConstraintsToNss( + const CE_PolicyConstraints *cdsaObj, + NSS_PolicyConstraints *nssObj, + SecNssCoder &coder); +void CL_nssPolicyConstraintsToCssm( + const NSS_PolicyConstraints *nssObj, + CE_PolicyConstraints *cdsaObj, + SecNssCoder &coder, // for temp decoding + Allocator &alloc); +void CL_freeCssmPolicyConstraints( + CE_PolicyConstraints *cssmPcs, + Allocator &alloc); + +CSSM_ALGORITHMS CL_nssDecodeECDSASigAlgParams( + const CSSM_DATA &algParams, + SecNssCoder &coder); + +void CL_certCrlDecodeComponents( + const CssmData &signedItem, // DER-encoded cert or CRL + CssmOwnedData &tbsBlob, // still DER-encoded + CssmOwnedData &algId, // ditto + CssmOwnedData &rawSig); // raw bits (not an encoded AsnBits) +void +CL_certEncodeComponents( + const CssmData &TBSCert, // DER-encoded + const CssmData &algId, // ditto + const CssmData &rawSig, // raw bits, not encoded + CssmOwnedData &signedCert); // DER-encoded + +#endif /* _CL_NSS_UTILS_H_ */ diff --git a/libsecurity_apple_x509_cl/lib/cldebugging.h b/libsecurity_apple_x509_cl/lib/cldebugging.h new file mode 100644 index 00000000..80078490 --- /dev/null +++ b/libsecurity_apple_x509_cl/lib/cldebugging.h @@ -0,0 +1,38 @@ +/* + * 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: cldebugging.h + + Contains: Debugging macros. +*/ + +#ifndef _CLDEBUGGING_H_ +#define _CLDEBUGGING_H_ + +#include + +#ifdef NDEBUG +/* this actually compiles to nothing */ +#define clErrorLog(args...) secdebug("clError", ## args) +#else +#define clErrorLog(args...) printf(args) +#endif +#define clFieldLog(args...) secdebug("clField", ## args) + +#endif /* _CLDEBUGGING_H_ */ diff --git a/libsecurity_apple_x509_cl/libsecurity_apple_x509_cl.xcodeproj/project.pbxproj b/libsecurity_apple_x509_cl/libsecurity_apple_x509_cl.xcodeproj/project.pbxproj new file mode 100644 index 00000000..c55e15eb --- /dev/null +++ b/libsecurity_apple_x509_cl/libsecurity_apple_x509_cl.xcodeproj/project.pbxproj @@ -0,0 +1,487 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 4094AFC3057E9E3F00B44BCC /* AppleX509CLPlugin.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C284365C053485B1000AE0FC /* AppleX509CLPlugin.cpp */; }; + 4CEDA0F10612784300545384 /* cl_common.mdsinfo in Resources */ = {isa = PBXBuildFile; fileRef = 4094B07D057EA5D400B44BCC /* cl_common.mdsinfo */; }; + 4CEDA0F20612784300545384 /* cl_primary.mdsinfo in Resources */ = {isa = PBXBuildFile; fileRef = 4094B07E057EA5D400B44BCC /* cl_primary.mdsinfo */; }; + C256F8E5053B20A300B26642 /* AppleX509CLBuiltin.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C256F8E4053B20A300B26642 /* AppleX509CLBuiltin.cpp */; }; + C284367D053485B1000AE0FC /* AppleX509CL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C284365A053485B1000AE0FC /* AppleX509CL.cpp */; }; + C284367E053485B1000AE0FC /* AppleX509CL.h in Headers */ = {isa = PBXBuildFile; fileRef = C284365B053485B1000AE0FC /* AppleX509CL.h */; }; + C2843680053485B1000AE0FC /* AppleX509CLSession.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C284365D053485B1000AE0FC /* AppleX509CLSession.cpp */; }; + C2843681053485B1000AE0FC /* AppleX509CLSession.h in Headers */ = {isa = PBXBuildFile; fileRef = C284365E053485B1000AE0FC /* AppleX509CLSession.h */; }; + C2843682053485B1000AE0FC /* CertFields.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C284365F053485B1000AE0FC /* CertFields.cpp */; }; + C2843683053485B1000AE0FC /* CLCachedEntry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2843660053485B1000AE0FC /* CLCachedEntry.cpp */; }; + C2843684053485B1000AE0FC /* CLCachedEntry.h in Headers */ = {isa = PBXBuildFile; fileRef = C2843661053485B1000AE0FC /* CLCachedEntry.h */; }; + C2843685053485B1000AE0FC /* CLCertExtensions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2843662053485B1000AE0FC /* CLCertExtensions.cpp */; }; + C2843686053485B1000AE0FC /* CLCertExtensions.h in Headers */ = {isa = PBXBuildFile; fileRef = C2843663053485B1000AE0FC /* CLCertExtensions.h */; }; + C2843687053485B1000AE0FC /* CLCrlExtensions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2843664053485B1000AE0FC /* CLCrlExtensions.cpp */; }; + C2843688053485B1000AE0FC /* CLCrlExtensions.h in Headers */ = {isa = PBXBuildFile; fileRef = C2843665053485B1000AE0FC /* CLCrlExtensions.h */; }; + C2843689053485B1000AE0FC /* cldebugging.h in Headers */ = {isa = PBXBuildFile; fileRef = C2843666053485B1000AE0FC /* cldebugging.h */; }; + C284368A053485B1000AE0FC /* CLFieldsCommon.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2843667053485B1000AE0FC /* CLFieldsCommon.cpp */; }; + C284368B053485B1000AE0FC /* CLFieldsCommon.h in Headers */ = {isa = PBXBuildFile; fileRef = C2843668053485B1000AE0FC /* CLFieldsCommon.h */; }; + C284368C053485B1000AE0FC /* clNameUtils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2843669053485B1000AE0FC /* clNameUtils.cpp */; }; + C284368D053485B1000AE0FC /* clNameUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = C284366A053485B1000AE0FC /* clNameUtils.h */; }; + C284368E053485B1000AE0FC /* clNssUtils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C284366B053485B1000AE0FC /* clNssUtils.cpp */; }; + C284368F053485B1000AE0FC /* clNssUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = C284366C053485B1000AE0FC /* clNssUtils.h */; }; + C2843690053485B1000AE0FC /* CrlFields.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C284366D053485B1000AE0FC /* CrlFields.cpp */; }; + C2843691053485B1000AE0FC /* CSPAttacher.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C284366E053485B1000AE0FC /* CSPAttacher.cpp */; }; + C2843692053485B1000AE0FC /* CSPAttacher.h in Headers */ = {isa = PBXBuildFile; fileRef = C284366F053485B1000AE0FC /* CSPAttacher.h */; }; + C2843693053485B1000AE0FC /* DecodedCert.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2843670053485B1000AE0FC /* DecodedCert.cpp */; }; + C2843694053485B1000AE0FC /* DecodedCert.h in Headers */ = {isa = PBXBuildFile; fileRef = C2843671053485B1000AE0FC /* DecodedCert.h */; }; + C2843695053485B1000AE0FC /* DecodedCrl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2843672053485B1000AE0FC /* DecodedCrl.cpp */; }; + C2843696053485B1000AE0FC /* DecodedCrl.h in Headers */ = {isa = PBXBuildFile; fileRef = C2843673053485B1000AE0FC /* DecodedCrl.h */; }; + C2843697053485B1000AE0FC /* DecodedExtensions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2843674053485B1000AE0FC /* DecodedExtensions.cpp */; }; + C2843698053485B1000AE0FC /* DecodedExtensions.h in Headers */ = {isa = PBXBuildFile; fileRef = C2843675053485B1000AE0FC /* DecodedExtensions.h */; }; + C2843699053485B1000AE0FC /* DecodedItem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2843676053485B1000AE0FC /* DecodedItem.cpp */; }; + C284369A053485B1000AE0FC /* DecodedItem.h in Headers */ = {isa = PBXBuildFile; fileRef = C2843677053485B1000AE0FC /* DecodedItem.h */; }; + C284369B053485B1000AE0FC /* LockedMap.h in Headers */ = {isa = PBXBuildFile; fileRef = C2843678053485B1000AE0FC /* LockedMap.h */; }; + C284369C053485B1000AE0FC /* Session_Cert.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2843679053485B1000AE0FC /* Session_Cert.cpp */; }; + C284369D053485B1000AE0FC /* Session_CRL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C284367A053485B1000AE0FC /* Session_CRL.cpp */; }; + C284369E053485B1000AE0FC /* Session_Crypto.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C284367B053485B1000AE0FC /* Session_Crypto.cpp */; }; + C284369F053485B1000AE0FC /* Session_CSR.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C284367C053485B1000AE0FC /* Session_CSR.cpp */; }; + C2D3112E053B225E00CB61B1 /* AppleX509CLPlugin.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C284365C053485B1000AE0FC /* AppleX509CLPlugin.cpp */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 182BB350146F110B000BF1F3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 18446107146E84E500B12992 /* libsecurity_cdsa_plugin.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = C2C38A530535EDE600D7421F; + remoteInfo = libsecurity_cdsa_plugin_generate; + }; + 1844610C146E84E500B12992 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 18446107146E84E500B12992 /* libsecurity_cdsa_plugin.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 4CA1FEBE052A3C8100F22E42; + remoteInfo = libsecurity_cdsa_plugin; + }; + 4094B04E057EA52A00B44BCC /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4CA1FEAB052A3C3800F22E42 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4CA1FEBD052A3C8100F22E42; + remoteInfo = libsecurity_apple_x509_cl; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 184460FE146E82B800B12992 /* base.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = base.xcconfig; sourceTree = ""; }; + 184460FF146E82B800B12992 /* debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = debug.xcconfig; sourceTree = ""; }; + 18446100146E82B800B12992 /* lib.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = lib.xcconfig; sourceTree = ""; }; + 18446101146E82B800B12992 /* release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = release.xcconfig; sourceTree = ""; }; + 18446107146E84E500B12992 /* libsecurity_cdsa_plugin.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libsecurity_cdsa_plugin.xcodeproj; path = ../libsecurity_cdsa_plugin/libsecurity_cdsa_plugin.xcodeproj; sourceTree = ""; }; + 4094B07D057EA5D400B44BCC /* cl_common.mdsinfo */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.xml; path = cl_common.mdsinfo; sourceTree = ""; }; + 4094B07E057EA5D400B44BCC /* cl_primary.mdsinfo */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.xml; path = cl_primary.mdsinfo; sourceTree = ""; }; + 4CC7C27506127AA100E6CE35 /* libsecurity_apple_x509_cl.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libsecurity_apple_x509_cl.a; sourceTree = BUILT_PRODUCTS_DIR; }; + C207F277053B21E600FF85CB /* apple_x509_cl.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; path = apple_x509_cl.bundle; sourceTree = BUILT_PRODUCTS_DIR; }; + C256F8E4053B20A300B26642 /* AppleX509CLBuiltin.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = AppleX509CLBuiltin.cpp; sourceTree = ""; }; + C284365A053485B1000AE0FC /* AppleX509CL.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = AppleX509CL.cpp; sourceTree = ""; }; + C284365B053485B1000AE0FC /* AppleX509CL.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = AppleX509CL.h; sourceTree = ""; }; + C284365C053485B1000AE0FC /* AppleX509CLPlugin.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = AppleX509CLPlugin.cpp; sourceTree = ""; }; + C284365D053485B1000AE0FC /* AppleX509CLSession.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = AppleX509CLSession.cpp; sourceTree = ""; }; + C284365E053485B1000AE0FC /* AppleX509CLSession.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = AppleX509CLSession.h; sourceTree = ""; }; + C284365F053485B1000AE0FC /* CertFields.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = CertFields.cpp; sourceTree = ""; }; + C2843660053485B1000AE0FC /* CLCachedEntry.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = CLCachedEntry.cpp; sourceTree = ""; }; + C2843661053485B1000AE0FC /* CLCachedEntry.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = CLCachedEntry.h; sourceTree = ""; }; + C2843662053485B1000AE0FC /* CLCertExtensions.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = CLCertExtensions.cpp; sourceTree = ""; }; + C2843663053485B1000AE0FC /* CLCertExtensions.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = CLCertExtensions.h; sourceTree = ""; }; + C2843664053485B1000AE0FC /* CLCrlExtensions.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = CLCrlExtensions.cpp; sourceTree = ""; }; + C2843665053485B1000AE0FC /* CLCrlExtensions.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = CLCrlExtensions.h; sourceTree = ""; }; + C2843666053485B1000AE0FC /* cldebugging.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cldebugging.h; sourceTree = ""; }; + C2843667053485B1000AE0FC /* CLFieldsCommon.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = CLFieldsCommon.cpp; sourceTree = ""; }; + C2843668053485B1000AE0FC /* CLFieldsCommon.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = CLFieldsCommon.h; sourceTree = ""; }; + C2843669053485B1000AE0FC /* clNameUtils.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = clNameUtils.cpp; sourceTree = ""; }; + C284366A053485B1000AE0FC /* clNameUtils.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = clNameUtils.h; sourceTree = ""; }; + C284366B053485B1000AE0FC /* clNssUtils.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = clNssUtils.cpp; sourceTree = ""; }; + C284366C053485B1000AE0FC /* clNssUtils.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = clNssUtils.h; sourceTree = ""; }; + C284366D053485B1000AE0FC /* CrlFields.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = CrlFields.cpp; sourceTree = ""; }; + C284366E053485B1000AE0FC /* CSPAttacher.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = CSPAttacher.cpp; sourceTree = ""; }; + C284366F053485B1000AE0FC /* CSPAttacher.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = CSPAttacher.h; sourceTree = ""; }; + C2843670053485B1000AE0FC /* DecodedCert.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = DecodedCert.cpp; sourceTree = ""; }; + C2843671053485B1000AE0FC /* DecodedCert.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DecodedCert.h; sourceTree = ""; }; + C2843672053485B1000AE0FC /* DecodedCrl.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = DecodedCrl.cpp; sourceTree = ""; }; + C2843673053485B1000AE0FC /* DecodedCrl.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DecodedCrl.h; sourceTree = ""; }; + C2843674053485B1000AE0FC /* DecodedExtensions.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = DecodedExtensions.cpp; sourceTree = ""; }; + C2843675053485B1000AE0FC /* DecodedExtensions.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DecodedExtensions.h; sourceTree = ""; }; + C2843676053485B1000AE0FC /* DecodedItem.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = DecodedItem.cpp; sourceTree = ""; }; + C2843677053485B1000AE0FC /* DecodedItem.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DecodedItem.h; sourceTree = ""; }; + C2843678053485B1000AE0FC /* LockedMap.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = LockedMap.h; sourceTree = ""; }; + C2843679053485B1000AE0FC /* Session_Cert.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = Session_Cert.cpp; sourceTree = ""; }; + C284367A053485B1000AE0FC /* Session_CRL.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = Session_CRL.cpp; sourceTree = ""; }; + C284367B053485B1000AE0FC /* Session_Crypto.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = Session_Crypto.cpp; sourceTree = ""; }; + C284367C053485B1000AE0FC /* Session_CSR.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = Session_CSR.cpp; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 4CA1FEBB052A3C8100F22E42 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4CEDA0FD0612788200545384 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 184460FD146E82B800B12992 /* config */ = { + isa = PBXGroup; + children = ( + 184460FE146E82B800B12992 /* base.xcconfig */, + 184460FF146E82B800B12992 /* debug.xcconfig */, + 18446100146E82B800B12992 /* lib.xcconfig */, + 18446101146E82B800B12992 /* release.xcconfig */, + ); + name = config; + path = ../config; + sourceTree = ""; + }; + 18446108146E84E500B12992 /* Products */ = { + isa = PBXGroup; + children = ( + 1844610D146E84E500B12992 /* libsecurity_cdsa_plugin.a */, + ); + name = Products; + sourceTree = ""; + }; + 4094B07C057EA5D400B44BCC /* mds */ = { + isa = PBXGroup; + children = ( + 4094B07D057EA5D400B44BCC /* cl_common.mdsinfo */, + 4094B07E057EA5D400B44BCC /* cl_primary.mdsinfo */, + ); + path = mds; + sourceTree = ""; + }; + 4CA1FEA7052A3C3800F22E42 = { + isa = PBXGroup; + children = ( + 18446107146E84E500B12992 /* libsecurity_cdsa_plugin.xcodeproj */, + C2843659053485B1000AE0FC /* lib */, + 184460FD146E82B800B12992 /* config */, + 4094B07C057EA5D400B44BCC /* mds */, + 4CA1FEBF052A3C8100F22E42 /* Products */, + ); + sourceTree = ""; + }; + 4CA1FEBF052A3C8100F22E42 /* Products */ = { + isa = PBXGroup; + children = ( + C207F277053B21E600FF85CB /* apple_x509_cl.bundle */, + 4CC7C27506127AA100E6CE35 /* libsecurity_apple_x509_cl.a */, + ); + name = Products; + sourceTree = ""; + }; + C2843659053485B1000AE0FC /* lib */ = { + isa = PBXGroup; + children = ( + C284365A053485B1000AE0FC /* AppleX509CL.cpp */, + C284365B053485B1000AE0FC /* AppleX509CL.h */, + C256F8E4053B20A300B26642 /* AppleX509CLBuiltin.cpp */, + C284365C053485B1000AE0FC /* AppleX509CLPlugin.cpp */, + C284365D053485B1000AE0FC /* AppleX509CLSession.cpp */, + C284365E053485B1000AE0FC /* AppleX509CLSession.h */, + C284365F053485B1000AE0FC /* CertFields.cpp */, + C2843660053485B1000AE0FC /* CLCachedEntry.cpp */, + C2843661053485B1000AE0FC /* CLCachedEntry.h */, + C2843662053485B1000AE0FC /* CLCertExtensions.cpp */, + C2843663053485B1000AE0FC /* CLCertExtensions.h */, + C2843664053485B1000AE0FC /* CLCrlExtensions.cpp */, + C2843665053485B1000AE0FC /* CLCrlExtensions.h */, + C2843666053485B1000AE0FC /* cldebugging.h */, + C2843667053485B1000AE0FC /* CLFieldsCommon.cpp */, + C2843668053485B1000AE0FC /* CLFieldsCommon.h */, + C2843669053485B1000AE0FC /* clNameUtils.cpp */, + C284366A053485B1000AE0FC /* clNameUtils.h */, + C284366B053485B1000AE0FC /* clNssUtils.cpp */, + C284366C053485B1000AE0FC /* clNssUtils.h */, + C284366D053485B1000AE0FC /* CrlFields.cpp */, + C284366E053485B1000AE0FC /* CSPAttacher.cpp */, + C284366F053485B1000AE0FC /* CSPAttacher.h */, + C2843670053485B1000AE0FC /* DecodedCert.cpp */, + C2843671053485B1000AE0FC /* DecodedCert.h */, + C2843672053485B1000AE0FC /* DecodedCrl.cpp */, + C2843673053485B1000AE0FC /* DecodedCrl.h */, + C2843674053485B1000AE0FC /* DecodedExtensions.cpp */, + C2843675053485B1000AE0FC /* DecodedExtensions.h */, + C2843676053485B1000AE0FC /* DecodedItem.cpp */, + C2843677053485B1000AE0FC /* DecodedItem.h */, + C2843678053485B1000AE0FC /* LockedMap.h */, + C2843679053485B1000AE0FC /* Session_Cert.cpp */, + C284367A053485B1000AE0FC /* Session_CRL.cpp */, + C284367B053485B1000AE0FC /* Session_Crypto.cpp */, + C284367C053485B1000AE0FC /* Session_CSR.cpp */, + ); + path = lib; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 4CA1FEB9052A3C8100F22E42 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + C284367E053485B1000AE0FC /* AppleX509CL.h in Headers */, + C2843681053485B1000AE0FC /* AppleX509CLSession.h in Headers */, + C2843684053485B1000AE0FC /* CLCachedEntry.h in Headers */, + C2843686053485B1000AE0FC /* CLCertExtensions.h in Headers */, + C2843688053485B1000AE0FC /* CLCrlExtensions.h in Headers */, + C2843689053485B1000AE0FC /* cldebugging.h in Headers */, + C284368B053485B1000AE0FC /* CLFieldsCommon.h in Headers */, + C284368D053485B1000AE0FC /* clNameUtils.h in Headers */, + C284368F053485B1000AE0FC /* clNssUtils.h in Headers */, + C2843692053485B1000AE0FC /* CSPAttacher.h in Headers */, + C2843694053485B1000AE0FC /* DecodedCert.h in Headers */, + C2843696053485B1000AE0FC /* DecodedCrl.h in Headers */, + C2843698053485B1000AE0FC /* DecodedExtensions.h in Headers */, + C284369A053485B1000AE0FC /* DecodedItem.h in Headers */, + C284369B053485B1000AE0FC /* LockedMap.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 4CA1FEBD052A3C8100F22E42 /* libsecurity_apple_x509_cl */ = { + isa = PBXNativeTarget; + buildConfigurationList = C27AD2850987FCDC001272E0 /* Build configuration list for PBXNativeTarget "libsecurity_apple_x509_cl" */; + buildPhases = ( + 4CA1FEB9052A3C8100F22E42 /* Headers */, + 4CA1FEBA052A3C8100F22E42 /* Sources */, + 4CA1FEBB052A3C8100F22E42 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + 182BB351146F110B000BF1F3 /* PBXTargetDependency */, + ); + name = libsecurity_apple_x509_cl; + productInstallPath = /usr/local/lib; + productName = libsecurity_apple_x509_cl; + productReference = 4CC7C27506127AA100E6CE35 /* libsecurity_apple_x509_cl.a */; + productType = "com.apple.product-type.library.static"; + }; + C207F276053B21E600FF85CB /* plugin_apple_x509_cl */ = { + isa = PBXNativeTarget; + buildConfigurationList = C27AD2890987FCDC001272E0 /* Build configuration list for PBXNativeTarget "plugin_apple_x509_cl" */; + buildPhases = ( + C207F272053B21E600FF85CB /* Resources */, + C207F273053B21E600FF85CB /* Sources */, + 4CEDA0FD0612788200545384 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + C2AAE44B053B54E2009142E3 /* PBXTargetDependency */, + ); + name = plugin_apple_x509_cl; + productInstallPath = "$(USER_LIBRARY_DIR)/Bundles"; + productName = plugin_apple_x509_cl; + productReference = C207F277053B21E600FF85CB /* apple_x509_cl.bundle */; + productType = "com.apple.product-type.bundle"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 4CA1FEAB052A3C3800F22E42 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0420; + }; + buildConfigurationList = C27AD28D0987FCDC001272E0 /* Build configuration list for PBXProject "libsecurity_apple_x509_cl" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 1; + knownRegions = ( + en, + ); + mainGroup = 4CA1FEA7052A3C3800F22E42; + productRefGroup = 4CA1FEBF052A3C8100F22E42 /* Products */; + projectDirPath = ""; + projectReferences = ( + { + ProductGroup = 18446108146E84E500B12992 /* Products */; + ProjectRef = 18446107146E84E500B12992 /* libsecurity_cdsa_plugin.xcodeproj */; + }, + ); + projectRoot = ""; + targets = ( + 4CA1FEBD052A3C8100F22E42 /* libsecurity_apple_x509_cl */, + C207F276053B21E600FF85CB /* plugin_apple_x509_cl */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXReferenceProxy section */ + 1844610D146E84E500B12992 /* libsecurity_cdsa_plugin.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libsecurity_cdsa_plugin.a; + remoteRef = 1844610C146E84E500B12992 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; +/* End PBXReferenceProxy section */ + +/* Begin PBXResourcesBuildPhase section */ + C207F272053B21E600FF85CB /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4CEDA0F10612784300545384 /* cl_common.mdsinfo in Resources */, + 4CEDA0F20612784300545384 /* cl_primary.mdsinfo in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 4CA1FEBA052A3C8100F22E42 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + C284367D053485B1000AE0FC /* AppleX509CL.cpp in Sources */, + C2843680053485B1000AE0FC /* AppleX509CLSession.cpp in Sources */, + C2843682053485B1000AE0FC /* CertFields.cpp in Sources */, + C2843683053485B1000AE0FC /* CLCachedEntry.cpp in Sources */, + C2843685053485B1000AE0FC /* CLCertExtensions.cpp in Sources */, + C2843687053485B1000AE0FC /* CLCrlExtensions.cpp in Sources */, + C284368A053485B1000AE0FC /* CLFieldsCommon.cpp in Sources */, + C284368C053485B1000AE0FC /* clNameUtils.cpp in Sources */, + C284368E053485B1000AE0FC /* clNssUtils.cpp in Sources */, + C2843690053485B1000AE0FC /* CrlFields.cpp in Sources */, + C2843691053485B1000AE0FC /* CSPAttacher.cpp in Sources */, + C2843693053485B1000AE0FC /* DecodedCert.cpp in Sources */, + C2843695053485B1000AE0FC /* DecodedCrl.cpp in Sources */, + C2843697053485B1000AE0FC /* DecodedExtensions.cpp in Sources */, + C2843699053485B1000AE0FC /* DecodedItem.cpp in Sources */, + C284369C053485B1000AE0FC /* Session_Cert.cpp in Sources */, + C284369D053485B1000AE0FC /* Session_CRL.cpp in Sources */, + C284369E053485B1000AE0FC /* Session_Crypto.cpp in Sources */, + C284369F053485B1000AE0FC /* Session_CSR.cpp in Sources */, + C256F8E5053B20A300B26642 /* AppleX509CLBuiltin.cpp in Sources */, + 4094AFC3057E9E3F00B44BCC /* AppleX509CLPlugin.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + C207F273053B21E600FF85CB /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + C2D3112E053B225E00CB61B1 /* AppleX509CLPlugin.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 182BB351146F110B000BF1F3 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = libsecurity_cdsa_plugin_generate; + targetProxy = 182BB350146F110B000BF1F3 /* PBXContainerItemProxy */; + }; + C2AAE44B053B54E2009142E3 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 4CA1FEBD052A3C8100F22E42 /* libsecurity_apple_x509_cl */; + targetProxy = 4094B04E057EA52A00B44BCC /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + C27AD2860987FCDC001272E0 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 184460FF146E82B800B12992 /* debug.xcconfig */; + buildSettings = { + }; + name = Debug; + }; + C27AD2880987FCDC001272E0 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 18446101146E82B800B12992 /* release.xcconfig */; + buildSettings = { + }; + name = Release; + }; + C27AD28A0987FCDC001272E0 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + EXECUTABLE_PREFIX = ""; + INFOPLIST_FILE = "Info-plugin_apple_x509_cl.plist"; + PRODUCT_NAME = apple_x509_cl; + WRAPPER_EXTENSION = bundle; + }; + name = Debug; + }; + C27AD28C0987FCDC001272E0 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + EXECUTABLE_PREFIX = ""; + INFOPLIST_FILE = "Info-plugin_apple_x509_cl.plist"; + PRODUCT_NAME = apple_x509_cl; + WRAPPER_EXTENSION = bundle; + }; + name = Release; + }; + C27AD28E0987FCDC001272E0 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 18446100146E82B800B12992 /* lib.xcconfig */; + buildSettings = { + }; + name = Debug; + }; + C27AD2900987FCDC001272E0 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 18446100146E82B800B12992 /* lib.xcconfig */; + buildSettings = { + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + C27AD2850987FCDC001272E0 /* Build configuration list for PBXNativeTarget "libsecurity_apple_x509_cl" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C27AD2860987FCDC001272E0 /* Debug */, + C27AD2880987FCDC001272E0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C27AD2890987FCDC001272E0 /* Build configuration list for PBXNativeTarget "plugin_apple_x509_cl" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C27AD28A0987FCDC001272E0 /* Debug */, + C27AD28C0987FCDC001272E0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C27AD28D0987FCDC001272E0 /* Build configuration list for PBXProject "libsecurity_apple_x509_cl" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C27AD28E0987FCDC001272E0 /* Debug */, + C27AD2900987FCDC001272E0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 4CA1FEAB052A3C3800F22E42 /* Project object */; +} diff --git a/libsecurity_apple_x509_cl/mds/cl_common.mdsinfo b/libsecurity_apple_x509_cl/mds/cl_common.mdsinfo new file mode 100644 index 00000000..0dfcb178 --- /dev/null +++ b/libsecurity_apple_x509_cl/mds/cl_common.mdsinfo @@ -0,0 +1,30 @@ + + + + + BuiltIn + + CDSAVersion + 2.0 + Desc + Apple built-in CL + DynamicFlag + + MdsFileDescription + Built-in X509 CL Common info + MdsFileType + PluginCommon + ModuleID + {87191ca4-0fc9-11d4-849a-000502b52122} + ModuleName + AppleX509CL + MultiThreadFlag + + ProductVersion + 1.0 + ServiceMask + CSSM_SERVICE_CL + Path + *AppleX509CL + + diff --git a/libsecurity_apple_x509_cl/mds/cl_primary.mdsinfo b/libsecurity_apple_x509_cl/mds/cl_primary.mdsinfo new file mode 100644 index 00000000..04c96cfd --- /dev/null +++ b/libsecurity_apple_x509_cl/mds/cl_primary.mdsinfo @@ -0,0 +1,38 @@ + + + + + BundleTypeFormat + + CertFieldsNames + + + CertTypeFormat + <<CSSM_CERT_X_509v3 | CSSM_CERT_ENCODING_DER + CrlTypeFormat_NONE + 0 + DefaultTemplateType + CSSM_CL_TEMPLATE_INTERMEDIATE_CERT + MdsFileDescription + Built-in X509CL Primary info + MdsFileType + PluginSpecific + MdsRecordType + MDS_CDSADIR_CL_PRIMARY_RECORDTYPE + ModuleID + {87191ca4-0fc9-11d4-849a-000502b52122} + ModuleName + AppleX509CL + ProductVersion + 1.0 + SSID + 0 + TemplateFieldNames + + + Vendor + Apple Computer, Inc. + XlationTypeFormat + + + diff --git a/libsecurity_apple_x509_tp/Info-security_apple_x509_tp.plist b/libsecurity_apple_x509_tp/Info-security_apple_x509_tp.plist new file mode 100644 index 00000000..0c67376e --- /dev/null +++ b/libsecurity_apple_x509_tp/Info-security_apple_x509_tp.plist @@ -0,0 +1,5 @@ + + + + + diff --git a/libsecurity_apple_x509_tp/lib/AppleTP.cpp b/libsecurity_apple_x509_tp/lib/AppleTP.cpp new file mode 100644 index 00000000..6bd8977b --- /dev/null +++ b/libsecurity_apple_x509_tp/lib/AppleTP.cpp @@ -0,0 +1,62 @@ +/* + * 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. + */ + + +// +// AppleTP.cpp +// +#include "AppleTP.h" +#include "AppleTPSession.h" + + +// +// Make and break the plugin object +// +AppleTP::AppleTP() +{ +} + +AppleTP::~AppleTP() +{ +} + + +// +// Create a new plugin session, our way +// +PluginSession *AppleTP::makeSession( + CSSM_MODULE_HANDLE handle, + const CSSM_VERSION &version, + uint32 subserviceId, + CSSM_SERVICE_TYPE subserviceType, + CSSM_ATTACH_FLAGS attachFlags, + const CSSM_UPCALLS &upcalls) +{ + switch (subserviceType) { + case CSSM_SERVICE_TP: + return new AppleTPSession(handle, + *this, + version, + subserviceId, + subserviceType, + attachFlags, + upcalls); + default: + CssmError::throwMe(CSSMERR_CSSM_INVALID_SERVICE_MASK); + return 0; // placebo + } +} diff --git a/libsecurity_apple_x509_tp/lib/AppleTP.h b/libsecurity_apple_x509_tp/lib/AppleTP.h new file mode 100644 index 00000000..ce9780e4 --- /dev/null +++ b/libsecurity_apple_x509_tp/lib/AppleTP.h @@ -0,0 +1,48 @@ +/* + * 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. + */ + + +// +// AppleTP.h - TP module for X509, SSL, iSign +// +#ifndef _H_APPLETP +#define _H_APPLETP + +#include +#include + +class AppleTP : public CssmPlugin +{ +public: + AppleTP(); + ~AppleTP(); + + PluginSession *makeSession( + CSSM_MODULE_HANDLE handle, + const CSSM_VERSION &version, + uint32 subserviceId, + CSSM_SERVICE_TYPE subserviceType, + CSSM_ATTACH_FLAGS attachFlags, + const CSSM_UPCALLS &upcalls); +private: + // Don't copy AppleTP + AppleTP(const AppleTP&); + void operator=(const AppleTP&); +}; + + +#endif //_H_APPLETP diff --git a/libsecurity_apple_x509_tp/lib/AppleTPSession.cpp b/libsecurity_apple_x509_tp/lib/AppleTPSession.cpp new file mode 100644 index 00000000..211ccb01 --- /dev/null +++ b/libsecurity_apple_x509_tp/lib/AppleTPSession.cpp @@ -0,0 +1,312 @@ +/* + * 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. + */ + + +/* + * AppleTPSession.cpp - general session support and (mostly) unimplemented functions + */ + +#include "AppleTPSession.h" +#include "TPCertInfo.h" +#include "TPCrlInfo.h" +#include "tpCrlVerify.h" +#include "tpdebugging.h" +#include + +AppleTPSession::AppleTPSession( + CSSM_MODULE_HANDLE theHandle, + CssmPlugin &plug, + const CSSM_VERSION &version, + uint32 subserviceId, + CSSM_SERVICE_TYPE subserviceType, + CSSM_ATTACH_FLAGS attachFlags, + const CSSM_UPCALLS &upcalls) + : TPPluginSession(theHandle, plug, version, subserviceId, + subserviceType,attachFlags, upcalls) +{ +} + +AppleTPSession::~AppleTPSession() +{ +} + +void AppleTPSession::CertCreateTemplate(CSSM_CL_HANDLE CLHandle, + uint32 NumberOfFields, + const CSSM_FIELD CertFields[], + CssmData &CertTemplate) +{ + CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); +} + +void AppleTPSession::CrlVerify(CSSM_CL_HANDLE CLHandle, + CSSM_CSP_HANDLE CSPHandle, + const CSSM_ENCODED_CRL &CrlToBeVerified, + const CSSM_CERTGROUP &SignerCertGroup, + const CSSM_TP_VERIFY_CONTEXT *VerifyContext, + CSSM_TP_VERIFY_CONTEXT_RESULT *RevokerVerifyResult) +{ + /* verify input args */ + if(RevokerVerifyResult != NULL) { + /* not yet, but probably someday */ + CssmError::throwMe(CSSMERR_TP_INVALID_REQUEST_INPUTS); + } + switch(CrlToBeVerified.CrlType) { + case CSSM_CRL_TYPE_X_509v1: + case CSSM_CRL_TYPE_X_509v2: + break; + default: + CssmError::throwMe(CSSMERR_TP_INVALID_CRL_TYPE); + } + switch(CrlToBeVerified.CrlEncoding) { + case CSSM_CRL_ENCODING_BER: + case CSSM_CRL_ENCODING_DER: + break; + default: + CssmError::throwMe(CSSMERR_TP_INVALID_CRL_ENCODING); + } + + /* optional arguments */ + CSSM_TIMESTRING cssmTimeStr = NULL; + const CSSM_TP_CALLERAUTH_CONTEXT *cred = NULL; + uint32 NumberOfAnchorCerts = 0; + CSSM_DATA_PTR AnchorCerts = NULL; + CSSM_DL_DB_LIST_PTR DBList = NULL; + CSSM_APPLE_TP_ACTION_FLAGS actionFlags = 0; + CSSM_APPLE_TP_ACTION_DATA *actionData = NULL; + + if(VerifyContext != NULL) { + cred = VerifyContext->Cred; + actionData = + (CSSM_APPLE_TP_ACTION_DATA *)VerifyContext->ActionData.Data; + if(actionData != NULL) { + switch(actionData->Version) { + case CSSM_APPLE_TP_ACTION_VERSION: + if(VerifyContext->ActionData.Length != + sizeof(CSSM_APPLE_TP_ACTION_DATA)) { + CssmError::throwMe(CSSMERR_TP_INVALID_ACTION_DATA); + } + break; + /* handle backwards versions here if we ever go + * beyond version 0 */ + default: + CssmError::throwMe(CSSMERR_TP_INVALID_ACTION_DATA); + } + actionFlags = actionData->ActionFlags; + } + } + if(cred != NULL) { + cssmTimeStr = cred->VerifyTime; + NumberOfAnchorCerts = cred->NumberOfAnchorCerts; + AnchorCerts = cred->AnchorCerts; + DBList = cred->DBList; + } + + /* this must be parseable, throw immediately if not */ + TPCrlInfo crlToVerify(CLHandle, CSPHandle, &CrlToBeVerified.CrlBlob, + TIC_NoCopy, cssmTimeStr); + + /* Both required at the API but in fact may be empty */ + TPCertGroup inCertGroup(SignerCertGroup, CLHandle, CSPHandle, *this, + cssmTimeStr, // optional 'this' time + false, // firstCertMustBeValid + TGO_Group); + TPCertGroup gatheredCerts(*this, TGO_Group); + + /* common CRL/OCSP verify parameters */ + TPVerifyContext vfyCtx(*this, + CLHandle, + CSPHandle, + cssmTimeStr, + NumberOfAnchorCerts, + AnchorCerts, + &inCertGroup, + NULL, // no CRLs, we're on our own + gatheredCerts, + DBList, + kRevokeCrlBasic, + actionFlags, + NULL, // crlOpts + NULL, // OCSP opts + &CSSMOID_APPLE_TP_REVOCATION_CRL, + NULL, // UT policyString + 0, + CSSM_KEYUSE_VERIFY); + + /* + * We assert the doCrlVerify flag to ensure CRL verification + * if intermediate certs which verifyWithContext() gathers to + * verify this CRL. + */ + CSSM_RETURN crtn = crlToVerify.verifyWithContext(vfyCtx, NULL, true); + if(crtn) { + tpCrlDebug("CrlVerify failure"); + CssmError::throwMe(crtn); + } +} + +void AppleTPSession::CertReclaimKey(const CSSM_CERTGROUP &CertGroup, + uint32 CertIndex, + CSSM_LONG_HANDLE KeyCacheHandle, + CSSM_CSP_HANDLE CSPHandle, + const CSSM_RESOURCE_CONTROL_CONTEXT *CredAndAclEntry) +{ + CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); +} + +/*** CertGroupVerify, CertGroupConstruct in TPCertGroup.cpp ***/ + +void AppleTPSession::CertSign(CSSM_CL_HANDLE CLHandle, + CSSM_CC_HANDLE CCHandle, + const CssmData &CertTemplateToBeSigned, + const CSSM_CERTGROUP &SignerCertGroup, + const CSSM_TP_VERIFY_CONTEXT *SignerVerifyContext, + CSSM_TP_VERIFY_CONTEXT_RESULT *SignerVerifyResult, + CssmData &SignedCert) +{ + CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); +} + +void AppleTPSession::TupleGroupToCertGroup(CSSM_CL_HANDLE CLHandle, + const CSSM_TUPLEGROUP &TupleGroup, + CSSM_CERTGROUP_PTR &CertTemplates) +{ + CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); +} + +void AppleTPSession::ReceiveConfirmation(const CssmData &ReferenceIdentifier, + CSSM_TP_CONFIRM_RESPONSE_PTR &Responses, + sint32 &ElapsedTime) +{ + CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); +} + +void AppleTPSession::PassThrough(CSSM_CL_HANDLE CLHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_DL_DB_LIST *DBList, + uint32 PassThroughId, + const void *InputParams, + void **OutputParams) +{ + CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); +} + +void AppleTPSession::CertRemoveFromCrlTemplate(CSSM_CL_HANDLE CLHandle, + CSSM_CSP_HANDLE CSPHandle, + const CssmData *OldCrlTemplate, + const CSSM_CERTGROUP &CertGroupToBeRemoved, + const CSSM_CERTGROUP &RevokerCertGroup, + const CSSM_TP_VERIFY_CONTEXT &RevokerVerifyContext, + CSSM_TP_VERIFY_CONTEXT_RESULT &RevokerVerifyResult, + CssmData &NewCrlTemplate) +{ + CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); +} + +void AppleTPSession::CertRevoke(CSSM_CL_HANDLE CLHandle, + CSSM_CSP_HANDLE CSPHandle, + const CssmData *OldCrlTemplate, + const CSSM_CERTGROUP &CertGroupToBeRevoked, + const CSSM_CERTGROUP &RevokerCertGroup, + const CSSM_TP_VERIFY_CONTEXT &RevokerVerifyContext, + CSSM_TP_VERIFY_CONTEXT_RESULT &RevokerVerifyResult, + CSSM_TP_CERTCHANGE_REASON Reason, + CssmData &NewCrlTemplate) +{ + CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); +} + +void AppleTPSession::CertReclaimAbort(CSSM_LONG_HANDLE KeyCacheHandle) +{ + CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); +} + +void AppleTPSession::CrlCreateTemplate(CSSM_CL_HANDLE CLHandle, + uint32 NumberOfFields, + const CSSM_FIELD CrlFields[], + CssmData &NewCrlTemplate) +{ + CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); +} + +void AppleTPSession::CertGroupToTupleGroup(CSSM_CL_HANDLE CLHandle, + const CSSM_CERTGROUP &CertGroup, + CSSM_TUPLEGROUP_PTR &TupleGroup) +{ + CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); +} + +void AppleTPSession::FormRequest(const CSSM_TP_AUTHORITY_ID *PreferredAuthority, + CSSM_TP_FORM_TYPE FormType, + CssmData &BlankForm) +{ + CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); +} + +void AppleTPSession::CrlSign(CSSM_CL_HANDLE CLHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_ENCODED_CRL &CrlToBeSigned, + const CSSM_CERTGROUP &SignerCertGroup, + const CSSM_TP_VERIFY_CONTEXT *SignerVerifyContext, + CSSM_TP_VERIFY_CONTEXT_RESULT *SignerVerifyResult, + CssmData &SignedCrl) +{ + CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); +} + +void AppleTPSession::CertGroupPrune(CSSM_CL_HANDLE CLHandle, + const CSSM_DL_DB_LIST &DBList, + const CSSM_CERTGROUP &OrderedCertGroup, + CSSM_CERTGROUP_PTR &PrunedCertGroup) +{ + CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); +} + +void AppleTPSession::ApplyCrlToDb(CSSM_CL_HANDLE CLHandle, + CSSM_CSP_HANDLE CSPHandle, + const CSSM_ENCODED_CRL &CrlToBeApplied, + const CSSM_CERTGROUP &SignerCertGroup, + const CSSM_TP_VERIFY_CONTEXT *ApplyCrlVerifyContext, + CSSM_TP_VERIFY_CONTEXT_RESULT &ApplyCrlVerifyResult) +{ + CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); +} + +void AppleTPSession::CertGetAllTemplateFields(CSSM_CL_HANDLE CLHandle, + const CssmData &CertTemplate, + uint32 &NumberOfFields, + CSSM_FIELD_PTR &CertFields) +{ + CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); +} + +void AppleTPSession::ConfirmCredResult(const CssmData &ReferenceIdentifier, + const CSSM_TP_CALLERAUTH_CONTEXT *CallerAuthCredentials, + const CSSM_TP_CONFIRM_RESPONSE &Responses, + const CSSM_TP_AUTHORITY_ID *PreferredAuthority) +{ + CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); +} + +void AppleTPSession::FormSubmit(CSSM_TP_FORM_TYPE FormType, + const CssmData &Form, + const CSSM_TP_AUTHORITY_ID *ClearanceAuthority, + const CSSM_TP_AUTHORITY_ID *RepresentedAuthority, + AccessCredentials *Credentials) +{ + CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); +} + diff --git a/libsecurity_apple_x509_tp/lib/AppleTPSession.h b/libsecurity_apple_x509_tp/lib/AppleTPSession.h new file mode 100644 index 00000000..a595e3b7 --- /dev/null +++ b/libsecurity_apple_x509_tp/lib/AppleTPSession.h @@ -0,0 +1,265 @@ +/* + * 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. + */ + + +/* + * AppleTPSession.h - TP session functions. + * + * Created 10/5/2000 by Doug Mitchell. + */ + +#ifndef _H_APPLE_TP_SESSION +#define _H_APPLE_TP_SESSION + +#include +#include "TPCertInfo.h" + +#define REALLOC_WORKAROUND 0 +#if REALLOC_WORKAROUND +#include +#endif + +class AppleTPSession : public TPPluginSession { + +public: + + AppleTPSession( + CSSM_MODULE_HANDLE theHandle, + CssmPlugin &plug, + const CSSM_VERSION &version, + uint32 subserviceId, + CSSM_SERVICE_TYPE subserviceType, + CSSM_ATTACH_FLAGS attachFlags, + const CSSM_UPCALLS &upcalls); + + ~AppleTPSession(); + + #if REALLOC_WORKAROUND + void *realloc(void *oldp, size_t size) { + void *newp = malloc(size); + memmove(newp, oldp, size); + free(oldp); + return newp; + } + #endif /* REALLOC_WORKAROUND */ + + /* methods declared in TPabstractSession.h */ + void CertCreateTemplate(CSSM_CL_HANDLE CLHandle, + uint32 NumberOfFields, + const CSSM_FIELD CertFields[], + CssmData &CertTemplate); + void CrlVerify(CSSM_CL_HANDLE CLHandle, + CSSM_CSP_HANDLE CSPHandle, + const CSSM_ENCODED_CRL &CrlToBeVerified, + const CSSM_CERTGROUP &SignerCertGroup, + const CSSM_TP_VERIFY_CONTEXT *VerifyContext, + CSSM_TP_VERIFY_CONTEXT_RESULT *RevokerVerifyResult); + void CertReclaimKey(const CSSM_CERTGROUP &CertGroup, + uint32 CertIndex, + CSSM_LONG_HANDLE KeyCacheHandle, + CSSM_CSP_HANDLE CSPHandle, + const CSSM_RESOURCE_CONTROL_CONTEXT *CredAndAclEntry); + void CertGroupVerify(CSSM_CL_HANDLE CLHandle, + CSSM_CSP_HANDLE CSPHandle, + const CSSM_CERTGROUP &CertGroupToBeVerified, + const CSSM_TP_VERIFY_CONTEXT *VerifyContext, + CSSM_TP_VERIFY_CONTEXT_RESULT_PTR VerifyContextResult); + void CertGroupConstruct(CSSM_CL_HANDLE CLHandle, + CSSM_CSP_HANDLE CSPHandle, + const CSSM_DL_DB_LIST &DBList, + const void *ConstructParams, + const CSSM_CERTGROUP &CertGroupFrag, + CSSM_CERTGROUP_PTR &CertGroup); + void CertSign(CSSM_CL_HANDLE CLHandle, + CSSM_CC_HANDLE CCHandle, + const CssmData &CertTemplateToBeSigned, + const CSSM_CERTGROUP &SignerCertGroup, + const CSSM_TP_VERIFY_CONTEXT *SignerVerifyContext, + CSSM_TP_VERIFY_CONTEXT_RESULT *SignerVerifyResult, + CssmData &SignedCert); + void TupleGroupToCertGroup(CSSM_CL_HANDLE CLHandle, + const CSSM_TUPLEGROUP &TupleGroup, + CSSM_CERTGROUP_PTR &CertTemplates); + void ReceiveConfirmation(const CssmData &ReferenceIdentifier, + CSSM_TP_CONFIRM_RESPONSE_PTR &Responses, + sint32 &ElapsedTime); + void PassThrough(CSSM_CL_HANDLE CLHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_DL_DB_LIST *DBList, + uint32 PassThroughId, + const void *InputParams, + void **OutputParams); + void CertRemoveFromCrlTemplate(CSSM_CL_HANDLE CLHandle, + CSSM_CSP_HANDLE CSPHandle, + const CssmData *OldCrlTemplate, + const CSSM_CERTGROUP &CertGroupToBeRemoved, + const CSSM_CERTGROUP &RevokerCertGroup, + const CSSM_TP_VERIFY_CONTEXT &RevokerVerifyContext, + CSSM_TP_VERIFY_CONTEXT_RESULT &RevokerVerifyResult, + CssmData &NewCrlTemplate); + void CertRevoke(CSSM_CL_HANDLE CLHandle, + CSSM_CSP_HANDLE CSPHandle, + const CssmData *OldCrlTemplate, + const CSSM_CERTGROUP &CertGroupToBeRevoked, + const CSSM_CERTGROUP &RevokerCertGroup, + const CSSM_TP_VERIFY_CONTEXT &RevokerVerifyContext, + CSSM_TP_VERIFY_CONTEXT_RESULT &RevokerVerifyResult, + CSSM_TP_CERTCHANGE_REASON Reason, + CssmData &NewCrlTemplate); + void CertReclaimAbort(CSSM_LONG_HANDLE KeyCacheHandle); + void CrlCreateTemplate(CSSM_CL_HANDLE CLHandle, + uint32 NumberOfFields, + const CSSM_FIELD CrlFields[], + CssmData &NewCrlTemplate); + void CertGroupToTupleGroup(CSSM_CL_HANDLE CLHandle, + const CSSM_CERTGROUP &CertGroup, + CSSM_TUPLEGROUP_PTR &TupleGroup); + void SubmitCredRequest(const CSSM_TP_AUTHORITY_ID *PreferredAuthority, + CSSM_TP_AUTHORITY_REQUEST_TYPE RequestType, + const CSSM_TP_REQUEST_SET &RequestInput, + const CSSM_TP_CALLERAUTH_CONTEXT *CallerAuthContext, + sint32 &EstimatedTime, + CssmData &ReferenceIdentifier); + void FormRequest(const CSSM_TP_AUTHORITY_ID *PreferredAuthority, + CSSM_TP_FORM_TYPE FormType, + CssmData &BlankForm); + void CrlSign(CSSM_CL_HANDLE CLHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_ENCODED_CRL &CrlToBeSigned, + const CSSM_CERTGROUP &SignerCertGroup, + const CSSM_TP_VERIFY_CONTEXT *SignerVerifyContext, + CSSM_TP_VERIFY_CONTEXT_RESULT *SignerVerifyResult, + CssmData &SignedCrl); + void CertGroupPrune(CSSM_CL_HANDLE CLHandle, + const CSSM_DL_DB_LIST &DBList, + const CSSM_CERTGROUP &OrderedCertGroup, + CSSM_CERTGROUP_PTR &PrunedCertGroup); + void ApplyCrlToDb(CSSM_CL_HANDLE CLHandle, + CSSM_CSP_HANDLE CSPHandle, + const CSSM_ENCODED_CRL &CrlToBeApplied, + const CSSM_CERTGROUP &SignerCertGroup, + const CSSM_TP_VERIFY_CONTEXT *ApplyCrlVerifyContext, + CSSM_TP_VERIFY_CONTEXT_RESULT &ApplyCrlVerifyResult); + void CertGetAllTemplateFields(CSSM_CL_HANDLE CLHandle, + const CssmData &CertTemplate, + uint32 &NumberOfFields, + CSSM_FIELD_PTR &CertFields); + void ConfirmCredResult(const CssmData &ReferenceIdentifier, + const CSSM_TP_CALLERAUTH_CONTEXT *CallerAuthCredentials, + const CSSM_TP_CONFIRM_RESPONSE &Responses, + const CSSM_TP_AUTHORITY_ID *PreferredAuthority); + void FormSubmit(CSSM_TP_FORM_TYPE FormType, + const CssmData &Form, + const CSSM_TP_AUTHORITY_ID *ClearanceAuthority, + const CSSM_TP_AUTHORITY_ID *RepresentedAuthority, + AccessCredentials *Credentials); + void RetrieveCredResult(const CssmData &ReferenceIdentifier, + const CSSM_TP_CALLERAUTH_CONTEXT *CallerAuthCredentials, + sint32 &EstimatedTime, + CSSM_BOOL &ConfirmationRequired, + CSSM_TP_RESULT_SET_PTR &RetrieveOutput); + +private: + void CertGroupConstructPriv(CSSM_CL_HANDLE clHand, + CSSM_CSP_HANDLE cspHand, + TPCertGroup &inCertGroup, + const CSSM_DL_DB_LIST *DBList, // optional here + const char *cssmTimeStr, // optional + uint32 numAnchorCerts, // optional + const CSSM_DATA *anchorCerts, + + /* CSSM_TP_ACTION_FETCH_CERT_FROM_NET, CSSM_TP_ACTION_TRUST_SETTINGS */ + CSSM_APPLE_TP_ACTION_FLAGS actionFlags, + + /* optional user trust parameters */ + const CSSM_OID *policyOid, + const char *policyStr, + uint32 policyStrLen, + CSSM_KEYUSE keyUse, + + /* + * Certs to be freed by caller (i.e., TPCertInfo which we allocate + * as a result of using a cert from anchorCerts of dbList) are added + * to this group. + */ + TPCertGroup &certsToBeFreed, + + /* returned */ + CSSM_BOOL &verifiedToRoot, // end of chain self-verifies + CSSM_BOOL &verifiedToAnchor, // end of chain in anchors + CSSM_BOOL &verifiedViaTrustSetting, // chain ends per Trust Setting + TPCertGroup &outCertGroup); // RETURNED + + /* in tpCredRequest.cp */ + CSSM_X509_NAME * buildX509Name(const CSSM_APPLE_TP_NAME_OID *nameArray, + unsigned numNames); + void freeX509Name(CSSM_X509_NAME *top); + CSSM_X509_TIME *buildX509Time(unsigned secondsFromNow); + void freeX509Time(CSSM_X509_TIME *xtime); + void refKeyToRaw( + CSSM_CSP_HANDLE cspHand, + const CSSM_KEY *refKey, + CSSM_KEY_PTR rawKey); + void makeCertTemplate( + /* required */ + CSSM_CL_HANDLE clHand, + CSSM_CSP_HANDLE cspHand, // for converting ref to raw key + 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 *subjectPubKey, + const CSSM_OID &sigOid, // e.g., CSSMOID_SHA1WithRSA + /* optional */ + const CSSM_DATA *subjectUniqueId, + const CSSM_DATA *issuerUniqueId, + CSSM_X509_EXTENSION *extensions, + unsigned numExtensions, + CSSM_DATA_PTR &rawCert); + + void SubmitCsrRequest( + const CSSM_TP_REQUEST_SET &RequestInput, + const CSSM_TP_CALLERAUTH_CONTEXT *CallerAuthContext, + sint32 &EstimatedTime, + CssmData &ReferenceIdentifier); + + /* + * Per-session storage of SubmitCredRequest results. + * + * A TpCredHandle is just an address of a cert, cast to a CSSM_INTPTR. It's + * what ReferenceIdentifier.Data points to. + */ + typedef CSSM_INTPTR TpCredHandle; + typedef std::map credMap; + credMap tpCredMap; + Mutex tpCredMapLock; + + /* given a cert and a ReferenceIdentifier, fill in ReferenceIdentifier and + * add it and the cert to tpCredMap. */ + void addCertToMap( + const CSSM_DATA *cert, + CSSM_DATA_PTR refId); + + /* given a ReferenceIdentifier, obtain associated cert and remove from the map */ + CSSM_DATA_PTR getCertFromMap( + const CSSM_DATA *refId); + +}; + +#endif /* _H_APPLE_TP_SESSION */ diff --git a/libsecurity_apple_x509_tp/lib/AppleX509TPBuiltin.cpp b/libsecurity_apple_x509_tp/lib/AppleX509TPBuiltin.cpp new file mode 100644 index 00000000..4488d108 --- /dev/null +++ b/libsecurity_apple_x509_tp/lib/AppleX509TPBuiltin.cpp @@ -0,0 +1,32 @@ +/* + * 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 obtai +n + * 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. + */ + + +// +// Produce the "genuine plugin version" of the Apple X509 TP +// +#include + + +// +// Create the plugin object and generate the C layer hookup +// +static ModuleNexus plugin; + +#define SPINAME(s) s ## __apple_x509_tp +#include diff --git a/libsecurity_apple_x509_tp/lib/AppleX509TPPlugin.cpp b/libsecurity_apple_x509_tp/lib/AppleX509TPPlugin.cpp new file mode 100644 index 00000000..268860a7 --- /dev/null +++ b/libsecurity_apple_x509_tp/lib/AppleX509TPPlugin.cpp @@ -0,0 +1,31 @@ +/* + * 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 obtai +n + * 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. + */ + + +// +// Produce the "genuine plugin version" of the Apple X509 TP +// +#include + + +// +// Create the plugin object and generate the C layer hookup +// +ModuleNexus plugin; + +#include diff --git a/libsecurity_apple_x509_tp/lib/TPCertInfo.cpp b/libsecurity_apple_x509_tp/lib/TPCertInfo.cpp new file mode 100644 index 00000000..c32bb404 --- /dev/null +++ b/libsecurity_apple_x509_tp/lib/TPCertInfo.cpp @@ -0,0 +1,2289 @@ +/* + * 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'). + * 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. + */ + + +/* + * TPCertInfo.cpp - TP's private certificate info classes + */ + +#include "TPCertInfo.h" +#include "tpdebugging.h" +#include "tpTime.h" +#include "certGroupUtils.h" +#include "TPDatabase.h" +#include "TPNetwork.h" +#include +#include +#include +#include +#include /* for memcmp */ +#include /* for Mutex */ +#include +#include +#include +#include +#include +#include +#include + +#define tpTimeDbg(args...) secdebug("tpTime", ## args) +#define tpCertInfoDbg(args...) secdebug("tpCert", ## args) + +static const TPClItemCalls tpCertClCalls = +{ + CSSM_CL_CertGetFirstCachedFieldValue, + CSSM_CL_CertAbortQuery, + CSSM_CL_CertCache, + CSSM_CL_CertAbortCache, + CSSM_CL_CertVerify, + &CSSMOID_X509V1ValidityNotBefore, + &CSSMOID_X509V1ValidityNotAfter, + CSSMERR_TP_INVALID_CERT_POINTER, + CSSMERR_TP_CERT_EXPIRED, + CSSMERR_TP_CERT_NOT_VALID_YET +}; + +TPClItemInfo::TPClItemInfo( + CSSM_CL_HANDLE clHand, + CSSM_CSP_HANDLE cspHand, + const TPClItemCalls &clCalls, + const CSSM_DATA *itemData, + TPItemCopy copyItemData, + const char *verifyTime) // may be NULL + : + mClHand(clHand), + mCspHand(cspHand), + mClCalls(clCalls), + mWeOwnTheData(false), + mCacheHand(0), + mIssuerName(NULL), + mItemData(NULL), + mSigAlg(CSSM_ALGID_NONE), + mNotBefore(NULL), + mNotAfter(NULL), + mIsExpired(false), + mIsNotValidYet(false), + mIndex(0) +{ + try { + CSSM_RETURN crtn = cacheItem(itemData, copyItemData); + if(crtn) { + CssmError::throwMe(crtn); + } + + /* + * Fetch standard fields... + * Issue name assumes same OID for Certs and CRLs! + */ + crtn = fetchField(&CSSMOID_X509V1IssuerName, &mIssuerName); + if(crtn) { + CssmError::throwMe(crtn); + } + + /* + * Signing algorithm, infer from TBS algId + * Note this assumes that the OID for fetching this field is the + * same for CRLs and Certs. + */ + CSSM_DATA_PTR algField; + crtn = fetchField(&CSSMOID_X509V1SignatureAlgorithmTBS, &algField); + if(crtn) { + releaseResources(); + CssmError::throwMe(crtn); + } + if(algField->Length != sizeof(CSSM_X509_ALGORITHM_IDENTIFIER)) { + tpErrorLog("TPClItemInfo: bad CSSM_X509_ALGORITHM_IDENTIFIER\n"); + CssmError::throwMe(CSSMERR_TP_INTERNAL_ERROR); + } + CSSM_X509_ALGORITHM_IDENTIFIER *algId = + (CSSM_X509_ALGORITHM_IDENTIFIER *)algField->Data; + bool algFound = cssmOidToAlg(&algId->algorithm, &mSigAlg); + if(!algFound) { + tpErrorLog("TPClItemInfo: unknown signature algorithm\n"); + CssmError::throwMe(CSSMERR_TP_UNKNOWN_FORMAT); + } + if(mSigAlg == CSSM_ALGID_ECDSA_SPECIFIED) { + /* Further processing needed to get digest algorithm */ + if(decodeECDSA_SigAlgParams(&algId->parameters, &mSigAlg)) { + tpErrorLog("TPClItemInfo: incomplete/unknown ECDSA signature algorithm\n"); + CssmError::throwMe(CSSMERR_TP_UNKNOWN_FORMAT); + } + } + freeField(&CSSMOID_X509V1SignatureAlgorithmTBS, algField); + + fetchNotBeforeAfter(); + calculateCurrent(verifyTime); + } + catch(...) { + releaseResources(); + throw; + } +} + +TPClItemInfo::~TPClItemInfo() +{ + tpCertInfoDbg("TPClItemInfo destruct this %p", this); + releaseResources(); +} + +void TPClItemInfo::releaseResources() +{ + if(mWeOwnTheData && (mItemData != NULL)) { + tpFreeCssmData(Allocator::standard(), mItemData, CSSM_TRUE); + mWeOwnTheData = false; + mItemData = NULL; + } + if(mIssuerName) { + freeField(&CSSMOID_X509V1IssuerName, mIssuerName); + mIssuerName = NULL; + } + if(mCacheHand != 0) { + mClCalls.abortCache(mClHand, mCacheHand); + mCacheHand = 0; + } + if(mNotBefore) { + CFRelease(mNotBefore); + mNotBefore = NULL; + } + if(mNotAfter) { + CFRelease(mNotAfter); + mNotAfter = NULL; + } +} + +/* fetch arbitrary field from cached cert */ +CSSM_RETURN TPClItemInfo::fetchField( + const CSSM_OID *fieldOid, + CSSM_DATA_PTR *fieldData) // mallocd by CL and RETURNED +{ + CSSM_RETURN crtn; + + uint32 NumberOfFields = 0; + CSSM_HANDLE resultHand = 0; + *fieldData = NULL; + + assert(mClCalls.getField != NULL); + assert(mCacheHand != 0); + crtn = mClCalls.getField( + mClHand, + mCacheHand, + fieldOid, + &resultHand, + &NumberOfFields, + fieldData); + if(crtn) { + return crtn; + } + if(NumberOfFields != 1) { + tpErrorLog("TPCertInfo::fetchField: numFields %d, expected 1\n", + (int)NumberOfFields); + } + mClCalls.abortQuery(mClHand, resultHand); + return CSSM_OK; +} + +/* free arbitrary field obtained from fetchField() */ +CSSM_RETURN TPClItemInfo::freeField( + const CSSM_OID *fieldOid, + CSSM_DATA_PTR fieldData) +{ + return CSSM_CL_FreeFieldValue(mClHand, fieldOid, fieldData); + +} + +/* + * Verify with an issuer cert - works on certs and CRLs. + * Issuer/subject name match already performed by caller. + * Optional paramCert is used to provide parameters when issuer + * has a partial public key. + */ +CSSM_RETURN TPClItemInfo::verifyWithIssuer( + TPCertInfo *issuerCert, + TPCertInfo *paramCert /* = NULL */) const +{ + CSSM_RETURN crtn; + + assert(mClHand != 0); + assert(issuerCert->isIssuerOf(*this)); + assert(mCspHand != 0); + + /* + * Special case: detect partial public key right now; don't even + * bother trying the cert verify in that case. + */ + if(issuerCert->hasPartialKey() && (paramCert == NULL)) { + /* caller deals with this later */ + tpVfyDebug("verifyWithIssuer PUBLIC_KEY_INCOMPLETE"); + return CSSMERR_CSP_APPLE_PUBLIC_KEY_INCOMPLETE; + } + + CSSM_CC_HANDLE ccHand; + crtn = CSSM_CSP_CreateSignatureContext(mCspHand, + mSigAlg, + NULL, // Access Creds + issuerCert->pubKey(), + &ccHand); + if(crtn != CSSM_OK) { + tpErrorLog("verifyWithIssuer: CreateSignatureContext error\n"); + CssmError::throwMe(crtn); + } + if(paramCert != NULL) { + assert(issuerCert->hasPartialKey()); + + /* add in parameter-bearing key */ + CSSM_CONTEXT_ATTRIBUTE newAttr; + + newAttr.AttributeType = CSSM_ATTRIBUTE_PARAM_KEY; + newAttr.AttributeLength = sizeof(CSSM_KEY); + newAttr.Attribute.Key = paramCert->pubKey(); + crtn = CSSM_UpdateContextAttributes(ccHand, 1, &newAttr); + if(crtn) { + tpErrorLog("verifyWithIssuer: CSSM_UpdateContextAttributes error\n"); + CssmError::throwMe(crtn); + } + } + crtn = mClCalls.itemVerify(mClHand, + ccHand, + mItemData, + NULL, // issuer cert + NULL, // VerifyScope + 0); // ScopeSize + + switch(crtn) { + case CSSM_OK: // success + case CSSMERR_CSP_APPLE_PUBLIC_KEY_INCOMPLETE: // caller handles + tpVfyDebug("verifyWithIssuer GOOD"); + break; + default: + /* all others appear here as general cert verify error */ + crtn = CSSMERR_TP_VERIFICATION_FAILURE; + tpVfyDebug("verifyWithIssuer BAD"); + break; + } + CSSM_DeleteContext(ccHand); + return crtn; +} + +CSSM_RETURN TPClItemInfo::cacheItem( + const CSSM_DATA *itemData, + TPItemCopy copyItemData) +{ + switch(copyItemData) { + case TIC_NoCopy: + mItemData = const_cast(itemData); + break; + case TIC_CopyData: + mItemData = tpMallocCopyCssmData(Allocator::standard(), itemData); + mWeOwnTheData = true; + break; + default: + assert(0); + CssmError::throwMe(CSSMERR_TP_INTERNAL_ERROR); + } + + /* cache the cert/CRL in the CL */ + return mClCalls.cacheItem(mClHand, mItemData, &mCacheHand); +} + +/* + * Calculate not before/after times as struct tm. Only throws on + * gross error (CSSMERR_TP_INVALID_CERT_POINTER, etc.). + * + * Only differences between Cert and CRL flavors of this are the + * OIDs used to fetch the appropriate before/after times, both of + * which are expressed as CSSM_X509_TIME structs for both Certs + * and CRLS. + */ +void TPClItemInfo::fetchNotBeforeAfter() +{ + CSSM_DATA_PTR notBeforeField = NULL; + CSSM_DATA_PTR notAfterField = NULL; + CSSM_RETURN crtn = CSSM_OK; + CSSM_X509_TIME *xTime; + + assert(cacheHand() != CSSM_INVALID_HANDLE); + crtn = fetchField(mClCalls.notBeforeOid, ¬BeforeField); + if(crtn) { + tpErrorLog("fetchNotBeforeAfter: GetField error\n"); + CssmError::throwMe(mClCalls.invalidItemRtn); + } + + /* subsequent errors to errOut */ + xTime = (CSSM_X509_TIME *)notBeforeField->Data; + if(timeStringToCfDate((char *)xTime->time.Data, xTime->time.Length, &mNotBefore)) { + tpErrorLog("fetchNotBeforeAfter: malformed notBefore time\n"); + crtn = mClCalls.invalidItemRtn; + goto errOut; + } + + crtn = fetchField(mClCalls.notAfterOid, ¬AfterField); + if(crtn) { + /* + * Tolerate a missing NextUpdate in CRL only + */ + if(mClCalls.notAfterOid == &CSSMOID_X509V1ValidityNotAfter) { + tpErrorLog("fetchNotBeforeAfter: GetField error\n"); + crtn = mClCalls.invalidItemRtn; + goto errOut; + } + else { + /* + * Fake NextUpdate to be "at the end of time" + */ + timeStringToCfDate(CSSM_APPLE_CRL_END_OF_TIME, + strlen(CSSM_APPLE_CRL_END_OF_TIME), + &mNotAfter); + } + } + else { + xTime = (CSSM_X509_TIME *)notAfterField->Data; + if(timeStringToCfDate((char *)xTime->time.Data, xTime->time.Length, &mNotAfter)) { + tpErrorLog("fetchNotBeforeAfter: malformed notAfter time\n"); + crtn = mClCalls.invalidItemRtn; + goto errOut; + } + } + crtn = CSSM_OK; +errOut: + if(notAfterField) { + freeField(mClCalls.notAfterOid, notAfterField); + } + if(notBeforeField) { + freeField(mClCalls.notBeforeOid, notBeforeField); + } + if(crtn != CSSM_OK) { + CssmError::throwMe(crtn); + } +} + +/* + * Verify validity (not before/after) by comparing the reference + * time (verifyString if present, or "now" if NULL) to the + * not before/after fields fetched from the item at construction. + * + * Called implicitly at construction; can be called again any time + * to re-establish validity (e.g. after fetching an item from a cache). + * + * We use some stdlib time calls over in tpTime.c; the stdlib function + * gmtime() is not thread-safe, so we do the protection here. Note that + * this makes *our* calls to gmtime() thread-safe, but if the app has + * other threads which are also calling gmtime, we're out of luck. + */ +ModuleNexus tpTimeLock; + +CSSM_RETURN TPClItemInfo::calculateCurrent( + const char *verifyString) +{ + CFDateRef refTime = NULL; + + if(verifyString != NULL) { + /* caller specifies verification time base */ + if(timeStringToCfDate(verifyString, strlen(verifyString), &refTime)) { + tpErrorLog("calculateCurrent: timeStringToCfDate error\n"); + return CSSMERR_TP_INVALID_TIMESTRING; + } + } + else { + /* time base = right now */ + refTime = CFDateCreate(NULL, CFAbsoluteTimeGetCurrent()); + } + if(compareTimes(refTime, mNotBefore) < 0) { + mIsNotValidYet = true; + tpTimeDbg("\nTP_CERT_NOT_VALID_YET: now %g notBefore %g", + CFDateGetAbsoluteTime(refTime), CFDateGetAbsoluteTime(mNotBefore)); + CFRelease(refTime); + return mClCalls.notValidYetRtn; + } + else { + mIsNotValidYet = false; + } + + if(compareTimes(refTime, mNotAfter) > 0) { + mIsExpired = true; + tpTimeDbg("\nTP_CERT_EXPIRED: now %g notBefore %g", + CFDateGetAbsoluteTime(refTime), CFDateGetAbsoluteTime(mNotBefore)); + CFRelease(refTime); + return mClCalls.expiredRtn; + } + else { + mIsExpired = false; + CFRelease(refTime); + return CSSM_OK; + } +} + + +/* + * No default constructor - this is the only way. + * This caches the cert and fetches subjectName, issuerName, and + * mPublicKey to ensure the incoming certData is well-constructed. + */ +TPCertInfo::TPCertInfo( + CSSM_CL_HANDLE clHand, + CSSM_CSP_HANDLE cspHand, + const CSSM_DATA *certData, + TPItemCopy copyCertData, // true: we copy, we free + // false - caller owns + const char *verifyTime) // may be NULL + : + TPClItemInfo(clHand, cspHand, tpCertClCalls, certData, + copyCertData, verifyTime), + mSubjectName(NULL), + mPublicKeyData(NULL), + mPublicKey(NULL), + mIsAnchor(false), + mIsFromInputCerts(false), + mIsFromNet(false), + mNumStatusCodes(0), + mStatusCodes(NULL), + mUniqueRecord(NULL), + mUsed(false), + mIsLeaf(false), + mIsRoot(TRS_Unknown), + mRevCheckGood(false), + mRevCheckComplete(false), + mTrustSettingsEvaluated(false), + mTrustSettingsDomain(kSecTrustSettingsDomainSystem), + mTrustSettingsResult(kSecTrustSettingsResultInvalid), + mTrustSettingsFoundAnyEntry(false), + mTrustSettingsFoundMatchingEntry(false), + mAllowedErrs(NULL), + mNumAllowedErrs(0), + mIgnoredError(false), + mTrustSettingsKeyUsage(0), + mCertHashStr(NULL) +{ + CSSM_RETURN crtn; + + tpCertInfoDbg("TPCertInfo construct this %p", this); + mDlDbHandle.DLHandle = 0; + mDlDbHandle.DBHandle = 0; + + /* fetch subject name */ + crtn = fetchField(&CSSMOID_X509V1SubjectName, &mSubjectName); + if(crtn) { + /* bad cert */ + releaseResources(); + CssmError::throwMe(crtn); + } + + /* this cert's public key */ + crtn = fetchField(&CSSMOID_CSSMKeyStruct, &mPublicKeyData); + if(crtn || (mPublicKeyData->Length != sizeof(CSSM_KEY))) { + /* bad cert */ + releaseResources(); + CssmError::throwMe(crtn); + } + mPublicKey = (CSSM_KEY_PTR)mPublicKeyData->Data; + + /* calculate other commonly used fields */ + if(tpCompareCssmData(mSubjectName, issuerName())) { + /* + * Per Radar 3374978, perform complete signature verification + * lazily - just check subject/issuer match here. + */ + tpAnchorDebug("TPCertInfo potential anchor"); + mIsRoot = TRS_NamesMatch; + } + else { + mIsRoot = TRS_NotRoot; + } +} + +/* frees mSubjectName, mIssuerName, mCacheHand via mClHand */ +TPCertInfo::~TPCertInfo() +{ + tpCertInfoDbg("TPCertInfo destruct this %p", this); + releaseResources(); +} + +void TPCertInfo::releaseResources() +{ + if(mSubjectName) { + freeField(&CSSMOID_X509V1SubjectName, mSubjectName); + mSubjectName = NULL; + } + if(mPublicKeyData) { + freeField(&CSSMOID_CSSMKeyStruct, mPublicKeyData); + mPublicKey = NULL; + mPublicKeyData = NULL; + } + if(mStatusCodes) { + free(mStatusCodes); + mStatusCodes = NULL; + } + if(mAllowedErrs) { + free(mAllowedErrs); + } + if(mCertHashStr) { + CFRelease(mCertHashStr); + } + TPClItemInfo::releaseResources(); +} + +const CSSM_DATA *TPCertInfo::subjectName() +{ + assert(mSubjectName != NULL); + return mSubjectName; +} + +/* + * Perform semi-lazy evaluation of "rootness". Subject and issuer names + * compared at constructor. + * If avoidVerify is true, we won't do the signature verify: caller + * just wants to know if the subject and issuer names match. + */ +bool TPCertInfo::isSelfSigned(bool avoidVerify) +{ + switch(mIsRoot) { + case TRS_NotRoot: // known not to be root + return false; + case TRS_IsRoot: + return true; + case TRS_NamesMatch: + if(avoidVerify) { + return true; + } + /* else drop through and verify */ + case TRS_Unknown: // actually shouldn't happen, but to be safe... + default: + /* do the signature verify */ + if(verifyWithIssuer(this) == CSSM_OK) { + tpAnchorDebug("isSelfSigned anchor verified"); + mIsRoot = TRS_IsRoot; + return true; + } + else { + tpAnchorDebug("isSelfSigned anchor vfy FAIL"); + mIsRoot = TRS_NotRoot; + return false; + } + } +} + +/* + * Am I the issuer of the specified subject item? Returns true if so. + * Works for subject certs as well as CRLs. + */ +bool TPCertInfo::isIssuerOf( + const TPClItemInfo &subject) +{ + assert(mSubjectName != NULL); + assert(subject.issuerName() != NULL); + if(tpCompareCssmData(mSubjectName, subject.issuerName())) { + return true; + } + else { + return false; + } +} + +bool TPCertInfo::addStatusCode(CSSM_RETURN code) +{ + mNumStatusCodes++; + mStatusCodes = (CSSM_RETURN *)realloc(mStatusCodes, + mNumStatusCodes * sizeof(CSSM_RETURN)); + mStatusCodes[mNumStatusCodes - 1] = code; + return isStatusFatal(code); +} + +bool TPCertInfo::hasStatusCode(CSSM_RETURN code) +{ + for(unsigned dex=0; dexKeyHeader.KeyAttr & CSSM_KEYATTR_PARTIAL) { + return true; + } + else { + return false; + } +} + +/* + * + */ +bool TPCertInfo::shouldReject() +{ + static unsigned char _UTN_UF_H_ISSUER_BYTES[154] = { + 0x30, 0x81, 0x97, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x02, 0x55, 0x54, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, + 0x04, 0x07, 0x13, 0x0e, 0x53, 0x41, 0x4c, 0x54, 0x20, 0x4c, 0x41, 0x4b, + 0x45, 0x20, 0x43, 0x49, 0x54, 0x59, 0x31, 0x1e, 0x30, 0x1c, 0x06, 0x03, + 0x55, 0x04, 0x0a, 0x13, 0x15, 0x54, 0x48, 0x45, 0x20, 0x55, 0x53, 0x45, + 0x52, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x4e, 0x45, 0x54, 0x57, 0x4f, + 0x52, 0x4b, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, + 0x18, 0x48, 0x54, 0x54, 0x50, 0x3a, 0x2f, 0x2f, 0x57, 0x57, 0x57, 0x2e, + 0x55, 0x53, 0x45, 0x52, 0x54, 0x52, 0x55, 0x53, 0x54, 0x2e, 0x43, 0x4f, + 0x4d, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x16, + 0x55, 0x54, 0x4e, 0x2d, 0x55, 0x53, 0x45, 0x52, 0x46, 0x49, 0x52, 0x53, + 0x54, 0x2d, 0x48, 0x41, 0x52, 0x44, 0x57, 0x41, 0x52, 0x45 + }; + CSSM_DATA _UTN_UF_H_ISSUER = { sizeof(_UTN_UF_H_ISSUER_BYTES), _UTN_UF_H_ISSUER_BYTES }; + + static CSSM_DATA _UTN_UF_H_SERIALS[] = { + { 17, (uint8*)"\x00\x92\x39\xd5\x34\x8f\x40\xd1\x69\x5a\x74\x54\x70\xe1\xf2\x3f\x43" }, // amo + { 17, (uint8*)"\x00\xd8\xf3\x5f\x4e\xb7\x87\x2b\x2d\xab\x06\x92\xe3\x15\x38\x2f\xb0" }, // gt + { 17, (uint8*)"\x00\xb0\xb7\x13\x3e\xd0\x96\xf9\xb5\x6f\xae\x91\xc8\x74\xbd\x3a\xc0" }, // llc + { 17, (uint8*)"\x00\xe9\x02\x8b\x95\x78\xe4\x15\xdc\x1a\x71\x0a\x2b\x88\x15\x44\x47" }, // lsc + { 17, (uint8*)"\x00\xd7\x55\x8f\xda\xf5\xf1\x10\x5b\xb2\x13\x28\x2b\x70\x77\x29\xa3" }, // lyc + { 16, (uint8*)"\x39\x2a\x43\x4f\x0e\x07\xdf\x1f\x8a\xa3\x05\xde\x34\xe0\xc2\x29" }, // lyc1 + { 16, (uint8*)"\x3e\x75\xce\xd4\x6b\x69\x30\x21\x21\x88\x30\xae\x86\xa8\x2a\x71" }, // lyc2 + { 16, (uint8*)"\x04\x7e\xcb\xe9\xfc\xa5\x5f\x7b\xd0\x9e\xae\x36\xe1\x0c\xae\x1e" }, // mgc + { 17, (uint8*)"\x00\xf5\xc8\x6a\xf3\x61\x62\xf1\x3a\x64\xf5\x4f\x6d\xc9\x58\x7c\x06" }, // wgc + { 0, NULL } + }; + + const CSSM_DATA *issuer=issuerName(); + if(!issuer || !(tpCompareCssmData(issuer, &_UTN_UF_H_ISSUER))) + return false; + + CSSM_DATA *serialNumber=NULL; + CSSM_RETURN crtn = fetchField(&CSSMOID_X509V1SerialNumber, &serialNumber); + if(crtn || !serialNumber) + return false; + + CSSM_DATA *p=_UTN_UF_H_SERIALS; + bool matched=false; + while(p->Length) { + if(tpCompareCssmData(serialNumber, p)) { + matched=true; + addStatusCode(CSSMERR_TP_CERT_REVOKED); + break; + } + ++p; + } + freeField(&CSSMOID_X509V1SerialNumber, serialNumber); + return matched; +} + +/* + * Evaluate trust settings; returns true in *foundMatchingEntry if positive + * match found - i.e., cert chain construction is done. + */ +OSStatus TPCertInfo::evaluateTrustSettings( + const CSSM_OID &policyOid, + const char *policyString, // optional + uint32 policyStringLen, + SecTrustSettingsKeyUsage keyUse, // required + bool *foundMatchingEntry, // RETURNED + bool *foundAnyEntry) // RETURNED +{ + /* + * We might have to force a re-evaluation if the requested key usage + * is not a subset of what we already checked for (and cached). + */ + if(mTrustSettingsEvaluated) { + bool doFlush = false; + if(mTrustSettingsKeyUsage != kSecTrustSettingsKeyUseAny) { + if(keyUse == kSecTrustSettingsKeyUseAny) { + /* now want "any", checked something else before */ + doFlush = true; + } + else if((keyUse & mTrustSettingsKeyUsage) != keyUse) { + /* want bits that we didn't ask for before */ + doFlush = true; + } + } + if(doFlush) { + tpTrustSettingsDbg("evaluateTrustSettings: flushing cached trust for " + "%p due to keyUse 0x%x", this, (int)keyUse); + mTrustSettingsEvaluated = false; + mTrustSettingsFoundAnyEntry = false; + mTrustSettingsResult = kSecTrustSettingsResultInvalid; + mTrustSettingsFoundMatchingEntry = false; + if(mAllowedErrs != NULL) { + free(mAllowedErrs); + } + mNumAllowedErrs = 0; + } + /* else we can safely use the cached values */ + } + if(!mTrustSettingsEvaluated) { + + if(mCertHashStr == NULL) { + const CSSM_DATA *certData = itemData(); + mCertHashStr = SecTrustSettingsCertHashStrFromData(certData->Data, + certData->Length); + } + + OSStatus ortn = SecTrustSettingsEvaluateCert(mCertHashStr, + &policyOid, + policyString, + policyStringLen, + keyUse, + /* + * This is the purpose of the avoidVerify option, right here. + * If this is a root cert and it has trust settings, we avoid + * the signature verify. If it turns out there are no trust + * settings and this is a root, we'll verify the signature + * elsewhere (e.g. post_trust_setting: in buildCertGroup()). + */ + isSelfSigned(true), + &mTrustSettingsDomain, + &mAllowedErrs, + &mNumAllowedErrs, + &mTrustSettingsResult, + &mTrustSettingsFoundMatchingEntry, + &mTrustSettingsFoundAnyEntry); + if(ortn) { + tpTrustSettingsDbg("evaluateTrustSettings: SecTrustSettingsEvaluateCert error!"); + return ortn; + } + mTrustSettingsEvaluated = true; + mTrustSettingsKeyUsage = keyUse; + #ifndef NDEBUG + if(mTrustSettingsFoundMatchingEntry) { + tpTrustSettingsDbg("evaluateTrustSettings: found for %p result %d", + this, (int)mTrustSettingsResult); + } + #endif + /* one more thing... */ + if(shouldReject()) { + return CSSMERR_TP_INVALID_CERTIFICATE; + } + } + *foundMatchingEntry = mTrustSettingsFoundMatchingEntry; + *foundAnyEntry = mTrustSettingsFoundAnyEntry; + + return noErr; +} + +/* true means "verification terminated due to user trust setting" */ +bool TPCertInfo::trustSettingsFound() +{ + switch(mTrustSettingsResult) { + case kSecTrustSettingsResultUnspecified: /* entry but not definitive */ + case kSecTrustSettingsResultInvalid: /* no entry */ + return false; + default: + return true; + } +} + +/* + * Determine if this has an empty SubjectName field. Returns true if so. + */ +bool TPCertInfo::hasEmptySubjectName() +{ + /* + * A "pure" empty subject is two bytes (0x30 00) - constructed sequence, + * short form length, length 0. We'll be robust and tolerate a missing + * field, as well as a possible BER-encoded subject with some extra cruft. + */ + if((mSubjectName == NULL) || (mSubjectName->Length <= 4)) { + return true; + } + else { + return false; + } +} + +/* + * Free mUniqueRecord if it exists. + * This is *not* done in our destructor because this record sometimes + * has to persist in the form of a CSSM evidence chain. + */ +void TPCertInfo::freeUniqueRecord() +{ + if(mUniqueRecord == NULL) { + return; + } + tpDbDebug("freeUniqueRecord: freeing cert record %p", mUniqueRecord); + CSSM_DL_FreeUniqueRecord(mDlDbHandle, mUniqueRecord); +} + +/*** + *** TPCertGroup class + ***/ + +/* build empty group */ +TPCertGroup::TPCertGroup( + Allocator &alloc, + TPGroupOwner whoOwns) : + mAlloc(alloc), + mCertInfo(NULL), + mNumCerts(0), + mSizeofCertInfo(0), + mWhoOwns(whoOwns) +{ + tpCertInfoDbg("TPCertGroup simple construct this %p", this); + /* nothing for now */ +} + +/* + * Construct from unordered, untrusted CSSM_CERTGROUP. Resulting + * TPCertInfos are more or less in the same order as the incoming + * certs, though incoming certs are discarded if they don't parse. + * No verification of any sort is performed. + */ +TPCertGroup::TPCertGroup( + const CSSM_CERTGROUP &CertGroupFrag, + CSSM_CL_HANDLE clHand, + CSSM_CSP_HANDLE cspHand, + Allocator &alloc, + const char *verifyTime, // may be NULL + bool firstCertMustBeValid, + TPGroupOwner whoOwns) : + mAlloc(alloc), + mCertInfo(NULL), + mNumCerts(0), + mSizeofCertInfo(0), + mWhoOwns(whoOwns) +{ + tpCertInfoDbg("TPCertGroup hard construct this %p", this); + + /* verify input args */ + if(cspHand == CSSM_INVALID_HANDLE) { + CssmError::throwMe(CSSMERR_TP_INVALID_CSP_HANDLE); + } + if(clHand == CSSM_INVALID_HANDLE) { + CssmError::throwMe(CSSMERR_TP_INVALID_CL_HANDLE); + } + if(firstCertMustBeValid) { + if( (CertGroupFrag.NumCerts == 0) || + (CertGroupFrag.GroupList.CertList[0].Data == NULL) || + (CertGroupFrag.GroupList.CertList[0].Length == 0)) { + CssmError::throwMe(CSSMERR_TP_INVALID_CERTIFICATE); + } + } + if(CertGroupFrag.CertGroupType != CSSM_CERTGROUP_DATA) { + CssmError::throwMe(CSSMERR_TP_INVALID_CERTGROUP); + } + switch(CertGroupFrag.CertType) { + case CSSM_CERT_X_509v1: + case CSSM_CERT_X_509v2: + case CSSM_CERT_X_509v3: + break; + default: + CssmError::throwMe(CSSMERR_TP_UNKNOWN_FORMAT); + } + switch(CertGroupFrag.CertEncoding) { + case CSSM_CERT_ENCODING_BER: + case CSSM_CERT_ENCODING_DER: + break; + default: + CssmError::throwMe(CSSMERR_TP_UNKNOWN_FORMAT); + } + + /* + * Add remaining input certs to mCertInfo. + */ + TPCertInfo *certInfo = NULL; + for(unsigned certDex=0; certDexindex(certDex); + appendCert(certInfo); + } +} + +/* + * Deletes contents of mCertInfo[] if appropriate. + */ +TPCertGroup::~TPCertGroup() +{ + if(mWhoOwns == TGO_Group) { + unsigned i; + for(i=0; i here, but + * gdb is so lame that it doesn't even let one examine the contents + * of an array<> (or just about anything else in the STL). I prefer + * debuggability over saving a few lines of trivial code. + */ +void TPCertGroup::appendCert( + TPCertInfo *certInfo) // appends to end of mCertInfo +{ + if(mNumCerts == mSizeofCertInfo) { + if(mSizeofCertInfo == 0) { + /* appending to empty array */ + mSizeofCertInfo = 1; + } + else { + mSizeofCertInfo *= 2; + } + mCertInfo = (TPCertInfo **)mAlloc.realloc(mCertInfo, + mSizeofCertInfo * sizeof(TPCertInfo *)); + } + mCertInfo[mNumCerts++] = certInfo; +} + +TPCertInfo *TPCertGroup::certAtIndex( + unsigned index) +{ + if(index > (mNumCerts - 1)) { + CssmError::throwMe(CSSMERR_TP_INTERNAL_ERROR); + } + return mCertInfo[index]; +} + +TPCertInfo *TPCertGroup::removeCertAtIndex( + unsigned index) // doesn't delete the cert, just + // removes it from out list +{ + if(index > (mNumCerts - 1)) { + CssmError::throwMe(CSSMERR_TP_INTERNAL_ERROR); + } + TPCertInfo *rtn = mCertInfo[index]; + + /* removed requested element and compact remaining array */ + unsigned i; + for(i=index; i<(mNumCerts - 1); i++) { + mCertInfo[i] = mCertInfo[i+1]; + } + mNumCerts--; + return rtn; +} + +TPCertInfo *TPCertGroup::firstCert() +{ + if(mNumCerts == 0) { + /* the caller really should not do this... */ + CssmError::throwMe(CSSMERR_TP_INTERNAL_ERROR); + } + else { + return mCertInfo[0]; + } +} + +TPCertInfo *TPCertGroup::lastCert() +{ + if(mNumCerts == 0) { + return NULL; + } + else { + return mCertInfo[mNumCerts - 1]; + } +} + +/* build a CSSM_CERTGROUP corresponding with our mCertInfo */ +CSSM_CERTGROUP_PTR TPCertGroup::buildCssmCertGroup() +{ + CSSM_CERTGROUP_PTR cgrp = + (CSSM_CERTGROUP_PTR)mAlloc.malloc(sizeof(CSSM_CERTGROUP)); + cgrp->NumCerts = mNumCerts; + cgrp->CertGroupType = CSSM_CERTGROUP_DATA; + cgrp->CertType = CSSM_CERT_X_509v3; + cgrp->CertEncoding = CSSM_CERT_ENCODING_DER; + if(mNumCerts == 0) { + /* legal */ + cgrp->GroupList.CertList = NULL; + return cgrp; + } + cgrp->GroupList.CertList = (CSSM_DATA_PTR)mAlloc.calloc(mNumCerts, + sizeof(CSSM_DATA)); + for(unsigned i=0; iitemData(), + &cgrp->GroupList.CertList[i]); + } + return cgrp; +} + +/* build a CSSM_TP_APPLE_EVIDENCE_INFO array */ +CSSM_TP_APPLE_EVIDENCE_INFO *TPCertGroup::buildCssmEvidenceInfo() +{ + CSSM_TP_APPLE_EVIDENCE_INFO *infoArray; + + infoArray = (CSSM_TP_APPLE_EVIDENCE_INFO *)mAlloc.calloc(mNumCerts, + sizeof(CSSM_TP_APPLE_EVIDENCE_INFO)); + for(unsigned i=0; iisExpired()) { + evInfo->StatusBits |= CSSM_CERT_STATUS_EXPIRED; + } + if(certInfo->isNotValidYet()) { + evInfo->StatusBits |= CSSM_CERT_STATUS_NOT_VALID_YET; + } + if(certInfo->isAnchor()) { + tpAnchorDebug("buildCssmEvidenceInfo: flagging IS_IN_ANCHORS"); + evInfo->StatusBits |= CSSM_CERT_STATUS_IS_IN_ANCHORS; + } + if(certInfo->dlDbHandle().DLHandle == 0) { + if(certInfo->isFromNet()) { + evInfo->StatusBits |= CSSM_CERT_STATUS_IS_FROM_NET; + } + else if(certInfo->isFromInputCerts()) { + evInfo->StatusBits |= CSSM_CERT_STATUS_IS_IN_INPUT_CERTS; + } + } + /* If trust settings apply to a root, skip verifying the signature */ + bool avoidVerify = false; + switch(certInfo->trustSettingsResult()) { + case kSecTrustSettingsResultTrustRoot: + case kSecTrustSettingsResultTrustAsRoot: + /* these two can be disambiguated by IS_ROOT */ + evInfo->StatusBits |= CSSM_CERT_STATUS_TRUST_SETTINGS_TRUST; + avoidVerify = true; + break; + case kSecTrustSettingsResultDeny: + evInfo->StatusBits |= CSSM_CERT_STATUS_TRUST_SETTINGS_DENY; + avoidVerify = true; + break; + case kSecTrustSettingsResultUnspecified: + case kSecTrustSettingsResultInvalid: + default: + break; + } + if(certInfo->isSelfSigned(avoidVerify)) { + evInfo->StatusBits |= CSSM_CERT_STATUS_IS_ROOT; + } + if(certInfo->ignoredError()) { + evInfo->StatusBits |= CSSM_CERT_STATUS_TRUST_SETTINGS_IGNORED_ERROR; + } + unsigned numCodes = certInfo->numStatusCodes(); + if(numCodes) { + evInfo->NumStatusCodes = numCodes; + evInfo->StatusCodes = (CSSM_RETURN *)mAlloc.calloc(numCodes, + sizeof(CSSM_RETURN)); + for(unsigned j=0; jStatusCodes[j] = (certInfo->statusCodes())[j]; + } + } + if(evInfo->StatusBits & (CSSM_CERT_STATUS_TRUST_SETTINGS_TRUST | + CSSM_CERT_STATUS_TRUST_SETTINGS_DENY | + CSSM_CERT_STATUS_TRUST_SETTINGS_IGNORED_ERROR)) { + /* Something noteworthy happened involving TrustSettings */ + uint32 whichDomain = 0; + switch(certInfo->trustSettingsDomain()) { + case kSecTrustSettingsDomainUser: + whichDomain = CSSM_CERT_STATUS_TRUST_SETTINGS_FOUND_USER; + break; + case kSecTrustSettingsDomainAdmin: + whichDomain = CSSM_CERT_STATUS_TRUST_SETTINGS_FOUND_ADMIN; + break; + case kSecTrustSettingsDomainSystem: + whichDomain = CSSM_CERT_STATUS_TRUST_SETTINGS_FOUND_SYSTEM; + break; + } + evInfo->StatusBits |= whichDomain; + } + evInfo->Index = certInfo->index(); + evInfo->DlDbHandle = certInfo->dlDbHandle(); + evInfo->UniqueRecord = certInfo->uniqueRecord(); + } + return infoArray; +} + +/* Given a status for basic construction of a cert group and a status + * of (optional) policy verification, plus the implicit notBefore/notAfter + * status in the certs, calculate a global return code. This just + * encapsulates a policy for CertGroupConstruct and CertGroupVerify. + */ +CSSM_RETURN TPCertGroup::getReturnCode( + CSSM_RETURN constructStatus, + CSSM_RETURN policyStatus, + CSSM_APPLE_TP_ACTION_FLAGS actionFlags) +{ + if(constructStatus) { + /* CSSMERR_TP_NOT_TRUSTED, CSSMERR_TP_INVALID_ANCHOR_CERT, gross errors */ + return constructStatus; + } + + bool expired = false; + bool postdated = false; + bool allowExpiredRoot = (actionFlags & CSSM_TP_ACTION_ALLOW_EXPIRED_ROOT) ? + true : false; + bool allowExpired = (actionFlags & CSSM_TP_ACTION_ALLOW_EXPIRED) ? true : false; + bool allowPostdated = allowExpired; // flag overrides any temporal invalidity + bool requireRevPerCert = (actionFlags & CSSM_TP_ACTION_REQUIRE_REV_PER_CERT) ? + true : false; + + /* check for expired, not valid yet */ + for(unsigned i=0; iisExpired() && + !(allowExpiredRoot && ci->isSelfSigned(true)) && // allowed globally + ci->isStatusFatal(CSSMERR_TP_CERT_EXPIRED)) { // allowed for this cert + expired = true; + } + if(ci->isNotValidYet() && + ci->isStatusFatal(CSSMERR_TP_CERT_NOT_VALID_YET)) { + postdated = true; + } + } + if(expired && !allowExpired) { + return CSSMERR_TP_CERT_EXPIRED; + } + if(postdated && !allowPostdated) { + return CSSMERR_TP_CERT_NOT_VALID_YET; + } + + /* Check for missing revocation check */ + if(requireRevPerCert) { + for(unsigned i=0; iisSelfSigned(true)) { + /* revocation check meaningless for a root cert */ + tpDebug("getReturnCode: ignoring revocation for self-signed cert %d", i); + continue; + } + if(!ci->revokeCheckGood() && + ci->isStatusFatal(CSSMERR_APPLETP_INCOMPLETE_REVOCATION_CHECK)) { + tpDebug("getReturnCode: FATAL: revocation check incomplete for cert %d", i); + return CSSMERR_APPLETP_INCOMPLETE_REVOCATION_CHECK; + } + #ifndef NDEBUG + else { + tpDebug("getReturnCode: revocation check %s for cert %d", + (ci->revokeCheckGood()) ? "GOOD" : "OK", i); + } + #endif + } + } + return policyStatus; +} + +/* set all TPCertInfo.mUsed flags false */ +void TPCertGroup::setAllUnused() +{ + for(unsigned dex=0; dexused(false); + } +} + +/* + * See if the specified error status is allowed (return true) or + * fatal (return false) per each cert's mAllowedErrs[]. Returns + * true if any cert returns false for its isStatusFatal() call. + * The list of errors which can apply to cert-chain-wide allowedErrors + * is right here; if the incoming error is not in that list, we + * return false. If the incoming error code is CSSM_OK we return + * true as a convenience for our callers. + */ +bool TPCertGroup::isAllowedError( + CSSM_RETURN code) +{ + switch(code) { + case CSSM_OK: + return true; + case CSSMERR_TP_NOT_TRUSTED: + case CSSMERR_TP_INVALID_ANCHOR_CERT: + case CSSMERR_TP_VERIFY_ACTION_FAILED: + case CSSMERR_TP_INVALID_CERT_AUTHORITY: + case CSSMERR_APPLETP_CS_BAD_CERT_CHAIN_LENGTH: + case CSSMERR_APPLETP_RS_BAD_CERT_CHAIN_LENGTH: + /* continue processing these candidates */ + break; + default: + /* not a candidate for cert-chain-wide allowedErrors */ + return false; + } + + for(unsigned dex=0; dexisStatusFatal(code)) { + tpTrustSettingsDbg("TPCertGroup::isAllowedError: allowing for cert %u", + dex); + return true; + } + } + + /* every cert thought this was fatal; it is. */ + return false; +} + +/* + * Determine if we already have the specified cert in this group. + */ +bool TPCertGroup::isInGroup(TPCertInfo &certInfo) +{ + for(unsigned dex=0; dexitemData())) { + return true; + } + } + return false; +} + +/* + * Encode issuing certs in this group as a PEM-encoded data blob. + * Caller must free. + */ +void TPCertGroup::encodeIssuers(CSSM_DATA &issuers) +{ + /* FIXME: probably want to rewrite this using pemEncode() from libsecurity_cdsa_utils, + * since use of Sec* APIs from this layer violates the API reentrancy contract. + */ + issuers.Data = NULL; + issuers.Length = 0; + CFMutableArrayRef certArray = CFArrayCreateMutable(kCFAllocatorDefault, + 0, &kCFTypeArrayCallBacks); + if(!certArray) { + return; + } + for(unsigned certDex=0; certDex 1) { + continue; /* don't need the leaf */ + } + CSSM_DATA *cssmData = (CSSM_DATA*)((certInfo) ? certInfo->itemData() : NULL); + if(!cssmData || !cssmData->Data || !cssmData->Length) { + continue; + } + CFDataRef dataRef = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, + (const UInt8 *)cssmData->Data, cssmData->Length, + kCFAllocatorNull); + if(!dataRef) { + continue; + } + SecCertificateRef certRef = SecCertificateCreateWithData(kCFAllocatorDefault, + dataRef); + if(!certRef) { + CFRelease(dataRef); + continue; + } + CFArrayAppendValue(certArray, certRef); + CFRelease(certRef); + CFRelease(dataRef); + } + CFDataRef exportedPEMData = NULL; + OSStatus status = SecItemExport(certArray, + kSecFormatPEMSequence, + kSecItemPemArmour, + NULL, + &exportedPEMData); + CFRelease(certArray); + + if(!status) { + uint8 *dataPtr = (uint8*)CFDataGetBytePtr(exportedPEMData); + size_t dataLen = CFDataGetLength(exportedPEMData); + issuers.Data = (uint8*)malloc(dataLen); + memmove(issuers.Data, dataPtr, dataLen); + issuers.Length = dataLen; + CFRelease(exportedPEMData); + } +} + +/* + * Search unused incoming certs to find an issuer of specified cert or CRL. + * WARNING this assumes a valid "used" state for all certs in this group. + * If partialIssuerKey is true on return, caller must re-verify signature + * of subject later when sufficient info is available. + */ +TPCertInfo *TPCertGroup::findIssuerForCertOrCrl( + const TPClItemInfo &subject, + bool &partialIssuerKey) +{ + partialIssuerKey = false; + TPCertInfo *expiredIssuer = NULL; + + for(unsigned certDex=0; certDexused()) { + continue; + } + + /* subject/issuer names match? */ + if(certInfo->isIssuerOf(subject)) { + /* yep, do a sig verify */ + tpVfyDebug("findIssuerForCertOrCrl issuer/subj match checking sig"); + CSSM_RETURN crtn = subject.verifyWithIssuer(certInfo); + switch(crtn) { + case CSSMERR_CSP_APPLE_PUBLIC_KEY_INCOMPLETE: + /* issuer OK, check sig later */ + partialIssuerKey = true; + /* and fall thru */ + case CSSM_OK: + /* + * Temporal validity check: if we're not already holding an expired + * issuer, and this one's invalid, hold it and keep going. + */ + if((crtn == CSSM_OK) && (expiredIssuer == NULL)) { + if(certInfo->isExpired() || certInfo->isNotValidYet()) { + tpDebug("findIssuerForCertOrCrl: holding expired cert %p", + certInfo); + expiredIssuer = certInfo; + break; + } + } + /* YES */ + certInfo->used(true); + return certInfo; + default: + /* just skip this one and keep looking */ + tpVfyDebug("findIssuerForCertOrCrl issuer/subj match BAD SIG"); + break; + } + } /* names match */ + } + if(expiredIssuer != NULL) { + /* OK, we'll use this one */ + tpDbDebug("findIssuerForCertOrCrl: using expired cert %p", expiredIssuer); + expiredIssuer->used(true); + return expiredIssuer; + } + + /* not found */ + return NULL; +} + +/* + * Construct ordered, verified cert chain from a variety of inputs. + * Time validity does not affect the function return or any status, + * we always try to find a valid cert to replace an expired or + * not-yet-valid cert if we can. Final temporal validity of each + * cert must be checked by caller (it's stored in each TPCertInfo + * we add to ourself during construction). + * + * Only possible error returns are: + * CSSMERR_TP_CERTIFICATE_CANT_OPERATE : issuer cert was found with a partial + * public key, rendering full verification impossible. + * CSSMERR_TP_INVALID_CERT_AUTHORITY : issuer cert was found with a partial + * public key and which failed to perform subsequent signature + * verification. + * + * Other interesting status is returned via the verifiedToRoot and + * verifiedToAnchor flags. + * + * NOTE: is it the caller's responsibility to call setAllUnused() for both + * incoming cert groups (inCertGroup and gatheredCerts). We don't do that + * here because we may call ourself recursively. + */ +CSSM_RETURN TPCertGroup::buildCertGroup( + const TPClItemInfo &subjectItem, // Cert or CRL + TPCertGroup *inCertGroup, // optional + const CSSM_DL_DB_LIST *dbList, // optional + CSSM_CL_HANDLE clHand, + CSSM_CSP_HANDLE cspHand, + const char *verifyTime, // optional, for establishing + // validity of new TPCertInfos + /* trusted anchors, optional */ + /* FIXME - maybe this should be a TPCertGroup */ + uint32 numAnchorCerts, + const CSSM_DATA *anchorCerts, + + /* + * Certs to be freed by caller (i.e., TPCertInfo which we allocate + * as a result of using a cert from anchorCerts or dbList) are added + * to this group. + */ + TPCertGroup &certsToBeFreed, + + /* + * Other certificates gathered during the course of this operation, + * currently consisting of certs fetched from DBs and from the net. + * This is not used when called by AppleTPSession::CertGroupConstructPriv; + * it's an optimization for the case when we're building a cert group + * for TPCrlInfo::verifyWithContext - we avoid re-fetching certs from + * the net which are needed to verify both the subject cert and a CRL. + * We don't modify this TPCertGroup, we only use certs from it. + */ + TPCertGroup *gatheredCerts, + + /* + * Indicates that subjectItem is a cert in this cert group. + * If true, that cert will be tested for "root-ness", including + * -- subject/issuer compare + * -- signature self-verify + * -- anchor compare + */ + CSSM_BOOL subjectIsInGroup, + + /* + * CSSM_TP_ACTION_FETCH_CERT_FROM_NET, + * CSSM_TP_ACTION_TRUST_SETTING, + * CSSM_TP_ACTION_IMPLICIT_ANCHORS are interesting + */ + CSSM_APPLE_TP_ACTION_FLAGS actionFlags, + + /* CSSM_TP_ACTION_TRUST_SETTING parameters */ + const CSSM_OID *policyOid, + const char *policyStr, + uint32 policyStrLen, + SecTrustSettingsKeyUsage leafKeyUse, // usage of *first* cert in chain + + /* returned */ + CSSM_BOOL &verifiedToRoot, // end of chain self-verifies + CSSM_BOOL &verifiedToAnchor, // end of chain in anchors + CSSM_BOOL &verifiedViaTrustSettings) // chain ends per User Trust setting +{ + const TPClItemInfo *thisSubject = &subjectItem; + CSSM_RETURN crtn = CSSM_OK; + TPCertInfo *issuerCert = NULL; + unsigned certDex; + TPCertInfo *anchorInfo = NULL; + bool foundPartialIssuer = false; + bool attemptNetworkFetch = false; + CSSM_BOOL firstSubjectIsInGroup = subjectIsInGroup; + TPCertInfo *endCert; + + tpVfyDebug("buildCertGroup top"); + + /* possible expired root which we'll only use if we can't find + * a better one */ + TPCertInfo *expiredRoot = NULL; + + /* and the general case of an expired or not yet valid cert */ + TPCertInfo *expiredIssuer = NULL; + + verifiedToRoot = CSSM_FALSE; + verifiedToAnchor = CSSM_FALSE; + verifiedViaTrustSettings = CSSM_FALSE; + + /*** main loop to seach inCertGroup and dbList *** + * + * Exit loop on: + * -- find a root cert in the chain (self-signed) + * -- find a non-root cert which is also in the anchors list + * -- find a cert which is trusted per Trust Settings (if enabled) + * -- memory error + * -- or no more certs to add to chain. + */ + for(;;) { + /* + * Top of loop: thisSubject is the item we're trying to verify. + */ + + /* is thisSubject a root cert or listed in user trust list? */ + if(subjectIsInGroup) { + TPCertInfo *subjCert = lastCert(); + assert(subjCert != NULL); + + if(actionFlags & CSSM_TP_ACTION_TRUST_SETTINGS) { + assert(policyOid != NULL); + + /* + * Figure out key usage. If this is a leaf cert, the caller - actually + * the per-policy code - inferred the usage. Else it could be for + * verifying a cert or a CRL. + * + * We want to avoid multiple calls to the effective portion of + * evaluateTrustSettings(), but a CA cert could be usable for only + * signing certs and not CRLs. Thus we're evaluating a CA cert, + * try to evaluate for signing certs *and* CRLs in case we come + * this way again later when performing CRL verification. If that + * fails, then retry with just cert signing. + */ + SecTrustSettingsKeyUsage localKeyUse; + bool doRetry = false; + if(subjCert == firstCert()) { + /* leaf - use caller's spec */ + localKeyUse = leafKeyUse; + /* FIXME - add in CRL if this is cert checking? */ + } + else { + localKeyUse = kSecTrustSettingsKeyUseSignCert | kSecTrustSettingsKeyUseSignRevocation; + /* and if necessary */ + doRetry = true; + } + /* this lets us avoid searching for the same thing twice when there + * is in fact no entry for it */ + bool foundEntry = false; + bool trustSettingsFound = false; + OSStatus ortn = subjCert->evaluateTrustSettings(*policyOid, + policyStr, policyStrLen, localKeyUse, &trustSettingsFound, &foundEntry); + if(ortn) { + /* this is only a dire error */ + crtn = ortn; + goto final_out; + } + if(!trustSettingsFound && foundEntry && doRetry) { + tpTrustSettingsDbg("buildCertGroup: retrying evaluateTrustSettings with Cert only"); + ortn = subjCert->evaluateTrustSettings(*policyOid, + policyStr, policyStrLen, kSecTrustSettingsKeyUseSignCert, + &trustSettingsFound, &foundEntry); + if(ortn) { + crtn = ortn; + goto final_out; + } + } + if(trustSettingsFound) { + switch(subjCert->trustSettingsResult()) { + case kSecTrustSettingsResultInvalid: + /* should not happen... */ + assert(0); + crtn = CSSMERR_TP_INTERNAL_ERROR; + break; + case kSecTrustSettingsResultTrustRoot: + case kSecTrustSettingsResultTrustAsRoot: + tpTrustSettingsDbg("Trust[As]Root found"); + crtn = CSSM_OK; + break; + case kSecTrustSettingsResultDeny: + tpTrustSettingsDbg("TrustResultDeny found"); + crtn = CSSMERR_APPLETP_TRUST_SETTING_DENY; + break; + case kSecTrustSettingsResultUnspecified: + /* special case here: this means "keep going, we don't trust or + * distrust this cert". Typically used to express allowed errors + * only. + */ + tpTrustSettingsDbg("TrustResultUnspecified found"); + goto post_trust_setting; + default: + tpTrustSettingsDbg("Unknown TrustResult (%d)", + (int)subjCert->trustSettingsResult()); + crtn = CSSMERR_TP_INTERNAL_ERROR; + break; + } + /* cleanup partial key processing */ + verifiedViaTrustSettings = CSSM_TRUE; + goto final_out; + } + } /* CSSM_TP_ACTION_TRUST_SETTING */ + +post_trust_setting: + if(subjCert->isSelfSigned()) { + /* We're at the end of the chain. */ + verifiedToRoot = CSSM_TRUE; + + /* + * Special case if this root is temporally invalid (and it's not + * the leaf): remove it from the outgoing cert group, save it, + * and proceed, looking another (good) root in anchors. + * There's no way we'll find another good one in this loop. + */ + if((subjCert->isExpired() || subjCert->isNotValidYet()) && + (!firstSubjectIsInGroup || (mNumCerts > 1))) { + tpDebug("buildCertGroup: EXPIRED ROOT %p, looking for good one", subjCert); + expiredRoot = subjCert; + if(mNumCerts) { + /* roll back to previous cert */ + mNumCerts--; + } + if(mNumCerts == 0) { + /* roll back to caller's initial condition */ + thisSubject = &subjectItem; + } + else { + thisSubject = lastCert(); + } + } + break; /* out of main loop */ + } /* root */ + + /* + * If this non-root cert is in the provided anchors list, + * we can stop building the chain at this point. + * + * If this cert is a leaf, the chain ends in an anchor, but if it's + * also temporally invalid, we can't do anything further. However, + * if it's not a leaf, then we need to roll back the chain to a + * point just before this cert, so Case 1 will subsequently find + * the anchor (and handle the anchor correctly if it's expired.) + */ + if(numAnchorCerts && anchorCerts) { + bool foundNonRootAnchor = false; + for(certDex=0; certDexitemData(), &anchorCerts[certDex])) { + foundNonRootAnchor = true; + /* if it's not the leaf, remove it from the outgoing cert group. */ + if(!firstSubjectIsInGroup || (mNumCerts > 1)) { + if(mNumCerts) { + /* roll back to previous cert */ + mNumCerts--; + } + if(mNumCerts == 0) { + /* roll back to caller's initial condition */ + thisSubject = &subjectItem; + } + else { + thisSubject = lastCert(); + } + tpAnchorDebug("buildCertGroup: CA cert in input AND anchors"); + } /* not leaf */ + else { + if(subjCert->isExpired() || subjCert->isNotValidYet()) { + crtn = CSSM_CERT_STATUS_EXPIRED; + } else { + crtn = CSSM_OK; + } + subjCert->isAnchor(true); + verifiedToAnchor = CSSM_TRUE; + tpAnchorDebug("buildCertGroup: leaf cert in input AND anchors"); + } /* leaf */ + break; /* out of anchor-checking loop */ + } + } + if(foundNonRootAnchor) { + break; /* out of main loop */ + } + } /* non-root */ + + } /* subjectIsInGroup */ + + /* + * Search unused incoming certs to find an issuer. + * Both cert groups are optional. + * We'll add issuer to outCertGroup below. + * If we find a cert that's expired or not yet valid, we hold on to it + * and look for a better one. If we don't find it here we drop back to the + * expired one at the end of the loop. If that expired cert is a root + * cert, we'll use the expiredRoot mechanism (see above) to roll back and + * see if we can find a good root in the incoming anchors. + */ + if(inCertGroup != NULL) { + bool partial = false; + issuerCert = inCertGroup->findIssuerForCertOrCrl(*thisSubject, + partial); + if(issuerCert) { + issuerCert->isFromInputCerts(true); + if(partial) { + /* deal with this later */ + foundPartialIssuer = true; + tpDebug("buildCertGroup: PARTIAL Cert FOUND in inCertGroup"); + } + else { + tpDebug("buildCertGroup: Cert FOUND in inCertGroup"); + } + } + } + if(issuerCert != NULL) { + if(issuerCert->isExpired() || issuerCert->isNotValidYet()) { + if(expiredIssuer == NULL) { + tpDebug("buildCertGroup: saving expired cert %p (1)", issuerCert); + expiredIssuer = issuerCert; + issuerCert = NULL; + } + /* else we already have an expired issuer candidate */ + } + else { + /* unconditionally done with possible expiredIssuer */ + #ifndef NDEBUG + if(expiredIssuer != NULL) { + tpDebug("buildCertGroup: DISCARDING expired cert %p (1)", expiredIssuer); + } + #endif + expiredIssuer = NULL; + } + } + + if((issuerCert == NULL) && (gatheredCerts != NULL)) { + bool partial = false; + issuerCert = gatheredCerts->findIssuerForCertOrCrl(*thisSubject, + partial); + if(issuerCert) { + if(partial) { + /* deal with this later */ + foundPartialIssuer = true; + tpDebug("buildCertGroup: PARTIAL Cert FOUND in gatheredCerts"); + } + else { + tpDebug("buildCertGroup: Cert FOUND in gatheredCerts"); + } + } + } + + if(issuerCert != NULL) { + if(issuerCert->isExpired() || issuerCert->isNotValidYet()) { + if(expiredIssuer == NULL) { + tpDebug("buildCertGroup: saving expired cert %p (2)", issuerCert); + expiredIssuer = issuerCert; + issuerCert = NULL; + } + /* else we already have an expired issuer candidate */ + } + else { + /* unconditionally done with possible expiredIssuer */ + #ifndef NDEBUG + if(expiredIssuer != NULL) { + tpDebug("buildCertGroup: DISCARDING expired cert %p (2)", expiredIssuer); + } + #endif + expiredIssuer = NULL; + } + } + + if((issuerCert == NULL) && (dbList != NULL)) { + /* Issuer not in incoming cert group or gathered certs. Search DBList. */ + bool partial = false; + try { + issuerCert = tpDbFindIssuerCert(mAlloc, + clHand, + cspHand, + thisSubject, + dbList, + verifyTime, + partial); + } + catch (...) {} + + if(issuerCert) { + /* unconditionally done with possible expiredIssuer */ + #ifndef NDEBUG + if(expiredIssuer != NULL) { + tpDebug("buildCertGroup: DISCARDING expired cert %p (3)", expiredIssuer); + } + #endif + expiredIssuer = NULL; + + /* + * Handle Radar 4566041, endless loop of cross-signed certs. + * This can only happen when fetching certs from a DLDB or + * from the net; we prevent that from happening when the certs + * are in inCertGroup or gatheredCerts by keeping track of those + * certs' mUsed state. + */ + if(isInGroup(*issuerCert)) { + tpDebug("buildCertGroup: Multiple instances of cert"); + delete issuerCert; + issuerCert = NULL; + } + else { + /* caller must free */ + certsToBeFreed.appendCert(issuerCert); + if(partial) { + /* deal with this later */ + foundPartialIssuer = true; + tpDebug("buildCertGroup: PARTIAL Cert FOUND in dbList"); + } + else { + tpDebug("buildCertGroup: Cert FOUND in dbList"); + } + } + } + } /* searching DLDB list */ + + /* + * Note: we don't handle an expired cert returned from tpDbFindIssuerCert() + * in any special way like we do with findIssuerForCertOrCrl(). + * tpDbFindIssuerCert() does its best to give us a temporally valid cert; if + * it returns an expired cert (or, if findIssuerForCertOrCrl() gave us an + * expired cert and tpDbFindIssuerCert() could not do any better), that's all + * we have to work with at this point. We'll go back to the top of the loop + * and apply trust settings if enabled; if an expired cert is trusted per + * Trust Settings, we're done. (Note that anchors are fetched from a DLDB + * when Trust Settings are enabled, so even if two roots with the same key + * and subject name are in DLDBs, and one of them is expired, we'll have the + * good one at this time because of tpDbFindIssuerCert()'s ability to find + * the best cert.) + * + * If Trust Settings are not enabled, and we have an expired root at this + * point, the expiredRoot mechanism is used to roll back and search for + * an anchor that verifies the last good cert. + */ + + if((issuerCert == NULL) && /* tpDbFindIssuerCert() hasn't found one and + * we don't have a good one */ + (expiredIssuer != NULL)) { /* but we have an expired candidate */ + /* + * OK, we'll take the expired issuer. + * Note we don't have to free expiredIssuer if we found a good one since + * expiredIssuer can only come from inCertGroup or gatheredCerts (not from + * dbList). + */ + tpDebug("buildCertGroup: USING expired cert %p", expiredIssuer); + issuerCert = expiredIssuer; + expiredIssuer = NULL; + } + if(issuerCert == NULL) { + /* end of search, broken chain */ + break; + } + + /* + * One way or the other, we've found a cert which verifies subjectCert. + * Add the issuer to outCertGroup and make it the new thisSubject for + * the next pass. + */ + appendCert(issuerCert); + thisSubject = issuerCert; + subjectIsInGroup = CSSM_TRUE; + issuerCert = NULL; + } /* main loop */ + + /* + * This can be NULL if we're evaluating a CRL (and we haven't + * gotten very far). + */ + endCert = lastCert(); + + /* + * This, on the other hand, is always valid. It could be a CRL. + */ + assert(thisSubject != NULL); + + if( (actionFlags & CSSM_TP_ACTION_IMPLICIT_ANCHORS) && + ( (endCert && endCert->isSelfSigned()) || expiredRoot) ) { + /* + * Caller will be satisfied with this; skip further anchor processing. + */ + tpAnchorDebug("buildCertGroup: found IMPLICIT anchor"); + goto post_anchor; + } + if(numAnchorCerts == 0) { + /* we're probably done */ + goto post_anchor; + } + assert(anchorCerts != NULL); + + /*** anchor cert handling ***/ + + /* + * Case 1: If thisSubject is not a root cert, try to validate with incoming anchor certs. + */ + expiredIssuer = NULL; + if(!(endCert && endCert->isSelfSigned())) { + for(certDex=0; certDexisIssuerOf(*thisSubject)) { + /* not this anchor */ + tpAnchorDebug("buildCertGroup anchor not issuer"); + delete anchorInfo; + anchorInfo = NULL; + continue; + } + + crtn = thisSubject->verifyWithIssuer(anchorInfo); + + if(crtn == CSSM_OK) { + if(anchorInfo->isExpired() || anchorInfo->isNotValidYet()) { + if(expiredIssuer == NULL) { + /* + * Hang on to this one; keep looking for a better one. + */ + tpDebug("buildCertGroup: saving expired anchor %p", anchorInfo); + expiredIssuer = anchorInfo; + /* flag this condition for the switch below */ + crtn = CSSM_CERT_STATUS_EXPIRED; + expiredIssuer->isAnchor(true); + assert(!anchorInfo->isFromInputCerts()); + expiredIssuer->index(certDex); + certsToBeFreed.appendCert(expiredIssuer); + } + /* else we already have an expired candidate anchor */ + } + else { + /* + * Done with possible expiredIssuer. We don't delete it, since we already added + * it to certsToBeFreed, above. + */ + if(expiredIssuer != NULL) { + tpDebug("buildCertGroup: DISCARDING expired anchor %p", expiredIssuer); + expiredIssuer = NULL; + } + } + } + + switch(crtn) { + case CSSMERR_CSP_APPLE_PUBLIC_KEY_INCOMPLETE: + /* + * A bit of a corner case. Found an issuer in AnchorCerts, but + * we can't do a signature verify since the issuer has a partial + * public key. Proceed but return + * CSSMERR_TP_CERTIFICATE_CANT_OPERATE. + */ + if(anchorInfo->addStatusCode(CSSMERR_TP_CERTIFICATE_CANT_OPERATE)) { + foundPartialIssuer = true; + crtn = CSSMERR_TP_CERTIFICATE_CANT_OPERATE; + } + else { + /* ignore */ + crtn = CSSM_OK; + } + /* drop thru */ + case CSSM_OK: + /* A fully successful return. */ + verifiedToAnchor = CSSM_TRUE; + if(anchorInfo->isSelfSigned()) { + verifiedToRoot = CSSM_TRUE; + } + + /* + * Add this anchor cert to the output group + * and to certsToBeFreed. + */ + appendCert(anchorInfo); + anchorInfo->isAnchor(true); + assert(!anchorInfo->isFromInputCerts()); + anchorInfo->index(certDex); + certsToBeFreed.appendCert(anchorInfo); + tpDebug("buildCertGroup: Cert FOUND by signer in AnchorList"); + tpAnchorDebug("buildCertGroup: Cert FOUND by signer in AnchorList"); + /* one more thing: partial public key processing needed? */ + if(foundPartialIssuer) { + return verifyWithPartialKeys(subjectItem); + } + else { + return crtn; + } + + default: + /* continue to next anchor */ + if(crtn != CSSM_CERT_STATUS_EXPIRED) { + /* Expired means we're saving it in expiredIssuer */ + tpVfyDebug("buildCertGroup found issuer in anchor, BAD SIG"); + delete anchorInfo; + } + anchorInfo = NULL; + break; + } + } /* for each anchor */ + } /* thisSubject not a root cert */ + + /* + * Case 2: Check whether endCert is present in anchor certs. + * + * Also used to validate an expiredRoot that we pulled off the chain in + * hopes of finding something better (which, if we're here, we haven't done). + * + * Note that the main loop above did the actual root self-verify test. + */ + if(endCert || expiredRoot) { + + TPCertInfo *theRoot; + if(expiredRoot) { + /* this is NOT in our outgoing cert group (yet) */ + theRoot = expiredRoot; + } + else { + theRoot = endCert; + } + /* see if that root cert is identical to one of the anchor certs */ + for(certDex=0; certDexitemData(), &anchorCerts[certDex])) { + /* one fully successful return */ + tpAnchorDebug("buildCertGroup: end cert in input AND anchors"); + verifiedToAnchor = CSSM_TRUE; + theRoot->isAnchor(true); + if(!theRoot->isFromInputCerts()) { + /* Don't override index into input certs */ + theRoot->index(certDex); + } + if(expiredRoot) { + /* verified to anchor but caller will see + * CSSMERR_TP_CERT_EXPIRED */ + appendCert(expiredRoot); + } + /* one more thing: partial public key processing needed? */ + if(foundPartialIssuer) { + return verifyWithPartialKeys(subjectItem); + } + else { + return CSSM_OK; + } + } + } + tpAnchorDebug("buildCertGroup: end cert in input, NOT anchors"); + + if(!expiredRoot && endCert->isSelfSigned()) { + /* verified to a root cert which is not an anchor */ + /* Generally maps to CSSMERR_TP_INVALID_ANCHOR_CERT by caller */ + /* one more thing: partial public key processing needed? */ + if(foundPartialIssuer) { + return verifyWithPartialKeys(subjectItem); + } + else { + return CSSM_OK; + } + } + /* else try finding a good anchor */ + } + + /* regardless of anchor search status... */ + crtn = CSSM_OK; + if(!verifiedToAnchor && (expiredIssuer != NULL)) { + /* expiredIssuer here is always an anchor */ + tpDebug("buildCertGroup: accepting expired anchor %p", expiredIssuer); + appendCert(expiredIssuer); + verifiedToAnchor = CSSM_TRUE; + if(expiredIssuer->isSelfSigned()) { + verifiedToRoot = CSSM_TRUE; + } + /* no matter what, we don't want this one */ + expiredRoot = NULL; + } +post_anchor: + if(expiredRoot) { + /* + * One remaining special case: expiredRoot found in input certs, but + * no luck resolving the problem with the anchors. Go ahead and (re-)append + * the expired root and return. + */ + tpDebug("buildCertGroup: accepting EXPIRED root"); + appendCert(expiredRoot); + if(foundPartialIssuer) { + return verifyWithPartialKeys(subjectItem); + } + else { + return CSSM_OK; + } + } + + /* If we get here, determine if fetching the issuer from the network + * should be attempted: + */ + attemptNetworkFetch = (actionFlags & CSSM_TP_ACTION_FETCH_CERT_FROM_NET); + if( (!dbList || (dbList->NumHandles == 0)) && + (!anchorCerts || (numAnchorCerts == 0)) ) { + /* DB list is empty *and* anchors are empty; there is no point in going + * out to the network, since we cannot build a chain to a trusted root. + * (This can occur when the caller wants to evaluate a single certificate + * without trying to build the chain, e.g. to check its key usage.) + */ + attemptNetworkFetch = false; + } + + /* + * If we haven't verified to a root, and net fetch of certs is enabled, + * try to get the issuer of the last cert in the chain from the net. + * If that succeeds, then call ourself recursively to perform the + * whole search again (including comparing to or verifying against + * anchor certs). + */ + if(!verifiedToRoot && !verifiedToAnchor && + (endCert != NULL) && attemptNetworkFetch) { + TPCertInfo *issuer = NULL; + CSSM_RETURN cr = tpFetchIssuerFromNet(*endCert, + clHand, + cspHand, + verifyTime, + issuer); + switch(cr) { + case CSSMERR_TP_CERTGROUP_INCOMPLETE: + /* no issuerAltName, no reason to log this */ + break; + default: + /* gross error */ + endCert->addStatusCode(cr); + break; + case CSSMERR_CSP_APPLE_PUBLIC_KEY_INCOMPLETE: + /* use this one but re-verify later */ + foundPartialIssuer = true; + /* and drop thru */ + case CSSM_OK: + if (!issuer) + break; + tpDebug("buildCertGroup: Cert FOUND from Net; recursing"); + + if(isInGroup(*issuer)) { + tpDebug("buildCertGroup: Multiple instances of cert from net"); + delete issuer; + issuer = NULL; + crtn = CSSMERR_TP_CERTGROUP_INCOMPLETE; + break; + } + + /* add this fetched cert to constructed group */ + appendCert(issuer); + issuer->isFromNet(true); + certsToBeFreed.appendCert(issuer); + + /* and go again */ + cr = buildCertGroup(*issuer, + inCertGroup, + dbList, + clHand, + cspHand, + verifyTime, + numAnchorCerts, + anchorCerts, + certsToBeFreed, + gatheredCerts, + CSSM_TRUE, // subjectIsInGroup + actionFlags, + policyOid, + policyStr, + policyStrLen, + leafKeyUse, // actually don't care since the leaf will not + // be evaluated + verifiedToRoot, + verifiedToAnchor, + verifiedViaTrustSettings); + if(cr) { + return cr; + } + + /* one more thing: partial public key processing needed? */ + if(foundPartialIssuer) { + return verifyWithPartialKeys(subjectItem); + } + else { + return CSSM_OK; + } + } + } +final_out: + /* regardless of outcome, check for partial keys to log per-cert status */ + CSSM_RETURN partRtn = CSSM_OK; + if(foundPartialIssuer) { + partRtn = verifyWithPartialKeys(subjectItem); + } + if(crtn) { + return crtn; + } + else { + return partRtn; + } +} + +/* + * Called from buildCertGroup as final processing of a constructed + * group when CSSMERR_CSP_APPLE_PUBLIC_KEY_INCOMPLETE has been + * detected. Perform partial public key processing. + * + * We don't have to verify every element, just the ones whose + * issuers have partial public keys. + * + * Returns: + * CSSMERR_TP_CERTIFICATE_CANT_OPERATE in the case of an issuer cert + * with a partial public key which can't be completed. + * CSSMERR_TP_INVALID_CERT_AUTHORITY if sig verify failed with + * a (supposedly) completed partial key + */ +CSSM_RETURN TPCertGroup::verifyWithPartialKeys( + const TPClItemInfo &subjectItem) // Cert or CRL +{ + TPCertInfo *lastFullKeyCert = NULL; + tpDebug("verifyWithPartialKeys top"); + + /* start from the end - it's easier */ + for(int dex=mNumCerts-1; dex >= 0; dex--) { + TPCertInfo *thisCert = mCertInfo[dex]; + + /* + * If this is the start of the cert chain, and it's not being + * used to verify subjectItem, then we're done. + */ + if(dex == 0) { + if((void *)thisCert == (void *)&subjectItem) { + tpDebug("verifyWithPartialKeys: success at leaf cert"); + return CSSM_OK; + } + } + if(!thisCert->hasPartialKey()) { + /* + * Good to know. Record this and move on. + */ + lastFullKeyCert = thisCert; + tpDebug("full key cert found at index %d", dex); + continue; + } + if(lastFullKeyCert == NULL) { + /* + * No full keys between here and the end! + */ + tpDebug("UNCOMPLETABLE cert at index %d", dex); + if(thisCert->addStatusCode(CSSMERR_TP_CERTIFICATE_CANT_OPERATE)) { + return CSSMERR_TP_CERTIFICATE_CANT_OPERATE; + } + else { + break; + } + } + + /* do the verify - of next cert in chain or of subjectItem */ + const TPClItemInfo *subject; + if(dex == 0) { + subject = &subjectItem; + tpDebug("...verifying subject item with partial cert 0"); + } + else { + subject = mCertInfo[dex - 1]; + tpDebug("...verifying with partial cert %d", dex); + } + CSSM_RETURN crtn = subject->verifyWithIssuer(thisCert, + lastFullKeyCert); + if(crtn) { + tpDebug("CERT VERIFY ERROR with partial cert at index %d", dex); + if(thisCert->addStatusCode(CSSMERR_TP_CERTIFICATE_CANT_OPERATE)) { + return CSSMERR_TP_INVALID_CERT_AUTHORITY; + } + else { + break; + } + } + } + + /* we just verified subjectItem - right? */ + assert((void *)mCertInfo[0] != (void *)&subjectItem); + tpDebug("verifyWithPartialKeys: success at subjectItem"); + return CSSM_OK; +} + +/* + * Free records obtained from DBs. Called when these records are not going to + * be passed to caller of CertGroupConstruct or CertGroupVerify. + */ +void TPCertGroup::freeDbRecords() +{ + for(unsigned dex=0; dexfreeUniqueRecord(); + } +} diff --git a/libsecurity_apple_x509_tp/lib/TPCertInfo.h b/libsecurity_apple_x509_tp/lib/TPCertInfo.h new file mode 100644 index 00000000..9bba9add --- /dev/null +++ b/libsecurity_apple_x509_tp/lib/TPCertInfo.h @@ -0,0 +1,612 @@ +/* + * 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'). + * 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. + */ + + +/* + * TPCertInfo.h - TP's private certificate info and cert group classes + */ + +#ifndef _TP_CERT_INFO_H_ +#define _TP_CERT_INFO_H_ + +#include +#include +#include +#include +#include +#include +#include + +/* protects TP-wide access to time() and gmtime() */ +extern ModuleNexus tpTimeLock; + +/* + * Prototypes for functions which are isomorphic between certs and CRLs at the + * CL API. + */ +typedef CSSM_RETURN (*clGetFirstFieldFcn)( + CSSM_CL_HANDLE CLHandle, + CSSM_HANDLE ItemHandle, // cached cert or CRL + const CSSM_OID *ItemField, + CSSM_HANDLE_PTR ResultsHandle, + uint32 *NumberOfMatchedFields, + CSSM_DATA_PTR *Value); +typedef CSSM_RETURN (*clAbortQueryFcn)( + CSSM_CL_HANDLE CLHandle, + CSSM_HANDLE ResultsHandle); // from clGetFirstFieldFcn +typedef CSSM_RETURN (*clCacheItemFcn)( + CSSM_CL_HANDLE CLHandle, + const CSSM_DATA *Item, // raw cert or CRL + CSSM_HANDLE_PTR CertHandle); +typedef CSSM_RETURN (*clAbortCacheFcn)( + CSSM_CL_HANDLE CLHandle, + CSSM_HANDLE ItemHandle); // from clCacheItemFcn +typedef CSSM_RETURN (*clItemVfyFcn)( + CSSM_CL_HANDLE CLHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_DATA *CrlOrCertToBeVerified, + const CSSM_DATA *SignerCert, + const CSSM_FIELD *VerifyScope, + uint32 ScopeSize); + +typedef struct { + /* CL/cert-specific functions */ + clGetFirstFieldFcn getField; + clAbortQueryFcn abortQuery; + clCacheItemFcn cacheItem; + clAbortCacheFcn abortCache; + clItemVfyFcn itemVerify; + /* CL/cert-specific OIDs */ + const CSSM_OID *notBeforeOid; + const CSSM_OID *notAfterOid; + /* CL/cert specific errors */ + CSSM_RETURN invalidItemRtn; // CSSMERR_TP_INVALID_{CERT,CRL}_POINTER + CSSM_RETURN expiredRtn; + CSSM_RETURN notValidYetRtn; +} TPClItemCalls; + +class TPCertInfo; + +/* + * On construction of a TPClItemInfo, specifies whether or not to + * copy the incoming item data (in which we free it upon destruction) + * or to use caller's data as is (in which case the caller maintains + * the data). + */ +typedef enum { + TIC_None = 0, // never used + TIC_NoCopy, // caller maintains + TIC_CopyData // we copy and free +} TPItemCopy; + +/* + * State of a cert's mIsRoot flag. We do signature self-verify on demand. + */ +typedef enum { + TRS_Unknown, // initial state + TRS_NamesMatch, // subject == issuer, but no sig verify yet + TRS_NotRoot, // subject != issuer, OR sig verify failed + TRS_IsRoot // it's a root +} TPRootState; + +/* + * Base class for TPCertInfo and TPCrlInfo. Encapsulates caching of + * an entity within the CL, field lookup/free, and signature verify, + * all of which use similar functions at the CL API. + */ +class TPClItemInfo +{ + NOCOPY(TPClItemInfo) +public: + TPClItemInfo( + CSSM_CL_HANDLE clHand, + CSSM_CSP_HANDLE cspHand, + const TPClItemCalls &clCalls, + const CSSM_DATA *itemData, + TPItemCopy copyItemData, + const char *verifyTime); // may be NULL + + ~TPClItemInfo(); + void releaseResources(); + + /* + * Fetch arbitrary field from cached item. + * Only should be used when caller is sure there is either zero or one + * of the requested fields present in the cert. + */ + CSSM_RETURN fetchField( + const CSSM_OID *fieldOid, + CSSM_DATA_PTR *fieldData); // mallocd by CL and RETURNED + + /* free arbitrary field obtained from fetchField() */ + CSSM_RETURN freeField( + const CSSM_OID *fieldOid, + CSSM_DATA_PTR fieldData); + + /* + * Verify with an issuer cert - works on certs and CRLs. + * Issuer/subject name match already performed by caller. + * May return CSSMERR_CSP_APPLE_PUBLIC_KEY_INCOMPLETE without + * performing a signature op, in which case it is the caller's + * resposibility to complete this operation later when + * sufficient information is available. + * + * Optional paramCert is used to provide parameters when issuer + * has a partial public key. + */ + CSSM_RETURN verifyWithIssuer( + TPCertInfo *issuerCert, + TPCertInfo *paramCert = NULL) const; + + /* accessors */ + CSSM_CL_HANDLE clHand() const { return mClHand; } + CSSM_CSP_HANDLE cspHand() const { return mCspHand; } + CSSM_HANDLE cacheHand() const { return mCacheHand; } + const CSSM_DATA *itemData() const { return mItemData; } + const CSSM_DATA *issuerName() const { return mIssuerName; }; + unsigned index() const { return mIndex; } + void index(unsigned dex) { mIndex = dex; } + bool isExpired() { return mIsExpired; } + bool isNotValidYet() { return mIsNotValidYet; } + + /* + * Calculate validity (not before/after). Returns + * CSSMERR_{TP_CERT,APPLETP_CRL}_NOT_VALID_YET + * CSSMERR_xxx_T_EXPIRED + * CSSM_OK + * CSSMERR_xxx_INVALID_CERT_POINTER, other "bogus cert" errors + */ + CSSM_RETURN calculateCurrent( + const char *verifyString = NULL); + +private: + + /* Tell CL to parse and cache the item */ + CSSM_RETURN cacheItem( + const CSSM_DATA *itemData, + TPItemCopy copyItemData); + + + /* fetch not before/after fields */ + void fetchNotBeforeAfter(); + + CSSM_CL_HANDLE mClHand; // always valid + CSSM_CSP_HANDLE mCspHand; // always valid + const TPClItemCalls &mClCalls; + bool mWeOwnTheData; // if true, we have to free + // mCertData + /* following four valid subsequent to cacheItem(), generally + * called by subclass's constructor */ + CSSM_HANDLE mCacheHand; + CSSM_DATA_PTR mIssuerName; + CSSM_DATA *mItemData; + CSSM_ALGORITHMS mSigAlg; + + /* calculated implicitly at construction */ + CFDateRef mNotBefore; + CFDateRef mNotAfter; + + /* also calculated at construction, but can be recalculated at will */ + bool mIsExpired; + bool mIsNotValidYet; + + unsigned mIndex; +}; + +/* + * Class representing one certificate. The raw cert data usually comes from + * a client (via incoming cert groups in CertGroupConstruct() and + * CertGroupVerify()); in this case, we don't own the raw data and + * don't copy or free it. Caller can optionally specify that we copy + * (and own and eventually free) the raw cert data. Currently this is + * done when we find a cert in a DlDb or from the net. The constructor throws + * on any error (bad cert data); subsequent to successful construction, no CSSM + * errors are thrown and it's guaranteed that the cert is basically good and + * successfully cached in the CL, and that we have a locally cached subject + * and issuer name (in normalized encoded format). + */ +class TPCertInfo : public TPClItemInfo +{ + NOCOPY(TPCertInfo) +public: + /* + * No default constructor - this is the only way. + * This caches the cert and fetches subjectName and issuerName + * to ensure the incoming certData is well-constructed. + */ + TPCertInfo( + CSSM_CL_HANDLE clHand, + CSSM_CSP_HANDLE cspHand, + const CSSM_DATA *certData, + TPItemCopy copyCertData, + + const char *verifyTime); // may be NULL + + /* frees mSubjectName, mIssuerName, mCacheHand via mClHand */ + ~TPCertInfo(); + + /* accessors */ + const CSSM_DATA *subjectName(); + + bool isSelfSigned(bool avoidVerify = false); + + bool isAnchor() { return mIsAnchor; } + void isAnchor(bool a) { mIsAnchor = a; } + bool isFromNet() { return mIsFromNet; } + void isFromNet(bool n) { mIsFromNet = n; }; + bool isFromInputCerts() { return mIsFromInputCerts; } + void isFromInputCerts(bool i) { mIsFromInputCerts = i; } + unsigned numStatusCodes() { return mNumStatusCodes; } + CSSM_RETURN *statusCodes() { return mStatusCodes; } + CSSM_DL_DB_HANDLE dlDbHandle() { return mDlDbHandle; } + void dlDbHandle(CSSM_DL_DB_HANDLE hand) + { mDlDbHandle = hand; } + CSSM_DB_UNIQUE_RECORD_PTR uniqueRecord() + { return mUniqueRecord; } + void uniqueRecord(CSSM_DB_UNIQUE_RECORD_PTR rec) + { mUniqueRecord = rec; } + CSSM_KEY_PTR pubKey() { return mPublicKey; } + bool used() { return mUsed; } + void used(bool u) { mUsed = u; } + bool isLeaf() { return mIsLeaf; } + void isLeaf(bool l) { mIsLeaf = l; } + + SecTrustSettingsDomain trustSettingsDomain() { return mTrustSettingsDomain; } + SecTrustSettingsResult trustSettingsResult() { return mTrustSettingsResult; } + bool ignoredError() { return mIgnoredError; } + + /* true means "verification terminated due to user trust setting" */ + bool trustSettingsFound(); + /* + * Am I the issuer of the specified subject item? Returns true if so. + * Works for subject certs as well as CRLs. + */ + bool isIssuerOf( + const TPClItemInfo &subject); + + /* + * Add error status to mStatusCodes[]. Check to see if the + * added status is allowed per mAllowedErrs; if not return true. + * Returns false of the status *is* an allowed error. + */ + bool addStatusCode( + CSSM_RETURN code); + + /* + * See if the specified error status is in the mStatusCodes array. + */ + bool hasStatusCode( + CSSM_RETURN code); + + /* + * See if the specified error status is allowed (return false) or + * fatal (return true) per mAllowedErrs[]. + */ + bool isStatusFatal( + CSSM_RETURN code); + + /* + * Indicate whether this cert's public key is a CSSM_KEYATTR_PARTIAL + * key. + */ + bool hasPartialKey(); + + /* Indicate whether this cert should be explicitly rejected. + */ + bool shouldReject(); + + /* + * Flag to indicate that at least one revocation policy has successfully + * achieved a positive verification of the cert. + */ + bool revokeCheckGood() { return mRevCheckGood; } + void revokeCheckGood(bool b) { mRevCheckGood = b; } + + /* + * Flag to indicate "I have successfully been checked for revocation + * status and the per-policy action data indicates that I need not be + * checked again by any other revocation policy". E.g., + * CSSM_TP_ACTION_CRL_SUFFICIENT is set and CRL revocation checking + * was successful for this cert. + */ + bool revokeCheckComplete() { return mRevCheckComplete; } + void revokeCheckComplete(bool b) { mRevCheckComplete = b; } + + /* + * Evaluate user trust; returns true if positive match found - i.e., + * cert chain construction is done. + * The foundEntry return value indicates that *some* entry was found for + * the cert, regardless of the trust setting evaluation. + */ + OSStatus evaluateTrustSettings( + const CSSM_OID &policyOid, + const char *policyString, // optional + uint32 policyStringLen, + SecTrustSettingsKeyUsage keyUse, // optional + bool *foundMatchingEntry, + bool *foundEntry); // RETURNED + + bool hasEmptySubjectName(); + + /* Free mUniqueRecord if it exists */ + void freeUniqueRecord(); + +private: + /* obtained from CL at construction */ + CSSM_DATA_PTR mSubjectName; // always valid + CSSM_DATA_PTR mPublicKeyData; // mPublicKey obtained from this field + CSSM_KEY_PTR mPublicKey; + + /* maintained by caller, default at constructor 0/false */ + bool mIsAnchor; + bool mIsFromInputCerts; + bool mIsFromNet; + unsigned mNumStatusCodes; + CSSM_RETURN *mStatusCodes; + CSSM_DL_DB_HANDLE mDlDbHandle; + CSSM_DB_UNIQUE_RECORD_PTR mUniqueRecord; + bool mUsed; // e.g., used in current loop + bool mIsLeaf; // first in chain + TPRootState mIsRoot; // subject == issuer + bool mRevCheckGood; // >= 1 revoke check good + bool mRevCheckComplete; // no more revoke checking needed + + /* + * When true, we've already called SecTrustSettingsEvaluateCert, + * and the cached results are in following member vars. + */ + bool mTrustSettingsEvaluated; + + /* result of trust settings evaluation */ + SecTrustSettingsDomain mTrustSettingsDomain; + SecTrustSettingsResult mTrustSettingsResult; + bool mTrustSettingsFoundAnyEntry; + bool mTrustSettingsFoundMatchingEntry; + + /* allowed errors obtained from SecTrustSettingsEvaluateCert() */ + CSSM_RETURN *mAllowedErrs; + uint32 mNumAllowedErrs; + + /* we actually ignored one of mAllowedErrors[] */ + bool mIgnoredError; + + /* key usage for which mTrustSettingsResult was evaluated */ + SecTrustSettingsKeyUsage mTrustSettingsKeyUsage; + + /* for SecTrustSettingsEvaluateCert() */ + CFStringRef mCertHashStr; + + void releaseResources(); +}; + +/* Describe who owns the items in a TP{Cert,Crl}Group */ +typedef enum { + TGO_None = 0, // not used + TGO_Group, // TP{Cert,Crl}Group owns the items + TGO_Caller // caller owns the items +} TPGroupOwner; + +/* + * TP's private Cert Group class. Provides a list of TPCertInfo pointers, + * to which caller can append additional elements, access an element at + * an arbitrary position, and remove an element at an arbitrary position. + */ +class TPCertGroup +{ + NOCOPY(TPCertGroup) +public: + /* + * No default constructor. + * This one creates an empty TPCertGroup. + */ + TPCertGroup( + Allocator &alloc, + TPGroupOwner whoOwns); // if TGO_Group, we delete + + /* + * Construct from unordered, untrusted CSSM_CERTGROUP. Resulting + * TPCertInfos are more or less in the same order as the incoming + * certs, though incoming certs are discarded if they don't parse. + * No verification of any sort is performed. + */ + TPCertGroup( + const CSSM_CERTGROUP &CertGroupFrag, + CSSM_CL_HANDLE clHand, + CSSM_CSP_HANDLE cspHand, + Allocator &alloc, + const char *verifyString, // may be NULL + bool firstCertMustBeValid, + TPGroupOwner whoOwns); + + /* + * Deletes all TPCertInfo's. + */ + ~TPCertGroup(); + + /* + * Construct ordered, verified cert chain from a variety of inputs. + * Time validity is ignored and needs to be checked by caller (it's + * stored in each TPCertInfo we add to ourself during construction). + * The only error returned is CSSMERR_APPLETP_INVALID_ROOT, meaning + * we verified back to a supposed root cert which did not in fact + * self-verify. Other interesting status is returned via the + * verifiedToRoot and verifiedToAnchor flags. + * + * NOTE: is it the caller's responsibility to call setAllUnused() + * for both incoming cert groups (inCertGroup and gatheredCerts). + * We don't do that here because we may call ourself recursively. + * + * subjectItem may or may not be in the cert group (currently, it + * is in the group if it's a cert and it's not if it's a CRL, but + * we don't rely on that). + */ + CSSM_RETURN buildCertGroup( + const TPClItemInfo &subjectItem, // Cert or CRL + TPCertGroup *inCertGroup, // optional + const CSSM_DL_DB_LIST *dbList, // optional + CSSM_CL_HANDLE clHand, + CSSM_CSP_HANDLE cspHand, + const char *verifyString, // optional, for establishing + // validity of new TPCertInfos + /* trusted anchors, optional */ + /* FIXME - maybe this should be a TPCertGroup */ + uint32 numAnchorCerts, + const CSSM_DATA *anchorCerts, + + /* + * Certs to be freed by caller (i.e., TPCertInfo which we allocate + * as a result of using a cert from anchorCerts or dbList) are added + * to this group. + */ + TPCertGroup &certsToBeFreed, + + /* + * Other certificates gathered during the course of this operation, + * currently consisting of certs fetched from DBs and from the net. + * This is not used when called by AppleTPSession::CertGroupConstructPriv; + * it's an optimization for the case when we're building a cert group + * for TPCrlInfo::verifyWithContext - we avoid re-fetching certs from + * the net which are needed to verify both the subject cert and a CRL. + */ + TPCertGroup *gatheredCerts, + + /* + * Indicates that subjectItem is a cert in this cert group. + * If true, that cert will be tested for "root-ness", including + * -- subject/issuer compare + * -- signature self-verify + * -- anchor compare + */ + CSSM_BOOL subjectIsInGroup, + + /* currently, only CSSM_TP_ACTION_FETCH_CERT_FROM_NET and + * CSSM_TP_ACTION_TRUST_SETTINGS are interesting */ + CSSM_APPLE_TP_ACTION_FLAGS actionFlags, + + /* CSSM_TP_ACTION_TRUST_SETTINGS parameters */ + const CSSM_OID *policyOid, + const char *policyStr, + uint32 policyStrLen, + SecTrustSettingsKeyUsage leafKeyUse, + + /* returned */ + CSSM_BOOL &verifiedToRoot, // end of chain self-verifies + CSSM_BOOL &verifiedToAnchor, // end of chain in anchors + CSSM_BOOL &verifiedViaTrustSettings); // chain ends per User Trust setting + + /* add/remove/access TPTCertInfo's. */ + void appendCert( + TPCertInfo *certInfo); // appends to end of mCertInfo + TPCertInfo *certAtIndex( + unsigned index); + TPCertInfo *removeCertAtIndex( + unsigned index); // doesn't delete the cert, just + // removes it from our list + unsigned numCerts() const // how many do we have? + { return mNumCerts; } + + /* + * Convenience accessors for first and last cert, only valid when we have + * at least one cert. + */ + TPCertInfo *firstCert(); + TPCertInfo *lastCert(); + + /* build a CSSM_CERTGROUP corresponding with our mCertInfo */ + CSSM_CERTGROUP_PTR buildCssmCertGroup(); + + /* build a CSSM_TP_APPLE_EVIDENCE_INFO array corresponding with our + * mCertInfo */ + CSSM_TP_APPLE_EVIDENCE_INFO *buildCssmEvidenceInfo(); + + /* Given a status for basic construction of a cert group and a status + * of (optional) policy verification, plus the implicit notBefore/notAfter + * status in the certs, calculate a global return code. This just + * encapsulates a policy for CertGroupConstruct and CertGroupVerify. + */ + CSSM_RETURN getReturnCode( + CSSM_RETURN constructStatus, + CSSM_RETURN policyStatus, + CSSM_APPLE_TP_ACTION_FLAGS actionFlags); + + Allocator + &alloc() {return mAlloc; } + + /* set all TPCertInfo.mUsed flags false */ + void setAllUnused(); + + /* free records obtained from DBs */ + void freeDbRecords(); + + /* + * See if the specified error status is allowed (return true) or + * fatal (return false) per each cert's mAllowedErrs[]. Returns + * true if any cert returns false for its isStatusFatal() call. + * The list of errors which can apply to cert-chain-wide allowedErrors + * is right here; if the incoming error is not in that list, we + * return false. If the incoming error code is CSSM_OK we return + * true as a convenience for our callers. + */ + bool isAllowedError( + CSSM_RETURN code); + + /* + * Determine if we already have the specified cert in this group. + */ + bool isInGroup(TPCertInfo &certInfo); + + /* + * Given a constructed cert group, encode all the issuers + * (i.e. chain minus the leaf, unless numCerts() is 1) as a PEM data blob. + * Caller is responsible for freeing the data. + */ + void encodeIssuers(CSSM_DATA &issuers); + +private: + + /* + * Search unused incoming certs to find an issuer of specified + * cert or CRL. + * WARNING this assumes a valied "used" state for all certs + * in this group. + * If partialIssuerKey is true on return, caller must re-verify signature + * of subject later when sufficient info is available. + */ + TPCertInfo *findIssuerForCertOrCrl( + const TPClItemInfo &subject, + bool &partialIssuerKey); + + /* + * Called from buildCertGroup as final processing of a constructed + * group when CSSMERR_CSP_APPLE_PUBLIC_KEY_INCOMPLETE has been + * detected. Perform partial public key processing. + * Returns: + * CSSMERR_TP_CERTIFICATE_CANT_OPERATE - can't complete partial key + * CSSMERR_TP_INVALID_CERT_AUTHORITY - sig verify failed with + * (supposedly) completed partial key + */ + CSSM_RETURN verifyWithPartialKeys( + const TPClItemInfo &subjectItem); // Cert or CRL + + Allocator &mAlloc; + TPCertInfo **mCertInfo; // just an array of pointers + unsigned mNumCerts; // valid certs in certInfo + unsigned mSizeofCertInfo; // mallocd space in certInfo + TPGroupOwner mWhoOwns; // if TGO_Group, we delete certs + // upon destruction +}; +#endif /* _TP_CERT_INFO_H_ */ diff --git a/libsecurity_apple_x509_tp/lib/TPCrlInfo.cpp b/libsecurity_apple_x509_tp/lib/TPCrlInfo.cpp new file mode 100644 index 00000000..4efa50c1 --- /dev/null +++ b/libsecurity_apple_x509_tp/lib/TPCrlInfo.cpp @@ -0,0 +1,788 @@ +/* + * Copyright (c) 2002 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. + */ + + +/* + * TPCrlInfo.h - TP's private CRL and CRL group + * + * Written 9/30/2002 by Doug Mitchell. + */ + +#include "TPCrlInfo.h" +#include "tpdebugging.h" +#include "certGroupUtils.h" +#include "tpCrlVerify.h" +#include "tpPolicies.h" +#include "tpTime.h" +#include +#include +#include +#include +#include +#include /* for memcmp */ +#include + +/* + * Replacement for CSSM_CL_CrlGetFirstCachedFieldValue for use with + * TPCrlItemInfo's generic getFirstCachedField mechanism. + */ +static CSSM_RETURN tpGetFirstCachedFieldValue (CSSM_CL_HANDLE CLHandle, + CSSM_HANDLE CrlHandle, + const CSSM_OID *CrlField, + CSSM_HANDLE_PTR ResultsHandle, + uint32 *NumberOfMatchedFields, + CSSM_DATA_PTR *Value) +{ + return CSSM_CL_CrlGetFirstCachedFieldValue(CLHandle, + CrlHandle, + NULL, // const CSSM_DATA *CrlRecordIndex, + CrlField, + ResultsHandle, + NumberOfMatchedFields, + Value); +} + +static const TPClItemCalls tpCrlClCalls = +{ + tpGetFirstCachedFieldValue, + CSSM_CL_CrlAbortQuery, + CSSM_CL_CrlCache, + CSSM_CL_CrlAbortCache, + CSSM_CL_CrlVerify, + &CSSMOID_X509V1CRLThisUpdate, + &CSSMOID_X509V1CRLNextUpdate, + CSSMERR_TP_INVALID_CRL_POINTER, + CSSMERR_APPLETP_CRL_EXPIRED, + CSSMERR_APPLETP_CRL_NOT_VALID_YET +}; + + +/* + * No default constructor - this is the only way. + * This caches the cert and fetches subjectName and issuerName + * to ensure the incoming certData is well-constructed. + */ +TPCrlInfo::TPCrlInfo( + CSSM_CL_HANDLE clHand, + CSSM_CSP_HANDLE cspHand, + const CSSM_DATA *crlData, + TPItemCopy copyCrlData, // true: we copy, we free + // false - caller owns + const char *verifyTime) // = NULL + + : TPClItemInfo(clHand, cspHand, tpCrlClCalls, crlData, + copyCrlData, verifyTime), + mRefCount(0), + mFromWhere(CFW_Nowhere), + mX509Crl(NULL), + mCrlFieldToFree(NULL), + mVerifyState(CVS_Unknown), + mVerifyError(CSSMERR_TP_INTERNAL_ERROR) +{ + CSSM_RETURN crtn; + + mUri.Data = NULL; + mUri.Length = 0; + + /* fetch parsed CRL */ + crtn = fetchField(&CSSMOID_X509V2CRLSignedCrlCStruct, &mCrlFieldToFree); + if(crtn) { + /* bad CRL */ + releaseResources(); + CssmError::throwMe(crtn); + } + if(mCrlFieldToFree->Length != sizeof(CSSM_X509_SIGNED_CRL)) { + tpErrorLog("fetchField(SignedCrlCStruct) length error\n"); + releaseResources(); + CssmError::throwMe(CSSMERR_TP_INTERNAL_ERROR); + } + mX509Crl = (CSSM_X509_SIGNED_CRL *)mCrlFieldToFree->Data; + /* any other other commonly used fields? */ +} + +TPCrlInfo::~TPCrlInfo() +{ + releaseResources(); +} + +void TPCrlInfo::releaseResources() +{ + if(mCrlFieldToFree) { + freeField(&CSSMOID_X509V2CRLSignedCrlCStruct, mCrlFieldToFree); + mCrlFieldToFree = NULL; + } + if(mUri.Data) { + Allocator::standard().free(mUri.Data); + mUri.Data = NULL; + mUri.Length = 0; + } + TPClItemInfo::releaseResources(); +} + +void TPCrlInfo::uri(const CSSM_DATA &uri) +{ + tpCopyCssmData(Allocator::standard(), &uri, &mUri); +} + +/* + * List of extensions we understand and can accept as critical. + */ +static const CSSM_OID *const TPGoodCrlExtens[] = +{ + &CSSMOID_CrlNumber, + /* Note NOT CSSMOID_DeltaCrlIndicator! That's fatal */ + &CSSMOID_CrlReason, + &CSSMOID_CertIssuer, + &CSSMOID_IssuingDistributionPoint, + &CSSMOID_HoldInstructionCode, + &CSSMOID_InvalidityDate, + &CSSMOID_AuthorityKeyIdentifier, + &CSSMOID_SubjectAltName, + &CSSMOID_IssuerAltName +}; + +#define NUM_KNOWN_EXTENS (sizeof(TPGoodCrlExtens) / sizeof(CSSM_OID_PTR)) + +/* + * Do our best to understand all the entries in a CSSM_X509_EXTENSIONS, + * which may be per-CRL or per-entry. + * + * For now, we just ensure that for every critical extension, + * we actually understand it and can deal it. + */ +CSSM_RETURN TPCrlInfo::parseExtensions( + TPVerifyContext &vfyCtx, + bool isPerEntry, + uint32 entryIndex, // if isPerEntry + const CSSM_X509_EXTENSIONS &extens, + TPCertInfo *forCert, // optional + bool &isIndirectCrl) // RETURNED +{ + isIndirectCrl = false; + for(uint32 dex=0; dexcritical) { + /* critical: is it in our list of understood extensions? */ + unsigned i; + for(i=0; iextnId, TPGoodCrlExtens[i])) { + /* we're cool with this one */ + break; + } + } + if(i == NUM_KNOWN_EXTENS) { + tpCrlDebug("parseExtensions: Unknown Critical Extension\n"); + return CSSMERR_APPLETP_UNKNOWN_CRL_EXTEN; + } + } + + /* Specific extension handling. */ + if(tpCompareOids(&exten->extnId, + &CSSMOID_IssuingDistributionPoint)) { + /* + * If this assertion fails, we're out of sync with the CL + */ + assert(exten->format == CSSM_X509_DATAFORMAT_PARSED); + CE_IssuingDistributionPoint *idp = + (CE_IssuingDistributionPoint *) + exten->value.parsedValue; + + /* + * Snag indirectCrl flag for caller in any case + */ + if(idp->indirectCrlPresent && idp->indirectCrl) { + isIndirectCrl = true; + } + if(forCert != NULL) { + /* If no target cert, i.e., we're just verifying a CRL, + * skip the remaining IDP checks. */ + + /* verify onlyCACerts/onlyUserCerts */ + bool isUserCert; + if(forCert->isLeaf() && + !(vfyCtx.actionFlags & CSSM_TP_ACTION_LEAF_IS_CA)) { + isUserCert = true; + } + else { + isUserCert = false; + } + if((idp->onlyUserCertsPresent) && (idp->onlyUserCerts)) { + if(!isUserCert) { + tpCrlDebug("parseExtensions: onlyUserCerts, " + "!leaf\n"); + return CSSMERR_APPLETP_IDP_FAIL; + } + } + if((idp->onlyCACertsPresent) && (idp->onlyCACerts)) { + if(isUserCert) { + tpCrlDebug("parseExtensions: onlyCACerts, leaf\n"); + return CSSMERR_APPLETP_IDP_FAIL; + } + } + } /* IDP */ + } /* have target cert */ + } + + return CSSM_OK; +} + +/* + * The heavyweight "perform full verification of this CRL" op. + * Must verify to an anchor cert in tpVerifyContext or via + * Trust Settings if so enabled. + * Intermediate certs can come from signerCerts or dBList. + */ +CSSM_RETURN TPCrlInfo::verifyWithContext( + TPVerifyContext &tpVerifyContext, + TPCertInfo *forCert, // optional + bool doCrlVerify) +{ + /* + * Step 1: this CRL must be current. Caller might have re-evaluated + * expired/notValidYet since our construction via calculateCurrent(). + */ + if(isExpired()) { + return CSSMERR_APPLETP_CRL_EXPIRED; + } + if(isNotValidYet()) { + return CSSMERR_APPLETP_CRL_NOT_VALID_YET; + } + + /* subsequent verify state is cached */ + switch(mVerifyState) { + case CVS_Good: + return CSSM_OK; + case CVS_Bad: + return mVerifyError; + case CVS_Unknown: + break; + default: + tpErrorLog("verifyWithContext: bad verifyState\n"); + return CSSMERR_TP_INTERNAL_ERROR; + } + + /* + * Step 2: parse & understand all critical CRL extensions. + */ + CSSM_RETURN crtn; + bool isIndirectCrl; + crtn = parseExtensions(tpVerifyContext, + false, + 0, + mX509Crl->tbsCertList.extensions, + forCert, + isIndirectCrl); + if(crtn) { + mVerifyState = CVS_Bad; + if(!forCert || forCert->addStatusCode(crtn)) { + return crtn; + } + /* else continue */ + } + CSSM_X509_REVOKED_CERT_LIST_PTR revoked = + mX509Crl->tbsCertList.revokedCertificates; + if(revoked != NULL) { + for(uint32 dex=0; dexnumberOfRevokedCertEntries; dex++) { + bool dummyIsIndirect; // can't be set here + crtn = parseExtensions(tpVerifyContext, + true, + dex, + revoked->revokedCertEntry[dex].extensions, + forCert, + dummyIsIndirect); + if(crtn) { + if(!forCert || forCert->addStatusCode(crtn)) { + mVerifyState = CVS_Bad; + return crtn; + } + } + } + } + + /* + * Step 3: obtain a fully verified cert chain which verifies this CRL. + */ + CSSM_BOOL verifiedToRoot; + CSSM_BOOL verifiedToAnchor; + CSSM_BOOL verifiedViaTrustSetting; + + TPCertGroup outCertGroup(tpVerifyContext.alloc, + TGO_Caller); // CRLs owned by inCertGroup + + /* set up for disposal of TPCertInfos created by + * CertGroupConstructPriv */ + TPCertGroup certsToBeFreed(tpVerifyContext.alloc, TGO_Group); + + if(tpVerifyContext.signerCerts) { + /* start from scratch with this group */ + tpVerifyContext.signerCerts->setAllUnused(); + } + crtn = outCertGroup.buildCertGroup( + *this, // subject item + tpVerifyContext.signerCerts, // inCertGroup, optional + tpVerifyContext.dbList, // optional + tpVerifyContext.clHand, + tpVerifyContext.cspHand, + tpVerifyContext.verifyTime, + tpVerifyContext.numAnchorCerts, + tpVerifyContext.anchorCerts, + certsToBeFreed, + &tpVerifyContext.gatheredCerts, + CSSM_FALSE, // subjectIsInGroup + tpVerifyContext.actionFlags, + tpVerifyContext.policyOid, + tpVerifyContext.policyStr, + tpVerifyContext.policyStrLen, + kSecTrustSettingsKeyUseSignRevocation, + verifiedToRoot, + verifiedToAnchor, + verifiedViaTrustSetting); + /* subsequent errors to errOut: */ + + if(crtn) { + tpCrlDebug("TPCrlInfo::verifyWithContext buildCertGroup failure " + "index %u", index()); + if(!forCert || forCert->addStatusCode(crtn)) { + goto errOut; + } + } + if (verifiedToRoot && (tpVerifyContext.actionFlags & CSSM_TP_ACTION_IMPLICIT_ANCHORS)) + verifiedToAnchor = CSSM_TRUE; + if(!verifiedToAnchor && !verifiedViaTrustSetting) { + /* required */ + if(verifiedToRoot) { + /* verified to root which is not an anchor */ + tpCrlDebug("TPCrlInfo::verifyWithContext root, no anchor, " + "index %u", index()); + crtn = CSSMERR_APPLETP_CRL_INVALID_ANCHOR_CERT; + } + else { + /* partial chain, no root, not verifiable by anchor */ + tpCrlDebug("TPCrlInfo::verifyWithContext no root, no anchor, " + "index %u", index()); + crtn = CSSMERR_APPLETP_CRL_NOT_TRUSTED; + } + if(!forCert || forCert->addStatusCode(crtn)) { + mVerifyState = CVS_Bad; + goto errOut; + } + } + + /* + * Step 4: policy verification on the returned cert group + * We need to (temporarily) assert the "leaf cert is a CA" flag + * here. + */ + outCertGroup.certAtIndex(0)->isLeaf(true); + crtn = tp_policyVerify(kCrlPolicy, + tpVerifyContext.alloc, + tpVerifyContext.clHand, + tpVerifyContext.cspHand, + &outCertGroup, + verifiedToRoot, + verifiedViaTrustSetting, + tpVerifyContext.actionFlags | CSSM_TP_ACTION_LEAF_IS_CA, + NULL, // sslOpts + NULL); // policyOpts, not currently used + if(crtn) { + tpCrlDebug(" ...verifyWithContext policy FAILURE CRL %u", + index()); + if(!forCert || forCert->addStatusCode(CSSMERR_APPLETP_CRL_POLICY_FAIL)) { + mVerifyState = CVS_Bad; + goto errOut; + } + } + + /* + * Step 5: recursively perform CRL verification on the certs + * gathered to verify this CRL. + * Only performed if this CRL is an indirect CRL or the caller + * explicitly told us to do this (i.e., caller is verifying a + * CRL, not a cert chain). + */ + if(isIndirectCrl || doCrlVerify) { + tpCrlDebug("verifyWithContext recursing to " + "tpVerifyCertGroupWithCrls"); + crtn = tpVerifyCertGroupWithCrls(tpVerifyContext, + outCertGroup); + if(crtn) { + tpCrlDebug(" ...verifyWithContext CRL reverify FAILURE CRL %u", + index()); + if(!forCert || forCert->addStatusCode(crtn)) { + mVerifyState = CVS_Bad; + goto errOut; + } + } + } + + tpCrlDebug(" ...verifyWithContext CRL %u SUCCESS", index()); + mVerifyState = CVS_Good; +errOut: + /* we own these, we free the DB records */ + certsToBeFreed.freeDbRecords(); + return crtn; +} + +/* + * Wrapper for verifyWithContext for use when evaluating a CRL + * "now" instead of at the time in TPVerifyContext.verifyTime. + * In this case, on entry, TPVerifyContext.verifyTime is the + * time at which a cert is being evaluated. + */ +CSSM_RETURN TPCrlInfo::verifyWithContextNow( + TPVerifyContext &tpVerifyContext, + TPCertInfo *forCert, // optional + bool doCrlVerify) +{ + CSSM_TIMESTRING ctxTime = tpVerifyContext.verifyTime; + CSSM_RETURN crtn = verifyWithContext(tpVerifyContext, forCert, doCrlVerify); + tpVerifyContext.verifyTime = ctxTime; + return crtn; +} + +/* + * Do I have the same issuer as the specified subject cert? Returns + * true if so. + */ +bool TPCrlInfo::hasSameIssuer( + const TPCertInfo &subject) +{ + assert(subject.issuerName() != NULL); + if(tpCompareCssmData(issuerName(), subject.issuerName())) { + return true; + } + else { + return false; + } +} + +/* + * Determine if specified cert has been revoked as of the + * provided time; a NULL timestring indicates "now". + * + * Assumes current CRL is verified good and that issuer names of + * the cert and CRL match. + * + * This duplicates similar logic in the CL, but to avoid re-parsing + * the subject cert (which we have parsed and cached), we just do it + * here. + * + * Possible errors are + * CSSMERR_TP_CERT_REVOKED + * CSSMERR_TP_CERT_SUSPENDED + * TBD + * + * Error status is added to subjectCert. + */ +CSSM_RETURN TPCrlInfo::isCertRevoked( + TPCertInfo &subjectCert, + CSSM_TIMESTRING verifyTime) +{ + assert(mVerifyState == CVS_Good); + CSSM_X509_TBS_CERTLIST_PTR tbs = &mX509Crl->tbsCertList; + + /* trivial case - empty CRL */ + if((tbs->revokedCertificates == NULL) || + (tbs->revokedCertificates->numberOfRevokedCertEntries == 0)) { + tpCrlDebug(" isCertRevoked: empty CRL at index %u", index()); + return CSSM_OK; + } + + /* is subject cert's serial number in this CRL? */ + CSSM_DATA_PTR subjSerial = NULL; + CSSM_RETURN crtn; + crtn = subjectCert.fetchField(&CSSMOID_X509V1SerialNumber, &subjSerial); + if(crtn) { + /* should never happen */ + tpErrorLog("TPCrlInfo:isCertRevoked: error fetching serial number\n"); + if(subjectCert.addStatusCode(crtn)) { + return crtn; + } + else { + /* allowed error - can't proceed; punt with success */ + return CSSM_OK; + } + } + /* subsequent errors to errOut: */ + + uint32 numEntries = tbs->revokedCertificates->numberOfRevokedCertEntries; + CSSM_X509_REVOKED_CERT_ENTRY_PTR entries = + tbs->revokedCertificates->revokedCertEntry; + crtn = CSSM_OK; + CFDateRef cfRevokedTime = NULL; + CFDateRef cfVerifyTime = NULL; + + for(uint32 dex=0; dexcertificateSerialNumber)) { + /* + * It's in there. Compare revocation time in the CRL to + * our caller-specified verifyTime. + */ + CSSM_X509_TIME_PTR xTime = &entry->revocationDate; + int rtn; + rtn = timeStringToCfDate((char *)xTime->time.Data, xTime->time.Length, + &cfRevokedTime); + if(rtn) { + tpErrorLog("fetchNotBeforeAfter: malformed revocationDate\n"); + } + else { + if(verifyTime != NULL) { + rtn = timeStringToCfDate((char *)verifyTime, strlen(verifyTime), + &cfVerifyTime); + } + else { + /* verify right now */ + cfVerifyTime = CFDateCreate(NULL, CFAbsoluteTimeGetCurrent()); + } + if((rtn == 0) && cfVerifyTime != NULL) { + CFComparisonResult res = CFDateCompare(cfVerifyTime, cfRevokedTime, NULL); + if(res == kCFCompareLessThan) { + /* cfVerifyTime < cfRevokedTime; I guess this one's OK */ + tpCrlDebug(" isCertRevoked: cert %u NOT YET REVOKED by CRL %u", + subjectCert.index(), index()); + break; + } + } + } + + /* + * REQUIRED TBD: parse the entry's extensions, specifically to + * get a reason. This will entail a bunch of new TP/cert specific + * CSSM_RETURNS. + * For now, just flag it revoked. + */ + crtn = CSSMERR_TP_CERT_REVOKED; + tpCrlDebug(" isCertRevoked: cert %u REVOKED by CRL %u", + subjectCert.index(), index()); + break; + } + } + + subjectCert.freeField(&CSSMOID_X509V1SerialNumber, subjSerial); + if(crtn && !subjectCert.addStatusCode(crtn)) { + return CSSM_OK; + } + if(cfRevokedTime) { + CFRelease(cfRevokedTime); + } + if(cfVerifyTime) { + CFRelease(cfVerifyTime); + } + return crtn; +} + +/*** + *** TPCrlGroup class + ***/ + +/* build empty group */ +TPCrlGroup::TPCrlGroup( + Allocator &alloc, + TPGroupOwner whoOwns) : + mAlloc(alloc), + mCrlInfo(NULL), + mNumCrls(0), + mSizeofCrlInfo(0), + mWhoOwns(whoOwns) +{ + /* nothing for now */ +} + +/* + * Construct from unordered, untrusted CSSM_CRLGROUP. Resulting + * TPCrlInfos are more or less in the same order as the incoming + * CRLs, though incoming CRLs are discarded if they don't parse. + * No verification of any sort is performed. + */ +TPCrlGroup::TPCrlGroup( + const CSSM_CRLGROUP *cssmCrlGroup, // optional + CSSM_CL_HANDLE clHand, + CSSM_CSP_HANDLE cspHand, + Allocator &alloc, + const char *verifyTime, // may be NULL + TPGroupOwner whoOwns) : + mAlloc(alloc), + mCrlInfo(NULL), + mNumCrls(0), + mSizeofCrlInfo(0), + mWhoOwns(whoOwns) +{ + /* verify input args */ + if((cssmCrlGroup == NULL) || (cssmCrlGroup->NumberOfCrls == 0)) { + return; + } + if(cspHand == CSSM_INVALID_HANDLE) { + CssmError::throwMe(CSSMERR_TP_INVALID_CSP_HANDLE); + } + if(clHand == CSSM_INVALID_HANDLE) { + CssmError::throwMe(CSSMERR_TP_INVALID_CL_HANDLE); + } + if(cssmCrlGroup->CrlGroupType != CSSM_CRLGROUP_DATA) { + CssmError::throwMe(CSSMERR_TP_INVALID_CERTGROUP); + } + switch(cssmCrlGroup->CrlType) { + case CSSM_CRL_TYPE_X_509v1: + case CSSM_CRL_TYPE_X_509v2: + break; + default: + CssmError::throwMe(CSSMERR_TP_UNKNOWN_FORMAT); + } + switch(cssmCrlGroup->CrlEncoding) { + case CSSM_CRL_ENCODING_BER: + case CSSM_CRL_ENCODING_DER: + break; + default: + CssmError::throwMe(CSSMERR_TP_UNKNOWN_FORMAT); + } + + /* + * Add remaining input certs to mCrlInfo. + */ + TPCrlInfo *crlInfo = NULL; + for(unsigned crlDex=0; crlDexNumberOfCrls; crlDex++) { + try { + crlInfo = new TPCrlInfo(clHand, + cspHand, + &cssmCrlGroup->GroupCrlList.CrlList[crlDex], + TIC_NoCopy, // don't copy data + verifyTime); + } + catch (...) { + /* just ignore this CRL */ + continue; + } + crlInfo->index(crlDex); + appendCrl(*crlInfo); + } +} + +/* + * Deletes all TPCrlInfo's if appropriate. + */ +TPCrlGroup::~TPCrlGroup() +{ + if(mWhoOwns == TGO_Group) { + unsigned i; + for(i=0; i here, but + * gdb is so lame that it doesn't even let one examine the contents + * of an array<> (or just about anything else in the STL). I prefer + * debuggability over saving a few lines of trivial code. + */ +void TPCrlGroup::appendCrl( + TPCrlInfo &crlInfo) +{ + if(mNumCrls == mSizeofCrlInfo) { + if(mSizeofCrlInfo == 0) { + /* appending to empty array */ + mSizeofCrlInfo = 1; + } + else { + mSizeofCrlInfo *= 2; + } + mCrlInfo = (TPCrlInfo **)mAlloc.realloc(mCrlInfo, + mSizeofCrlInfo * sizeof(TPCrlInfo *)); + } + mCrlInfo[mNumCrls++] = &crlInfo; +} + +TPCrlInfo *TPCrlGroup::crlAtIndex( + unsigned index) +{ + if(index > (mNumCrls - 1)) { + CssmError::throwMe(CSSMERR_TP_INTERNAL_ERROR); + } + return mCrlInfo[index]; +} + +TPCrlInfo &TPCrlGroup::removeCrlAtIndex( + unsigned index) // doesn't delete the cert, just + // removes it from our list +{ + if(index > (mNumCrls - 1)) { + CssmError::throwMe(CSSMERR_TP_INTERNAL_ERROR); + } + TPCrlInfo &rtn = *mCrlInfo[index]; + + /* removed requested element and compact remaining array */ + unsigned i; + for(i=index; i<(mNumCrls - 1); i++) { + mCrlInfo[i] = mCrlInfo[i+1]; + } + mNumCrls--; + return rtn; +} + +void TPCrlGroup::removeCrl( + TPCrlInfo &crlInfo) +{ + for(unsigned dex=0; dexhasSameIssuer(subject)) { + return crl; + } + } + return NULL; +} diff --git a/libsecurity_apple_x509_tp/lib/TPCrlInfo.h b/libsecurity_apple_x509_tp/lib/TPCrlInfo.h new file mode 100644 index 00000000..743b5850 --- /dev/null +++ b/libsecurity_apple_x509_tp/lib/TPCrlInfo.h @@ -0,0 +1,238 @@ +/* + * Copyright (c) 2002 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. + */ + + +/* + * TPCrlInfo.h - TP's private CRL and CRL group classes + * + * Written 9/25/2001 by Doug Mitchell. + */ + +#ifndef _TP_CRL_INFO_H_ +#define _TP_CRL_INFO_H_ + +#include +#include +#include +#include +#include "TPCertInfo.h" +#include "tpCrlVerify.h" + +/* + * Verification state of a TPCrlInfo. Verification refers to the process + * of cert chain validation from the CRL to a trusted root. Since this + * is a rather heavyweight operation, this is done on demand, when a given + * CRL is "believed to be" the appropriate one for a given cert. It + * is separate from not before/after verification, which is performed + * on the fly as needed. + */ +typedef enum { + CVS_Unknown, // initial default state + CVS_Good, // known good + CVS_Bad // known bad +} TPCrlVerifyState; + +/* + * Indicates where a particular CRL came from. Currently only used + * in the tpCrlVerify module. + */ +typedef enum { + CFW_Nowhere, // default, never returned + CFW_InGroup, // from incoming TPCrlGroup + CFW_DlDb, // verifyContext.dbList + CFW_LocalCache, // tpGlobalCrlCache + CFW_Net, // tpFetchCrlFromNet + /* probably others */ +} TPCrlFromWhere; + + +/* + * Class representing one CRL. The raw CRL data usually comes from + * a client (via incoming CSSM_TP_VERIFY_CONTEXT.Crls); in this case, we + * don't own the raw data and don't copy or free it. Caller can + * optionally specify that we copy (and own and eventually free) the raw cert data. + * Currently this is only done when we find a CRL in a DlDb. The constructor throws + * on any error (bad CRL data); subsequent to successful construction, no CSSM + * errors are thrown and it's guaranteed that the CRL is basically readable and + * successfully cached in the CL, and that we have a locally cached + * CSSM_X509_SIGNED_CRL and issuer name (in normalized encoded format). + */ +class TPCrlInfo : public TPClItemInfo +{ + NOCOPY(TPCrlInfo) +public: + /* + * No default constructor - this is the only way. + */ + TPCrlInfo( + CSSM_CL_HANDLE clHand, + CSSM_CSP_HANDLE cspHand, + const CSSM_DATA *crlData, + TPItemCopy copyCrlData, + const char *verifyTime); // NULL ==> time = right now + + /* frees mIssuerName, mCacheHand, mX509Crl via mClHand */ + ~TPCrlInfo(); + + /* + * The heavyweight "perform full verification" op. + * If doCrlVerify is true, we'll do an eventually recursive + * CRL verification test on the cert group we construct + * here to verify the CRL in question. This recursive + * verify is also done if the CRL is an indirect CRL. + * Currently, the doCrlVerifyFlag will be set false in the + * normal case of verifying a cert chain; in that case the + * various certs needed to verify the CRL are assumed to + * be a subset of the cert chain being verified, and CRL + * verification of that cert chain is being performed + * elsewhere. The caller would set doCrlVerify true when + * the top-level op is simply a CRL verify. + */ + CSSM_RETURN verifyWithContext( + TPVerifyContext &tpVerifyContext, + TPCertInfo *forCert, // optional + bool doCrlVerify = false); + + /* + * Wrapper for verifyWithContext for use when evaluating a CRL + * "now" instead of at the time in TPVerifyContext.verifyTime. + */ + CSSM_RETURN verifyWithContextNow( + TPVerifyContext &tpVerifyContext, + TPCertInfo *forCert, // optional + bool doCrlVerify = false); + + /* + * Do I have the same issuer as the specified subject cert? + * Returns true if so. + */ + bool hasSameIssuer( + const TPCertInfo &subject); + + /* + * Determine if specified cert has been revoked as of the + * provided time; a NULL timestring indicates "now". + * Assumes that the current CRL has been fully verified. + */ + CSSM_RETURN isCertRevoked( + TPCertInfo &subjectCert, + CSSM_TIMESTRING verifyTime); + + /* accessors */ + const CSSM_X509_SIGNED_CRL *x509Crl() { return mX509Crl; } + TPCrlVerifyState verifyState() { return mVerifyState; } + + const CSSM_DATA *uri() { return &mUri; } + void uri(const CSSM_DATA &uri); + + /* + * Ref count info maintained by caller (currently only in + * tpCrlVfy.cpp's global cache module). + */ + int mRefCount; + + /* used only by tpCrlVerify */ + TPCrlFromWhere mFromWhere; + + +private: + CSSM_X509_SIGNED_CRL *mX509Crl; + CSSM_DATA_PTR mCrlFieldToFree; + TPCrlVerifyState mVerifyState; + CSSM_RETURN mVerifyError; // only if mVerifyState = CVS_Bad + CSSM_DATA mUri; // if fetched from net + + void releaseResources(); + CSSM_RETURN parseExtensions( + TPVerifyContext &tpVerifyContext, + bool isPerEntry, + uint32 entryIndex, // if isPerEntry + const CSSM_X509_EXTENSIONS &extens, + TPCertInfo *forCert, // optional + bool &isIndirectCrl);// RETURNED + +}; + +/* + * TP's private CRL Group class. + */ +class TPCrlGroup +{ + NOCOPY(TPCrlGroup) +public: + /* construct empty CRL group */ + TPCrlGroup( + Allocator &alloc, + TPGroupOwner whoOwns); // if TGO_Group, we delete + + /* + * Construct from unordered, untrusted CSSM_CRLGROUP. Resulting + * TPCrlInfos are more or less in the same order as the incoming + * CRLs, though incoming CRLs are discarded if they don't parse. + * No verification of any sort is performed. + */ + TPCrlGroup( + const CSSM_CRLGROUP *cssmCrlGroup, // optional + CSSM_CL_HANDLE clHand, + CSSM_CSP_HANDLE cspHand, + Allocator &alloc, + const char *cssmTimeStr, // may be NULL + TPGroupOwner whoOwns); + + /* + * Deletes all TPCrlInfo's. + */ + ~TPCrlGroup(); + + /* add/remove/access TPCrlInfo's. */ + void appendCrl( + TPCrlInfo &crlInfo); // appends to end of mCertInfo + TPCrlInfo *crlAtIndex( + unsigned index); + TPCrlInfo &removeCrlAtIndex( + unsigned index); // doesn't delete the cert, just + // removes it from our list + void removeCrl( + TPCrlInfo &crlInfo); // ditto + + /* + * Convenience accessors for first and last CRL, only valid when we have + * at least one cert. + */ + TPCrlInfo *firstCrl(); + TPCrlInfo *lastCrl(); + + /* + * Find a CRL whose issuer matches specified subject cert. + * Returned CRL has not necessarily been verified. + */ + TPCrlInfo *findCrlForCert( + TPCertInfo &subject); + + Allocator &alloc() { return mAlloc; } + unsigned numCrls() { return mNumCrls; } + +private: + Allocator &mAlloc; + TPCrlInfo **mCrlInfo; // just an array of pointers + unsigned mNumCrls; // valid certs in certInfo + unsigned mSizeofCrlInfo; // mallocd space in certInfo + TPGroupOwner mWhoOwns; // if TGO_Group, we delete CRLs + // upon destruction +}; +#endif /* _TP_CRL_INFO_H_ */ + diff --git a/libsecurity_apple_x509_tp/lib/TPDatabase.cpp b/libsecurity_apple_x509_tp/lib/TPDatabase.cpp new file mode 100644 index 00000000..43176955 --- /dev/null +++ b/libsecurity_apple_x509_tp/lib/TPDatabase.cpp @@ -0,0 +1,506 @@ +/* + * Copyright (c) 2002-2009 Apple Inc. All Rights Reserved. + * + * The 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. + */ + + +/* + * TPDatabase.cpp - TP's DL/DB access functions. + * + * Created 10/9/2002 by Doug Mitchell. + */ + +#include +#include +#include /* private API */ +#include /* private SecTrustKeychainsGetMutex() */ +#include /* private SecInferLabelFromX509Name() */ +#include +#include "TPDatabase.h" +#include "tpdebugging.h" +#include "certGroupUtils.h" +#include "TPCertInfo.h" +#include "TPCrlInfo.h" +#include "tpCrlVerify.h" +#include "tpTime.h" + + +/* + * Given a DL/DB, look up cert by subject name. Subsequent + * certs can be found using the returned result handle. + */ +static CSSM_DB_UNIQUE_RECORD_PTR tpCertLookup( + CSSM_DL_DB_HANDLE dlDb, + const CSSM_DATA *subjectName, // DER-encoded + CSSM_HANDLE_PTR resultHand, // RETURNED + CSSM_DATA_PTR cert) // RETURNED +{ + CSSM_QUERY query; + 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 = + 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; + query.SelectionPredicate = &predicate; + query.QueryLimits.TimeLimit = 0; // FIXME - meaningful? + query.QueryLimits.SizeLimit = 1; // FIXME - meaningful? + query.QueryFlags = 0; // FIXME - used? + + CSSM_DL_DataGetFirst(dlDb, + &query, + resultHand, + NULL, // don't fetch attributes + cert, + &record); + + return record; +} + +/* + * 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. + * A true partialIssuerKey on return indicates that caller must deal + * 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. + */ +TPCertInfo *tpDbFindIssuerCert( + Allocator &alloc, + CSSM_CL_HANDLE clHand, + CSSM_CSP_HANDLE cspHand, + const TPClItemInfo *subjectItem, + const CSSM_DL_DB_LIST *dbList, + const char *verifyTime, // may be NULL + bool &partialIssuerKey) // RETURNED +{ + StLock _(SecTrustKeychainsGetMutex()); + + uint32 dbDex; + CSSM_HANDLE resultHand; + CSSM_DATA cert; + CSSM_DL_DB_HANDLE dlDb; + CSSM_DB_UNIQUE_RECORD_PTR record; + TPCertInfo *issuerCert = NULL; + bool foundIt; + TPCertInfo *expiredIssuer = NULL; + + partialIssuerKey = false; + if(dbList == NULL) { + return NULL; + } + for(dbDex=0; dbDexNumHandles; dbDex++) { + dlDb = dbList->DLDBHandle[dbDex]; + cert.Data = NULL; + cert.Length = 0; + resultHand = 0; + record = tpCertLookup(dlDb, + 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 + * (by placing it in issuerCert)... + */ + if(record != NULL) { + /* Found one */ + assert(cert.Data != NULL); + tpDbDebug("tpDbFindIssuerCert: found cert record %p", record); + issuerCert = NULL; + CSSM_RETURN crtn = CSSM_OK; + try { + issuerCert = new TPCertInfo(clHand, cspHand, &cert, TIC_CopyData, verifyTime); + } + catch(...) { + crtn = CSSMERR_TP_INVALID_CERTIFICATE; + } + + /* we're done with raw cert data */ + 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 + * 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 + * this situation in the switch below. + */ + tpDbDebug("tpDbFindIssuerCert: holding expired cert (1)"); + crtn = CSSM_CERT_STATUS_EXPIRED; + expiredIssuer = issuerCert; + expiredIssuer->dlDbHandle(dlDb); + expiredIssuer->uniqueRecord(record); + } + } + switch(crtn) { + case CSSM_OK: + break; + case CSSMERR_CSP_APPLE_PUBLIC_KEY_INCOMPLETE: + partialIssuerKey = true; + break; + default: + issuerCert = NULL; + if(crtn != CSSM_CERT_STATUS_EXPIRED) { + delete issuerCert; + CSSM_DL_FreeUniqueRecord(dlDb, record); + } + + /* + * 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, + resultHand, + NULL, // no attrs + &cert, + &record); + if(crtn) { + /* no more, done with this DB */ + assert(cert.Data == NULL); + break; + } + assert(cert.Data != NULL); + tpDbDebug("tpDbFindIssuerCert: found cert record %p", record); + + /* found one - does it verify subject? */ + try { + issuerCert = new TPCertInfo(clHand, cspHand, &cert, TIC_CopyData, + verifyTime); + } + catch(...) { + crtn = CSSMERR_TP_INVALID_CERTIFICATE; + } + /* we're done with raw cert data */ + tpFreePluginMemory(dlDb.DLHandle, cert.Data); + cert.Data = NULL; + cert.Length = 0; + + if(crtn == CSSM_OK) { + crtn = subjectItem->verifyWithIssuer(issuerCert); + } + + /* temporal validity check, again */ + if((crtn == CSSM_OK) && (expiredIssuer == NULL)) { + if(issuerCert->isExpired() || issuerCert->isNotValidYet()) { + tpDbDebug("tpDbFindIssuerCert: holding expired cert (2)"); + crtn = CSSM_CERT_STATUS_EXPIRED; + expiredIssuer = issuerCert; + expiredIssuer->dlDbHandle(dlDb); + expiredIssuer->uniqueRecord(record); + } + } + + foundIt = false; + switch(crtn) { + case CSSM_OK: + foundIt = true; + break; + case CSSMERR_CSP_APPLE_PUBLIC_KEY_INCOMPLETE: + partialIssuerKey = true; + foundIt = true; + break; + default: + break; + } + if(foundIt) { + /* yes! */ + break; + } + if(crtn != CSSM_CERT_STATUS_EXPIRED) { + delete issuerCert; + CSSM_DL_FreeUniqueRecord(dlDb, record); + } + issuerCert = NULL; + } /* searching subsequent records */ + } /* switch verify */ + + if(record != NULL) { + /* NULL record --> end of search --> DB auto-aborted */ + crtn = CSSM_DL_DataAbortQuery(dlDb, resultHand); + assert(crtn == CSSM_OK); + } + if(issuerCert != NULL) { + /* successful return */ + tpDbDebug("tpDbFindIssuer: returning record %p", record); + issuerCert->dlDbHandle(dlDb); + issuerCert->uniqueRecord(record); + if(expiredIssuer != NULL) { + /* We found a replacement */ + tpDbDebug("tpDbFindIssuer: discarding expired cert"); + expiredIssuer->freeUniqueRecord(); + delete expiredIssuer; + } + return issuerCert; + } + } /* tpCertLookup, i.e., CSSM_DL_DataGetFirst, succeeded */ + else { + assert(cert.Data == NULL); + assert(resultHand == 0); + } + } /* main loop searching dbList */ + + if(expiredIssuer != NULL) { + /* OK, we'll take this one */ + tpDbDebug("tpDbFindIssuer: taking expired cert after all, record %p", + expiredIssuer->uniqueRecord()); + return expiredIssuer; + } + /* issuer not found */ + return NULL; +} + +/* + * 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 + +static CSSM_DB_UNIQUE_RECORD_PTR tpCrlLookup( + CSSM_DL_DB_HANDLE dlDb, + const CSSM_DATA *issuerName, // DER-encoded + CSSM_TIMESTRING verifyTime, // may be NULL, implies "now" + CSSM_HANDLE_PTR resultHand, // RETURNED + CSSM_DATA_PTR crl) // RETURNED +{ + CSSM_QUERY query; + 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 = + 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 */ + int rtn = tpTimeToCssmTimestring(verifyTime, strlen(verifyTime), timeStr); + if(rtn) { + tpErrorLog("tpCrlLookup: Invalid VerifyTime string\n"); + return NULL; + } + } + else { + /* right now */ + StLock _(tpTimeLock()); + timeAtNowPlus(0, TIME_CSSM, timeStr); + } + 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; + pred[1].Attribute.Info.Label.AttributeName = (char*) "NextUpdate"; + 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"; + pred[2].Attribute.Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_BLOB; + 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 + query.NumSelectionPredicates = 3; + #else + query.NumSelectionPredicates = 1; + #endif + query.SelectionPredicate = pred; + query.QueryLimits.TimeLimit = 0; // FIXME - meaningful? + query.QueryLimits.SizeLimit = 1; // FIXME - meaningful? + query.QueryFlags = 0; // FIXME - used? + + CSSM_DL_DataGetFirst(dlDb, + &query, + resultHand, + NULL, // don't fetch attributes + crl, + &record); + return record; +} + +/* + * 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. + */ +TPCrlInfo *tpDbFindIssuerCrl( + TPVerifyContext &vfyCtx, + const CSSM_DATA &issuer, + TPCertInfo &forCert) +{ + StLock _(SecTrustKeychainsGetMutex()); + + uint32 dbDex; + CSSM_HANDLE resultHand; + 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; + } + for(dbDex=0; dbDexNumHandles; dbDex++) { + dlDb = dbList->DLDBHandle[dbDex]; + crl.Data = NULL; + crl.Length = 0; + record = tpCrlLookup(dlDb, + &issuer, + 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 + * (by placing it in issuerCert)... + */ + if(record != NULL) { + /* Found one */ + assert(crl.Data != NULL); + issuerCrl = new TPCrlInfo(vfyCtx.clHand, + vfyCtx.cspHand, + &crl, + TIC_CopyData, + vfyCtx.verifyTime); + /* we're done with raw CRL data */ + /* 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. + */ + for(;;) { + crl.Data = NULL; + crl.Length = 0; + crtn = CSSM_DL_DataGetNext(dlDb, + resultHand, + NULL, // no attrs + &crl, + &record); + if(crtn) { + /* no more, done with this DB */ + assert(crl.Data == NULL); + break; + } + assert(crl.Data != NULL); + + /* found one - is it any good? */ + issuerCrl = new TPCrlInfo(vfyCtx.clHand, + vfyCtx.cspHand, + &crl, + TIC_CopyData, + vfyCtx.verifyTime); + /* we're done with raw CRL data */ + /* 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; + + CSSM_DL_FreeUniqueRecord(dlDb, record); + + crtn = issuerCrl->verifyWithContextNow(vfyCtx, &forCert); + if(crtn == CSSM_OK) { + /* yes! */ + break; + } + delete issuerCrl; + issuerCrl = NULL; + } /* searching subsequent records */ + } /* verify fail */ + /* else success! */ + + if(issuerCrl != NULL) { + /* successful return */ + CSSM_DL_DataAbortQuery(dlDb, resultHand); + tpDebug("tpDbFindIssuerCrl: found CRL record %p", record); + return issuerCrl; + } + } /* tpCrlLookup, i.e., CSSM_DL_DataGetFirst, succeeded */ + else { + assert(crl.Data == NULL); + } + /* in any case, abort the query for this db */ + CSSM_DL_DataAbortQuery(dlDb, resultHand); + + } /* main loop searching dbList */ + + /* issuer not found */ + return NULL; +} + diff --git a/libsecurity_apple_x509_tp/lib/TPDatabase.h b/libsecurity_apple_x509_tp/lib/TPDatabase.h new file mode 100644 index 00000000..a7ad4369 --- /dev/null +++ b/libsecurity_apple_x509_tp/lib/TPDatabase.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2002 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. + */ + + +/* + * TPDatabase.h - TP's DL/DB access functions. + * + * Created 10/9/2002 by Doug Mitchell. + */ + +#ifndef _TP_DATABASE_H_ +#define _TP_DATABASE_H_ + +#include +#include +#include "TPCertInfo.h" + +#ifdef __cplusplus +extern "C" { +#endif + +TPCertInfo *tpDbFindIssuerCert( + Allocator &alloc, + CSSM_CL_HANDLE clHand, + CSSM_CSP_HANDLE cspHand, + const TPClItemInfo *subjectItem, + const CSSM_DL_DB_LIST *dbList, + const char *verifyTime, // may be NULL + bool &partialIssuerKey); // RETURNED + +/* + * 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. + */ +class TPCrlInfo; +class TPVerifyContext; + +TPCrlInfo *tpDbFindIssuerCrl( + TPVerifyContext &vfyCtx, + const CSSM_DATA &issuer, + TPCertInfo &forCert); + +#if WRITE_FETCHED_CRLS_TO_DB +/* + * Store a CRL in a DLDB. + */ +CSSM_RETURN tpDbStoreCrl( + TPCrlInfo &crl, + CSSM_DL_DB_HANDLE &dlDb); + +#endif /* WRITE_FETCHED_CRLS_TO_DB */ + +#ifdef __cplusplus +} +#endif + +#endif /* _TP_DATABASE_H_ */ diff --git a/libsecurity_apple_x509_tp/lib/TPNetwork.cpp b/libsecurity_apple_x509_tp/lib/TPNetwork.cpp new file mode 100644 index 00000000..377be276 --- /dev/null +++ b/libsecurity_apple_x509_tp/lib/TPNetwork.cpp @@ -0,0 +1,511 @@ +/* + * 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'). + * 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. + */ + + +/* + * TPNetwork.h - LDAP, HTTP and (eventually) other network tools + */ + +#include "TPNetwork.h" +#include "tpdebugging.h" +#include "tpTime.h" +#include "cuEnc64.h" +#include +#include +#include +#include +#include + +#define CA_ISSUERS_OID OID_PKIX, 0x30, 0x02 +#define CA_ISSUERS_OID_LEN OID_PKIX_LENGTH + 2 + +static const uint8 OID_CA_ISSUERS[] = {CA_ISSUERS_OID}; +const CSSM_OID CSSMOID_CA_ISSUERS = {CA_ISSUERS_OID_LEN, (uint8 *)OID_CA_ISSUERS}; + +typedef enum { + LT_Crl = 1, + LT_Cert +} LF_Type; + +static CSSM_RETURN tpDecodeCert( + Allocator &alloc, + CSSM_DATA &rtnBlob) // will be reallocated if needed +{ + const unsigned char *inbuf = (const unsigned char *)rtnBlob.Data; + unsigned inlen = rtnBlob.Length; + unsigned char *outbuf = NULL; + unsigned outlen = 0; + CSSM_RETURN ortn = cuConvertPem(inbuf, inlen, &outbuf, &outlen); + + if(ortn == 0 && outbuf != NULL) { + /* Decoded result needs to be malloc'd via input allocator */ + unsigned char *rtnP = (unsigned char *) alloc.malloc(outlen); + if(rtnP != NULL) { + memcpy(rtnP, outbuf, outlen); + rtnBlob.Data = rtnP; + rtnBlob.Length = outlen; + } + free(outbuf); + alloc.free((void *)inbuf); + } + return ortn; +} + +static CSSM_RETURN tpFetchViaNet( + const CSSM_DATA &url, + const CSSM_DATA *issuer, // optional + LF_Type lfType, + CSSM_TIMESTRING verifyTime, // CRL only + Allocator &alloc, + CSSM_DATA &rtnBlob) // mallocd and RETURNED +{ + if(lfType == LT_Crl) { + return ocspdCRLFetch(alloc, url, issuer, + true, true, // cache r/w both enable + verifyTime, rtnBlob); + } + else { + CSSM_RETURN result = ocspdCertFetch(alloc, url, rtnBlob); + if(result == CSSM_OK) { + /* The data might be in PEM format; if so, convert it here */ + (void)tpDecodeCert(alloc, rtnBlob); + } + return result; + } +} + +static CSSM_RETURN tpCrlViaNet( + const CSSM_DATA &url, + const CSSM_DATA *issuer, // optional, only if cert and CRL have same issuer + TPVerifyContext &vfyCtx, + TPCertInfo &forCert, // for verifyWithContext + TPCrlInfo *&rtnCrl) +{ + TPCrlInfo *crl = NULL; + CSSM_DATA crlData; + CSSM_RETURN crtn; + Allocator &alloc = Allocator::standard(); + char cssmTime[CSSM_TIME_STRLEN+1]; + + rtnCrl = NULL; + + /* verifyTime: we want a CRL that's valid right now. */ + { + StLock _(tpTimeLock()); + timeAtNowPlus(0, TIME_CSSM, cssmTime); + } + + crtn = tpFetchViaNet(url, issuer, LT_Crl, cssmTime, alloc, crlData); + if(crtn) { + return crtn; + } + try { + crl = new TPCrlInfo(vfyCtx.clHand, + vfyCtx.cspHand, + &crlData, + TIC_CopyData, + NULL); // verifyTime = Now + } + catch(...) { + alloc.free(crlData.Data); + + /* + * There is a slight possibility of recovering from this error. In case + * the CRL came from disk cache, flush the cache and try to get the CRL + * from the net. + */ + tpDebug(" bad CRL; flushing from cache and retrying"); + ocspdCRLFlush(url); + crtn = tpFetchViaNet(url, issuer, LT_Crl, cssmTime, alloc, crlData); + if(crtn == CSSM_OK) { + try { + crl = new TPCrlInfo(vfyCtx.clHand, + vfyCtx.cspHand, + &crlData, + TIC_CopyData, + NULL); + tpDebug(" RECOVERY: good CRL obtained from net"); + } + catch(...) { + alloc.free(crlData.Data); + tpDebug(" bad CRL; recovery FAILED (1)"); + return CSSMERR_APPLETP_CRL_NOT_FOUND; + } + } + else { + /* it was in cache but we can't find it on the net */ + tpDebug(" bad CRL; recovery FAILED (2)"); + return CSSMERR_APPLETP_CRL_NOT_FOUND; + } + } + alloc.free(crlData.Data); + + /* + * Full CRL verify. + * The verify time in the TPVerifyContext is the time at which various + * entities (CRL and its own cert chain) are to be verified; that's + * NULL for "right now". The current vfyCtx.verifyTime is the time at + * which the cert's revocation status to be determined; this call to + * verifyWithContextNow() doesn't do that. + */ + crtn = crl->verifyWithContextNow(vfyCtx, &forCert); + if(crtn == CSSM_OK) { + crl->uri(url); + } + else { + delete crl; + crl = NULL; + } + rtnCrl = crl; + return crtn; +} + +static CSSM_RETURN tpIssuerCertViaNet( + const CSSM_DATA &url, + CSSM_CL_HANDLE clHand, + CSSM_CSP_HANDLE cspHand, + const char *verifyTime, + TPCertInfo &subject, + TPCertInfo *&rtnCert) +{ + TPCertInfo *issuer = NULL; + CSSM_DATA certData; + CSSM_RETURN crtn; + Allocator &alloc = Allocator::standard(); + + crtn = tpFetchViaNet(url, NULL, LT_Cert, NULL, alloc, certData); + if(crtn) { + tpErrorLog("tpIssuerCertViaNet: net fetch failed\n"); + return CSSMERR_APPLETP_CERT_NOT_FOUND_FROM_ISSUER; + } + try { + issuer = new TPCertInfo(clHand, + cspHand, + &certData, + TIC_CopyData, + verifyTime); + } + catch(...) { + tpErrorLog("tpIssuerCertViaNet: bad cert via net fetch\n"); + alloc.free(certData.Data); + rtnCert = NULL; + return CSSMERR_APPLETP_BAD_CERT_FROM_ISSUER; + } + alloc.free(certData.Data); + + /* subject/issuer match? */ + if(!issuer->isIssuerOf(subject)) { + tpErrorLog("tpIssuerCertViaNet: wrong issuer cert via net fetch\n"); + crtn = CSSMERR_APPLETP_BAD_CERT_FROM_ISSUER; + } + else { + /* yep, do a sig verify */ + crtn = subject.verifyWithIssuer(issuer); + if(crtn) { + tpErrorLog("tpIssuerCertViaNet: sig verify fail for cert via net " + "fetch\n"); + crtn = CSSMERR_APPLETP_BAD_CERT_FROM_ISSUER; + } + } + if(crtn) { + assert(issuer != NULL); + delete issuer; + issuer = NULL; + } + rtnCert = issuer; + return crtn; +} + +/* + * Fetch a CRL or a cert via a GeneralNames. + * Shared by cert and CRL code to avoid duplicating GeneralNames traversal + * code, despite the awkward interface for this function. + */ +static CSSM_RETURN tpFetchViaGeneralNames( + const CE_GeneralNames *names, + TPCertInfo &forCert, + const CSSM_DATA *issuer, // optional, and only for CRLs + TPVerifyContext *verifyContext, // only for CRLs + CSSM_CL_HANDLE clHand, // only for certs + CSSM_CSP_HANDLE cspHand, // only for certs + const char *verifyTime, // optional + /* exactly one must be non-NULL, that one is returned */ + TPCertInfo **certInfo, + TPCrlInfo **crlInfo) +{ + assert(certInfo || crlInfo); + assert(!certInfo || !crlInfo); + 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; + } + if(certInfo) { + tpDebug(" fetching cert via net"); + crtn = tpIssuerCertViaNet(name->name, + clHand, + cspHand, + verifyTime, + forCert, + *certInfo); + } + else { + tpDebug(" fetching CRL via net"); + assert(verifyContext != NULL); + crtn = tpCrlViaNet(name->name, + issuer, + *verifyContext, + forCert, + *crlInfo); + } + switch(crtn) { + case CSSM_OK: + case CSSMERR_CSP_APPLE_PUBLIC_KEY_INCOMPLETE: // caller handles + return crtn; + default: + break; + } + /* not found/no good; try again */ + break; + default: + tpCrlDebug(" tpFetchCrlFromNet: unknown" + "nameType (%u)", (unsigned)name->nameType); + break; + } /* switch nameType */ + } /* for each name */ + if(certInfo) { + return CSSMERR_TP_CERTGROUP_INCOMPLETE; + } + else { + return CSSMERR_APPLETP_CRL_NOT_FOUND; + } +} + +/* + * Fetch CRL(s) from specified cert if the cert has a cRlDistributionPoint + * extension. + * + * Return values: + * CSSM_OK - found and returned fully verified CRL + * CSSMERR_APPLETP_CRL_NOT_FOUND - no CRL in cRlDistributionPoint + * Anything else - gross error, typically from last LDAP/HTTP attempt + * + * FIXME - this whole mechanism sort of falls apart if verifyContext.verifyTime + * is non-NULL. How are we supposed to get the CRL which was valid at + * a specified time in the past? + */ +CSSM_RETURN tpFetchCrlFromNet( + TPCertInfo &cert, + TPVerifyContext &vfyCtx, + TPCrlInfo *&crl) // RETURNED +{ + /* does the cert have a cRlDistributionPoint? */ + CSSM_DATA_PTR fieldValue; // mallocd by CL + + CSSM_RETURN crtn = cert.fetchField(&CSSMOID_CrlDistributionPoints, + &fieldValue); + switch(crtn) { + case CSSM_OK: + break; + case CSSMERR_CL_NO_FIELD_VALUES: + /* field not present */ + return CSSMERR_APPLETP_CRL_NOT_FOUND; + default: + /* gross error */ + return crtn; + } + if(fieldValue->Length != sizeof(CSSM_X509_EXTENSION)) { + tpErrorLog("tpFetchCrlFromNet: malformed CSSM_FIELD"); + return CSSMERR_TP_UNKNOWN_FORMAT; + } + CSSM_X509_EXTENSION *cssmExt = (CSSM_X509_EXTENSION *)fieldValue->Data; + CE_CRLDistPointsSyntax *dps = + (CE_CRLDistPointsSyntax *)cssmExt->value.parsedValue; + TPCrlInfo *rtnCrl = NULL; + + /* default return if we don't find anything */ + crtn = CSSMERR_APPLETP_CRL_NOT_FOUND; + for(unsigned dex=0; dexnumDistPoints; dex++) { + CE_CRLDistributionPoint *dp = &dps->distPoints[dex]; + if(dp->distPointName == NULL) { + continue; + } + /* + * FIXME if this uses an indirect CRL, we need to follow the + * crlIssuer field... TBD. + */ + switch(dp->distPointName->nameType) { + case CE_CDNT_NameRelativeToCrlIssuer: + /* not yet */ + tpErrorLog("tpFetchCrlFromNet: " + "CE_CDNT_NameRelativeToCrlIssuer not implemented\n"); + break; + + case CE_CDNT_FullName: + { + /* + * Since we don't support indirect CRLs (yet), we always pass + * the cert-to-be-verified's issuer as the CRL issuer for + * cache lookup. + */ + CE_GeneralNames *names = dp->distPointName->dpn.fullName; + crtn = tpFetchViaGeneralNames(names, + cert, + cert.issuerName(), + &vfyCtx, + 0, // clHand, use the one in vfyCtx + 0, // cspHand, ditto + vfyCtx.verifyTime, + NULL, + &rtnCrl); + break; + } /* CE_CDNT_FullName */ + + default: + /* not yet */ + tpErrorLog("tpFetchCrlFromNet: " + "unknown distPointName->nameType (%u)\n", + (unsigned)dp->distPointName->nameType); + break; + } /* switch distPointName->nameType */ + if(crtn == CSSM_OK) { + /* i.e., tpFetchViaGeneralNames SUCCEEDED */ + break; + } + } /* for each distPoints */ + + cert.freeField(&CSSMOID_CrlDistributionPoints, fieldValue); + if(crtn == CSSM_OK) { + assert(rtnCrl != NULL); + crl = rtnCrl; + } + return crtn; +} + +/* + * Fetch issuer cert of specified cert if the cert has an issuerAltName + * with a URI. If non-NULL cert is returned, it has passed subject/issuer + * name comparison and signature verification with target cert. + * + * Return values: + * CSSM_OK - found and returned issuer cert + * CSSMERR_TP_CERTGROUP_INCOMPLETE - no URL in issuerAltName + * CSSMERR_CSP_APPLE_PUBLIC_KEY_INCOMPLETE - found and returned issuer + * cert, but signature verification needs subsequent retry. + * Anything else - gross error, typically from last LDAP/HTTP attempt + */ +CSSM_RETURN tpFetchIssuerFromNet( + TPCertInfo &subject, + CSSM_CL_HANDLE clHand, + CSSM_CSP_HANDLE cspHand, + const char *verifyTime, + TPCertInfo *&issuer) // RETURNED +{ + CSSM_OID_PTR fieldOid = NULL; + CSSM_DATA_PTR fieldValue = NULL; // mallocd by CL + CSSM_RETURN crtn; + bool hasAIA = false; + + /* look for the Authority Info Access extension first */ + fieldOid = (CSSM_OID_PTR)&CSSMOID_AuthorityInfoAccess; + crtn = subject.fetchField(fieldOid, + &fieldValue); + hasAIA = (crtn == CSSM_OK); + if (!hasAIA) { + /* fall back to Issuer Alternative Name extension */ + fieldOid = (CSSM_OID_PTR)&CSSMOID_IssuerAltName; + crtn = subject.fetchField(fieldOid, + &fieldValue); + } + switch(crtn) { + case CSSM_OK: + break; + case CSSMERR_CL_NO_FIELD_VALUES: + /* field not present */ + return CSSMERR_TP_CERTGROUP_INCOMPLETE; + default: + /* gross error */ + return crtn; + } + if(fieldValue->Length != sizeof(CSSM_X509_EXTENSION)) { + tpPolicyError("tpFetchIssuerFromNet: malformed CSSM_FIELD"); + return CSSMERR_TP_UNKNOWN_FORMAT; + } + CSSM_X509_EXTENSION *cssmExt = (CSSM_X509_EXTENSION *)fieldValue->Data; + CE_GeneralNames *names = (CE_GeneralNames *)cssmExt->value.parsedValue; + TPCertInfo *rtnCert = NULL; + if (hasAIA) { /* authority info access */ + CE_AuthorityInfoAccess *access = (CE_AuthorityInfoAccess *)cssmExt->value.parsedValue; + for (uint32 index = 0; access && index < access->numAccessDescriptions; index++) { + CE_AccessDescription *accessDesc = &access->accessDescriptions[index]; + CSSM_OID_PTR methodOid = (CSSM_OID_PTR)&accessDesc->accessMethod; + /* look for the CA Issuers method */ + if(methodOid->Data != NULL && methodOid->Length == CSSMOID_CA_ISSUERS.Length && + !memcmp(methodOid->Data, CSSMOID_CA_ISSUERS.Data, methodOid->Length)) { + CE_GeneralNames aiaNames = { 1, &accessDesc->accessLocation }; + /* attempt to fetch cert from named location */ + crtn = tpFetchViaGeneralNames(&aiaNames, + subject, + NULL, // issuer - not used + NULL, // verifyContext + clHand, + cspHand, + verifyTime, + &rtnCert, + NULL); + if (crtn == CSSM_OK || + crtn == CSSMERR_CSP_APPLE_PUBLIC_KEY_INCOMPLETE) { + break; // got one + } + } + } + subject.freeField(fieldOid, fieldValue); + } + else { /* issuer alt name */ + crtn = tpFetchViaGeneralNames(names, + subject, + NULL, // issuer - not used + NULL, // verifyContext + clHand, + cspHand, + verifyTime, + &rtnCert, + NULL); + subject.freeField(fieldOid, fieldValue); + } + switch(crtn) { + case CSSM_OK: + case CSSMERR_CSP_APPLE_PUBLIC_KEY_INCOMPLETE: + issuer = rtnCert; + break; + default: + break; + } + return crtn; +} + + diff --git a/libsecurity_apple_x509_tp/lib/TPNetwork.h b/libsecurity_apple_x509_tp/lib/TPNetwork.h new file mode 100644 index 00000000..6bc97a2d --- /dev/null +++ b/libsecurity_apple_x509_tp/lib/TPNetwork.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2002 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. + */ + + +/* + * TPNetwork.h - LDAP (and eventually) other network tools + * + * Written 10/3/2002 by Doug Mitchell. + */ + +#ifndef _TP_NETWORK_H_ +#define _TP_NETWORK_H_ + +#include +#include "TPCertInfo.h" +#include "TPCrlInfo.h" + +extern "C" { + +/* + * Fetch CRL(s) for specified cert if the cert has a cRlDistributionPoint + * extension. If a non-NULL CRL is returned, it has passed verification + * with specified TPVerifyContext. + * The common, trivial failure of "no URI in a cRlDistributionPoint + * extension" is indicated by CSSMERR_APPLETP_CRL_NOT_FOUND. + */ +extern CSSM_RETURN tpFetchCrlFromNet( + TPCertInfo &cert, + TPVerifyContext &verifyContext, + TPCrlInfo *&crl); // RETURNED + +/* + * Fetch issuer cert of specified cert if the cert has an issuerAltName + * with a URI. If non-NULL cert is returned, it has passed subject/issuer + * name comparison and signature verification with target cert. + * The common, trivial failure of "no URI in an issuerAltName + * extension" is indicated by CSSMERR_TP_CERTGROUP_INCOMPLETE. + * A CSSMERR_CSP_APPLE_PUBLIC_KEY_INCOMPLETE return indicates that + * subsequent signature verification is needed. + */ +extern CSSM_RETURN tpFetchIssuerFromNet( + TPCertInfo &subject, + CSSM_CL_HANDLE clHand, + CSSM_CSP_HANDLE cspHand, + const char *verifyTime, + TPCertInfo *&issuer); // RETURNED + +} + +#endif /* TP_NETWORK_H_ */ diff --git a/libsecurity_apple_x509_tp/lib/certGroupUtils.cpp b/libsecurity_apple_x509_tp/lib/certGroupUtils.cpp new file mode 100644 index 00000000..06b00d34 --- /dev/null +++ b/libsecurity_apple_x509_tp/lib/certGroupUtils.cpp @@ -0,0 +1,618 @@ +/* + * 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. + */ + + +/* + certGroupUtils.cpp + + Created 10/9/2000 by Doug Mitchell. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "certGroupUtils.h" +#include "tpdebugging.h" +#include "tpTime.h" + +#include /* for memcmp */ + + +/* + * Copy one CSSM_DATA to another, mallocing destination. + */ +void tpCopyCssmData( + Allocator &alloc, + const CSSM_DATA *src, + CSSM_DATA_PTR dst) +{ + dst->Data = (uint8 *)alloc.malloc(src->Length); + dst->Length = src->Length; + memmove(dst->Data, src->Data, src->Length); +} + +/* + * Malloc a CSSM_DATA, copy another one to it. + */ +CSSM_DATA_PTR tpMallocCopyCssmData( + Allocator &alloc, + const CSSM_DATA *src) +{ + CSSM_DATA_PTR dst = (CSSM_DATA_PTR)alloc.malloc(sizeof(CSSM_DATA)); + tpCopyCssmData(alloc, src, dst); + return dst; +} + +/* + * Free the data referenced by a CSSM data, and optionally, the struct itself. + */ +void tpFreeCssmData( + Allocator &alloc, + CSSM_DATA_PTR data, + CSSM_BOOL freeStruct) +{ + if(data == NULL) { + return; + } + if(data->Length != 0) { + tpFree(alloc, data->Data); + } + if(freeStruct) { + tpFree(alloc, data); + } + else { + data->Length = 0; + data->Data = NULL; + } +} + +/* + * Compare two CSSM_DATAs, return CSSM_TRUE if identical. + */ +CSSM_BOOL tpCompareCssmData( + const CSSM_DATA *data1, + const CSSM_DATA *data2) +{ + if((data1 == NULL) || (data1->Data == NULL) || + (data2 == NULL) || (data2->Data == NULL) || + (data1->Length != data2->Length)) { + return CSSM_FALSE; + } + if(data1->Length != data2->Length) { + return CSSM_FALSE; + } + if(memcmp(data1->Data, data2->Data, data1->Length) == 0) { + return CSSM_TRUE; + } + else { + return CSSM_FALSE; + } +} + +/* + * Free memory via specified plugin's app-level allocator + */ +void tpFreePluginMemory( + CSSM_HANDLE hand, + void *p) +{ + CSSM_API_MEMORY_FUNCS memFuncs; + CSSM_RETURN crtn = CSSM_GetAPIMemoryFunctions(hand, &memFuncs); + if(crtn) { + tpErrorLog("CSSM_GetAPIMemoryFunctions failure\n"); + /* oh well, leak and continue */ + return; + } + memFuncs.free_func(p, memFuncs.AllocRef); +} + +/* + * Obtain the public key blob from a cert. + */ +CSSM_DATA_PTR tp_CertGetPublicKey( + TPCertInfo *cert, + CSSM_DATA_PTR *valueToFree) // used in tp_CertFreePublicKey +{ + CSSM_RETURN crtn; + CSSM_DATA_PTR val; + CSSM_X509_SUBJECT_PUBLIC_KEY_INFO *keyInfo; + + *valueToFree = NULL; + crtn = cert->fetchField(&CSSMOID_X509V1SubjectPublicKeyCStruct, &val); + if(crtn) { + tpErrorLog("Error on CSSM_CL_CertGetFirstFieldValue(PublicKeyCStruct)\n"); + return NULL; + } + *valueToFree = val; + keyInfo = (CSSM_X509_SUBJECT_PUBLIC_KEY_INFO *)val->Data; + return &keyInfo->subjectPublicKey; +} + +void tp_CertFreePublicKey( + CSSM_CL_HANDLE clHand, + CSSM_DATA_PTR value) +{ + CSSM_CL_FreeFieldValue(clHand, &CSSMOID_X509V1SubjectPublicKeyCStruct, value); +} + +/* + * Obtain signature algorithm info from a cert. + */ +CSSM_X509_ALGORITHM_IDENTIFIER_PTR tp_CertGetAlgId( + TPCertInfo *cert, + CSSM_DATA_PTR *valueToFree) // used in tp_CertFreeAlgId +{ + CSSM_RETURN crtn; + CSSM_DATA_PTR val; + + *valueToFree = NULL; + crtn = cert->fetchField(&CSSMOID_X509V1SignatureAlgorithm, &val); + if(crtn) { + tpErrorLog("Error on fetchField(CSSMOID_X509V1SignatureAlgorithm)\n"); + return NULL; + } + *valueToFree = val; + return (CSSM_X509_ALGORITHM_IDENTIFIER_PTR)val->Data; +} + +void tp_CertFreeAlgId( + CSSM_CL_HANDLE clHand, + CSSM_DATA_PTR value) +{ + CSSM_CL_FreeFieldValue(clHand, &CSSMOID_X509V1SignatureAlgorithm, value); +} + +/* + * Determine if two certs - passed in encoded form - are equivalent. + */ +CSSM_BOOL tp_CompareCerts( + const CSSM_DATA *cert1, + const CSSM_DATA *cert2) +{ + return tpCompareCssmData(cert1, cert2); +} + +/* + * Convert a C string to lower case in place. NULL terminator not needed. + */ +void tpToLower( + char *str, + unsigned strLen) +{ + for(unsigned i=0; i= MAX_DNS_COMP_LEN. + * Returns true if a component was found. + */ +static bool tpNextDnsComp( + const char *inBuf, + uint32 &inBufLen, // IN/OUT + char *outBuf, // component RETURNED here + uint32 &outBufLen) // RETURNED length of component +{ + outBufLen = 0; + if(inBufLen == 0) { + return false; + } + + /* skip over leading '.' */ + if(*inBuf == '.') { + inBuf++; + if(--inBufLen == 0) { + return false; + } + } + + /* copy chars until out of data or next '.' found */ + do { + if(*inBuf == '.') { + break; + } + *outBuf++ = *inBuf++; + inBufLen--; + outBufLen++; + if(outBufLen >= MAX_DNS_COMP_LEN) { + /* abort */ + break; + } + } while(inBufLen != 0); + if(outBufLen) { + return true; + } + else { + return false; + } +} + +/* + * Find location of specified substring in given bigstring. Returns + * pointer to start of substring in bigstring, else returns NULL. + */ +static const char *tpSubStr( + const char *bigstr, + uint32 bigstrLen, + const char *substr, + uint32 substrLen) +{ + /* stop searching substrLen chars before end of bigstr */ + const char *endBigStr = bigstr + bigstrLen - substrLen; + for( ; bigstr <= endBigStr; ) { + if(*bigstr == *substr) { + /* first char match - remainder? */ + if(substrLen == 1) { + /* don't count on memcmp(a,b,0) */ + return bigstr; + } + if(!memcmp(bigstr+1, substr+1, substrLen - 1)) { + return bigstr; + } + } + bigstr++; + } + return NULL; +} + +/* + * Compare two DNS components, with full wildcard check. We assume + * that no '.' chars exist (per the processing performed in + * tpNextDnsComp()). Returns CSSM_TRUE on match, else CSSM_FALSE. + */ +static CSSM_BOOL tpCompareComps( + const char *hostComp, // no wildcards + uint32 hostCompLen, + const char *certComp, // wildcards OK here + uint32 certCompLen) +{ + const char *endCertComp = certComp + certCompLen; + const char *endHostComp = hostComp + hostCompLen; + do { + /* wild card in cert name? */ + const char *wildCard = tpSubStr(certComp, certCompLen, + "*", 1); + if(wildCard == NULL) { + /* no, require perfect literal match right now */ + if((hostCompLen == certCompLen) && + !memcmp(hostComp, certComp, certCompLen)) { + return CSSM_TRUE; + } + else { + return CSSM_FALSE; + } + } + + if(wildCard != certComp) { + /* + * Require literal match of hostComp with certComp + * up until (but not including) the wildcard + */ + uint32 subStrLen = wildCard - certComp; + if(subStrLen > hostCompLen) { + /* out of host name chars */ + return CSSM_FALSE; + } + if(memcmp(certComp, hostComp, subStrLen)) { + return CSSM_FALSE; + } + /* OK, skip over substring */ + hostComp += subStrLen; + hostCompLen -= subStrLen; + /* start parsing at the wildcard itself */ + certComp = wildCard; + certCompLen -= subStrLen; + continue; + } + + /* + * Currently looking at a wildcard. + * + * Find substring in hostComp which matches from the char after + * the wildcard up to whichever of these comes next: + * + * -- end of certComp + * -- another wildcard + */ + wildCard++; + if(wildCard == endCertComp) { + /* + * -- Wild card at end of cert's DNS + * -- nothing else to match - rest of hostComp is the wildcard + * match + * -- done, success + */ + return CSSM_TRUE; + } + + const char *afterSubStr; // in certComp + afterSubStr = tpSubStr(wildCard, endCertComp - wildCard, + "*", 1); + if(afterSubStr == NULL) { + /* no more wildcards - use end of certComp */ + afterSubStr = endCertComp; + } + uint32 subStrLen = afterSubStr - wildCard; + const char *foundSub = tpSubStr(hostComp, hostCompLen, + wildCard, subStrLen); + if(foundSub == NULL) { + /* No match of explicit chars */ + return CSSM_FALSE; + } + + /* found it - skip past this substring */ + hostComp = foundSub + subStrLen; + hostCompLen = endHostComp - hostComp; + certComp = afterSubStr; + certCompLen = endCertComp - afterSubStr; + + } while((hostCompLen != 0) || (certCompLen != 0)); + if((hostCompLen == 0) && (certCompLen == 0)) { + return CSSM_TRUE; + } + else { + /* end of one but not the other */ + return CSSM_FALSE; + } +} + +/* + * Compare hostname, is presented to the TP in + * CSSM_APPLE_TP_SSL_OPTIONS.ServerName, to a server name obtained + * from the server's cert (i.e., from subjectAltName or commonName). + * Limited wildcard checking is performed here. + * + * The incoming hostname is assumed to have been processed by tpToLower(); + * we'll perform that processing on certName here. + * + * Trailing '.' characters in both host names will be ignored per Radar 3996792. + * + * Returns CSSM_TRUE on match, else CSSM_FALSE. + */ +CSSM_BOOL tpCompareHostNames( + const char *hostName, // spec'd by app, tpToLower'd + uint32 hostNameLen, + char *certName, // from cert, we tpToLower + uint32 certNameLen) +{ + tpToLower(certName, certNameLen); + + /* tolerate optional NULL terminators for both */ + if(hostNameLen && (hostName[hostNameLen - 1] == '\0')) { + hostNameLen--; + } + if(certNameLen && (certName[certNameLen - 1] == '\0')) { + certNameLen--; + } + + if((hostNameLen == 0) || (certNameLen == 0)) { + /* trivial case with at least one empty name */ + if(hostNameLen == certNameLen) { + return CSSM_TRUE; + } + else { + return CSSM_FALSE; + } + } + + /* trim off trailing dots */ + if(hostName[hostNameLen - 1] == '.') { + hostNameLen--; + } + if(certName[certNameLen - 1] == '.') { + certNameLen--; + } + + /* Case 1: exact match */ + if((certNameLen == hostNameLen) && + !memcmp(certName, hostName, certNameLen)) { + return CSSM_TRUE; + } + + /* + * Case 2: Compare one component at a time, handling wildcards in + * cert's server name. The characters implicitly matched by a + * wildcard span only one component of a dnsName. + */ + do { + /* get next component from each dnsName */ + char hostComp[MAX_DNS_COMP_LEN]; + char certComp[MAX_DNS_COMP_LEN]; + uint32 hostCompLen; + uint32 certCompLen; + + bool foundHost = tpNextDnsComp(hostName, hostNameLen, + hostComp, hostCompLen); + bool foundCert = tpNextDnsComp(certName, certNameLen, + certComp, certCompLen); + if(foundHost != foundCert) { + /* unequal number of components */ + tpPolicyError("tpCompareHostNames: wildcard mismatch (1)"); + return CSSM_FALSE; + } + if(!foundHost) { + /* normal successful termination */ + return CSSM_TRUE; + } + + /* compare individual components */ + if(!tpCompareComps(hostComp, hostCompLen, + certComp, certCompLen)) { + tpPolicyError("tpCompareHostNames: wildcard mismatch (2)"); + return CSSM_FALSE; + } + + /* skip over this component + * (note: since tpNextDnsComp will first skip over a leading '.', + * we must make sure to skip over it here as well.) + */ + if(*hostName == '.') hostName++; + hostName += hostCompLen; + if(*certName == '.') certName++; + certName += certCompLen; + } while(1); + /* NOT REACHED */ + //assert(0): + return CSSM_FALSE; +} + +/* + * Compare email address, is presented to the TP in + * CSSM_APPLE_TP_SMIME_OPTIONS.SenderEmail, to a string obtained + * from the sender's cert (i.e., from subjectAltName or Subject DN). + * + * Returns CSSM_TRUE on match, else CSSM_FALSE. + * + * Incoming appEmail string has already been tpNormalizeAddrSpec'd. + * We do that for certEmail string here. + */ +CSSM_BOOL tpCompareEmailAddr( + const char *appEmail, // spec'd by app, normalized + uint32 appEmailLen, + char *certEmail, // from cert, we normalize + uint32 certEmailLen, + bool normalizeAll) // true : lower-case all certEmail characters + +{ + tpNormalizeAddrSpec(certEmail, certEmailLen, normalizeAll); + + /* tolerate optional NULL terminators for both */ + if(appEmailLen > 0 && appEmail[appEmailLen - 1] == '\0') { + appEmailLen--; + } + if(certEmailLen > 0 && certEmail[certEmailLen - 1] == '\0') { + certEmailLen--; + } + if((certEmailLen == appEmailLen) && + !memcmp(certEmail, appEmail, certEmailLen)) { + return CSSM_TRUE; + } + else { + /* mismatch */ + tpPolicyError("tpCompareEmailAddr: app/cert email addrs mismatch"); + return CSSM_FALSE; + } +} + +/* + * Following a CSSMOID_ECDSA_WithSpecified algorithm is an encoded + * ECDSA_SigAlgParams containing the digest agorithm OID. Decode and return + * a unified ECDSA/digest alg (e.g. CSSM_ALGID_SHA512WithECDSA). + * Returns nonzero on error. + */ +int decodeECDSA_SigAlgParams( + const CSSM_DATA *params, + CSSM_ALGORITHMS *cssmAlg) /* RETURNED */ +{ + SecAsn1CoderRef coder = NULL; + if(SecAsn1CoderCreate(&coder)) { + tpErrorLog("***Error in SecAsn1CoderCreate()\n"); + return -1; + } + CSSM_X509_ALGORITHM_IDENTIFIER algParams; + memset(&algParams, 0, sizeof(algParams)); + int ourRtn = 0; + bool algFound = false; + if(SecAsn1DecodeData(coder, params, kSecAsn1AlgorithmIDTemplate, + &algParams)) { + tpErrorLog("***Error decoding CSSM_X509_ALGORITHM_IDENTIFIER\n"); + ourRtn = -1; + goto errOut; + } + CSSM_ALGORITHMS digestAlg; + algFound = cssmOidToAlg(&algParams.algorithm, &digestAlg); + if(!algFound) { + tpErrorLog("***Unknown algorithm in CSSM_X509_ALGORITHM_IDENTIFIER\n"); + ourRtn = -1; + goto errOut; + } + switch(digestAlg) { + case CSSM_ALGID_SHA1: + *cssmAlg = CSSM_ALGID_SHA1WithECDSA; + break; + case CSSM_ALGID_SHA224: + *cssmAlg = CSSM_ALGID_SHA224WithECDSA; + break; + case CSSM_ALGID_SHA256: + *cssmAlg = CSSM_ALGID_SHA256WithECDSA; + break; + case CSSM_ALGID_SHA384: + *cssmAlg = CSSM_ALGID_SHA384WithECDSA; + break; + case CSSM_ALGID_SHA512: + *cssmAlg = CSSM_ALGID_SHA512WithECDSA; + break; + default: + tpErrorLog("***Unknown algorithm in ECDSA_SigAlgParams\n"); + ourRtn = -1; + } +errOut: + SecAsn1CoderRelease(coder); + return ourRtn; +} + diff --git a/libsecurity_apple_x509_tp/lib/certGroupUtils.h b/libsecurity_apple_x509_tp/lib/certGroupUtils.h new file mode 100644 index 00000000..a1719524 --- /dev/null +++ b/libsecurity_apple_x509_tp/lib/certGroupUtils.h @@ -0,0 +1,114 @@ +/* + * 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. + */ + + +/* + certGroupUtils.h + + Created 10/9/2000 by Doug Mitchell. +*/ + +#ifndef _CERT_GROUP_UTILS_H +#define _CERT_GROUP_UTILS_H + +#include +#include +#include "TPCertInfo.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* quick & dirty port from OS9 to OS X... */ +#define tpFree(alloc, ptr) (alloc).free(ptr) +#define tpMalloc(alloc, size) (alloc).malloc(size) +#define tpCalloc(alloc, num, size) (alloc).calloc(num, size) + +void tpCopyCssmData( + Allocator &alloc, + const CSSM_DATA *src, + CSSM_DATA_PTR dst); +CSSM_DATA_PTR tpMallocCopyCssmData( + Allocator &alloc, + const CSSM_DATA *src); +void tpFreeCssmData( + Allocator &alloc, + CSSM_DATA_PTR data, + CSSM_BOOL freeStruct); +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. + */ +#define tpCompareOids(oid1, oid2) tpCompareCssmData(oid1, oid2) + +void tpFreePluginMemory( + CSSM_HANDLE hand, + void *p); + +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( + TPCertInfo *cert, + CSSM_DATA_PTR *valueToFree); // used in tp_CertFreeAlgId +void tp_CertFreeAlgId( + CSSM_CL_HANDLE clHand, + CSSM_DATA_PTR value); + +CSSM_BOOL tp_CompareCerts( + const CSSM_DATA *cert1, + const CSSM_DATA *cert2); + +void tpToLower( + char *str, + unsigned strLen); + +void tpNormalizeAddrSpec( + char *addr, + unsigned addrLen, + bool normalizeAll); + +CSSM_BOOL tpCompareHostNames( + const char *hostName, // spec'd by app, tpToLower'd + uint32 hostNameLen, + char *certName, // from cert, we tpToLower + uint32 certNameLen); + +CSSM_BOOL tpCompareEmailAddr( + const char *appEmail, // spec'd by app, tpToLower'd + uint32 appEmailLen, + char *certEmail, // from cert, we tpToLower + uint32 certEmailLen, + bool normalizeAll); // true : lower-case all certEmail characters + +int decodeECDSA_SigAlgParams( + const CSSM_DATA *params, + CSSM_ALGORITHMS *cssmAlg); /* RETURNED */ + +#ifdef __cplusplus +} +#endif + +#endif /* _CERT_GROUP_UTILS_H */ diff --git a/libsecurity_apple_x509_tp/lib/cuEnc64.c b/libsecurity_apple_x509_tp/lib/cuEnc64.c new file mode 100644 index 00000000..4e258ee4 --- /dev/null +++ b/libsecurity_apple_x509_tp/lib/cuEnc64.c @@ -0,0 +1,586 @@ +/* + * 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 + +#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; + unsigned 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++; + } + unsigned 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 = 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; + unsigned 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 = 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 new file mode 100644 index 00000000..2b3abeb5 --- /dev/null +++ b/libsecurity_apple_x509_tp/lib/cuEnc64.h @@ -0,0 +1,77 @@ +/* + * 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 new file mode 100644 index 00000000..e5cbda69 --- /dev/null +++ b/libsecurity_apple_x509_tp/lib/ocspRequest.cpp @@ -0,0 +1,214 @@ +/* + * 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; + + 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, 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, 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 new file mode 100644 index 00000000..627e60c2 --- /dev/null +++ b/libsecurity_apple_x509_tp/lib/ocspRequest.h @@ -0,0 +1,83 @@ +/* + * 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/lib/tpCertGroup.cpp b/libsecurity_apple_x509_tp/lib/tpCertGroup.cpp new file mode 100644 index 00000000..9867134a --- /dev/null +++ b/libsecurity_apple_x509_tp/lib/tpCertGroup.cpp @@ -0,0 +1,1003 @@ +/* + * 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. + */ + + +/* + * tpCertGroup.cpp - Cert group functions (construct, verify) + */ + +#include "AppleTPSession.h" +#include "certGroupUtils.h" +#include "TPCertInfo.h" +#include "TPCrlInfo.h" +#include "tpPolicies.h" +#include "tpdebugging.h" +#include "tpCrlVerify.h" +#include +#include + +/* + * This is a temporary hack to allow verification of PKINIT server certs + * which are self-signed and not in the system anchors list. If the self- + * signed cert is in a magic keychain (whose location is not published), + * we'll allow it as if it were indeed a full-fledged anchor cert. + */ +#define TP_PKINIT_SERVER_HACK 1 +#if TP_PKINIT_SERVER_HACK + +#include +#include +#include +#include +#include +#include + +#define CFRELEASE(cf) if(cf) { CFRelease(cf); } + +/* + * Returns true if we are to allow/trust the specified + * cert as a PKINIT-only anchor. + */ +static bool tpCheckPkinitServerCert( + TPCertGroup &certGroup) +{ + /* + * Basic requirement: exactly one cert, self-signed. + * The numCerts == 1 requirement might change... + */ + unsigned numCerts = certGroup.numCerts(); + if(numCerts != 1) { + tpDebug("tpCheckPkinitServerCert: too many certs"); + return false; + } + /* end of chain... */ + TPCertInfo *theCert = certGroup.certAtIndex(numCerts - 1); + if(!theCert->isSelfSigned()) { + tpDebug("tpCheckPkinitServerCert: 1 cert, not self-signed"); + return false; + } + const CSSM_DATA *subjectName = theCert->subjectName(); + + /* + * Open the magic keychain. + * We're going up and over the Sec layer here, not generally + * kosher, but this is a temp hack. + */ + OSStatus ortn; + SecKeychainRef kcRef = NULL; + string fullPathName; + const char *homeDir = getenv("HOME"); + if (homeDir == NULL) + { + // If $HOME is unset get the current user's home directory + // from the passwd file. + uid_t uid = geteuid(); + if (!uid) uid = getuid(); + struct passwd *pw = getpwuid(uid); + if (!pw) { + return false; + } + homeDir = pw->pw_dir; + } + fullPathName = homeDir; + fullPathName += "/Library/Application Support/PKINIT/TrustedServers.keychain"; + ortn = SecKeychainOpen(fullPathName.c_str(), &kcRef); + if(ortn) { + tpDebug("tpCheckPkinitServerCert: keychain not found (1)"); + return false; + } + /* subsequent errors to errOut: */ + + bool ourRtn = false; + SecKeychainStatus kcStatus; + CSSM_DATA_PTR subjSerial = NULL; + CSSM_RETURN crtn; + SecKeychainSearchRef srchRef = NULL; + SecKeychainAttributeList attrList; + SecKeychainAttribute attrs[2]; + SecKeychainItemRef foundItem = NULL; + + ortn = SecKeychainGetStatus(kcRef, &kcStatus); + if(ortn) { + tpDebug("tpCheckPkinitServerCert: keychain not found (2)"); + goto errOut; + } + + /* + * We already have this cert's normalized name; get its + * serial number. + */ + crtn = theCert->fetchField(&CSSMOID_X509V1SerialNumber, &subjSerial); + if(crtn) { + /* should never happen */ + tpDebug("tpCheckPkinitServerCert: error fetching serial number"); + goto errOut; + } + + attrs[0].tag = kSecSubjectItemAttr; + attrs[0].length = subjectName->Length; + attrs[0].data = subjectName->Data; + attrs[1].tag = kSecSerialNumberItemAttr; + attrs[1].length = subjSerial->Length; + attrs[1].data = subjSerial->Data; + attrList.count = 2; + attrList.attr = attrs; + + ortn = SecKeychainSearchCreateFromAttributes(kcRef, + kSecCertificateItemClass, + &attrList, + &srchRef); + if(ortn) { + tpDebug("tpCheckPkinitServerCert: search failure"); + goto errOut; + } + for(;;) { + ortn = SecKeychainSearchCopyNext(srchRef, &foundItem); + if(ortn) { + tpDebug("tpCheckPkinitServerCert: end search"); + break; + } + + /* found a matching cert; do byte-for-byte compare */ + CSSM_DATA certData; + ortn = SecCertificateGetData((SecCertificateRef)foundItem, &certData); + if(ortn) { + tpDebug("tpCheckPkinitServerCert: SecCertificateGetData failure"); + continue; + } + if(tpCompareCssmData(&certData, theCert->itemData())){ + tpDebug("tpCheckPkinitServerCert: FOUND CERT"); + ourRtn = true; + break; + } + tpDebug("tpCheckPkinitServerCert: skipping matching cert"); + CFRelease(foundItem); + foundItem = NULL; + } +errOut: + CFRELEASE(kcRef); + CFRELEASE(srchRef); + CFRELEASE(foundItem); + if(subjSerial != NULL) { + theCert->freeField(&CSSMOID_X509V1SerialNumber, subjSerial); + } + return ourRtn; +} +#endif /* TP_PKINIT_SERVER_HACK */ + + +/*----------------------------------------------------------------------------- + * CertGroupConstruct + * + * Description: + * This function returns a pointer to a mallocd CSSM_CERTGROUP which + * refers to a mallocd list of raw ordered X.509 certs which verify back as + * far as the TP is able to go. The first cert of the returned list is the + * subject cert. The TP will attempt to search thru the DBs passed in + * DBList in order to complete the chain. The chain is completed when a + * self-signed (root) cert is found in the chain. The root cert may be + * present in the input CertGroupFrag, or it may have been obtained from + * one of the DBs passed in DBList. It is not an error if no root cert is + * found. + * + * The error conditions are: + * -- The first cert of CertGroupFrag is an invalid cert. NULL is returned, + * err = CSSM_TP_INVALID_CERTIFICATE. + * -- The root cert (if found) fails to verify. Valid certgroup is returned, + * err = CSSMERR_TP_VERIFICATION_FAILURE. + * -- Any cert in the (possibly partially) constructed chain has expired or + * isn't valid yet, err = CSSMERR_TP_CERT_EXPIRED or + * CSSMERR_TP_CERT_NOT_VALID_YET. A CertGroup is returned. + * -- CSSMERR_TP_CERT_EXPIRED and CSSMERR_TP_CERT_NOT_VALID_YET. If one of these + * conditions obtains for the first (leaf) cert, the function throws this + * error immediately and the outgoing cert group is empty. For subsequent certs, + * the temporal validity of a cert is only tested AFTER a cert successfully + * meets the cert chaining criteria (subject/issuer match and signature + * verify). A cert in a chain with this error is not added to the outgoing + * cert group. + * -- the usual errors like bad handle or memory failure. + * + * Parameters: + * Two handles - to an open CL and CSP. The CSP must be capable of + * dealing with the signature algorithms used by the certs. The CL must be + * an X.509-savvy CL. + * + * CertGroupFrag, an unordered array of raw X.509 certs in the form of a + * CSSM_CERTGROUP_PTR. The first cert of this list is the subject cert + * which is eventually to be verified. The other certs can be in any order + * and may not even have any relevance to the cert chain being constructed. + * They may also be invalid certs. + * + * DBList, a list of DB/DL handles which may contain certs necessary to + * complete the desired cert chain. (Not currently implemented.) + * + *---------------------------------------------------------------------------*/ + +/* public version */ +void AppleTPSession::CertGroupConstruct(CSSM_CL_HANDLE clHand, + CSSM_CSP_HANDLE cspHand, + const CSSM_DL_DB_LIST &DBList, + const void *ConstructParams, + const CSSM_CERTGROUP &CertGroupFrag, + CSSM_CERTGROUP_PTR &CertGroup) +{ + TPCertGroup outCertGroup(*this, TGO_Caller); + TPCertGroup inCertGroup(CertGroupFrag, + clHand, + cspHand, + *this, + NULL, // cssmTimeStr + true, // firstCertMustBeValid + TGO_Group); + + /* set up for disposal of TPCertInfos created by CertGroupConstructPriv */ + TPCertGroup gatheredCerts(*this, TGO_Group); + + CSSM_RETURN constructReturn = CSSM_OK; + CSSM_APPLE_TP_ACTION_FLAGS actionFlags = 0; + CSSM_BOOL verifiedToRoot; // not used + CSSM_BOOL verifiedToAnchor; // not used + CSSM_BOOL verifiedViaTrustSetting; // not used + + try { + CertGroupConstructPriv(clHand, + cspHand, + inCertGroup, + &DBList, + NULL, // cssmTimeStr + /* no anchors */ + 0, NULL, + actionFlags, + /* no user trust */ + NULL, NULL, 0, 0, + gatheredCerts, + verifiedToRoot, + verifiedToAnchor, + verifiedViaTrustSetting, + outCertGroup); + } + catch(const CssmError &cerr) { + constructReturn = cerr.error; + /* abort if no certs found */ + if(outCertGroup.numCerts() == 0) { + CssmError::throwMe(constructReturn); + } + } + CertGroup = outCertGroup.buildCssmCertGroup(); + /* caller of this function never gets evidence... */ + outCertGroup.freeDbRecords(); + + if(constructReturn) { + CssmError::throwMe(constructReturn); + } +} + + +/* + * Private version of CertGroupConstruct, used by CertGroupConstruct and + * CertGroupVerify. Populates a TP-style TPCertGroup for further processing. + * This only throws CSSM-style exceptions in the following cases: + * + * -- input parameter errors + * -- the first (leaf) cert is bad (doesn't parse, expired, not valid yet). + * -- root found but it doesn't self-verify + * + * All other cert-related errors simply result in the bad cert being ignored. + * Other exceptions are gross system errors like malloc failure. + */ +void AppleTPSession::CertGroupConstructPriv(CSSM_CL_HANDLE clHand, + CSSM_CSP_HANDLE cspHand, + TPCertGroup &inCertGroup, + const CSSM_DL_DB_LIST *DBList, // optional here + const char *cssmTimeStr, // optional + + /* trusted anchors, optional */ + /* FIXME - maybe this should be a TPCertGroup */ + uint32 numAnchorCerts, + const CSSM_DATA *anchorCerts, + + /* CSSM_TP_ACTION_FETCH_CERT_FROM_NET, CSSM_TP_ACTION_TRUST_SETTINGS */ + CSSM_APPLE_TP_ACTION_FLAGS actionFlags, + + /* optional user trust parameters */ + const CSSM_OID *policyOid, + const char *policyStr, + uint32 policyStrLen, + SecTrustSettingsKeyUsage keyUse, + + /* + * Certs to be freed by caller (i.e., TPCertInfo which we allocate + * as a result of using a cert from anchorCerts or dbList) are added + * to this group. + */ + TPCertGroup &certsToBeFreed, + + /* returned */ + CSSM_BOOL &verifiedToRoot, // end of chain self-verifies + CSSM_BOOL &verifiedToAnchor, // end of chain in anchors + CSSM_BOOL &verifiedViaTrustSetting, // chain ends per User Trust setting + TPCertGroup &outCertGroup) // RETURNED +{ + TPCertInfo *subjectCert; // the one we're working on + CSSM_RETURN outErr = CSSM_OK; + + /* this'll be the first subject cert in the main loop */ + subjectCert = inCertGroup.certAtIndex(0); + + /* Append leaf cert to outCertGroup */ + outCertGroup.appendCert(subjectCert); + subjectCert->isLeaf(true); + subjectCert->isFromInputCerts(true); + outCertGroup.setAllUnused(); + subjectCert->used(true); + + outErr = outCertGroup.buildCertGroup( + *subjectCert, + &inCertGroup, + DBList, + clHand, + cspHand, + cssmTimeStr, + numAnchorCerts, + anchorCerts, + certsToBeFreed, + &certsToBeFreed, // gatheredCerts to accumulate net/DB fetches + CSSM_TRUE, // subjectIsInGroup - enables root check on + // subject cert + actionFlags, + policyOid, + policyStr, + policyStrLen, + keyUse, + + verifiedToRoot, + verifiedToAnchor, + verifiedViaTrustSetting); + if(outErr) { + CssmError::throwMe(outErr); + } +} + +/* + * Map a policy OID to one of the standard (non-revocation) policies. + * Returns true if it's a standard policy. + */ +static bool checkPolicyOid( + const CSSM_OID &oid, + TPPolicy &tpPolicy) /* RETURNED */ +{ + if(tpCompareOids(&oid, &CSSMOID_APPLE_TP_SSL)) { + tpPolicy = kTP_SSL; + return true; + } + else if(tpCompareOids(&oid, &CSSMOID_APPLE_X509_BASIC)) { + tpPolicy = kTPx509Basic; + return true; + } + else if(tpCompareOids(&oid, &CSSMOID_APPLE_TP_SMIME)) { + tpPolicy = kTP_SMIME; + return true; + } + else if(tpCompareOids(&oid, &CSSMOID_APPLE_TP_EAP)) { + tpPolicy = kTP_EAP; + return true; + } + else if(tpCompareOids(&oid, &CSSMOID_APPLE_TP_SW_UPDATE_SIGNING)) { + /* note: this was CSSMOID_APPLE_TP_CODE_SIGN until 8/15/06 */ + tpPolicy = kTP_SWUpdateSign; + return true; + } + else if(tpCompareOids(&oid, &CSSMOID_APPLE_TP_RESOURCE_SIGN)) { + tpPolicy = kTP_ResourceSign; + return true; + } + else if(tpCompareOids(&oid, &CSSMOID_APPLE_TP_IP_SEC)) { + tpPolicy = kTP_IPSec; + return true; + } + else if(tpCompareOids(&oid, &CSSMOID_APPLE_TP_ICHAT)) { + tpPolicy = kTP_iChat; + return true; + } + else if(tpCompareOids(&oid, &CSSMOID_APPLE_ISIGN)) { + tpPolicy = kTPiSign; + return true; + } + else if(tpCompareOids(&oid, &CSSMOID_APPLE_TP_PKINIT_CLIENT)) { + tpPolicy = kTP_PKINIT_Client; + return true; + } + else if(tpCompareOids(&oid, &CSSMOID_APPLE_TP_PKINIT_SERVER)) { + tpPolicy = kTP_PKINIT_Server; + return true; + } + else if(tpCompareOids(&oid, &CSSMOID_APPLE_TP_CODE_SIGNING)) { + tpPolicy = kTP_CodeSigning; + return true; + } + else if(tpCompareOids(&oid, &CSSMOID_APPLE_TP_PACKAGE_SIGNING)) { + tpPolicy = kTP_PackageSigning; + return true; + } + else if(tpCompareOids(&oid, &CSSMOID_APPLE_TP_MACAPPSTORE_RECEIPT)) { + tpPolicy = kTP_MacAppStoreRec; + return true; + } + else if(tpCompareOids(&oid, &CSSMOID_APPLE_TP_APPLEID_SHARING)) { + tpPolicy = kTP_AppleIDSharing; + return true; + } + else if(tpCompareOids(&oid, &CSSMOID_APPLE_TP_TIMESTAMPING)) { + tpPolicy = kTP_TimeStamping; + return true; + } + return false; +} + +/*----------------------------------------------------------------------------- + * CertGroupVerify + * + * Description: + * -- Construct a cert chain using TP_CertGroupConstruct. + * -- Attempt to verify that cert chain against one of the known + * good certs passed in AnchorCerts. + * -- Optionally enforces additional policies (TBD) when verifying the cert chain. + * -- Optionally returns the entire cert chain constructed in + * TP_CertGroupConstruct and here, all the way to an anchor cert or as + * far as we were able to go, in *Evidence. + * + * Parameters: + * Two handles - to an open CL and CSP. The CSP must be capable of + * dealing with the signature algorithms used by the certs. The CL must be + * an X.509-savvy CL. + * + * RawCerts, an unordered array of raw certs in the form of a + * CSSM_CERTGROUP_PTR. The first cert of this list is the subject cert + * which is eventually to be verified. The other certs can be in any order + * and may not even have any relevance to the cert chain being constructed. + * They may also be invalid certs. + * + * DBList, a list of DB/DL handles which may contain certs necessary to + * complete the desired cert chain. (Currently not implemented.) + * + * AnchorCerts, a list of known trusted certs. + * NumberOfAnchorCerts, size of AnchorCerts array. + * + * PolicyIdentifiers, Optional policy OID. NULL indicates default + * X.509 trust policy. + * + * Supported Policies: + * CSSMOID_APPLE_ISIGN + * CSSMOID_APPLE_X509_BASIC + * + * For both of these, the associated FieldValue must be {0, NULL}, + * + * NumberOfPolicyIdentifiers, size of PolicyIdentifiers array, must be + * zero or one. + * + * All other arguments must be zero/NULL. + * + * Returns: + * CSSM_OK : cert chain verified all the way back to an AnchorCert. + * CSSMERR_TP_INVALID_ANCHOR_CERT : In this case, the cert chain + * was validated back to a self-signed (root) cert found in either + * CertToBeVerified or in one of the DBs in DBList, but that root cert + * was *NOT* found in the AnchorCert list. + * CSSMERR_TP_NOT_TRUSTED: no root cert was found and no AnchorCert + * verified the end of the constructed cert chain. + * CSSMERR_TP_VERIFICATION_FAILURE: a root cert was found which does + * not self-verify. + * CSSMERR_TP_VERIFY_ACTION_FAILED: indicates a failure of the requested + * policy action. + * CSSMERR_TP_INVALID_CERTIFICATE: indicates a bad leaf cert. + * CSSMERR_TP_INVALID_REQUEST_INPUTS : no incoming VerifyContext. + * CSSMERR_TP_CERT_EXPIRED and CSSMERR_TP_CERT_NOT_VALID_YET: see comments + * for CertGroupConstruct. + * CSSMERR_TP_CERTIFICATE_CANT_OPERATE : issuer cert was found with a partial + * public key, rendering full verification impossible. + * CSSMERR_TP_INVALID_CERT_AUTHORITY : issuer cert was found with a partial + * public key and which failed to perform subsequent signature + * verification. + *---------------------------------------------------------------------------*/ + +void AppleTPSession::CertGroupVerify(CSSM_CL_HANDLE clHand, + CSSM_CSP_HANDLE cspHand, + const CSSM_CERTGROUP &CertGroupToBeVerified, + const CSSM_TP_VERIFY_CONTEXT *VerifyContext, + CSSM_TP_VERIFY_CONTEXT_RESULT_PTR VerifyContextResult) +{ + CSSM_BOOL verifiedToRoot = CSSM_FALSE; + CSSM_BOOL verifiedToAnchor = CSSM_FALSE; + CSSM_BOOL verifiedViaTrustSetting = CSSM_FALSE; + CSSM_RETURN constructReturn = CSSM_OK; + CSSM_RETURN policyReturn = CSSM_OK; + const CSSM_TP_CALLERAUTH_CONTEXT *cred; + /* declare volatile as compiler workaround to avoid caching in CR4 */ + const CSSM_APPLE_TP_ACTION_DATA * volatile actionData = NULL; + CSSM_TIMESTRING cssmTimeStr; + CSSM_APPLE_TP_ACTION_FLAGS actionFlags = 0; + CSSM_TP_STOP_ON tpStopOn = 0; + + /* keep track of whether we did policy checking; if not, we do defaults */ + bool didCertPolicy = false; + bool didRevokePolicy = false; + + /* user trust parameters */ + CSSM_OID utNullPolicy = {0, NULL}; + const CSSM_OID *utPolicyOid = NULL; + const char *utPolicyStr = NULL; + uint32 utPolicyStrLen = 0; + SecTrustSettingsKeyUsage utKeyUse = 0; + bool utTrustSettingEnabled = false; + + if(VerifyContextResult) { + memset(VerifyContextResult, 0, sizeof(*VerifyContextResult)); + } + + /* verify input args, skipping the ones checked by CertGroupConstruct */ + if((VerifyContext == NULL) || (VerifyContext->Cred == NULL)) { + /* the spec says that this is optional but we require it */ + CssmError::throwMe(CSSMERR_TP_INVALID_REQUEST_INPUTS); + } + cred = VerifyContext->Cred; + + /* Optional ActionData affecting all policies */ + actionData = (CSSM_APPLE_TP_ACTION_DATA * volatile)VerifyContext->ActionData.Data; + if(actionData != NULL) { + switch(actionData->Version) { + case CSSM_APPLE_TP_ACTION_VERSION: + if(VerifyContext->ActionData.Length != + sizeof(CSSM_APPLE_TP_ACTION_DATA)) { + CssmError::throwMe(CSSMERR_TP_INVALID_ACTION_DATA); + } + break; + /* handle backwards versions here if we ever go beyond version 0 */ + default: + CssmError::throwMe(CSSMERR_TP_INVALID_ACTION_DATA); + } + actionFlags = actionData->ActionFlags; + if(actionFlags & CSSM_TP_ACTION_TRUST_SETTINGS) { + utTrustSettingEnabled = true; + } + } + + /* optional, may be NULL */ + cssmTimeStr = cred->VerifyTime; + + tpStopOn = cred->VerificationAbortOn; + switch(tpStopOn) { + /* the only two we support */ + case CSSM_TP_STOP_ON_NONE: + case CSSM_TP_STOP_ON_FIRST_FAIL: + break; + /* default maps to stop on first fail */ + case CSSM_TP_STOP_ON_POLICY: + tpStopOn = CSSM_TP_STOP_ON_FIRST_FAIL; + break; + default: + CssmError::throwMe(CSSMERR_TP_INVALID_STOP_ON_POLICY); + } + + /* now the args we can't deal with */ + if(cred->CallerCredentials != NULL) { + CssmError::throwMe(CSSMERR_TP_INVALID_CALLERAUTH_CONTEXT_POINTER); + } + /* ...any others? */ + + /* set up for optional user trust evaluation */ + if(utTrustSettingEnabled) { + const CSSM_TP_POLICYINFO *pinfo = &cred->Policy; + TPPolicy utPolicy = kTPx509Basic; + + /* default policy OID in case caller hasn't specified one */ + utPolicyOid = &utNullPolicy; + if(pinfo->NumberOfPolicyIds == 0) { + tpTrustSettingsDbg("CertGroupVerify: User trust enabled but no policies (1)"); + /* keep going, I guess - no policy-specific info - use kTPx509Basic */ + } + else { + CSSM_FIELD_PTR utPolicyField = &pinfo->PolicyIds[0]; + utPolicyOid = &utPolicyField->FieldOid; + bool foundPolicy = checkPolicyOid(*utPolicyOid, utPolicy); + if(!foundPolicy) { + tpTrustSettingsDbg("CertGroupVerify: User trust enabled but no policies"); + /* keep going, I guess - no policy-specific info - use kTPx509Basic */ + } + else { + /* get policy-specific info */ + tp_policyTrustSettingParams(utPolicy, &utPolicyField->FieldValue, + &utPolicyStr, &utPolicyStrLen, &utKeyUse); + } + } + } + + /* get verified (possibly partial) outCertGroup - error is fatal */ + /* BUT: we still return partial evidence if asked to...from now on. */ + TPCertGroup outCertGroup(*this, + TGO_Caller); // certs are owned by inCertGroup + TPCertGroup inCertGroup(CertGroupToBeVerified, clHand, cspHand, *this, + cssmTimeStr, // optional 'this' time + true, // firstCertMustBeValid + TGO_Group); + + /* set up for disposal of TPCertInfos created by CertGroupConstructPriv */ + TPCertGroup gatheredCerts(*this, TGO_Group); + + try { + CertGroupConstructPriv( + clHand, + cspHand, + inCertGroup, + cred->DBList, + cssmTimeStr, + cred->NumberOfAnchorCerts, + cred->AnchorCerts, + actionFlags, + utPolicyOid, + utPolicyStr, + utPolicyStrLen, + utKeyUse, + gatheredCerts, + verifiedToRoot, + verifiedToAnchor, + verifiedViaTrustSetting, + outCertGroup); + } + catch(const CssmError &cerr) { + constructReturn = cerr.error; + /* abort if no certs found */ + if(outCertGroup.numCerts() == 0) { + CssmError::throwMe(constructReturn); + } + /* else press on, collecting as much info as we can */ + } + /* others are way fatal */ + assert(outCertGroup.numCerts() >= 1); + + /* Infer interim status from return values */ + switch(constructReturn) { + /* these values do not get overridden */ + case CSSMERR_TP_CERTIFICATE_CANT_OPERATE: + case CSSMERR_TP_INVALID_CERT_AUTHORITY: + case CSSMERR_APPLETP_TRUST_SETTING_DENY: + case errSecInvalidTrustSettings: + break; + default: + /* infer status from these values... */ + if(verifiedToAnchor || verifiedViaTrustSetting) { + /* full success; anchor doesn't have to be root */ + constructReturn = CSSM_OK; + } + else if(verifiedToRoot) { + if(actionFlags & CSSM_TP_ACTION_IMPLICIT_ANCHORS) { + constructReturn = CSSM_OK; + } + else { + /* verified to root which is not an anchor */ + constructReturn = CSSMERR_TP_INVALID_ANCHOR_CERT; + } + } + else { + /* partial chain, no root, not verifiable by anchor */ + constructReturn = CSSMERR_TP_NOT_TRUSTED; + } + + /* + * Those errors can be allowed, cert-chain-wide, per individual + * certs' allowedErrors + */ + if((constructReturn != CSSM_OK) && + outCertGroup.isAllowedError(constructReturn)) { + constructReturn = CSSM_OK; + } + break; + } + + /* + * Parameters passed to tp_policyVerify() and which vary per policy + * in the loop below + */ + TPPolicy tpPolicy; + const CSSM_APPLE_TP_SSL_OPTIONS *sslOpts; + CSSM_RETURN thisPolicyRtn = CSSM_OK; // returned from tp_policyVerify() + + /* common CRL verify parameters */ + TPCrlGroup *crlGroup = NULL; + try { + crlGroup = new TPCrlGroup(&VerifyContext->Crls, + clHand, cspHand, + *this, // alloc + NULL, // cssmTimeStr - we want CRLs that are valid 'now' + TGO_Group); + } + catch(const CssmError &cerr) { + CSSM_RETURN cr = cerr.error; + /* I don't see a straightforward way to report this error, + * other than adding it to the leaf cert's status... */ + outCertGroup.certAtIndex(0)->addStatusCode(cr); + tpDebug("CertGroupVerify: error constructing CrlGroup; continuing\n"); + } + /* others are way fatal */ + + TPVerifyContext revokeVfyContext(*this, + clHand, + cspHand, + cssmTimeStr, + cred->NumberOfAnchorCerts, + cred->AnchorCerts, + &inCertGroup, + crlGroup, + /* + * This may consist of certs gathered from the net (which is the purpose + * of this argument) and from DLDBs (a side-effect optimization). + */ + gatheredCerts, + cred->DBList, + kRevokeNone, // policy + actionFlags, + NULL, // CRL options + NULL, // OCSP options + utPolicyOid, + utPolicyStr, + utPolicyStrLen, + utKeyUse); + + /* true if we're to execute tp_policyVerify at end of loop */ + bool doPolicyVerify; + /* true if we're to execute a revocation policy at end of loop */ + bool doRevocationPolicy; + + /* grind thru each policy */ + for(uint32 polDex=0; polDexPolicy.NumberOfPolicyIds; polDex++) { + if(cred->Policy.PolicyIds == NULL) { + policyReturn = CSSMERR_TP_INVALID_POLICY_IDENTIFIERS; + break; + } + CSSM_FIELD_PTR policyId = &cred->Policy.PolicyIds[polDex]; + const CSSM_DATA *fieldVal = &policyId->FieldValue; + const CSSM_OID *oid = &policyId->FieldOid; + thisPolicyRtn = CSSM_OK; + doPolicyVerify = false; + doRevocationPolicy = false; + sslOpts = NULL; + + /* first the basic cert policies */ + doPolicyVerify = checkPolicyOid(*oid, tpPolicy); + if(doPolicyVerify) { + /* some basic checks... */ + bool policyAbort = false; + switch(tpPolicy) { + case kTPx509Basic: + case kTPiSign: + case kTP_PKINIT_Client: + case kTP_PKINIT_Server: + if(fieldVal->Data != NULL) { + policyReturn = CSSMERR_TP_INVALID_POLICY_IDENTIFIERS; + policyAbort = true; + break; + } + break; + default: + break; + } + if(policyAbort) { + break; + } + #if TP_PKINIT_SERVER_HACK + if(tpPolicy == kTP_PKINIT_Server) { + /* possible override of "root not in anchors" */ + if(constructReturn == CSSMERR_TP_INVALID_ANCHOR_CERT) { + if(tpCheckPkinitServerCert(outCertGroup)) { + constructReturn = CSSM_OK; + } + } + } + #endif /* TP_PKINIT_SERVER_HACK */ + } + + /* + * Now revocation policies. Note some fields in revokeVfyContext can + * accumulate across multiple policy calls, e.g., signerCerts. + */ + else if(tpCompareOids(oid, &CSSMOID_APPLE_TP_REVOCATION_CRL)) { + /* CRL-specific options */ + const CSSM_APPLE_TP_CRL_OPTIONS *crlOpts; + crlOpts = (CSSM_APPLE_TP_CRL_OPTIONS *)fieldVal->Data; + thisPolicyRtn = CSSM_OK; + if(crlOpts != NULL) { + switch(crlOpts->Version) { + case CSSM_APPLE_TP_CRL_OPTS_VERSION: + if(fieldVal->Length != + sizeof(CSSM_APPLE_TP_CRL_OPTIONS)) { + thisPolicyRtn = + CSSMERR_TP_INVALID_POLICY_IDENTIFIERS; + break; + } + break; + /* handle backwards compatibility here if necessary */ + default: + thisPolicyRtn = CSSMERR_TP_INVALID_POLICY_IDENTIFIERS; + break; + } + if(thisPolicyRtn != CSSM_OK) { + policyReturn = thisPolicyRtn; + break; + } + } + revokeVfyContext.policy = kRevokeCrlBasic; + revokeVfyContext.crlOpts = crlOpts; + doRevocationPolicy = true; + } + else if(tpCompareOids(oid, &CSSMOID_APPLE_TP_REVOCATION_OCSP)) { + /* OCSP-specific options */ + const CSSM_APPLE_TP_OCSP_OPTIONS *ocspOpts; + ocspOpts = (CSSM_APPLE_TP_OCSP_OPTIONS *)fieldVal->Data; + thisPolicyRtn = CSSM_OK; + if(ocspOpts != NULL) { + switch(ocspOpts->Version) { + case CSSM_APPLE_TP_OCSP_OPTS_VERSION: + if(fieldVal->Length != + sizeof(CSSM_APPLE_TP_OCSP_OPTIONS)) { + thisPolicyRtn = + CSSMERR_TP_INVALID_POLICY_IDENTIFIERS; + break; + } + break; + /* handle backwards compatibility here if necessary */ + default: + thisPolicyRtn = CSSMERR_TP_INVALID_POLICY_IDENTIFIERS; + break; + } + if(thisPolicyRtn != CSSM_OK) { + policyReturn = thisPolicyRtn; + break; + } + } + revokeVfyContext.policy = kRevokeOcsp; + revokeVfyContext.ocspOpts = ocspOpts; + doRevocationPolicy = true; + } + /* etc. - add more policies here */ + else { + /* unknown TP policy OID */ + policyReturn = CSSMERR_TP_INVALID_POLICY_IDENTIFIERS; + break; + } + + /* common cert policy call */ + if(doPolicyVerify) { + assert(!doRevocationPolicy); // one at a time + thisPolicyRtn = tp_policyVerify(tpPolicy, + *this, + clHand, + cspHand, + &outCertGroup, + verifiedToRoot, + verifiedViaTrustSetting, + actionFlags, + fieldVal, + cred->Policy.PolicyControl); // not currently used + didCertPolicy = true; + } + /* common revocation policy call */ + if(doRevocationPolicy) { + assert(!doPolicyVerify); // one at a time + thisPolicyRtn = tpRevocationPolicyVerify(revokeVfyContext, outCertGroup); + didRevokePolicy = true; + } + /* See if possible error is allowed, cert-chain-wide. */ + if((thisPolicyRtn != CSSM_OK) && + outCertGroup.isAllowedError(thisPolicyRtn)) { + thisPolicyRtn = CSSM_OK; + } + if(thisPolicyRtn) { + /* Now remember the error if it's the first policy + * error we've seen. */ + if(policyReturn == CSSM_OK) { + policyReturn = thisPolicyRtn; + } + /* Keep going? */ + if(tpStopOn == CSSM_TP_STOP_ON_FIRST_FAIL) { + /* Nope; we're done with policy evaluation */ + break; + } + } + } /* for each policy */ + + /* + * Upon completion of the above loop, perform default policy ops if + * appropriate. + */ + if((policyReturn == CSSM_OK) || (tpStopOn == CSSM_TP_STOP_ON_NONE)) { + if(!didCertPolicy) { + policyReturn = tp_policyVerify(kTPDefault, + *this, + clHand, + cspHand, + &outCertGroup, + verifiedToRoot, + verifiedViaTrustSetting, + actionFlags, + NULL, // policyFieldData + cred->Policy.PolicyControl); // not currently used + /* See if error is allowed, cert-chain-wide. */ + if((policyReturn != CSSM_OK) && + outCertGroup.isAllowedError(policyReturn)) { + policyReturn = CSSM_OK; + } + } + if( !didRevokePolicy && // no revoke policy yet + ( (policyReturn == CSSM_OK || // default cert policy OK + (tpStopOn == CSSM_TP_STOP_ON_NONE)) // keep going anyway + ) + ) { + revokeVfyContext.policy = TP_CRL_POLICY_DEFAULT; + CSSM_RETURN thisPolicyRtn = tpRevocationPolicyVerify(revokeVfyContext, + outCertGroup); + if((thisPolicyRtn != CSSM_OK) && + outCertGroup.isAllowedError(thisPolicyRtn)) { + thisPolicyRtn = CSSM_OK; + } + if((thisPolicyRtn != CSSM_OK) && (policyReturn == CSSM_OK)) { + policyReturn = thisPolicyRtn; + } + + } + } /* default policy opts */ + + delete crlGroup; + + /* return evidence - i.e., constructed chain - if asked to */ + if(VerifyContextResult != NULL) { + /* + * VerifyContextResult->Evidence[0] : CSSM_TP_APPLE_EVIDENCE_HEADER + * VerifyContextResult->Evidence[1] : CSSM_CERTGROUP + * VerifyContextResult->Evidence[2] : CSSM_TP_APPLE_EVIDENCE_INFO + */ + VerifyContextResult->NumberOfEvidences = 3; + VerifyContextResult->Evidence = + (CSSM_EVIDENCE_PTR)calloc(3, sizeof(CSSM_EVIDENCE)); + + CSSM_TP_APPLE_EVIDENCE_HEADER *hdr = + (CSSM_TP_APPLE_EVIDENCE_HEADER *)malloc( + sizeof(CSSM_TP_APPLE_EVIDENCE_HEADER)); + hdr->Version = CSSM_TP_APPLE_EVIDENCE_VERSION; + CSSM_EVIDENCE_PTR ev = &VerifyContextResult->Evidence[0]; + ev->EvidenceForm = CSSM_EVIDENCE_FORM_APPLE_HEADER; + ev->Evidence = hdr; + + ev = &VerifyContextResult->Evidence[1]; + ev->EvidenceForm = CSSM_EVIDENCE_FORM_APPLE_CERTGROUP; + ev->Evidence = outCertGroup.buildCssmCertGroup(); + + ev = &VerifyContextResult->Evidence[2]; + ev->EvidenceForm = CSSM_EVIDENCE_FORM_APPLE_CERT_INFO; + ev->Evidence = outCertGroup.buildCssmEvidenceInfo(); + } + else { + /* caller responsible for freeing these if they are for evidence.... */ + outCertGroup.freeDbRecords(); + } + CSSM_RETURN outErr = outCertGroup.getReturnCode(constructReturn, policyReturn, + actionFlags); + + if(outErr) { + CssmError::throwMe(outErr); + } +} + + diff --git a/libsecurity_apple_x509_tp/lib/tpCredRequest.cpp b/libsecurity_apple_x509_tp/lib/tpCredRequest.cpp new file mode 100644 index 00000000..038f328f --- /dev/null +++ b/libsecurity_apple_x509_tp/lib/tpCredRequest.cpp @@ -0,0 +1,828 @@ +/* + * Copyright (c) 2002 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. + */ + + +/* + * tpCredRequest.cpp - credential request functions SubmitCredRequest, + * RetrieveCredResult + * + * Created 1/24/2002 by Doug Mitchell. + */ + +#include "AppleTPSession.h" +#include "certGroupUtils.h" +#include "tpdebugging.h" +#include "tpTime.h" +#include +#include +#include +#include +#include +#include +#include + +#define tpCredDebug(args...) secdebug("tpCred", ## args) + +/* + * 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 * AppleTPSession::buildX509Name( + const CSSM_APPLE_TP_NAME_OID *nameArray, + unsigned numNames) +{ + CSSM_X509_NAME *top = (CSSM_X509_NAME *)malloc(sizeof(CSSM_X509_NAME)); + top->numberOfRDNs = numNames; + if(numNames == 0) { + /* legal! */ + top->RelativeDistinguishedName = NULL; + return top; + } + top->RelativeDistinguishedName = + (CSSM_X509_RDN_PTR)malloc(sizeof(CSSM_X509_RDN) * numNames); + CSSM_X509_RDN_PTR rdn; + const CSSM_APPLE_TP_NAME_OID *nameOid; + unsigned nameDex; + for(nameDex=0; nameDexRelativeDistinguishedName[nameDex]; + nameOid = &nameArray[nameDex]; + rdn->numberOfPairs = 1; + rdn->AttributeTypeAndValue = (CSSM_X509_TYPE_VALUE_PAIR_PTR) + malloc(sizeof(CSSM_X509_TYPE_VALUE_PAIR)); + CSSM_X509_TYPE_VALUE_PAIR_PTR atvp = rdn->AttributeTypeAndValue; + tpCopyCssmData(*this, nameOid->oid, &atvp->type); + atvp->value.Length = strlen(nameOid->string); + if(tpCompareOids(&CSSMOID_CountryName, nameOid->oid)) { + /* + * Country handled differently per RFC 3280 - must be printable, + * max of two characters in length + */ + if(atvp->value.Length > 2) { + CssmError::throwMe(CSSMERR_TP_INVALID_DATA); + } + for(unsigned dex=0; dexvalue.Length; dex++) { + int c = nameOid->string[dex]; + if(!isprint(c) || (c == EOF)) { + CssmError::throwMe(CSSMERR_TP_INVALID_DATA); + } + } + atvp->valueType = BER_TAG_PRINTABLE_STRING; + } + /* other special cases per RFC 3280 */ + else if(tpCompareOids(&CSSMOID_DNQualifier, nameOid->oid)) { + atvp->valueType = BER_TAG_PRINTABLE_STRING; + } + else if(tpCompareOids(&CSSMOID_SerialNumber, nameOid->oid)) { + atvp->valueType = BER_TAG_PRINTABLE_STRING; + } + else if(tpCompareOids(&CSSMOID_EmailAddress, nameOid->oid)) { + atvp->valueType = BER_TAG_IA5_STRING; + } + else { + /* Default type */ + atvp->valueType = BER_TAG_PKIX_UTF8_STRING; + } + atvp->value.Data = (uint8 *)malloc(atvp->value.Length); + memmove(atvp->value.Data, nameOid->string, atvp->value.Length); + } + return top; +} + +/* free the CSSM_X509_NAME obtained from buildX509Name */ +void AppleTPSession::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]; + free(atvp->type.Data); + free(atvp->value.Data); + } + free(rdn->AttributeTypeAndValue); + } + } + free(top->RelativeDistinguishedName); + free(top); +} + +/* Obtain a CSSM_X509_TIME representing "now" plus specified seconds */ + +/* + * Although RFC 2459, *the* spec for X509 certs, allows for not before/after + * times to be expressed in ther generalized (4-digit year) or UTC (2-digit year + * with implied century rollover), IE 5 on Mac will not accept the generalized + * format. + */ +#define TP_FOUR_DIGIT_YEAR 0 +#if TP_FOUR_DIGIT_YEAR +#define TP_TIME_FORMAT TIME_GEN +#define TP_TIME_TAG BER_TAG_GENERALIZED_TIME +#else +#define TP_TIME_FORMAT TIME_UTC +#define TP_TIME_TAG BER_TAG_UTC_TIME +#endif /* TP_FOUR_DIGIT_YEAR */ + +CSSM_X509_TIME * AppleTPSession::buildX509Time( + unsigned secondsFromNow) +{ + CSSM_X509_TIME *xtime = (CSSM_X509_TIME *)malloc(sizeof(CSSM_X509_TIME)); + xtime->timeType = TP_TIME_TAG; + char *ts = (char *)malloc(GENERALIZED_TIME_STRLEN + 1); + { + StLock _(tpTimeLock()); + timeAtNowPlus(secondsFromNow, TP_TIME_FORMAT, ts); + } + xtime->time.Data = (uint8 *)ts; + xtime->time.Length = strlen(ts); + return xtime; +} + +/* Free CSSM_X509_TIME obtained in buildX509Time */ +void AppleTPSession::freeX509Time( + CSSM_X509_TIME *xtime) +{ + if(xtime == NULL) { + return; + } + free((char *)xtime->time.Data); + free(xtime); +} + +/* + * Cook up a CSSM_DATA with specified integer, DER style (minimum number of + * bytes, big-endian). + */ +static void intToDER( + CSSM_INTPTR theInt, + CSSM_DATA &DER_Data, + Allocator &alloc) +{ + /* + * Calculate length in bytes of encoded integer, minimum length of 1. + */ + DER_Data.Length = 1; + uintptr_t unsignedInt = (uintptr_t)theInt; + while(unsignedInt > 0xff) { + DER_Data.Length++; + unsignedInt >>= 8; + } + + /* + * DER encoding requires top bit to be zero, else it's a negative number. + * Even though we're passing around integers as CSSM_INTPTR, they really are + * always unsigned. + * unsignedInt contains the m.s. byte of theInt in its l.s. byte. + */ + if(unsignedInt & 0x80) { + DER_Data.Length++; + } + + DER_Data.Data = (uint8 *)alloc.malloc(DER_Data.Length); + uint8 *dst = DER_Data.Data + DER_Data.Length - 1; + unsignedInt = (uintptr_t)theInt; + for(unsigned dex=0; dex>= 8; + } +} + +/* The reverse of the above. */ +static CSSM_INTPTR DERToInt( + const CSSM_DATA &DER_Data) +{ + CSSM_INTPTR rtn = 0; + uint8 *bp = DER_Data.Data; + for(unsigned dex=0; dexKeyHeader.BlobType) { + case CSSM_KEYBLOB_RAW: + actPubKey = subjectPubKey; + break; + case CSSM_KEYBLOB_REFERENCE: + refKeyToRaw(cspHand, subjectPubKey, &rawPubKey); + actPubKey = &rawPubKey; + freeRawKey = CSSM_TRUE; + break; + default: + tpCredDebug("CSSM_CL_CertCreateTemplate: bad key blob type (%u)", + (unsigned)subjectPubKey->KeyHeader.BlobType); + CssmError::throwMe(CSSMERR_TP_INVALID_REQUEST_INPUTS); + } + + + /* + * version, always 2 (X509v3) + * serialNumber thru subjectPubKey + */ + unsigned numFields = 8 + numExtensions; + if(subjectUniqueId) { + numFields++; + } + if(issuerUniqueId) { + numFields++; + } + + certTemp = (CSSM_FIELD *)malloc(sizeof(CSSM_FIELD) * numFields); + + + /* version */ + intToDER(2, versionDER, *this); + certTemp[fieldDex].FieldOid = CSSMOID_X509V1Version; + certTemp[fieldDex++].FieldValue = versionDER; + + /* serial number */ + intToDER(serialNumber, serialDER, *this); + 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 *)actPubKey; + 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); + } + assert(fieldDex == numFields); + + /* + * OK, here we go + */ + rawCert = (CSSM_DATA_PTR)malloc(sizeof(CSSM_DATA)); + rawCert->Data = NULL; + rawCert->Length = 0; + CSSM_RETURN crtn = CSSM_CL_CertCreateTemplate(clHand, + fieldDex, + certTemp, + rawCert); + if(crtn) { + tpCredDebug("CSSM_CL_CertCreateTemplate returned %ld", (long)crtn); + free(rawCert->Data); + free(rawCert); + rawCert = NULL; + } + + /* free the stuff we mallocd to get here */ + free(serialDER.Data); + free(versionDER.Data); + free(certTemp); + if(freeRawKey) { + tpFreeCssmData(*this, &rawPubKey.KeyData, CSSM_FALSE); + } + if(crtn) { + CssmError::throwMe(crtn); + } +} + +/* given a cert and a ReferenceIdentifier, fill in ReferenceIdentifier and + * add it and the cert to tpCredMap. */ +void AppleTPSession::addCertToMap( + const CSSM_DATA *cert, + CSSM_DATA_PTR refId) +{ + StLock _(tpCredMapLock); + + TpCredHandle hand = reinterpret_cast(cert); + intToDER(hand, *refId, *this); + tpCredMap[hand] = cert; +} + +/* given a ReferenceIdentifier, obtain associated cert and remove from the map */ +CSSM_DATA_PTR AppleTPSession::getCertFromMap( + const CSSM_DATA *refId) +{ + StLock _(tpCredMapLock); + CSSM_DATA_PTR rtn = NULL; + + if((refId == NULL) || (refId->Data == NULL)) { + return NULL; + } + TpCredHandle hand = DERToInt(*refId); + credMap::iterator it = tpCredMap.find(hand); + if(it == tpCredMap.end()) { + return NULL; + } + rtn = const_cast(it->second); + tpCredMap.erase(hand); + return rtn; +} + +/* + * SubmitCredRequest, CSR form. + */ +void AppleTPSession::SubmitCsrRequest( + const CSSM_TP_REQUEST_SET &RequestInput, + const CSSM_TP_CALLERAUTH_CONTEXT *CallerAuthContext, + sint32 &EstimatedTime, // RETURNED + CssmData &ReferenceIdentifier) // RETURNED +{ + CSSM_DATA_PTR csrPtr = NULL; + CSSM_CC_HANDLE sigHand = 0; + CSSM_APPLE_CL_CSR_REQUEST csrReq; + + memset(&csrReq, 0, sizeof(csrReq)); + + /* for now we're using the same struct for input as the the normal + * X509 cert request. */ + CSSM_APPLE_TP_CERT_REQUEST *certReq = + (CSSM_APPLE_TP_CERT_REQUEST *)RequestInput.Requests; + if((certReq->cspHand == 0) || + (certReq->clHand == 0) || + (certReq->certPublicKey == NULL) || + (certReq->issuerPrivateKey == NULL) || + (certReq->signatureOid.Data == NULL)) { + CssmError::throwMe(CSSMERR_TP_INVALID_REQUEST_INPUTS); + } + + /* convert ref public key to raw per CL requirements */ + const CSSM_KEY *subjectPubKey = certReq->certPublicKey; + const CSSM_KEY *actPubKey = NULL; + CSSM_BOOL freeRawKey = CSSM_FALSE; + CSSM_KEY rawPubKey; + + switch(subjectPubKey->KeyHeader.BlobType) { + case CSSM_KEYBLOB_RAW: + actPubKey = subjectPubKey; + break; + case CSSM_KEYBLOB_REFERENCE: + refKeyToRaw(certReq->cspHand, subjectPubKey, &rawPubKey); + actPubKey = &rawPubKey; + freeRawKey = CSSM_TRUE; + break; + default: + tpCredDebug("SubmitCsrRequest: bad key blob type (%u)", + (unsigned)subjectPubKey->KeyHeader.BlobType); + CssmError::throwMe(CSSMERR_TP_INVALID_REQUEST_INPUTS); + } + + /* cook up a CL-passthrough-specific request */ + csrReq.subjectNameX509 = buildX509Name(certReq->subjectNames, + certReq->numSubjectNames); + csrReq.signatureAlg = certReq->signatureAlg; + csrReq.signatureOid = certReq->signatureOid; + csrReq.cspHand = certReq->cspHand; + csrReq.subjectPublicKey = actPubKey; + csrReq.subjectPrivateKey = certReq->issuerPrivateKey; + csrReq.challengeString = certReq->challengeString; + + /* A crypto handle to pass to the CL */ + CSSM_RETURN crtn; + crtn = CSSM_CSP_CreateSignatureContext(certReq->cspHand, + certReq->signatureAlg, + (CallerAuthContext ? CallerAuthContext->CallerCredentials : NULL), + certReq->issuerPrivateKey, + &sigHand); + if(crtn) { + tpCredDebug("CSSM_CSP_CreateSignatureContext returned %ld", (long)crtn); + goto abort; + } + + /* down to the CL to do the actual work */ + crtn = CSSM_CL_PassThrough(certReq->clHand, + sigHand, + CSSM_APPLEX509CL_OBTAIN_CSR, + &csrReq, + (void **)&csrPtr); + if(crtn) { + tpCredDebug("CSSM_CL_PassThrough returned %ld", (long)crtn); + goto abort; + } + + /* save it for retrieval by RetrieveCredResult */ + addCertToMap(csrPtr, &ReferenceIdentifier); + EstimatedTime = 0; + +abort: + /* free local resources */ + if(csrReq.subjectNameX509) { + freeX509Name(csrReq.subjectNameX509); + } + if(sigHand) { + CSSM_DeleteContext(sigHand); + } + if(freeRawKey) { + tpFreeCssmData(*this, &rawPubKey.KeyData, CSSM_FALSE); + } + if(crtn) { + CssmError::throwMe(crtn); + } +} + +/* + * Submit cred (cert) request. Currently the only form of request we + * handle is the basis "sign this cert with key right now", with policy OI + * CSSMOID_APPLE_TP_LOCAL_CERT_GEN. + */ +void AppleTPSession::SubmitCredRequest( + const CSSM_TP_AUTHORITY_ID *PreferredAuthority, + CSSM_TP_AUTHORITY_REQUEST_TYPE RequestType, + const CSSM_TP_REQUEST_SET &RequestInput, + const CSSM_TP_CALLERAUTH_CONTEXT *CallerAuthContext, + sint32 &EstimatedTime, + CssmData &ReferenceIdentifier) +{ + /* free all of these on return if non-NULL */ + CSSM_DATA_PTR certTemplate = NULL; + CSSM_X509_TIME_PTR notBeforeX509 = NULL; + CSSM_X509_TIME_PTR notAfterX509 = NULL; + CSSM_X509_NAME_PTR subjectX509 = NULL; + CSSM_X509_NAME_PTR issuerX509 = NULL; + CSSM_X509_EXTENSION_PTR extens509 = NULL; + CSSM_CC_HANDLE sigContext = 0; + + /* this gets saved on success */ + CSSM_DATA_PTR signedCert = NULL; + + /* validate rather limited set of input args */ + if(PreferredAuthority != NULL) { + CssmError::throwMe(CSSMERR_TP_INVALID_AUTHORITY); + } + if(RequestType != CSSM_TP_AUTHORITY_REQUEST_CERTISSUE) { + CssmError::throwMe(CSSMERR_TP_UNSUPPORTED_SERVICE); + } + if(CallerAuthContext == NULL) { + CssmError::throwMe(CSSMERR_TP_INVALID_CALLERAUTH_CONTEXT_POINTER); + } + if((RequestInput.NumberOfRequests != 1) || + (RequestInput.Requests == NULL)) { + CssmError::throwMe(CSSMERR_TP_INVALID_REQUEST_INPUTS); + } + + /* Apple-specific args */ + const CSSM_TP_POLICYINFO *tpPolicy = &CallerAuthContext->Policy; + if((tpPolicy->NumberOfPolicyIds != 1) || + (tpPolicy->PolicyIds == NULL)) { + CssmError::throwMe(CSSMERR_TP_INVALID_CALLERAUTH_CONTEXT_POINTER); + } + if(tpCompareCssmData(&tpPolicy->PolicyIds->FieldOid, + &CSSMOID_APPLE_TP_CSR_GEN)) { + /* break out to CSR-specific code */ + SubmitCsrRequest(RequestInput, CallerAuthContext, EstimatedTime, ReferenceIdentifier); + return; + } + else if(!tpCompareCssmData(&tpPolicy->PolicyIds->FieldOid, + &CSSMOID_APPLE_TP_LOCAL_CERT_GEN)) { + CssmError::throwMe(CSSMERR_TP_INVALID_POLICY_IDENTIFIERS); + } + + CSSM_APPLE_TP_CERT_REQUEST *certReq = + (CSSM_APPLE_TP_CERT_REQUEST *)RequestInput.Requests; + if((certReq->cspHand == 0) || + (certReq->clHand == 0) || + (certReq->certPublicKey == NULL) || + (certReq->issuerPrivateKey == NULL)) { + CssmError::throwMe(CSSMERR_TP_INVALID_REQUEST_INPUTS); + } + if((certReq->numExtensions != 0) & (certReq->extensions == NULL)) { + CssmError::throwMe(CSSMERR_TP_INVALID_POINTER); + } + + CSSM_RETURN ourRtn = CSSM_OK; + + try { + /* convert caller's friendly names and times to CDSA style */ + subjectX509 = buildX509Name(certReq->subjectNames, certReq->numSubjectNames); + if(certReq->issuerNames != NULL) { + issuerX509 = buildX509Name(certReq->issuerNames, certReq->numIssuerNames); + } + else if(certReq->issuerNameX509) { + /* caller obtained this from an existing signer's cert */ + issuerX509 = certReq->issuerNameX509; + } + else { + /* self-signed */ + issuerX509 = subjectX509; + } + notBeforeX509 = buildX509Time(certReq->notBefore); + notAfterX509 = buildX509Time(certReq->notAfter); + + if(certReq->numExtensions != 0) { + /* convert extensions array from CE_DataAndType to CSSM_X509_EXTENSION */ + extens509 = (CSSM_X509_EXTENSION *)malloc(sizeof(CSSM_X509_EXTENSION) * + certReq->numExtensions); + memset(extens509, 0, sizeof(CSSM_X509_EXTENSION) * + certReq->numExtensions); + for(unsigned dex=0; dexnumExtensions; dex++) { + CSSM_X509_EXTENSION *extn = &extens509[dex]; + CE_DataAndType *cdt = &certReq->extensions[dex]; + void *parsedValue; + CSSM_OID extnId; + + switch(cdt->type) { + case DT_AuthorityKeyID: + parsedValue = &cdt->extension.authorityKeyID; + extnId = CSSMOID_AuthorityKeyIdentifier; + break; + case DT_SubjectKeyID: + parsedValue = &cdt->extension.subjectKeyID; + extnId = CSSMOID_SubjectKeyIdentifier; + break; + case DT_KeyUsage: + parsedValue = &cdt->extension.keyUsage; + extnId = CSSMOID_KeyUsage; + break; + case DT_SubjectAltName: + parsedValue = &cdt->extension.subjectAltName; + extnId = CSSMOID_SubjectAltName; + break; + case DT_IssuerAltName: + parsedValue = &cdt->extension.issuerAltName; + extnId = CSSMOID_IssuerAltName; + break; + case DT_ExtendedKeyUsage: + parsedValue = &cdt->extension.extendedKeyUsage; + extnId = CSSMOID_ExtendedKeyUsage; + break; + case DT_BasicConstraints: + parsedValue = &cdt->extension.basicConstraints; + extnId = CSSMOID_BasicConstraints; + break; + case DT_CertPolicies: + parsedValue = &cdt->extension.certPolicies; + extnId = CSSMOID_CertificatePolicies; + break; + case DT_NetscapeCertType: + parsedValue = &cdt->extension.netscapeCertType; + extnId = CSSMOID_NetscapeCertType; + break; + case DT_CrlDistributionPoints: + parsedValue = &cdt->extension.crlDistPoints; + extnId = CSSMOID_CrlDistributionPoints; + break; + case DT_AuthorityInfoAccess: + parsedValue = &cdt->extension.authorityInfoAccess; + extnId = CSSMOID_AuthorityInfoAccess; + break; + case DT_Other: + default: + tpCredDebug("SubmitCredRequest: DT_Other not supported"); + CssmError::throwMe(CSSMERR_TP_UNKNOWN_TAG); + // NOT REACHED + } + extn->extnId = extnId; + extn->critical = cdt->critical; + extn->format = CSSM_X509_DATAFORMAT_PARSED; + extn->value.parsedValue = parsedValue; + extn->BERvalue.Data = NULL; + extn->BERvalue.Length = 0; + } /* for each extension */ + } /* converting extensions */ + + /* cook up the unsigned template */ + makeCertTemplate(certReq->clHand, + certReq->cspHand, + certReq->serialNumber, + issuerX509, + subjectX509, + notBeforeX509, + notAfterX509, + certReq->certPublicKey, + certReq->signatureOid, + NULL, // subjectUniqueID, not used here (yet) + NULL, // issuerUniqueId + extens509, + certReq->numExtensions, + certTemplate); + + /* create signature context */ + ourRtn = CSSM_CSP_CreateSignatureContext(certReq->cspHand, + certReq->signatureAlg, + (CallerAuthContext ? CallerAuthContext->CallerCredentials : NULL), + certReq->issuerPrivateKey, + &sigContext); + if(ourRtn) { + tpCredDebug("CSSM_CSP_CreateSignatureContext returned %ld", (long)ourRtn); + CssmError::throwMe(ourRtn); + } + + signedCert = (CSSM_DATA_PTR)malloc(sizeof(CSSM_DATA)); + signedCert->Data = NULL; + signedCert->Length = 0; + ourRtn = CSSM_CL_CertSign(certReq->clHand, + sigContext, + certTemplate, // CertToBeSigned + NULL, // SignScope + 0, // ScopeSize, + signedCert); + if(ourRtn) { + tpCredDebug("CSSM_CL_CertSign returned %ld", (long)ourRtn); + CssmError::throwMe(ourRtn); + } + + /* save it for retrieval by RetrieveCredResult */ + addCertToMap(signedCert, &ReferenceIdentifier); + EstimatedTime = 0; + } + catch (const CssmError &cerr) { + tpCredDebug("SubmitCredRequest: CSSM error %ld", (long)cerr.error); + ourRtn = cerr.error; + } + catch(...) { + tpCredDebug("SubmitCredRequest: unknown exception"); + ourRtn = CSSMERR_TP_INTERNAL_ERROR; // ?? + } + + /* free reources */ + tpFreeCssmData(*this, certTemplate, CSSM_TRUE); + freeX509Name(subjectX509); + if(certReq->issuerNames) { + freeX509Name(issuerX509); + } + /* else same as subject */ + freeX509Time(notBeforeX509); + freeX509Time(notAfterX509); + if(extens509) { + free(extens509); + } + if(sigContext != 0) { + CSSM_DeleteContext(sigContext); + } + if(ourRtn) { + CssmError::throwMe(ourRtn); + } +} + +void AppleTPSession::RetrieveCredResult( + const CssmData &ReferenceIdentifier, + const CSSM_TP_CALLERAUTH_CONTEXT *CallerAuthCredentials, + sint32 &EstimatedTime, + CSSM_BOOL &ConfirmationRequired, + CSSM_TP_RESULT_SET_PTR &RetrieveOutput) +{ + CSSM_DATA *cert = getCertFromMap(&ReferenceIdentifier); + + if(cert == NULL) { + tpCredDebug("RetrieveCredResult: refId not found"); + CssmError::throwMe(CSSMERR_TP_INVALID_IDENTIFIER); + } + + /* CSSM_TP_RESULT_SET.Results points to a CSSM_ENCODED_CERT */ + CSSM_ENCODED_CERT *encCert = (CSSM_ENCODED_CERT *)malloc(sizeof(CSSM_ENCODED_CERT)); + encCert->CertType = CSSM_CERT_X_509v3; + encCert->CertEncoding = CSSM_CERT_ENCODING_DER; + + /* + * caller must free all three: + * CSSM_TP_RESULT_SET_PTR RetrieveOutput + * RetrieveOutput->Results (CSSM_ENCODED_CERT *encCert) + * encCert->CertBlob.Data (the actual cert) + * We free: + * cert -- mallocd in SubmitCredRequest + */ + encCert->CertBlob = *cert; + RetrieveOutput = (CSSM_TP_RESULT_SET_PTR)malloc( + sizeof(CSSM_TP_RESULT_SET)); + RetrieveOutput->Results = encCert; + RetrieveOutput->NumberOfResults = 1; + ConfirmationRequired = CSSM_FALSE; + free(cert); + EstimatedTime = 0; +} diff --git a/libsecurity_apple_x509_tp/lib/tpCrlVerify.cpp b/libsecurity_apple_x509_tp/lib/tpCrlVerify.cpp new file mode 100644 index 00000000..71007b79 --- /dev/null +++ b/libsecurity_apple_x509_tp/lib/tpCrlVerify.cpp @@ -0,0 +1,469 @@ +/* + * 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'). + * 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. + */ + + +/* + * tpCrlVerify.cpp - routines to verify CRLs and to verify certs against CRLs. + */ + +#include "tpCrlVerify.h" +#include "TPCertInfo.h" +#include "TPCrlInfo.h" +#include "tpOcspVerify.h" +#include "tpdebugging.h" +#include "TPNetwork.h" +#include "TPDatabase.h" +#include +#include +#include +#include +#include +#include +#include + +/* general purpose, switch to policy-specific code based on TPVerifyContext.policy */ +CSSM_RETURN tpRevocationPolicyVerify( + TPVerifyContext &tpVerifyContext, + TPCertGroup &certGroup) +{ + switch(tpVerifyContext.policy) { + case kRevokeNone: + return CSSM_OK; + case kRevokeCrlBasic: + return tpVerifyCertGroupWithCrls(tpVerifyContext, certGroup); + case kRevokeOcsp: + return tpVerifyCertGroupWithOCSP(tpVerifyContext, certGroup); + default: + assert(0); + return CSSMERR_TP_INTERNAL_ERROR; + } +} + +/* + * For now, a process-wide memory resident CRL cache. + * We are responsible for deleting the CRLs which get added to this + * cache. Currently the only time we add a CRL to this cache is + * when we fetch one from the net. We ref count CRLs in this cache + * to allow multi-threaded access. + * Entries do not persist past the tpVerifyCertGroupWithCrls() in + * which they were created unless another thread in the same + * process snags a refcount (also from tpVerifyCertGroupWithCrls()). + * I.e. when cert verification is complete the cache will be empty. + * This is a change from Tiger and previous. CRLs get pretty big, + * up to a megabyte or so, and it's just not worth it to keep those + * around in memory. (OCSP responses, which are much smaller than + * CRLs, are indeed cached in memory. See tpOcspCache.cpp.) + */ +class TPCRLCache : private TPCrlGroup +{ +public: + TPCRLCache(); + ~TPCRLCache() { } + TPCrlInfo *search( + TPCertInfo &cert, + TPVerifyContext &vfyCtx); + void add( + TPCrlInfo &crl); + void remove( + TPCrlInfo &crl); + void release( + TPCrlInfo &crl); + +private: + /* Protects ref count of all members of the cache */ + Mutex mLock; +}; + +TPCRLCache::TPCRLCache() + : TPCrlGroup(Allocator::standard(), TGO_Group) +{ + +} + +TPCrlInfo *TPCRLCache::search( + TPCertInfo &cert, + TPVerifyContext &vfyCtx) +{ + StLock _(mLock); + TPCrlInfo *crl = findCrlForCert(cert); + if(crl) { + /* reevaluate validity */ + crl->calculateCurrent(vfyCtx.verifyTime); + crl->mRefCount++; + tpCrlDebug("TPCRLCache hit"); + } + else { + tpCrlDebug("TPCRLCache miss"); + } + return crl; +} + +/* bumps ref count - caller is going to be using the CRL */ +void TPCRLCache::add( + TPCrlInfo &crl) +{ + StLock _(mLock); + tpCrlDebug("TPCRLCache add"); + crl.mRefCount++; + appendCrl(crl); +} + +/* delete and remove from cache if refCount zero */ +void TPCRLCache::release( + TPCrlInfo &crl) +{ + StLock _(mLock); + assert(crl.mRefCount > 0); + crl.mRefCount--; + if(crl.mRefCount == 0) { + tpCrlDebug("TPCRLCache release; deleting"); + removeCrl(crl); + delete &crl; + } + else { + tpCrlDebug("TPCRLCache release; in use"); + } +} + +static ModuleNexus tpGlobalCrlCache; + +/* + * Find CRL for specified cert. Only returns a fully verified CRL. + * Cert-specific errors such as CSSMERR_APPLETP_CRL_NOT_FOUND will be added + * to cert's return codes. + */ +static CSSM_RETURN tpFindCrlForCert( + TPCertInfo &subject, + TPCrlInfo *&foundCrl, // RETURNED + TPVerifyContext &vfyCtx) +{ + + tpCrlDebug("tpFindCrlForCert top"); + TPCrlInfo *crl = NULL; + foundCrl = NULL; + CSSM_APPLE_TP_CRL_OPT_FLAGS crlOptFlags = 0; + + if(vfyCtx.crlOpts) { + crlOptFlags = vfyCtx.crlOpts->CrlFlags; + } + + /* Search inputCrls for a CRL for subject cert */ + if(vfyCtx.inputCrls != NULL) { + crl = vfyCtx.inputCrls->findCrlForCert(subject); + if(crl && (crl->verifyWithContextNow(vfyCtx, &subject) == CSSM_OK)) { + foundCrl = crl; + crl->mFromWhere = CFW_InGroup; + tpCrlDebug(" ...CRL found in CrlGroup"); + return CSSM_OK; + } + } + + /* local process-wide cache */ + crl = tpGlobalCrlCache().search(subject, vfyCtx); + if(crl) { + tpCrlDebug("...tpFindCrlForCert found CRL in cache, calling verifyWithContext"); + if(crl->verifyWithContextNow(vfyCtx, &subject) == CSSM_OK) { + foundCrl = crl; + crl->mFromWhere = CFW_LocalCache; + tpCrlDebug(" ...CRL found in local cache"); + return CSSM_OK; + } + else { + tpGlobalCrlCache().release(*crl); + } + } + + /* + * Try DL/DB. + * Note tpDbFindIssuerCrl() returns a verified CRL. + */ + crl = tpDbFindIssuerCrl(vfyCtx, *subject.issuerName(), subject); + if(crl) { + foundCrl = crl; + crl->mFromWhere = CFW_DlDb; + tpCrlDebug(" ...CRL found in DlDb"); + return CSSM_OK; + } + + /* Last resort: try net if enabled */ + CSSM_RETURN crtn = CSSMERR_APPLETP_CRL_NOT_FOUND; + crl = NULL; + if(crlOptFlags & CSSM_TP_ACTION_FETCH_CRL_FROM_NET) { + crtn = tpFetchCrlFromNet(subject, vfyCtx, crl); + } + + if(crtn) { + tpCrlDebug(" ...tpFindCrlForCert: CRL not found"); + if(subject.addStatusCode(crtn)) { + return crtn; + } + else { + return CSSM_OK; + } + } + + /* got one from net - add to global cache */ + assert(crl != NULL); + tpGlobalCrlCache().add(*crl); + crl->mFromWhere = CFW_Net; + tpCrlDebug(" ...CRL found from net"); + + foundCrl = crl; + return CSSM_OK; +} + +/* + * Dispose of a CRL obtained from tpFindCrlForCert(). + */ +static void tpDisposeCrl( + TPCrlInfo &crl, + TPVerifyContext &vfyCtx) +{ + switch(crl.mFromWhere) { + case CFW_Nowhere: + default: + assert(0); + CssmError::throwMe(CSSMERR_TP_INTERNAL_ERROR); + case CFW_InGroup: + /* nothing to do, handled by TPCrlGroup */ + return; + case CFW_DlDb: + /* cooked up specially for this call */ + delete &crl; + return; + case CFW_LocalCache: // cache hit + case CFW_Net: // fetched from net & added to cache + tpGlobalCrlCache().release(crl); + return; + /* probably others */ + } +} + +/* + * Does this cert have a CrlDistributionPoints extension? We don't parse it, we + * just tell the caller whether or not it has one. + */ +static bool tpCertHasCrlDistPt( + TPCertInfo &cert) +{ + CSSM_DATA_PTR fieldValue; + CSSM_RETURN crtn = cert.fetchField(&CSSMOID_CrlDistributionPoints, &fieldValue); + if(crtn) { + return false; + } + else { + cert.freeField(&CSSMOID_CrlDistributionPoints, fieldValue); + return true; + } +} + +/* + * Get current CRL status for a certificate and its issuers. + * + * Possible results: + * + * CSSM_OK (we have a valid CRL; certificate is not revoked) + * CSSMERR_TP_CERT_REVOKED (we have a valid CRL; certificate is revoked) + * CSSMERR_APPLETP_NETWORK_FAILURE (CRL not available, download in progress) + * CSSMERR_APPLETP_CRL_NOT_FOUND (CRL not available, and not being fetched) + * CSSMERR_TP_INTERNAL_ERROR (unexpected error) + * + * Note that ocspdCRLStatus does NOT wait for the CRL to be downloaded before + * returning, nor does it initiate a CRL download. + */ +CSSM_RETURN tpGetCrlStatusForCert( + TPCertInfo &subject, + const CSSM_DATA &issuers) +{ + CSSM_DATA *serialNumber=NULL; + CSSM_RETURN crtn = subject.fetchField(&CSSMOID_X509V1SerialNumber, &serialNumber); + if(crtn || !serialNumber) { + return CSSMERR_TP_INTERNAL_ERROR; + } + crtn = ocspdCRLStatus(*serialNumber, issuers, subject.issuerName(), NULL); + subject.freeField(&CSSMOID_X509V1SerialNumber, serialNumber); + return crtn; +} + +/* + * Perform CRL verification on a cert group. + * The cert group has already passed basic issuer/subject and signature + * verification. The status of the incoming CRLs is completely unknown. + * + * FIXME - No mechanism to get CRLs from net with non-NULL verifyTime. + * How are we supposed to get the CRL which was valid at a specified + * time in the past? + */ +CSSM_RETURN tpVerifyCertGroupWithCrls( + TPVerifyContext &vfyCtx, + TPCertGroup &certGroup) // to be verified +{ + CSSM_RETURN crtn; + CSSM_RETURN ourRtn = CSSM_OK; + + assert(vfyCtx.clHand != 0); + assert(vfyCtx.policy == kRevokeCrlBasic); + tpCrlDebug("tpVerifyCertGroupWithCrls numCerts %u", certGroup.numCerts()); + CSSM_DATA issuers = { 0, NULL }; + CSSM_APPLE_TP_CRL_OPT_FLAGS optFlags = 0; + if(vfyCtx.crlOpts != NULL) { + optFlags = vfyCtx.crlOpts->CrlFlags; + } + + /* found & verified CRLs we need to release */ + TPCrlGroup foundCrls(vfyCtx.alloc, TGO_Caller); + + try { + + unsigned certDex; + TPCrlInfo *crl = NULL; + + /* get issuers as PEM-encoded data blob; we need to release */ + certGroup.encodeIssuers(issuers); + + /* main loop, verify each cert */ + for(certDex=0; certDexisAnchor() ? "anchor " : "", cert->index()); + if(cert->isSelfSigned() || cert->trustSettingsFound()) { + /* CRL meaningless for a root or trusted cert */ + continue; + } + if(cert->revokeCheckComplete()) { + /* Another revocation policy claimed that this cert is good to go */ + tpCrlDebug(" ...cert at index %u revokeCheckComplete; skipping", + cert->index()); + continue; + } + crl = NULL; + do { + /* first, see if we have CRL status available for this cert */ + crtn = tpGetCrlStatusForCert(*cert, issuers); + tpCrlDebug("...tpGetCrlStatusForCert: %u", crtn); + if(crtn == CSSM_OK) { + tpCrlDebug("tpVerifyCertGroupWithCrls: cert %u verified by local .crl\n", + cert->index()); + cert->revokeCheckGood(true); + if(optFlags & CSSM_TP_ACTION_CRL_SUFFICIENT) { + /* no more revocation checking necessary for this cert */ + cert->revokeCheckComplete(true); + } + break; + } + if(crtn == CSSMERR_TP_CERT_REVOKED) { + tpCrlDebug("tpVerifyCertGroupWithCrls: cert %u revoked in local .crl\n", + cert->index()); + cert->addStatusCode(crtn); + break; + } + if(crtn == CSSMERR_APPLETP_NETWORK_FAILURE) { + /* crl is being fetched from net, but we don't have it yet */ + if((optFlags & CSSM_TP_ACTION_REQUIRE_CRL_IF_PRESENT) && + tpCertHasCrlDistPt(*cert)) { + /* crl is required; we don't have it yet, so we fail */ + tpCrlDebug(" ...cert %u: REQUIRE_CRL_IF_PRESENT abort", + cert->index()); + break; + } + /* "Best Attempt" case, so give the cert a pass for now */ + tpCrlDebug(" ...cert %u: no CRL; tolerating", cert->index()); + crtn = CSSM_OK; + break; + } + /* all other CRL status results: try to fetch the CRL */ + + /* find a CRL for this cert by hook or crook */ + crtn = tpFindCrlForCert(*cert, crl, vfyCtx); + if(crtn) { + /* tpFindCrlForCert may have simply caused ocspd to start + * downloading a CRL asynchronously; depending on the speed + * of the network and the CRL size, this may return 0 bytes + * of data with a CSSMERR_APPLETP_NETWORK_FAILURE result. + * We won't know the actual revocation result until the + * next time we call tpGetCrlStatusForCert after the full + * CRL has been downloaded successfully. + */ + if(optFlags & CSSM_TP_ACTION_REQUIRE_CRL_PER_CERT) { + tpCrlDebug(" ...cert %u: REQUIRE_CRL_PER_CERT abort", + cert->index()); + break; + } + if((optFlags & CSSM_TP_ACTION_REQUIRE_CRL_IF_PRESENT) && + tpCertHasCrlDistPt(*cert)) { + tpCrlDebug(" ...cert %u: REQUIRE_CRL_IF_PRESENT abort", + cert->index()); + break; + } + /* + * This is the only place where "Best Attempt" tolerates an error + */ + tpCrlDebug(" ...cert %u: no CRL; tolerating", cert->index()); + crtn = CSSM_OK; + assert(crl == NULL); + break; + } + + /* Keep track; we'll release all when done. */ + assert(crl != NULL); + foundCrls.appendCrl(*crl); + + /* revoked? */ + crtn = crl->isCertRevoked(*cert, vfyCtx.verifyTime); + if(crtn) { + break; + } + tpCrlDebug(" ...cert %u VERIFIED by CRL", cert->index()); + cert->revokeCheckGood(true); + if(optFlags & CSSM_TP_ACTION_CRL_SUFFICIENT) { + /* no more revocation checking necessary for this cert */ + cert->revokeCheckComplete(true); + } + } while(0); + + /* done processing one cert */ + if(crtn) { + tpCrlDebug(" ...cert at index %u FAILED crl vfy", + cert->index()); + if(ourRtn == CSSM_OK) { + ourRtn = crtn; + } + /* continue on to next cert */ + } /* error on one cert */ + } /* for each cert */ + } + catch(const CssmError &cerr) { + if(ourRtn == CSSM_OK) { + ourRtn = cerr.error; + } + } + /* other exceptions fatal */ + + /* release all found CRLs */ + for(unsigned dex=0; dex +#include +#include +#include + +class TPCertInfo; +class TPCertGroup; +class TPCrlInfo; +class TPCrlGroup; + +/* + * Enumerated CRL policies enforced by this module. + */ +typedef enum { + kRevokeNone, /* no revocation checking */ + kRevokeCrlBasic, + kRevokeOcsp +} TPRevocationPolicy; + +/* Module-specific default policy */ +#define TP_CRL_POLICY_DEFAULT kRevokeNone + +/* + * Various parameters widely used in any operation involving CRL and + * OCSP verification. Most fields are optional. + */ +class TPVerifyContext { + NOCOPY(TPVerifyContext) +public: + TPVerifyContext( + Allocator &_alloc, + CSSM_CL_HANDLE _clHand, + CSSM_CSP_HANDLE _cspHand, + CSSM_TIMESTRING _verifyTime, + uint32 _numAnchorCerts, + const CSSM_DATA *_anchorCerts, + TPCertGroup *_signerCerts, + TPCrlGroup *_inputCrls, + TPCertGroup &_gatheredCerts, + CSSM_DL_DB_LIST_PTR _dbList, + TPRevocationPolicy _policy, + CSSM_APPLE_TP_ACTION_FLAGS _actionFlags, + CSSM_APPLE_TP_CRL_OPTIONS *_crlOpts, + CSSM_APPLE_TP_OCSP_OPTIONS *_ocspOpts, + const CSSM_OID *_policyOid, + const char *_policyStr, + uint32 _policyStrLen, + CSSM_KEYUSE _keyUse) + : alloc(_alloc), + clHand(_clHand), + cspHand(_cspHand), + verifyTime(_verifyTime), + numAnchorCerts(_numAnchorCerts), + anchorCerts(_anchorCerts), + signerCerts(_signerCerts), + inputCrls(_inputCrls), + gatheredCerts(_gatheredCerts), + dbList(_dbList), + policy(_policy), + actionFlags(_actionFlags), + crlOpts(_crlOpts), + ocspOpts(_ocspOpts), + policyOid(_policyOid), + policyStr(_policyStr), + policyStrLen(_policyStrLen), + keyUse(_keyUse) + { } + + ~TPVerifyContext() { } + + Allocator &alloc; + CSSM_CL_HANDLE clHand; + CSSM_CSP_HANDLE cspHand; + + /* + * NULL means "verify for this momemt", otherwise indicates + * time at which an entity is to be verified. + */ + CSSM_TIMESTRING verifyTime; + + /* trusted anchors */ + /* FIXME - maybe this should be a TPCertGroup */ + uint32 numAnchorCerts; + const CSSM_DATA *anchorCerts; + + /* + * Intermediate signing certs. Always present. + * This could come from the raw cert group to be verified + * in CertGroupVerify(), or the explicit SignerCertGroup in + * CrlVerify(). IN both cases the cert group owns the certs and + * eventually frees them. These certs have not been verified in any + * way other than to ensure that they parse and have been cached + * by the CL. + */ + TPCertGroup *signerCerts; + + /* Raw CRLs provided by caller, state unknown, optional */ + TPCrlGroup *inputCrls; + + /* + * Other certificates gathered during the course of this operation, + * currently consisting of certs fetched from DBs and from the net. + * This is currently set to AppleTPSession::CertGroupVerify's + * certsToBeFreed, to include certs fetched from the net (a + * significant optimization) and from DLDB (a side effect, also + * a slight optimization). + */ + TPCertGroup &gatheredCerts; + + /* can contain certs and/or CRLs */ + CSSM_DL_DB_LIST_PTR dbList; + + TPRevocationPolicy policy; + CSSM_APPLE_TP_ACTION_FLAGS actionFlags; + + /* one of these valid, depends on policy */ + const CSSM_APPLE_TP_CRL_OPTIONS *crlOpts; + const CSSM_APPLE_TP_OCSP_OPTIONS *ocspOpts; + + /* optional user trust parameters */ + const CSSM_OID *policyOid; + const char *policyStr; + uint32 policyStrLen; + CSSM_KEYUSE keyUse; +}; + +extern "C" { + +/* CRL - specific */ +CSSM_RETURN tpVerifyCertGroupWithCrls( + TPVerifyContext &tpVerifyContext, + TPCertGroup &certGroup); // to be verified + +/* general purpose, switch to policy-specific code based on TPVerifyContext.policy */ +CSSM_RETURN tpRevocationPolicyVerify( + TPVerifyContext &tpVerifyContext, + TPCertGroup &certGroup); // to be verified + +} + +#endif /* _TP_CRL_VERIFY_H_ */ diff --git a/libsecurity_apple_x509_tp/lib/tpOcspCache.cpp b/libsecurity_apple_x509_tp/lib/tpOcspCache.cpp new file mode 100644 index 00000000..cbb24ef5 --- /dev/null +++ b/libsecurity_apple_x509_tp/lib/tpOcspCache.cpp @@ -0,0 +1,319 @@ +/* + * 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@ + */ + +/* + * tpOcspCache.cpp - local OCSP response cache. + */ + +#include "tpOcspCache.h" +#include "tpdebugging.h" +#include "certGroupUtils.h" +#include +#include +#include +#include + +/* + * Set this flag nonzero to turn off this cache module. Generally used to debug + * the ocspd disk cache. + */ +#ifndef NDEBUG +#define TP_OCSP_CACHE_DISABLE 0 +#else +/* cache always enabled in production build */ +#define TP_OCSP_CACHE_DISABLE 0 +#endif + +#pragma mark ---- single cache entry ---- + +/* + * One cache entry, just a parsed OCSPResponse plus an optional URI and a + * "latest" nextUpdate time. An entry is stale when its nextUpdate time has + * come and gone. + */ +class OcspCacheEntry : public OCSPResponse +{ +public: + OcspCacheEntry( + const CSSM_DATA derEncoded, + const CSSM_DATA *localResponder); // optional + ~OcspCacheEntry(); + + /* a trusting environment, this module...all public */ + CSSM_DATA mLocalResponder; // we new[] +}; + +OcspCacheEntry::OcspCacheEntry( + const CSSM_DATA derEncoded, + const CSSM_DATA *localResponder) // optional + : OCSPResponse(derEncoded, TP_OCSP_CACHE_TTL) +{ + if(localResponder) { + mLocalResponder.Data = new uint8[localResponder->Length]; + mLocalResponder.Length = localResponder->Length; + memmove(mLocalResponder.Data, localResponder->Data, localResponder->Length); + } + else { + mLocalResponder.Data = NULL; + mLocalResponder.Length = 0; + } +} + +OcspCacheEntry::~OcspCacheEntry() +{ + delete[] mLocalResponder.Data; +} + +#pragma mark ---- global cache object ---- + +/* + * The cache object; ModuleNexus provides each task with at most of of these. + * All ops which affect the contents of the cache hold the (essentially) global + * mCacheLock. + */ +class OcspCache +{ +public: + OcspCache(); + ~OcspCache(); + + /* The methods corresponding to this module's public interface */ + OCSPSingleResponse *lookup( + OCSPClientCertID &certID, + const CSSM_DATA *localResponderURI); // optional + void addResponse( + const CSSM_DATA &ocspResp, // we'll decode it + const CSSM_DATA *localResponderURI); // optional + void flush( + OCSPClientCertID &certID); + +private: + void removeEntry(unsigned dex); + void scanForStale(); + OCSPSingleResponse *lookupPriv( + OCSPClientCertID &certID, + const CSSM_DATA *localResponderURI, // optional + unsigned &rtnDex); // RETURNED on success + + Mutex mCacheLock; + + /* + * NOTE: I am aware that most folks would just use an array<> here, but + * gdb is so lame that it doesn't even let one examine the contents + * of an array<> (or just about anything else in the STL). I prefer + * debuggability over saving a few lines of trivial code. + */ + OcspCacheEntry **mEntries; // just an array of pointers + unsigned mNumEntries; // valid entries in mEntries + unsigned mSizeofEntries; // mallocd space in mEntries +}; + +OcspCache::OcspCache() + : mEntries(NULL), mNumEntries(0), mSizeofEntries(0) +{ + +} + +/* As of Tiger I believe that this code never runs */ +OcspCache::~OcspCache() +{ + for(unsigned dex=0; dexexpireTime() < now) { + tpOcspCacheDebug("OcspCache::scanForStale: deleting stale entry %p", + entry); + removeEntry(dex); + foundOne = true; + break; + } + } + } while(foundOne); +} + +/* + * Private lookup routine. Caller holds mCacheLock. We return both an + * OCSPSingleResponse and the index into mEntries at which we found it. + */ + OCSPSingleResponse *OcspCache::lookupPriv( + OCSPClientCertID &certID, + const CSSM_DATA *localResponderURI, // optional + unsigned &rtnDex) // RETURNED on success +{ + OCSPSingleResponse *resp = NULL; + for(unsigned dex=0; dexmLocalResponder.Data == NULL) { + /* came from somewhere else, skip it */ + tpOcspCacheDebug("OcspCache::lookup: uri mismatch (1) on entry %p", + entry); + continue; + } + if(!tpCompareCssmData(localResponderURI, &entry->mLocalResponder)) { + tpOcspCacheDebug("OcspCache::lookup: uri mismatch (2) on entry %p", + entry); + continue; + } + } + resp = entry->singleResponseFor(certID); + if(resp) { + tpOcspCacheDebug("OcspCache::lookupPriv: cache HIT on entry %p", entry); + rtnDex=dex; + return resp; + } + } + tpOcspCacheDebug("OcspCache::lookupPriv: cache MISS"); + return NULL; +} + +OCSPSingleResponse *OcspCache::lookup( + OCSPClientCertID &certID, + const CSSM_DATA *localResponderURI) // optional +{ + StLock _(mCacheLock); + + /* take care of stale entries right away */ + scanForStale(); + + unsigned rtnDex; + return lookupPriv(certID, localResponderURI, rtnDex); +} + +void OcspCache::addResponse( + const CSSM_DATA &ocspResp, // we'll decode it + const CSSM_DATA *localResponderURI) // optional +{ + StLock _(mCacheLock); + + OcspCacheEntry *entry = new OcspCacheEntry(ocspResp, localResponderURI); + if(mNumEntries == mSizeofEntries) { + if(mSizeofEntries == 0) { + /* appending to empty array */ + mSizeofEntries = 1; + } + else { + mSizeofEntries *= 2; + } + mEntries = (OcspCacheEntry **)realloc(mEntries, + mSizeofEntries * sizeof(OcspCacheEntry *)); + } + mEntries[mNumEntries++] = entry; + tpOcspCacheDebug("OcspCache::addResponse: add entry %p", entry); +} + +void OcspCache::flush( + OCSPClientCertID &certID) +{ + StLock _(mCacheLock); + + /* take care of all stale entries */ + scanForStale(); + + unsigned rtnDex; + OCSPSingleResponse *resp; + do { + /* execute as until we find no more entries matching */ + resp = lookupPriv(certID, NULL, rtnDex); + if(resp) { + assert((rtnDex >= 0) && (rtnDex < mNumEntries)); + tpOcspCacheDebug("OcspCache::flush: deleting entry %p", mEntries[rtnDex]); + removeEntry(rtnDex); + } + } while(resp != NULL); +} + + +static ModuleNexus tpOcspCache; + +#pragma mark ---- Public API ---- +/* + * Lookup locally cached response. Caller must free the returned OCSPSingleResponse. + */ +OCSPSingleResponse *tpOcspCacheLookup( + OCSPClientCertID &certID, + const CSSM_DATA *localResponderURI) // optional +{ + return tpOcspCache().lookup(certID, localResponderURI); +} + +/* + * Add a fully verified OCSP response to cache. + */ +void tpOcspCacheAdd( + const CSSM_DATA &ocspResp, // we'll decode it, not keep a ref + const CSSM_DATA *localResponderURI) // optional +{ + #if TP_OCSP_CACHE_DISABLE + return; + #endif + tpOcspCache().addResponse(ocspResp, localResponderURI); +} + +/* + * Delete any entry associated with specified certID from cache. + */ +void tpOcspCacheFlush( + OCSPClientCertID &certID) +{ + tpOcspCache().flush(certID); +} + diff --git a/libsecurity_apple_x509_tp/lib/tpOcspCache.h b/libsecurity_apple_x509_tp/lib/tpOcspCache.h new file mode 100644 index 00000000..09412e4e --- /dev/null +++ b/libsecurity_apple_x509_tp/lib/tpOcspCache.h @@ -0,0 +1,62 @@ +/* + * 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@ + */ + +/* + * tpOcspCache.h - local OCSP response cache. + */ + +#ifndef _TP_OCSP_CACHE_H_ +#define _TP_OCSP_CACHE_H_ + +#include + +/* max default TTL currently 12 hours */ +#define TP_OCSP_CACHE_TTL (60.0 * 60.0 * 12.0) + +extern "C" { + +/* + * Lookup locally cached response. Caller must free the returned OCSPSingleResponse. + * Never returns a stale entry; we always check the enclosed SingleResponse for + * temporal validity. + */ +OCSPSingleResponse *tpOcspCacheLookup( + OCSPClientCertID &certID, + const CSSM_DATA *localResponderURI); // optional + +/* + * Add a fully verified OCSP response to cache. + */ +void tpOcspCacheAdd( + const CSSM_DATA &ocspResp, // we'll decode it and own the result + const CSSM_DATA *localResponderURI); // optional + +/* + * Delete any entry associated with specified certID from cache. + */ +void tpOcspCacheFlush( + OCSPClientCertID &certID); + +} +#endif /* _TP_OCSP_CACHE_H_ */ + diff --git a/libsecurity_apple_x509_tp/lib/tpOcspCertVfy.cpp b/libsecurity_apple_x509_tp/lib/tpOcspCertVfy.cpp new file mode 100644 index 00000000..287f0f63 --- /dev/null +++ b/libsecurity_apple_x509_tp/lib/tpOcspCertVfy.cpp @@ -0,0 +1,591 @@ +/* + * 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@ + */ + +/* + * tpOcspCertVfy.cpp - OCSP cert verification routines + */ + +#include "tpOcspCertVfy.h" +#include "tpdebugging.h" +#include "certGroupUtils.h" +#include +#include +#include + +/* + * Is signerCert authorized to sign OCSP responses by issuerCert? IssuerCert is + * assumed to be (i.e., must, but we don't check that here) the signer of the + * cert being verified, which is not in the loop for this op. Just a bool returned; + * it's autoritized or it's not. + */ +static bool tpIsAuthorizedOcspSigner( + TPCertInfo &issuerCert, // issuer of cert being verified + TPCertInfo &signerCert) // potential signer of OCSP response +{ + CSSM_DATA_PTR fieldValue = NULL; // mallocd by CL + CSSM_RETURN crtn; + bool ourRtn = false; + CE_ExtendedKeyUsage *eku = NULL; + bool foundEku = false; + + /* + * First see if issuerCert issued signerCert (No signature vfy yet, just + * subject/issuer check). + */ + if(!issuerCert.isIssuerOf(signerCert)) { + return false; + } + + /* Fetch ExtendedKeyUse field from signerCert */ + crtn = signerCert.fetchField(&CSSMOID_ExtendedKeyUsage, &fieldValue); + if(crtn) { + tpOcspDebug("tpIsAuthorizedOcspSigner: signer is issued by issuer, no EKU"); + return false; + } + CSSM_X509_EXTENSION *cssmExt = (CSSM_X509_EXTENSION *)fieldValue->Data; + if(cssmExt->format != CSSM_X509_DATAFORMAT_PARSED) { + tpOcspDebug("tpIsAuthorizedOcspSigner: bad extension format"); + goto errOut; + } + eku = (CE_ExtendedKeyUsage *)cssmExt->value.parsedValue; + + /* Look for OID_KP_OCSPSigning */ + for(unsigned dex=0; dexnumPurposes; dex++) { + if(tpCompareCssmData(&eku->purposes[dex], &CSSMOID_OCSPSigning)) { + foundEku = true; + break; + } + } + if(!foundEku) { + tpOcspDebug("tpIsAuthorizedOcspSigner: signer is issued by issuer, no OCSP " + "signing EKU"); + goto errOut; + } + + /* + * OK, signerCert is authorized by *someone* to sign OCSP requests, and + * it claims to be issued by issuer. Sig verify to be sure. + * FIXME this is not handling partial public keys, which would be a colossal + * mess to handle in this module...so we don't. + */ + crtn = signerCert.verifyWithIssuer(&issuerCert, NULL); + if(crtn == CSSM_OK) { + tpOcspDebug("tpIsAuthorizedOcspSigner: FOUND authorized signer"); + ourRtn = true; + } + else { + /* This is a highly irregular situation... */ + tpOcspDebug("tpIsAuthorizedOcspSigner: signer sig verify FAIL"); + } +errOut: + if(fieldValue != NULL) { + signerCert.freeField(&CSSMOID_ExtendedKeyUsage, fieldValue); + } + return ourRtn; +} + +/* + * Check ResponderID linkage between an OCSPResponse and a cert we believe to + * be the issuer of both that response and the cert being verified. Returns + * true if OK. + */ +bool tpOcspResponderIDCheck( + OCSPResponse &ocspResp, + TPCertInfo &signer) +{ + bool shouldBeSigner = false; + if(ocspResp.responderIDTag() == RIT_Name) { + /* + * Name inside response must == signer's SubjectName. + * Note we can't use signer.subjectName(); that's normalized. + */ + + const CSSM_DATA *respIdName = ocspResp.encResponderName(); + CSSM_DATA *subjectName = NULL; + CSSM_RETURN crtn = signer.fetchField(&CSSMOID_X509V1SubjectNameStd, + &subjectName); + if(crtn) { + /* bad cert */ + tpOcspDebug("tpOcspResponderIDCheck: error on fetchField(subjectName"); + return false; + } + if(tpCompareCssmData(respIdName, subjectName)) { + tpOcspDebug("tpOcspResponderIDCheck: good ResponderID.byName"); + shouldBeSigner = true; + } + else { + tpOcspDebug("tpOcspResponderIDCheck: BAD ResponderID.byName"); + } + signer.freeField(&CSSMOID_X509V1SubjectNameStd, subjectName); + } + else { + /* ResponderID.byKey must == SHA1(signer's public key) */ + const CSSM_KEY *pubKey = signer.pubKey(); + assert(pubKey != NULL); + uint8 digest[CC_SHA1_DIGEST_LENGTH]; + CSSM_DATA keyHash = {CC_SHA1_DIGEST_LENGTH, digest}; + ocspdSha1(pubKey->KeyData.Data, pubKey->KeyData.Length, digest); + const CSSM_DATA *respKeyHash = &ocspResp.responderID().byKey; + if(tpCompareCssmData(&keyHash, respKeyHash)) { + tpOcspDebug("tpOcspResponderIDCheck: good ResponderID.byKey"); + shouldBeSigner = true; + } + else { + tpOcspDebug("tpOcspResponderIDCheck: BAD ResponderID.byKey"); + } + } + return shouldBeSigner; +} + +/* + * Verify the signature of an OCSP response. Caller is responsible for all other + * verification of the response, this is just the crypto. + * Returns true on success. + */ +static bool tpOcspResponseSigVerify( + TPVerifyContext &vfyCtx, + OCSPResponse &ocspResp, // parsed response + TPCertInfo &signer) +{ + /* get signature algorithm in CSSM form from the response */ + const SecAsn1OCSPBasicResponse &basicResp = ocspResp.basicResponse(); + const CSSM_OID *algOid = &basicResp.algId.algorithm; + CSSM_ALGORITHMS sigAlg; + + if(!cssmOidToAlg(algOid, &sigAlg)) { + tpOcspDebug("tpOcspResponseSigVerify: unknown signature algorithm"); + } + + /* signer's public key from the cert */ + const CSSM_KEY *pubKey = signer.pubKey(); + + /* signature: on decode, length is in BITS */ + CSSM_DATA sig = basicResp.sig; + sig.Length /= 8; + + CSSM_RETURN crtn; + CSSM_CC_HANDLE sigHand; + bool ourRtn = false; + crtn = CSSM_CSP_CreateSignatureContext(vfyCtx.cspHand, sigAlg, NULL, + pubKey, &sigHand); + if(crtn) { + #ifndef NDEBUG + cssmPerror("tpOcspResponseSigVerify, CSSM_CSP_CreateSignatureContext", crtn); + #endif + return false; + } + crtn = CSSM_VerifyData(sigHand, &basicResp.tbsResponseData, 1, + CSSM_ALGID_NONE, &sig); + if(crtn) { + #ifndef NDEBUG + cssmPerror("tpOcspResponseSigVerify, CSSM_VerifyData", crtn); + #endif + } + else { + ourRtn = true; + } + CSSM_DeleteContext(sigHand); + return ourRtn; +} + +/* possible return from tpIsOcspIssuer() */ +typedef enum { + OIS_No, // not the issuer + OIS_Good, // is the issuer and signature matches + OIS_BadSig, // appears to be issuer, but signature doesn't match +} OcspIssuerStatus; + +/* type of rawCert passed to tpIsOcspIssuer */ +typedef enum { + OCT_Local, // LocalResponder - no checking other than signature + OCT_Issuer, // it's the issuer of the cert being verified + OCT_Provided, // came with response, provenance unknown +} OcspCertType; + +/* + * Did specified cert issue the OCSP response? + * + * This implements the algorithm described in RFC2560, section 4.2.2.2, + * "Authorized Responders". It sees if the cert could be the issuer of the + * OCSP response per that algorithm; then if it could, it performs signature + * verification. + */ +static OcspIssuerStatus tpIsOcspIssuer( + TPVerifyContext &vfyCtx, + OCSPResponse &ocspResp, // parsed response + /* on input specify at least one of the following two */ + const CSSM_DATA *signerData, + TPCertInfo *signer, + OcspCertType certType, // where rawCert came from + TPCertInfo *issuer, // OPTIONAL, if known + TPCertInfo **signerRtn) // optionally RETURNED if at all possible +{ + assert((signerData != NULL) || (signer != NULL)); + + /* get signer as TPCertInfo if caller hasn't provided */ + TPCertInfo *tmpSigner = NULL; + if(signer == NULL) { + try { + tmpSigner = new TPCertInfo(vfyCtx.clHand, vfyCtx.cspHand, signerData, + TIC_CopyData, vfyCtx.verifyTime); + } + catch(...) { + tpOcspDebug("tpIsOcspIssuer: bad cert"); + return OIS_No; + } + signer = tmpSigner; + } + if(signer == NULL) { + return OIS_No; + } + if(signerRtn != NULL) { + *signerRtn = signer; + } + + /* + * Qualification of "this can be the signer" depends on where the + * signer came from. + */ + bool shouldBeSigner = false; + OcspIssuerStatus ourRtn = OIS_No; + + switch(certType) { + case OCT_Local: // caller trusts this and thinks it's the signer + shouldBeSigner = true; + break; + case OCT_Issuer: // last resort, the actual issuer + /* check ResponderID linkage */ + shouldBeSigner = tpOcspResponderIDCheck(ocspResp, *signer); + break; + case OCT_Provided: + { + /* + * This cert came with the response. + */ + if(issuer == NULL) { + /* + * careful, might not know the issuer...how would this path ever + * work then? I don't think it needs to because you can NOT + * do OCSP on a cert without its issuer in hand. + */ + break; + } + + /* check EKU linkage */ + shouldBeSigner = tpIsAuthorizedOcspSigner(*issuer, *signer); + break; + } + } + if(!shouldBeSigner) { + goto errOut; + } + + /* verify the signature */ + if(tpOcspResponseSigVerify(vfyCtx, ocspResp, *signer)) { + ourRtn = OIS_Good; + } + +errOut: + if((signerRtn == NULL) && (tmpSigner != NULL)) { + delete tmpSigner; + } + return ourRtn; + +} + +OcspRespStatus tpVerifyOcspResp( + TPVerifyContext &vfyCtx, + SecNssCoder &coder, + TPCertInfo *issuer, // issuer of the related cert, may be issuer of + // reply, may not be known + OCSPResponse &ocspResp, + CSSM_RETURN &cssmErr) // possible per-cert error +{ + OcspRespStatus ourRtn = ORS_Unknown; + CSSM_RETURN crtn; + + tpOcspDebug("tpVerifyOcspResp top"); + + switch(ocspResp.responseStatus()) { + case RS_Success: + crtn = CSSM_OK; + break; + case RS_MalformedRequest: + crtn = CSSMERR_APPLETP_OCSP_RESP_MALFORMED_REQ; + break; + case RS_InternalError: + crtn = CSSMERR_APPLETP_OCSP_RESP_INTERNAL_ERR; + break; + case RS_TryLater: + crtn = CSSMERR_APPLETP_OCSP_RESP_TRY_LATER; + break; + case RS_SigRequired: + crtn = CSSMERR_APPLETP_OCSP_RESP_SIG_REQUIRED; + break; + case RS_Unauthorized: + crtn = CSSMERR_APPLETP_OCSP_RESP_UNAUTHORIZED; + break; + default: + crtn = CSSMERR_APPLETP_OCSP_BAD_RESPONSE; + break; + } + if(crtn) { + tpOcspDebug("tpVerifyOcspResp aborting due to response status %d", + (int)(ocspResp.responseStatus())); + cssmErr = crtn; + return ORS_Unknown; + } + cssmErr = CSSM_OK; + + /* one of our main jobs is to locate the signer of the response, here */ + TPCertInfo *signerInfo = NULL; + TPCertInfo *signerInfoTBD = NULL; // if non NULL at end, we delete + /* we'll be verifying into this cert group */ + TPCertGroup ocspCerts(vfyCtx.alloc, TGO_Caller); + CSSM_BOOL verifiedToRoot; + CSSM_BOOL verifiedToAnchor; + CSSM_BOOL verifiedViaTrustSetting; + + const CSSM_APPLE_TP_OCSP_OPTIONS *ocspOpts = vfyCtx.ocspOpts; + OcspIssuerStatus issuerStat; + + /* + * Set true if we ever find an apparent issuer which does not correctly + * pass signature verify. If true and we never success, that's a XXX error. + */ + bool foundBadIssuer = false; + bool foundLocalResponder = false; + uint32 numSignerCerts = ocspResp.numSignerCerts(); + + /* + * This cert group, allocated by AppleTPSession::CertGroupVerify(), + * serves two functions here: + * + * -- it accumulates certs we get from the net (as parts of OCSP responses) + * for user in verifying OCSPResponse-related certs. + * TPCertGroup::buildCertGroup() uses this group as one of the many + * sources of certs when building a cert chain. + * + * -- it provides a container into which to stash TPCertInfos which + * persist at least as long as the TPVerifyContext; it's of type TGO_Group, + * so all of the certs added to it get freed when the group does. + */ + assert(vfyCtx.signerCerts != NULL); + + TPCertGroup &gatheredCerts = vfyCtx.gatheredCerts; + + /* set up for disposal of TPCertInfos created by TPCertGroup::buildCertGroup() */ + TPCertGroup certsToBeFreed(vfyCtx.alloc, TGO_Group); + + /* + * First job is to find the cert which signed this response. + * Give priority to caller's LocalResponderCert. + */ + if((ocspOpts != NULL) && (ocspOpts->LocalResponderCert != NULL)) { + TPCertInfo *responderInfo = NULL; + issuerStat = tpIsOcspIssuer(vfyCtx, ocspResp, + ocspOpts->LocalResponderCert, NULL, + OCT_Local, issuer, &responderInfo); + switch(issuerStat) { + case OIS_BadSig: + foundBadIssuer = true; + /* drop thru */ + case OIS_No: + if(responderInfo != NULL) { + /* can't use it - should this be an immediate error? */ + delete responderInfo; + } + break; + case OIS_Good: + assert(responderInfo != NULL); + signerInfo = signerInfoTBD = responderInfo; + foundLocalResponder = true; + tpOcspDebug("tpVerifyOcspResp: signer := LocalResponderCert"); + break; + } + } + + if((signerInfo == NULL) && (numSignerCerts != 0)) { + /* + * App did not specify a local responder (or provided a bad one) + * and the response came with some certs. Try those. + */ + TPCertInfo *respCert = NULL; + for(unsigned dex=0; dexisStatusFatal(CSSMERR_APPLETP_OCSP_NO_SIGNER)) { + /* user wants to proceed without verifying! */ + tpOcspDebug("tpVerifyOcspResp: no signer found, user allows!"); + ourRtn = ORS_Good; + } + else { + tpOcspDebug("tpVerifyOcspResp: no signer found"); + ourRtn = ORS_Unknown; + /* caller adds to per-cert status */ + cssmErr = CSSMERR_APPLETP_OCSP_NO_SIGNER; + } + goto errOut; + } + + if(signerInfo != NULL && !foundLocalResponder) { + /* + * tpIsOcspIssuer has verified that signerInfo is the signer of the + * OCSP response, and that it is either the issuer of the cert being + * checked or is a valid authorized responder for that issuer based on + * key id linkage and EKU. There is no stipulation in RFC2560 to also + * build the chain back to a trusted anchor; however, we'll continue to + * enforce this for the local responder case. (10742723) + */ + tpOcspDebug("tpVerifyOcspResp SUCCESS"); + ourRtn = ORS_Good; + goto errOut; + } + + /* + * Last remaining task is to verify the signer, and all the certs back to + * an anchor + */ + + /* start from scratch with both of these groups */ + gatheredCerts.setAllUnused(); + vfyCtx.signerCerts->setAllUnused(); + crtn = ocspCerts.buildCertGroup( + *signerInfo, // subject item + vfyCtx.signerCerts, // inCertGroup the original group-to-be-verified + vfyCtx.dbList, // optional + vfyCtx.clHand, + vfyCtx.cspHand, + vfyCtx.verifyTime, + vfyCtx.numAnchorCerts, + vfyCtx.anchorCerts, + certsToBeFreed, // local to-be-freed right now + &gatheredCerts, // accumulate gathered certs here + CSSM_FALSE, // subjectIsInGroup + vfyCtx.actionFlags, + vfyCtx.policyOid, + vfyCtx.policyStr, + vfyCtx.policyStrLen, + kSecTrustSettingsKeyUseSignRevocation, + verifiedToRoot, + verifiedToAnchor, + verifiedViaTrustSetting); + if(crtn) { + tpOcspDebug("tpVerifyOcspResp buildCertGroup failure"); + cssmErr = crtn; + ourRtn = ORS_Unknown; + goto errOut; + } + + if(!verifiedToAnchor && !verifiedViaTrustSetting) { + /* required */ + ourRtn = ORS_Unknown; + if(verifiedToRoot) { + /* verified to root which is not an anchor */ + tpOcspDebug("tpVerifyOcspResp root, no anchor"); + cssmErr = CSSMERR_APPLETP_OCSP_INVALID_ANCHOR_CERT; + } + else { + /* partial chain, no root, not verifiable by anchor */ + tpOcspDebug("tpVerifyOcspResp no root, no anchor"); + cssmErr = CSSMERR_APPLETP_OCSP_NOT_TRUSTED; + } + if((issuer != NULL) && !issuer->isStatusFatal(cssmErr)) { + tpOcspDebug("...ignoring last error per trust setting"); + ourRtn = ORS_Good; + } + else { + ourRtn = ORS_Unknown; + } + } + else { + tpOcspDebug("tpVerifyOcspResp SUCCESS; chain verified"); + ourRtn = ORS_Good; + } + + /* FIXME policy verify? */ + +errOut: + delete signerInfoTBD; + /* any other cleanup? */ + return ourRtn; +} diff --git a/libsecurity_apple_x509_tp/lib/tpOcspCertVfy.h b/libsecurity_apple_x509_tp/lib/tpOcspCertVfy.h new file mode 100644 index 00000000..16a6757e --- /dev/null +++ b/libsecurity_apple_x509_tp/lib/tpOcspCertVfy.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@ + */ + +/* + * tpOcspCertVfy.h - OCSP cert verification routines + */ + +#ifndef _TP_OCSP_CERT_VFY_H_ +#define _TP_OCSP_CERT_VFY_H_ + +#include "TPCertInfo.h" +#include "tpCrlVerify.h" +#include +#include + +#ifdef __cplusplus> + +extern "C" { +#endif + +/* + * Verify an OCSP response in the form of a pre-decoded OCSPResponse. Does + * signature verification as well as cert chain verification. Sometimes we can + * verify if we don't know the issuer; sometimes we can. + */ +typedef enum { + ORS_Unknown, // unable to verify one way or another + ORS_Good, // known to be good + ORS_Bad // known to be bad +} OcspRespStatus; + +OcspRespStatus tpVerifyOcspResp( + TPVerifyContext &vfyCtx, + SecNssCoder &coder, + TPCertInfo *issuer, // issuer of the related cert, may be issuer of + // reply + OCSPResponse &ocspResp, + CSSM_RETURN &cssmErr); // possible per-cert error + +#ifdef __cplusplus +} +#endif + +#endif /* _TP_OCSP_CERT_VFY_H_ */ + diff --git a/libsecurity_apple_x509_tp/lib/tpOcspVerify.cpp b/libsecurity_apple_x509_tp/lib/tpOcspVerify.cpp new file mode 100644 index 00000000..d85a0434 --- /dev/null +++ b/libsecurity_apple_x509_tp/lib/tpOcspVerify.cpp @@ -0,0 +1,870 @@ +/* + * 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@ + */ + +/* + * tpOcspVerify.cpp - top-level OCSP verification + */ + +#include "tpOcspVerify.h" +#include "tpdebugging.h" +#include "ocspRequest.h" +#include "tpOcspCache.h" +#include "tpOcspCertVfy.h" +#include +#include "certGroupUtils.h" +#include +#include +#include +#include +#include +#include +#include "tpTime.h" + +#pragma mark ---- private routines ---- + +/* + * Get a smart CertID for specified cert and issuer + */ +static CSSM_RETURN tpOcspGetCertId( + TPCertInfo &subject, + TPCertInfo &issuer, + OCSPClientCertID *&certID) /* mallocd by coder and RETURNED */ +{ + CSSM_RETURN crtn; + CSSM_DATA_PTR issuerSubject = NULL; + CSSM_DATA_PTR issuerPubKeyData = NULL; + CSSM_KEY_PTR issuerPubKey; + CSSM_DATA_PTR subjectSerial = NULL; + + crtn = subject.fetchField(&CSSMOID_X509V1SerialNumber, &subjectSerial); + if(crtn) { + return crtn; + } + crtn = subject.fetchField(&CSSMOID_X509V1IssuerNameStd, &issuerSubject); + if(crtn) { + return crtn; + } + crtn = issuer.fetchField(&CSSMOID_CSSMKeyStruct, &issuerPubKeyData); + if(crtn) { + return crtn; + } + assert(issuerPubKeyData->Length == sizeof(CSSM_KEY)); + issuerPubKey = (CSSM_KEY_PTR)issuerPubKeyData->Data; + certID = new OCSPClientCertID(*issuerSubject, issuerPubKey->KeyData, *subjectSerial); + + subject.freeField(&CSSMOID_X509V1SerialNumber, subjectSerial); + issuer.freeField(&CSSMOID_X509V1IssuerNameStd, issuerSubject); + issuer.freeField(&CSSMOID_CSSMKeyStruct, issuerPubKeyData); + return CSSM_OK; +} + +/* + * Examine cert, looking for AuthorityInfoAccess, with id-ad-ocsp URIs. Create + * an NULL_terminated array of CSSM_DATAs containing the URIs if found. + */ +static CSSM_DATA **tpOcspUrlsFromCert( + TPCertInfo &subject, + SecNssCoder &coder) +{ + CSSM_DATA_PTR extField = NULL; + CSSM_RETURN crtn; + + crtn = subject.fetchField(&CSSMOID_AuthorityInfoAccess, &extField); + if(crtn) { + tpOcspDebug("tpOcspUrlsFromCert: no AIA extension"); + return NULL; + } + if(extField->Length != sizeof(CSSM_X509_EXTENSION)) { + tpErrorLog("tpOcspUrlsFromCert: malformed CSSM_FIELD"); + return NULL; + } + CSSM_X509_EXTENSION *cssmExt = (CSSM_X509_EXTENSION *)extField->Data; + if(cssmExt->format != CSSM_X509_DATAFORMAT_PARSED) { + tpErrorLog("tpOcspUrlsFromCert: malformed CSSM_X509_EXTENSION"); + return NULL; + } + + CE_AuthorityInfoAccess *aia = + (CE_AuthorityInfoAccess *)cssmExt->value.parsedValue; + CSSM_DATA **urls = NULL; + unsigned numUrls = 0; + for(unsigned dex=0; dexnumAccessDescriptions; dex++) { + CE_AccessDescription *ad = &aia->accessDescriptions[dex]; + if(!tpCompareCssmData(&ad->accessMethod, &CSSMOID_AD_OCSP)) { + continue; + } + CE_GeneralName *genName = &ad->accessLocation; + if(genName->nameType != GNT_URI) { + tpErrorLog("tpOcspUrlsFromCert: CSSMOID_AD_OCSP, but not type URI"); + continue; + } + + /* got one */ + if(urls == NULL) { + urls = coder.mallocn(2); + } + else { + /* realloc */ + CSSM_DATA **oldUrls = urls; + urls = coder.mallocn(numUrls + 2); + for(unsigned i=0; i(); + coder.allocCopyItem(genName->name, *urls[numUrls++]); + urls[numUrls] = NULL; + #ifndef NDEBUG + { + CSSM_DATA urlStr; + coder.allocItem(urlStr, genName->name.Length + 1); + memmove(urlStr.Data, genName->name.Data, genName->name.Length); + urlStr.Data[urlStr.Length-1] = '\0'; + tpOcspDebug("tpOcspUrlsFromCert: found URI %s", urlStr.Data); + } + #endif + } + subject.freeField(&CSSMOID_AuthorityInfoAccess, extField); + return urls; +} + +/* + * Create an SecAsn1OCSPDRequest for one cert. This consists of: + * + * -- cooking up an OCSPRequest if net fetch is enabled or a local responder + * is configured; + * -- extracting URLs from subject cert if net fetch is enabled; + * -- creating an SecAsn1OCSPDRequest, mallocd in coder's space; + */ +static SecAsn1OCSPDRequest *tpGenOcspdReq( + TPVerifyContext &vfyCtx, + SecNssCoder &coder, + TPCertInfo &subject, + TPCertInfo &issuer, + OCSPClientCertID &certId, + const CSSM_DATA **urls, // from subject's AuthorityInfoAccess + CSSM_DATA &nonce) // possibly mallocd in coder's space and RETURNED +{ + OCSPRequest *ocspReq = NULL; + SecAsn1OCSPDRequest *ocspdReq = NULL; // to return + OCSPClientCertID *certID = NULL; + CSSM_RETURN crtn; + bool deleteCertID = false; + + /* gather options or their defaults */ + CSSM_APPLE_TP_OCSP_OPT_FLAGS optFlags = 0; + const CSSM_APPLE_TP_OCSP_OPTIONS *ocspOpts = vfyCtx.ocspOpts; + CSSM_DATA_PTR localResponder = NULL; + CSSM_DATA_PTR localResponderCert = NULL; + if(ocspOpts != NULL) { + optFlags = vfyCtx.ocspOpts->Flags; + localResponder = ocspOpts->LocalResponder; + localResponderCert = ocspOpts->LocalResponderCert; + } + bool genNonce = optFlags & CSSM_TP_OCSP_GEN_NONCE ? true : false; + bool requireRespNonce = optFlags & CSSM_TP_OCSP_REQUIRE_RESP_NONCE ? true : false; + + /* + * One degenerate case in case we can't really do anything. + * If no URI and no local responder, only proceed if cache is not disabled + * and we're requiring full OCSP per cert. + */ + if( ( (optFlags & CSSM_TP_ACTION_OCSP_CACHE_READ_DISABLE) || + !(optFlags & CSSM_TP_ACTION_OCSP_REQUIRE_PER_CERT) + ) && + (localResponder == NULL) && + (urls == NULL)) { + tpOcspDebug("tpGenOcspdReq: no route to OCSP; NULL return"); + return NULL; + } + + /* do we need an OCSP request? */ + if(!(optFlags & CSSM_TP_ACTION_OCSP_DISABLE_NET) || (localResponder != NULL)) { + try { + ocspReq = new OCSPRequest(subject, issuer, genNonce); + certID = ocspReq->certID(); + } + catch(...) { + /* not sure how this could even happen but that was a fair amount of code */ + tpErrorLog("tpGenOcspdReq: error cooking up OCSPRequest\n"); + if(ocspReq != NULL) { + delete ocspReq; + return NULL; + } + } + } + + /* certID needed one way or the other */ + if(certID == NULL) { + crtn = tpOcspGetCertId(subject, issuer, certID); + if(crtn) { + goto errOut; + } + deleteCertID = true; + } + + /* + * Create the SecAsn1OCSPDRequest. All fields optional. + */ + ocspdReq = coder.mallocn(); + memset(ocspdReq, 0, sizeof(*ocspdReq)); + if(optFlags & CSSM_TP_ACTION_OCSP_CACHE_WRITE_DISABLE) { + ocspdReq->cacheWriteDisable = coder.mallocn(); + ocspdReq->cacheWriteDisable->Data = coder.mallocn(); + ocspdReq->cacheWriteDisable->Data[0] = 0xff; + ocspdReq->cacheWriteDisable->Length = 1; + } + /* + * Note we're enforcing a not-so-obvious policy here: if nonce match is + * required, disk cache reads by ocspd are disabled. In-core cache is + * still enabled and hits in that cache do NOT require nonce matches. + */ + if((optFlags & CSSM_TP_ACTION_OCSP_CACHE_READ_DISABLE) || requireRespNonce) { + ocspdReq->cacheReadDisable = coder.mallocn(); + ocspdReq->cacheReadDisable->Data = coder.mallocn(); + ocspdReq->cacheReadDisable->Data[0] = 0xff; + ocspdReq->cacheReadDisable->Length = 1; + } + /* CertID, only required field */ + coder.allocCopyItem(*certID->encode(), ocspdReq->certID); + if(ocspReq != NULL) { + ocspdReq->ocspReq = coder.mallocn(); + coder.allocCopyItem(*ocspReq->encode(), *ocspdReq->ocspReq); + if(genNonce) { + /* nonce not available until encode() called */ + coder.allocCopyItem(*ocspReq->nonce(), nonce); + } + } + if(localResponder != NULL) { + ocspdReq->localRespURI = localResponder; + } + if(!(optFlags & CSSM_TP_ACTION_OCSP_DISABLE_NET)) { + ocspdReq->urls = const_cast(urls); + } + +errOut: + delete ocspReq; + if(deleteCertID) { + delete certID; + } + return ocspdReq; +} + +static bool revocationTimeAfterVerificationTime(CFAbsoluteTime revokedTime, CSSM_TIMESTRING verifyTimeStr) +{ + // Return true if the revocation time is after the specified verification time (i.e. "good") + // If verifyTime not specified, use now for the verifyTime + + CFAbsoluteTime verifyTime = 0; + + if (verifyTimeStr) + { + CFDateRef cfVerifyTime = NULL; // made with CFDateCreate + int rtn = timeStringToCfDate((char *)verifyTimeStr, (unsigned)strlen(verifyTimeStr), &cfVerifyTime); + if (!rtn) + if (cfVerifyTime) + { + verifyTime = CFDateGetAbsoluteTime(cfVerifyTime); + CFRelease(cfVerifyTime); + } + } + + if (verifyTime == 0) + verifyTime = CFAbsoluteTimeGetCurrent(); + + return verifyTime < revokedTime; +} + +/* + * Apply a verified OCSPSingleResponse to a TPCertInfo. + */ +static CSSM_RETURN tpApplySingleResp( + OCSPSingleResponse &singleResp, + TPCertInfo &cert, + unsigned dex, // for debug + CSSM_APPLE_TP_OCSP_OPT_FLAGS flags, // for OCSP_SUFFICIENT + CSSM_TIMESTRING verifyTime, // Check revocation at specific time + bool &processed) // set true iff CS_Good or CS_Revoked found +{ + SecAsn1OCSPCertStatusTag certStatus = singleResp.certStatus(); + CSSM_RETURN crtn = CSSM_OK; + if ((certStatus == CS_Revoked) && + revocationTimeAfterVerificationTime(singleResp.revokedTime(), verifyTime)) + { + tpOcspDebug("tpApplySingleResp: CS_Revoked for cert %u, but revoked after verification time", dex); + certStatus = CS_Good; + } + + switch(certStatus) { + case CS_Good: + tpOcspDebug("tpApplySingleResp: CS_Good for cert %u", dex); + cert.revokeCheckGood(true); + if(flags & CSSM_TP_ACTION_OCSP_SUFFICIENT) { + /* no more revocation checking necessary for this cert */ + cert.revokeCheckComplete(true); + } + processed = true; + break; + case CS_Revoked: + tpOcspDebug("tpApplySingleResp: CS_Revoked for cert %u", dex); + switch(singleResp.crlReason()) { + case CE_CR_CertificateHold: + crtn = CSSMERR_TP_CERT_SUSPENDED; + break; + default: + /* FIXME - may want more detailed CRLReason-specific errors */ + crtn = CSSMERR_TP_CERT_REVOKED; + break; + } + if(!cert.addStatusCode(crtn)) { + crtn = CSSM_OK; + } + processed = true; + break; + case CS_Unknown: + /* not an error, no per-cert status, nothing here */ + tpOcspDebug("tpApplySingleResp: CS_Unknown for cert %u", dex); + break; + default: + tpOcspDebug("tpApplySingleResp: BAD certStatus (%d) for cert %u", + (int)certStatus, dex); + if(cert.addStatusCode(CSSMERR_APPLETP_OCSP_STATUS_UNRECOGNIZED)) { + crtn = CSSMERR_APPLETP_OCSP_STATUS_UNRECOGNIZED; + } + break; + } + return crtn; +} + +/* + * An exceptional case: synchronously flush the OCSPD cache and send a new + * resquest for just this one cert. + */ +static OCSPResponse *tpOcspFlushAndReFetch( + TPVerifyContext &vfyCtx, + SecNssCoder &coder, + TPCertInfo &subject, + TPCertInfo &issuer, + OCSPClientCertID &certID) +{ + const CSSM_DATA *derCertID = certID.encode(); + CSSM_RETURN crtn; + + crtn = ocspdCacheFlush(*derCertID); + if(crtn) { + #ifndef NDEBUG + cssmPerror("ocspdCacheFlush", crtn); + #endif + return NULL; + } + + /* Cook up an OCSPDRequests, one request, just for this */ + /* send it to ocsdp */ + /* munge reply into an OCSPRsponse and return it */ + tpOcspDebug("pOcspFlushAndReFetch: Code on demand"); + return NULL; +} + +class PendingRequest +{ +public: + PendingRequest( + TPCertInfo &subject, + TPCertInfo &issuer, + OCSPClientCertID &cid, + CSSM_DATA **u, + unsigned dex); + ~PendingRequest() {} + + TPCertInfo &subject; + TPCertInfo &issuer; + OCSPClientCertID &certID; // owned by caller + CSSM_DATA **urls; // owner-managed array of URLs obtained from subject's + // AuthorityInfoAccess.id-ad-ocsp. + CSSM_DATA nonce; // owner-managed copy of this requests' nonce, if it + // has one + unsigned dex; // in inputCerts, for debug + bool processed; +}; + +PendingRequest::PendingRequest( + TPCertInfo &subj, + TPCertInfo &iss, + OCSPClientCertID &cid, + CSSM_DATA **u, + unsigned dx) + : subject(subj), issuer(iss), certID(cid), + urls(u), dex(dx), processed(false) +{ + nonce.Data = NULL; + nonce.Length = 0; +} + +#pragma mark ---- public API ---- + +CSSM_RETURN tpVerifyCertGroupWithOCSP( + TPVerifyContext &vfyCtx, + TPCertGroup &certGroup) // to be verified +{ + assert(vfyCtx.clHand != 0); + assert(vfyCtx.policy == kRevokeOcsp); + + CSSM_RETURN ourRtn = CSSM_OK; + OcspRespStatus respStat; + SecNssCoder coder; + CSSM_RETURN crtn; + SecAsn1OCSPDRequests ocspdReqs; + SecAsn1OCSPReplies ocspdReplies; + unsigned numRequests = 0; // in ocspdReqs + CSSM_DATA derOcspdRequests = {0, NULL}; + CSSM_DATA derOcspdReplies = {0, NULL}; + uint8 version = OCSPD_REQUEST_VERS; + unsigned numReplies; + unsigned numCerts = certGroup.numCerts(); + if(numCerts <= 1) { + /* Can't verify without an issuer; we're done */ + return CSSM_OK; + } + numCerts--; + + /* gather options or their defaults */ + CSSM_APPLE_TP_OCSP_OPT_FLAGS optFlags = 0; + const CSSM_APPLE_TP_OCSP_OPTIONS *ocspOpts = vfyCtx.ocspOpts; + CSSM_DATA_PTR localResponder = NULL; + CSSM_DATA_PTR localResponderCert = NULL; + bool cacheReadDisable = false; + bool cacheWriteDisable = false; + bool genNonce = false; // in outgoing request + bool requireRespNonce = false; // in incoming response + PRErrorCode prtn; + + if(ocspOpts != NULL) { + optFlags = vfyCtx.ocspOpts->Flags; + localResponder = ocspOpts->LocalResponder; + localResponderCert = ocspOpts->LocalResponderCert; + } + if(optFlags & CSSM_TP_ACTION_OCSP_CACHE_READ_DISABLE) { + cacheReadDisable = true; + } + if(optFlags & CSSM_TP_ACTION_OCSP_CACHE_WRITE_DISABLE) { + cacheWriteDisable = true; + } + if(optFlags & CSSM_TP_OCSP_GEN_NONCE) { + genNonce = true; + } + if(optFlags & CSSM_TP_OCSP_REQUIRE_RESP_NONCE) { + requireRespNonce = true; + } + if(requireRespNonce & !genNonce) { + /* no can do */ + tpErrorLog("tpVerifyCertGroupWithOCSP: requireRespNonce, !genNonce\n"); + return CSSMERR_TP_INVALID_REQUEST_INPUTS; + } + + tpOcspDebug("tpVerifyCertGroupWithOCSP numCerts %u optFlags 0x%lx", + numCerts, (unsigned long)optFlags); + + /* + * create list of pendingRequests parallel to certGroup + */ + PendingRequest **pending = coder.mallocn(numCerts); + memset(pending, 0, (numCerts * sizeof(PendingRequest *))); + + for(unsigned dex=0; dextrustSettingsFound()) { + /* functionally equivalent to root - we're done */ + tpOcspDebug("...tpVerifyCertGroupWithOCSP: terminate per user trust at %u", + (unsigned)dex); + goto postOcspd; + } + TPCertInfo *issuer = certGroup.certAtIndex(dex + 1); + crtn = tpOcspGetCertId(*subject, *issuer, certID); + if(crtn) { + tpErrorLog("tpVerifyCertGroupWithOCSP: error extracting cert fields; " + "aborting\n"); + goto errOut; + } + + /* + * We use the URLs in the subject cert's AuthorityInfoAccess extension + * for two things - mainly to get the URL(s) for actual OCSP transactions, + * but also for CSSM_TP_ACTION_OCSP_REQUIRE_IF_RESP_PRESENT processing. + * So, we do the per-cert processing to get them right now even if we + * wind up using a local responder or getting verification from cache. + */ + CSSM_DATA **urls = tpOcspUrlsFromCert(*subject, coder); + pending[dex] = new PendingRequest(*subject, *issuer, *certID, urls, dex); + } + /* subsequent errors to errOut: */ + + /* + * Create empty SecAsn1OCSPDRequests big enough for all certs + */ + ocspdReqs.requests = coder.mallocn(numCerts + 1); + memset(ocspdReqs.requests, 0, (numCerts + 1) * sizeof(SecAsn1OCSPDRequest *)); + ocspdReqs.version.Data = &version; + ocspdReqs.version.Length = 1; + + /* + * For each cert, either obtain a cached OCSPResponse, or create + * a request to get one. + * + * NOTE: in-core cache reads (via tpOcspCacheLookup() do NOT involve a + * nonce check, no matter what the app says. If nonce checking is required by the + * app, responses don't get added to cache if the nonce doesn't match, but once + * a response is validated and added to cache it's fair game for that task. + */ + for(unsigned dex=0; dexcertID, localResponder); + } + if(singleResp) { + tpOcspDebug("...tpVerifyCertGroupWithOCSP: localCache hit (1) dex %u", + (unsigned)dex); + crtn = tpApplySingleResp(*singleResp, pendReq->subject, dex, optFlags, + vfyCtx.verifyTime, pendReq->processed); + delete singleResp; + if(pendReq->processed) { + /* definitely done with this cert one way or the other */ + if(crtn && (ourRtn == CSSM_OK)) { + /* real cert error: first error encountered; we'll keep going */ + ourRtn = crtn; + } + continue; + } + if(crtn) { + /* + * This indicates a bad cached response. Well that's kinda weird, let's + * just flush this out and try a normal transaction. + */ + tpOcspCacheFlush(pendReq->certID); + } + } + + /* + * Prepare a request for ocspd + */ + SecAsn1OCSPDRequest *ocspdReq = tpGenOcspdReq(vfyCtx, coder, + pendReq->subject, pendReq->issuer, pendReq->certID, + const_cast(pendReq->urls), + pendReq->nonce); + if(ocspdReq == NULL) { + /* tpGenOcspdReq determined there was no route to OCSP responder */ + tpOcspDebug("tpVerifyCertGroupWithOCSP: no OCSP possible for cert %u", dex); + continue; + } + ocspdReqs.requests[numRequests++] = ocspdReq; + } + if(numRequests == 0) { + /* no candidates for OCSP: almost done */ + goto postOcspd; + } + + /* ship requests off to ocspd, get ocspReplies back */ + if(coder.encodeItem(&ocspdReqs, kSecAsn1OCSPDRequestsTemplate, derOcspdRequests)) { + tpErrorLog("tpVerifyCertGroupWithOCSP: error encoding ocspdReqs\n"); + ourRtn = CSSMERR_TP_INTERNAL_ERROR; + goto errOut; + } + crtn = ocspdFetch(vfyCtx.alloc, derOcspdRequests, derOcspdReplies); + if(crtn) { + tpErrorLog("tpVerifyCertGroupWithOCSP: error during ocspd RPC\n"); + #ifndef NDEBUG + cssmPerror("ocspdFetch", crtn); + #endif + /* But this is not necessarily fatal...update per-cert status and check + * caller requirements below */ + goto postOcspd; + } + memset(&ocspdReplies, 0, sizeof(ocspdReplies)); + prtn = coder.decodeItem(derOcspdReplies, kSecAsn1OCSPDRepliesTemplate, + &ocspdReplies); + /* we're done with this, mallocd in ocspdFetch() */ + vfyCtx.alloc.free(derOcspdReplies.Data); + if(prtn) { + /* + * This can happen when an OCSP server provides bad data...we cannot + * determine which cert is associated with this bad response; + * just flag it with the first one and proceed to the loop that + * handles CSSM_TP_ACTION_OCSP_REQUIRE_PER_CERT. + */ + tpErrorLog("tpVerifyCertGroupWithOCSP: error decoding ocspd reply\n"); + pending[0]->subject.addStatusCode(CSSMERR_APPLETP_OCSP_BAD_RESPONSE); + goto postOcspd; + } + if((ocspdReplies.version.Length != 1) || + (ocspdReplies.version.Data[0] != OCSPD_REPLY_VERS)) { + tpErrorLog("tpVerifyCertGroupWithOCSP: ocspd reply version mismatch\n"); + if(ourRtn == CSSM_OK) { + ourRtn = CSSMERR_TP_INTERNAL_ERROR; // maybe something better? + } + goto errOut; + } + + /* process each reply */ + numReplies = ocspdArraySize((const void **)ocspdReplies.replies); + for(unsigned dex=0; dexocspResp, TP_OCSP_CACHE_TTL); + } + catch(...) { + tpErrorLog("tpVerifyCertGroupWithOCSP: error decoding ocsp response\n"); + /* what the heck, keep going */ + continue; + } + + /* + * Find matching subject cert if possible (it's technically optional for + * verification of the response in some cases, e.g., local responder). + */ + PendingRequest *pendReq = NULL; // fully qualified + PendingRequest *reqWithIdMatch = NULL; // CertID match only, not nonce + for(unsigned pdex=0; pdexcertID.compareToExist(reply->certID)) { + reqWithIdMatch = pending[pdex]; + } + if(reqWithIdMatch == NULL) { + continue; + } + if(!genNonce) { + /* that's good enough */ + pendReq = reqWithIdMatch; + tpOcspDebug("OCSP processs reply: CertID match, no nonce"); + break; + } + if(tpCompareCssmData(&reqWithIdMatch->nonce, ocspResp->nonce())) { + tpOcspDebug("OCSP processs reply: nonce MATCH"); + pendReq = reqWithIdMatch; + break; + } + + /* + * In this case we keep going; if we never find a match, then we can + * use reqWithIdMatch if !requireRespNonce. + */ + tpOcspDebug("OCSP processs reply: certID match, nonce MISMATCH"); + } + if(pendReq == NULL) { + if(requireRespNonce) { + tpOcspDebug("OCSP processs reply: tossing out response due to " + "requireRespNonce"); + delete ocspResp; + if(ourRtn == CSSM_OK) { + ourRtn = CSSMERR_APPLETP_OCSP_NONCE_MISMATCH; + } + continue; + } + if(reqWithIdMatch != NULL) { + /* + * Nonce mismatch but caller thinks that's OK. Log it and proceed. + */ + assert(genNonce); + tpOcspDebug("OCSP processs reply: using bad nonce due to !requireRespNonce"); + pendReq = reqWithIdMatch; + pendReq->subject.addStatusCode(CSSMERR_APPLETP_OCSP_NONCE_MISMATCH); + } + } + TPCertInfo *issuer = NULL; + if(pendReq != NULL) { + issuer = &pendReq->issuer; + } + + /* verify response and either throw out or add to local cache */ + respStat = tpVerifyOcspResp(vfyCtx, coder, issuer, *ocspResp, crtn); + switch(respStat) { + case ORS_Good: + break; + case ORS_Unknown: + /* not an error but we can't use it */ + if((crtn != CSSM_OK) && (pendReq != NULL)) { + /* pass this info back to caller here... */ + pendReq->subject.addStatusCode(crtn); + } + delete ocspResp; + continue; + case ORS_Bad: + delete ocspResp; + /* + * An exceptional case: synchronously flush the OCSPD cache and send a + * new request for just this one cert. + * FIXME: does this really buy us anything? A DOS attacker who managed + * to get this bogus response into our cache is likely to be able + * to do it again and again. + */ + tpOcspDebug("tpVerifyCertGroupWithOCSP: flush/refetch for cert %u", dex); + ocspResp = tpOcspFlushAndReFetch(vfyCtx, coder, pendReq->subject, + pendReq->issuer, pendReq->certID); + if(ocspResp == NULL) { + tpErrorLog("tpVerifyCertGroupWithOCSP: error on flush/refetch\n"); + ourRtn = CSSMERR_APPLETP_OCSP_BAD_RESPONSE; + goto errOut; + } + respStat = tpVerifyOcspResp(vfyCtx, coder, issuer, *ocspResp, crtn); + if(respStat != ORS_Good) { + tpErrorLog("tpVerifyCertGroupWithOCSP: verify error after " + "flush/refetch\n"); + if((crtn != CSSM_OK) && (pendReq != NULL)) { + /* pass this info back to caller here... */ + if(pendReq->subject.addStatusCode(crtn)) { + ourRtn = CSSMERR_APPLETP_OCSP_BAD_RESPONSE; + } + } + else { + ourRtn = CSSMERR_APPLETP_OCSP_BAD_RESPONSE; + } + goto errOut; + } + /* Voila! Recovery. Proceed. */ + tpOcspDebug("tpVerifyCertGroupWithOCSP: refetch for cert %u SUCCEEDED", + dex); + break; + } /* switch response status */ + + if(!cacheWriteDisable) { + tpOcspCacheAdd(reply->ocspResp, localResponder); + } + + /* attempt to apply to pendReq */ + if(pendReq != NULL) { + OCSPSingleResponse *singleResp = + ocspResp->singleResponseFor(pendReq->certID); + if(singleResp) { + crtn = tpApplySingleResp(*singleResp, pendReq->subject, pendReq->dex, + optFlags, vfyCtx.verifyTime, pendReq->processed); + if(crtn && (ourRtn == CSSM_OK)) { + ourRtn = crtn; + } + delete singleResp; + } + } /* a reply which matches a pending request */ + + /* + * Done with this - note local OCSP response cache doesn't store this + * object; it stores an encoded copy. + */ + delete ocspResp; + } /* for each reply */ + +postOcspd: + + /* + * Now process each cert which hasn't had an OCSP response applied to it. + * This can happen if we get back replies which are not strictly in 1-1 sync with + * our requests but which nevertheless contain valid info for more than one + * cert each. + */ + for(unsigned dex=0; dexprocessed) { + continue; + } + OCSPSingleResponse *singleResp = NULL; + /* Note this corner case will not work if cache is disabled. */ + if(!cacheReadDisable) { + singleResp = tpOcspCacheLookup(pendReq->certID, localResponder); + } + if(singleResp) { + tpOcspDebug("...tpVerifyCertGroupWithOCSP: localCache (2) hit dex %u", + (unsigned)dex); + crtn = tpApplySingleResp(*singleResp, pendReq->subject, dex, optFlags, + vfyCtx.verifyTime, pendReq->processed); + if(crtn) { + if(ourRtn == CSSM_OK) { + ourRtn = crtn; + } + } + delete singleResp; + } + if(!pendReq->processed) { + /* Couldn't perform OCSP for this cert. */ + tpOcspDebug("tpVerifyCertGroupWithOCSP: OCSP_UNAVAILABLE for cert %u", dex); + bool required = false; + CSSM_RETURN responseStatus = CSSM_OK; + if(pendReq->subject.numStatusCodes() > 0) { + /* + * Check whether we got a response for this cert, but it was rejected + * due to being improperly signed. That should result in an actual + * error, even under Best Attempt processing. (10743149) + */ + if(pendReq->subject.hasStatusCode(CSSMERR_APPLETP_OCSP_BAD_RESPONSE)) { +// responseStatus = CSSMERR_APPLETP_OCSP_BAD_RESPONSE; + } else if(pendReq->subject.hasStatusCode(CSSMERR_APPLETP_OCSP_SIG_ERROR)) { + responseStatus = CSSMERR_APPLETP_OCSP_SIG_ERROR; + } else if(pendReq->subject.hasStatusCode(CSSMERR_APPLETP_OCSP_NO_SIGNER)) { + responseStatus = CSSMERR_APPLETP_OCSP_NO_SIGNER; + } + } + if(responseStatus == CSSM_OK) { + /* no response available (as opposed to getting an invalid response) */ + pendReq->subject.addStatusCode(CSSMERR_APPLETP_OCSP_UNAVAILABLE); + } + if(optFlags & CSSM_TP_ACTION_OCSP_REQUIRE_PER_CERT) { + /* every cert needs OCSP */ + tpOcspDebug("tpVerifyCertGroupWithOCSP: response required for all certs, missing for cert %u", dex); + required = true; + } + else if(optFlags & CSSM_TP_ACTION_OCSP_REQUIRE_IF_RESP_PRESENT) { + /* this cert needs OCSP if it had an AIA extension with an OCSP URI */ + if(pendReq->urls) { + tpOcspDebug("tpVerifyCertGroupWithOCSP: OCSP URI present but no valid response for cert %u", dex); + required = true; + } + } + if( (required && pendReq->subject.isStatusFatal(CSSMERR_APPLETP_OCSP_UNAVAILABLE)) || + (responseStatus != CSSM_OK && pendReq->subject.isStatusFatal(responseStatus)) ) { + /* fatal error, but we keep on processing */ + if(ourRtn == CSSM_OK) { + ourRtn = (responseStatus != CSSM_OK) ? responseStatus : CSSMERR_APPLETP_OCSP_UNAVAILABLE; + } + } + } + } +errOut: + for(unsigned dex=0; dexcertID; + delete pendReq; + } + return ourRtn; +} diff --git a/libsecurity_apple_x509_tp/lib/tpOcspVerify.h b/libsecurity_apple_x509_tp/lib/tpOcspVerify.h new file mode 100644 index 00000000..2b0caf5f --- /dev/null +++ b/libsecurity_apple_x509_tp/lib/tpOcspVerify.h @@ -0,0 +1,47 @@ +/* + * 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@ + */ + +/* + * tpOcspVerify.h - top-level OCSP verification + */ + +#ifndef _TP_OCSP_VERIFY_H_ +#define _TP_OCSP_VERIFY_H_ + +#include "tpCrlVerify.h" + +extern "C" { + +/* + * The sole and deceptively simple looking public interface to this module. + * It's pretty heavyweight; expect to spend millions or billions of cycles + * here before returning. + */ +CSSM_RETURN tpVerifyCertGroupWithOCSP( + TPVerifyContext &tpVerifyContext, + TPCertGroup &certGroup); // to be verified + +} + +#endif /* _TP_OCSP_VERIFY_H_ */ + diff --git a/libsecurity_apple_x509_tp/lib/tpPolicies.cpp b/libsecurity_apple_x509_tp/lib/tpPolicies.cpp new file mode 100644 index 00000000..07a1f791 --- /dev/null +++ b/libsecurity_apple_x509_tp/lib/tpPolicies.cpp @@ -0,0 +1,2762 @@ +/* + * 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'). + * 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. + */ + + +/* + policies.cpp - TP module policy implementation +*/ + +#include +#include +#include "tpPolicies.h" +#include +#include "tpdebugging.h" +#include "certGroupUtils.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/* + * Our private per-extension info. One of these per (understood) extension per + * cert. + */ +typedef struct { + CSSM_BOOL present; + CSSM_BOOL critical; + CE_Data *extnData; // mallocd by CL + CSSM_DATA *valToFree; // the data we pass to freeField() +} iSignExtenInfo; + +/* + * Struct to keep track of info pertinent to one cert. + */ +typedef struct { + + /* extensions we're interested in */ + iSignExtenInfo authorityId; + iSignExtenInfo subjectId; + iSignExtenInfo keyUsage; + iSignExtenInfo extendKeyUsage; + iSignExtenInfo basicConstraints; + iSignExtenInfo netscapeCertType; + iSignExtenInfo subjectAltName; + iSignExtenInfo certPolicies; + iSignExtenInfo qualCertStatements; + iSignExtenInfo nameConstraints; + iSignExtenInfo policyMappings; + iSignExtenInfo policyConstraints; + iSignExtenInfo inhibitAnyPolicy; + iSignExtenInfo certificatePolicies; + + /* flag indicating presence of a critical extension we don't understand */ + CSSM_BOOL foundUnknownCritical; + /* flag indicating that this certificate was signed with a known-broken algorithm */ + CSSM_BOOL untrustedSigAlg; + +} iSignCertInfo; + +/* + * The list of Qualified Cert Statement statementIds we understand, even though + * we don't actually do anything with them; if these are found in a Qualified + * Cert Statement that's critical, we can truthfully say "yes we understand this". + */ +static const CSSM_OID_PTR knownQualifiedCertStatements[] = +{ + (const CSSM_OID_PTR)&CSSMOID_OID_QCS_SYNTAX_V1, + (const CSSM_OID_PTR)&CSSMOID_OID_QCS_SYNTAX_V2, + (const CSSM_OID_PTR)&CSSMOID_ETSI_QCS_QC_COMPLIANCE, + (const CSSM_OID_PTR)&CSSMOID_ETSI_QCS_QC_LIMIT_VALUE, + (const CSSM_OID_PTR)&CSSMOID_ETSI_QCS_QC_RETENTION, + (const CSSM_OID_PTR)&CSSMOID_ETSI_QCS_QC_SSCD +}; +#define NUM_KNOWN_QUAL_CERT_STATEMENTS (sizeof(knownQualifiedCertStatements) / sizeof(CSSM_OID_PTR)) + +static CSSM_RETURN tp_verifyMacAppStoreReciptOpts(TPCertGroup &certGroup, + const CSSM_DATA *fieldOpts, const iSignCertInfo *certInfo); +bool certificatePoliciesContainsOID(const CE_CertPolicies *certPolicies, const CSSM_OID *oidToFind); + +/* + * Certificate policy OIDs + */ + +/* 2.5.29.32.0 */ +#define ANY_POLICY_OID OID_EXTENSION, 0x32, 0x00 +#define ANY_POLICY_OID_LEN OID_EXTENSION_LENGTH + 2 + +/* 2.5.29.54 */ +#define INHIBIT_ANY_POLICY_OID OID_EXTENSION, 0x54 +#define INHIBIT_ANY_POLICY_OID_LEN OID_EXTENSION_LENGTH + 1 + +/* 2.16.840.1.101.2.1 */ +#define US_DOD_INFOSEC 0x60, 0x86, 0x48, 0x01, 0x65, 0x02, 0x01 +#define US_DOD_INFOSEC_LEN 7 + +/* 2.16.840.1.101.2.1.11.10 */ +#define PIV_AUTH_OID US_DOD_INFOSEC, 0x0B, 0x0A +#define PIV_AUTH_OID_LEN US_DOD_INFOSEC_LEN + 2 + +/* 2.16.840.1.101.2.1.11.20 */ +#define PIV_AUTH_2048_OID US_DOD_INFOSEC, 0x0B, 0x14 +#define PIV_AUTH_2048_OID_LEN US_DOD_INFOSEC_LEN + 2 + +static const uint8 OID_ANY_POLICY[] = {ANY_POLICY_OID}; +const CSSM_OID CSSMOID_ANY_POLICY = {ANY_POLICY_OID_LEN, (uint8 *)OID_ANY_POLICY}; +static const uint8 OID_INHIBIT_ANY_POLICY[] = {INHIBIT_ANY_POLICY_OID}; +const CSSM_OID CSSMOID_INHIBIT_ANY_POLICY = {INHIBIT_ANY_POLICY_OID_LEN, (uint8 *)OID_INHIBIT_ANY_POLICY}; +static const uint8 OID_PIV_AUTH[] = {PIV_AUTH_OID}; +const CSSM_OID CSSMOID_PIV_AUTH = {PIV_AUTH_OID_LEN, (uint8 *)OID_PIV_AUTH}; +static const uint8 OID_PIV_AUTH_2048[] = {PIV_AUTH_2048_OID}; +const CSSM_OID CSSMOID_PIV_AUTH_2048 = {PIV_AUTH_2048_OID_LEN, (uint8 *)OID_PIV_AUTH_2048}; + +static CSSM_RETURN tp_verifyAppleIDSharingOpts(TPCertGroup &certGroup, + const CSSM_DATA *fieldOpts, // optional Common Name + const iSignCertInfo *certInfo); +/* + * Setup a single iSignExtenInfo. Called once per known extension + * per cert. + */ +static CSSM_RETURN tpSetupExtension( + Allocator &alloc, + CSSM_DATA *extnData, + iSignExtenInfo *extnInfo) // which component of certInfo +{ + if(extnData->Length != sizeof(CSSM_X509_EXTENSION)) { + tpPolicyError("tpSetupExtension: malformed CSSM_FIELD"); + return CSSMERR_TP_UNKNOWN_FORMAT; + } + CSSM_X509_EXTENSION *cssmExt = (CSSM_X509_EXTENSION *)extnData->Data; + extnInfo->present = CSSM_TRUE; + extnInfo->critical = cssmExt->critical; + extnInfo->extnData = (CE_Data *)cssmExt->value.parsedValue; + extnInfo->valToFree = extnData; + return CSSM_OK; +} + +/* + * Fetch a known extension, set up associated iSignExtenInfo if present. + */ +static CSSM_RETURN iSignFetchExtension( + Allocator &alloc, + TPCertInfo *tpCert, + const CSSM_OID *fieldOid, // which extension to fetch + iSignExtenInfo *extnInfo) // where the info goes +{ + CSSM_DATA_PTR fieldValue; // mallocd by CL + CSSM_RETURN crtn; + + crtn = tpCert->fetchField(fieldOid, &fieldValue); + switch(crtn) { + case CSSM_OK: + break; + case CSSMERR_CL_NO_FIELD_VALUES: + /* field not present, OK */ + return CSSM_OK; + default: + return crtn; + } + return tpSetupExtension(alloc, + fieldValue, + extnInfo); +} + +/* + * This function performs a check of an extension marked 'critical' + * to see if it's one we understand. Returns CSSM_OK if the extension + * is acceptable, CSSMERR_APPLETP_UNKNOWN_CRITICAL_EXTEN if unknown. + */ +static CSSM_RETURN iSignVerifyCriticalExtension( + CSSM_X509_EXTENSION *cssmExt) +{ + if (!cssmExt || !cssmExt->extnId.Data) + return CSSMERR_TP_INVALID_FIELD_POINTER; + + if (!cssmExt->critical) + return CSSM_OK; + + /* FIXME: remove when policyConstraints NSS template is fixed */ + if (!memcmp(cssmExt->extnId.Data, CSSMOID_PolicyConstraints.Data, CSSMOID_PolicyConstraints.Length)) + return CSSM_OK; + + if (cssmExt->extnId.Length > APPLE_EXTENSION_OID_LENGTH && + !memcmp(cssmExt->extnId.Data, CSSMOID_APPLE_EXTENSION.Data, APPLE_EXTENSION_OID_LENGTH)) { + /* This extension's OID is under the appleCertificateExtensions arc */ + return CSSM_OK; + + } + return CSSMERR_APPLETP_UNKNOWN_CRITICAL_EXTEN; +} + +/* + * Search for all unknown extensions. If we find one which is flagged critical, + * flag certInfo->foundUnknownCritical. Only returns error on gross errors. + */ +static CSSM_RETURN iSignSearchUnknownExtensions( + TPCertInfo *tpCert, + iSignCertInfo *certInfo) +{ + CSSM_RETURN crtn; + CSSM_DATA_PTR fieldValue = NULL; + CSSM_HANDLE searchHand = CSSM_INVALID_HANDLE; + uint32 numFields = 0; + + crtn = CSSM_CL_CertGetFirstCachedFieldValue(tpCert->clHand(), + tpCert->cacheHand(), + &CSSMOID_X509V3CertificateExtensionCStruct, + &searchHand, + &numFields, + &fieldValue); + switch(crtn) { + case CSSM_OK: + /* found one, proceed */ + break; + case CSSMERR_CL_NO_FIELD_VALUES: + /* no unknown extensions present, OK */ + return CSSM_OK; + default: + return crtn; + } + + if(fieldValue->Length != sizeof(CSSM_X509_EXTENSION)) { + tpPolicyError("iSignSearchUnknownExtensions: malformed CSSM_FIELD"); + return CSSMERR_TP_UNKNOWN_FORMAT; + } + CSSM_X509_EXTENSION *cssmExt = (CSSM_X509_EXTENSION *)fieldValue->Data; + if(iSignVerifyCriticalExtension(cssmExt) != CSSM_OK) { + /* BRRZAPP! Found an unknown extension marked critical */ + certInfo->foundUnknownCritical = CSSM_TRUE; + goto fini; + } + CSSM_CL_FreeFieldValue(tpCert->clHand(), + &CSSMOID_X509V3CertificateExtensionCStruct, + fieldValue); + fieldValue = NULL; + + /* process remaining unknown extensions */ + for(unsigned i=1; iclHand(), + searchHand, + &fieldValue); + if(crtn) { + /* should never happen */ + tpPolicyError("searchUnknownExtensions: GetNextCachedFieldValue" + "error"); + break; + } + if(fieldValue->Length != sizeof(CSSM_X509_EXTENSION)) { + tpPolicyError("iSignSearchUnknownExtensions: " + "malformed CSSM_FIELD"); + crtn = CSSMERR_TP_UNKNOWN_FORMAT; + break; + } + CSSM_X509_EXTENSION *cssmExt = (CSSM_X509_EXTENSION *)fieldValue->Data; + if(iSignVerifyCriticalExtension(cssmExt) != CSSM_OK) { + /* BRRZAPP! Found an unknown extension marked critical */ + certInfo->foundUnknownCritical = CSSM_TRUE; + break; + } + CSSM_CL_FreeFieldValue(tpCert->clHand(), + &CSSMOID_X509V3CertificateExtensionCStruct, + fieldValue); + fieldValue = NULL; + } /* for additional fields */ + +fini: + if(fieldValue) { + CSSM_CL_FreeFieldValue(tpCert->clHand(), + &CSSMOID_X509V3CertificateExtensionCStruct, + fieldValue); + } + if(searchHand != CSSM_INVALID_HANDLE) { + CSSM_CL_CertAbortQuery(tpCert->clHand(), searchHand); + } + return crtn; +} + +/* + * Check the signature algorithm. If it's known to be untrusted, + * flag certInfo->untrustedSigAlg. + */ +static void iSignCheckSignatureAlgorithm( + TPCertInfo *tpCert, + iSignCertInfo *certInfo) +{ + CSSM_X509_ALGORITHM_IDENTIFIER *algId = NULL; + CSSM_DATA_PTR valueToFree = NULL; + + algId = tp_CertGetAlgId(tpCert, &valueToFree); + if(!algId || + tpCompareCssmData(&algId->algorithm, &CSSMOID_MD2) || + tpCompareCssmData(&algId->algorithm, &CSSMOID_MD2WithRSA)) { + certInfo->untrustedSigAlg = CSSM_TRUE; + } else { + certInfo->untrustedSigAlg = CSSM_FALSE; + } + + if (valueToFree) { + tp_CertFreeAlgId(tpCert->clHand(), valueToFree); + } +} + +/* + * Given a TPCertInfo, fetch the associated iSignCertInfo fields. + * Returns CSSM_FAIL on error. + */ +static CSSM_RETURN iSignGetCertInfo( + Allocator &alloc, + TPCertInfo *tpCert, + iSignCertInfo *certInfo) +{ + CSSM_RETURN crtn; + + /* first grind thru the extensions we're interested in */ + crtn = iSignFetchExtension(alloc, + tpCert, + &CSSMOID_AuthorityKeyIdentifier, + &certInfo->authorityId); + if(crtn) { + return crtn; + } + crtn = iSignFetchExtension(alloc, + tpCert, + &CSSMOID_SubjectKeyIdentifier, + &certInfo->subjectId); + if(crtn) { + return crtn; + } + crtn = iSignFetchExtension(alloc, + tpCert, + &CSSMOID_KeyUsage, + &certInfo->keyUsage); + if(crtn) { + return crtn; + } + crtn = iSignFetchExtension(alloc, + tpCert, + &CSSMOID_ExtendedKeyUsage, + &certInfo->extendKeyUsage); + if(crtn) { + return crtn; + } + crtn = iSignFetchExtension(alloc, + tpCert, + &CSSMOID_BasicConstraints, + &certInfo->basicConstraints); + if(crtn) { + return crtn; + } + crtn = iSignFetchExtension(alloc, + tpCert, + &CSSMOID_NetscapeCertType, + &certInfo->netscapeCertType); + if(crtn) { + return crtn; + } + crtn = iSignFetchExtension(alloc, + tpCert, + &CSSMOID_SubjectAltName, + &certInfo->subjectAltName); + if(crtn) { + return crtn; + } + crtn = iSignFetchExtension(alloc, + tpCert, + &CSSMOID_CertificatePolicies, + &certInfo->certPolicies); + if(crtn) { + return crtn; + } + crtn = iSignFetchExtension(alloc, + tpCert, + &CSSMOID_QC_Statements, + &certInfo->qualCertStatements); + if(crtn) { + return crtn; + } + crtn = iSignFetchExtension(alloc, + tpCert, + &CSSMOID_NameConstraints, + &certInfo->nameConstraints); + if(crtn) { + return crtn; + } + crtn = iSignFetchExtension(alloc, + tpCert, + &CSSMOID_PolicyMappings, + &certInfo->policyMappings); + if(crtn) { + return crtn; + } + crtn = iSignFetchExtension(alloc, + tpCert, + &CSSMOID_PolicyConstraints, + &certInfo->policyConstraints); + if(crtn) { + return crtn; + } + crtn = iSignFetchExtension(alloc, + tpCert, + &CSSMOID_InhibitAnyPolicy, + &certInfo->inhibitAnyPolicy); + if(crtn) { + return crtn; + } + crtn = iSignFetchExtension(alloc, + tpCert, + &CSSMOID_CertificatePolicies, + &certInfo->certificatePolicies); + if(crtn) { + return crtn; + } + + /* check signature algorithm field */ + iSignCheckSignatureAlgorithm(tpCert, certInfo); + + /* now look for extensions we don't understand - the only thing we're interested + * in is the critical flag. */ + return iSignSearchUnknownExtensions(tpCert, certInfo); +} + +/* + * Free (via CL) the fields allocated in iSignGetCertInfo(). + */ +static void iSignFreeCertInfo( + CSSM_CL_HANDLE clHand, + iSignCertInfo *certInfo) +{ + if(certInfo->authorityId.present) { + CSSM_CL_FreeFieldValue(clHand, &CSSMOID_AuthorityKeyIdentifier, + certInfo->authorityId.valToFree); + } + if(certInfo->subjectId.present) { + CSSM_CL_FreeFieldValue(clHand, &CSSMOID_SubjectKeyIdentifier, + certInfo->subjectId.valToFree); + } + if(certInfo->keyUsage.present) { + CSSM_CL_FreeFieldValue(clHand, &CSSMOID_KeyUsage, + certInfo->keyUsage.valToFree); + } + if(certInfo->extendKeyUsage.present) { + CSSM_CL_FreeFieldValue(clHand, &CSSMOID_ExtendedKeyUsage, + certInfo->extendKeyUsage.valToFree); + } + if(certInfo->basicConstraints.present) { + CSSM_CL_FreeFieldValue(clHand, &CSSMOID_BasicConstraints, + certInfo->basicConstraints.valToFree); + } + if(certInfo->netscapeCertType.present) { + CSSM_CL_FreeFieldValue(clHand, &CSSMOID_NetscapeCertType, + certInfo->netscapeCertType.valToFree); + } + if(certInfo->subjectAltName.present) { + CSSM_CL_FreeFieldValue(clHand, &CSSMOID_SubjectAltName, + certInfo->subjectAltName.valToFree); + } + if(certInfo->certPolicies.present) { + CSSM_CL_FreeFieldValue(clHand, &CSSMOID_CertificatePolicies, + certInfo->certPolicies.valToFree); + } +// if(certInfo->policyConstraints.present) { +// CSSM_CL_FreeFieldValue(clHand, &CSSMOID_PolicyConstraints, +// certInfo->policyConstraints.valToFree); +// } + if(certInfo->qualCertStatements.present) { + CSSM_CL_FreeFieldValue(clHand, &CSSMOID_QC_Statements, + certInfo->qualCertStatements.valToFree); + } + if(certInfo->certificatePolicies.present) { + CSSM_CL_FreeFieldValue(clHand, &CSSMOID_CertificatePolicies, + certInfo->certificatePolicies.valToFree); + } +} + +/* + * See if cert's Subject.{commonName,EmailAddress} matches caller-specified + * string. Returns CSSM_TRUE if match, else returns CSSM_FALSE. + * Also indicates whether *any* of the specified fields were found, regardless + * of match state. + */ +typedef enum { + SN_CommonName, // CSSMOID_CommonName, host name format + SN_Email // CSSMOID_EmailAddress +} SubjSubjNameSearchType; + +static CSSM_BOOL tpCompareSubjectName( + TPCertInfo &cert, + SubjSubjNameSearchType searchType, + bool normalizeAll, // for SN_Email case: lower-case all of + // the cert's value, not just the portion + // after the '@' + const char *callerStr, // already tpToLower'd + uint32 callerStrLen, + bool &fieldFound) +{ + char *certName = NULL; // from cert's subject name + uint32 certNameLen = 0; + CSSM_DATA_PTR subjNameData = NULL; + CSSM_RETURN crtn; + CSSM_BOOL ourRtn = CSSM_FALSE; + const CSSM_OID *oidSrch; + + fieldFound = false; + switch(searchType) { + case SN_CommonName: + oidSrch = &CSSMOID_CommonName; + break; + case SN_Email: + oidSrch = &CSSMOID_EmailAddress; + break; + default: + assert(0); + return CSSM_FALSE; + } + crtn = cert.fetchField(&CSSMOID_X509V1SubjectNameCStruct, &subjNameData); + if(crtn) { + /* should never happen, we shouldn't be here if there is no subject */ + tpPolicyError("tpCompareSubjectName: error retrieving subject name"); + return CSSM_FALSE; + } + CSSM_X509_NAME_PTR x509name = (CSSM_X509_NAME_PTR)subjNameData->Data; + if((x509name == NULL) || (subjNameData->Length != sizeof(CSSM_X509_NAME))) { + tpPolicyError("tpCompareSubjectName: malformed CSSM_X509_NAME"); + cert.freeField(&CSSMOID_X509V1SubjectNameCStruct, subjNameData); + return CSSM_FALSE; + } + + /* Now grunge thru the X509 name looking for a common name */ + CSSM_X509_TYPE_VALUE_PAIR *ptvp; + CSSM_X509_RDN_PTR rdnp; + unsigned rdnDex; + unsigned pairDex; + + for(rdnDex=0; rdnDexnumberOfRDNs; rdnDex++) { + rdnp = &x509name->RelativeDistinguishedName[rdnDex]; + for(pairDex=0; pairDexnumberOfPairs; pairDex++) { + ptvp = &rdnp->AttributeTypeAndValue[pairDex]; + if(tpCompareOids(&ptvp->type, oidSrch)) { + fieldFound = true; + certName = (char *)ptvp->value.Data; + certNameLen = ptvp->value.Length; + switch(searchType) { + case SN_CommonName: + { + /* handle odd encodings that we need to convert to 8-bit */ + CFStringBuiltInEncodings encoding; + CFDataRef cfd = NULL; + bool doConvert = false; + switch(ptvp->valueType) { + case BER_TAG_T61_STRING: + /* a.k.a. Teletex */ + encoding = kCFStringEncodingISOLatin1; + doConvert = true; + break; + case BER_TAG_PKIX_BMP_STRING: + encoding = kCFStringEncodingUnicode; + doConvert = true; + break; + /* + * All others - either take as is, or let it fail due to + * illegal/incomprehensible format + */ + default: + break; + } + if(doConvert) { + /* raw data ==> CFString */ + cfd = CFDataCreate(NULL, (UInt8 *)certName, certNameLen); + if(cfd == NULL) { + /* try next component */ + break; + } + CFStringRef cfStr = CFStringCreateFromExternalRepresentation( + NULL, cfd, encoding); + CFRelease(cfd); + if(cfStr == NULL) { + tpPolicyError("tpCompareSubjectName: bad str (1)"); + break; + } + + /* CFString ==> straight ASCII */ + cfd = CFStringCreateExternalRepresentation(NULL, + cfStr, kCFStringEncodingASCII, 0); + CFRelease(cfStr); + if(cfd == NULL) { + tpPolicyError("tpCompareSubjectName: bad str (2)"); + break; + } + certNameLen = CFDataGetLength(cfd); + certName = (char *)CFDataGetBytePtr(cfd); + } + ourRtn = tpCompareHostNames(callerStr, callerStrLen, + certName, certNameLen); + if(doConvert) { + assert(cfd != NULL); + CFRelease(cfd); + } + break; + } + case SN_Email: + ourRtn = tpCompareEmailAddr(callerStr, callerStrLen, + certName, certNameLen, normalizeAll); + break; + } + if(ourRtn) { + /* success */ + break; + } + /* else keep going, maybe there's another common name */ + } + } + if(ourRtn) { + break; + } + } + cert.freeField(&CSSMOID_X509V1SubjectNameCStruct, subjNameData); + return ourRtn; +} + +/* + * Compare ASCII form of an IP address to a CSSM_DATA containing + * the IP address's numeric components. Returns true on match. + */ +static CSSM_BOOL tpCompIpAddrStr( + const char *str, + unsigned strLen, + const CSSM_DATA *numeric) +{ + const char *cp = str; + const char *nextDot; + char buf[100]; + + if((numeric == NULL) || (numeric->Length == 0) || (str == NULL)) { + return CSSM_FALSE; + } + if(cp[strLen - 1] == '\0') { + /* ignore NULL terminator */ + strLen--; + } + for(unsigned dex=0; dexLength; dex++) { + /* cp points to start of current string digit */ + /* find next dot */ + const char *lastChar = cp + strLen; + nextDot = cp + 1; + for( ; nextDotLength - 1)) { + return CSSM_FALSE; + } + } + else if(dex == (numeric->Length - 1)) { + return CSSM_FALSE; + } + unsigned digLen = nextDot - cp; + if(digLen >= sizeof(buf)) { + /* preposterous */ + return CSSM_FALSE; + } + memmove(buf, cp, digLen); + buf[digLen] = '\0'; + /* incr digLen to include the next dot */ + digLen++; + cp += digLen; + strLen -= digLen; + int digVal = atoi(buf); + if(digVal != numeric->Data[dex]) { + return CSSM_FALSE; + } + } + return CSSM_TRUE; +} + +/* + * See if cert's subjectAltName contains an element matching caller-specified + * string, hostname, in the following forms: + * + * SAN_HostName : dnsName, iPAddress + * SAN_Email : RFC822Name + * + * Returns CSSM_TRUE if match, else returns CSSM_FALSE. + * + * Also indicates whether or not a dnsName (search type HostName) or + * RFC822Name (search type SAM_Email) was found, regardless of result + * of comparison. + * + * The appStr/appStrLen args are optional - if NULL/0, only the + * search for dnsName/RFC822Name is done. + */ +typedef enum { + SAN_HostName, + SAN_Email +} SubjAltNameSearchType; + +static CSSM_BOOL tpCompareSubjectAltName( + const iSignExtenInfo &subjAltNameInfo, + const char *appStr, // caller has lower-cased as appropriate + uint32 appStrLen, + SubjAltNameSearchType searchType, + bool normalizeAll, // for SAN_Email case: lower-case all of + // the cert's value, not just the portion + // after the '@' + bool &dnsNameFound, // RETURNED, SAN_HostName case + bool &emailFound) // RETURNED, SAN_Email case +{ + dnsNameFound = false; + emailFound = false; + if(!subjAltNameInfo.present) { + /* common failure, no subjectAltName found */ + return CSSM_FALSE; + } + + CE_GeneralNames *names = &subjAltNameInfo.extnData->subjectAltName; + CSSM_BOOL ourRtn = CSSM_FALSE; + char *certName; + unsigned certNameLen; + + /* Search thru the CE_GeneralNames looking for the appropriate attribute */ + for(unsigned dex=0; dexnumNames; dex++) { + CE_GeneralName *name = &names->generalName[dex]; + switch(searchType) { + case SAN_HostName: + switch(name->nameType) { + case GNT_IPAddress: + if(appStr == NULL) { + /* nothing to do here */ + break; + } + ourRtn = tpCompIpAddrStr(appStr, appStrLen, &name->name); + break; + + case GNT_DNSName: + if(name->berEncoded) { + tpErrorLog("tpCompareSubjectAltName: malformed " + "CE_GeneralName (1)\n"); + break; + } + certName = (char *)name->name.Data; + if(certName == NULL) { + tpErrorLog("tpCompareSubjectAltName: malformed " + "CE_GeneralName (2)\n"); + break; + } + certNameLen = name->name.Length; + dnsNameFound = true; + if(appStr != NULL) { + /* skip if caller passed in NULL */ + ourRtn = tpCompareHostNames(appStr, appStrLen, + certName, certNameLen); + } + break; + + default: + /* not interested, proceed to next name */ + break; + } + break; /* from case HostName */ + + case SAN_Email: + if(name->nameType != GNT_RFC822Name) { + /* not interested */ + break; + } + certName = (char *)name->name.Data; + if(certName == NULL) { + tpErrorLog("tpCompareSubjectAltName: malformed " + "GNT_RFC822Name\n"); + break; + } + certNameLen = name->name.Length; + emailFound = true; + if(appStr != NULL) { + ourRtn = tpCompareEmailAddr(appStr, appStrLen, certName, + certNameLen, normalizeAll); + } + break; + } + if(ourRtn) { + /* success */ + break; + } + } + return ourRtn; +} + +/* is host name in the form of a.b.c.d, where a,b,c, and d are digits? */ +static CSSM_BOOL tpIsNumeric( + const char *hostName, + unsigned hostNameLen) +{ + if(hostName[hostNameLen - 1] == '\0') { + /* ignore NULL terminator */ + hostNameLen--; + } + for(unsigned i=0; ivalueType) { + case BER_TAG_T61_STRING: + /* a.k.a. Teletex */ + encoding = kCFStringEncodingISOLatin1; + break; + case BER_TAG_PKIX_BMP_STRING: + encoding = kCFStringEncodingUnicode; + break; + case BER_TAG_PRINTABLE_STRING: + case BER_TAG_IA5_STRING: + case BER_TAG_PKIX_UTF8_STRING: + encoding = kCFStringEncodingUTF8; + break; + default: + return NULL; + } + + /* raw data ==> CFString */ + CFDataRef cfd = CFDataCreate(NULL, tvp->value.Data, tvp->value.Length); + if(cfd == NULL) { + return NULL; + } + CFStringRef cfStr = CFStringCreateFromExternalRepresentation(NULL, cfd, encoding); + CFRelease(cfd); + return cfStr; +} + +/* + * Compare a CFString and a string represented by a CSSM_X509_TYPE_VALUE_PAIR. + * Returns CSSM_TRUE if they are equal. + */ +static bool tpCompareTvpToCfString( + const CSSM_X509_TYPE_VALUE_PAIR *tvp, + CFStringRef refStr, + CFOptionFlags flags) // e.g., kCFCompareCaseInsensitive +{ + CFStringRef cfStr = tpTvpToCfString(tvp); + if(cfStr == NULL) { + return false; + } + CFComparisonResult res = CFStringCompare(refStr, cfStr, flags); + CFRelease(cfStr); + if(res == kCFCompareEqualTo) { + return true; + } + else { + return false; + } +} + +/* + * Given one iSignCertInfo, determine whether or not the specified + * EKU OID, or - optionally - CSSMOID_ExtendedKeyUsageAny - is present. + * Returns true if so, else false. + */ +static bool tpVerifyEKU( + const iSignCertInfo &certInfo, + const CSSM_OID &ekuOid, + bool ekuAnyOK) // if true, CSSMOID_ExtendedKeyUsageAny counts as "found" +{ + if(!certInfo.extendKeyUsage.present) { + return false; + } + CE_ExtendedKeyUsage *eku = &certInfo.extendKeyUsage.extnData->extendedKeyUsage; + assert(eku != NULL); + + for(unsigned i=0; inumPurposes; i++) { + const CSSM_OID *foundEku = &eku->purposes[i]; + if(tpCompareOids(foundEku, &ekuOid)) { + return true; + } + if(ekuAnyOK && tpCompareOids(foundEku, &CSSMOID_ExtendedKeyUsageAny)) { + return true; + } + } + return false; +} + +/* + * Given one iSignCertInfo, determine whether or not the specified + * Certificate Policy OID, or - optionally - CSSMOID_ANY_POLICY - is present. + * Returns true if so, else false. + */ +static bool tpVerifyCPE( + const iSignCertInfo &certInfo, + const CSSM_OID &cpOid, + bool anyPolicyOK) // if true, CSSMOID_ANY_POLICY counts as "found" +{ + if(!certInfo.certPolicies.present) { + return false; + } + CE_CertPolicies *cp = &certInfo.certPolicies.extnData->certPolicies; + assert(cp != NULL); + + for(unsigned i=0; inumPolicies; i++) { + const CE_PolicyInformation *foundPolicy = &cp->policies[i]; + if(tpCompareOids(&foundPolicy->certPolicyId, &cpOid)) { + return true; + } + if(anyPolicyOK && tpCompareOids(&foundPolicy->certPolicyId, &CSSMOID_ANY_POLICY)) { + return true; + } + } + return false; +} + +/* + * Verify iChat handle. We search for a matching (case-insensitive) string + * comprised of: + * + * -- name component ("dmitch") from subject name's CommonName + * -- implicit '@' + * -- domain name from subject name's organizationalUnit + * + * Plus we require an Organization component of "Apple Computer, Inc." or "Apple Inc." + */ +static bool tpCompareIChatHandleName( + TPCertInfo &cert, + const char *iChatHandle, // UTF8 + uint32 iChatHandleLen) +{ + CSSM_DATA_PTR subjNameData = NULL; // from fetchField + CSSM_RETURN crtn; + bool ourRtn = false; + CSSM_X509_NAME_PTR x509name; + CSSM_X509_TYPE_VALUE_PAIR *ptvp; + CSSM_X509_RDN_PTR rdnp; + unsigned rdnDex; + unsigned pairDex; + + /* search until all of these are true */ + CSSM_BOOL commonNameMatch = CSSM_FALSE; // name before '@' + CSSM_BOOL orgUnitMatch = CSSM_FALSE; // domain after '@ + CSSM_BOOL orgMatch = CSSM_FALSE; // Apple Computer, Inc. (or Apple Inc.) + + /* + * incoming UTF8 handle ==> two components. + * First convert to CFString. + */ + if(iChatHandle[iChatHandleLen - 1] == '\0') { + /* avoid NULL when creating CFStrings */ + iChatHandleLen--; + } + CFDataRef cfd = CFDataCreate(NULL, (const UInt8 *)iChatHandle, iChatHandleLen); + if(cfd == NULL) { + return false; + } + CFStringRef handleStr = CFStringCreateFromExternalRepresentation(NULL, cfd, + kCFStringEncodingUTF8); + CFRelease(cfd); + if(handleStr == NULL) { + tpPolicyError("tpCompareIChatHandleName: bad incoming handle (1)"); + return false; + } + + /* + * Find the '@' delimiter + */ + CFRange whereIsAt; + whereIsAt = CFStringFind(handleStr, CFSTR("@"), 0); + if(whereIsAt.length == 0) { + tpPolicyError("tpCompareIChatHandleName: bad incoming handle: no @"); + CFRelease(handleStr); + return false; + } + + /* + * Two components, before and after delimiter + */ + CFRange r = {0, whereIsAt.location}; + CFStringRef iChatName = CFStringCreateWithSubstring(NULL, handleStr, r); + if(iChatName == NULL) { + tpPolicyError("tpCompareIChatHandleName: bad incoming handle (2)"); + CFRelease(handleStr); + return false; + } + r.location = whereIsAt.location + 1; // after the '@' + r.length = CFStringGetLength(handleStr) - r.location; + CFStringRef iChatDomain = CFStringCreateWithSubstring(NULL, handleStr, r); + CFRelease(handleStr); + if(iChatDomain == NULL) { + tpPolicyError("tpCompareIChatHandleName: bad incoming handle (3)"); + CFRelease(iChatName); + return false; + } + /* subsequent errors to errOut: */ + + /* get subject name in CSSM form, all subsequent ops work on that */ + crtn = cert.fetchField(&CSSMOID_X509V1SubjectNameCStruct, &subjNameData); + if(crtn) { + /* should never happen, we shouldn't be here if there is no subject */ + tpPolicyError("tpCompareIChatHandleName: error retrieving subject name"); + goto errOut; + } + + x509name = (CSSM_X509_NAME_PTR)subjNameData->Data; + if((x509name == NULL) || (subjNameData->Length != sizeof(CSSM_X509_NAME))) { + tpPolicyError("tpCompareIChatHandleName: malformed CSSM_X509_NAME"); + goto errOut; + } + + /* Now grunge thru the X509 name looking for three fields */ + + for(rdnDex=0; rdnDexnumberOfRDNs; rdnDex++) { + rdnp = &x509name->RelativeDistinguishedName[rdnDex]; + for(pairDex=0; pairDexnumberOfPairs; pairDex++) { + ptvp = &rdnp->AttributeTypeAndValue[pairDex]; + if(!commonNameMatch && + tpCompareOids(&ptvp->type, &CSSMOID_CommonName) && + tpCompareTvpToCfString(ptvp, iChatName, kCFCompareCaseInsensitive)) { + commonNameMatch = CSSM_TRUE; + } + + if(!orgUnitMatch && + tpCompareOids(&ptvp->type, &CSSMOID_OrganizationalUnitName) && + tpCompareTvpToCfString(ptvp, iChatDomain, kCFCompareCaseInsensitive)) { + orgUnitMatch = CSSM_TRUE; + } + + if(!orgMatch && + tpCompareOids(&ptvp->type, &CSSMOID_OrganizationName) && + /* this one is case sensitive */ + (tpCompareTvpToCfString(ptvp, CFSTR("Apple Computer, Inc."), 0) || + tpCompareTvpToCfString(ptvp, CFSTR("Apple Inc."), 0))) { + orgMatch = CSSM_TRUE; + } + + if(commonNameMatch && orgUnitMatch && orgMatch) { + /* TA DA */ + ourRtn = true; + goto errOut; + } + } + } +errOut: + cert.freeField(&CSSMOID_X509V1SubjectNameCStruct, subjNameData); + CFRelease(iChatName); + CFRelease(iChatDomain); + return ourRtn; +} + +/* + * Verify SSL options. Currently this just consists of matching the + * leaf cert's subject common name against the caller's (optional) + * server name. + */ +static CSSM_RETURN tp_verifySslOpts( + TPPolicy policy, + TPCertGroup &certGroup, + const CSSM_DATA *sslFieldOpts, + const iSignCertInfo &leafCertInfo) +{ + CSSM_APPLE_TP_SSL_OPTIONS *sslOpts = NULL; + unsigned hostNameLen = 0; + const char *serverName = NULL; + TPCertInfo *leaf = certGroup.certAtIndex(0); + assert(leaf != NULL); + + /* CSSM_APPLE_TP_SSL_OPTIONS is optional */ + if((sslFieldOpts != NULL) && (sslFieldOpts->Data != NULL)) { + sslOpts = (CSSM_APPLE_TP_SSL_OPTIONS *)sslFieldOpts->Data; + switch(sslOpts->Version) { + case CSSM_APPLE_TP_SSL_OPTS_VERSION: + if(sslFieldOpts->Length != sizeof(CSSM_APPLE_TP_SSL_OPTIONS)) { + return CSSMERR_TP_INVALID_POLICY_IDENTIFIERS; + } + break; + /* handle backwards compatibility here if necessary */ + default: + return CSSMERR_TP_INVALID_POLICY_IDENTIFIERS; + } + hostNameLen = sslOpts->ServerNameLen; + serverName = sslOpts->ServerName; + } + + /* host name check is optional */ + if(hostNameLen != 0) { + if(serverName == NULL) { + return CSSMERR_TP_INVALID_POINTER; + } + + /* convert caller's hostname string to lower case */ + char *hostName = (char *)certGroup.alloc().malloc(hostNameLen); + memmove(hostName, serverName, hostNameLen); + tpToLower(hostName, hostNameLen); + + CSSM_BOOL match = CSSM_FALSE; + + /* First check subjectAltName... */ + bool dnsNameFound = false; + bool dummy; + match = tpCompareSubjectAltName(leafCertInfo.subjectAltName, + hostName, hostNameLen, + SAN_HostName, false, dnsNameFound, dummy); + + /* + * Then common name, if + * -- no match from subjectAltName, AND + * -- dnsName was NOT found, AND + * -- hostName is not strictly numeric form (1.2.3.4) + */ + if(!match && !dnsNameFound && !tpIsNumeric(hostName, hostNameLen)) { + bool fieldFound; + match = tpCompareSubjectName(*leaf, SN_CommonName, false, hostName, hostNameLen, + fieldFound); + } + certGroup.alloc().free(hostName); + if(!match) { + if(leaf->addStatusCode(CSSMERR_APPLETP_HOSTNAME_MISMATCH)) { + return CSSMERR_APPLETP_HOSTNAME_MISMATCH; + } + } + } + + /* + * Ensure that, if an extendedKeyUsage extension is present in the + * leaf, that either anyExtendedKeyUsage or the appropriate + * CSSMOID_{Server,Client}Auth, or a SeverGatedCrypto usage is present. + */ + const iSignExtenInfo &ekuInfo = leafCertInfo.extendKeyUsage; + if(ekuInfo.present) { + bool foundGoodEku = false; + bool isServer = true; + CE_ExtendedKeyUsage *eku = (CE_ExtendedKeyUsage *)ekuInfo.extnData; + assert(eku != NULL); + + /* + * Determine appropriate extended key usage; default is SSL server + */ + const CSSM_OID *extUse = &CSSMOID_ServerAuth; + if((sslOpts != NULL) && /* optional, default server side */ + (sslOpts->Version > 0) && /* this was added in struct version 1 */ + (sslOpts->Flags & CSSM_APPLE_TP_SSL_CLIENT)) { + extUse = &CSSMOID_ClientAuth; + isServer = false; + } + + /* search for that one or for "any" indicator */ + for(unsigned i=0; inumPurposes; i++) { + const CSSM_OID *purpose = &eku->purposes[i]; + if(tpCompareOids(purpose, extUse)) { + foundGoodEku = true; + break; + } + if(tpCompareOids(purpose, &CSSMOID_ExtendedKeyUsageAny)) { + foundGoodEku = true; + break; + } + if((policy == kTP_IPSec) && (tpCompareOids(purpose, &CSSMOID_EKU_IPSec))) { + foundGoodEku = true; + break; + } + if(isServer) { + /* server gated crypto: server side only */ + if(tpCompareOids(purpose, &CSSMOID_NetscapeSGC)) { + foundGoodEku = true; + break; + } + if(tpCompareOids(purpose, &CSSMOID_MicrosoftSGC)) { + foundGoodEku = true; + break; + } + } + } + if(!foundGoodEku) { + if(leaf->addStatusCode(CSSMERR_APPLETP_SSL_BAD_EXT_KEY_USE)) { + return CSSMERR_TP_VERIFY_ACTION_FAILED; + } + } + } + return CSSM_OK; +} + +/* + * Verify SMIME and iChat options. + * This deals with both S/MIME and iChat policies; within the iChat domain it + * deals with Apple-specific .mac certs as well as what we call "generic AIM" + * certs, as used in the Windows AIM client. + */ +#define CE_CIPHER_MASK (~(CE_KU_EncipherOnly | CE_KU_DecipherOnly)) + +static CSSM_RETURN tp_verifySmimeOpts( + TPPolicy policy, + TPCertGroup &certGroup, + const CSSM_DATA *smimeFieldOpts, + const iSignCertInfo &leafCertInfo) +{ + bool iChat = (policy == kTP_iChat) ? true : false; + + /* + * The CSSM_APPLE_TP_SMIME_OPTIONS pointer is optional as is everything in it. + */ + CSSM_APPLE_TP_SMIME_OPTIONS *smimeOpts = NULL; + if(smimeFieldOpts != NULL) { + smimeOpts = (CSSM_APPLE_TP_SMIME_OPTIONS *)smimeFieldOpts->Data; + } + if(smimeOpts != NULL) { + switch(smimeOpts->Version) { + case CSSM_APPLE_TP_SMIME_OPTS_VERSION: + if(smimeFieldOpts->Length != + sizeof(CSSM_APPLE_TP_SMIME_OPTIONS)) { + return CSSMERR_TP_INVALID_POLICY_IDENTIFIERS; + } + break; + /* handle backwards compatibility here if necessary */ + default: + return CSSMERR_TP_INVALID_POLICY_IDENTIFIERS; + } + } + + TPCertInfo *leaf = certGroup.certAtIndex(0); + assert(leaf != NULL); + + /* Verify optional email address, a.k.a. handle for iChat policy */ + unsigned emailLen = 0; + if(smimeOpts != NULL) { + emailLen = smimeOpts->SenderEmailLen; + } + + bool match = false; + bool emailFoundInSAN = false; + bool iChatHandleFound = false; /* indicates a genuine Apple iChat cert */ + bool emailFoundInDN = false; + if(emailLen != 0) { + if(smimeOpts->SenderEmail == NULL) { + return CSSMERR_TP_INVALID_POINTER; + } + + /* iChat - first try the Apple custom format */ + if(iChat) { + iChatHandleFound = tpCompareIChatHandleName(*leaf, smimeOpts->SenderEmail, + emailLen); + if(iChatHandleFound) { + match = true; + } + + } + + if(!match) { + /* + * normalize caller's email string + * SMIME - lowercase only the portion after '@' + * iChat - lowercase all of it + */ + char *email = (char *)certGroup.alloc().malloc(emailLen); + memmove(email, smimeOpts->SenderEmail, emailLen); + tpNormalizeAddrSpec(email, emailLen, iChat); + + + /* + * First check subjectAltName. The emailFound bool indicates + * that *some* email address was found, regardless of a match + * condition. + */ + bool dummy; + match = tpCompareSubjectAltName(leafCertInfo.subjectAltName, + email, emailLen, + SAN_Email, iChat, dummy, emailFoundInSAN); + + /* + * Then subject DN, CSSMOID_EmailAddress, if no match from + * subjectAltName. In this case the whole email address is + * case insensitive (RFC 3280, section 4.1.2.6), so + * renormalize. + */ + if(!match) { + tpNormalizeAddrSpec(email, emailLen, true); + match = tpCompareSubjectName(*leaf, SN_Email, true, email, emailLen, + emailFoundInDN); + } + certGroup.alloc().free(email); + + /* + * Error here if no match found but there was indeed *some* + * email address in the cert. + */ + if(!match && (emailFoundInSAN || emailFoundInDN)) { + if(leaf->addStatusCode(CSSMERR_APPLETP_SMIME_EMAIL_ADDRS_NOT_FOUND)) { + tpPolicyError("SMIME email addrs in cert but no match"); + return CSSMERR_APPLETP_SMIME_EMAIL_ADDRS_NOT_FOUND; + } + } + } + + /* + * iChat only: error if app specified email address but there was + * none in the cert. + */ + if(iChat && !emailFoundInSAN && !emailFoundInDN && !iChatHandleFound) { + if(leaf->addStatusCode(CSSMERR_APPLETP_SMIME_NO_EMAIL_ADDRS)) { + tpPolicyError("iChat: no email address or handle in cert"); + return CSSMERR_APPLETP_SMIME_NO_EMAIL_ADDRS; + } + } + } + + /* + * Going by the letter of the law, here's what RFC 2632 has to say + * about the legality of an empty Subject Name: + * + * ...the subject DN in a user's (i.e. end-entity) certificate MAY + * be an empty SEQUENCE in which case the subjectAltName extension + * will include the subject's identifier and MUST be marked as + * critical. + * + * OK, first examine the leaf cert's subject name. + */ + CSSM_RETURN crtn; + CSSM_DATA_PTR subjNameData = NULL; + const iSignExtenInfo &kuInfo = leafCertInfo.keyUsage; + const iSignExtenInfo &ekuInfo = leafCertInfo.extendKeyUsage; + const CSSM_X509_NAME *x509Name = NULL; + + if(iChat) { + /* empty subject name processing is S/MIME only */ + goto checkEku; + } + + crtn = leaf->fetchField(&CSSMOID_X509V1SubjectNameCStruct, &subjNameData); + if(crtn) { + /* This should really never happen */ + tpPolicyError("SMIME policy: error fetching subjectName"); + leaf->addStatusCode(CSSMERR_TP_INVALID_CERTIFICATE); + return CSSMERR_TP_INVALID_CERTIFICATE; + } + /* must do a leaf->freeField(&CSSMOID_X509V1SubjectNameCStruct on exit */ + + x509Name = (const CSSM_X509_NAME *)subjNameData->Data; + if(x509Name->numberOfRDNs == 0) { + /* + * Empty subject name. If we haven't already seen a valid + * email address in the subject alternate name (by looking + * for a specific address specified by app), try to find + * one now. + */ + if(!emailFoundInSAN && // haven't found one, and + (emailLen == 0)) { // didn't even look yet + bool dummy; + tpCompareSubjectAltName(leafCertInfo.subjectAltName, + NULL, 0, // email, emailLen, + SAN_Email, false, dummy, + emailFoundInSAN); // the variable we're updating + } + if(!emailFoundInSAN) { + tpPolicyError("SMIME policy fail: empty subject name and " + "no Email Addrs in SubjectAltName"); + if(leaf->addStatusCode(CSSMERR_APPLETP_SMIME_NO_EMAIL_ADDRS)) { + leaf->freeField(&CSSMOID_X509V1SubjectNameCStruct, subjNameData); + return CSSMERR_TP_VERIFY_ACTION_FAILED; + } + else { + /* have to skip the next block */ + goto postSAN; + } + } + + /* + * One more thing: this leaf must indeed have a subjAltName + * extension and it must be critical. We would not have gotten this + * far if the subjAltName extension was not actually present.... + */ + assert(leafCertInfo.subjectAltName.present); + if(!leafCertInfo.subjectAltName.critical) { + tpPolicyError("SMIME policy fail: empty subject name and " + "no Email Addrs in SubjectAltName"); + if(leaf->addStatusCode(CSSMERR_APPLETP_SMIME_SUBJ_ALT_NAME_NOT_CRIT)) { + leaf->freeField(&CSSMOID_X509V1SubjectNameCStruct, subjNameData); + return CSSMERR_TP_VERIFY_ACTION_FAILED; + } + } + } +postSAN: + leaf->freeField(&CSSMOID_X509V1SubjectNameCStruct, subjNameData); + + /* + * Enforce the usage of the key associated with the leaf cert. + * Cert's KeyUsage must be a superset of what the app is trying to do. + * Note the {en,de}cipherOnly flags are handled separately.... + */ + if(kuInfo.present && (smimeOpts != NULL)) { + CE_KeyUsage certKu = *((CE_KeyUsage *)kuInfo.extnData); + CE_KeyUsage appKu = smimeOpts->IntendedUsage; + CE_KeyUsage intersection = certKu & appKu; + if((intersection & CE_CIPHER_MASK) != (appKu & CE_CIPHER_MASK)) { + tpPolicyError("SMIME KeyUsage err: appKu 0x%x certKu 0x%x", + appKu, certKu); + if(leaf->addStatusCode(CSSMERR_APPLETP_SMIME_BAD_KEY_USE)) { + return CSSMERR_TP_VERIFY_ACTION_FAILED; + } + } + + /* Now the en/de cipher only bits - for keyAgreement only */ + if(appKu & CE_KU_KeyAgreement) { + /* + * 1. App wants to use this for key agreement; it must + * say what it wants to do with the derived key. + * In this context, the app's XXXonly bit means that + * it wants to use the key for that op - not necessarliy + * "only". + */ + if((appKu & (CE_KU_EncipherOnly | CE_KU_DecipherOnly)) == 0) { + tpPolicyError("SMIME KeyUsage err: KeyAgreement with " + "no Encipher or Decipher"); + if(leaf->addStatusCode(CSSMERR_APPLETP_SMIME_BAD_KEY_USE)) { + return CSSMERR_TP_VERIFY_ACTION_FAILED; + } + } + + /* + * 2. If cert restricts to encipher only make sure the + * app isn't trying to decipher. + */ + if((certKu & CE_KU_EncipherOnly) && + (appKu & CE_KU_DecipherOnly)) { + tpPolicyError("SMIME KeyUsage err: cert EncipherOnly, " + "app wants to decipher"); + if(leaf->addStatusCode(CSSMERR_APPLETP_SMIME_BAD_KEY_USE)) { + return CSSMERR_TP_VERIFY_ACTION_FAILED; + } + } + + /* + * 3. If cert restricts to decipher only make sure the + * app isn't trying to encipher. + */ + if((certKu & CE_KU_DecipherOnly) && + (appKu & CE_KU_EncipherOnly)) { + tpPolicyError("SMIME KeyUsage err: cert DecipherOnly, " + "app wants to encipher"); + if(leaf->addStatusCode(CSSMERR_APPLETP_SMIME_BAD_KEY_USE)) { + return CSSMERR_TP_VERIFY_ACTION_FAILED; + } + } + } + } + + /* + * Extended Key Use verification, which is different for the two policies. + */ +checkEku: + if(iChat && !ekuInfo.present) { + /* + * iChat: whether generic AIM cert or Apple .mac/iChat cert, we must have an + * extended key use extension. + */ + tpPolicyError("iChat: No extended Key Use"); + if(leaf->addStatusCode(CSSMERR_APPLETP_SMIME_BAD_EXT_KEY_USE)) { + return CSSMERR_APPLETP_SMIME_BAD_EXT_KEY_USE; + } + } + + if(!iChatHandleFound) { + /* + * S/MIME and generic AIM certs when evaluating iChat policy. + * Look for either emailProtection or anyExtendedKeyUsage usages. + * + * S/MIME : the whole extension is optional. + * iChat : extension must be there (which we've already covered, above) + * and we must find one of those extensions. + */ + if(ekuInfo.present) { + bool foundGoodEku = false; + CE_ExtendedKeyUsage *eku = (CE_ExtendedKeyUsage *)ekuInfo.extnData; + assert(eku != NULL); + for(unsigned i=0; inumPurposes; i++) { + if(tpCompareOids(&eku->purposes[i], &CSSMOID_EmailProtection)) { + foundGoodEku = true; + break; + } + if(tpCompareOids(&eku->purposes[i], &CSSMOID_ExtendedKeyUsageAny)) { + foundGoodEku = true; + break; + } + } + if(!foundGoodEku) { + tpPolicyError("iChat/SMIME: No appropriate extended Key Use"); + if(leaf->addStatusCode(CSSMERR_APPLETP_SMIME_BAD_EXT_KEY_USE)) { + return CSSMERR_APPLETP_SMIME_BAD_EXT_KEY_USE; + } + } + } + } + else { + /* + * Apple iChat cert. Look for anyExtendedKeyUsage, iChatSigning, + * ichatEncrypting - the latter of two which can optionally be + * required by app. + */ + assert(iChat); /* or we could not have even looked for an iChat style handle */ + assert(ekuInfo.present); /* checked above */ + bool foundAnyEku = false; + bool foundIChatSign = false; + bool foundISignEncrypt = false; + CE_ExtendedKeyUsage *eku = (CE_ExtendedKeyUsage *)ekuInfo.extnData; + assert(eku != NULL); + + for(unsigned i=0; inumPurposes; i++) { + if(tpCompareOids(&eku->purposes[i], + &CSSMOID_APPLE_EKU_ICHAT_SIGNING)) { + foundIChatSign = true; + } + else if(tpCompareOids(&eku->purposes[i], + &CSSMOID_APPLE_EKU_ICHAT_ENCRYPTION)) { + foundISignEncrypt = true; + } + else if(tpCompareOids(&eku->purposes[i], &CSSMOID_ExtendedKeyUsageAny)) { + foundAnyEku = true; + } + } + + if(!foundAnyEku && !foundISignEncrypt && !foundIChatSign) { + /* No go - no acceptable uses found */ + tpPolicyError("iChat: No valid extended Key Uses found"); + if(leaf->addStatusCode(CSSMERR_APPLETP_SMIME_BAD_EXT_KEY_USE)) { + return CSSMERR_APPLETP_SMIME_BAD_EXT_KEY_USE; + } + } + + /* check for specifically required uses */ + if((smimeOpts != NULL) && (smimeOpts->IntendedUsage != 0)) { + if(smimeOpts->IntendedUsage & CE_KU_DigitalSignature) { + if(!foundIChatSign) { + tpPolicyError("iChat: ICHAT_SIGNING required, but missing"); + if(leaf->addStatusCode(CSSMERR_APPLETP_SMIME_BAD_EXT_KEY_USE)) { + return CSSMERR_APPLETP_SMIME_BAD_EXT_KEY_USE; + } + } + } + if(smimeOpts->IntendedUsage & CE_KU_DataEncipherment) { + if(!foundISignEncrypt) { + tpPolicyError("iChat: ICHAT_ENCRYPT required, but missing"); + if(leaf->addStatusCode(CSSMERR_APPLETP_SMIME_BAD_EXT_KEY_USE)) { + return CSSMERR_APPLETP_SMIME_BAD_EXT_KEY_USE; + } + } + } + } /* checking IntendedUsage */ + } /* iChat cert format */ + + return CSSM_OK; +} + +/* + * Verify Apple SW Update signing (was Apple Code Signing, pre-Leopard) options. + * + * -- Must have one intermediate cert + * -- intermediate must have basic constraints with path length 0 + * -- intermediate has CSSMOID_APPLE_EKU_CODE_SIGNING EKU + * -- leaf cert has either CODE_SIGNING or CODE_SIGN_DEVELOPMENT EKU (the latter of + * which triggers a CSSMERR_APPLETP_CODE_SIGN_DEVELOPMENT error) + */ +static CSSM_RETURN tp_verifySWUpdateSigningOpts( + TPCertGroup &certGroup, + const CSSM_DATA *fieldOpts, // currently unused + const iSignCertInfo *certInfo) // all certs, size certGroup.numCerts() +{ + unsigned numCerts = certGroup.numCerts(); + const iSignCertInfo *isCertInfo; + TPCertInfo *tpCert; +// const CE_BasicConstraints *bc; // currently unused + CE_ExtendedKeyUsage *eku; + CSSM_RETURN crtn = CSSM_OK; + + if(numCerts != 3) { + if(!certGroup.isAllowedError(CSSMERR_APPLETP_CS_BAD_CERT_CHAIN_LENGTH)) { + tpPolicyError("tp_verifySWUpdateSigningOpts: numCerts %u", numCerts); + return CSSMERR_APPLETP_CS_BAD_CERT_CHAIN_LENGTH; + } + else if(numCerts < 3) { + /* this error allowed, but no intermediate...check leaf */ + goto checkLeaf; + } + } + + /* verify intermediate cert */ + isCertInfo = &certInfo[1]; + tpCert = certGroup.certAtIndex(1); + + if(!isCertInfo->basicConstraints.present) { + tpPolicyError("tp_verifySWUpdateSigningOpts: no basicConstraints in intermediate"); + if(tpCert->addStatusCode(CSSMERR_APPLETP_CS_NO_BASIC_CONSTRAINTS)) { + return CSSMERR_APPLETP_CS_NO_BASIC_CONSTRAINTS; + } + } + + /* ExtendedKeyUse required, one legal value */ + if(!isCertInfo->extendKeyUsage.present) { + tpPolicyError("tp_verifySWUpdateSigningOpts: no extendedKeyUse in intermediate"); + if(tpCert->addStatusCode(CSSMERR_APPLETP_CS_NO_EXTENDED_KEY_USAGE)) { + return CSSMERR_APPLETP_CS_NO_EXTENDED_KEY_USAGE; + } + else { + goto checkLeaf; + } + } + + eku = &isCertInfo->extendKeyUsage.extnData->extendedKeyUsage; + assert(eku != NULL); + if(eku->numPurposes != 1) { + tpPolicyError("tp_verifySWUpdateSigningOpts: bad eku->numPurposes in intermediate (%lu)", + (unsigned long)eku->numPurposes); + if(tpCert->addStatusCode(CSSMERR_APPLETP_INVALID_EXTENDED_KEY_USAGE)) { + return CSSMERR_APPLETP_INVALID_EXTENDED_KEY_USAGE; + } + else if(eku->numPurposes == 0) { + /* ignore that error but no EKU - skip EKU check */ + goto checkLeaf; + } + /* else ignore error and we have an intermediate EKU; proceed */ + } + + if(!tpCompareOids(&eku->purposes[0], &CSSMOID_APPLE_EKU_CODE_SIGNING)) { + tpPolicyError("tp_verifySWUpdateSigningOpts: bad EKU"); + if(tpCert->addStatusCode(CSSMERR_APPLETP_INVALID_EXTENDED_KEY_USAGE)) { + crtn = CSSMERR_APPLETP_INVALID_EXTENDED_KEY_USAGE; + } + } + +checkLeaf: + + /* verify leaf cert */ + isCertInfo = &certInfo[0]; + tpCert = certGroup.certAtIndex(0); + if(!isCertInfo->extendKeyUsage.present) { + tpPolicyError("tp_verifySWUpdateSigningOpts: no extendedKeyUse in leaf"); + if(tpCert->addStatusCode(CSSMERR_APPLETP_CS_NO_EXTENDED_KEY_USAGE)) { + return crtn ? crtn : CSSMERR_APPLETP_CS_NO_EXTENDED_KEY_USAGE; + } + else { + /* have to skip remainder */ + return CSSM_OK; + } + } + + eku = &isCertInfo->extendKeyUsage.extnData->extendedKeyUsage; + assert(eku != NULL); + if(eku->numPurposes != 1) { + tpPolicyError("tp_verifySWUpdateSigningOpts: bad eku->numPurposes (%lu)", + (unsigned long)eku->numPurposes); + if(tpCert->addStatusCode(CSSMERR_APPLETP_INVALID_EXTENDED_KEY_USAGE)) { + if(crtn == CSSM_OK) { + crtn = CSSMERR_APPLETP_INVALID_EXTENDED_KEY_USAGE; + } + } + return crtn; + } + if(!tpCompareOids(&eku->purposes[0], &CSSMOID_APPLE_EKU_CODE_SIGNING)) { + if(tpCompareOids(&eku->purposes[0], &CSSMOID_APPLE_EKU_CODE_SIGNING_DEV)) { + tpPolicyError("tp_verifySWUpdateSigningOpts: DEVELOPMENT cert"); + if(tpCert->addStatusCode(CSSMERR_APPLETP_CODE_SIGN_DEVELOPMENT)) { + if(crtn == CSSM_OK) { + crtn = CSSMERR_APPLETP_CODE_SIGN_DEVELOPMENT; + } + } + } + else { + tpPolicyError("tp_verifySWUpdateSigningOpts: bad EKU in leaf"); + if(tpCert->addStatusCode(CSSMERR_APPLETP_INVALID_EXTENDED_KEY_USAGE)) { + if(crtn == CSSM_OK) { + crtn = CSSMERR_APPLETP_INVALID_EXTENDED_KEY_USAGE; + } + } + } + } + + return crtn; +} + +/* + * Verify Apple Resource Signing options. + * + * -- leaf cert must have CSSMOID_APPLE_EKU_RESOURCE_SIGNING EKU + * -- chain length must be >= 2 + * -- mainline code already verified that leaf KeyUsage = digitalSignature (only) + */ +static CSSM_RETURN tp_verifyResourceSigningOpts( + TPCertGroup &certGroup, + const CSSM_DATA *fieldOpts, // currently unused + const iSignCertInfo *certInfo) // all certs, size certGroup.numCerts() +{ + unsigned numCerts = certGroup.numCerts(); + if(numCerts < 2) { + if(!certGroup.isAllowedError(CSSMERR_APPLETP_RS_BAD_CERT_CHAIN_LENGTH)) { + tpPolicyError("tp_verifyResourceSigningOpts: numCerts %u", numCerts); + return CSSMERR_APPLETP_RS_BAD_CERT_CHAIN_LENGTH; + } + } + const iSignCertInfo &leafCert = certInfo[0]; + TPCertInfo *leaf = certGroup.certAtIndex(0); + + /* leaf ExtendedKeyUse required, one legal value */ + if(!tpVerifyEKU(leafCert, CSSMOID_APPLE_EKU_RESOURCE_SIGNING, false)) { + tpPolicyError("tp_verifyResourceSigningOpts: no RESOURCE_SIGNING EKU"); + if(leaf->addStatusCode(CSSMERR_APPLETP_INVALID_EXTENDED_KEY_USAGE)) { + return CSSMERR_APPLETP_INVALID_EXTENDED_KEY_USAGE; + } + } + + return CSSM_OK; +} + +/* + * Common code for Apple Code Signing and Apple Package Signing. + * For now we just require an RFC3280-style CodeSigning EKU in the leaf + * for both policies. + */ +static CSSM_RETURN tp_verifyCodePkgSignOpts( + TPPolicy policy, + TPCertGroup &certGroup, + const CSSM_DATA *fieldOpts, // currently unused + const iSignCertInfo *certInfo) // all certs, size certGroup.numCerts() +{ + const iSignCertInfo &leafCert = certInfo[0]; + + /* leaf ExtendedKeyUse required, one legal value */ + if(!tpVerifyEKU(leafCert, CSSMOID_ExtendedUseCodeSigning, false)) { + TPCertInfo *leaf = certGroup.certAtIndex(0); + tpPolicyError("tp_verifyCodePkgSignOpts: no CodeSigning EKU"); + if(leaf->addStatusCode(CSSMERR_APPLETP_INVALID_EXTENDED_KEY_USAGE)) { + return CSSMERR_APPLETP_INVALID_EXTENDED_KEY_USAGE; + } + } + + return CSSM_OK; + +} + +/* + * Verify MacAppStore receipt verification policy options. + * + * -- Must have one intermediate cert + * -- intermediate must be the FairPlay intermediate + * -- leaf cert has the CSSMOID_APPLE_EXTENSION_MACAPPSTORE_RECEIPT marker extension + */ +static CSSM_RETURN tp_verifyMacAppStoreReciptOpts( + TPCertGroup &certGroup, + const CSSM_DATA *fieldOpts, // currently unused + const iSignCertInfo *certInfo) // all certs, size certGroup.numCerts() +{ + unsigned numCerts = certGroup.numCerts(); + if (numCerts < 3) + { + if (!certGroup.isAllowedError(CSSMERR_APPLETP_CS_BAD_CERT_CHAIN_LENGTH)) + { + tpPolicyError("tp_verifyMacAppStoreReciptOpts: numCerts %u", numCerts); + return CSSMERR_APPLETP_CS_BAD_CERT_CHAIN_LENGTH; + } + } + + const iSignCertInfo *isCertInfo; + TPCertInfo *tpCert; + + /* verify intermediate cert */ + isCertInfo = &certInfo[1]; + tpCert = certGroup.certAtIndex(1); + + if (!isCertInfo->basicConstraints.present) + { + tpPolicyError("tp_verifyAppleIDSharingOpts: no basicConstraints in intermediate"); + if (tpCert->addStatusCode(CSSMERR_APPLETP_CS_NO_BASIC_CONSTRAINTS)) + return CSSMERR_APPLETP_CS_NO_BASIC_CONSTRAINTS; + } + + // Now check the leaf + isCertInfo = &certInfo[0]; + tpCert = certGroup.certAtIndex(0); + if (certInfo->certificatePolicies.present) + { + // syslog(LOG_ERR, "tp_verifyMacAppStoreReciptOpts: found certificatePolicies"); + const CE_CertPolicies *certPolicies = + &isCertInfo->certificatePolicies.extnData->certPolicies; + if (!certificatePoliciesContainsOID(certPolicies, &CSSMOID_MACAPPSTORE_RECEIPT_CERT_POLICY)) + if (tpCert->addStatusCode(CSSMERR_APPLETP_MISSING_REQUIRED_EXTENSION)) + return CSSMERR_APPLETP_MISSING_REQUIRED_EXTENSION; + } + else + { + // syslog(LOG_ERR, "tp_verifyMacAppStoreReciptOpts: no certificatePolicies present"); // DEBUG + tpPolicyError("tp_verifyMacAppStoreReciptOpts: no certificatePolicies present in leaf"); + if (tpCert->addStatusCode(CSSMERR_APPLETP_MISSING_REQUIRED_EXTENSION)) + return CSSMERR_APPLETP_MISSING_REQUIRED_EXTENSION; + } + + return CSSM_OK; +} + +bool certificatePoliciesContainsOID(const CE_CertPolicies *certPolicies, const CSSM_OID *oidToFind) +{ + // returns true if the given OID is present in the cert policies + + if (!certPolicies || !oidToFind) + return false; + + const uint32 maxIndex = 100; // sanity check + for (uint32 policyIndex = 0; policyIndex < certPolicies->numPolicies && policyIndex < maxIndex; policyIndex++) + { + CE_PolicyInformation *certPolicyInfo = &certPolicies->policies[policyIndex]; + CSSM_OID_PTR oid = &certPolicyInfo->certPolicyId; + if (oid && tpCompareOids(oid, oidToFind)) // found it + return true; + } + + return false; +} + + +/* + * Verify Apple ID Sharing options. + * + * -- Do basic cert validation (OCSP-based certs) + * -- Validate that the cert is an Apple ID sharing cert: + * has a custom extension: OID: Apple ID Sharing Certificate ( 1 2 840 113635 100 4 7 ) + * (CSSMOID_APPLE_EXTENSION_APPLEID_SHARING) + * EKU should have both client and server authentication + * chains to the "Apple Application Integration Certification Authority" intermediate + * -- optionally has a client-specified common name, which is the Apple ID account's UUID. + + * -- Must have one intermediate cert ("Apple Application Integration Certification Authority") + * -- intermediate must have basic constraints with path length 0 + * -- intermediate has CSSMOID_APPLE_EXTENSION_AAI_INTERMEDIATE extension (OID 1 2 840 113635 100 6 2 3) + OR APPLE_EXTENSION_AAI_INTERMEDIATE_2 + */ + +static CSSM_RETURN tp_verifyAppleIDSharingOpts(TPCertGroup &certGroup, + const CSSM_DATA *fieldOpts, // optional Common Name + const iSignCertInfo *certInfo) // all certs, size certGroup.numCerts() +{ + unsigned numCerts = certGroup.numCerts(); + const iSignCertInfo *isCertInfo; + TPCertInfo *tpCert; + // const CE_BasicConstraints *bc; // currently unused + CE_ExtendedKeyUsage *eku; + CSSM_RETURN crtn = CSSM_OK; + unsigned int serverNameLen = 0; + const char *serverName = NULL; + + // The CSSM_APPLE_TP_SMIME_OPTIONS pointer is optional as is everything in it. + if (fieldOpts && fieldOpts->Data) + { + CSSM_APPLE_TP_SSL_OPTIONS *sslOpts = (CSSM_APPLE_TP_SSL_OPTIONS *)fieldOpts->Data; + switch (sslOpts->Version) + { + case CSSM_APPLE_TP_SSL_OPTS_VERSION: + if (fieldOpts->Length != sizeof(CSSM_APPLE_TP_SSL_OPTIONS)) + return CSSMERR_TP_INVALID_POLICY_IDENTIFIERS; + break; + /* handle backwards compatibility here if necessary */ + default: + return CSSMERR_TP_INVALID_POLICY_IDENTIFIERS; + } + serverNameLen = sslOpts->ServerNameLen; + serverName = sslOpts->ServerName; + } + + //------------------------------------------------------------------------ + + if (numCerts != 3) + { + if (!certGroup.isAllowedError(CSSMERR_APPLETP_CS_BAD_CERT_CHAIN_LENGTH)) + { + tpPolicyError("tp_verifyAppleIDSharingOpts: numCerts %u", numCerts); + return CSSMERR_APPLETP_CS_BAD_CERT_CHAIN_LENGTH; + } + else + if (numCerts < 3) + { + /* this error allowed, but no intermediate...check leaf */ + goto checkLeaf; + } + } + + /* verify intermediate cert */ + isCertInfo = &certInfo[1]; + tpCert = certGroup.certAtIndex(1); + + if (!isCertInfo->basicConstraints.present) + { + tpPolicyError("tp_verifyAppleIDSharingOpts: no basicConstraints in intermediate"); + if (tpCert->addStatusCode(CSSMERR_APPLETP_CS_NO_BASIC_CONSTRAINTS)) + return CSSMERR_APPLETP_CS_NO_BASIC_CONSTRAINTS; + } + +checkLeaf: + + /* verify leaf cert */ + isCertInfo = &certInfo[0]; + tpCert = certGroup.certAtIndex(0); + + /* host name check is optional */ + if (serverNameLen != 0) + { + if (serverName == NULL) + return CSSMERR_TP_INVALID_POINTER; + + /* convert caller's hostname string to lower case */ + char *hostName = (char *)certGroup.alloc().malloc(serverNameLen); + memmove(hostName, serverName, serverNameLen); + tpToLower(hostName, serverNameLen); + + /* Check common name... */ + + bool fieldFound; + CSSM_BOOL match = tpCompareSubjectName(*tpCert, SN_CommonName, false, hostName, + serverNameLen, fieldFound); + + certGroup.alloc().free(hostName); + if (!match && tpCert->addStatusCode(CSSMERR_APPLETP_HOSTNAME_MISMATCH)) + return CSSMERR_APPLETP_HOSTNAME_MISMATCH; + } + + if (certInfo->certificatePolicies.present) + { + const CE_CertPolicies *certPolicies = + &isCertInfo->certificatePolicies.extnData->certPolicies; + if (!certificatePoliciesContainsOID(certPolicies, &CSSMOID_APPLEID_SHARING_CERT_POLICY)) + if (tpCert->addStatusCode(CSSMERR_APPLETP_MISSING_REQUIRED_EXTENSION)) + return CSSMERR_APPLETP_MISSING_REQUIRED_EXTENSION; + } + else + if (tpCert->addStatusCode(CSSMERR_APPLETP_MISSING_REQUIRED_EXTENSION)) + return CSSMERR_APPLETP_MISSING_REQUIRED_EXTENSION; + + if (!isCertInfo->extendKeyUsage.present) + { + tpPolicyError("tp_verifyAppleIDSharingOpts: no extendedKeyUse in leaf"); + if (tpCert->addStatusCode(CSSMERR_APPLETP_CS_NO_EXTENDED_KEY_USAGE)) + return crtn ? crtn : CSSMERR_APPLETP_CS_NO_EXTENDED_KEY_USAGE; + + /* have to skip remainder */ + return CSSM_OK; + } + + // Check that certificate can do Client and Server Authentication (EKU) + eku = &isCertInfo->extendKeyUsage.extnData->extendedKeyUsage; + assert(eku != NULL); + if(eku->numPurposes != 2) + { + tpPolicyError("tp_verifyAppleIDSharingOpts: bad eku->numPurposes (%lu)", + (unsigned long)eku->numPurposes); + if (tpCert->addStatusCode(CSSMERR_APPLETP_INVALID_EXTENDED_KEY_USAGE)) + { + if (crtn == CSSM_OK) + crtn = CSSMERR_APPLETP_INVALID_EXTENDED_KEY_USAGE; + } + return crtn; + } + bool canDoClientAuth = false, canDoServerAuth = false, ekuError = false; + for (int ix=0;ix<2;ix++) + { + if (tpCompareOids(&eku->purposes[ix], &CSSMOID_ClientAuth)) + canDoClientAuth = true; + else + if (tpCompareOids(&eku->purposes[ix], &CSSMOID_ServerAuth)) + canDoServerAuth = true; + else + { + ekuError = true; + break; + } + } + + if (!(canDoClientAuth && canDoServerAuth)) + ekuError = true; + if (ekuError) + { + tpPolicyError("tp_verifyAppleIDSharingOpts: bad EKU in leaf"); + if (tpCert->addStatusCode(CSSMERR_APPLETP_INVALID_EXTENDED_KEY_USAGE)) + { + if (crtn == CSSM_OK) + crtn = CSSMERR_APPLETP_INVALID_EXTENDED_KEY_USAGE; + } + } + + return crtn; +} + +/* + * Verify Time Stamping (RFC3161) policy options. + * + * -- Leaf must contain Extended Key Usage (EKU), marked critical + * -- The EKU must contain the id-kp-timeStamping purpose and no other + */ +static CSSM_RETURN tp_verifyTimeStampingOpts(TPCertGroup &certGroup, + const CSSM_DATA *fieldOpts, // currently unused + const iSignCertInfo *certInfo) // all certs, size certGroup.numCerts() +{ + unsigned numCerts = certGroup.numCerts(); + const iSignCertInfo *isCertInfo; + TPCertInfo *tpCert; + CE_ExtendedKeyUsage *eku; + + isCertInfo = &certInfo[0]; + tpCert = certGroup.certAtIndex(0); + + if (!isCertInfo->extendKeyUsage.present) + { + tpPolicyError("tp_verifyTimeStampingOpts: no extendedKeyUse in leaf"); + tpCert->addStatusCode(CSSMERR_APPLETP_MISSING_REQUIRED_EXTENSION); + return CSSMERR_APPLETP_MISSING_REQUIRED_EXTENSION; + } + + if(!isCertInfo->extendKeyUsage.critical) + { + tpPolicyError("tp_verifyTimeStampingOpts: extended key usage !critical"); + tpCert->addStatusCode(CSSMERR_APPLETP_EXT_KEYUSAGE_NOT_CRITICAL); + return CSSMERR_APPLETP_EXT_KEYUSAGE_NOT_CRITICAL; + } + + eku = &isCertInfo->extendKeyUsage.extnData->extendedKeyUsage; + assert(eku != NULL); + + if(eku->numPurposes != 1) + { + tpPolicyError("tp_verifyTimeStampingOpts: bad eku->numPurposes (%lu)", + (unsigned long)eku->numPurposes); + tpCert->addStatusCode(CSSMERR_APPLETP_INVALID_EXTENDED_KEY_USAGE); + return CSSMERR_APPLETP_INVALID_EXTENDED_KEY_USAGE; + } + + if(!tpCompareOids(&eku->purposes[0], &CSSMOID_TimeStamping)) + { + tpPolicyError("tp_verifyTimeStampingOpts: TimeStamping purpose not found"); + tpCert->addStatusCode(CSSMERR_APPLETP_INVALID_EXTENDED_KEY_USAGE); + return CSSMERR_APPLETP_INVALID_EXTENDED_KEY_USAGE; + } + + return CSSM_OK; +} + +/* + * RFC2459 says basicConstraints must be flagged critical for + * CA certs, but Verisign doesn't work that way. + */ +#define BASIC_CONSTRAINTS_MUST_BE_CRITICAL 0 + +/* + * TP iSign spec says Extended Key Usage required for leaf certs, + * but Verisign doesn't work that way. + */ +#define EXTENDED_KEY_USAGE_REQUIRED_FOR_LEAF 0 + +/* + * TP iSign spec says Subject Alternate Name required for leaf certs, + * but Verisign doesn't work that way. + */ +#define SUBJECT_ALT_NAME_REQUIRED_FOR_LEAF 0 + +/* + * TP iSign spec originally required KeyUsage for all certs, but + * Verisign doesn't have that in their roots. + */ +#define KEY_USAGE_REQUIRED_FOR_ROOT 0 + +/* + * RFC 2632, "S/MIME Version 3 Certificate Handling", section + * 4.4.2, says that KeyUsage extensions MUST be flagged critical, + * but Thawte's intermediate cert (common name "Thawte Personal + * Freemail Issuing CA") does not meet this requirement. + */ +#define SMIME_KEY_USAGE_MUST_BE_CRITICAL 0 + +/* + * Public routine to perform TP verification on a constructed + * cert group. + * Returns CSSM_OK on success. + * Assumes the chain has passed basic subject/issuer verification. First cert of + * incoming certGroup is end-entity (leaf). + * + * Per-policy details: + * iSign: Assumes that last cert in incoming certGroup is a root cert. + * Also assumes a cert group of more than one cert. + * kTPx509Basic: CertGroup of length one allowed. + */ +CSSM_RETURN tp_policyVerify( + TPPolicy policy, + Allocator &alloc, + CSSM_CL_HANDLE clHand, + CSSM_CSP_HANDLE cspHand, + TPCertGroup *certGroup, + CSSM_BOOL verifiedToRoot, // last cert is good root + CSSM_BOOL verifiedViaTrustSetting, // last cert verified via + // user trust + CSSM_APPLE_TP_ACTION_FLAGS actionFlags, + const CSSM_DATA *policyFieldData, // optional + void *policyOpts) // future options +{ + iSignCertInfo *certInfo = NULL; + uint32 numCerts; + iSignCertInfo *thisCertInfo; + uint16 expUsage; + uint16 actUsage; + unsigned certDex; + CSSM_BOOL cA = CSSM_FALSE; // init for compiler warning + bool isLeaf; // end entity + bool isRoot; // root cert + CE_ExtendedKeyUsage *extendUsage; + CE_AuthorityKeyID *authorityId; + CSSM_KEY_PTR pubKey; + CSSM_RETURN outErr = CSSM_OK; // for gross, non-policy errors + CSSM_BOOL policyFail = CSSM_FALSE;// generic CSSMERR_TP_VERIFY_ACTION_FAILED + CSSM_RETURN policyError = CSSM_OK; // policy-specific failure + + /* First, kTPDefault is a nop here */ + if(policy == kTPDefault) { + return CSSM_OK; + } + + if(certGroup == NULL) { + return CSSMERR_TP_INVALID_CERTGROUP; + } + numCerts = certGroup->numCerts(); + if(numCerts == 0) { + return CSSMERR_TP_INVALID_CERTGROUP; + } + if(policy == kTPiSign) { + if(!verifiedToRoot) { + /* no way, this requires a root cert */ + return CSSMERR_TP_VERIFY_ACTION_FAILED; + } + if(numCerts <= 1) { + /* nope, not for iSign */ + return CSSMERR_TP_VERIFY_ACTION_FAILED; + } + } + + /* cook up an iSignCertInfo array */ + certInfo = (iSignCertInfo *)tpCalloc(alloc, numCerts, sizeof(iSignCertInfo)); + /* subsequent errors to errOut: */ + + /* fill it with interesting info from parsed certs */ + for(certDex=0; certDexcertAtIndex(certDex), + &certInfo[certDex])) { + (certGroup->certAtIndex(certDex))->addStatusCode( + CSSMERR_TP_INVALID_CERTIFICATE); + /* this one is fatal (and can't ignore) */ + outErr = CSSMERR_TP_INVALID_CERTIFICATE; + goto errOut; + } + } + + /* + * OK, the heart of TP enforcement. + */ + for(certDex=0; certDexcertAtIndex(certDex); + + /* + * First check for presence of required extensions and + * critical extensions we don't understand. + */ + if(thisCertInfo->foundUnknownCritical) { + /* illegal for all policies */ + tpPolicyError("tp_policyVerify: critical flag in unknown extension"); + if(thisTpCertInfo->addStatusCode(CSSMERR_APPLETP_UNKNOWN_CRITICAL_EXTEN)) { + policyFail = CSSM_TRUE; + } + } + + /* + * Check for unsupported key length, per + */ + if((pubKey=thisTpCertInfo->pubKey()) != NULL) { + CSSM_KEYHEADER *keyHdr = &pubKey->KeyHeader; + if(keyHdr->AlgorithmId == CSSM_ALGID_RSA && keyHdr->LogicalKeySizeInBits < 1024) { + tpPolicyError("tp_policyVerify: RSA key size too small"); + if(thisTpCertInfo->addStatusCode(CSSMERR_CSP_UNSUPPORTED_KEY_SIZE)) { + policyFail = CSSM_TRUE; + } + } + } + + /* + * Note it's possible for both of these to be true, for a chain + * of length one (kTPx509Basic, kCrlPolicy only!) + * FIXME: should this code work if the last cert in the chain is NOT a root? + */ + isLeaf = thisTpCertInfo->isLeaf(); + isRoot = thisTpCertInfo->isSelfSigned(true); + + /* + * BasicConstraints.cA + * iSign: required in all but leaf and root, + * for which it is optional (with default values of false + * for leaf and true for root). + * all others: always optional, default of false for leaf and + * true for others + * All: cA must be false for leaf, true for others + */ + if(!thisCertInfo->basicConstraints.present) { + /* + * No basicConstraints present; infer a cA value if appropriate. + */ + if(isLeaf) { + /* cool, use default; note that kTPx509Basic with + * certGroup length of one may take this case */ + cA = CSSM_FALSE; + } + else if(isRoot) { + /* cool, use default */ + cA = CSSM_TRUE; + } + else { + switch(policy) { + default: + /* + * not present, not leaf, not root.... + * ....RFC2459 says this can not be a CA + */ + cA = CSSM_FALSE; + break; + case kTPiSign: + /* required for iSign in this position */ + tpPolicyError("tp_policyVerify: no " + "basicConstraints"); + if(thisTpCertInfo->addStatusCode( + CSSMERR_APPLETP_NO_BASIC_CONSTRAINTS)) { + policyFail = CSSM_TRUE; + } + break; + } + } + } /* inferred a default value */ + else { + /* basicConstraints present */ + #if BASIC_CONSTRAINTS_MUST_BE_CRITICAL + /* disabled for verisign compatibility */ + if(!thisCertInfo->basicConstraints.critical) { + /* per RFC 2459 */ + tpPolicyError("tp_policyVerify: basicConstraints marked " + "not critical"); + if(thisTpCertInfo->addStatusCode(CSSMERR_TP_VERIFY_ACTION_FAILED)) { + policyFail = CSSM_TRUE; + } + } + #endif /* BASIC_CONSTRAINTS_MUST_BE_CRITICAL */ + + const CE_BasicConstraints *bcp = + &thisCertInfo->basicConstraints.extnData->basicConstraints; + + cA = bcp->cA; + + /* Verify pathLenConstraint if present */ + if(!isLeaf && // leaf, certDex=0, don't care + cA && // p.l.c. only valid for CAs + bcp->pathLenConstraintPresent) { // present? + /* + * pathLenConstraint=0 legal for certDex 1 only + * pathLenConstraint=1 legal for certDex {1,2} + * etc. + */ + if(certDex > (bcp->pathLenConstraint + 1)) { + tpPolicyError("tp_policyVerify: pathLenConstraint " + "exceeded"); + if(thisTpCertInfo->addStatusCode( + CSSMERR_APPLETP_PATH_LEN_CONSTRAINT)) { + policyFail = CSSM_TRUE; + } + } + } + } + + if(isLeaf) { + /* + * Special cases to allow a chain of length 1, leaf and root + * both true, and for caller to override the "leaf can't be a CA" + * requirement when a CA cert is explicitly being evaluated as the + * leaf. + */ + if(cA && !isRoot && + !(actionFlags & CSSM_TP_ACTION_LEAF_IS_CA)) { + tpPolicyError("tp_policyVerify: cA true for leaf"); + if(thisTpCertInfo->addStatusCode(CSSMERR_APPLETP_INVALID_CA)) { + policyFail = CSSM_TRUE; + } + } + } else if(!cA) { + tpPolicyError("tp_policyVerify: cA false for non-leaf"); + if(thisTpCertInfo->addStatusCode(CSSMERR_APPLETP_INVALID_CA)) { + policyFail = CSSM_TRUE; + } + } + + /* + * Authority Key Identifier optional + * iSign : only allowed in !root. + * If present, must not be critical. + * all others : ignored (though used later for chain verification) + */ + if((policy == kTPiSign) && thisCertInfo->authorityId.present) { + if(isRoot) { + tpPolicyError("tp_policyVerify: authorityId in root"); + if(thisTpCertInfo->addStatusCode(CSSMERR_APPLETP_INVALID_AUTHORITY_ID)) { + policyFail = CSSM_TRUE; + } + } + if(thisCertInfo->authorityId.critical) { + /* illegal per RFC 2459 */ + tpPolicyError("tp_policyVerify: authorityId marked " + "critical"); + if(thisTpCertInfo->addStatusCode(CSSMERR_APPLETP_INVALID_AUTHORITY_ID)) { + policyFail = CSSM_TRUE; + } + } + } + + /* + * Subject Key Identifier optional + * iSign : can't be critical. + * all others : ignored (though used later for chain verification) + */ + if(thisCertInfo->subjectId.present) { + if((policy == kTPiSign) && thisCertInfo->subjectId.critical) { + tpPolicyError("tp_policyVerify: subjectId marked critical"); + if(thisTpCertInfo->addStatusCode(CSSMERR_APPLETP_INVALID_SUBJECT_ID)) { + policyFail = CSSM_TRUE; + } + } + } + + /* + * Key Usage optional except required as noted + * iSign : required for non-root/non-leaf + * Leaf cert : if present, usage = digitalSignature + * Exception : if leaf, and keyUsage not present, + * netscape-cert-type must be present, with + * Object Signing bit set + * kCrlPolicy : Leaf: usage = CRLSign + * kTP_SMIME : if present, must be critical + * kTP_SWUpdateSign, kTP_ResourceSign, kTP_CodeSigning, kTP_PackageSigning : Leaf : + usage = digitalSignature + * all others : non-leaf : usage = keyCertSign + * Leaf : don't care + */ + if(thisCertInfo->keyUsage.present) { + /* + * Leaf cert: + * iSign and *Signing: usage = digitalSignature + * all others : don't care + * Others: usage = keyCertSign + * We only require that one bit to be set, we ignore others. + */ + if(isLeaf) { + switch(policy) { + case kTPiSign: + case kTP_SWUpdateSign: + case kTP_ResourceSign: + case kTP_CodeSigning: + case kTP_PackageSigning: + expUsage = CE_KU_DigitalSignature; + break; + case kCrlPolicy: + /* if present, this bit must be set */ + expUsage = CE_KU_CRLSign; + break; + default: + /* accept whatever's there */ + expUsage = thisCertInfo->keyUsage.extnData->keyUsage; + break; + } + } + else { + /* !leaf: this is true for all policies */ + expUsage = CE_KU_KeyCertSign; + } + actUsage = thisCertInfo->keyUsage.extnData->keyUsage; + if(!(actUsage & expUsage)) { + tpPolicyError("tp_policyVerify: bad keyUsage (leaf %s; " + "usage 0x%x)", + (certDex == 0) ? "TRUE" : "FALSE", actUsage); + if(thisTpCertInfo->addStatusCode(CSSMERR_APPLETP_INVALID_KEY_USAGE)) { + policyFail = CSSM_TRUE; + } + } + + #if 0 + /* + * Radar 3523221 renders this whole check obsolete, but I'm leaving + * the code here to document its conspicuous functional absence. + */ + if((policy == kTP_SMIME) && !thisCertInfo->keyUsage.critical) { + /* + * Per Radar 3410245, allow this for intermediate certs. + */ + if(SMIME_KEY_USAGE_MUST_BE_CRITICAL || isLeaf || isRoot) { + tpPolicyError("tp_policyVerify: key usage, !critical, SMIME"); + if(thisTpCertInfo->addStatusCode( + CSSMERR_APPLETP_SMIME_KEYUSAGE_NOT_CRITICAL)) { + policyFail = CSSM_TRUE; + } + } + } + #endif + } + else if(policy == kTPiSign) { + /* + * iSign requires keyUsage present for non root OR + * netscape-cert-type/ObjectSigning for leaf + */ + if(isLeaf && thisCertInfo->netscapeCertType.present) { + CE_NetscapeCertType ct = + thisCertInfo->netscapeCertType.extnData->netscapeCertType; + + if(!(ct & CE_NCT_ObjSign)) { + tpPolicyError("tp_policyVerify: netscape-cert-type, " + "!ObjectSign"); + if(thisTpCertInfo->addStatusCode(CSSMERR_APPLETP_INVALID_KEY_USAGE)) { + policyFail = CSSM_TRUE; + } + } + } + else if(!isRoot) { + tpPolicyError("tp_policyVerify: !isRoot, no keyUsage, " + "!(leaf and netscapeCertType)"); + if(thisTpCertInfo->addStatusCode(CSSMERR_APPLETP_INVALID_KEY_USAGE)) { + policyFail = CSSM_TRUE; + } + } + } + + /* + * RFC 3280, 4.1.2.6, says that an empty subject name can only appear in a + * leaf cert, and only if subjectAltName is present and marked critical. + */ + if(isLeaf && thisTpCertInfo->hasEmptySubjectName()) { + bool badEmptySubject = false; + if(actionFlags & CSSM_TP_ACTION_LEAF_IS_CA) { + /* + * True when evaluating a CA cert as well as when + * evaluating a CRL's cert chain. Note the odd case of a CRL's + * signer having an empty subject matching an empty issuer + * in the CRL. That'll be caught here. + */ + badEmptySubject = true; + } + else if(!thisCertInfo->subjectAltName.present || /* no subjectAltName */ + !thisCertInfo->subjectAltName.critical) { /* not critical */ + badEmptySubject = true; + } + if(badEmptySubject) { + tpPolicyError("tp_policyVerify: bad empty subject"); + if(thisTpCertInfo->addStatusCode(CSSMERR_APPLETP_INVALID_EMPTY_SUBJECT)) { + policyFail = CSSM_TRUE; + } + } + } + + /* + * RFC 3739: if this cert has a Qualified Cert Statements extension, and + * it's Critical, make sure we understand all of the extension's statementIds. + */ + if(thisCertInfo->qualCertStatements.present && + thisCertInfo->qualCertStatements.critical) { + CE_QC_Statements *qcss = + &thisCertInfo->qualCertStatements.extnData->qualifiedCertStatements; + uint32 numQcs = qcss->numQCStatements; + for(unsigned qdex=0; qdexqcStatements[qdex].statementId; + bool ok = false; + for(unsigned kdex=0; kdexaddStatusCode(CSSMERR_APPLETP_UNKNOWN_QUAL_CERT_STATEMENT)) { + policyFail = CSSM_TRUE; + break; + } + } + } + } /* critical Qualified Cert Statement */ + + /* + * Certificate Policies extension validation, per section 1.2 of: + * http://iase.disa.mil/pki/dod_cp_v10_final_2_mar_09_signed.pdf + */ + if (tpVerifyCPE(*thisCertInfo, CSSMOID_PIV_AUTH, false) || + tpVerifyCPE(*thisCertInfo, CSSMOID_PIV_AUTH_2048, false)) { + /* + * Certificate asserts one of the PIV-Auth Certificate Policy OIDs; + * check the required Key Usage extension for compliance. + * + * Leaf cert: + * usage = digitalSignature (only; no other bits asserted) + * Others: + * usage = keyCertSign (required; other bits ignored) + */ + if(thisCertInfo->keyUsage.present) { + actUsage = thisCertInfo->keyUsage.extnData->keyUsage; + } else { + /* No key usage! Policy fail. */ + actUsage = 0; + } + if(!(actionFlags & CSSM_TP_ACTION_LEAF_IS_CA) && (certDex == 0)) { + expUsage = CE_KU_DigitalSignature; + } else { + expUsage = actUsage | CE_KU_KeyCertSign; + } + if(!(actUsage == expUsage)) { + tpPolicyError("tp_policyVerify: bad keyUsage for PIV-Auth policy (leaf %s; " + "usage 0x%x)", + (certDex == 0) ? "TRUE" : "FALSE", actUsage); + if(thisTpCertInfo->addStatusCode(CSSMERR_APPLETP_INVALID_KEY_USAGE)) { + policyFail = CSSM_TRUE; + } + } + } /* Certificate Policies */ + + + } /* for certDex, checking presence of extensions */ + + /* + * Special case checking for leaf (end entity) cert + * + * iSign only: Extended key usage, optional for leaf, + * value CSSMOID_ExtendedUseCodeSigning + */ + if((policy == kTPiSign) && certInfo[0].extendKeyUsage.present) { + extendUsage = &certInfo[0].extendKeyUsage.extnData->extendedKeyUsage; + if(extendUsage->numPurposes != 1) { + tpPolicyError("tp_policyVerify: bad extendUsage->numPurposes " + "(%d)", + (int)extendUsage->numPurposes); + if((certGroup->certAtIndex(0))->addStatusCode( + CSSMERR_APPLETP_INVALID_EXTENDED_KEY_USAGE)) { + policyFail = CSSM_TRUE; + } + } + if(!tpCompareOids(extendUsage->purposes, + &CSSMOID_ExtendedUseCodeSigning)) { + tpPolicyError("tp_policyVerify: bad extendKeyUsage"); + if((certGroup->certAtIndex(0))->addStatusCode( + CSSMERR_APPLETP_INVALID_EXTENDED_KEY_USAGE)) { + policyFail = CSSM_TRUE; + } + } + } + + /* + * Verify authorityId-->subjectId linkage. + * All optional - skip if needed fields not present. + * Also, always skip last (root) cert. + */ + for(certDex=0; certDex<(numCerts-1); certDex++) { + if(!certInfo[certDex].authorityId.present || + !certInfo[certDex+1].subjectId.present) { + continue; + } + authorityId = &certInfo[certDex].authorityId.extnData->authorityKeyID; + if(!authorityId->keyIdentifierPresent) { + /* we only know how to compare keyIdentifier */ + continue; + } + if(!tpCompareCssmData(&authorityId->keyIdentifier, + &certInfo[certDex+1].subjectId.extnData->subjectKeyID)) { + tpPolicyError("tp_policyVerify: bad key ID linkage"); + if((certGroup->certAtIndex(certDex))->addStatusCode( + CSSMERR_APPLETP_INVALID_ID_LINKAGE)) { + policyFail = CSSM_TRUE; + } + } + } + + /* + * Check signature algorithm on all non-root certs, + * reject if known to be untrusted + */ + for(certDex=0; certDex<(numCerts-1); certDex++) { + if(certInfo[certDex].untrustedSigAlg) { + tpPolicyError("tp_policyVerify: untrusted signature algorithm"); + if((certGroup->certAtIndex(certDex))->addStatusCode( + CSSMERR_TP_INVALID_CERTIFICATE)) { + policyFail = CSSM_TRUE; + } + } + } + + /* specific per-policy checking */ + switch(policy) { + case kTP_SSL: + case kTP_EAP: + case kTP_IPSec: + /* + * SSL, EAP, IPSec: optionally verify common name; all are identical + * other than their names. + * 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]); + break; + + case kTP_iChat: + tpDebug("iChat policy"); + /* fall thru */ + case kTP_SMIME: + policyError = tp_verifySmimeOpts(policy, *certGroup, policyFieldData, + certInfo[0]); + break; + case kTP_SWUpdateSign: + policyError = tp_verifySWUpdateSigningOpts(*certGroup, policyFieldData, certInfo); + break; + case kTP_ResourceSign: + policyError = tp_verifyResourceSigningOpts(*certGroup, policyFieldData, certInfo); + break; + case kTP_CodeSigning: + case kTP_PackageSigning: + policyError = tp_verifyCodePkgSignOpts(policy, *certGroup, policyFieldData, certInfo); + break; + case kTP_MacAppStoreRec: + policyError = tp_verifyMacAppStoreReciptOpts(*certGroup, policyFieldData, certInfo); + break; + case kTP_AppleIDSharing: + policyError = tp_verifyAppleIDSharingOpts(*certGroup, policyFieldData, certInfo); + break; + case kTP_TimeStamping: + policyError = tp_verifyTimeStampingOpts(*certGroup, policyFieldData, certInfo); + break; + case kTPx509Basic: + case kTPiSign: + case kCrlPolicy: + case kTP_PKINIT_Client: + default: + break; + + } + + if(outErr == CSSM_OK) { + /* policy-specific error takes precedence here */ + if(policyError != CSSM_OK) { + outErr = policyError; + } + else if(policyFail) { + /* plain vanilla error return from this module */ + outErr = CSSMERR_TP_VERIFY_ACTION_FAILED; + } + } +errOut: + /* free resources */ + for(certDex=0; certDexData == NULL)) { + /* currently, no further action possible */ + return; + } + switch(policy) { + case kTP_SSL: + case kTP_EAP: + case kTP_IPSec: + { + if(policyData->Length != sizeof(CSSM_APPLE_TP_SSL_OPTIONS)) { + /* this error will be caught later */ + return; + } + CSSM_APPLE_TP_SSL_OPTIONS *sslOpts = + (CSSM_APPLE_TP_SSL_OPTIONS *)policyData->Data; + *policyStr = sslOpts->ServerName; + *policyStrLen = sslOpts->ServerNameLen; + if(sslOpts->Flags & CSSM_APPLE_TP_SSL_CLIENT) { + /* + * Client signs with its priv key. Server end, + * which (also) verifies the client cert, verifies. + */ + *keyUse = kSecTrustSettingsKeyUseSignature; + } + else { + /* server decrypts */ + *keyUse = kSecTrustSettingsKeyUseEnDecryptKey; + } + return; + } + + case kTP_iChat: + case kTP_SMIME: + { + if(policyData->Length != sizeof(CSSM_APPLE_TP_SMIME_OPTIONS)) { + /* this error will be caught later */ + return; + } + CSSM_APPLE_TP_SMIME_OPTIONS *smimeOpts = + (CSSM_APPLE_TP_SMIME_OPTIONS *)policyData->Data; + *policyStr = smimeOpts->SenderEmail; + *policyStrLen = smimeOpts->SenderEmailLen; + SecTrustSettingsKeyUsage ku = 0; + CE_KeyUsage smimeKu = smimeOpts->IntendedUsage; + if(smimeKu & (CE_KU_DigitalSignature | CE_KU_KeyCertSign | CE_KU_CRLSign)) { + ku |= kSecTrustSettingsKeyUseSignature; + } + if(smimeKu & (CE_KU_KeyEncipherment | CE_KU_DataEncipherment)) { + ku |= kSecTrustSettingsKeyUseEnDecryptKey; + } + *keyUse = ku; + return; + } + + default: + /* no other options */ + return; + } +} diff --git a/libsecurity_apple_x509_tp/lib/tpPolicies.h b/libsecurity_apple_x509_tp/lib/tpPolicies.h new file mode 100644 index 00000000..25fd2652 --- /dev/null +++ b/libsecurity_apple_x509_tp/lib/tpPolicies.h @@ -0,0 +1,88 @@ +/* + * 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'). + * 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. + */ + + +/* + tpPolicies.h - TP module policy implementation +*/ + +#ifndef _TP_POLICIES_H_ +#define _TP_POLICIES_H_ + +#include +#include +#include +#include "TPCertInfo.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* + * Enumerated certificate policies enforced by this module. + */ +typedef enum { + kTPDefault, /* no extension parsing, just sig and expiration */ + kTPx509Basic, /* basic X.509/RFC3280 */ + kTPiSign, /* (obsolete) Apple code signing */ + kTP_SSL, /* SecureTransport/SSL */ + kCrlPolicy, /* cert chain verification via CRL */ + kTP_SMIME, /* S/MIME */ + kTP_EAP, + kTP_SWUpdateSign, /* Apple SW Update signing (was Apple Code Signing) */ + kTP_ResourceSign, /* Apple Resource Signing */ + kTP_IPSec, /* IPSEC */ + kTP_iChat, /* iChat */ + kTP_PKINIT_Client, /* PKINIT client cert */ + kTP_PKINIT_Server, /* PKINIT server cert */ + kTP_CodeSigning, /* new Apple Code Signing (Leopard/10.5) */ + kTP_PackageSigning, /* Package Signing */ + kTP_MacAppStoreRec, /* MacApp store receipt */ + kTP_AppleIDSharing, /* AppleID Sharing */ + kTP_TimeStamping /* RFC3161 time stamping */ +} TPPolicy; + +/* + * Perform TP verification on a constructed (ordered) cert group. + */ +CSSM_RETURN tp_policyVerify( + TPPolicy policy, + Allocator &alloc, + CSSM_CL_HANDLE clHand, + CSSM_CSP_HANDLE cspHand, + TPCertGroup *certGroup, + CSSM_BOOL verifiedToRoot, // last cert is good root + CSSM_BOOL verifiedViaTrustSetting,// last cert has valid user trust + CSSM_APPLE_TP_ACTION_FLAGS actionFlags, + const CSSM_DATA *policyFieldData, // optional + void *policyControl); // future use + +/* + * Obtain policy-specific User Trust parameters + */ +void tp_policyTrustSettingParams( + TPPolicy policy, + const CSSM_DATA *policyFieldData, // optional + /* returned values - not mallocd */ + const char **policyStr, + uint32 *policyStrLen, + SecTrustSettingsKeyUsage *keyUse); + +#ifdef __cplusplus +} +#endif +#endif /* _TP_POLICIES_H_ */ diff --git a/libsecurity_apple_x509_tp/lib/tpTime.c b/libsecurity_apple_x509_tp/lib/tpTime.c new file mode 100644 index 00000000..2793e57d --- /dev/null +++ b/libsecurity_apple_x509_tp/lib/tpTime.c @@ -0,0 +1,365 @@ +/* + * 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. + */ + + +/* + * tpTime.c - cert related time functions + * + * Written 10/10/2000 by Doug Mitchell. + */ + +#include "tpTime.h" +#include +#include +#include +#include +#include + +/* + * Given a string containing either a UTC-style or "generalized time" + * time string, convert to a CFDateRef. Returns nonzero on + * error. + */ +int timeStringToCfDate( + const char *str, + unsigned len, + CFDateRef *cfDate) +{ + char szTemp[5]; + bool isUtc = false; // 2-digit year + bool isLocal = false; // trailing timezone offset + bool isCssmTime = false; // no trailing 'Z' + bool noSeconds = false; + unsigned x; + unsigned i; + char *cp; + CFGregorianDate gd; + CFTimeZoneRef timeZone; + CFTimeInterval gmtOff = 0; + + if((str == NULL) || (len == 0) || (cfDate == NULL)) { + return 1; + } + + /* tolerate NULL terminated or not */ + if(str[len - 1] == '\0') { + len--; + } + switch(len) { + case UTC_TIME_NOSEC_LEN: // 2-digit year, no seconds, not y2K compliant + isUtc = true; + noSeconds = true; + break; + case UTC_TIME_STRLEN: // 2-digit year, not Y2K compliant + isUtc = true; + break; + case CSSM_TIME_STRLEN: + isCssmTime = true; + break; + case GENERALIZED_TIME_STRLEN: // 4-digit year + break; + case LOCALIZED_UTC_TIME_STRLEN: // "YYMMDDhhmmssThhmm" (where T=[+,-]) + isUtc = 1; + // deliberate fallthrough + case LOCALIZED_TIME_STRLEN: // "YYYYMMDDhhmmssThhmm" (where T=[+,-]) + isLocal = 1; + break; + default: // unknown format + return 1; + } + + cp = (char *)str; + + /* check that all characters except last (or timezone indicator, if localized) are digits */ + for(i=0; i<(len - 1); i++) { + if ( !(isdigit(cp[i])) ) + if ( !isLocal || !(cp[i]=='+' || cp[i]=='-') ) + return 1; + } + + /* check last character is a 'Z' or digit as appropriate */ + if(isCssmTime || isLocal) { + if(!isdigit(cp[len - 1])) { + return 1; + } + } + else { + 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 + * ...though we allow this as of 10/10/02...dmitch + * 70 < year <= 99 : assume century 20 + */ + if(x < 50) { + x += 2000; + } + /* + else if(x < 70) { + return 1; + } + */ + else { + /* century 20 */ + x += 1900; + } + } + gd.year = x; + + /* 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; + } + gd.month = x; + + /* 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; + } + gd.day = x; + + /* HOUR */ + szTemp[0] = *cp++; + szTemp[1] = *cp++; + szTemp[2] = '\0'; + x = atoi( szTemp ); + if((x > 23) || (x < 0)) { + return 1; + } + gd.hour = x; + + /* MINUTE */ + szTemp[0] = *cp++; + szTemp[1] = *cp++; + szTemp[2] = '\0'; + x = atoi( szTemp ); + if((x > 59) || (x < 0)) { + return 1; + } + gd.minute = x; + + /* SECOND */ + if(noSeconds) { + gd.second = 0; + } + else { + szTemp[0] = *cp++; + szTemp[1] = *cp++; + szTemp[2] = '\0'; + x = atoi( szTemp ); + if((x > 59) || (x < 0)) { + return 1; + } + gd.second = x; + } + + if (isLocal) { + /* ZONE INDICATOR */ + switch(*cp++) { + case '+': + gmtOff = 1; + break; + case '-': + gmtOff = -1; + break; + default: + return 1; + } + /* ZONE HH OFFSET */ + szTemp[0] = *cp++; + szTemp[1] = *cp++; + szTemp[2] = '\0'; + x = atoi( szTemp ) * 60 * 60; + gmtOff *= x; + /* ZONE MM OFFSET */ + szTemp[0] = *cp++; + szTemp[1] = *cp++; + szTemp[2] = '\0'; + x = atoi( szTemp ) * 60; + if(gmtOff < 0) { + gmtOff -= x; + } + else { + gmtOff += x; + } + } + timeZone = CFTimeZoneCreateWithTimeIntervalFromGMT(NULL, gmtOff); + if (!timeZone) { + return 1; + } + *cfDate = CFDateCreate(NULL, CFGregorianDateGetAbsoluteTime(gd, timeZone)); + CFRelease(timeZone); + return 0; +} + +/* + * Compare two times. Assumes they're both in GMT. Returns: + * -1 if t1 < t2 + * 0 if t1 == t2 + * 1 if t1 > t2 + */ +int compareTimes( + CFDateRef t1, + CFDateRef t2) +{ + switch(CFDateCompare(t1, t2, NULL)) { + case kCFCompareLessThan: + return -1; + case kCFCompareEqualTo: + return 0; + case kCFCompareGreaterThan: + return 1; + } + /* NOT REACHED */ + assert(0); + return 0; +} + +/* + * Create a time string, in either UTC (2-digit) or or Generalized (4-digit) + * year format. Caller mallocs the output string whose length is at least + * (UTC_TIME_STRLEN+1), (GENERALIZED_TIME_STRLEN+1), or (CSSM_TIME_STRLEN+1) + * respectively. Caller must hold tpTimeLock. + */ +void timeAtNowPlus(unsigned secFromNow, + TpTimeSpec timeSpec, + char *outStr) +{ + struct tm utc; + time_t baseTime; + + baseTime = time(NULL); + baseTime += (time_t)secFromNow; + utc = *gmtime(&baseTime); + + switch(timeSpec) { + 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; + } +} + +/* + * Convert a time string, which can be in any of three forms (UTC, + * generalized, or CSSM_TIMESTRING) into a CSSM_TIMESTRING. Caller + * mallocs the result, which must be at least (CSSM_TIME_STRLEN+1) bytes. + * Returns nonzero if incoming time string is badly formed. + */ +int tpTimeToCssmTimestring( + const char *inStr, // not necessarily NULL terminated + unsigned inStrLen, // not including possible NULL + char *outTime) +{ + if((inStrLen == 0) || (inStr == NULL)) { + return 1; + } + outTime[0] = '\0'; + switch(inStrLen) { + 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(outTime, "20"); + } + else if(year < 70) { + return 1; + } + else { + /* century 20 */ + strcpy(outTime, "19"); + } + memmove(outTime + 2, inStr, inStrLen - 1); // don't copy the Z + break; + } + case CSSM_TIME_STRLEN: + memmove(outTime, inStr, inStrLen); // trivial case + break; + case GENERALIZED_TIME_STRLEN: + memmove(outTime, inStr, inStrLen - 1); // don't copy the Z + break; + + default: + return 1; + } + outTime[CSSM_TIME_STRLEN] = '\0'; + return 0; +} + + diff --git a/libsecurity_apple_x509_tp/lib/tpTime.h b/libsecurity_apple_x509_tp/lib/tpTime.h new file mode 100644 index 00000000..82d109fa --- /dev/null +++ b/libsecurity_apple_x509_tp/lib/tpTime.h @@ -0,0 +1,95 @@ +/* + * 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. + */ + + +/* + * tpTime.h - cert related time functions + * + * Written 10/10/2000 by Doug Mitchell. + */ + +#ifndef _TP_TIME_H_ +#define _TP_TIME_H_ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* lengths of time strings without trailing NULL */ +#define UTC_TIME_NOSEC_LEN 11 +#define UTC_TIME_STRLEN 13 +#define CSSM_TIME_STRLEN 14 /* no trailing 'Z' */ +#define GENERALIZED_TIME_STRLEN 15 +#define LOCALIZED_UTC_TIME_STRLEN 17 +#define LOCALIZED_TIME_STRLEN 19 + +/* + * Given a string containing either a UTC-style or "generalized time" + * time string, convert to a CFDateRef. Returns nonzero on + * error. + */ +extern int timeStringToCfDate( + const char *str, + unsigned len, + CFDateRef *cfDate); + +/* + * Compare two times. Assumes they're both in GMT. Returns: + * -1 if t1 < t2 + * 0 if t1 == t2 + * 1 if t1 > t2 + */ +extern int compareTimes( + CFDateRef t1, + CFDateRef t2); + +/* + * Create a time string, in either UTC (2-digit) or or Generalized (4-digit) + * year format. Caller mallocs the output string whose length is at least + * (UTC_TIME_STRLEN+1), (GENERALIZED_TIME_STRLEN+1), or (CSSM_TIME_STRLEN+1) + * respectively. Caller must hold tpTimeLock. + */ +typedef enum { + TIME_UTC, + TIME_GEN, + TIME_CSSM +} TpTimeSpec; + +void timeAtNowPlus(unsigned secFromNow, + TpTimeSpec timeSpec, + char *outStr); + +/* + * Convert a time string, which can be in any of three forms (UTC, + * generalized, or CSSM_TIMESTRING) into a CSSM_TIMESTRING. Caller + * mallocs the result, which must be at least (CSSM_TIME_STRLEN+1) bytes. + * Returns nonzero if incoming time string is badly formed. + */ +int tpTimeToCssmTimestring( + const char *inStr, // not necessarily NULL terminated + unsigned inStrLen, // not including possible NULL + char *outTime); // caller mallocs + +#ifdef __cplusplus +} +#endif + +#endif /* _TP_TIME_H_*/ diff --git a/libsecurity_apple_x509_tp/lib/tpdebugging.h b/libsecurity_apple_x509_tp/lib/tpdebugging.h new file mode 100644 index 00000000..681dd811 --- /dev/null +++ b/libsecurity_apple_x509_tp/lib/tpdebugging.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2000-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 _TPDEBUGGING_H_ +#define _TPDEBUGGING_H_ + +#include + +/* If TP_USE_SYSLOG is defined and not 0, use syslog() for debug + * logging in addition to invoking the secdebug macro (which, as of + * Snow Leopard, emits a static dtrace probe instead of an actual + * log message.) + */ +#ifndef TP_USE_SYSLOG +#define TP_USE_SYSLOG 0 +#endif + +#if TP_USE_SYSLOG +#include +#define tp_secdebug(scope, format...) \ +{ \ + syslog(LOG_NOTICE, format); \ + secdebug(scope, format); \ +} +#else +#define tp_secdebug(scope, format...) \ + secdebug(scope, format) +#endif + +#ifdef NDEBUG +/* this actually compiles to nothing */ +#define tpErrorLog(args...) tp_secdebug("tpError", ## args) +#else +#define tpErrorLog(args...) printf(args) +#endif + +#define tpDebug(args...) tp_secdebug("tpDebug", ## args) +#define tpDbDebug(args...) tp_secdebug("tpDbDebug", ## args) +#define tpCrlDebug(args...) tp_secdebug("tpCrlDebug", ## args) +#define tpPolicyError(args...) tp_secdebug("tpPolicy", ## args) +#define tpVfyDebug(args...) tp_secdebug("tpVfyDebug", ## args) +#define tpAnchorDebug(args...) tp_secdebug("tpAnchorDebug", ## args) +#define tpOcspDebug(args...) tp_secdebug("tpOcsp", ## args) +#define tpOcspCacheDebug(args...) tp_secdebug("tpOcspCache", ## args) +#define tpTrustSettingsDbg(args...) tp_secdebug("tpTrustSettings", ## args) + +#endif /* _TPDEBUGGING_H_ */ diff --git a/libsecurity_apple_x509_tp/libsecurity_apple_x509_tp.xcodeproj/project.pbxproj b/libsecurity_apple_x509_tp/libsecurity_apple_x509_tp.xcodeproj/project.pbxproj new file mode 100644 index 00000000..56d1dd5c --- /dev/null +++ b/libsecurity_apple_x509_tp/libsecurity_apple_x509_tp.xcodeproj/project.pbxproj @@ -0,0 +1,393 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 0544C53506A8718D00F54E48 /* ocspRequest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0544C52D06A8718D00F54E48 /* ocspRequest.cpp */; }; + 0544C53606A8718D00F54E48 /* ocspRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = 0544C52E06A8718D00F54E48 /* ocspRequest.h */; }; + 0544C53706A8718D00F54E48 /* tpOcspCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0544C52F06A8718D00F54E48 /* tpOcspCache.cpp */; }; + 0544C53806A8718D00F54E48 /* tpOcspCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 0544C53006A8718D00F54E48 /* tpOcspCache.h */; }; + 0544C53906A8718D00F54E48 /* tpOcspCertVfy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0544C53106A8718D00F54E48 /* tpOcspCertVfy.cpp */; }; + 0544C53A06A8718D00F54E48 /* tpOcspCertVfy.h in Headers */ = {isa = PBXBuildFile; fileRef = 0544C53206A8718D00F54E48 /* tpOcspCertVfy.h */; }; + 0544C53B06A8718D00F54E48 /* tpOcspVerify.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0544C53306A8718D00F54E48 /* tpOcspVerify.cpp */; }; + 0544C53C06A8718D00F54E48 /* tpOcspVerify.h in Headers */ = {isa = PBXBuildFile; fileRef = 0544C53406A8718D00F54E48 /* tpOcspVerify.h */; }; + BE4866E211A21E3C00361B64 /* cuEnc64.c in Sources */ = {isa = PBXBuildFile; fileRef = BE4866E011A21E3C00361B64 /* cuEnc64.c */; }; + BE4866E311A21E3C00361B64 /* cuEnc64.h in Headers */ = {isa = PBXBuildFile; fileRef = BE4866E111A21E3C00361B64 /* cuEnc64.h */; }; + C2196B77053B5A2B005808D4 /* AppleX509TPBuiltin.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2196B76053B5A2B005808D4 /* AppleX509TPBuiltin.cpp */; }; + C2B5C4F00534C6AA00AF53F5 /* AppleTP.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2B5C4D40534C6AA00AF53F5 /* AppleTP.cpp */; }; + C2B5C4F10534C6AA00AF53F5 /* AppleTP.h in Headers */ = {isa = PBXBuildFile; fileRef = C2B5C4D50534C6AA00AF53F5 /* AppleTP.h */; }; + C2B5C4F20534C6AA00AF53F5 /* AppleTPSession.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2B5C4D60534C6AA00AF53F5 /* AppleTPSession.cpp */; }; + C2B5C4F30534C6AA00AF53F5 /* AppleTPSession.h in Headers */ = {isa = PBXBuildFile; fileRef = C2B5C4D70534C6AA00AF53F5 /* AppleTPSession.h */; }; + C2B5C4F50534C6AA00AF53F5 /* certGroupUtils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2B5C4D90534C6AA00AF53F5 /* certGroupUtils.cpp */; }; + C2B5C4F60534C6AA00AF53F5 /* certGroupUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = C2B5C4DA0534C6AA00AF53F5 /* certGroupUtils.h */; }; + C2B5C4FB0534C6AA00AF53F5 /* tpCertGroup.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2B5C4DF0534C6AA00AF53F5 /* tpCertGroup.cpp */; }; + C2B5C4FC0534C6AA00AF53F5 /* TPCertInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2B5C4E00534C6AA00AF53F5 /* TPCertInfo.cpp */; }; + C2B5C4FD0534C6AA00AF53F5 /* TPCertInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = C2B5C4E10534C6AA00AF53F5 /* TPCertInfo.h */; }; + C2B5C4FE0534C6AA00AF53F5 /* tpCredRequest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2B5C4E20534C6AA00AF53F5 /* tpCredRequest.cpp */; }; + C2B5C4FF0534C6AA00AF53F5 /* TPCrlInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2B5C4E30534C6AA00AF53F5 /* TPCrlInfo.cpp */; }; + C2B5C5000534C6AA00AF53F5 /* TPCrlInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = C2B5C4E40534C6AA00AF53F5 /* TPCrlInfo.h */; }; + C2B5C5010534C6AA00AF53F5 /* tpCrlVerify.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2B5C4E50534C6AA00AF53F5 /* tpCrlVerify.cpp */; }; + C2B5C5020534C6AA00AF53F5 /* tpCrlVerify.h in Headers */ = {isa = PBXBuildFile; fileRef = C2B5C4E60534C6AA00AF53F5 /* tpCrlVerify.h */; }; + C2B5C5030534C6AA00AF53F5 /* TPDatabase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2B5C4E70534C6AA00AF53F5 /* TPDatabase.cpp */; }; + C2B5C5040534C6AA00AF53F5 /* TPDatabase.h in Headers */ = {isa = PBXBuildFile; fileRef = C2B5C4E80534C6AA00AF53F5 /* TPDatabase.h */; }; + C2B5C5050534C6AA00AF53F5 /* tpdebugging.h in Headers */ = {isa = PBXBuildFile; fileRef = C2B5C4E90534C6AA00AF53F5 /* tpdebugging.h */; }; + C2B5C5060534C6AA00AF53F5 /* TPNetwork.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2B5C4EA0534C6AA00AF53F5 /* TPNetwork.cpp */; }; + C2B5C5070534C6AA00AF53F5 /* TPNetwork.h in Headers */ = {isa = PBXBuildFile; fileRef = C2B5C4EB0534C6AA00AF53F5 /* TPNetwork.h */; }; + C2B5C5080534C6AA00AF53F5 /* tpPolicies.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2B5C4EC0534C6AA00AF53F5 /* tpPolicies.cpp */; }; + C2B5C5090534C6AA00AF53F5 /* tpPolicies.h in Headers */ = {isa = PBXBuildFile; fileRef = C2B5C4ED0534C6AA00AF53F5 /* tpPolicies.h */; }; + C2B5C50A0534C6AA00AF53F5 /* tpTime.c in Sources */ = {isa = PBXBuildFile; fileRef = C2B5C4EE0534C6AA00AF53F5 /* tpTime.c */; }; + C2B5C50B0534C6AA00AF53F5 /* tpTime.h in Headers */ = {isa = PBXBuildFile; fileRef = C2B5C4EF0534C6AA00AF53F5 /* tpTime.h */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 182BB354146F1117000BF1F3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1844611E146E86A900B12992 /* libsecurity_cdsa_plugin.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = C2C38A530535EDE600D7421F; + remoteInfo = libsecurity_cdsa_plugin_generate; + }; + 18446123146E86A900B12992 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1844611E146E86A900B12992 /* libsecurity_cdsa_plugin.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 4CA1FEBE052A3C8100F22E42; + remoteInfo = libsecurity_cdsa_plugin; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 0544C52D06A8718D00F54E48 /* ocspRequest.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ocspRequest.cpp; sourceTree = ""; }; + 0544C52E06A8718D00F54E48 /* ocspRequest.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ocspRequest.h; sourceTree = ""; }; + 0544C52F06A8718D00F54E48 /* tpOcspCache.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = tpOcspCache.cpp; sourceTree = ""; }; + 0544C53006A8718D00F54E48 /* tpOcspCache.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = tpOcspCache.h; sourceTree = ""; }; + 0544C53106A8718D00F54E48 /* tpOcspCertVfy.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = tpOcspCertVfy.cpp; sourceTree = ""; }; + 0544C53206A8718D00F54E48 /* tpOcspCertVfy.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = tpOcspCertVfy.h; sourceTree = ""; }; + 0544C53306A8718D00F54E48 /* tpOcspVerify.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = tpOcspVerify.cpp; sourceTree = ""; }; + 0544C53406A8718D00F54E48 /* tpOcspVerify.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = tpOcspVerify.h; sourceTree = ""; }; + 1844611A146E85EA00B12992 /* base.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = base.xcconfig; sourceTree = ""; }; + 1844611B146E85EA00B12992 /* debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = debug.xcconfig; sourceTree = ""; }; + 1844611C146E85EA00B12992 /* lib.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = lib.xcconfig; sourceTree = ""; }; + 1844611D146E85EA00B12992 /* release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = release.xcconfig; sourceTree = ""; }; + 1844611E146E86A900B12992 /* libsecurity_cdsa_plugin.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libsecurity_cdsa_plugin.xcodeproj; path = ../libsecurity_cdsa_plugin/libsecurity_cdsa_plugin.xcodeproj; sourceTree = ""; }; + 4094B069057EA5B000B44BCC /* tp_common.mdsinfo */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.xml; path = tp_common.mdsinfo; sourceTree = ""; }; + 4094B06A057EA5B000B44BCC /* tp_policyOids.mdsinfo */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.xml; path = tp_policyOids.mdsinfo; sourceTree = ""; }; + 4094B06B057EA5B000B44BCC /* tp_primary.mdsinfo */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.xml; path = tp_primary.mdsinfo; sourceTree = ""; }; + 4CA1FEBE052A3C8100F22E42 /* libsecurity_apple_x509_tp.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libsecurity_apple_x509_tp.a; sourceTree = BUILT_PRODUCTS_DIR; }; + BE4866E011A21E3C00361B64 /* cuEnc64.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cuEnc64.c; sourceTree = ""; }; + BE4866E111A21E3C00361B64 /* cuEnc64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cuEnc64.h; sourceTree = ""; }; + C2196B76053B5A2B005808D4 /* AppleX509TPBuiltin.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = AppleX509TPBuiltin.cpp; path = lib/AppleX509TPBuiltin.cpp; sourceTree = ""; }; + C2B5C4D40534C6AA00AF53F5 /* AppleTP.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = AppleTP.cpp; sourceTree = ""; }; + C2B5C4D50534C6AA00AF53F5 /* AppleTP.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = AppleTP.h; sourceTree = ""; }; + C2B5C4D60534C6AA00AF53F5 /* AppleTPSession.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = AppleTPSession.cpp; sourceTree = ""; }; + C2B5C4D70534C6AA00AF53F5 /* AppleTPSession.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = AppleTPSession.h; sourceTree = ""; }; + C2B5C4D80534C6AA00AF53F5 /* AppleX509TPPlugin.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = AppleX509TPPlugin.cpp; sourceTree = ""; }; + C2B5C4D90534C6AA00AF53F5 /* certGroupUtils.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = certGroupUtils.cpp; sourceTree = ""; }; + C2B5C4DA0534C6AA00AF53F5 /* certGroupUtils.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = certGroupUtils.h; sourceTree = ""; }; + C2B5C4DF0534C6AA00AF53F5 /* tpCertGroup.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = tpCertGroup.cpp; sourceTree = ""; }; + C2B5C4E00534C6AA00AF53F5 /* TPCertInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = TPCertInfo.cpp; sourceTree = ""; }; + C2B5C4E10534C6AA00AF53F5 /* TPCertInfo.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = TPCertInfo.h; sourceTree = ""; }; + C2B5C4E20534C6AA00AF53F5 /* tpCredRequest.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = tpCredRequest.cpp; sourceTree = ""; }; + C2B5C4E30534C6AA00AF53F5 /* TPCrlInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = TPCrlInfo.cpp; sourceTree = ""; }; + C2B5C4E40534C6AA00AF53F5 /* TPCrlInfo.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = TPCrlInfo.h; sourceTree = ""; }; + C2B5C4E50534C6AA00AF53F5 /* tpCrlVerify.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = tpCrlVerify.cpp; sourceTree = ""; }; + C2B5C4E60534C6AA00AF53F5 /* tpCrlVerify.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = tpCrlVerify.h; sourceTree = ""; }; + C2B5C4E70534C6AA00AF53F5 /* TPDatabase.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = TPDatabase.cpp; sourceTree = ""; }; + C2B5C4E80534C6AA00AF53F5 /* TPDatabase.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = TPDatabase.h; sourceTree = ""; }; + C2B5C4E90534C6AA00AF53F5 /* tpdebugging.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = tpdebugging.h; sourceTree = ""; }; + C2B5C4EA0534C6AA00AF53F5 /* TPNetwork.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = TPNetwork.cpp; sourceTree = ""; }; + C2B5C4EB0534C6AA00AF53F5 /* TPNetwork.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = TPNetwork.h; sourceTree = ""; }; + C2B5C4EC0534C6AA00AF53F5 /* tpPolicies.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = tpPolicies.cpp; sourceTree = ""; }; + C2B5C4ED0534C6AA00AF53F5 /* tpPolicies.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = tpPolicies.h; sourceTree = ""; }; + C2B5C4EE0534C6AA00AF53F5 /* tpTime.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = tpTime.c; sourceTree = ""; }; + C2B5C4EF0534C6AA00AF53F5 /* tpTime.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = tpTime.h; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 4CA1FEBB052A3C8100F22E42 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 18446119146E85EA00B12992 /* config */ = { + isa = PBXGroup; + children = ( + 1844611A146E85EA00B12992 /* base.xcconfig */, + 1844611B146E85EA00B12992 /* debug.xcconfig */, + 1844611C146E85EA00B12992 /* lib.xcconfig */, + 1844611D146E85EA00B12992 /* release.xcconfig */, + ); + name = config; + path = ../config; + sourceTree = ""; + }; + 1844611F146E86A900B12992 /* Products */ = { + isa = PBXGroup; + children = ( + 18446124146E86A900B12992 /* libsecurity_cdsa_plugin.a */, + ); + name = Products; + sourceTree = ""; + }; + 4094B068057EA5B000B44BCC /* mds */ = { + isa = PBXGroup; + children = ( + 4094B069057EA5B000B44BCC /* tp_common.mdsinfo */, + 4094B06A057EA5B000B44BCC /* tp_policyOids.mdsinfo */, + 4094B06B057EA5B000B44BCC /* tp_primary.mdsinfo */, + ); + path = mds; + sourceTree = ""; + }; + 4CA1FEA7052A3C3800F22E42 = { + isa = PBXGroup; + children = ( + 1844611E146E86A900B12992 /* libsecurity_cdsa_plugin.xcodeproj */, + C2B5C4D30534C6AA00AF53F5 /* lib */, + 18446119146E85EA00B12992 /* config */, + 4094B068057EA5B000B44BCC /* mds */, + 4CA1FEBF052A3C8100F22E42 /* Products */, + C2196B76053B5A2B005808D4 /* AppleX509TPBuiltin.cpp */, + ); + sourceTree = ""; + }; + 4CA1FEBF052A3C8100F22E42 /* Products */ = { + isa = PBXGroup; + children = ( + 4CA1FEBE052A3C8100F22E42 /* libsecurity_apple_x509_tp.a */, + ); + name = Products; + sourceTree = ""; + }; + C2B5C4D30534C6AA00AF53F5 /* lib */ = { + isa = PBXGroup; + children = ( + C2B5C4D40534C6AA00AF53F5 /* AppleTP.cpp */, + C2B5C4D50534C6AA00AF53F5 /* AppleTP.h */, + C2B5C4D60534C6AA00AF53F5 /* AppleTPSession.cpp */, + C2B5C4D70534C6AA00AF53F5 /* AppleTPSession.h */, + C2B5C4D80534C6AA00AF53F5 /* AppleX509TPPlugin.cpp */, + C2B5C4D90534C6AA00AF53F5 /* certGroupUtils.cpp */, + C2B5C4DA0534C6AA00AF53F5 /* certGroupUtils.h */, + BE4866E011A21E3C00361B64 /* cuEnc64.c */, + BE4866E111A21E3C00361B64 /* cuEnc64.h */, + C2B5C4DF0534C6AA00AF53F5 /* tpCertGroup.cpp */, + C2B5C4E00534C6AA00AF53F5 /* TPCertInfo.cpp */, + C2B5C4E10534C6AA00AF53F5 /* TPCertInfo.h */, + C2B5C4E20534C6AA00AF53F5 /* tpCredRequest.cpp */, + C2B5C4E30534C6AA00AF53F5 /* TPCrlInfo.cpp */, + C2B5C4E40534C6AA00AF53F5 /* TPCrlInfo.h */, + C2B5C4E50534C6AA00AF53F5 /* tpCrlVerify.cpp */, + C2B5C4E60534C6AA00AF53F5 /* tpCrlVerify.h */, + C2B5C4E70534C6AA00AF53F5 /* TPDatabase.cpp */, + C2B5C4E80534C6AA00AF53F5 /* TPDatabase.h */, + C2B5C4E90534C6AA00AF53F5 /* tpdebugging.h */, + C2B5C4EA0534C6AA00AF53F5 /* TPNetwork.cpp */, + C2B5C4EB0534C6AA00AF53F5 /* TPNetwork.h */, + 0544C52D06A8718D00F54E48 /* ocspRequest.cpp */, + 0544C52E06A8718D00F54E48 /* ocspRequest.h */, + 0544C52F06A8718D00F54E48 /* tpOcspCache.cpp */, + 0544C53006A8718D00F54E48 /* tpOcspCache.h */, + 0544C53106A8718D00F54E48 /* tpOcspCertVfy.cpp */, + 0544C53206A8718D00F54E48 /* tpOcspCertVfy.h */, + 0544C53306A8718D00F54E48 /* tpOcspVerify.cpp */, + 0544C53406A8718D00F54E48 /* tpOcspVerify.h */, + C2B5C4EC0534C6AA00AF53F5 /* tpPolicies.cpp */, + C2B5C4ED0534C6AA00AF53F5 /* tpPolicies.h */, + C2B5C4EE0534C6AA00AF53F5 /* tpTime.c */, + C2B5C4EF0534C6AA00AF53F5 /* tpTime.h */, + ); + path = lib; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 4CA1FEB9052A3C8100F22E42 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + C2B5C4F10534C6AA00AF53F5 /* AppleTP.h in Headers */, + C2B5C4F30534C6AA00AF53F5 /* AppleTPSession.h in Headers */, + C2B5C4F60534C6AA00AF53F5 /* certGroupUtils.h in Headers */, + C2B5C4FD0534C6AA00AF53F5 /* TPCertInfo.h in Headers */, + C2B5C5000534C6AA00AF53F5 /* TPCrlInfo.h in Headers */, + C2B5C5020534C6AA00AF53F5 /* tpCrlVerify.h in Headers */, + C2B5C5040534C6AA00AF53F5 /* TPDatabase.h in Headers */, + C2B5C5050534C6AA00AF53F5 /* tpdebugging.h in Headers */, + C2B5C5070534C6AA00AF53F5 /* TPNetwork.h in Headers */, + C2B5C5090534C6AA00AF53F5 /* tpPolicies.h in Headers */, + C2B5C50B0534C6AA00AF53F5 /* tpTime.h in Headers */, + 0544C53606A8718D00F54E48 /* ocspRequest.h in Headers */, + 0544C53806A8718D00F54E48 /* tpOcspCache.h in Headers */, + 0544C53A06A8718D00F54E48 /* tpOcspCertVfy.h in Headers */, + 0544C53C06A8718D00F54E48 /* tpOcspVerify.h in Headers */, + BE4866E311A21E3C00361B64 /* cuEnc64.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 4CA1FEBD052A3C8100F22E42 /* libsecurity_apple_x509_tp */ = { + isa = PBXNativeTarget; + buildConfigurationList = C27AD2970987FCDD001272E0 /* Build configuration list for PBXNativeTarget "libsecurity_apple_x509_tp" */; + buildPhases = ( + 4CA1FEB9052A3C8100F22E42 /* Headers */, + 4CA1FEBA052A3C8100F22E42 /* Sources */, + 4CA1FEBB052A3C8100F22E42 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + 182BB355146F1117000BF1F3 /* PBXTargetDependency */, + ); + name = libsecurity_apple_x509_tp; + productInstallPath = /usr/local/lib; + productName = libsecurity_apple_x509_tp; + productReference = 4CA1FEBE052A3C8100F22E42 /* libsecurity_apple_x509_tp.a */; + productType = "com.apple.product-type.library.static"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 4CA1FEAB052A3C3800F22E42 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0420; + }; + buildConfigurationList = C27AD29B0987FCDD001272E0 /* Build configuration list for PBXProject "libsecurity_apple_x509_tp" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 1; + knownRegions = ( + English, + Japanese, + French, + German, + ); + mainGroup = 4CA1FEA7052A3C3800F22E42; + productRefGroup = 4CA1FEBF052A3C8100F22E42 /* Products */; + projectDirPath = ""; + projectReferences = ( + { + ProductGroup = 1844611F146E86A900B12992 /* Products */; + ProjectRef = 1844611E146E86A900B12992 /* libsecurity_cdsa_plugin.xcodeproj */; + }, + ); + projectRoot = ""; + targets = ( + 4CA1FEBD052A3C8100F22E42 /* libsecurity_apple_x509_tp */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXReferenceProxy section */ + 18446124146E86A900B12992 /* libsecurity_cdsa_plugin.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libsecurity_cdsa_plugin.a; + remoteRef = 18446123146E86A900B12992 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; +/* End PBXReferenceProxy section */ + +/* Begin PBXSourcesBuildPhase section */ + 4CA1FEBA052A3C8100F22E42 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + C2B5C4F00534C6AA00AF53F5 /* AppleTP.cpp in Sources */, + C2B5C4F20534C6AA00AF53F5 /* AppleTPSession.cpp in Sources */, + C2B5C4F50534C6AA00AF53F5 /* certGroupUtils.cpp in Sources */, + C2B5C4FB0534C6AA00AF53F5 /* tpCertGroup.cpp in Sources */, + C2B5C4FC0534C6AA00AF53F5 /* TPCertInfo.cpp in Sources */, + C2B5C4FE0534C6AA00AF53F5 /* tpCredRequest.cpp in Sources */, + C2B5C4FF0534C6AA00AF53F5 /* TPCrlInfo.cpp in Sources */, + C2B5C5010534C6AA00AF53F5 /* tpCrlVerify.cpp in Sources */, + C2B5C5030534C6AA00AF53F5 /* TPDatabase.cpp in Sources */, + C2B5C5060534C6AA00AF53F5 /* TPNetwork.cpp in Sources */, + C2B5C5080534C6AA00AF53F5 /* tpPolicies.cpp in Sources */, + C2B5C50A0534C6AA00AF53F5 /* tpTime.c in Sources */, + C2196B77053B5A2B005808D4 /* AppleX509TPBuiltin.cpp in Sources */, + 0544C53506A8718D00F54E48 /* ocspRequest.cpp in Sources */, + 0544C53706A8718D00F54E48 /* tpOcspCache.cpp in Sources */, + 0544C53906A8718D00F54E48 /* tpOcspCertVfy.cpp in Sources */, + 0544C53B06A8718D00F54E48 /* tpOcspVerify.cpp in Sources */, + BE4866E211A21E3C00361B64 /* cuEnc64.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 182BB355146F1117000BF1F3 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = libsecurity_cdsa_plugin_generate; + targetProxy = 182BB354146F1117000BF1F3 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + C27AD2980987FCDD001272E0 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1844611B146E85EA00B12992 /* debug.xcconfig */; + buildSettings = { + }; + name = Debug; + }; + C27AD29A0987FCDD001272E0 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1844611D146E85EA00B12992 /* release.xcconfig */; + buildSettings = { + }; + name = Release; + }; + C27AD29C0987FCDD001272E0 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1844611C146E85EA00B12992 /* lib.xcconfig */; + buildSettings = { + }; + name = Debug; + }; + C27AD29E0987FCDD001272E0 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1844611C146E85EA00B12992 /* lib.xcconfig */; + buildSettings = { + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + C27AD2970987FCDD001272E0 /* Build configuration list for PBXNativeTarget "libsecurity_apple_x509_tp" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C27AD2980987FCDD001272E0 /* Debug */, + C27AD29A0987FCDD001272E0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C27AD29B0987FCDD001272E0 /* Build configuration list for PBXProject "libsecurity_apple_x509_tp" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C27AD29C0987FCDD001272E0 /* Debug */, + C27AD29E0987FCDD001272E0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 4CA1FEAB052A3C3800F22E42 /* Project object */; +} diff --git a/libsecurity_apple_x509_tp/mds/tp_common.mdsinfo b/libsecurity_apple_x509_tp/mds/tp_common.mdsinfo new file mode 100644 index 00000000..8c56cb44 --- /dev/null +++ b/libsecurity_apple_x509_tp/mds/tp_common.mdsinfo @@ -0,0 +1,30 @@ + + + + + BuiltIn + + CDSAVersion + 2.0 + Desc + Apple built-in X509TP + DynamicFlag + + MdsFileDescription + Built-in X509TP Common info + MdsFileType + PluginCommon + ModuleID + {87191ca5-0fc9-11d4-849a-000502b52122} + ModuleName + AppleX509TP + MultiThreadFlag + + ProductVersion + 1.0 + ServiceMask + CSSM_SERVICE_TP + Path + *AppleX509TP + + diff --git a/libsecurity_apple_x509_tp/mds/tp_policyOids.mdsinfo b/libsecurity_apple_x509_tp/mds/tp_policyOids.mdsinfo new file mode 100644 index 00000000..6736f700 --- /dev/null +++ b/libsecurity_apple_x509_tp/mds/tp_policyOids.mdsinfo @@ -0,0 +1,46 @@ + + + + + MdsFileDescription + Built-in X509TP Policy OIDs + MdsFileType + PluginSpecific + MdsRecordType + MDS_CDSADIR_TP_OIDS_RECORDTYPE + ModuleID + {87191ca5-0fc9-11d4-849a-000502b52122} + Policies + + + OID + + KoZIhvdjZAEB + + Value + + + + + OID + + KoZIhvdjZAEC + + Value + + + + + OID + + KoZIhvdjZAED + + Value + + + + + SSID + 0 + + diff --git a/libsecurity_apple_x509_tp/mds/tp_primary.mdsinfo b/libsecurity_apple_x509_tp/mds/tp_primary.mdsinfo new file mode 100644 index 00000000..6a6846b7 --- /dev/null +++ b/libsecurity_apple_x509_tp/mds/tp_primary.mdsinfo @@ -0,0 +1,34 @@ + + + + + AclSubjectTypes + + CSSM_ACL_SUBJECT_TYPE_ANY + + AuthTags + + CSSM_ACL_AUTHORIZATION_ANY + + CertTypeFormat + <<CSSM_CERT_X_509v3 | CSSM_CERT_ENCODING_DER + MdsFileDescription + Built-in X509TP Primary info + MdsFileType + PluginSpecific + MdsRecordType + MDS_CDSADIR_TP_PRIMARY_RECORDTYPE + ModuleID + {87191ca5-0fc9-11d4-849a-000502b52122} + ModuleName + AppleX509TP + ProductVersion + 1.0 + SSID + 0 + SampleTypes + + Vendor + Apple Computer, Inc. + + diff --git a/libsecurity_asn1/APPLE_LICENSE b/libsecurity_asn1/APPLE_LICENSE new file mode 100644 index 00000000..71fe6fd7 --- /dev/null +++ b/libsecurity_asn1/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/libsecurity_asn1/CHANGES.Apple b/libsecurity_asn1/CHANGES.Apple new file mode 100644 index 00000000..c921ce61 --- /dev/null +++ b/libsecurity_asn1/CHANGES.Apple @@ -0,0 +1,58 @@ +Per the terms of the Mozilla Public License, version 1.1, this file contains +a summary of the changes made by Apple Computer ("Apple") to source code +originally developed by Netscape. + +General Notes +------------- + +1. This module, SecurityNssAsn1, is based on the Netscape Security + Services ("NSS") portion of the Mozilla Browser project. The + source upon which SecurityNssAsn1 was based was pulled from + the Mozilla CVS repository, top of tree as of January 21, 2003. + The SecurityNssAsn1 project contains only those portions of NSS + used to perform BER encoding and decoding, along with minimal + support required by the encode/decode routines. + +2. The directory structure of SecurityNssAsn1 differs significantly + from that of NSS, rendering simple diffs to document changes + unwieldy. Diffs could still be performed on a file-by-file basis. + +3. All Apple changes are flagged by the symbol __APPLE__, either + via "#ifdef __APPLE__" or in a comment. + + +Changes +------- + +1. Basic platform-specific support is in nsprPub/Source/nsprPortX.c. + This support is specific to Mac OS X. + +2. The fundamental data wrapper, SECItem, has been typedef'd to a + CSSM_DATA. This provides interoperability between the code in + this module with the code in the Apple Security framework. + +3. Indication of signed integer types has moved from the + source/destination of encoding/decoding (SecItem.type) to a flag + in the template defining encoding/decoding rules + (SEC_ASN1_SIGNED_INT in SEC_ASN1Template.kind). The default + for ASN1 integer types, when this flag is not set, is unsigned. + +4. The dynamic template resolution mechanism has been updated to + provide the template chooser routine specific access to the + SECItem being encoded to or decoded from. This faciliates + efficient inline processing of many ASN_ANY and CHOICE types. + +5. The source of the core secasn1e.c and secasn1d.c files has been + reformatted to be legible with 4-space tabs. Contrary to the + comments at the top of these files, these files were actually + formatted for 8-space tabs. + +6. Templates for encoding/decoding of fundamental ASN types was moved + from secasn1d.c to a new file, asn1Templates.c. All other + templates in the SecurityNssAsn1 source were written by Apple. + +7. Updated the prcpucfg.h file to nspr-4.8.9 version. + +8. Changed various integer types for variables and functions arguments + to be 64 bits safe. + diff --git a/libsecurity_asn1/Info-security_asn1.plist b/libsecurity_asn1/Info-security_asn1.plist new file mode 100644 index 00000000..0c67376e --- /dev/null +++ b/libsecurity_asn1/Info-security_asn1.plist @@ -0,0 +1,5 @@ + + + + + diff --git a/libsecurity_asn1/Makefile b/libsecurity_asn1/Makefile new file mode 100644 index 00000000..2c72a57a --- /dev/null +++ b/libsecurity_asn1/Makefile @@ -0,0 +1,101 @@ + +CONFIG ?= DEBUG_EMU +CFLAGS_DEBUG_ARM = -O0 -gdwarf-2 -arch armv6 +CFLAGS_RELEASE_ARM = -arch armv6 -Os -gdwarf-2 -Wuninitialized -DNDEBUG +CFLAGS_DEBUG_EMU = -O0 -gdwarf-2 -DDEBUG +CFLAGS_RELEASE_EMU = -gdwarf-2 -Os -Wuninitialized -DNDEBUG + +WFLAGS = -Wno-trigraphs -Werror -Wunused-function \ + -Wunused-label -Wunused-variable -Wunknown-pragmas \ + -Wmost -Wno-four-char-constants -Wno-unknown-pragmas \ + -Wmissing-prototypes + +CFLAGS = --std=c99 -pipe \ + -fpascal-strings -fasm-blocks -fmessage-length=0 \ + $(WFLAGS) $(CFLAGS_$(CONFIG)) + +LDFLAGS := -Wl,-dylib -Wl,-dead_strip -Wl,-exported_symbols_list lib/security_asn1.exp + + + +HEADER_PATHS := . .. ../libDER +CFLAGS += $(addprefix -I$(include),$(HEADER_PATHS)) + +SOURCES = \ + lib/oidsattr.c \ + lib/oidsalg.c \ + lib/SecAsn1Coder.c \ + lib/SecAsn1Templates.c \ + \ + lib/X509Templates.c \ + lib/certExtensionTemplates.c \ + lib/csrTemplates.c \ + lib/keyTemplates.c \ + lib/nameTemplates.c \ + lib/ocspTemplates.c \ + lib/osKeyTemplates.c \ + lib/pkcs12Templates.c \ + lib/pkcs7Templates.c \ + \ + lib/nsprPortX.c \ + lib/nssUtils.c \ + lib/plarena.c \ + lib/secErrorStr.c \ + \ + lib/secasn1d.c \ + lib/secasn1e.c \ + lib/secasn1u.c \ + lib/secport.c + +PUBLIC_HEADERS = \ + lib/SecAsn1Coder.h \ + lib/SecAsn1Templates.h \ + lib/SecAsn1Types.h \ + lib/oidsattr.h \ + lib/oidsalg.h \ + lib/oidsbase.h + +PRIVATE_HEADERS = \ + lib/secasn1t.h \ + lib/X509Templates.h \ + lib/asn1Templates.h \ + lib/certExtensionTemplates.h \ + lib/csrTemplates.h \ + lib/keyTemplates.h \ + lib/nameTemplates.h \ + lib/nssUtils.h \ + lib/nssilckt.h \ + lib/nssilock.h \ + lib/nsslocks.h \ + lib/ocspTemplates.h \ + lib/osKeyTemplates.h \ + lib/pkcs7Templates.h \ + lib/pkcs12Templates.h \ + lib/plarena.h \ + lib/prinit.h + +INTERNAL_HEADERS = lib/plarenas.h lib/plstr.h lib/prbit.h lib/prcpucfg.h lib/prcvar.h lib/prenv.h \ + lib/prerr.h lib/prerror.h lib/prinrval.h lib/prlock.h lib/prlog.h lib/prlong.h lib/prmem.h lib/prmon.h \ + lib/protypes.h lib/prthread.h lib/prtime.h lib/prtypes.h lib/prvrsion.h lib/secasn1.h lib/seccomon.h \ + lib/secerr.h lib/secport.h + +OBJECTS := $(SOURCES:.c=.o) + +all: install-headers build + +install-headers: $(PUBLIC_HEADERS) $(PRIVATE_HEADERS) $(INTERNAL_HEADERS) + @install -d Security + @install -d security_asn1 + @install -m 0444 $(PUBLIC_HEADERS) $(PRIVATE_HEADERS) Security + @install -m 0444 $(INTERNAL_HEADERS) security_asn1 + +build: $(OBJECTS) + $(CC) $(CFLAGS) $(LDFLAGS) -dynamiclib -dynamic -compatibility_version 0 -current_version 0 -install_name libasn1.dylib -o libasn1.dylib $(OBJECTS) + +clean: + @rm -f $(OBJECTS) $(PROGNAME) + +tags: $(SOURCES) $(PROG) + etags $+ + + diff --git a/libsecurity_asn1/MozillaPublicLicense1.1.html b/libsecurity_asn1/MozillaPublicLicense1.1.html new file mode 100644 index 00000000..cbd7e3f5 --- /dev/null +++ b/libsecurity_asn1/MozillaPublicLicense1.1.html @@ -0,0 +1,796 @@ + + + + + + + + + + + Mozilla Public License version 1.1 + + + + + + + +
MOZILLA PUBLIC LICENSE + +
Version 1.1 + +

+ +


+ + + +

1. Definitions. + +

    1.0.1. "Commercial Use" means distribution or otherwise making + +the Covered Code available to a third party. + +

    1.1. ''Contributor'' means each entity that creates or contributes + +to the creation of Modifications. + +

    1.2. ''Contributor Version'' means the combination of the Original + +Code, prior Modifications used by a Contributor, and the Modifications + +made by that particular Contributor. + +

    1.3. ''Covered Code'' means the Original Code or Modifications + +or the combination of the Original Code and Modifications, in each case + +including portions thereof. + +

    1.4. ''Electronic Distribution Mechanism'' means a mechanism + +generally accepted in the software development community for the electronic + +transfer of data. + +

    1.5. ''Executable'' means Covered Code in any form other than + +Source Code. + +

    1.6. ''Initial Developer'' means the individual or entity identified + +as the Initial Developer in the Source Code notice required by Exhibit + +A. + +

    1.7. ''Larger Work'' means a work which combines Covered Code + +or portions thereof with code not governed by the terms of this License. + +

    1.8. ''License'' means this document. + +

    1.8.1. "Licensable" means having the right to grant, to the maximum + +extent possible, whether at the time of the initial grant or subsequently + +acquired, any and all of the rights conveyed herein. + +

    1.9. ''Modifications'' means any addition to or deletion from + +the substance or structure of either the Original Code or any previous + +Modifications. When Covered Code is released as a series of files, a Modification + +is: + +

      A. Any addition to or deletion from the contents of a file containing + +Original Code or previous Modifications. + +

      B. Any new file that contains any part of the Original Code or + +previous Modifications. + +
       

    + +1.10. ''Original Code'' means Source Code of computer software code + +which is described in the Source Code notice required by Exhibit A + +as Original Code, and which, at the time of its release under this License + +is not already Covered Code governed by this License. + +

    1.10.1. "Patent Claims" means any patent claim(s), now owned + +or hereafter acquired, including without limitation,  method, process, + +and apparatus claims, in any patent Licensable by grantor. + +

    1.11. ''Source Code'' means the preferred form of the Covered + +Code 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, or source code differential + +comparisons against either the Original Code or another well known, available + +Covered Code of the Contributor's choice. The Source Code can be in a compressed + +or archival form, provided the appropriate decompression or de-archiving + +software is widely available for no charge. + +

    1.12. "You'' (or "Your")  means an individual or a legal + +entity exercising rights under, and complying with all of the terms of, + +this License or a future version of this License issued under Section 6.1. + +For legal entities, "You'' includes any entity which controls, is controlled + +by, or is under common control with You. For purposes of this definition, + +"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 more than fifty percent (50%) of the outstanding shares or + +beneficial ownership of such entity.

+ +2. Source Code License. + +
    2.1. The Initial Developer Grant. + +
    The Initial Developer hereby grants You a world-wide, royalty-free, + +non-exclusive license, subject to third party intellectual property claims: + +
      (a)  under intellectual property rights (other than + +patent or trademark) Licensable by Initial Developer to use, reproduce, + +modify, display, perform, sublicense and distribute the Original Code (or + +portions thereof) with or without Modifications, and/or as part of a Larger + +Work; and + +

      (b) under Patents Claims infringed by the making, using or selling + +of Original Code, to make, have made, use, practice, sell, and offer for + +sale, and/or otherwise dispose of the Original Code (or portions thereof). + +

        + +
           
        + +
      + +(c) the licenses granted in this Section 2.1(a) and (b) are effective + +on the date Initial Developer first distributes Original Code under the + +terms of this License. + +

      (d) Notwithstanding Section 2.1(b) above, no patent license is + +granted: 1) for code that You delete from the Original Code; 2) separate + +from the Original Code;  or 3) for infringements caused by: i) the + +modification of the Original Code or ii) the combination of the Original + +Code with other software or devices. + +
       

    + +2.2. Contributor Grant. + +
    Subject to third party intellectual property claims, each Contributor + +hereby grants You a world-wide, royalty-free, non-exclusive license + +
        + +
      (a)  under intellectual property rights (other than + +patent or trademark) Licensable by Contributor, to use, reproduce, modify, + +display, perform, sublicense and distribute the Modifications created by + +such Contributor (or portions thereof) either on an unmodified basis, with + +other Modifications, as Covered Code and/or as part of a Larger Work; and + +

      (b) under Patent Claims infringed by the making, using, or selling + +of  Modifications made by that Contributor either alone and/or in + +combination with its Contributor Version (or portions of such combination), + +to make, use, sell, offer for sale, have made, and/or otherwise dispose + +of: 1) Modifications made by that Contributor (or portions thereof); and + +2) the combination of  Modifications made by that Contributor with + +its Contributor Version (or portions of such combination). + +

      (c) the licenses granted in Sections 2.2(a) and 2.2(b) are effective + +on the date Contributor first makes Commercial Use of the Covered Code. + +

      (d)    Notwithstanding Section 2.2(b) above, no + +patent license is granted: 1) for any code that Contributor has deleted + +from the Contributor Version; 2)  separate from the Contributor Version;  + +3)  for infringements caused by: i) third party modifications of Contributor + +Version or ii)  the combination of Modifications made by that Contributor + +with other software  (except as part of the Contributor Version) or + +other devices; or 4) under Patent Claims infringed by Covered Code in the + +absence of Modifications made by that Contributor.

    + +
+ + + +


3. Distribution Obligations. + +

    3.1. Application of License. + +
    The Modifications which You create or to which You contribute are governed + +by the terms of this License, including without limitation Section 2.2. + +The Source Code version of Covered Code may be distributed only under the + +terms of this License or a future version of this License released under + +Section 6.1, and You must include a copy of this License with every + +copy of the Source Code You distribute. You may not offer or impose any + +terms on any Source Code version that alters or restricts the applicable + +version of this License or the recipients' rights hereunder. However, You + +may include an additional document offering the additional rights described + +in Section 3.5. + +

    3.2. Availability of Source Code. + +
    Any Modification which You create or to which You contribute must be + +made available in Source Code form under the terms of this License either + +on the same media as an Executable version or via an accepted Electronic + +Distribution Mechanism to anyone to whom you made an Executable version + +available; and if made available via Electronic Distribution Mechanism, + +must remain available for at least twelve (12) months after the date it + +initially became available, or at least six (6) months after a subsequent + +version of that particular Modification has been made available to such + +recipients. You are responsible for ensuring that the Source Code version + +remains available even if the Electronic Distribution Mechanism is maintained + +by a third party. + +

    3.3. Description of Modifications. + +
    You must cause all Covered Code to which You contribute to contain + +a file documenting the changes You made to create that Covered Code and + +the date of any change. You must include a prominent statement that the + +Modification is derived, directly or indirectly, from Original Code provided + +by the Initial Developer and including the name of the Initial Developer + +in (a) the Source Code, and (b) in any notice in an Executable version + +or related documentation in which You describe the origin or ownership + +of the Covered Code. + +

    3.4. Intellectual Property Matters + +

      (a) Third Party Claims. + +
      If Contributor has knowledge that a license under a third party's intellectual + +property rights is required to exercise the rights granted by such Contributor + +under Sections 2.1 or 2.2, Contributor must include a text file with the + +Source Code distribution titled "LEGAL'' which describes the claim and + +the party making the claim in sufficient detail that a recipient will know + +whom to contact. If Contributor obtains such knowledge after the Modification + +is made available as described in Section 3.2, Contributor shall promptly + +modify the LEGAL file in all copies Contributor makes available thereafter + +and shall take other steps (such as notifying appropriate mailing lists + +or newsgroups) reasonably calculated to inform those who received the Covered + +Code that new knowledge has been obtained. + +

      (b) Contributor APIs. + +
      If Contributor's Modifications include an application programming interface + +and Contributor has knowledge of patent licenses which are reasonably necessary + +to implement that API, Contributor must also include this information in + +the LEGAL file. + +
       

    + +          (c)    + +Representations. + +
      Contributor represents that, except as disclosed pursuant to Section + +3.4(a) above, Contributor believes that Contributor's Modifications are + +Contributor's original creation(s) and/or Contributor has sufficient rights + +to grant the rights conveyed by this License.
    + + + +


    3.5. Required Notices. + +
    You must duplicate the notice in Exhibit A in each file of the + +Source Code.  If it is not possible to put such notice in a particular + +Source Code file due to its structure, then You must include such notice + +in a location (such as a relevant directory) where a user would be likely + +to look for such a notice.  If You created one or more Modification(s) + +You may add your name as a Contributor to the notice described in Exhibit + +A.  You must also duplicate this License in any documentation + +for the Source Code where You describe recipients' rights or ownership + +rights relating to Covered Code.  You may choose to offer, and to + +charge a fee for, warranty, support, indemnity or liability obligations + +to one or more recipients of Covered Code. However, You may do so only + +on Your own behalf, and not on behalf of the Initial Developer or any Contributor. + +You must make it absolutely clear than any such warranty, support, indemnity + +or liability obligation is offered by You alone, and You hereby agree to + +indemnify the Initial Developer and every Contributor for any liability + +incurred by the Initial Developer or such Contributor as a result of warranty, + +support, indemnity or liability terms You offer. + +

    3.6. Distribution of Executable Versions. + +
    You may distribute Covered Code in Executable form only if the requirements + +of Section 3.1-3.5 have been met for that Covered Code, and if You + +include a notice stating that the Source Code version of the Covered Code + +is available under the terms of this License, including a description of + +how and where You have fulfilled the obligations of Section 3.2. + +The notice must be conspicuously included in any notice in an Executable + +version, related documentation or collateral in which You describe recipients' + +rights relating to the Covered Code. You may distribute the Executable + +version of Covered Code or ownership rights under a license of Your choice, + +which may contain terms different from this License, provided that You + +are in compliance with the terms of this License and that the license for + +the Executable version does not attempt to limit or alter the recipient's + +rights in the Source Code version from the rights set forth in this License. + +If You distribute the Executable version under a different license You + +must make it absolutely clear that any terms which differ from this License + +are offered by You alone, not by the Initial Developer or any Contributor. + +You hereby agree to indemnify the Initial Developer and every Contributor + +for any liability incurred by the Initial Developer or such Contributor + +as a result of any such terms You offer. + +

    3.7. 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 such a case, You must make sure the requirements + +of this License are fulfilled for the Covered Code.

+ +4. Inability to Comply Due to Statute or Regulation. + +
    If it is impossible for You to comply with any of the terms of this + +License with respect to some or all of the Covered Code due to statute, + +judicial order, or regulation then You must: (a) comply with the terms + +of this License to the maximum extent possible; and (b) describe the limitations + +and the code they affect. Such description must be included in the LEGAL + +file described in Section 3.4 and must be included with all distributions + +of the Source Code. Except to the extent prohibited by statute or regulation, + +such description must be sufficiently detailed for a recipient of ordinary + +skill to be able to understand it.
+ +5. Application of this License. + +
    This License applies to code to which the Initial Developer has attached + +the notice in Exhibit A and to related Covered Code.
+ +6. Versions of the License. + +
    6.1. New Versions. + +
    Netscape Communications Corporation (''Netscape'') may publish revised + +and/or new versions of the License from time to time. Each version will + +be given a distinguishing version number. + +

    6.2. Effect of New Versions. + +
    Once Covered Code has been published under a particular version of + +the License, You may always continue to use it under the terms of that + +version. You may also choose to use such Covered Code under the terms of + +any subsequent version of the License published by Netscape. No one other + +than Netscape has the right to modify the terms applicable to Covered Code + +created under this License. + +

    6.3. Derivative Works. + +
    If You create or use a modified version of this License (which you + +may only do in order to apply it to code which is not already Covered Code + +governed by this License), You must (a) rename Your license so that the + +phrases ''Mozilla'', ''MOZILLAPL'', ''MOZPL'', ''Netscape'', "MPL", ''NPL'' + +or any confusingly similar phrase do not appear in your license (except + +to note that your license differs from this License) and (b) otherwise + +make it clear that Your version of the license contains terms which differ + +from the Mozilla Public License and Netscape Public License. (Filling in + +the name of the Initial Developer, Original Code or Contributor in the + +notice described in Exhibit A shall not of themselves be deemed + +to be modifications of this License.)

+ +7. DISCLAIMER OF WARRANTY. + +
    COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS'' BASIS, WITHOUT + +WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, + +WARRANTIES THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT + +FOR A PARTICULAR PURPOSE OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY + +AND PERFORMANCE OF THE COVERED CODE IS WITH YOU. SHOULD ANY COVERED CODE + +PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER + +CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. + +THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. + +NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER.
+ +8. TERMINATION. + +
    8.1.  This License and the rights granted hereunder will + +terminate automatically if You fail to comply with terms herein and fail + +to cure such breach within 30 days of becoming aware of the breach. All + +sublicenses to the Covered Code which are properly granted shall survive + +any termination of this License. Provisions which, by their nature, must + +remain in effect beyond the termination of this License shall survive. + +

    8.2.  If You initiate litigation by asserting a patent infringement + +claim (excluding declatory judgment actions) against Initial Developer + +or a Contributor (the Initial Developer or Contributor against whom You + +file such action is referred to as "Participant")  alleging that: + +

    (a)  such Participant's Contributor Version directly or + +indirectly infringes any patent, then any and all rights granted by such + +Participant to You under Sections 2.1 and/or 2.2 of this License shall, + +upon 60 days notice from Participant terminate prospectively, unless if + +within 60 days after receipt of notice You either: (i)  agree in writing + +to pay Participant a mutually agreeable reasonable royalty for Your past + +and future use of Modifications made by such Participant, or (ii) withdraw + +Your litigation claim with respect to the Contributor Version against such + +Participant.  If within 60 days of notice, a reasonable royalty and + +payment arrangement are not mutually agreed upon in writing by the parties + +or the litigation claim is not withdrawn, the rights granted by Participant + +to You under Sections 2.1 and/or 2.2 automatically terminate at the expiration + +of the 60 day notice period specified above. + +

    (b)  any software, hardware, or device, other than such + +Participant's Contributor Version, directly or indirectly infringes any + +patent, then any rights granted to You by such Participant under Sections + +2.1(b) and 2.2(b) are revoked effective as of the date You first made, + +used, sold, distributed, or had made, Modifications made by that Participant. + +

    8.3.  If You assert a patent infringement claim against + +Participant alleging that such Participant's Contributor Version directly + +or indirectly infringes any patent where such claim is resolved (such as + +by license or settlement) prior to the initiation of patent infringement + +litigation, then the reasonable value of the licenses granted by such Participant + +under Sections 2.1 or 2.2 shall be taken into account in determining the + +amount or value of any payment or license. + +

    8.4.  In the event of termination under Sections 8.1 or + +8.2 above,  all end user license agreements (excluding distributors + +and resellers) which have been validly granted by You or any distributor + +hereunder prior to termination shall survive termination.

+ +9. LIMITATION OF LIABILITY. + +
    UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT (INCLUDING + +NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE INITIAL DEVELOPER, + +ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF COVERED CODE, OR ANY SUPPLIER + +OF ANY OF SUCH PARTIES, BE LIABLE TO ANY PERSON FOR ANY INDIRECT, SPECIAL, + +INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY CHARACTER INCLUDING, WITHOUT + +LIMITATION, DAMAGES FOR LOSS OF GOODWILL, WORK STOPPAGE, COMPUTER FAILURE + +OR MALFUNCTION, OR ANY AND ALL OTHER COMMERCIAL DAMAGES OR LOSSES, EVEN + +IF SUCH PARTY SHALL HAVE BEEN INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. + +THIS LIMITATION OF LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR + +PERSONAL INJURY RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT APPLICABLE + +LAW PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION + +OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THIS EXCLUSION + +AND LIMITATION MAY NOT APPLY TO YOU.
+ +10. U.S. GOVERNMENT END USERS. + +
    The Covered Code is a ''commercial item,'' as that term is defined + +in 48 C.F.R. 2.101 (Oct. 1995), consisting of ''commercial computer software'' + +and ''commercial computer software documentation,'' as such terms are used + +in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48 C.F.R. 12.212 and + +48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995), all U.S. Government + +End Users acquire Covered Code with only those rights set forth herein.
+ +11. MISCELLANEOUS. + +
    This License represents the complete agreement concerning subject matter + +hereof. If any provision of this License is held to be unenforceable, such + +provision shall be reformed only to the extent necessary to make it enforceable. + +This License shall be governed by California law provisions (except to + +the extent applicable law, if any, provides otherwise), excluding its conflict-of-law + +provisions. With respect to disputes in which at least one party is a citizen + +of, or an entity chartered or registered to do business in the United States + +of America, any litigation relating to this License shall be subject to + +the jurisdiction of the Federal Courts of the Northern District of California, + +with venue lying in Santa Clara County, California, with the losing party + +responsible for costs, including without limitation, court costs and reasonable + +attorneys' fees and expenses. The application of the United Nations Convention + +on Contracts for the International Sale of Goods is expressly excluded. + +Any law or regulation which provides that the language of a contract shall + +be construed against the drafter shall not apply to this License.
+ +12. RESPONSIBILITY FOR CLAIMS. + +
    As between Initial Developer and the Contributors, each party is responsible + +for claims and damages arising, directly or indirectly, out of its utilization + +of rights under this License and You agree to work with Initial Developer + +and Contributors to distribute such responsibility on an equitable basis. + +Nothing herein is intended or shall be deemed to constitute any admission + +of liability.
+ +13. MULTIPLE-LICENSED CODE. + +
    Initial Developer may designate portions of the Covered Code as “Multiple-Licensed”.  + +“Multiple-Licensed” means that the Initial Developer permits you to utilize + +portions of the Covered Code under Your choice of the MPL or the alternative + +licenses, if any, specified by the Initial Developer in the file described + +in Exhibit A.
+ + + +


EXHIBIT A -Mozilla Public License. + +

    ``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 Initial Developer of the Original Code is ________________________. + +Portions created by + +
     ______________________ are Copyright (C) ______ _______________________. + +All Rights + +
    Reserved. + +

    Contributor(s): ______________________________________. + +

    Alternatively, the contents of this file may be used under the terms + +of the _____ license (the  “[___] License”), in which case the provisions + +of [______] License are applicable  instead of those above.  + +If you wish to allow use of your version of this file only under the terms + +of the [____] License 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 [___] License.  If you do not delete the provisions above, + +a recipient may use your version of this file under either the MPL or the + +[___] License." + +

    [NOTE: The text of this Exhibit A may differ slightly from the text + +of the notices in the Source Code files of the Original Code. You should + +use the text of this Exhibit A rather than the text found in the Original + +Code Source Code for Your Modifications.] + +

    + + + + + diff --git a/libsecurity_asn1/Security b/libsecurity_asn1/Security new file mode 120000 index 00000000..945c9b46 --- /dev/null +++ b/libsecurity_asn1/Security @@ -0,0 +1 @@ +. \ No newline at end of file diff --git a/libsecurity_asn1/asn1/README b/libsecurity_asn1/asn1/README new file mode 100644 index 00000000..a5025d23 --- /dev/null +++ b/libsecurity_asn1/asn1/README @@ -0,0 +1,2 @@ +This directory contains ASN1 definitions for X500, X509, and PKCS +data types. It serves as documentation only. diff --git a/libsecurity_asn1/asn1/appleoids.asn b/libsecurity_asn1/asn1/appleoids.asn new file mode 100644 index 00000000..71b63ec5 --- /dev/null +++ b/libsecurity_asn1/asn1/appleoids.asn @@ -0,0 +1,237 @@ +APPLE-OIDS +DEFINITIONS IMPLICIT TAGS ::= +BEGIN +-- EXPORTS All -- + +IMPORTS + BigIntegerStr + FROM VdaEnhancedTypes + pkcs + FROM PKCS1-OIDS +; + +-- base OIDs for Apple, Apple Data Security +appleBaseOid OBJECT IDENTIFIER ::= { 1 2 840 113635 } +appleDataSecurity OBJECT IDENTIFIER ::= { appleBaseOid 100 } + +-- base OIDs for Apple Trust Policies and Algorithms +appleTrustPolicy OBJECT IDENTIFIER ::= { appleDataSecurity 1 } +appleSecurityAlgorithm OBJECT IDENTIFIER ::=Ê{ appleDataSecurity 2 } + +-- Apple trust policy OIDs + +appleISignTP OBJECT IDENTIFIER ::= { appleTrustPolicy 1 } +appleX509Basic OBJECT IDENTIFIER ::= { appleTrustPolicy 2 } +appleSSLPolicy OBJECT IDENTIFIER ::= { appleTrustPolicy 3 } + +-- Apple algorithms +appleFee OBJECT IDENTIFIER ::= { appleSecurityAlgorithm 1 } +appleAsc OBJECT IDENTIFIER ::= { appleSecurityAlgorithm 2 } +appleFeeMD5 OBJECT IDENTIFIER ::= { appleSecurityAlgorithm 3 } +appleFeeSHA1 OBJECT IDENTIFIER ::= { appleSecurityAlgorithm 4 } +appleFeed OBJECT IDENTIFIER ::= { appleSecurityAlgorithm 5 } +appleFeedExp OBJECT IDENTIFIER ::= { appleSecurityAlgorithm 6 } +appleECDSA OBJECT IDENTIFIER ::= { appleSecurityAlgorithm 7 } + +-- PKCS3 OIDs +pkcs-3 OBJECT IDENTIFIER ::= { pkcs 3 } +dhKeyAgreement OBJECT IDENTIFIER ::= { pkcs-3 1 } + +-- FEE ElGamal-style signature +FEEElGamalSignature ::= SEQUENCE { + u BigIntegerStr, + pmX BigIntegerStr +} + +-- FEE ECDSA-style signature +FEEECDSASignature ::= SEQUENCE { + c BigIntegerStr, + d BigIntegerStr +} + +-- FEE Curve parameters +FEEPrimeType ::= INTEGER { pt-mersenne(0), pt-fee(1), pt-general(2) } +FEECurveType ::= INTEGER { ct-montgomery(0), ct-weierstrass(1), ct-general(2) } + +FEECurveParameters ::= SEQUENCE +{ + primeType FEEPrimeType, + curveType FEECurveType, + q INTEGER, -- unsigned + k INTEGER, -- signed + m INTEGER, + a BigIntegerStr, + bb BigIntegerStr, -- can't use variable/field b + c BigIntegerStr, + x1Plus BigIntegerStr, + x1Minus BigIntegerStr, + cOrderPlus BigIntegerStr, + cOrderMinus BigIntegerStr, + x1OrderPlus BigIntegerStr, + x1OrderMinus BigIntegerStr, + basePrime BigIntegerStr OPTIONAL -- iff FEEPrimeType == pt-general +} + +-- FEE keys + +FEEPublicKey ::= SEQUENCE +{ + version INTEGER, + curveParams FEECurveParameters, + plusX BigIntegerStr, + minusX BigIntegerStr, + plusY BigIntegerStr OPTIONAL -- iff FEECurveType == ct-weierstrass +} + +FEEPrivateKey ::= SEQUENCE +{ + version INTEGER, + curveParams FEECurveParameters, + privData BigIntegerStr +} + +-- DSA keys +-- +-- DSA private keys are represented as a PrivateKeyInfo (pkcs8); DSA public keys +-- are represented as SubjectPublicKeyInfo (sm_s509af). However, the public p, g, +-- and q parameters are expressed in the AlgorithmIdentifier.parameters +-- field which is an ANY type. To simplify encoding and decoding (AsnAny is a royal +-- hassle to deal with), we define new structs for the entire keys here. +-- NOTE: these definition are derived from reverse engineering the key blobs +-- created by BSAFE 4.0 using info type KI_DSA{Public,Private}BER. The BSAFE +-- documentation claims that this encoding is X9.20 compatible; however BSAFE +-- adds a field to the dss-params (here called DSABSafeParams) struct which +-- indicates the prime size in bits. The encoding and decoding implemented here +-- is verified to be compatible with BSAFE 4.0 but no other implementations of +-- DSA keys. +-- +DSAPrivateKey ::= SEQUENCE +{ + version INTEGER, + dsaAlg DSAAlgorithmId, + privateKey OCTET STRING +} + +-- +-- The publicKey is actually the DER encoding of an ASN integer, wrapped in a +-- BIT STRING. +-- +DSAPublicKey ::= SEQUENCE +{ + dsaAlg DSAAlgorithmId, + publicKey BIT STRING +} + +-- +-- A convenient replacement for a DSA AlgorithmIdentifier +-- +DSAAlgorithmId ::= SEQUENCE +{ + algorithm OBJECT IDENTIFIER, -- id_dsa from sm_cms + params DSABsafeParams +} + +-- +-- This is the "ANY" parameter from AlgorithmIdentifier. +-- +DSABsafeParams ::= SEQUENCE +{ + keySizeInBits INTEGER, + p BigIntegerStr, + q BigIntegerStr, + g BigIntegerStr +} + +-- +-- DSAPrivateKey.privateKey is actually the DER encoding, as an AsnOcts, of this. +-- +DSAPrivateKeyOcts ::= SEQUENCE +{ + privateKey BigIntegerStr +} + +-- +-- DSA keys in openssl format. +-- +-- Public keys are SubjectPublicKeyInfo. AlgorithmIdentifier.parameters +-- is a DSAAlgParams. We redefine the whole thing here to avoid AsnAny +-- processing. +-- +-- The publicKey is actually the DER encoding of an ASN integer, wrapped in a +-- BIT STRING. +-- +DSAPublicKeyX509 ::= SEQUENCE +{ + dsaAlg DSAAlgorithmIdX509, + publicKey BIT STRING +} + +-- +-- A convenient replacement for a DSA AlgorithmIdentifier, X509 format +-- +DSAAlgorithmIdX509 ::= SEQUENCE +{ + algorithm OBJECT IDENTIFIER, -- id_dsa from sm_cms + -- + -- this replaces AsnAny parameters; it is the DSA parameter format + -- which is common to the CSP and to openssl + -- + params DSAAlgParams +} + +-- +-- Private keys are one of these, which appears to be specific to openssl. +-- +DSAPrivateKeyOpenssl ::= SEQUENCE +{ + version INTEGER, + p BigIntegerStr, + q BigIntegerStr, + g BigIntegerStr, + pub BigIntegerStr, + priv BigIntegerStr +} + +-- +-- DSA signature +-- +DSASignature ::= SEQUENCE +{ + r BigIntegerStr, + s BigIntegerStr +} + +-- +-- Encoding of the basic DSA parameters for use in a CDSA key generation context. +-- +DSAAlgParams ::= SEQUENCE +{ + p BigIntegerStr, + q BigIntegerStr, + g BigIntegerStr +} + +-- Diffie Hellman per PKCS3 + +DHPrivateKey ::= SEQUENCE +{ + dHOid OBJECT IDENTIFIER, -- dhKeyAgreement + params DHParameter, + secretPart BigIntegerStr +} + +DHParameterBlock ::= SEQUENCE +{ + oid OBJECT IDENTIFIER, -- pkcs-3 + params DHParameter +} + +DHParameter ::= SEQUENCE +{ + prime BigIntegerStr, -- p + base BigIntegerStr, -- g + privateValueLength BigIntegerStr OPTIONAL +} + +END -- APPLE-OIDS + diff --git a/libsecurity_asn1/asn1/asn-useful.asn1 b/libsecurity_asn1/asn1/asn-useful.asn1 new file mode 100644 index 00000000..3a4bdd7c --- /dev/null +++ b/libsecurity_asn1/asn1/asn-useful.asn1 @@ -0,0 +1,108 @@ +ASN-USEFUL DEFINITIONS ::= +BEGIN + +-- file: .../asn1specs/asn-useful.asn1 +-- +-- NOTE: every one of these types is marked as a PDU so the compiler +-- will produce the encode and decode routines that +-- enc/dec the top tag/len pairs, not just the content decoders. +-- (only nec for re-generating the library files "asn_useful.[ch]"). +-- The isPdu field does not affect how this module is linked +-- with other modules during compilation. +-- +-- (type DEF comment directives immediately follow the "::=") +-- +-- MS 92 +-- +-- $Header: /Volumes/Data2/cvs2svn/runf/cvs-mirror/tla/libsecurity_asn1/asn1/asn-useful.asn1,v 1.1 2003/02/19 19:06:35 dmitch Exp $ +-- $Log: asn-useful.asn1,v $ +-- Revision 1.1 2003/02/19 19:06:35 dmitch +-- Moved ASN source here from old Security/SecurityASN1 for documentation purposes. +-- +-- Revision 1.1.1.1 2001/05/18 23:13:59 mb +-- Move from private repository to open source repository +-- +-- Revision 1.1 2000/06/14 22:23:07 dmitch +-- New PKCS/CMS snacc-generated framework. +-- +-- Revision 1.1.1.1 2000/03/09 00:59:54 rmurphy +-- Base Fortissimo Tree +-- +-- Revision 1.2 1999/03/10 18:23:38 aram +-- Corrected definition of UTF8String. +-- +-- Revision 1.1 1999/03/10 18:16:44 aram +-- Added UTF8String definition. +-- +-- Revision 1.3 1995/07/24 15:12:35 rj +-- useful.asn1 renamed to asn-useful.asn1 to accomodate to snacc's new file name generation scheme. +-- +-- Revision 1.2 1994/08/28 09:54:19 rj +-- comment leader fixed. +-- +-- Revision 1.1 1994/08/28 09:51:15 rj +-- first check-in. + + +ObjectDescriptor ::= -- isPdu:"TRUE" -- + [UNIVERSAL 7] IMPLICIT OCTET STRING + +UTF8String ::= --snacc isPdu:"TRUE" -- + [UNIVERSAL 12] IMPLICIT OCTET STRING + +NumericString ::= --snacc isPdu:"TRUE" -- + [UNIVERSAL 18] IMPLICIT OCTET STRING + +PrintableString ::= --snacc isPdu:"TRUE" -- + [UNIVERSAL 19] IMPLICIT OCTET STRING + +TeletexString ::= --snacc isPdu:"TRUE" -- + [UNIVERSAL 20] IMPLICIT OCTET STRING + +T61String ::= --snacc isPdu:"TRUE" -- + [UNIVERSAL 20] IMPLICIT OCTET STRING + +VideotexString ::= --snacc isPdu:"TRUE" -- + [UNIVERSAL 21] IMPLICIT OCTET STRING + +IA5String ::= --snacc isPdu:"TRUE" -- + [UNIVERSAL 22] IMPLICIT OCTET STRING + +GraphicString ::= --snacc isPdu:"TRUE" -- + [UNIVERSAL 25] IMPLICIT OCTET STRING + +VisibleString ::= --snacc isPdu:"TRUE" -- + [UNIVERSAL 26] IMPLICIT OCTET STRING + +ISO646String ::= --snacc isPdu:"TRUE" -- + [UNIVERSAL 26] IMPLICIT OCTET STRING + +GeneralString ::= --snacc isPdu:"TRUE" -- + [UNIVERSAL 27] IMPLICIT OCTET STRING + +UTCTime ::= --snacc isPdu:"TRUE" -- + [UNIVERSAL 23] IMPLICIT OCTET STRING + +GeneralizedTime ::= --snacc isPdu:"TRUE" -- + [UNIVERSAL 24] IMPLICIT OCTET STRING + +UniversalString ::= --snacc isPdu:"TRUE" -- + [UNIVERSAL 28] IMPLICIT OCTET STRING + +BMPString ::= --snacc isPdu:"TRUE" -- + [UNIVERSAL 30] IMPLICIT OCTET STRING + +EXTERNAL ::= --snacc isPdu:"TRUE" -- [UNIVERSAL 8] IMPLICIT SEQUENCE +{ + direct-reference OBJECT IDENTIFIER OPTIONAL, + indirect-reference INTEGER OPTIONAL, + data-value-descriptor ObjectDescriptor OPTIONAL, + encoding CHOICE + { + single-ASN1-type [0] OCTET STRING, -- should be ANY + octet-aligned [1] IMPLICIT OCTET STRING, + arbitrary [2] IMPLICIT BIT STRING + } +} + +END -- of ASN-USEFUL type definitions diff --git a/libsecurity_asn1/asn1/pkcs1.asn1 b/libsecurity_asn1/asn1/pkcs1.asn1 new file mode 100644 index 00000000..56979908 --- /dev/null +++ b/libsecurity_asn1/asn1/pkcs1.asn1 @@ -0,0 +1,205 @@ +PKCS-1 {iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-1(1) + modules(0) pkcs-1(1)} + +-- $Revision: 1.1 $ + +-- This module has been checked for conformance with the ASN.1 +-- standard by the OSS ASN.1 Tools + +DEFINITIONS EXPLICIT TAGS ::= + +BEGIN + +-- EXPORTS ALL -- +-- All types and values defined in this module is exported for use in other +-- ASN.1 modules. + +-- IMPORTS None -- + +-- Basic object identifiers + +-- The DER for this in hexadecimal is: +-- 06 08 +-- 2A 86 48 86 F7 0D 01 01 +-- +pkcs-1 OBJECT IDENTIFIER ::= { + iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 1 } + +-- +-- When the following OIDs are used in an AlgorithmIdentifier +-- the parameters MUST be present and MUST be NULL. +-- +rsaEncryption OBJECT IDENTIFIER ::= { pkcs-1 1 } +md2WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 2 } +md4WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 3 } +md5WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 4 } +sha1WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 5 } +rsaOAEPEncryptionSET OBJECT IDENTIFIER ::= { pkcs-1 6 } + +-- +-- When id-RSAES-OAEP is used in an AlgorithmIdentifier +-- the parameters MUST be present and MUST be RSAES-OAEP-params. +-- +id-RSAES-OAEP OBJECT IDENTIFIER ::= { pkcs-1 7 } + +-- +-- When id-mgf1 is used in an AlgorithmIdentifier +-- the parameters MUST be present and MUST be +-- a DigestAlgorithmIdentifier, specifically SHA1Identifier. +-- +id-mgf1 OBJECT IDENTIFIER ::= { pkcs-1 8 } + +-- +-- When id-pSpecified is used in an AlgorithmIdentifier +-- the parameters MUST be an OCTET STRING. +-- +id-pSpecified OBJECT IDENTIFIER ::= { pkcs-1 9 } + +-- +-- This OID really belongs in a module with the secsig OIDs. +-- +id-sha1 OBJECT IDENTIFIER ::= { + iso(1) identified-organization(3) oiw(14) secsig(3) + algorithms(2) 26 } + + +-- Useful types + +ALGORITHM-IDENTIFIER ::= TYPE-IDENTIFIER + +-- Note: the parameter InfoObjectSet in the following definitions +-- allows a distinct information object set to be specified for +-- sets of algorithms such as: +-- DigestAlgorithms ALGORITHM-IDENTIFIER ::= { +-- { NULL IDENTIFIED BY id-sha1 }, +-- { NULL IDENTIFIED BY id-md5 }, +-- { NULL IDENTIFIED BY id-md2 } +-- } +-- +AlgorithmIdentifier { ALGORITHM-IDENTIFIER:InfoObjectSet } ::= +SEQUENCE { + algorithm ALGORITHM-IDENTIFIER.&id({InfoObjectSet}), + parameters ALGORITHM-IDENTIFIER.&Type({InfoObjectSet} + {@algorithm}) OPTIONAL +} + +-- Algorithms + +-- +-- Allowed OAEP digest algorithms. +-- +OAEPDigestAlgorithms ALGORITHM-IDENTIFIER ::= { + { SHA1Parameters IDENTIFIED BY id-sha1 }, + ... --Allows for future expansion +} + +sha1Identifier AlgorithmIdentifier {{ OAEPDigestAlgorithms }} ::= + {algorithm id-sha1, parameters SHA1Parameters : NULL} + +SHA1Parameters ::= NULL + +-- +-- Allowed Mask Generation Function algorithms. +-- If the identifier is id-mgf1, the parameters +-- are a single digest algorithm identifier. +-- +PKCS1MGFAlgorithms ALGORITHM-IDENTIFIER ::= { + { MGF1Parameters IDENTIFIED BY id-mgf1 }, + ...--Allows for future expansion +} + +MGF1Parameters ::= + AlgorithmIdentifier { {OAEPDigestAlgorithms} } + +-- +-- Allowed algorithms for pSourceFunc. +-- +PKCS1PSourceAlgorithms ALGORITHM-IDENTIFIER ::= { + { PEmptyString IDENTIFIED BY id-pSpecified }, + ...--Allows for future expansion +} + +PEmptyString ::= OCTET STRING (SIZE(0)) + +-- +-- This identifier means that P is an empty string, so the digest +-- of the empty string appears in the RSA block before masking. +-- +pSpecifiedEmptyIdentifier AlgorithmIdentifier {{ PKCS1PSourceAlgorithms }} ::= + { algorithm id-pSpecified, parameters PEmptyString : ''H } + +-- +-- Default AlgorithmIdentifier for id-RSAES-OAEP.maskGenFunc. +-- +mgf1SHA1Identifier AlgorithmIdentifier {{ PKCS1MGFAlgorithms }} ::= + { algorithm id-mgf1, + parameters AlgorithmIdentifier{{OAEPDigestAlgorithms}} : sha1Identifier} + +-- +-- Type identifier definitions for the PKCS #1 OIDs. +-- +PKCS1Algorithms ALGORITHM-IDENTIFIER ::= { + { NULL IDENTIFIED BY rsaEncryption } | + { NULL IDENTIFIED BY md2WithRSAEncryption } | + { NULL IDENTIFIED BY md4WithRSAEncryption } | + { NULL IDENTIFIED BY md5WithRSAEncryption } | + { NULL IDENTIFIED BY sha1WithRSAEncryption } | + { NULL IDENTIFIED BY rsaOAEPEncryptionSET } | + { RSAES-OAEP-params IDENTIFIED BY id-RSAES-OAEP } | + PKCS1PSourceAlgorithms, + ... -- Allows for future expansion +} + +-- Main structures + +RSAPublicKey ::= SEQUENCE { + modulus INTEGER, -- (Usually large) n = p*q + publicExponent INTEGER -- (Usually small) e +} + +-- +-- Representation of RSA private key with p and q +-- information for the CRT algorithm. +-- +RSAPrivateKey ::= SEQUENCE { + version INTEGER { rsaPrivateKeyVer0(0) }(rsaPrivateKeyVer0), + modulus INTEGER, -- (Usually large) n + publicExponent INTEGER, -- (Usually small) e + privateExponent INTEGER, -- (Usually large) d + prime1 INTEGER, -- (Usually large) p + prime2 INTEGER, -- (Usually large) q + exponent1 INTEGER, -- (Usually large) d mod (p-1) + exponent2 INTEGER, -- (Usually large) d mod (q-1) + coefficient INTEGER -- (Usually large) (inverse of q) mod p +} + +-- +-- AlgorithmIdentifier.parameters for id-RSAES-OAEP. +-- Note that the tags in this Sequence are explicit. +-- + +RSAES-OAEP-params ::= SEQUENCE { + hashFunc [0] AlgorithmIdentifier { {OAEPDigestAlgorithms} } + DEFAULT sha1Identifier, + maskGenFunc [1] AlgorithmIdentifier { {PKCS1MGFAlgorithms} } + DEFAULT mgf1SHA1Identifier, + pSourceFunc [2] AlgorithmIdentifier { {PKCS1PSourceAlgorithms} } + DEFAULT pSpecifiedEmptyIdentifier +} + +-- +-- Identifier for default RSAES-OAEP algorithm identifier +-- The DER Encoding of this is in hexadecimal: +-- 30 0D +-- 06 09 +-- 2A 86 48 86 F7 0D 01 01 07 +-- 30 00 +-- Notice that the DER encoding of default values is "empty". +-- +rSAES-OAEP-Default-Identifier AlgorithmIdentifier{ {PKCS1Algorithms} } ::= + {algorithm id-RSAES-OAEP, + parameters RSAES-OAEP-params : {hashFunc sha1Identifier, + maskGenFunc mgf1SHA1Identifier, + pSourceFunc pSpecifiedEmptyIdentifier}} + +END -- PKCS1Definitions diff --git a/libsecurity_asn1/asn1/pkcs10.asn b/libsecurity_asn1/asn1/pkcs10.asn new file mode 100644 index 00000000..73fdb819 --- /dev/null +++ b/libsecurity_asn1/asn1/pkcs10.asn @@ -0,0 +1,53 @@ +-- PKCS10 ASN module + +PKCS5 +DEFINITIONS IMPLICIT TAGS ::= +BEGIN +-- EXPORTS All -- + +IMPORTS + -- Directory Information Framework (X.501) + Name, Attribute, Attributes + FROM InformationFramework + + -- Directory Authentication Framework (X.509) + AlgorithmIdentifier, SubjectPublicKeyInfo + FROM AuthenticationFramework + + -- CryptographicMessageSyntax (draft-ietf-smime-cms-13) + Signature, SignatureAlgorithmIdentifier + FROM CryptographicMessageSyntax +; + +CertificationRequestInfo ::= SEQUENCE { + version VersionP10, + subject Name, + subjectPublicKeyInfo SubjectPublicKeyInfo, + attributes [0] IMPLICIT Attributes +} + +VersionP10 ::= INTEGER +-- redefined, same as InformationFramework (sm_x501if.asn) +-- Attributes ::= SET OF Attribute + +-- Per PKCS10 spec +CertificationRequest ::= SEQUENCE { + certificationRequestInfo CertificationRequestInfo, + signatureAlgorithm SignatureAlgorithmIdentifier, + signature Signature +} + +-- This is what we actually use to avoid unnecessary +-- setup and teardown of CertificationRequestInfo when +-- signing and verifying +CertificationRequestSigned ::= SEQUENCE { + certificationRequestInfo ANY, + signatureAlgorithm SignatureAlgorithmIdentifier, + signature Signature +} + +-- duplicated from CryptographicMessageSyntax +-- SignatureAlgorithmIdentifier ::= AlgorithmIdentifier +-- Signature ::= BIT STRING + +END -- PKCS10 diff --git a/libsecurity_asn1/asn1/pkcs1oids.asn b/libsecurity_asn1/asn1/pkcs1oids.asn new file mode 100644 index 00000000..bc1025df --- /dev/null +++ b/libsecurity_asn1/asn1/pkcs1oids.asn @@ -0,0 +1,46 @@ +PKCS1-OIDS +DEFINITIONS IMPLICIT TAGS ::= +BEGIN +-- EXPORTS All -- + +IMPORTS + BigIntegerStr + FROM VdaEnhancedTypes +; + +rsadsi OBJECT IDENTIFIER ::= { 1 2 840 113549 } +pkcs OBJECT IDENTIFIER ::= { rsadsi 1 } + +pkcs-1 OBJECT IDENTIFIER ::= { pkcs 1 } +rsaEncryption OBJECT IDENTIFIER ::= { pkcs-1 1 } +md2WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 2 } +md4WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 3 } +md5WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 4 } +sha1withRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 5 } -- dmitch + +rsaDigestAlgorithm OBJECT IDENTIFIER ::= { rsadsi 2 } +md2 OBJECT IDENTIFIER ::= { rsaDigestAlgorithm 2 } +md4 OBJECT IDENTIFIER ::= { rsaDigestAlgorithm 4 } +md5 OBJECT IDENTIFIER ::= { rsaDigestAlgorithm 5 } + +RSAPublicKey ::= SEQUENCE { + modulus BigIntegerStr, -- n + publicExponent BigIntegerStr -- e +} + +RSAPrivateKey ::= SEQUENCE { + version INTEGER, -- Version, + modulus BigIntegerStr, -- n + publicExponent BigIntegerStr, -- e + privateExponent BigIntegerStr, -- d + prime1 BigIntegerStr, -- p + prime2 BigIntegerStr, -- q + exponent1 BigIntegerStr, -- d mod (p-1) + exponent2 BigIntegerStr, -- d mod (q-1) + coefficient BigIntegerStr -- (inverse of q) mod p +} + +-- Version ::= INTEGER + +END -- PKCS1-OIDS + diff --git a/libsecurity_asn1/asn1/pkcs5.asn1 b/libsecurity_asn1/asn1/pkcs5.asn1 new file mode 100644 index 00000000..d090fbb7 --- /dev/null +++ b/libsecurity_asn1/asn1/pkcs5.asn1 @@ -0,0 +1,141 @@ +-- PKCS #5 v2.0 ASN.1 Module +-- Revised March 25, 1999 + +-- This module has been checked for conformance with the +-- ASN.1 standard by the OSS ASN.1 Tools + +PKCS5v2-0 {iso(1) member-body(2) us(840) rsadsi(113549) + pkcs(1) pkcs-5(5) modules(16) pkcs5v2-0(1)} + +DEFINITIONS ::= BEGIN + +-- Basic object identifiers + +rsadsi OBJECT IDENTIFIER ::= + {iso(1) member-body(2) us(840) 113549} +pkcs OBJECT IDENTIFIER ::= {rsadsi 1} +pkcs-5 OBJECT IDENTIFIER ::= {pkcs 5} + +-- Basic types and classes + +AlgorithmIdentifier { ALGORITHM-IDENTIFIER:InfoObjectSet } ::= +SEQUENCE { + algorithm ALGORITHM-IDENTIFIER.&id({InfoObjectSet}), + parameters ALGORITHM-IDENTIFIER.&Type({InfoObjectSet} + {@algorithm}) OPTIONAL } + +ALGORITHM-IDENTIFIER ::= TYPE-IDENTIFIER + +-- PBKDF2 + +PBKDF2Algorithms ALGORITHM-IDENTIFIER ::= + { {PBKDF2-params IDENTIFIED BY id-PBKDF2}, ...} + +id-PBKDF2 OBJECT IDENTIFIER ::= {pkcs-5 12} + +algid-hmacWithSHA1 AlgorithmIdentifier {{PBKDF2-PRFs}} ::= + {algorithm id-hmacWithSHA1, parameters NULL : NULL} + +PBKDF2-params ::= SEQUENCE { + salt CHOICE { + specified OCTET STRING, + otherSource AlgorithmIdentifier {{PBKDF2-SaltSources}} + }, + iterationCount INTEGER (1..MAX), + keyLength INTEGER (1..MAX) OPTIONAL, + prf AlgorithmIdentifier {{PBKDF2-PRFs}} DEFAULT + algid-hmacWithSHA1 } + +PBKDF2-SaltSources ALGORITHM-IDENTIFIER ::= { ... } + +PBKDF2-PRFs ALGORITHM-IDENTIFIER ::= + { {NULL IDENTIFIED BY id-hmacWithSHA1}, ... } + + -- PBES1 + +PBES1Algorithms ALGORITHM-IDENTIFIER ::= + { {PBEParameter IDENTIFIED BY pbeWithMD2AndDES-CBC} | + {PBEParameter IDENTIFIED BY pbeWithMD2AndRC2-CBC} | + {PBEParameter IDENTIFIED BY pbeWithMD5AndDES-CBC} | + {PBEParameter IDENTIFIED BY pbeWithMD5AndRC2-CBC} | + {PBEParameter IDENTIFIED BY pbeWithSHA1AndDES-CBC} | + {PBEParameter IDENTIFIED BY pbeWithSHA1AndRC2-CBC}, ...} + +pbeWithMD2AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 1} +pbeWithMD2AndRC2-CBC OBJECT IDENTIFIER ::= {pkcs-5 4} +pbeWithMD5AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 3} +pbeWithMD5AndRC2-CBC OBJECT IDENTIFIER ::= {pkcs-5 6} +pbeWithSHA1AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 10} +pbeWithSHA1AndRC2-CBC OBJECT IDENTIFIER ::= {pkcs-5 11} + +PBEParameter ::= SEQUENCE { + salt OCTET STRING (SIZE(8)), + iterationCount INTEGER } + +-- PBES2 + +PBES2Algorithms ALGORITHM-IDENTIFIER ::= + { {PBES2-params IDENTIFIED BY id-PBES2}, ...} + +id-PBES2 OBJECT IDENTIFIER ::= {pkcs-5 13} + +PBES2-params ::= SEQUENCE { + keyDerivationFunc AlgorithmIdentifier {{PBES2-KDFs}}, + encryptionScheme AlgorithmIdentifier {{PBES2-Encs}} } + +PBES2-KDFs ALGORITHM-IDENTIFIER ::= + { {PBKDF2-params IDENTIFIED BY id-PBKDF2}, ... } + +PBES2-Encs ALGORITHM-IDENTIFIER ::= { ... } + +-- PBMAC1 + +PBMAC1Algorithms ALGORITHM-IDENTIFIER ::= + { {PBMAC1-params IDENTIFIED BY id-PBMAC1}, ...} + +id-PBMAC1 OBJECT IDENTIFIER ::= {pkcs-5 14} + +PBMAC1-params ::= SEQUENCE { + keyDerivationFunc AlgorithmIdentifier {{PBMAC1-KDFs}}, + messageAuthScheme AlgorithmIdentifier {{PBMAC1-MACs}} } + +PBMAC1-KDFs ALGORITHM-IDENTIFIER ::= + { {PBKDF2-params IDENTIFIED BY id-PBKDF2}, ... } + +PBMAC1-MACs ALGORITHM-IDENTIFIER ::= { ... } + +-- Supporting techniques + +digestAlgorithm OBJECT IDENTIFIER ::= {rsadsi 2} +encryptionAlgorithm OBJECT IDENTIFIER ::= {rsadsi 3} + +SupportingAlgorithms ALGORITHM-IDENTIFIER ::= + { {NULL IDENTIFIED BY id-hmacWithSHA1} | + {OCTET STRING (SIZE(8)) IDENTIFIED BY desCBC} | + {OCTET STRING (SIZE(8)) IDENTIFIED BY des-EDE3-CBC} | + {RC2-CBC-Parameter IDENTIFIED BY rc2CBC} | + {RC5-CBC-Parameters IDENTIFIED BY rc5-CBC-PAD}, ... } + +id-hmacWithSHA1 OBJECT IDENTIFIER ::= {digestAlgorithm 7} + +desCBC OBJECT IDENTIFIER ::= + {iso(1) identified-organization(3) oiw(14) secsig(3) + algorithms(2) 7} -- from OIW + +des-EDE3-CBC OBJECT IDENTIFIER ::= {encryptionAlgorithm 7} + +rc2CBC OBJECT IDENTIFIER ::= {encryptionAlgorithm 2} + +RC2-CBC-Parameter ::= SEQUENCE { + rc2ParameterVersion INTEGER OPTIONAL, + iv OCTET STRING (SIZE(8)) } + +rc5-CBC-PAD OBJECT IDENTIFIER ::= {encryptionAlgorithm 9} + +RC5-CBC-Parameters ::= SEQUENCE { + version INTEGER {v1-0(16)} (v1-0), + rounds INTEGER (8..127), + blockSizeInBits INTEGER (64 | 128), + iv OCTET STRING OPTIONAL } + +END diff --git a/libsecurity_asn1/asn1/pkcs7.asn b/libsecurity_asn1/asn1/pkcs7.asn new file mode 100644 index 00000000..69b2d0b2 --- /dev/null +++ b/libsecurity_asn1/asn1/pkcs7.asn @@ -0,0 +1,63 @@ +PKCS7 + +-- ??? {iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-7(7) +-- modules(0) pkcs-7(1)} + +DEFINITIONS EXPLICIT TAGS ::= +BEGIN + +-- +-- 3. Definitions +-- + +-- EXPORTS All; + +IMPORTS + + informationFramework, authenticationFramework + FROM UsefulDefinitions { usefulDefinitions } + + AlgorithmIdentifier + FROM AuthenticationFramework { authenticationFramework } + +; + +-- *** A large amount of stuff we don't need right now deleted *** + +-- +-- 13. Encrypted-data content type +-- + +EncryptedData ::= SEQUENCE { + version INTEGER {edVer0(0)} (edVer0), + encryptedContentInfo EncryptedContentInfo +} + +EncryptedContentInfo ::= SEQUENCE { + contentType ContentType, + contentEncryptionAlgorithm + ContentEncryptionAlgorithmIdentifier, + encryptedContent + [0] IMPLICIT EncryptedContent OPTIONAL +} + +ContentType ::= OBJECT IDENTIFIER + +EncryptedContent ::= OCTET STRING + +ContentEncryptionAlgorithmIdentifier ::= AlgorithmIdentifier + +-- +-- 14. Object Identifiers +-- + +pkcs-7 OBJECT IDENTIFIER ::= + { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 7 } +dataPkcs7 OBJECT IDENTIFIER ::= { pkcs-7 1 } +signedData OBJECT IDENTIFIER ::= { pkcs-7 2 } +envelopedData OBJECT IDENTIFIER ::= { pkcs-7 3 } +signedAndEnvelopedData OBJECT IDENTIFIER ::= { pkcs-7 4 } +digestedData OBJECT IDENTIFIER ::= { pkcs-7 5 } +encryptedData OBJECT IDENTIFIER ::= { pkcs-7 6 } + +END diff --git a/libsecurity_asn1/asn1/pkcs8.asn b/libsecurity_asn1/asn1/pkcs8.asn new file mode 100644 index 00000000..163db63d --- /dev/null +++ b/libsecurity_asn1/asn1/pkcs8.asn @@ -0,0 +1,40 @@ +PrivateKeyInformationSyntax +-- PKCS#8 ASN.1 +DEFINITIONS IMPLICIT TAGS ::= +BEGIN +-- EXPORTS All -- +IMPORTS + AlgorithmIdentifier + FROM AuthenticationFramework { authenticationFramework } + Attributes + FROM InformationFramework { informationFramework } + EncryptedKey + FROM CryptographicMessageSyntax +; + +PrivateKeyInfo ::= SEQUENCE { + version INTEGER, -- Version, + privateKeyAlgorithm AlgorithmIdentifier, + privateKey PrivateKey, + attributes [0] IMPLICIT Attributes OPTIONAL } + + +-- Version ::= INTEGER + +-- PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier + + +PrivateKey ::= OCTET STRING + + +EncryptedPrivateKeyInfo ::= SEQUENCE { + encryptionAlgorithm AlgorithmIdentifier, + encryptedKey EncryptedKey } + + +-- EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier + +-- EncryptedKey ::= OCTET STRING + +END -- PrivateKeyInformationSyntax + diff --git a/libsecurity_asn1/asn1/pkcs9oids.asn b/libsecurity_asn1/asn1/pkcs9oids.asn new file mode 100644 index 00000000..c8113e39 --- /dev/null +++ b/libsecurity_asn1/asn1/pkcs9oids.asn @@ -0,0 +1,19 @@ +PKCS9-OIDS +DEFINITIONS IMPLICIT TAGS ::= +BEGIN +-- EXPORTS All -- + +pkcs-9 OBJECT IDENTIFIER ::= { 1 2 840 113549 1 9 } + +emailAddress OBJECT IDENTIFIER ::= { pkcs-9 1 } +unstructuredName OBJECT IDENTIFIER ::= { pkcs-9 2 } +contentTypePkcs9 OBJECT IDENTIFIER ::= { pkcs-9 3 } +messageDigest OBJECT IDENTIFIER ::= { pkcs-9 4 } +signingTime OBJECT IDENTIFIER ::= { pkcs-9 5 } +countersignature OBJECT IDENTIFIER ::= { pkcs-9 6 } +challengePassword OBJECT IDENTIFIER ::= { pkcs-9 7 } +unstructuredAddress OBJECT IDENTIFIER ::= { pkcs-9 8 } +extendedCertificateAttributes OBJECT IDENTIFIER ::= { pkcs-9 9 } + +END -- PKCS9-OIDS + diff --git a/libsecurity_asn1/asn1/rfc3161.asn1 b/libsecurity_asn1/asn1/rfc3161.asn1 new file mode 100644 index 00000000..196d3684 --- /dev/null +++ b/libsecurity_asn1/asn1/rfc3161.asn1 @@ -0,0 +1,137 @@ +PKIXTSP {iso(1) identified-organization(3) dod(6) internet(1) + security(5) mechanisms(5) pkix(7) id-mod(0) id-mod-tsp(13)} + +DEFINITIONS IMPLICIT TAGS ::= + +BEGIN + +-- EXPORTS ALL -- + +IMPORTS + + Extensions, AlgorithmIdentifier + FROM PKIX1Explicit88 {iso(1) identified-organization(3) + dod(6) internet(1) security(5) mechanisms(5) pkix(7) + id-mod(0) id-pkix1-explicit-88(1)} + + GeneralName FROM PKIX1Implicit88 {iso(1) + identified-organization(3) dod(6) internet(1) security(5) + mechanisms(5) pkix(7) id-mod(0) id-pkix1-implicit-88(2)} + + ContentInfo FROM CryptographicMessageSyntax {iso(1) + member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-9(9) + smime(16) modules(0) cms(1)} + + PKIFreeText FROM PKIXCMP {iso(1) identified-organization(3) + dod(6) internet(1) security(5) mechanisms(5) pkix(7) id-mod(0) + id-mod-cmp(9)} ; + + -- Locally defined OIDs -- + +-- eContentType for a time-stamp token + +id-ct-TSTInfo OBJECT IDENTIFIER ::= { iso(1) member-body(2) +us(840) rsadsi(113549) pkcs(1) pkcs-9(9) smime(16) ct(1) 4} + +-- 2.4.1 + +TimeStampReq ::= SEQUENCE { + version INTEGER { v1(1) }, + messageImprint MessageImprint, + --a hash algorithm OID and the hash value of the data to be + --time-stamped + reqPolicy TSAPolicyId OPTIONAL, + nonce INTEGER OPTIONAL, + certReq BOOLEAN DEFAULT FALSE, + extensions [0] IMPLICIT Extensions OPTIONAL } + +MessageImprint ::= SEQUENCE { + hashAlgorithm AlgorithmIdentifier, + hashedMessage OCTET STRING } + +TSAPolicyId ::= OBJECT IDENTIFIER + +-- 2.4.2 + +TimeStampResp ::= SEQUENCE { + status PKIStatusInfo, + timeStampToken TimeStampToken OPTIONAL } + +-- The status is based on the definition of status +-- in section 3.2.3 of [RFC2510] + +PKIStatusInfo ::= SEQUENCE { + status PKIStatus, + statusString PKIFreeText OPTIONAL, + failInfo PKIFailureInfo OPTIONAL } + +PKIStatus ::= INTEGER { + granted (0), + -- when the PKIStatus contains the value zero a TimeStampToken, as + requested, is present. + grantedWithMods (1), + -- when the PKIStatus contains the value one a TimeStampToken, + with modifications, is present. + rejection (2), + waiting (3), + revocationWarning (4), + -- this message contains a warning that a revocation is + -- imminent + revocationNotification (5) + -- notification that a revocation has occurred } + + -- When the TimeStampToken is not present + -- failInfo indicates the reason why the + -- time-stamp request was rejected and + -- may be one of the following values. + +PKIFailureInfo ::= BIT STRING { + badAlg (0), + -- unrecognized or unsupported Algorithm Identifier + badRequest (2), + -- transaction not permitted or supported + badDataFormat (5), + -- the data submitted has the wrong format + timeNotAvailable (14), + -- the TSA's time source is not available + unacceptedPolicy (15), + -- the requested TSA policy is not supported by the TSA. + unacceptedExtension (16), + -- the requested extension is not supported by the TSA. + addInfoNotAvailable (17) + -- the additional information requested could not be understood + -- or is not available + systemFailure (25) + -- the request cannot be handled due to system failure } + +TimeStampToken ::= ContentInfo + + -- contentType is id-signedData as defined in [CMS] + -- content is SignedData as defined in([CMS]) + -- eContentType within SignedData is id-ct-TSTInfo + -- eContent within SignedData is TSTInfo + +TSTInfo ::= SEQUENCE { + version INTEGER { v1(1) }, + policy TSAPolicyId, + messageImprint MessageImprint, + -- MUST have the same value as the similar field in + -- TimeStampReq + serialNumber INTEGER, + -- Time-Stamping users MUST be ready to accommodate integers + -- up to 160 bits. + genTime GeneralizedTime, + accuracy Accuracy OPTIONAL, + ordering BOOLEAN DEFAULT FALSE, + nonce INTEGER OPTIONAL, + -- MUST be present if the similar field was present + -- in TimeStampReq. In that case it MUST have the same value. + tsa [0] GeneralName OPTIONAL, + extensions [1] IMPLICIT Extensions OPTIONAL } + +Accuracy ::= SEQUENCE { + seconds INTEGER OPTIONAL, + millis [0] INTEGER (1..999) OPTIONAL, + micros [1] INTEGER (1..999) OPTIONAL } + + \ No newline at end of file diff --git a/libsecurity_asn1/asn1/sm_cms.asn b/libsecurity_asn1/asn1/sm_cms.asn new file mode 100644 index 00000000..c861a477 --- /dev/null +++ b/libsecurity_asn1/asn1/sm_cms.asn @@ -0,0 +1,431 @@ + +-- @(#) sm_cms.asn 1.13 12/17/98 14:17:10 +-- FROM cms.txt: + + CryptographicMessageSyntax + { 1 2 840 113549 1 9 16 0 1 } + --RWC;{ iso(1) member-body(2) us(840) rsadsi(113549) + --RWC; pkcs(1) pkcs-9(9) smime(16) modules(0) cms(1) } + + DEFINITIONS IMPLICIT TAGS ::= + BEGIN + + -- EXPORTS All + -- The types and values defined in this module are exported for use in + -- the other ASN.1 modules. Other applications may use them for their + -- own purposes. + + IMPORTS + + -- MB;KeyIdentifier (replaces SubjectKeyIdentifier) + KeyIdentifier + FROM CertificateExtensions + + -- MB;PKCS1-OIDS + rsadsi, pkcs --MB;rsaEncryption, md5 + FROM PKCS1-OIDS + + -- Useful Definitions from X.501 + informationFramework, authenticationFramework + FROM UsefulDefinitions { usefulDefinitions } + + -- Directory Information Framework (X.501) + Name, Attribute, Attributes, AttributeValue + FROM InformationFramework --RWC; { joint-iso-itu-t ds(5) rWCmodules(1) + --RWC; "modules(1)" re-defined from above "CrytpgraphicMessageSyntax". + --RWC; informationFramework(1) 3 } + + -- Directory Authentication Framework (X.509) + AlgorithmIdentifier, AttributeCertificate, Certificate, + CertificateList, CertificateSerialNumber, Time + FROM AuthenticationFramework; --RWC;{ joint-iso-itu-t rWCds(5) + --RWC; "ds(1)" re-defined. + --RWC;module(1) rWCauthenticationFramework(7) 3 } ; + + + + + + -- Cryptographic Message Syntax + + ContentInfo ::= SEQUENCE { + contentType ContentType, + content [0] EXPLICIT ANY } --RWC;DEFINED BY contentType } + + ContentType ::= OBJECT IDENTIFIER + + SignedData ::= SEQUENCE { + version CMSVersion, + digestAlgorithms DigestAlgorithmIdentifiers, + encapContentInfo EncapsulatedContentInfo, + certificates [0] IMPLICIT CertificateSet OPTIONAL, + crls [1] IMPLICIT CertificateRevocationLists OPTIONAL, + signerInfos SignerInfos } + + DigestAlgorithmIdentifiers ::= SET OF DigestAlgorithmIdentifier + + SignerInfos ::= SET OF SignerInfo + + + + EncapsulatedContentInfo ::= SEQUENCE { + eContentType ContentType, + eContent [0] EXPLICIT OCTET STRING OPTIONAL } + + SignerInfo ::= SEQUENCE { + version CMSVersion, + sid SignerIdentifier, + digestAlgorithm DigestAlgorithmIdentifier, + signedAttrs [0] IMPLICIT Attributes OPTIONAL, --MB;SignedAttributes OPTIONAL, + signatureAlgorithm SignatureAlgorithmIdentifier, + signature SignatureValue, + unsignedAttrs [1] IMPLICIT Attributes OPTIONAL } --MB;UnsignedAttributes OPTIONAL } + + SignerIdentifier ::= CHOICE { + issuerAndSerialNumber IssuerAndSerialNumber, + subjectKeyIdentifier [0] KeyIdentifier } --MB;SubjectKeyIdentifier } + + --MB;SignedAttributes ::= SET SIZE (1..MAX) OF Attribute + + --MB;UnsignedAttributes ::= SET SIZE (1..MAX) OF Attribute + + --MB;Attribute ::= SEQUENCE { + --MB; attrType OBJECT IDENTIFIER, + --MB; attrValues SET OF AttributeValue } + + --MB;AttributeValue ::= ANY + + SignatureValue ::= OCTET STRING + + EnvelopedData ::= SEQUENCE { + version CMSVersion, + originatorInfo [0] IMPLICIT OriginatorInfo OPTIONAL, + recipientInfos RecipientInfos, + encryptedContentInfo EncryptedContentInfo, + unprotectedAttrs [1] IMPLICIT Attributes OPTIONAL } --MB;UnprotectedAttributes OPTIONAL } + + OriginatorInfo ::= SEQUENCE { + certs [0] IMPLICIT CertificateSet OPTIONAL, + crls [1] IMPLICIT CertificateRevocationLists OPTIONAL } + + RecipientInfos ::= SET OF RecipientInfo + + EncryptedContentInfo ::= SEQUENCE { + contentType ContentType, + contentEncryptionAlgorithm ContentEncryptionAlgorithmIdentifier, + encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL } + + EncryptedContent ::= OCTET STRING + + + + --MB;UnprotectedAttributes ::= SET SIZE (1..MAX) OF Attribute + + RecipientInfo ::= CHOICE { + ktri KeyTransRecipientInfo, + kari [1] KeyAgreeRecipientInfo, + kekri [2] KEKRecipientInfo } + + EncryptedKey ::= OCTET STRING + + KeyTransRecipientInfo ::= SEQUENCE { + version CMSVersion, -- always set to 0 or 2 + rid RecipientIdentifier, + keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier, + encryptedKey EncryptedKey } + + RecipientIdentifier ::= CHOICE { + issuerAndSerialNumber IssuerAndSerialNumber, + subjectKeyIdentifier [0] KeyIdentifier } --MB;SubjectKeyIdentifier } + + KeyAgreeRecipientInfo ::= SEQUENCE { + version CMSVersion, -- always set to 3 + originator [0] EXPLICIT OriginatorIdentifierOrKey, + ukm [1] EXPLICIT UserKeyingMaterial OPTIONAL, + keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier, + recipientEncryptedKeys RecipientEncryptedKeys } + + OriginatorIdentifierOrKey ::= CHOICE { + issuerAndSerialNumber IssuerAndSerialNumber, + subjectKeyIdentifier [0] KeyIdentifier, --MB;SubjectKeyIdentifier, + originatorKey [1] OriginatorPublicKey } + + OriginatorPublicKey ::= SEQUENCE { + algorithm AlgorithmIdentifier, + publicKey BIT STRING } + + RecipientEncryptedKeys ::= SEQUENCE OF RecipientEncryptedKey + + RecipientEncryptedKey ::= SEQUENCE { + rid KeyAgreeRecipientIdentifier, + encryptedKey EncryptedKey } + + KeyAgreeRecipientIdentifier ::= CHOICE { + issuerAndSerialNumber IssuerAndSerialNumber, + rKeyId [0] IMPLICIT RecipientKeyIdentifier } + + + + + RecipientKeyIdentifier ::= SEQUENCE { + subjectKeyIdentifier KeyIdentifier, --MB;SubjectKeyIdentifier, + date GeneralizedTime OPTIONAL, + other OtherKeyAttribute OPTIONAL } + + --MB;SubjectKeyIdentifier ::= OCTET STRING + + KEKRecipientInfo ::= SEQUENCE { + version CMSVersion, -- always set to 4 + kekid KEKIdentifier, + keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier, + encryptedKey EncryptedKey } + + KEKIdentifier ::= SEQUENCE { + keyIdentifier OCTET STRING, + date GeneralizedTime OPTIONAL, + other OtherKeyAttribute OPTIONAL } + + DigestedData ::= SEQUENCE { + version CMSVersion, + digestAlgorithm DigestAlgorithmIdentifier, + encapContentInfo EncapsulatedContentInfo, + digest Digest } + + Digest ::= OCTET STRING + + EncryptedData ::= SEQUENCE { + version CMSVersion, + encryptedContentInfo EncryptedContentInfo } + + AuthenticatedData ::= SEQUENCE { + version CMSVersion, + originatorInfo [0] IMPLICIT OriginatorInfo OPTIONAL, + recipientInfos RecipientInfos, + macAlgorithm MessageAuthenticationCodeAlgorithm, + digestAlgorithm [1] DigestAlgorithmIdentifier OPTIONAL, + encapContentInfo EncapsulatedContentInfo, + authenctiatedAttributes [2] IMPLICIT Attributes OPTIONAL, --MB;AuthAttributes OPTIONAL, + mac MessageAuthenticationCode, + unauthenticatedAttributes [3] IMPLICIT Attributes OPTIONAL } --MB;UnauthAttributes OPTIONAL } + + --MB;AuthAttributes ::= SET SIZE (1..MAX) OF Attribute + + --MB;UnauthAttributes ::= SET SIZE (1..MAX) OF Attribute + + MessageAuthenticationCode ::= OCTET STRING + + DigestAlgorithmIdentifier ::= AlgorithmIdentifier + + + + SignatureAlgorithmIdentifier ::= AlgorithmIdentifier + + KeyEncryptionAlgorithmIdentifier ::= AlgorithmIdentifier + + ContentEncryptionAlgorithmIdentifier ::= AlgorithmIdentifier + + MessageAuthenticationCodeAlgorithm ::= AlgorithmIdentifier + + CertificateRevocationLists ::= SET OF CertificateList + + CertificateChoices ::= CHOICE { + certificate Certificate, -- See X.509 + extendedCertificate [0] IMPLICIT ExtendedCertificate, -- Obsolete + attrCert [1] IMPLICIT AttributeCertificate } -- See X.509 & X9.57 + + CertificateSet ::= SET OF CertificateChoices + + IssuerAndSerialNumber ::= SEQUENCE { + issuer Name, + serialNumber CertificateSerialNumber } + + CMSVersion ::= INTEGER { v0(0), v1(1), v2(2), v3(3), v4(4) } + + UserKeyingMaterial ::= OCTET STRING + + UserKeyingMaterials ::= SET SIZE (1..MAX) OF UserKeyingMaterial + + OtherKeyAttribute ::= SEQUENCE { + keyAttrId OBJECT IDENTIFIER, + keyAttr ANY OPTIONAL } --RWC;DEFINED BY keyAttrId OPTIONAL } + + + -- CMS Attributes + + MessageDigest ::= OCTET STRING + + SigningTime ::= Time + + --MB;Time ::= CHOICE { + --MB; utcTime UTCTime, + --MB; generalTime GeneralizedTime } + + Countersignature ::= SignerInfo + + + + -- Algorithm Identifiers + + sha-1 OBJECT IDENTIFIER ::= { 1 3 14 3 2 26 } --MB;{ iso(1) identified-organization(3) + --MB;oiw(14) secsig(3) algorithm(2) 26 } + + --MB;md5 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) + --MB; rsadsi(113549) digestAlgorithm(2) 5 } + + id-dsa-with-sha1 OBJECT IDENTIFIER ::= { 1 2 840 10040 4 3 } --MB;{ iso(1) member-body(2) + --MB;us(840) x9-57 (10040) x9cm(4) 3 } + + --MB;rsaEncryption OBJECT IDENTIFIER ::= { iso(1) member-body(2) + --MB; us(840) rsadsi(113549) pkcs(1) pkcs-1(1) 1 } + + dh-public-number OBJECT IDENTIFIER ::= { 1 2 840 10046 2 1 } --MB;{ iso(1) member-body(2) + --MB;us(840) ansi-x942(10046) number-type(2) 1 } + + id-alg-ESDH OBJECT IDENTIFIER ::= { pkcs 9 16 3 5 } --MB;{ iso(1) member-body(2) us(840) + --MB;rsadsi(113549) pkcs(1) pkcs-9(9) smime(16) alg(3) 5 } + + id-alg-CMS3DESwrap OBJECT IDENTIFIER ::= { pkcs 9 16 3 6 } --MB;{ iso(1) member-body(2) + --MB;us(840) rsadsi(113549) pkcs(1) pkcs-9(9) smime(16) alg(3) 6 } + + id-alg-CMSRC2wrap OBJECT IDENTIFIER ::= { pkcs 9 16 3 7 } --MB;{ iso(1) member-body(2) + --MB;us(840) rsadsi(113549) pkcs(1) pkcs-9(9) smime(16) alg(3) 7 } + + des-ede3-cbc OBJECT IDENTIFIER ::= { rsadsi 3 7 } --MB;{ iso(1) member-body(2) + --MB;us(840) rsadsi(113549) encryptionAlgorithm(3) 7 } + + rc2-cbc OBJECT IDENTIFIER ::= { rsadsi 3 2 } --MB;{ iso(1) member-body(2) us(840) + --MB;rsadsi(113549) encryptionAlgorithm(3) 2 } + + hMAC-SHA1 OBJECT IDENTIFIER ::= { 1 3 6 1 5 5 8 1 2 } --MB;{ iso(1) identified-organization(3) + --MB;dod(6) internet(1) security(5) mechanisms(5) 8 1 2 } + + -- some more algorithms added by dmitch + + rc2-ecb OBJECT IDENTIFIER ::= { rsadsi 3 3 } + + rc4 OBJECT IDENTIFIER ::= { rsadsi 3 4 } + + rc4WithMAC OBJECT IDENTIFIER ::= { rsadsi 3 5 } + + desx-CBC OBJECT IDENTIFIER ::= { rsadsi 3 6 } + + rc5CBC OBJECT IDENTIFIER ::= { rsadsi 3 8 } + + rc5-CBCPad OBJECT IDENTIFIER ::= { rsadsi 3 9 } + + desCDMF OBJECT IDENTIFIER ::= { rsadsi 3 10 } + + -- this is the OID used by BSAFE when generating DSA keys. It is not + -- the same as id_dsa from sm_x501ud... + + dsa-bsafe OBJECT IDENTIFIER ::= {1 3 14 3 2 12} + + -- end of dmitch addenda + + + -- Algorithm Parameters + + KeyWrapAlgorithm ::= AlgorithmIdentifier + + RC2wrapParameter ::= RC2ParameterVersion + + RC2ParameterVersion ::= INTEGER + + CBCParameter ::= IV + + IV ::= OCTET STRING -- exactly 8 octets + + RC2CBCParameter ::= SEQUENCE { + rc2ParameterVersion INTEGER, + iv OCTET STRING } -- exactly 8 octets + + + -- Content Type Object Identifiers + + id-data OBJECT IDENTIFIER ::= { pkcs 7 1 } --MB; { iso(1) member-body(2) + --MB;us(840) rsadsi(113549) pkcs(1) pkcs7(7) 1 } + + id-signedData OBJECT IDENTIFIER ::= { pkcs 7 2 } --MB;{ iso(1) member-body(2) + --MB;us(840) rsadsi(113549) pkcs(1) pkcs7(7) 2 } + + id-envelopedData OBJECT IDENTIFIER ::= { pkcs 7 3 } --MB;{ iso(1) member-body(2) + --MB;us(840) rsadsi(113549) pkcs(1) pkcs7(7) 3 } + + id-digestedData OBJECT IDENTIFIER ::= { pkcs 7 5 } --MB;{ iso(1) member-body(2) + --MB;us(840) rsadsi(113549) pkcs(1) pkcs7(7) 5 } + + id-encryptedData OBJECT IDENTIFIER ::= { pkcs 7 6 } --MB;{ iso(1) member-body(2) + --MB;us(840) rsadsi(113549) pkcs(1) pkcs7(7) 6 } + + id-ct-authData OBJECT IDENTIFIER ::= { pkcs 9 16 1 2 } --MB;{ iso(1) member-body(2) + --MB;us(840) rsadsi(113549) pkcs(1) pkcs-9(9) smime(16) + --MB;ct(1) 2 } + + + -- Attribute Object Identifiers + + id-contentType OBJECT IDENTIFIER ::= { pkcs 9 3 } --MB;{ iso(1) member-body(2) + --MB;us(840) rsadsi(113549) pkcs(1) pkcs9(9) 3 } + + id-messageDigest OBJECT IDENTIFIER ::= { pkcs 9 4 } --MB;{ iso(1) member-body(2) + --MB;us(840) rsadsi(113549) pkcs(1) pkcs9(9) 4 } + + id-signingTime OBJECT IDENTIFIER ::= { pkcs 9 5 } --MB;{ iso(1) member-body(2) + --MB;us(840) rsadsi(113549) pkcs(1) pkcs9(9) 5 } + + id-countersignature OBJECT IDENTIFIER ::= { pkcs 9 6 } --MB;{ iso(1) member-body(2) + --MB;us(840) rsadsi(113549) pkcs(1) pkcs9(9) 6 } + + + -- Obsolete Extended Certificate syntax from PKCS#6 + + ExtendedCertificateOrCertificate ::= CHOICE { + certificate Certificate, + extendedCertificate [0] IMPLICIT ExtendedCertificate } + + ExtendedCertificate ::= SEQUENCE { + extendedCertificateInfo ExtendedCertificateInfo, + signatureAlgorithm SignatureAlgorithmIdentifier, + signature Signature } + + ExtendedCertificateInfo ::= SEQUENCE { + version CMSVersion, + certificate Certificate, + attributes Attributes } --MB;UnauthAttributes } + + Signature ::= BIT STRING + + + + -- Everything below this line is not part of draft-ietf-smime-cms-13.txt + + + -- Attribute Object Identifiers + + id-macValue OBJECT IDENTIFIER ::= { pkcs 9 16 2 8 } --MB;{ iso(1) member-body(2) + --MB;us(840) rsadsi(113549) pkcs(1) pkcs9(9) smime(16) aa(2) 8 } + + + -- Algorithm Identifiers + + id-dsa OBJECT IDENTIFIER ::= { 1 2 840 10040 4 1 } --MB;{iso(1) member-body(2) + --MB;us(840) x9-57(10040) x9cm(4) 1 } + + + -- Content Encryption Algorithms + -- For the effective-key-bits (key size) greater than 32 and less + -- than 256, the RC2-CBC algorithm parameters are encoded as: + -- RC2-CBC parameter ::= SEQUENCE { + -- rc2ParameterVersion INTEGER, + -- iv OCTET STRING (8) } + -- For the effective-key-bits of 40, 64, and 128, the + -- rc2ParameterVersion values are 160, 120, 58 respectively. + + + -- Normally in PKCS#7 + DigestInfo ::= SEQUENCE { -- Defined in PKCS#7 but not IETF-CMS + digestAlgorithm DigestAlgorithmIdentifier, + digest Digest } + + + END -- of CryptographicMessageSyntax diff --git a/libsecurity_asn1/asn1/sm_ess.asn b/libsecurity_asn1/asn1/sm_ess.asn new file mode 100644 index 00000000..f90e24e7 --- /dev/null +++ b/libsecurity_asn1/asn1/sm_ess.asn @@ -0,0 +1,238 @@ +-- @(#) sm_ess.asn 1.13 12/17/98 14:17:02 +-- FROM ess.txt: draft-ietf-smime-ess-09.txt +ExtendedSecurityServices + { 1 2 840 113549 1 9 16 0 2 } --MB;{ iso(1) member-body(2) us(840) rsadsi(113549) + --MB; pkcs(1) pkcs-9(9) smime(16) modules(0) ess(2) } + +DEFINITIONS IMPLICIT TAGS ::= +BEGIN + +IMPORTS + + KeyIdentifier, PolicyQualifierInfo, PolicyInformation, CertPolicyId + FROM CertificateExtensions + + pkcs-9 + FROM PKCS9-OIDS + +-- Cryptographic Message Syntax (CMS) + ContentType, IssuerAndSerialNumber, CMSVersion + FROM CryptographicMessageSyntax { 1 2 840 113549 1 9 16 0 1 } + --RWC;iso(1) member-body(2) us(840) + --RWC;rsadsi(113549) pkcs(1) pkcs-9(9) smime(16) modules(0) cms(1)} + +-- PKIX Certificate and CRL Profile, Sec A.2 Implicitly Tagged Module, +-- 1988 Syntax + --RWC;PolicyInformation FROM PKIX1Implicit88 {iso(1) RWC; Added ")" + --RWC;identified-organization(3)dod(6) internet(1) security(5) + --RWC;mechanisms(5) pkix(7)id-mod(0) id-pkix1-implicit-88(2)} + +-- X.509 + --RWC;GeneralNames, CertificateSerialNumber FROM CertificateExtensions RWC; Removed "," + --RWC;{joint-iso-ccitt ds(5) module(1) certificateExtensions(26) 0} + + ub-security-categories, ub-privacy-mark-length, ub-integer-options FROM UpperBounds + -- RWC; Added to avoid SNACC ASN.1 Compiler link errors. + + CertificateSerialNumber, IssuerSerial + FROM AuthenticationFramework --RWC; Added + + GeneralNames FROM CommonX509Definitions ; --RWC; Added + + +-- Extended Security Services + +-- The construct "SEQUENCE SIZE (1..MAX) OF" appears in several ASN.1 +-- constructs in this module. A valid ASN.1 SEQUENCE can have zero or +-- more entries. The SIZE (1..MAX) construct constrains the SEQUENCE to +-- have at least one entry. MAX indicates the upper bound is unspecified. +-- Implementations are free to choose an upper bound that suits their +-- environment. + +-- Section 2.7 + +ReceiptRequest ::= SEQUENCE { + signedContentIdentifier ContentIdentifier, + receiptsFrom ReceiptsFrom, + receiptsTo SEQUENCE SIZE (1..ub-receiptsTo) OF GeneralNames } + +ub-receiptsTo INTEGER ::= 16 + +smime OBJECT IDENTIFIER ::= { pkcs-9 smime(16) } + +id-aa OBJECT IDENTIFIER ::= { pkcs-9 smime(16) 2 } + +id-aa-receiptRequest OBJECT IDENTIFIER ::= { id-aa 1 } + +ContentIdentifier ::= OCTET STRING + +id-aa-contentIdentifier OBJECT IDENTIFIER ::= { id-aa 7 } + +ReceiptsFrom ::= CHOICE { + allOrFirstTier [0] AllOrFirstTier, + -- formerly "allOrNone [0]AllOrNone" + receiptList [1] SEQUENCE OF GeneralNames } + +AllOrFirstTier ::= INTEGER { -- Formerly AllOrNone + allReceipts (0), + firstTierRecipients (1) } + + +-- Section 2.8 + +Receipt ::= SEQUENCE { + version CMSVersion, -- Version is imported from [CMS] + contentType ContentType, + signedContentIdentifier ContentIdentifier, + originatorSignatureValue OCTET STRING } + +id-ct-receipt OBJECT IDENTIFIER ::= { smime id-ct(1) 1 } + +-- Section 2.9 + +ContentHints ::= SEQUENCE { + contentDescription UTF8String OPTIONAL, --RWC;SIZE (1..MAX) OPTIONAL, + contentType ContentType } + +id-aa-contentHint OBJECT IDENTIFIER ::= { id-aa 4 } + +-- Section 2.10 + +MsgSigDigest ::= OCTET STRING + +id-aa-msgSigDigest OBJECT IDENTIFIER ::= { id-aa 5 } + +-- Section 2.11 + +ContentReference ::= SEQUENCE { + contentType ContentType, + signedContentIdentifier ContentIdentifier, + originatorSignatureValue OCTET STRING } + +id-aa-contentReference OBJECT IDENTIFIER ::= { id-aa 10 } + + +-- Section 3.2 + +ESSSecurityLabel ::= SET { + security-policy-identifier SecurityPolicyIdentifier, + security-classification SecurityClassification OPTIONAL, + privacy-mark ESSPrivacyMark OPTIONAL, + security-categories SecurityCategories OPTIONAL } + +id-aa-securityLabel OBJECT IDENTIFIER ::= { id-aa 2} + +SecurityPolicyIdentifier ::= OBJECT IDENTIFIER + +SecurityClassification ::= INTEGER { + unmarked (0), + unclassified (1), + restricted (2), + confidential (3), + secret (4), + top-secret (5) } (0..ub-integer-options) + +--RWC; IMPORTED;ub-integer-options INTEGER ::= 256 + +ESSPrivacyMark ::= CHOICE { + pStringááááá PrintableString, --RWC;SIZE (1..ub-privacy-mark-length), + utf8Stringáá UTF8String --RWC;SIZE (1..MAX) +} + +--RWC; IMPORTED;ub-privacy-mark-length INTEGER ::= 128 + +SecurityCategories ::= SET SIZE (1..ub-security-categories) OF + SecurityCategory + +--RWC; IMPORTED;ub-security-categories INTEGER ::= 64 + +SecurityCategory ::= SEQUENCE { + type [0] OBJECT IDENTIFIER, + value [1] ANY --RWC;DEFINED BY type +} + +--Note: The aforementioned SecurityCategory syntax produces identical +--hex encodings as the following SecurityCategory syntax that is +--documented in the X.411 specification: +-- +--SecurityCategory ::= SEQUENCE { +-- type [0] SECURITY-CATEGORY, +-- value [1] ANY DEFINED BY type } +-- +--SECURITY-CATEGORY MACRO ::= +--BEGIN +--TYPE NOTATION ::= type | empty +--VALUE NOTATION ::= value (VALUE OBJECT IDENTIFIER) +--END + +-- Section 3.4 + +EquivalentLabels ::= SEQUENCE OF ESSSecurityLabel + +id-aa-equivalentLabels OBJECT IDENTIFIER ::= { id-aa 9} + + +-- Section 4.4 + +MLExpansionHistory ::= SEQUENCE + SIZE (1..ub-ml-expansion-history) OF MLData + +id-aa-mlExpandHistory OBJECT IDENTIFIER ::= { id-aa 3} + +ub-ml-expansion-history INTEGER ::= 64 + +MLData ::= SEQUENCE { + mailListIdentifier EntityIdentifier, + -- EntityIdentifier is imported from [CMS] + expansionTime GeneralizedTime, + mlReceiptPolicy MLReceiptPolicy OPTIONAL } + +EntityIdentifier ::= CHOICE { + issuerAndSerialNumber IssuerAndSerialNumber, + subjectKeyIdentifier KeyIdentifier } + +MLReceiptPolicy ::= CHOICE { + none [0] NULL, + insteadOf [1] SEQUENCE SIZE (1..MAX) OF GeneralNames, + inAdditionTo [2] SEQUENCE SIZE (1..MAX) OF GeneralNames } + + +-- Section 5.4 + +SigningCertificate ::= SEQUENCE { + certs SEQUENCE OF ESSCertID, + policies SEQUENCE OF PolicyInformation OPTIONAL +} + +id-aa-signingCertificate OBJECT IDENTIFIER ::= { id-aa 4444 } --RWC;Removed } + +ESSCertID ::= SEQUENCE { + certHash CertHash, + issuerSerial IssuerSerial OPTIONAL +} + +CertHash ::= OCTET STRING -- SHA1 hash of entire certificate +--RWC; Modified "Hash" to "CertHash" to avoid crypto++ library contention. + +--RWC; +--RWC; Added for completeness +--RWC; + + + -- policyQualifierIds for Internet policy qualifiers + + id-pkix OBJECT IDENTIFIER ::= + { iso(1) identified-organization(3) dod(6) internet(1) + security(5) mechanisms(5) pkix(7) } + + 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 ) + + + + +END diff --git a/libsecurity_asn1/asn1/sm_vdatypes.asn b/libsecurity_asn1/asn1/sm_vdatypes.asn new file mode 100644 index 00000000..3fb591dc --- /dev/null +++ b/libsecurity_asn1/asn1/sm_vdatypes.asn @@ -0,0 +1,13 @@ +-- @(#) sm_vdatypes.asn 1.4 4/27/98 14:51:24 +VdaEnhancedTypes DEFINITIONS ::= +BEGIN + +-- NOTE: +-- This module contains the ASN.1 defintions for types that are not +-- supported by Snacc 1.3b1 (i.e. UniversalString) and some echanced +-- types for handling large integers. +-- + +BigIntegerStr ::= [UNIVERSAL 2] IMPLICIT OCTET STRING + +END diff --git a/libsecurity_asn1/asn1/sm_x411mtsas.asn b/libsecurity_asn1/asn1/sm_x411mtsas.asn new file mode 100644 index 00000000..8e819a0f --- /dev/null +++ b/libsecurity_asn1/asn1/sm_x411mtsas.asn @@ -0,0 +1,158 @@ +-- @(#) sm_x411mtsas.asn 1.3 2/25/98 16:39:35 +MTSAbstractService +-- { joint-iso-ccitt mhs-motis(6) mts(3) modules(0) +-- mts-abstract-service(1) } + +DEFINITIONS IMPLICIT TAGS ::= + +BEGIN + +-- Prologue + +-- Exports everything + +-- Import UpperBounds Information + +IMPORTS + ub-bit-options, ub-built-in-content-type, + ub-built-in-encoded-information-types, ub-common-name-length, + ub-content-id-length, ub-content-length, ub-content-types, + ub-country-name-alpha-length, ub-country-name-numeric-length, + ub-dl-expansions, ub-domain-defined-attribute-value-length, + ub-domain-defined-attributes, ub-domain-defined-attribute-type-length, + ub-domain-name-length, + ub-encoded-information-types, ub-extension-attributes, ub-extension-types, + ub-generation-qualifier-length, ub-given-name-length, ub-initials-length, + ub-integer-options, ub-labels-and-redirections, ub-local-id-length, + ub-mta-name-length, ub-mts-user-types, ub-numeric-user-id-length, + ub-organization-name-length, ub-organizational-unit-name-length, + ub-organizational-units, ub-password-length, ub-pds-name-length, + ub-pds-parameter-length, + ub-postal-code-length, ub-privacy-mark-length, ub-queue-size, + ub-reason-codes, ub-recipients, ub-recipient-number-for-advice-length, + ub-redirections, ub-security-categories, ub-security-labels, + ub-security-problems, ub-supplementary-info-length, ub-surname-length, + ub-terminal-id-length, ub-tsap-id-length, + ub-x121-address-length + FROM UpperBounds { upperBounds } ; + +-- O/R names + +-- not used +-- +-- ORName ::= [APPLICATION 0] SEQUENCE { +-- address COMPONENTS OF ORAddress, +-- directory-name [0] Name OPTIONAL } + +ORAddress ::= SEQUENCE { + standard-attributes StandardAttributes, + domain-defined-attributes DomainDefinedAttributes OPTIONAL, + + -- also see teletex-domain-defined-attributes + + extension-attributes ExtensionAttributes OPTIONAL } + +-- Note - The OR-address is semantically absent from the OR-name +-- if the standard-attribute sequence is empty and the +-- domain-defined-attributes and extension-attributes are both omitted. + +-- Standard attributes + +StandardAttributes ::= SEQUENCE { + country-name CountryName OPTIONAL, + administration-domain-name AdministrationDomainName OPTIONAL, + -- also see extended-network-address + network-address [0] NetworkAddress OPTIONAL, + terminal-identifier [1] TerminalIdentifier OPTIONAL, + private-domain-name [2] PrivateDomainName OPTIONAL, + --also see teletex-organization-name + organization-name [3] OrganizationName OPTIONAL, + numeric-user-identifier [4] NumericUserIdentifier OPTIONAL, + --also see teletex-personal-name + personal-name [5] PersonalName OPTIONAL, + --also see teletex-organizational-unit-names + organizational-unit-names [6] OrganizationUnitNames OPTIONAL } + + +CountryName ::= [APPLICATION 1] CHOICE { + x121-dcc-code NumericString (SIZE (ub-country-name-numeric-length)), + + iso-3166-alpha2-code PrintableString (SIZE (ub-country-name-alpha-length)) } + +AdministrationDomainName ::= [APPLICATION 2] CHOICE { + numeric NumericString (SIZE (0..ub-domain-name-length)), + printable PrintableString (SIZE (0..ub-domain-name-length)) } + +NetworkAddress ::= X121Address + +X121Address ::= NumericString (SIZE (1..ub-x121-address-length)) + +TerminalIdentifier ::= PrintableString (SIZE (1..ub-terminal-id-length)) + +PrivateDomainName ::= CHOICE { + numeric NumericString (SIZE (1. .ub-domain-name-length)), + printable PrintableString (SIZE (1..ub-domain-name-length)) } + +OrganizationName ::= PrintableString (SIZE (1..ub-organization-name-length)) + +NumericUserIdentifier ::= NumericString (SIZE (1..ub-numeric-user-id-length)) + +PersonalName ::= SET { + surname [0] PrintableString (SIZE (1..ub-surname-length)), + given-name [1] PrintableString (SIZE (1..ub-given-name-length)) OPTIONAL, + initials [2] PrintableString (SIZE (1..ub-initials-length)) OPTIONAL, + generation-qualifier [3] PrintableString + (SIZE (1..ub-generation-qualifier-length)) OPTIONAL } + +OrganizationUnitNames ::= SEQUENCE SIZE (1..ub-organizational-units) OF + OrganizationUnitName + +OrganizationUnitName ::= PrintableString + (SIZE (1..ub-organizational-unit-name-length)) + +-- Domain-defined attributes + +DomainDefinedAttributes ::= SEQUENCE SIZE (1..ub-domain-defined-attributes) + OF DomainDefinedAttribute + +DomainDefinedAttribute ::= SEQUENCE { + type PrintableString (SIZE (1..ub-domain-defined-attribute-type-length)), + value PrintableString (SIZE (1..ub-domain-defined-attribute-value-length)) } + +-- Extension attributes + +ExtensionAttributes ::= SET SIZE (1. .ub-extension-attributes) OF + ExtensionAttribute + +ExtensionAttribute ::= SEQUENCE { + extension-attribute-type [0] INTEGER, + extension-attribute-value [1] ANY } + +CommonName ::= PrintableString (SIZE (1..ub-common-name-length)) + +TeletexCommonName ::= TeletexString (SIZE (1..ub-common-name-length)) + +TeletexOrganizationalName ::= TeletexString + (SIZE (1..ub-organization-name-length)) + +TeletexPersonalName ::= SET { + surname [0] TeletexString (SIZE (1..ub-surname-length)), + given-name [1] TeletexString (SIZE (1..ub-given-name-length)) OPTIONAL, + initials [2] TeletexString (SIZE (1..ub-initials-length)) OPTIONAL, + generation-qualifier [3] TeletexString + (SIZE (1..ub-generation-qualifier-length)) OPTIONAL } + +TeletexOrganizationUnitNames ::= SEQUENCE SIZE (1..ub-organizational-units) OF + TeletexOrganizationalUnitName + +TeletexOrganizationalUnitName ::= TeletexString + (SIZE (1..ub-organizational-unit-name-length)) + +TeletexDomainDefinedAttributes ::= SEQUENCE + SIZE (1..ub-domain-defined-attributes) OF TeletexDomainDefinedAttribute + +TeletexDomainDefinedAttribute ::= SEQUENCE { + type TeletexString (SIZE (1..ub-domain-defined-attribute-type-length)), + value TeletexString (SIZE (1..ub-domain-defined-attribute-value-length)) } + +END diff --git a/libsecurity_asn1/asn1/sm_x411ub.asn b/libsecurity_asn1/asn1/sm_x411ub.asn new file mode 100644 index 00000000..2a9ed239 --- /dev/null +++ b/libsecurity_asn1/asn1/sm_x411ub.asn @@ -0,0 +1,131 @@ +-- @(#) sm_x411ub.asn 1.3 3/4/98 15:25:57 +UpperBounds +-- { joint-iso-ccitt mhs-motis(6) mts(3) modules(0) upper-bounds(3) } + +DEFINITIONS IMPLICIT TAGS ::= + +BEGIN + +-- Prologue + +-- Exports everything + +-- IMPORTS nothing + +-- Upper bounds + +ub-integer-options INTEGER ::= 256 + +ub-queue-size INTEGER ::= 2147483647 -- the largest integer in 32 bits + +ub-content-length INTEGER ::= 2147483647 -- the largest integer in 32 bits + +ub-password-length INTEGER ::= 62 + +ub-bit-options INTEGER ::= 16 + +ub-content-types INTEGER ::= 1024 + +ub-tsap-id-length INTEGER ::= 16 + +ub-recipients INTEGER ::= 32767 + +ub-content-id-length INTEGER ::= 16 + +ub-x121-address-length INTEGER ::= 15 + +ub-mts-user-types INTEGER ::= 256 + +ub-reason-codes INTEGER ::= 32767 + +ub-diagnostic-codes INTEGER ::= 32767 + +ub-supplementary-info-length INTEGER ::= 256 + +ub-extension-types INTEGER ::= 256 + +ub-recipient-number-for-advice-length INTEGER ::= 32 + +ub-content-correlator-length INTEGER ::= 512 + +ub-redirections INTEGER ::= 512 + +ub-dl-expansions INTEGER ::= 512 + +ub-built-in-content-type INTEGER ::= 32767 + +ub-local-id-length INTEGER ::= 32 + +ub-mta-name-length INTEGER ::= 32 + +ub-country-name-numeric-length INTEGER ::= 3 + +ub-country-name-alpha-length INTEGER ::= 2 + +ub-domain-name-length INTEGER ::= 16 + +ub-terminal-id-length INTEGER ::= 24 + +ub-organization-name-length INTEGER ::= 64 + +ub-numeric-user-id-length INTEGER ::= 32 + +ub-surname-length INTEGER ::= 40 + +ub-given-name-length INTEGER ::= 16 + +ub-initials-length INTEGER ::= 5 + +ub-generation-qualifier-length INTEGER ::= 3 + +ub-organizational-units INTEGER ::= 4 + +ub-organizational-unit-name-length INTEGER ::= 32 + +ub-domain-defined-attributes INTEGER ::= 4 + +ub-domain-defined-attribute-type-length INTEGER ::= 8 + +ub-domain-defined-attribute-value-length INTEGER ::= 128 + +ub-extension-attributes INTEGER ::= 256 + +ub-common-name-length INTEGER ::= 64 + +ub-pds-name-length INTEGER ::= 16 + +ub-postal-code-length INTEGER ::= 16 + +ub-pds-parameter-length INTEGER ::= 30 + +ub-physical-address-lines INTEGER ::= 6 + +ub-unformatted-address-length INTEGER ::= 180 + +ub-e163-4-number-length INTEGER ::= 15 + +ub-e163-4-sub-address-length INTEGER ::= 40 + +ub-built-in-encoded-information-types INTEGER ::= 32 + +ub-teletex-private-use-length INTEGER ::= 128 + +ub-encoded-information-types INTEGER ::= 1024 + +ub-security-labels INTEGER ::= 256 + +ub-labels-and-redirections INTEGER ::= 256 + +ub-security-problems INTEGER ::= 256 + +ub-privacy-mark-length INTEGER ::= 128 + +ub-security-categories INTEGER ::= 64 + +ub-transfers INTEGER ::= 512 + +ub-bilateral-info INTEGER ::= 1024 + +ub-additional-info INTEGER ::= 1024 + +END -- of UpperBounds diff --git a/libsecurity_asn1/asn1/sm_x501if.asn b/libsecurity_asn1/asn1/sm_x501if.asn new file mode 100644 index 00000000..2673eea4 --- /dev/null +++ b/libsecurity_asn1/asn1/sm_x501if.asn @@ -0,0 +1,48 @@ +-- @(#) sm_x501if.asn 1.2 2/24/98 13:39:21 +InformationFramework +-- +-- oid defined in sm_x501ud.asn +-- +-- { joint-iso-itu-t(1) ds(5) modules(1) informationFramework(1) 3 } +DEFINITIONS EXPLICIT TAGS ::= +BEGIN + + +-- Added this because the CMS module needs it and thinks it comes from +-- this module. +-- +-- Pierce 2/23/98 + +Attributes ::= SET OF Attribute + +AttributeType ::= OBJECT IDENTIFIER + +AttributeValue ::= ANY + +Attribute ::= SEQUENCE { + type AttributeType, + values SET OF AttributeValue +} + +Name ::= CHOICE { + rDNSequence RDNSequence +} + +DistinguishedName ::= RDNSequence + +RDNSequence ::= SEQUENCE OF RelativeDistinguishedName + +RelativeDistinguishedName ::= SET SIZE (1..MAX) OF + AttributeTypeAndDistinguishedValue + + +AttributeTypeAndDistinguishedValue ::= SEQUENCE { + type OBJECT IDENTIFIER, + value ANY, + primaryDistinguished BOOLEAN DEFAULT TRUE, + valuesWithContext SET SIZE (1 .. MAX) OF SEQUENCE { + distingAttrValue OBJECT IDENTIFIER OPTIONAL, + contextList SET SIZE (1 .. MAX) OF ANY } OPTIONAL +} + +END diff --git a/libsecurity_asn1/asn1/sm_x501ud.asn b/libsecurity_asn1/asn1/sm_x501ud.asn new file mode 100644 index 00000000..b5313955 --- /dev/null +++ b/libsecurity_asn1/asn1/sm_x501ud.asn @@ -0,0 +1,136 @@ +-- @(#) sm_x501ud.asn 1.3 3/2/98 12:55:28 +UsefulDefinitions +-- { joint-iso-ccitt ds(5) module(1) usefulDefinitions(0) 2 } +DEFINITIONS ::= + +BEGIN + +-- EXPORTS All -- + +-- The types and values defined in this module are exported for use in the +-- other ASN.1 modules contained within the Directory Specifications, and +-- for the use of other applications which will use them to access +-- Directory services. Other applications may use them for their own purposes, +-- but this will not constrain extensions and modifications needed to maintain +-- or improve the Directory service. + +ds OBJECT IDENTIFIER ::= { joint-iso-ccitt ds(5) } + +-- categories of information object + +module OBJECT IDENTIFIER ::= {ds 1} + +serviceElement OBJECT IDENTIFIER ::= {ds 2} +applicationContext OBJECT IDENTIFIER ::= {ds 3} +attributeType OBJECT IDENTIFIER ::= {ds 4} +attributeSyntax OBJECT IDENTIFIER ::= {ds 5} +objectClass OBJECT IDENTIFIER ::= {ds 6} +-- attributeSet OBJECT IDENTIFIER ::= {ds 7} +dsAlgorithm OBJECT IDENTIFIER ::= {ds 8} +abstractSyntax OBJECT IDENTIFIER ::= {ds 9} +-- object OBJECT IDENTIFIER ::= {ds 10} +-- port OBJECT IDENTIFIER ::= {ds 11} +dsaOperationalAttribute OBJECT IDENTIFIER ::= {ds 12} +matchingRule OBJECT IDENTIFIER ::= {ds 13} +knowledgeMatchingRule OBJECT IDENTIFIER ::= {ds 14} +nameForm OBJECT IDENTIFIER ::= {ds 15} +group OBJECT IDENTIFIER ::= {ds 16} +subentry OBJECT IDENTIFIER ::= {ds 17} +operationalAttributeType OBJECT IDENTIFIER ::= {ds 18} +operationalBinding OBJECT IDENTIFIER ::= {ds 19} +schemaObjectClass OBJECT IDENTIFIER ::= {ds 20} +schemaOperationalAttribute OBJECT IDENTIFIER ::= {ds 21} +administrativeRoles OBJECT IDENTIFIER ::= {ds 23} +accessControlAttribute OBJECT IDENTIFIER ::= {ds 24} +rosObject OBJECT IDENTIFIER ::= {ds 25} +contract OBJECT IDENTIFIER ::= {ds 26} +package OBJECT IDENTIFIER ::= {ds 27} +accessControlSchemes OBJECT IDENTIFIER ::= {ds 28} +certificateExtension OBJECT IDENTIFIER ::= {ds 29} +managementObject OBJECT IDENTIFIER ::= {ds 30} +-- modules -- + +-- already defined +-- +-- usefulDefinitions OBJECT IDENTIFIER ::= {module usefulDefinitions(0) 3} +informationFramework OBJECT IDENTIFIER ::= {module informationFramework(1) 3} +directoryAbstractService OBJECT IDENTIFIER ::= {module directoryAbstractService(2) 3} +distributedOperations OBJECT IDENTIFIER ::= {module distributedOperations(3) 3} +protocolObjectIdentifiers OBJECT IDENTIFIER ::= {module protocolObjectIdentifiers (4) 3} +selectedAttributeTypes OBJECT IDENTIFIER ::= {module selectedAttributeTypes(5) 3} +selectedObjectClasses OBJECT IDENTIFIER ::= {module selectedObjectClasses(6) 3} +authenticationFramework OBJECT IDENTIFIER ::= {module authenticationFramework(7) 3} +algorithmObjectIdentifiers OBJECT IDENTIFIER ::= {module algorithmObjectIdentifiers(8) 3} +directoryObjectIdentifiers OBJECT IDENTIFIER ::= {module directoryObjectIdentifiers(9) 3} +upperBounds OBJECT IDENTIFIER ::= {module upperBounds(10) 3} +dap OBJECT IDENTIFIER ::= {module dap(11) 3} + +dsp OBJECT IDENTIFIER ::= {module dsp(12) 3} +distributedDirectoryOIDs OBJECT IDENTIFIER ::= {module distributedDirectoryOIDs(13) 3} +directoryShadowOIDs OBJECT IDENTIFIER ::= {module directoryShadowOIDs(14) 3} +directoryShadowAbstractService OBJECT IDENTIFIER ::= {module directoryShadowAbstractService(15) 3} +disp OBJECT IDENTIFIER ::= {module disp(16) 3} +dop OBJECT IDENTIFIER ::= {module dop(17) 3} +opBindingManagement OBJECT IDENTIFIER ::= {module opBindingManagement(18) 3} +opBindingOIDs OBJECT IDENTIFIER ::= {module opBindingOIDs(19) 3} +hierarchicalOperationalBindings OBJECT IDENTIFIER ::= {module hierarchicalOperationalBindings(20) 3} +dsaOperationalAttributeTypes OBJECT IDENTIFIER ::= {module dsaOperationalAttributeTypes(22) 3} +schemaAdministration OBJECT IDENTIFIER ::= {module schemaAdministration(23) 3} +basicAccessControl OBJECT IDENTIFIER ::= {module basicAccessControl(24) 3} +directoryOperationalBindingTypes OBJECT IDENTIFIER ::= {module directoryOperationalBindingTypes(25) 3} +certificateExtensions OBJECT IDENTIFIER ::= {module certificateExtensions (26) 0} +directoryManagement OBJECT IDENTIFIER ::= {module directoryManagement (27) 1} +enhancedSecurity OBJECT IDENTIFIER ::= {module enhancedSecurity (28) } + + +-- synonyms -- +id-oc OBJECT IDENTIFIER ::= objectClass +id-at OBJECT IDENTIFIER ::= attributeType +id-as OBJECT IDENTIFIER ::= abstractSyntax +id-mr OBJECT IDENTIFIER ::= matchingRule +id-nf OBJECT IDENTIFIER ::= nameForm +id-sc OBJECT IDENTIFIER ::= subentry +id-oa OBJECT IDENTIFIER ::= operationalAttributeType +id-ob OBJECT IDENTIFIER ::= operationalBinding +id-doa OBJECT IDENTIFIER ::= dsaOperationalAttribute +id-kmr OBJECT IDENTIFIER ::= knowledgeMatchingRule +id-soc OBJECT IDENTIFIER ::= schemaObjectClass +id-soa OBJECT IDENTIFIER ::= schemaOperationalAttribute +id-ar OBJECT IDENTIFIER ::= administrativeRoles +id-aca OBJECT IDENTIFIER ::= accessControlAttribute +id-ac OBJECT IDENTIFIER ::= applicationContext +id-rosObject OBJECT IDENTIFIER ::= rosObject +id-contract OBJECT IDENTIFIER ::= contract +id-package OBJECT IDENTIFIER ::= package +id-acScheme OBJECT IDENTIFIER ::= accessControlSchemes +id-ce OBJECT IDENTIFIER ::= certificateExtension +id-mgt OBJECT IDENTIFIER ::= managementObject +-- obsolete module identifiers -- +-- usefulDefinitions OBJECT IDENTIFIER ::= {module 0} +-- informationFramework OBJECT IDENTIFIER ::= {module 1} +-- directoryAbstractService OBJECT IDENTIFIER ::= {module 2} +-- distributedOperations OBJECT IDENTIFIER ::= {module 3} +-- protocolObjectIdentifiers OBJECT IDENTIFIER ::= {module 4} +-- selectedAttributeTypes OBJECT IDENTIFIER ::= {module 5} +-- selectedObjectClasses OBJECT IDENTIFIER ::= {module 6} +-- authenticationFramework OBJECT IDENTIFIER ::= {module 7} +-- algorithmObjectIdentifiers OBJECT IDENTIFIER ::= {module 8} +-- directoryObjectIdentifiers OBJECT IDENTIFIER ::= {module 9} +-- upperBounds OBJECT IDENTIFIER ::= {module 10} +-- dap OBJECT IDENTIFIER ::= {module 11} +-- dsp OBJECT IDENTIFIER ::= {module 12} +-- distributedDirectoryObjectIdentifiers +-- OBJECT IDENTIFIER ::= {module 13} +-- unused module identifiers -- +-- directoryShadowOIDs OBJECT IDENTIFIER ::= {module 14} +-- directoryShadowAbstractService OBJECT IDENTIFIER ::= {module 15} +-- disp OBJECT IDENTIFIER ::= {module 16} +-- dop OBJECT IDENTIFIER ::= {module 17} +-- opBindingManagement OBJECT IDENTIFIER ::= {module 18} +-- opBindingOIDs OBJECT IDENTIFIER ::= {module 19} +-- hierarchicalOperationalBindings OBJECT IDENTIFIER ::= {module 20} +-- dsaOperationalAttributeTypes OBJECT IDENTIFIER ::= {module 22} +-- schemaAdministration OBJECT IDENTIFIER ::= {module 23} +-- basicAccessControl OBJECT IDENTIFIER ::= {module 24} +-- operationalBindingOIDs OBJECT IDENTIFIER ::= {module 25} +END diff --git a/libsecurity_asn1/asn1/sm_x509af.asn b/libsecurity_asn1/asn1/sm_x509af.asn new file mode 100644 index 00000000..ec2f40dc --- /dev/null +++ b/libsecurity_asn1/asn1/sm_x509af.asn @@ -0,0 +1,225 @@ +-- @(#) sm_x509af.asn 1.2 2/24/98 13:40:34 +AuthenticationFramework +-- +-- oid defined in sm_x501ud.asn +-- +-- {joint-iso-ccitt ds(5) module(1) authenticationFramework(7) 3} + +DEFINITIONS ::= + +BEGIN + +-- EXPORTS All -- +-- The types and values defined in this module are exported for use in the +-- other ASN.1 modules contained +-- within the Directory Specifications, and for the use of other applications +-- which will use them to access Directory services. Other applications may +-- use them for their own purposes, but this will not constrain +-- extensions and modifications needed to maintain or improve the Directory +-- service. + +IMPORTS + + BigIntegerStr + FROM VdaEnhancedTypes + + id-at, informationFramework, upperBounds, selectedAttributeTypes, + basicAccessControl, certificateExtensions + FROM UsefulDefinitions { usefulDefinitions } + + Name, Attribute, AttributeType + FROM InformationFramework { informationFramework } + + ub-password-length + FROM UpperBounds { upperBounds } + +-- not used +-- AuthenticationLevel +-- FROM BasicAccessControl { basicAccessControl } + +-- GeneralNames +-- FROM CertificateExtensions { certificateExtensions } + + GeneralNames + FROM CommonX509Definitions + + UniqueIdentifier + FROM SelectedAttributeTypes { selectedAttributeTypes } ; + +-- basic certificate definition + +Certificate ::= SEQUENCE { + certificateToSign CertificateToSign, + algorithmIdentifier AlgorithmIdentifier, + signatureValue BIT STRING } + +CertificateToSign ::= SEQUENCE { + version [0] Version DEFAULT v1, + serialNumber CertificateSerialNumber, + signature AlgorithmIdentifier, + issuer Name, + validity Validity, + subject Name, + subjectPublicKeyInfo SubjectPublicKeyInfo, + -- if present, version must be v2 or v3 + issuerUniqueIdentifier [1] IMPLICIT UniqueIdentifier OPTIONAL, + -- if present, version must be v2 or v3 + subjectUniqueIdentifier [2] IMPLICIT UniqueIdentifier OPTIONAL, + -- If present, version must be v3 + extensions [3] Extensions OPTIONAL } + +Version ::= INTEGER { v1(0), v2(1), v3(2) } + +-- CertificateSerialNumber ::= INTEGER + +CertificateSerialNumber ::= BigIntegerStr + + +AlgorithmIdentifier ::= SEQUENCE { + algorithm OBJECT IDENTIFIER, + parameters ANY OPTIONAL } + +Validity ::= SEQUENCE { + notBefore Time, + notAfter Time } + +SubjectPublicKeyInfo ::= SEQUENCE { + algorithm AlgorithmIdentifier, + subjectPublicKey BIT STRING } + +Time ::= CHOICE { + utcTime UTCTime, + generalizedTime GeneralizedTime } + +Extensions ::= SEQUENCE OF Extension + +-- For those extensions where ordering of individual extensions within the +-- SEQUENCE is significant, the specification of those individual extensions +-- shall include the rules for the significance of the order therein + +Extension ::= SEQUENCE { + extnId OBJECT IDENTIFIER, + critical BOOLEAN DEFAULT FALSE, + -- extnValue contains a DER encoding + extnValue OCTET STRING } + +-- other certifiate constructs + +Certificates ::= SEQUENCE { + userCertificate Certificate, + certificationPath ForwardCertificationPath OPTIONAL } + +ForwardCertificationPath ::= SEQUENCE OF CrossCertificates + +CrossCertificates ::= SET OF Certificate + +CertificationPath ::= SEQUENCE { + userCertificate Certificate, + theCACertificates SEQUENCE OF CertificatePair OPTIONAL } + +CertificatePair ::= SEQUENCE { + -- at least one of the pair shall be present + forward [0] Certificate OPTIONAL, + reverse [1] Certificate OPTIONAL } + +-- certificate revocation list (CRL) + +CertificateList ::= SEQUENCE { + crlToSign CRLToSign, + algorithmIdentifier AlgorithmIdentifier, + signatureValue BIT STRING } + +CRLToSign ::= SEQUENCE { + version Version OPTIONAL, -- if present, version must be v2 + signature AlgorithmIdentifier, + issuer Name, + thisUpdate Time, + nextUpdate Time OPTIONAL, + revokedCertificates SEQUENCE OF SEQUENCE { + userCertificate CertificateSerialNumber, + revocationDate Time, + crlEntryExtensions Extensions OPTIONAL } OPTIONAL, + crlExtensions [0] Extensions OPTIONAL } + +-- attribute certificate +AttributeCertificationPath ::= SEQUENCE { + attributeCertificate AttributeCertificate, + acPath SEQUENCE OF ACPathData OPTIONAL } + +ACPathData ::= SEQUENCE { + certificate [0] Certificate OPTIONAL, + attributeCertificate [1] AttributeCertificate OPTIONAL } + +AttributeCertificate ::= SEQUENCE { + attributeCertificateInfo AttributeCertificateInfo, + algorithmIdentifier AlgorithmIdentifier, + signatureValue BIT STRING } + +AttributeCertificateInfo ::= SEQUENCE { + version Version DEFAULT v1, + subject CHOICE { + baseCertificateID [0] IssuerSerial, -- associated with a Public Key + -- Certificate + subjectName [1] GeneralNames }, -- associated with a name + issuer GeneralNames, -- CA issuing the attribute certificate + signature AlgorithmIdentifier, + serialNumber CertificateSerialNumber, + attCertValidityPeriod AttCertValidityPeriod, + attributes SEQUENCE OF Attribute, + issuerUniqueID UniqueIdentifier OPTIONAL, + extensions Extensions OPTIONAL } + +IssuerSerial ::= SEQUENCE { + issuer GeneralNames, + serial CertificateSerialNumber, + issuerUID UniqueIdentifier OPTIONAL} + +AttCertValidityPeriod ::= SEQUENCE { + notBeforeTime GeneralizedTime, + notAfterTime GeneralizedTime } + +AttributeCertificateAssertion ::= SEQUENCE { + -- At least one component of the sequence must be present + subject [0] CHOICE { + baseCertificateID [0] IssuerSerial, + subjectName [1] Name } OPTIONAL, + issuer [1] Name OPTIONAL, + attCertValidity [2] GeneralizedTime OPTIONAL, + attType [3] SET OF AttributeType OPTIONAL } + +-- Apple addenda: abstract "signed CRL or cert". In this case the blob to be +-- signed is actually an encoded CertificateToSign or CRLToSign. Representing +-- that blob as an ASN ANY field allows for signature verify without decoding +-- the entire CertificateToSign or CRLToSign. + +SignedCertOrCrl ::= SEQUENCE { + tbsBlob ANY, + algIdBlob ANY, + signatureValue BIT STRING } + +-- attribute types -- + +UserPassword ::= OCTET STRING (SIZE (0..ub-password-length)) + +UserCertificate ::= Certificate + +CACertificate ::= Certificate + +CrossCertificatePair ::= CertificatePair + +AuthorityRevocationList ::= CertificateList + +CertificateRevocationList ::= CertificateList + +AttributeCertificateRevocationList ::= CertificateList + +-- object identifier assignments -- +id-at-userPassword OBJECT IDENTIFIER ::= {id-at 35} +id-at-userCertificate OBJECT IDENTIFIER ::= {id-at 36} +id-at-cAcertificate OBJECT IDENTIFIER ::= {id-at 37} +id-at-authorityRevocationList OBJECT IDENTIFIER ::= {id-at 38} +id-at-certificateRevocationList OBJECT IDENTIFIER ::= {id-at 39} +id-at-crossCertificatePair OBJECT IDENTIFIER ::= {id-at 40} +id-at-attributeCertificate OBJECT IDENTIFIER ::= {id-at 58} + +END diff --git a/libsecurity_asn1/asn1/sm_x509ce.asn b/libsecurity_asn1/asn1/sm_x509ce.asn new file mode 100644 index 00000000..b096a241 --- /dev/null +++ b/libsecurity_asn1/asn1/sm_x509ce.asn @@ -0,0 +1,265 @@ +-- @(#) sm_x509ce.asn 1.3 3/4/98 15:25:14 +CertificateExtensions +-- +-- oid defined sm_x501ud.asn +-- {joint-iso-ccitt ds(5) module(1) certificateExtensions(26) 0} + +DEFINITIONS IMPLICIT TAGS ::= + +BEGIN + +-- EXPORTS ALL + +IMPORTS + id-at, id-ce, id-mr, informationFramework, authenticationFramework, + selectedAttributeTypes, upperBounds + FROM UsefulDefinitions { usefulDefinitions } + + Name, RelativeDistinguishedName, Attribute + FROM InformationFramework { informationFramework } + + GeneralNames, GeneralName + FROM CommonX509Definitions + + CertificateSerialNumber, CertificateList, AlgorithmIdentifier + FROM AuthenticationFramework { authenticationFramework } + + DirectoryString + FROM SelectedAttributeTypes { selectedAttributeTypes } + + ORAddress + FROM MTSAbstractService { mTSAbstractService } + + id-pkix + FROM ExtendedSecurityServices { extendedSecurityServices }; + +-- Unless explicitly noted otherwise, there is no significance to the ordering +-- of components of a SEQUENCE OF construct in this specification. + +-- Key and policy information extensions -- + +AuthorityKeyIdentifier ::= SEQUENCE { + keyIdentifier [0] KeyIdentifier OPTIONAL, + authorityCertIssuer [1] GeneralNames OPTIONAL, + authorityCertSerialNumber [2] CertificateSerialNumber OPTIONAL } + +KeyIdentifier ::= OCTET STRING + +SubjectKeyIdentifier ::= KeyIdentifier + +KeyUsage ::= BIT STRING { + digitalSignature (0), + nonRepudiation (1), + keyEncipherment (2), + dataEncipherment (3), + keyAgreement (4), + keyCertSign (5), + cRLSign (6), + encipherOnly (7), + decipherOnly (8) } + +KeyPurposeId ::= OBJECT IDENTIFIER + +-- Added 9/14/00 by dmitch +ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId + +PrivateKeyUsagePeriod ::= SEQUENCE { + notBefore [0] GeneralizedTime OPTIONAL, + notAfter [1] GeneralizedTime OPTIONAL } + ( WITH COMPONENTS {..., notBefore PRESENT} | + WITH COMPONENTS {..., notAfter PRESENT} ) + + +CertificatePoliciesSyntax ::= SEQUENCE SIZE (1..MAX) OF PolicyInformation + +PolicyInformation ::= SEQUENCE { + policyIdentifier CertPolicyId, + policyQualifiers SEQUENCE SIZE (1..MAX) OF PolicyQualifierInfo OPTIONAL } + +CertPolicyId ::= OBJECT IDENTIFIER + +PolicyQualifierInfo ::= SEQUENCE { + policyQualifierId OBJECT IDENTIFIER, + qualifier ANY OPTIONAL } + +PolicyMappingsSyntax ::= SEQUENCE SIZE (1..MAX) OF SEQUENCE { + issuerDomainPolicy CertPolicyId, + subjectDomainPolicy CertPolicyId } + +SupportedAlgorithm ::= SEQUENCE { + algorithmIdentifier AlgorithmIdentifier, + intendedUsage [0] KeyUsage OPTIONAL, + intendedCertificatePolicies [1] CertificatePoliciesSyntax OPTIONAL } + +-- Certificate subject and certificate issuer attributes extensions -- + +SubjectName ::= GeneralNames + +-- moved to sm_x509cmn.asn since both sm_x509af.asn and sm_x509ce.asn need +-- it +-- +-- GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName + +-- GeneralName ::= CHOICE { +-- otherName [0] OTHER-NAME, + -- 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 } +-- +-- OTHER-NAME ::= OBJECT IDENTIFIER + +-- EDIPartyName ::= SEQUENCE { + -- nameAssigner [0] DirectoryString OPTIONAL, + -- partyName [1] DirectoryString } +-- + +IssuerAltName ::= GeneralNames + +SubjectDirectoryAttributes ::= AttributesSyntax + +AttributesSyntax ::= SEQUENCE SIZE (1..MAX) OF Attribute + + +-- Certification path constraints extensions -- + +BasicConstraintsSyntax ::= SEQUENCE { + cA BOOLEAN DEFAULT FALSE, + pathLenConstraint INTEGER (0..MAX) OPTIONAL } + +NameConstraintsSyntax ::= 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) + +PolicyConstraintsSyntax ::= SEQUENCE { + requireExplicitPolicy [0] SkipCerts OPTIONAL, + inhibitPolicyMapping [1] SkipCerts OPTIONAL } + +SkipCerts ::= INTEGER (0..MAX) + +CertPolicySet ::= SEQUENCE OF CertPolicyId + +-- Basic CRL extensions -- + +CRLNumber ::= INTEGER (0..MAX) + +CRLReason ::= ENUMERATED { + unspecified (0), + keyCompromise (1), + cACompromise (2), + affiliationChanged (3), + superseded (4), + cessationOfOperation (5), + certificateHold (6), -- note 7 is not used by this spec. + removeFromCRL (8) } + +HoldInstruction ::= OBJECT IDENTIFIER + + +InvalidityDate ::= GeneralizedTime + +-- CRL distribution points and delta-CRL extensions -- + +CRLDistPointsSyntax ::= SEQUENCE SIZE (1..MAX) OF DistributionPoint + +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) } + +IssuingDistPointSyntax ::= SEQUENCE { + distributionPoint [0] DistributionPointName OPTIONAL, + onlyContainsUserCerts [1] BOOLEAN DEFAULT FALSE, + onlyContainsCACerts [2] BOOLEAN DEFAULT FALSE, + onlySomeReasons [3] ReasonFlags OPTIONAL, + indirectCRL [4] BOOLEAN DEFAULT FALSE } + +CertificateIssuer ::= GeneralNames + +BaseCRLNumber ::= CRLNumber + +DeltaRevocationList ::= CertificateList + +-- Matching rules + +-- removed. Our ASN.1 compiler does not support matching ruling. We will +-- do this manually -Pierce +-- + +-- end of Matching rules + +-- Object identifier assignments -- + +id-at-supportedAlgorithms OBJECT IDENTIFIER ::= {id-at 52} +id-at-deltaRevocationList OBJECT IDENTIFIER ::= {id-at 53} +id-ce-subjectDirectoryAttributes OBJECT IDENTIFIER ::= {id-ce 9} +id-ce-subjectKeyIdentifier OBJECT IDENTIFIER ::= {id-ce 14} +id-ce-keyUsage OBJECT IDENTIFIER ::= {id-ce 15} +id-ce-privateKeyUsagePeriod OBJECT IDENTIFIER ::= {id-ce 16} +id-ce-subjectAltName OBJECT IDENTIFIER ::= {id-ce 17} +id-ce-issuerAltName OBJECT IDENTIFIER ::= {id-ce 18} +id-ce-basicConstraints OBJECT IDENTIFIER ::= {id-ce 19} +id-ce-cRLNumber OBJECT IDENTIFIER ::= {id-ce 20} +id-ce-reasonCode OBJECT IDENTIFIER ::= {id-ce 21} +id-ce-instructionCode OBJECT IDENTIFIER ::= {id-ce 23} +id-ce-invalidityDate OBJECT IDENTIFIER ::= {id-ce 24} +id-ce-deltaCRLIndicator OBJECT IDENTIFIER ::= {id-ce 27} +id-ce-issuingDistributionPoint OBJECT IDENTIFIER ::= {id-ce 28} +id-ce-certificateIssuer OBJECT IDENTIFIER ::= {id-ce 29} +id-ce-nameConstraints OBJECT IDENTIFIER ::= {id-ce 30} +id-ce-cRLDistributionPoints OBJECT IDENTIFIER ::= {id-ce 31} +id-ce-certificatePolicies OBJECT IDENTIFIER ::= {id-ce 32} +id-ce-policyMappings OBJECT IDENTIFIER ::= {id-ce 33} +-- deprecated OBJECT IDENTIFIER ::= {id-ce 34} +id-ce-authorityKeyIdentifier OBJECT IDENTIFIER ::= {id-ce 35} +id-ce-policyConstraints OBJECT IDENTIFIER ::= {id-ce 36} +id-ce-extKeyUsage OBJECT IDENTIFIER ::= {id-ce 37} +id-mr-certificateExactMatch OBJECT IDENTIFIER ::= {id-mr 34} +id-mr-certificateMatch OBJECT IDENTIFIER ::= {id-mr 35} +id-mr-certificatePairExactMatch OBJECT IDENTIFIER ::= {id-mr 36} +id-mr-certificatePairMatch OBJECT IDENTIFIER ::= {id-mr 37} +id-mr-certificateListExactMatch OBJECT IDENTIFIER ::= {id-mr 38} +id-mr-certificateListMatch OBJECT IDENTIFIER ::= {id-mr 39} +id-mr-algorithmIdentifierMatch OBJECT IDENTIFIER ::= {id-mr 40} + +id-kp OBJECT IDENTIFIER ::= {id-pkix 3} +id-kp-serverAuth OBJECT IDENTIFIER ::= {id-kp 1} +id-kp-clientAuth OBJECT IDENTIFIER ::= {id-kp 2} +id-kp-codeSigning OBJECT IDENTIFIER ::= {id-kp 3} +id-kp-emailProtection OBJECT IDENTIFIER ::= {id-kp 4} +id-kp-timeStamping OBJECT IDENTIFIER ::= {id-kp 8} + +id-netscape-cert-type OBJECT IDENTIFIER ::= {2 16 840 1 113730 1 1} + +-- The following OBJECT IDENTIFIERS are not used by this specification: +-- {id-ce 2}, {id-ce 3}, {id-ce 4}, {id-ce 5}, {id-ce 6}, {id-ce 7}, +-- {id-ce 8}, {id-ce 10}, {id-ce 11}, {id-ce 12}, {id-ce 13}, +-- {id-ce 22}, {id-ce 25}, {id-ce 26} + +END diff --git a/libsecurity_asn1/asn1/sm_x509cmn.asn b/libsecurity_asn1/asn1/sm_x509cmn.asn new file mode 100644 index 00000000..4c3a2fba --- /dev/null +++ b/libsecurity_asn1/asn1/sm_x509cmn.asn @@ -0,0 +1,44 @@ +-- @(#) sm_x509cmn.asn 1.3 3/2/98 12:56:14 +CommonX509Definitions +DEFINITIONS IMPLICIT TAGS ::= + +BEGIN + +-- EXPORTS ALL + +IMPORTS + informationFramework, selectedAttributeTypes + FROM UsefulDefinitions { usefulDefinitions } + + Name + FROM InformationFramework { informationFramework } + + DirectoryString + FROM SelectedAttributeTypes { selectedAttributeTypes } + + ORAddress + FROM MTSAbstractService { mTSAbstractService } ; + +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 } + +-- Was OID.... +OtherName ::= SEQUENCE { + typeId OBJECT IDENTIFIER, + value [0] EXPLICIT ANY } -- DEFINED BY contentType + +EDIPartyName ::= SEQUENCE { + nameAssigner [0] DirectoryString OPTIONAL, + partyName [1] DirectoryString } + +END diff --git a/libsecurity_asn1/asn1/sm_x520sa.asn b/libsecurity_asn1/asn1/sm_x520sa.asn new file mode 100644 index 00000000..6483a153 --- /dev/null +++ b/libsecurity_asn1/asn1/sm_x520sa.asn @@ -0,0 +1,196 @@ +-- @(#) sm_x520sa.asn 1.3 4/27/98 14:42:39 +SelectedAttributeTypes +-- +-- oid defined in sm_x501ud.asn +-- +-- {joint-iso-ccitt ds(5) module(1) selectedAttributeTypes(5) 2} +DEFINITIONS ::= + +BEGIN + +-- EXPORTS All -- + +-- The types and values defined in this module are exported for use in the +-- other ASN.1 modules contained +-- within the Directory Specifications, and for the use of other applications +-- which will use them to access +-- Directory services. Other applications may use them for their own purposes, +-- but this will not constrain +-- extensions and modifications needed to maintain or improve the Directory +-- service. +IMPORTS + + informationFramework, upperBounds, id-at, id-mr + FROM UsefulDefinitions { usefulDefinitions } + + AttributeType, DistinguishedName + FROM InformationFramework { informationFramework } ; + +-- Directory string type -- + +UniqueIdentifier ::= BIT STRING + +DirectoryString ::= CHOICE { + teletexString TeletexString (SIZE (1..MAX)), + printableString PrintableString (SIZE (1..MAX)), + universalString UniversalString (SIZE (1..MAX)), + bmpString BMPString (SIZE (1..MAX)), + utf8String UTF8String (SIZE (1..MAX)) } + + +-- Object identifier assignments +-- object identifiers assigned in other modules are shown in comments +-- Attributes +-- id-at-objectClass OBJECT IDENTIFIER ::= {id-at 0} +-- id-at-aliasedEntryName OBJECT IDENTIFIER ::= {id-at 1} +id-at-encryptedAliasedEntryName OBJECT IDENTIFIER ::= {id-at 1 2} +id-at-knowledgeInformation OBJECT IDENTIFIER ::= {id-at 2} +id-at-commonName OBJECT IDENTIFIER ::= {id-at 3} +id-at-encryptedCommonName OBJECT IDENTIFIER ::= {id-at 3 2} +id-at-surname OBJECT IDENTIFIER ::= {id-at 4} +id-at-encryptedSurname OBJECT IDENTIFIER ::= {id-at 4 2} +id-at-serialNumber OBJECT IDENTIFIER ::= {id-at 5} +id-at-encryptedSerialNumber OBJECT IDENTIFIER ::= {id-at 5 2} +id-at-countryName OBJECT IDENTIFIER ::= {id-at 6} +id-at-encryptedCountryName OBJECT IDENTIFIER ::= {id-at 6 2} +id-at-localityName OBJECT IDENTIFIER ::= {id-at 7} +id-at-encryptedLocalityName OBJECT IDENTIFIER ::= {id-at 7 2} +id-at-collectiveLocalityName OBJECT IDENTIFIER ::= {id-at 7 1} +id-at-encryptedCollectiveLocalityName OBJECT IDENTIFIER ::= {id-at 7 1 2} +id-at-stateOrProvinceName OBJECT IDENTIFIER ::= {id-at 8} +id-at-encryptedStateOrProvinceName OBJECT IDENTIFIER ::= {id-at 8 2} +id-at-collectiveStateOrProvinceName OBJECT IDENTIFIER ::= {id-at 8 1} +id-at-encryptedCollectiveStateOrProvinceName OBJECT IDENTIFIER ::= {id-at 8 1 2} +id-at-streetAddress OBJECT IDENTIFIER ::= {id-at 9} +id-at-encryptedStreetAddress OBJECT IDENTIFIER ::= {id-at 9 2} +id-at-collectiveStreetAddress OBJECT IDENTIFIER ::= {id-at 9 1} +id-at-encryptedCollectiveStreetAddress OBJECT IDENTIFIER ::= {id-at 9 1 2} +id-at-organizationName OBJECT IDENTIFIER ::= {id-at 10} +id-at-encryptedOrganizationName OBJECT IDENTIFIER ::= {id-at 10 2} +id-at-collectiveOrganizationName OBJECT IDENTIFIER ::= {id-at 10 1} +id-at-encryptedCollectiveOrganizationName OBJECT IDENTIFIER ::= {id-at 10 1 2} +id-at-organizationalUnitName OBJECT IDENTIFIER ::= {id-at 11} +id-at-encryptedOrganizationalUnitName OBJECT IDENTIFIER ::= {id-at 11 2} +id-at-collectiveOrganizationalUnitName OBJECT IDENTIFIER ::= {id-at 11 1} +id-at-encryptedCollectiveOrganizationalUnitName OBJECT IDENTIFIER ::= {id-at 11 1 2} +id-at-title OBJECT IDENTIFIER ::= {id-at 12} +id-at-encryptedTitle OBJECT IDENTIFIER ::= {id-at 12 2} +id-at-description OBJECT IDENTIFIER ::= {id-at 13} +id-at-encryptedDescription OBJECT IDENTIFIER ::= {id-at 13 2} +id-at-searchGuide OBJECT IDENTIFIER ::= {id-at 14} +id-at-encryptedSearchGuide OBJECT IDENTIFIER ::= {id-at 14 2} +id-at-businessCategory OBJECT IDENTIFIER ::= {id-at 15} +id-at-encryptedBusinessCategory OBJECT IDENTIFIER ::= {id-at 15 2} +id-at-postalAddress OBJECT IDENTIFIER ::= {id-at 16} +id-at-encryptedPostalAddress OBJECT IDENTIFIER ::= {id-at 16 2} +id-at-collectivePostalAddress OBJECT IDENTIFIER ::= {id-at 16 1} +id-at-encryptedCollectivePostalAddress OBJECT IDENTIFIER ::= {id-at 16 1 2} +id-at-postalCode OBJECT IDENTIFIER ::= {id-at 17} +id-at-encryptedPostalCode OBJECT IDENTIFIER ::= {id-at 17 2} +id-at-collectivePostalCode OBJECT IDENTIFIER ::= {id-at 17 1} +id-at-encryptedCollectivePostalCode OBJECT IDENTIFIER ::= {id-at 17 1 2} +id-at-postOfficeBox OBJECT IDENTIFIER ::= {id-at 18} +id-at-encryptedPostOfficeBox OBJECT IDENTIFIER ::= {id-at 18 2} +id-at-collectivePostOfficeBox OBJECT IDENTIFIER ::= {id-at 18 1} +id-at-encryptedCollectivePostOfficeBox OBJECT IDENTIFIER ::= {id-at 18 1 2} +id-at-physicalDeliveryOfficeName OBJECT IDENTIFIER ::= {id-at 19} +id-at-encryptedPhysicalDeliveryOfficeName OBJECT IDENTIFIER ::= {id-at 19 2} +id-at-collectivePhysicalDeliveryOfficeName OBJECT IDENTIFIER ::= {id-at 19 1} +id-at-encryptedCollectivePhysicalDeliveryOfficeName OBJECT IDENTIFIER ::= {id-at 19 1 2} +id-at-telephoneNumber OBJECT IDENTIFIER ::= {id-at 20} +id-at-encryptedTelephoneNumber OBJECT IDENTIFIER ::= {id-at 20 2} +id-at-collectiveTelephoneNumber OBJECT IDENTIFIER ::= {id-at 20 1} +id-at-encryptedCollectiveTelephoneNumber OBJECT IDENTIFIER ::= {id-at 20 1 2} +id-at-telexNumber OBJECT IDENTIFIER ::= {id-at 21} +id-at-encryptedTelexNumber OBJECT IDENTIFIER ::= {id-at 21 2} +id-at-collectiveTelexNumber OBJECT IDENTIFIER ::= {id-at 21 1} +id-at-encryptedCollectiveTelexNumber OBJECT IDENTIFIER ::= {id-at 21 1 2} +id-at-teletexTerminalIdentifier OBJECT IDENTIFIER ::= {id-at 22} +id-at-encryptedTeletexTerminalIdentifier OBJECT IDENTIFIER ::= {id-at 22 2} +id-at-collectiveTeletexTerminalIdentifier OBJECT IDENTIFIER ::= {id-at 22 1} +id-at-encryptedCollectiveTeletexTerminalIdentifier OBJECT IDENTIFIER ::= {id-at 22 1 2} +id-at-facsimileTelephoneNumber OBJECT IDENTIFIER ::= {id-at 23} +id-at-encryptedFacsimileTelephoneNumber OBJECT IDENTIFIER ::= {id-at 23 2} +id-at-collectiveFacsimileTelephoneNumber OBJECT IDENTIFIER ::= {id-at 23 1} +id-at-encryptedCollectiveFacsimileTelephoneNumber OBJECT IDENTIFIER ::= {id-at 23 1 2} +id-at-x121Address OBJECT IDENTIFIER ::= {id-at 24} +id-at-encryptedX121Address OBJECT IDENTIFIER ::= {id-at 24 2} +id-at-internationalISDNNumber OBJECT IDENTIFIER ::= {id-at 25} +id-at-encryptedInternationalISDNNumber OBJECT IDENTIFIER ::= {id-at 25 2} +id-at-collectiveInternationalISDNNumber OBJECT IDENTIFIER ::= {id-at 25 1} +id-at-encryptedCollectiveInternationalISDNNumber OBJECT IDENTIFIER ::= {id-at 25 1 2} +id-at-registeredAddress OBJECT IDENTIFIER ::= {id-at 26} +id-at-encryptedRegisteredAddress OBJECT IDENTIFIER ::= {id-at 26 2} +id-at-destinationIndicator OBJECT IDENTIFIER ::= {id-at 27} +id-at-encryptedDestinationIndicator OBJECT IDENTIFIER ::= {id-at 27 2} +id-at-preferredDeliveryMethod OBJECT IDENTIFIER ::= {id-at 28} +id-at-encryptedPreferredDeliveryMethod OBJECT IDENTIFIER ::= {id-at 28 2} +id-at-presentationAddress OBJECT IDENTIFIER ::= {id-at 29} +id-at-encryptedPresentationAddress OBJECT IDENTIFIER ::= {id-at 29 2} +id-at-supportedApplicationContext OBJECT IDENTIFIER ::= {id-at 30} +id-at-encryptedSupportedApplicationContext OBJECT IDENTIFIER ::= {id-at 30 2} +id-at-member OBJECT IDENTIFIER ::= {id-at 31} +id-at-encryptedMember OBJECT IDENTIFIER ::= {id-at 31 2} +id-at-owner OBJECT IDENTIFIER ::= {id-at 32} +id-at-encryptedOwner OBJECT IDENTIFIER ::= {id-at 32 2} +id-at-roleOccupant OBJECT IDENTIFIER ::= {id-at 33} +id-at-encryptedRoleOccupant OBJECT IDENTIFIER ::= {id-at 33 2} +id-at-seeAlso OBJECT IDENTIFIER ::= {id-at 34} +id-at-encryptedSeeAlso OBJECT IDENTIFIER ::= {id-at 34 2} +-- id-at-userPassword OBJECT IDENTIFIER ::= {id-at 35} +id-at-encryptedUserPassword OBJECT IDENTIFIER ::= {id-at 35 2} +-- id-at-userCertificate OBJECT IDENTIFIER ::= {id-at 36} +id-at-encryptedUserCertificate OBJECT IDENTIFIER ::= {id-at 36 2} +-- id-at-cACertificate OBJECT IDENTIFIER ::= {id-at 37} +id-at-encryptedCACertificate OBJECT IDENTIFIER ::= {id-at 37 2} +-- id-at-authorityRevocationList OBJECT IDENTIFIER ::= {id-at 38} +id-at-encryptedAuthorityRevocationList + OBJECT IDENTIFIER ::= {id-at 38 2} +-- id-at-certificateRevocationList OBJECT IDENTIFIER ::= {id-at 39} +id-at-encryptedCertificateRevocationList + OBJECT IDENTIFIER ::= {id-at 39 2} +-- id-at-crossCertificatePair OBJECT IDENTIFIER ::= {id-at 40} +id-at-encryptedCrossCertificatePair OBJECT IDENTIFIER ::= {id-at 40 2} +id-at-name OBJECT IDENTIFIER ::= {id-at 41} +id-at-givenName OBJECT IDENTIFIER ::= {id-at 42} +id-at-encryptedGivenName OBJECT IDENTIFIER ::= {id-at 42 2} +id-at-initials OBJECT IDENTIFIER ::= {id-at 43} +id-at-encryptedInitials OBJECT IDENTIFIER ::= {id-at 43 2} +id-at-generationQualifier OBJECT IDENTIFIER ::= {id-at 44} +id-at-encryptedGenerationQualifier OBJECT IDENTIFIER ::= {id-at 44 2} +id-at-uniqueIdentifier OBJECT IDENTIFIER ::= {id-at 45} +id-at-encryptedUniqueIdentifier OBJECT IDENTIFIER ::= {id-at 45 2} +id-at-dnQualifier OBJECT IDENTIFIER ::= {id-at 46} +id-at-encryptedDnQualifier OBJECT IDENTIFIER ::= {id-at 46 2} +id-at-enhancedSearchGuide OBJECT IDENTIFIER ::= {id-at 47} +id-at-encryptedEnhancedSearchGuide + OBJECT IDENTIFIER ::= {id-at 47 2} +id-at-protocolInformation OBJECT IDENTIFIER ::= {id-at 48} +id-at-encryptedProtocolInformation + OBJECT IDENTIFIER ::= {id-at 48 2} +id-at-distinguishedName OBJECT IDENTIFIER ::= {id-at 49} +id-at-encryptedDistinguishedName OBJECT IDENTIFIER ::= {id-at 49 2} +id-at-uniqueMember OBJECT IDENTIFIER ::= {id-at 50} +id-at-encryptedUniqueMember OBJECT IDENTIFIER ::= {id-at 50 2} +id-at-houseIdentifier OBJECT IDENTIFIER ::= {id-at 51} +id-at-encryptedHouseIdentifier OBJECT IDENTIFIER ::= {id-at 51 2} +--id-at-supportedAlgorithms OBJECT IDENTIFIER ::= {id-at 52} +id-at-encryptedSupportedAlgorithms OBJECT IDENTIFIER ::= {id-at 52 2} +--id-at-deltaRevocationList OBJECT IDENTIFIER ::= {id-at 53} +id-at-encryptedDeltaRevocationList OBJECT IDENTIFIER ::= {id-at 53 2} +id-at-dmdName OBJECT IDENTIFIER ::= {id-at 54} +id-at-encryptedDmdName OBJECT IDENTIFIER ::= {id-at 54 2} +-- id-at-clearance OBJECT IDENTIFIER ::= {id-at 55} +id-at-encryptedClearance OBJECT IDENTIFIER ::= {id-at 55 2} +-- id-at-defaultDirQop OBJECT IDENTIFIER ::= {id-at 56} +id-at-encryptedDefaultDirQop OBJECT IDENTIFIER ::= {id-at 56 2} +-- id-at-attributeIntegrityInfo OBJECT IDENTIFIER ::= {id-at 57} +id-at-encryptedAttributeIntegrityInfo OBJECT IDENTIFIER ::= {id-at 57 2} +--id-at-attributeCertificate OBJECT IDENTIFIER ::= {id-at 58} +id-at-encryptedAttributeCertificate OBJECT IDENTIFIER ::= {id-at 58 2} +-- id-at-attributeCertificateRevocationList OBJECT IDENTIFIER ::= {id-at 59} +id-at-encryptedAttributeCertificateRevocationList OBJECT IDENTIFIER ::= {id-at 59 2} +-- id-at-confKeyInfo OBJECT IDENTIFIER ::= {id-at 60} +id-at-encryptedConfKeyInfo OBJECT IDENTIFIER ::= {id-at 60 2} + +END diff --git a/libsecurity_asn1/config/base.xcconfig b/libsecurity_asn1/config/base.xcconfig new file mode 100644 index 00000000..1e170bff --- /dev/null +++ b/libsecurity_asn1/config/base.xcconfig @@ -0,0 +1,8 @@ +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) diff --git a/libsecurity_asn1/config/debug.xcconfig b/libsecurity_asn1/config/debug.xcconfig new file mode 100644 index 00000000..937d1775 --- /dev/null +++ b/libsecurity_asn1/config/debug.xcconfig @@ -0,0 +1,3 @@ +GCC_OPTIMIZATION_LEVEL = 0 +GCC_PREPROCESSOR_DEFINITIONS = DEBUG=1 $(inherited) +COPY_PHASE_STRIP = NO diff --git a/libsecurity_asn1/config/lib.xcconfig b/libsecurity_asn1/config/lib.xcconfig new file mode 100644 index 00000000..363ca975 --- /dev/null +++ b/libsecurity_asn1/config/lib.xcconfig @@ -0,0 +1,34 @@ +#include "base.xcconfig" +#include "/AppleInternal/XcodeConfig/AspenFamily.xcconfig" + +PRODUCT_NAME = $(TARGET_NAME) +EXECUTABLE_PREFIX = + +CODE_SIGN_IDENTITY = + +HEADER_SEARCH_PATHS[sdk=macosx*] = $(PROJECT_DIR) $(SYSTEM_LIBRARY_DIR)/Frameworks/CoreServices.framework/Frameworks/CarbonCore.framework/Headers $(inherited) + +HEADER_SEARCH_PATHS[sdk=iphone*] = $(PROJECT_DIR) $(BUILT_PRODUCTS_DIR)$(INDIGO_INSTALL_PATH_PREFIX)/usr/local/include $(inherited) + +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 +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/config/release.xcconfig b/libsecurity_asn1/config/release.xcconfig new file mode 100644 index 00000000..3110dcb5 --- /dev/null +++ b/libsecurity_asn1/config/release.xcconfig @@ -0,0 +1,2 @@ +GCC_PREPROCESSOR_DEFINITIONS = NDEBUG=1 $(inherited) +COPY_PHASE_STRIP = YES diff --git a/libsecurity_asn1/docs/libsecurity_asn1.plist b/libsecurity_asn1/docs/libsecurity_asn1.plist new file mode 100644 index 00000000..19f5b71d --- /dev/null +++ b/libsecurity_asn1/docs/libsecurity_asn1.plist @@ -0,0 +1,24 @@ + + + + + + OpenSourceLicense + mpl + OpenSourceImportDate + 2003-01-30 + OpenSourceLicenseFile + libsecurity_asn1.txt + OpenSourceModifications + a BER/DER encode/decode library based on Netscape's NSS + OpenSourceProject + Mozilla NSS + OpenSourceURL + ftp.mozilla.org/security/nss/releases/NSS_3_4_1_RTM/src/nss-3.4.1.tar.gz + OpenSourceVersion + NSS-3.4 + OpenSourceWebsiteURL + http://www.mozilla.org/projects/security/pki/nss/ + + + diff --git a/libsecurity_asn1/docs/libsecurity_asn1.txt b/libsecurity_asn1/docs/libsecurity_asn1.txt new file mode 100644 index 00000000..41797e6b --- /dev/null +++ b/libsecurity_asn1/docs/libsecurity_asn1.txt @@ -0,0 +1,146 @@ +MOZILLA PUBLIC LICENSE +Version 1.1 + +1. Definitions. + +1.0.1. "Commercial Use" means distribution or otherwise making the Covered Code available to a third party. +1.1. ''Contributor'' means each entity that creates or contributes to the creation of Modifications. + +1.2. ''Contributor Version'' means the combination of the Original Code, prior Modifications used by a Contributor, and the Modifications made by that particular Contributor. + +1.3. ''Covered Code'' means the Original Code or Modifications or the combination of the Original Code and Modifications, in each case including portions thereof. + +1.4. ''Electronic Distribution Mechanism'' means a mechanism generally accepted in the software development community for the electronic transfer of data. + +1.5. ''Executable'' means Covered Code in any form other than Source Code. + +1.6. ''Initial Developer'' means the individual or entity identified as the Initial Developer in the Source Code notice required by Exhibit A. + +1.7. ''Larger Work'' means a work which combines Covered Code or portions thereof with code not governed by the terms of this License. + +1.8. ''License'' means this document. + +1.8.1. "Licensable" means having the right to grant, to the maximum extent possible, whether at the time of the initial grant or subsequently acquired, any and all of the rights conveyed herein. + +1.9. ''Modifications'' means any addition to or deletion from the substance or structure of either the Original Code or any previous Modifications. When Covered Code is released as a series of files, a Modification is: + +A. Any addition to or deletion from the contents of a file containing Original Code or previous Modifications. +B. Any new file that contains any part of the Original Code or previous Modifications. + + +1.10. ''Original Code'' means Source Code of computer software code which is described in the Source Code notice required by Exhibit A as Original Code, and which, at the time of its release under this License is not already Covered Code governed by this License. +1.10.1. "Patent Claims" means any patent claim(s), now owned or hereafter acquired, including without limitation, method, process, and apparatus claims, in any patent Licensable by grantor. + +1.11. ''Source Code'' means the preferred form of the Covered Code 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, or source code differential comparisons against either the Original Code or another well known, available Covered Code of the Contributor's choice. The Source Code can be in a compressed or archival form, provided the appropriate decompression or de-archiving software is widely available for no charge. + +1.12. "You'' (or "Your") means an individual or a legal entity exercising rights under, and complying with all of the terms of, this License or a future version of this License issued under Section 6.1. For legal entities, "You'' includes any entity which controls, is controlled by, or is under common control with You. For purposes of this definition, "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 more than fifty percent (50%) of the outstanding shares or beneficial ownership of such entity. + +2. Source Code License. +2.1. The Initial Developer Grant. +The Initial Developer hereby grants You a world-wide, royalty-free, non-exclusive license, subject to third party intellectual property claims: +(a) under intellectual property rights (other than patent or trademark) Licensable by Initial Developer to use, reproduce, modify, display, perform, sublicense and distribute the Original Code (or portions thereof) with or without Modifications, and/or as part of a Larger Work; and +(b) under Patents Claims infringed by the making, using or selling of Original Code, to make, have made, use, practice, sell, and offer for sale, and/or otherwise dispose of the Original Code (or portions thereof). + + +(c) the licenses granted in this Section 2.1(a) and (b) are effective on the date Initial Developer first distributes Original Code under the terms of this License. +(d) Notwithstanding Section 2.1(b) above, no patent license is granted: 1) for code that You delete from the Original Code; 2) separate from the Original Code; or 3) for infringements caused by: i) the modification of the Original Code or ii) the combination of the Original Code with other software or devices. + + +2.2. Contributor Grant. +Subject to third party intellectual property claims, each Contributor hereby grants You a world-wide, royalty-free, non-exclusive license + +(a) under intellectual property rights (other than patent or trademark) Licensable by Contributor, to use, reproduce, modify, display, perform, sublicense and distribute the Modifications created by such Contributor (or portions thereof) either on an unmodified basis, with other Modifications, as Covered Code and/or as part of a Larger Work; and +(b) under Patent Claims infringed by the making, using, or selling of Modifications made by that Contributor either alone and/or in combination with its Contributor Version (or portions of such combination), to make, use, sell, offer for sale, have made, and/or otherwise dispose of: 1) Modifications made by that Contributor (or portions thereof); and 2) the combination of Modifications made by that Contributor with its Contributor Version (or portions of such combination). + +(c) the licenses granted in Sections 2.2(a) and 2.2(b) are effective on the date Contributor first makes Commercial Use of the Covered Code. + +(d) Notwithstanding Section 2.2(b) above, no patent license is granted: 1) for any code that Contributor has deleted from the Contributor Version; 2) separate from the Contributor Version; 3) for infringements caused by: i) third party modifications of Contributor Version or ii) the combination of Modifications made by that Contributor with other software (except as part of the Contributor Version) or other devices; or 4) under Patent Claims infringed by Covered Code in the absence of Modifications made by that Contributor. + + +3. Distribution Obligations. + +3.1. Application of License. +The Modifications which You create or to which You contribute are governed by the terms of this License, including without limitation Section 2.2. The Source Code version of Covered Code may be distributed only under the terms of this License or a future version of this License released under Section 6.1, and You must include a copy of this License with every copy of the Source Code You distribute. You may not offer or impose any terms on any Source Code version that alters or restricts the applicable version of this License or the recipients' rights hereunder. However, You may include an additional document offering the additional rights described in Section 3.5. +3.2. Availability of Source Code. +Any Modification which You create or to which You contribute must be made available in Source Code form under the terms of this License either on the same media as an Executable version or via an accepted Electronic Distribution Mechanism to anyone to whom you made an Executable version available; and if made available via Electronic Distribution Mechanism, must remain available for at least twelve (12) months after the date it initially became available, or at least six (6) months after a subsequent version of that particular Modification has been made available to such recipients. You are responsible for ensuring that the Source Code version remains available even if the Electronic Distribution Mechanism is maintained by a third party. + +3.3. Description of Modifications. +You must cause all Covered Code to which You contribute to contain a file documenting the changes You made to create that Covered Code and the date of any change. You must include a prominent statement that the Modification is derived, directly or indirectly, from Original Code provided by the Initial Developer and including the name of the Initial Developer in (a) the Source Code, and (b) in any notice in an Executable version or related documentation in which You describe the origin or ownership of the Covered Code. + +3.4. Intellectual Property Matters + +(a) Third Party Claims. +If Contributor has knowledge that a license under a third party's intellectual property rights is required to exercise the rights granted by such Contributor under Sections 2.1 or 2.2, Contributor must include a text file with the Source Code distribution titled "LEGAL'' which describes the claim and the party making the claim in sufficient detail that a recipient will know whom to contact. If Contributor obtains such knowledge after the Modification is made available as described in Section 3.2, Contributor shall promptly modify the LEGAL file in all copies Contributor makes available thereafter and shall take other steps (such as notifying appropriate mailing lists or newsgroups) reasonably calculated to inform those who received the Covered Code that new knowledge has been obtained. +(b) Contributor APIs. +If Contributor's Modifications include an application programming interface and Contributor has knowledge of patent licenses which are reasonably necessary to implement that API, Contributor must also include this information in the LEGAL file. + + + (c) Representations. +Contributor represents that, except as disclosed pursuant to Section 3.4(a) above, Contributor believes that Contributor's Modifications are Contributor's original creation(s) and/or Contributor has sufficient rights to grant the rights conveyed by this License. + +3.5. Required Notices. +You must duplicate the notice in Exhibit A in each file of the Source Code. If it is not possible to put such notice in a particular Source Code file due to its structure, then You must include such notice in a location (such as a relevant directory) where a user would be likely to look for such a notice. If You created one or more Modification(s) You may add your name as a Contributor to the notice described in Exhibit A. You must also duplicate this License in any documentation for the Source Code where You describe recipients' rights or ownership rights relating to Covered Code. You may choose to offer, and to charge a fee for, warranty, support, indemnity or liability obligations to one or more recipients of Covered Code. However, You may do so only on Your own behalf, and not on behalf of the Initial Developer or any Contributor. You must make it absolutely clear than any such warranty, support, indemnity or liability obligation is offered by You alone, and You hereby agree to indemnify the Initial Developer and every Contributor for any liability incurred by the Initial Developer or such Contributor as a result of warranty, support, indemnity or liability terms You offer. + +3.6. Distribution of Executable Versions. +You may distribute Covered Code in Executable form only if the requirements of Section 3.1-3.5 have been met for that Covered Code, and if You include a notice stating that the Source Code version of the Covered Code is available under the terms of this License, including a description of how and where You have fulfilled the obligations of Section 3.2. The notice must be conspicuously included in any notice in an Executable version, related documentation or collateral in which You describe recipients' rights relating to the Covered Code. You may distribute the Executable version of Covered Code or ownership rights under a license of Your choice, which may contain terms different from this License, provided that You are in compliance with the terms of this License and that the license for the Executable version does not attempt to limit or alter the recipient's rights in the Source Code version from the rights set forth in this License. If You distribute the Executable version under a different license You must make it absolutely clear that any terms which differ from this License are offered by You alone, not by the Initial Developer or any Contributor. You hereby agree to indemnify the Initial Developer and every Contributor for any liability incurred by the Initial Developer or such Contributor as a result of any such terms You offer. + +3.7. 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 such a case, You must make sure the requirements of this License are fulfilled for the Covered Code. + +4. Inability to Comply Due to Statute or Regulation. +If it is impossible for You to comply with any of the terms of this License with respect to some or all of the Covered Code due to statute, judicial order, or regulation then You must: (a) comply with the terms of this License to the maximum extent possible; and (b) describe the limitations and the code they affect. Such description must be included in the LEGAL file described in Section 3.4 and must be included with all distributions of the Source Code. Except to the extent prohibited by statute or regulation, such description must be sufficiently detailed for a recipient of ordinary skill to be able to understand it. +5. Application of this License. +This License applies to code to which the Initial Developer has attached the notice in Exhibit A and to related Covered Code. +6. Versions of the License. +6.1. New Versions. +Netscape Communications Corporation (''Netscape'') may publish revised and/or new versions of the License from time to time. Each version will be given a distinguishing version number. +6.2. Effect of New Versions. +Once Covered Code has been published under a particular version of the License, You may always continue to use it under the terms of that version. You may also choose to use such Covered Code under the terms of any subsequent version of the License published by Netscape. No one other than Netscape has the right to modify the terms applicable to Covered Code created under this License. + +6.3. Derivative Works. +If You create or use a modified version of this License (which you may only do in order to apply it to code which is not already Covered Code governed by this License), You must (a) rename Your license so that the phrases ''Mozilla'', ''MOZILLAPL'', ''MOZPL'', ''Netscape'', "MPL", ''NPL'' or any confusingly similar phrase do not appear in your license (except to note that your license differs from this License) and (b) otherwise make it clear that Your version of the license contains terms which differ from the Mozilla Public License and Netscape Public License. (Filling in the name of the Initial Developer, Original Code or Contributor in the notice described in Exhibit A shall not of themselves be deemed to be modifications of this License.) + +7. DISCLAIMER OF WARRANTY. +COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS'' BASIS, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER. +8. TERMINATION. +8.1. This License and the rights granted hereunder will terminate automatically if You fail to comply with terms herein and fail to cure such breach within 30 days of becoming aware of the breach. All sublicenses to the Covered Code which are properly granted shall survive any termination of this License. Provisions which, by their nature, must remain in effect beyond the termination of this License shall survive. +8.2. If You initiate litigation by asserting a patent infringement claim (excluding declatory judgment actions) against Initial Developer or a Contributor (the Initial Developer or Contributor against whom You file such action is referred to as "Participant") alleging that: + +(a) such Participant's Contributor Version directly or indirectly infringes any patent, then any and all rights granted by such Participant to You under Sections 2.1 and/or 2.2 of this License shall, upon 60 days notice from Participant terminate prospectively, unless if within 60 days after receipt of notice You either: (i) agree in writing to pay Participant a mutually agreeable reasonable royalty for Your past and future use of Modifications made by such Participant, or (ii) withdraw Your litigation claim with respect to the Contributor Version against such Participant. If within 60 days of notice, a reasonable royalty and payment arrangement are not mutually agreed upon in writing by the parties or the litigation claim is not withdrawn, the rights granted by Participant to You under Sections 2.1 and/or 2.2 automatically terminate at the expiration of the 60 day notice period specified above. + +(b) any software, hardware, or device, other than such Participant's Contributor Version, directly or indirectly infringes any patent, then any rights granted to You by such Participant under Sections 2.1(b) and 2.2(b) are revoked effective as of the date You first made, used, sold, distributed, or had made, Modifications made by that Participant. + +8.3. If You assert a patent infringement claim against Participant alleging that such Participant's Contributor Version directly or indirectly infringes any patent where such claim is resolved (such as by license or settlement) prior to the initiation of patent infringement litigation, then the reasonable value of the licenses granted by such Participant under Sections 2.1 or 2.2 shall be taken into account in determining the amount or value of any payment or license. + +8.4. In the event of termination under Sections 8.1 or 8.2 above, all end user license agreements (excluding distributors and resellers) which have been validly granted by You or any distributor hereunder prior to termination shall survive termination. + +9. LIMITATION OF LIABILITY. +UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE INITIAL DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF COVERED CODE, OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO ANY PERSON FOR ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL, WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT APPLICABLE LAW PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THIS EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU. +10. U.S. GOVERNMENT END USERS. +The Covered Code is a ''commercial item,'' as that term is defined in 48 C.F.R. 2.101 (Oct. 1995), consisting of ''commercial computer software'' and ''commercial computer software documentation,'' as such terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48 C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995), all U.S. Government End Users acquire Covered Code with only those rights set forth herein. +11. MISCELLANEOUS. +This License represents the complete agreement concerning subject matter hereof. If any provision of this License is held to be unenforceable, such provision shall be reformed only to the extent necessary to make it enforceable. This License shall be governed by California law provisions (except to the extent applicable law, if any, provides otherwise), excluding its conflict-of-law provisions. With respect to disputes in which at least one party is a citizen of, or an entity chartered or registered to do business in the United States of America, any litigation relating to this License shall be subject to the jurisdiction of the Federal Courts of the Northern District of California, with venue lying in Santa Clara County, California, with the losing party responsible for costs, including without limitation, court costs and reasonable attorneys' fees and expenses. The application of the United Nations Convention on Contracts for the International Sale of Goods is expressly excluded. Any law or regulation which provides that the language of a contract shall be construed against the drafter shall not apply to this License. +12. RESPONSIBILITY FOR CLAIMS. +As between Initial Developer and the Contributors, each party is responsible for claims and damages arising, directly or indirectly, out of its utilization of rights under this License and You agree to work with Initial Developer and Contributors to distribute such responsibility on an equitable basis. Nothing herein is intended or shall be deemed to constitute any admission of liability. +13. MULTIPLE-LICENSED CODE. +Initial Developer may designate portions of the Covered Code as ÒMultiple-LicensedÓ. ÒMultiple-LicensedÓ means that the Initial Developer permits you to utilize portions of the Covered Code under Your choice of the MPL or the alternative licenses, if any, specified by the Initial Developer in the file described in Exhibit A. + +EXHIBIT A -Mozilla Public License. + +``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 Initial Developer of the Original Code is ________________________. Portions created by + ______________________ are Copyright (C) ______ _______________________. All Rights +Reserved. + +Contributor(s): ______________________________________. + +Alternatively, the contents of this file may be used under the terms of the _____ license (the Ò[___] LicenseÓ), in which case the provisions of [______] License are applicable instead of those above. If you wish to allow use of your version of this file only under the terms of the [____] License 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 [___] License. If you do not delete the provisions above, a recipient may use your version of this file under either the MPL or the [___] License." + +[NOTE: The text of this Exhibit A may differ slightly from the text of the notices in the Source Code files of the Original Code. You should use the text of this Exhibit A rather than the text found in the Original Code Source Code for Your Modifications.] \ No newline at end of file diff --git a/libsecurity_asn1/lib/SecAsn1Coder.c b/libsecurity_asn1/lib/SecAsn1Coder.c new file mode 100644 index 00000000..29708f6d --- /dev/null +++ b/libsecurity_asn1/lib/SecAsn1Coder.c @@ -0,0 +1,220 @@ +/* + * 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@ + * + * SecAsn1Coder.h: ANS1 encode/decode object, ANSI C version. + */ + +#include "SecAsn1Coder.h" +#include "plarenas.h" +#include "prerror.h" +#include "seccomon.h" +#include "secasn1.h" +#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 CHUNKSIZE_DEF 1024 + +/* + * Caller's SecAsn1CoderRef points to one of these. + */ +typedef struct SecAsn1Coder { + PLArenaPool *mPool; +} SecAsn1Coder_t; + +/* + * Create/destroy SecAsn1Coder object. + */ +OSStatus SecAsn1CoderCreate( + SecAsn1CoderRef *coder) +{ + if(coder == NULL) { + return paramErr; + } + SecAsn1CoderRef _coder = (SecAsn1CoderRef)malloc(sizeof(SecAsn1Coder_t)); + _coder->mPool = PORT_NewArena(CHUNKSIZE_DEF); + if(_coder->mPool == NULL) { + return memFullErr; + } + *coder = _coder; + return noErr; +} + +OSStatus SecAsn1CoderRelease( + SecAsn1CoderRef coder) +{ + if(coder == NULL) { + return paramErr; + } + if(coder->mPool != NULL) { + /* + * Note: we're asking for a memory zero here, but + * PORT_FreeArena doesn't do that (yet). + */ + PORT_FreeArena(coder->mPool, PR_TRUE); + coder->mPool = NULL; + } + free(coder); + return noErr; +} + +/* + * DER decode an untyped item per the specified template array. + * The result is allocated in this SecAsn1Coder's memory pool and + * is freed when this object is released. + * + * The dest pointer is a template-specific struct allocated by the caller + * and must be zeroed by the caller. + */ +OSStatus SecAsn1Decode( + SecAsn1CoderRef coder, + const void *src, // DER-encoded source + size_t len, + const SecAsn1Template *templ, + void *dest) +{ + if((coder == NULL) || (src == NULL) || (templ == NULL) || (dest == NULL)) { + return paramErr; + } + SECStatus prtn = SEC_ASN1Decode(coder->mPool, dest, templ, (const char *)src, len); + if(prtn) { + return errSecDecode; + } + else { + return noErr; + } +} + +/* + * Convenience routine, decode from a SecAsn1Item. + */ +OSStatus SecAsn1DecodeData( + SecAsn1CoderRef coder, + const SecAsn1Item *src, + const SecAsn1Template *templ, + void *dest) +{ + return SecAsn1Decode(coder, src->Data, src->Length, templ, dest); +} + +/* + * DER encode. The encoded data (in dest.Data) is allocated in this + * SecAsn1Coder's memory pool and is freed when this object is released. + * + * The src pointer is a template-specific struct. + */ +OSStatus SecAsn1EncodeItem( + SecAsn1CoderRef coder, + const void *src, + const SecAsn1Template *templ, + SecAsn1Item *dest) +{ + if((coder == NULL) || (src == NULL) || (templ == NULL) || (dest == NULL)) { + return paramErr; + } + dest->Data = NULL; + dest->Length = 0; + + SecAsn1Item *rtnItem = SEC_ASN1EncodeItem(coder->mPool, dest, src, templ); + if(rtnItem == NULL) { + /* FIXME what to return here? */ + return paramErr; + } + else { + return noErr; + } +} + +/* + * Some alloc-related methods which come in handy when using + * this object. All memory is allocated using this object's + * memory 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 return a memFullErr in the highly unlikely event of + * a malloc failure. + */ +void *SecAsn1Malloc( + SecAsn1CoderRef coder, + size_t len) +{ + if(coder == NULL) { + return NULL; + } + return PORT_ArenaAlloc(coder->mPool, len); +} + +/* malloc item.Data, set item.Length */ +OSStatus SecAsn1AllocItem( + SecAsn1CoderRef coder, + SecAsn1Item *item, + size_t len) +{ + if((coder == NULL) || (item == NULL)) { + return paramErr; + } + item->Data = (uint8_t *)PORT_ArenaAlloc(coder->mPool, len); + if(item->Data == NULL) { + return memFullErr; + } + item->Length = len; + return noErr; +} + +/* malloc and copy, various forms */ +OSStatus SecAsn1AllocCopy( + SecAsn1CoderRef coder, + const void *src, + size_t len, + SecAsn1Item *dest) +{ + if(src == NULL) { + return paramErr; + } + OSStatus ortn = SecAsn1AllocItem(coder, dest, len); + if(ortn) { + return ortn; + } + memmove(dest->Data, src, len); + return noErr; +} + +OSStatus SecAsn1AllocCopyItem( + SecAsn1CoderRef coder, + const SecAsn1Item *src, + SecAsn1Item *dest) +{ + return SecAsn1AllocCopy(coder, src->Data, src->Length, dest); +} + +bool SecAsn1OidCompare(const SecAsn1Oid *oid1, const SecAsn1Oid *oid2) { + if (!oid1 || !oid2) + return oid1 == oid2; + if (oid1->Length != oid2->Length) + return false; + return !memcmp(oid1->Data, oid2->Data, oid1->Length); +} diff --git a/libsecurity_asn1/lib/SecAsn1Coder.h b/libsecurity_asn1/lib/SecAsn1Coder.h new file mode 100644 index 00000000..33ed59ec --- /dev/null +++ b/libsecurity_asn1/lib/SecAsn1Coder.h @@ -0,0 +1,149 @@ +/* + * 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@ + * + * SecAsn1Coder.h: ANS1 encode/decode object. + * + * A SecAsn1Coder is capable of encoding and decoding both DER and BER data + * streams, based on caller-supplied templates which in turn are based + * upon ASN.1 specifications. A SecAsn1Coder allocates memory during encode + * and decode using a memory pool which is owned and managed by the SecAsn1Coder + * object, and which is freed when the SecAsn1Coder object os released. + */ + +#ifndef _SEC_ASN1_CODER_H_ +#define _SEC_ASN1_CODER_H_ + +#include +#include +#include +#include /* error codes */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Opaque reference to a SecAsn1Coder object. + */ +typedef struct SecAsn1Coder *SecAsn1CoderRef; + +/* + * Create/destroy SecAsn1Coder object. + */ +OSStatus SecAsn1CoderCreate( + SecAsn1CoderRef *coder); + +OSStatus SecAsn1CoderRelease( + SecAsn1CoderRef coder); + +/* + * DER decode an untyped item per the specified template array. + * The result is allocated in this SecAsn1Coder's memory pool and + * is freed when this object is released. + * + * The templates argument points to a an array of SecAsn1Templates + * defining the object to be decoded; the end of the array is + * indicated by a SecAsn1Template with file kind equalling 0. + * + * The dest pointer is a template-specific struct allocated by the caller + * and must be zeroed by the caller. + * + * Returns errSecUnknownFormat on decode-specific error. + */ +OSStatus SecAsn1Decode( + SecAsn1CoderRef coder, + const void *src, // DER-encoded source + size_t len, + const SecAsn1Template *templates, + void *dest); + +/* + * Convenience routine, decode from a SecAsn1Item. + */ +OSStatus SecAsn1DecodeData( + SecAsn1CoderRef coder, + const SecAsn1Item *src, + const SecAsn1Template *templ, + void *dest); + +/* + * DER encode. The encoded data (in dest.Data) is allocated in this + * SecAsn1Coder's memory pool and is freed when this object is released. + * + * The src pointer is a template-specific struct. + * + * The templates argument points to a an array of SecAsn1Templates + * defining the object to be decoded; the end of the array is + * indicated by a SecAsn1Template with file kind equalling 0. + */ +OSStatus SecAsn1EncodeItem( + SecAsn1CoderRef coder, + const void *src, + const SecAsn1Template *templates, + SecAsn1Item *dest); + +/* + * Some alloc-related methods which come in handy when using + * this object. All memory is allocated using this object's + * memory 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. + * + * All except SecAsn1Malloc return a memFullErr in the highly + * unlikely event of a malloc failure. + * + * SecAsn1Malloc() returns a pointer to allocated memory, like + * malloc(). + */ +void *SecAsn1Malloc( + SecAsn1CoderRef coder, + size_t len); + +/* Allocate item.Data, set item.Length */ +OSStatus SecAsn1AllocItem( + SecAsn1CoderRef coder, + SecAsn1Item *item, + size_t len); + +/* Allocate and copy, various forms */ +OSStatus SecAsn1AllocCopy( + SecAsn1CoderRef coder, + const void *src, /* memory copied from here */ + size_t len, /* length to allocate & copy */ + SecAsn1Item *dest); /* dest->Data allocated and copied to; + * dest->Length := len */ + +OSStatus SecAsn1AllocCopyItem( + SecAsn1CoderRef coder, + const SecAsn1Item *src, /* src->Length bytes allocated and copied from + * src->Data */ + SecAsn1Item *dest); /* dest->Data allocated and copied to; + * dest->Length := src->Length */ + +/* Compare two decoded OIDs. Returns true iff they are equivalent. */ +bool SecAsn1OidCompare(const SecAsn1Oid *oid1, const SecAsn1Oid *oid2); + +#ifdef __cplusplus +} +#endif + +#endif /* _SEC_ASN1_CODER_H_ */ diff --git a/libsecurity_asn1/lib/SecAsn1Templates.c b/libsecurity_asn1/lib/SecAsn1Templates.c new file mode 100644 index 00000000..38b25ff6 --- /dev/null +++ b/libsecurity_asn1/lib/SecAsn1Templates.c @@ -0,0 +1,373 @@ +/* + * 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@ + * + * SecAsn1Templates.c - Common ASN1 templates for use with libsecurity_asn1. + */ + +#include "secasn1t.h" +#include "seccomon.h" +#include + +/* + * Generic templates for individual/simple items and pointers to + * and sets of same. + * + * If you need to add a new one, please note the following: + * - For each new basic type you should add *four* templates: + * one plain, one PointerTo, one SequenceOf and one SetOf. + * - If the new type can be constructed (meaning, it is a + * *string* type according to BER/DER rules), then you should + * or-in SEC_ASN1_MAY_STREAM to the type in the basic template. + * See the definition of the OctetString template for an example. + * - It may not be obvious, but these are in *alphabetical* + * order based on the SEC_ASN1_XXX name; so put new ones in + * the appropriate place. + */ + +const SecAsn1Template kSecAsn1AnyTemplate[] = { + { SEC_ASN1_ANY | SEC_ASN1_MAY_STREAM, 0, NULL, sizeof(SecAsn1Item) } +}; + +const SecAsn1Template kSecAsn1PointerToAnyTemplate[] = { + { SEC_ASN1_POINTER, 0, kSecAsn1AnyTemplate } +}; + +const SecAsn1Template kSecAsn1SequenceOfAnyTemplate[] = { + { SEC_ASN1_SEQUENCE_OF, 0, kSecAsn1AnyTemplate } +}; + +const SecAsn1Template kSecAsn1SetOfAnyTemplate[] = { + { SEC_ASN1_SET_OF, 0, kSecAsn1AnyTemplate } +}; + +const SecAsn1Template kSecAsn1BitStringTemplate[] = { + { SEC_ASN1_BIT_STRING | SEC_ASN1_MAY_STREAM, 0, NULL, sizeof(SecAsn1Item) } +}; + +const SecAsn1Template kSecAsn1PointerToBitStringTemplate[] = { + { SEC_ASN1_POINTER, 0, kSecAsn1BitStringTemplate } +}; + +const SecAsn1Template kSecAsn1SequenceOfBitStringTemplate[] = { + { SEC_ASN1_SEQUENCE_OF, 0, kSecAsn1BitStringTemplate } +}; + +const SecAsn1Template kSecAsn1SetOfBitStringTemplate[] = { + { SEC_ASN1_SET_OF, 0, kSecAsn1BitStringTemplate } +}; + +const SecAsn1Template kSecAsn1BMPStringTemplate[] = { + { SEC_ASN1_BMP_STRING | SEC_ASN1_MAY_STREAM, 0, NULL, sizeof(SecAsn1Item) } +}; + +const SecAsn1Template kSecAsn1PointerToBMPStringTemplate[] = { + { SEC_ASN1_POINTER, 0, kSecAsn1BMPStringTemplate } +}; + +const SecAsn1Template kSecAsn1SequenceOfBMPStringTemplate[] = { + { SEC_ASN1_SEQUENCE_OF, 0, kSecAsn1BMPStringTemplate } +}; + +const SecAsn1Template kSecAsn1SetOfBMPStringTemplate[] = { + { SEC_ASN1_SET_OF, 0, kSecAsn1BMPStringTemplate } +}; + +const SecAsn1Template kSecAsn1BooleanTemplate[] = { + { SEC_ASN1_BOOLEAN, 0, NULL, sizeof(SecAsn1Item) } +}; + +const SecAsn1Template kSecAsn1PointerToBooleanTemplate[] = { + { SEC_ASN1_POINTER, 0, kSecAsn1BooleanTemplate } +}; + +const SecAsn1Template kSecAsn1SequenceOfBooleanTemplate[] = { + { SEC_ASN1_SEQUENCE_OF, 0, kSecAsn1BooleanTemplate } +}; + +const SecAsn1Template kSecAsn1SetOfBooleanTemplate[] = { + { SEC_ASN1_SET_OF, 0, kSecAsn1BooleanTemplate } +}; + +const SecAsn1Template kSecAsn1EnumeratedTemplate[] = { + { SEC_ASN1_ENUMERATED, 0, NULL, sizeof(SecAsn1Item) } +}; + +const SecAsn1Template kSecAsn1PointerToEnumeratedTemplate[] = { + { SEC_ASN1_POINTER, 0, kSecAsn1EnumeratedTemplate } +}; + +const SecAsn1Template kSecAsn1SequenceOfEnumeratedTemplate[] = { + { SEC_ASN1_SEQUENCE_OF, 0, kSecAsn1EnumeratedTemplate } +}; + +const SecAsn1Template kSecAsn1SetOfEnumeratedTemplate[] = { + { SEC_ASN1_SET_OF, 0, kSecAsn1EnumeratedTemplate } +}; + +const SecAsn1Template kSecAsn1GeneralizedTimeTemplate[] = { + { SEC_ASN1_GENERALIZED_TIME | SEC_ASN1_MAY_STREAM, 0, NULL, sizeof(SecAsn1Item)} +}; + +const SecAsn1Template kSecAsn1PointerToGeneralizedTimeTemplate[] = { + { SEC_ASN1_POINTER, 0, kSecAsn1GeneralizedTimeTemplate } +}; + +const SecAsn1Template kSecAsn1SequenceOfGeneralizedTimeTemplate[] = { + { SEC_ASN1_SEQUENCE_OF, 0, kSecAsn1GeneralizedTimeTemplate } +}; + +const SecAsn1Template kSecAsn1SetOfGeneralizedTimeTemplate[] = { + { SEC_ASN1_SET_OF, 0, kSecAsn1GeneralizedTimeTemplate } +}; + +const SecAsn1Template kSecAsn1IA5StringTemplate[] = { + { SEC_ASN1_IA5_STRING | SEC_ASN1_MAY_STREAM, 0, NULL, sizeof(SecAsn1Item) } +}; + +const SecAsn1Template kSecAsn1PointerToIA5StringTemplate[] = { + { SEC_ASN1_POINTER, 0, kSecAsn1IA5StringTemplate } +}; + +const SecAsn1Template kSecAsn1SequenceOfIA5StringTemplate[] = { + { SEC_ASN1_SEQUENCE_OF, 0, kSecAsn1IA5StringTemplate } +}; + +const SecAsn1Template kSecAsn1SetOfIA5StringTemplate[] = { + { SEC_ASN1_SET_OF, 0, kSecAsn1IA5StringTemplate } +}; + +const SecAsn1Template kSecAsn1IntegerTemplate[] = { + { SEC_ASN1_INTEGER | SEC_ASN1_SIGNED_INT, 0, NULL, sizeof(SecAsn1Item) } +}; + +const SecAsn1Template kSecAsn1UnsignedIntegerTemplate[] = { + { SEC_ASN1_INTEGER, 0, NULL, sizeof(SecAsn1Item) } +}; + +const SecAsn1Template kSecAsn1PointerToIntegerTemplate[] = { + { SEC_ASN1_POINTER, 0, kSecAsn1IntegerTemplate } +}; + +const SecAsn1Template kSecAsn1SequenceOfIntegerTemplate[] = { + { SEC_ASN1_SEQUENCE_OF, 0, kSecAsn1IntegerTemplate } +}; + +const SecAsn1Template kSecAsn1SetOfIntegerTemplate[] = { + { SEC_ASN1_SET_OF, 0, kSecAsn1IntegerTemplate } +}; + +const SecAsn1Template kSecAsn1NullTemplate[] = { + { SEC_ASN1_NULL, 0, NULL, sizeof(SecAsn1Item) } +}; + +const SecAsn1Template kSecAsn1PointerToNullTemplate[] = { + { SEC_ASN1_POINTER, 0, kSecAsn1NullTemplate } +}; + +const SecAsn1Template kSecAsn1SequenceOfNullTemplate[] = { + { SEC_ASN1_SEQUENCE_OF, 0, kSecAsn1NullTemplate } +}; + +const SecAsn1Template kSecAsn1SetOfNullTemplate[] = { + { SEC_ASN1_SET_OF, 0, kSecAsn1NullTemplate } +}; + +const SecAsn1Template kSecAsn1ObjectIDTemplate[] = { + { SEC_ASN1_OBJECT_ID, 0, NULL, sizeof(SecAsn1Item) } +}; + +const SecAsn1Template kSecAsn1PointerToObjectIDTemplate[] = { + { SEC_ASN1_POINTER, 0, kSecAsn1ObjectIDTemplate } +}; + +const SecAsn1Template kSecAsn1SequenceOfObjectIDTemplate[] = { + { SEC_ASN1_SEQUENCE_OF, 0, kSecAsn1ObjectIDTemplate } +}; + +const SecAsn1Template kSecAsn1SetOfObjectIDTemplate[] = { + { SEC_ASN1_SET_OF, 0, kSecAsn1ObjectIDTemplate } +}; + +const SecAsn1Template kSecAsn1OctetStringTemplate[] = { + { SEC_ASN1_OCTET_STRING | SEC_ASN1_MAY_STREAM, 0, NULL, sizeof(SecAsn1Item) } +}; + +const SecAsn1Template kSecAsn1PointerToOctetStringTemplate[] = { + { SEC_ASN1_POINTER | SEC_ASN1_MAY_STREAM, 0, kSecAsn1OctetStringTemplate } +}; + +const SecAsn1Template kSecAsn1SequenceOfOctetStringTemplate[] = { + { SEC_ASN1_SEQUENCE_OF, 0, kSecAsn1OctetStringTemplate } +}; + +const SecAsn1Template kSecAsn1SetOfOctetStringTemplate[] = { + { SEC_ASN1_SET_OF, 0, kSecAsn1OctetStringTemplate } +}; + +const SecAsn1Template kSecAsn1PrintableStringTemplate[] = { + { SEC_ASN1_PRINTABLE_STRING | SEC_ASN1_MAY_STREAM, 0, NULL, sizeof(SecAsn1Item)} +}; + +const SecAsn1Template kSecAsn1PointerToPrintableStringTemplate[] = { + { SEC_ASN1_POINTER, 0, kSecAsn1PrintableStringTemplate } +}; + +const SecAsn1Template kSecAsn1SequenceOfPrintableStringTemplate[] = { + { SEC_ASN1_SEQUENCE_OF, 0, kSecAsn1PrintableStringTemplate } +}; + +const SecAsn1Template kSecAsn1SetOfPrintableStringTemplate[] = { + { SEC_ASN1_SET_OF, 0, kSecAsn1PrintableStringTemplate } +}; + +#ifdef __APPLE__ +const SecAsn1Template kSecAsn1TeletexStringTemplate[] = { + { SEC_ASN1_TELETEX_STRING | SEC_ASN1_MAY_STREAM, 0, NULL, sizeof(SecAsn1Item)} +}; + +const SecAsn1Template kSecAsn1PointerToTeletexStringTemplate[] = { + { SEC_ASN1_POINTER, 0, kSecAsn1TeletexStringTemplate } +}; + +const SecAsn1Template kSecAsn1SequenceOfTeletexStringTemplate[] = { + { SEC_ASN1_SEQUENCE_OF, 0, kSecAsn1TeletexStringTemplate } +}; + +const SecAsn1Template kSecAsn1SetOfTeletexStringTemplate[] = { + { SEC_ASN1_SET_OF, 0, kSecAsn1TeletexStringTemplate } +}; +#endif /* __APPLE__ */ + +const SecAsn1Template kSecAsn1T61StringTemplate[] = { + { SEC_ASN1_T61_STRING | SEC_ASN1_MAY_STREAM, 0, NULL, sizeof(SecAsn1Item) } +}; + +const SecAsn1Template kSecAsn1PointerToT61StringTemplate[] = { + { SEC_ASN1_POINTER, 0, kSecAsn1T61StringTemplate } +}; + +const SecAsn1Template kSecAsn1SequenceOfT61StringTemplate[] = { + { SEC_ASN1_SEQUENCE_OF, 0, kSecAsn1T61StringTemplate } +}; + +const SecAsn1Template kSecAsn1SetOfT61StringTemplate[] = { + { SEC_ASN1_SET_OF, 0, kSecAsn1T61StringTemplate } +}; + +const SecAsn1Template kSecAsn1UniversalStringTemplate[] = { + { SEC_ASN1_UNIVERSAL_STRING | SEC_ASN1_MAY_STREAM, 0, NULL, sizeof(SecAsn1Item)} +}; + +const SecAsn1Template kSecAsn1PointerToUniversalStringTemplate[] = { + { SEC_ASN1_POINTER, 0, kSecAsn1UniversalStringTemplate } +}; + +const SecAsn1Template kSecAsn1SequenceOfUniversalStringTemplate[] = { + { SEC_ASN1_SEQUENCE_OF, 0, kSecAsn1UniversalStringTemplate } +}; + +const SecAsn1Template kSecAsn1SetOfUniversalStringTemplate[] = { + { SEC_ASN1_SET_OF, 0, kSecAsn1UniversalStringTemplate } +}; + +const SecAsn1Template kSecAsn1UTCTimeTemplate[] = { + { SEC_ASN1_UTC_TIME | SEC_ASN1_MAY_STREAM, 0, NULL, sizeof(SecAsn1Item) } +}; + +const SecAsn1Template kSecAsn1PointerToUTCTimeTemplate[] = { + { SEC_ASN1_POINTER, 0, kSecAsn1UTCTimeTemplate } +}; + +const SecAsn1Template kSecAsn1SequenceOfUTCTimeTemplate[] = { + { SEC_ASN1_SEQUENCE_OF, 0, kSecAsn1UTCTimeTemplate } +}; + +const SecAsn1Template kSecAsn1SetOfUTCTimeTemplate[] = { + { SEC_ASN1_SET_OF, 0, kSecAsn1UTCTimeTemplate } +}; + +const SecAsn1Template kSecAsn1UTF8StringTemplate[] = { + { SEC_ASN1_UTF8_STRING | SEC_ASN1_MAY_STREAM, 0, NULL, sizeof(SecAsn1Item)} +}; + +const SecAsn1Template kSecAsn1PointerToUTF8StringTemplate[] = { + { SEC_ASN1_POINTER, 0, kSecAsn1UTF8StringTemplate } +}; + +const SecAsn1Template kSecAsn1SequenceOfUTF8StringTemplate[] = { + { SEC_ASN1_SEQUENCE_OF, 0, kSecAsn1UTF8StringTemplate } +}; + +const SecAsn1Template kSecAsn1SetOfUTF8StringTemplate[] = { + { SEC_ASN1_SET_OF, 0, kSecAsn1UTF8StringTemplate } +}; + +const SecAsn1Template kSecAsn1VisibleStringTemplate[] = { + { SEC_ASN1_VISIBLE_STRING | SEC_ASN1_MAY_STREAM, 0, NULL, sizeof(SecAsn1Item) } +}; + +const SecAsn1Template kSecAsn1PointerToVisibleStringTemplate[] = { + { SEC_ASN1_POINTER, 0, kSecAsn1VisibleStringTemplate } +}; + +const SecAsn1Template kSecAsn1SequenceOfVisibleStringTemplate[] = { + { SEC_ASN1_SEQUENCE_OF, 0, kSecAsn1VisibleStringTemplate } +}; + +const SecAsn1Template kSecAsn1SetOfVisibleStringTemplate[] = { + { SEC_ASN1_SET_OF, 0, kSecAsn1VisibleStringTemplate } +}; + + +/* + * Template for skipping a subitem. + * + * Note that it only makes sense to use this for decoding (when you want + * to decode something where you are only interested in one or two of + * the fields); you cannot encode a SKIP! + */ +const SecAsn1Template kSecAsn1SkipTemplate[] = { + { SEC_ASN1_SKIP } +}; + +#ifndef __APPLE__ + +/* These functions simply return the address of the above-declared templates. +** This is necessary for Windows DLLs. Sigh. +*/ +SEC_ASN1_CHOOSER_IMPLEMENT(SEC_AnyTemplate) +SEC_ASN1_CHOOSER_IMPLEMENT(SEC_BMPStringTemplate) +SEC_ASN1_CHOOSER_IMPLEMENT(SEC_BooleanTemplate) +SEC_ASN1_CHOOSER_IMPLEMENT(SEC_BitStringTemplate) +SEC_ASN1_CHOOSER_IMPLEMENT(SEC_IA5StringTemplate) +SEC_ASN1_CHOOSER_IMPLEMENT(SEC_GeneralizedTimeTemplate) +SEC_ASN1_CHOOSER_IMPLEMENT(SEC_IntegerTemplate) +SEC_ASN1_CHOOSER_IMPLEMENT(SEC_NullTemplate) +SEC_ASN1_CHOOSER_IMPLEMENT(SEC_ObjectIDTemplate) +SEC_ASN1_CHOOSER_IMPLEMENT(SEC_OctetStringTemplate) +SEC_ASN1_CHOOSER_IMPLEMENT(SEC_PointerToAnyTemplate) +SEC_ASN1_CHOOSER_IMPLEMENT(SEC_PointerToOctetStringTemplate) +SEC_ASN1_CHOOSER_IMPLEMENT(SEC_SetOfAnyTemplate) +SEC_ASN1_CHOOSER_IMPLEMENT(SEC_UTCTimeTemplate) +SEC_ASN1_CHOOSER_IMPLEMENT(SEC_UTF8StringTemplate) + +#endif /* __APPLE__ */ diff --git a/libsecurity_asn1/lib/SecAsn1Templates.h b/libsecurity_asn1/lib/SecAsn1Templates.h new file mode 100644 index 00000000..78cd73e3 --- /dev/null +++ b/libsecurity_asn1/lib/SecAsn1Templates.h @@ -0,0 +1,131 @@ +/* + * 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@ + * + * SecAsn1Templates.h - Common ASN1 primitive templates for use with SecAsn1Coder. + */ + +#ifndef _SEC_ASN1_TEMPLATES_H_ +#define _SEC_ASN1_TEMPLATES_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************/ + +/* + * Generic Templates + * One for each of the simple types, plus a special one for ANY, plus: + * - a pointer to each one of those + * - a set of each one of those + * - a sequence of each one of those + */ + +extern const SecAsn1Template kSecAsn1AnyTemplate[]; +extern const SecAsn1Template kSecAsn1BitStringTemplate[]; +extern const SecAsn1Template kSecAsn1BMPStringTemplate[]; +extern const SecAsn1Template kSecAsn1BooleanTemplate[]; +extern const SecAsn1Template kSecAsn1EnumeratedTemplate[]; +extern const SecAsn1Template kSecAsn1GeneralizedTimeTemplate[]; +extern const SecAsn1Template kSecAsn1IA5StringTemplate[]; +extern const SecAsn1Template kSecAsn1IntegerTemplate[]; +extern const SecAsn1Template kSecAsn1UnsignedIntegerTemplate[]; +extern const SecAsn1Template kSecAsn1NullTemplate[]; +extern const SecAsn1Template kSecAsn1ObjectIDTemplate[]; +extern const SecAsn1Template kSecAsn1OctetStringTemplate[]; +extern const SecAsn1Template kSecAsn1PrintableStringTemplate[]; +extern const SecAsn1Template kSecAsn1T61StringTemplate[]; +extern const SecAsn1Template kSecAsn1UniversalStringTemplate[]; +extern const SecAsn1Template kSecAsn1UTCTimeTemplate[]; +extern const SecAsn1Template kSecAsn1UTF8StringTemplate[]; +extern const SecAsn1Template kSecAsn1VisibleStringTemplate[]; +extern const SecAsn1Template kSecAsn1TeletexStringTemplate[]; + +extern const SecAsn1Template kSecAsn1PointerToAnyTemplate[]; +extern const SecAsn1Template kSecAsn1PointerToBitStringTemplate[]; +extern const SecAsn1Template kSecAsn1PointerToBMPStringTemplate[]; +extern const SecAsn1Template kSecAsn1PointerToBooleanTemplate[]; +extern const SecAsn1Template kSecAsn1PointerToEnumeratedTemplate[]; +extern const SecAsn1Template kSecAsn1PointerToGeneralizedTimeTemplate[]; +extern const SecAsn1Template kSecAsn1PointerToIA5StringTemplate[]; +extern const SecAsn1Template kSecAsn1PointerToIntegerTemplate[]; +extern const SecAsn1Template kSecAsn1PointerToNullTemplate[]; +extern const SecAsn1Template kSecAsn1PointerToObjectIDTemplate[]; +extern const SecAsn1Template kSecAsn1PointerToOctetStringTemplate[]; +extern const SecAsn1Template kSecAsn1PointerToPrintableStringTemplate[]; +extern const SecAsn1Template kSecAsn1PointerToT61StringTemplate[]; +extern const SecAsn1Template kSecAsn1PointerToUniversalStringTemplate[]; +extern const SecAsn1Template kSecAsn1PointerToUTCTimeTemplate[]; +extern const SecAsn1Template kSecAsn1PointerToUTF8StringTemplate[]; +extern const SecAsn1Template kSecAsn1PointerToVisibleStringTemplate[]; +extern const SecAsn1Template kSecAsn1PointerToTeletexStringTemplate[]; + +extern const SecAsn1Template kSecAsn1SequenceOfAnyTemplate[]; +extern const SecAsn1Template kSecAsn1SequenceOfBitStringTemplate[]; +extern const SecAsn1Template kSecAsn1SequenceOfBMPStringTemplate[]; +extern const SecAsn1Template kSecAsn1SequenceOfBooleanTemplate[]; +extern const SecAsn1Template kSecAsn1SequenceOfEnumeratedTemplate[]; +extern const SecAsn1Template kSecAsn1SequenceOfGeneralizedTimeTemplate[]; +extern const SecAsn1Template kSecAsn1SequenceOfIA5StringTemplate[]; +extern const SecAsn1Template kSecAsn1SequenceOfIntegerTemplate[]; +extern const SecAsn1Template kSecAsn1SequenceOfNullTemplate[]; +extern const SecAsn1Template kSecAsn1SequenceOfObjectIDTemplate[]; +extern const SecAsn1Template kSecAsn1SequenceOfOctetStringTemplate[]; +extern const SecAsn1Template kSecAsn1SequenceOfPrintableStringTemplate[]; +extern const SecAsn1Template kSecAsn1SequenceOfT61StringTemplate[]; +extern const SecAsn1Template kSecAsn1SequenceOfUniversalStringTemplate[]; +extern const SecAsn1Template kSecAsn1SequenceOfUTCTimeTemplate[]; +extern const SecAsn1Template kSecAsn1SequenceOfUTF8StringTemplate[]; +extern const SecAsn1Template kSecAsn1SequenceOfVisibleStringTemplate[]; +extern const SecAsn1Template kSecAsn1SequenceOfTeletexStringTemplate[]; + +extern const SecAsn1Template kSecAsn1SetOfAnyTemplate[]; +extern const SecAsn1Template kSecAsn1SetOfBitStringTemplate[]; +extern const SecAsn1Template kSecAsn1SetOfBMPStringTemplate[]; +extern const SecAsn1Template kSecAsn1SetOfBooleanTemplate[]; +extern const SecAsn1Template kSecAsn1SetOfEnumeratedTemplate[]; +extern const SecAsn1Template kSecAsn1SetOfGeneralizedTimeTemplate[]; +extern const SecAsn1Template kSecAsn1SetOfIA5StringTemplate[]; +extern const SecAsn1Template kSecAsn1SetOfIntegerTemplate[]; +extern const SecAsn1Template kSecAsn1SetOfNullTemplate[]; +extern const SecAsn1Template kSecAsn1SetOfObjectIDTemplate[]; +extern const SecAsn1Template kSecAsn1SetOfOctetStringTemplate[]; +extern const SecAsn1Template kSecAsn1SetOfPrintableStringTemplate[]; +extern const SecAsn1Template kSecAsn1SetOfT61StringTemplate[]; +extern const SecAsn1Template kSecAsn1SetOfUniversalStringTemplate[]; +extern const SecAsn1Template kSecAsn1SetOfUTCTimeTemplate[]; +extern const SecAsn1Template kSecAsn1SetOfUTF8StringTemplate[]; +extern const SecAsn1Template kSecAsn1SetOfVisibleStringTemplate[]; +extern const SecAsn1Template kSecAsn1SetOfTeletexStringTemplate[]; + +/* + * Template for skipping a subitem; only used when decoding. + */ +extern const SecAsn1Template kSecAsn1SkipTemplate[]; + +#ifdef __cplusplus +} +#endif + +#endif /* _SEC_ASN1_TEMPLATES_H_ */ diff --git a/libsecurity_asn1/lib/SecAsn1Types.h b/libsecurity_asn1/lib/SecAsn1Types.h new file mode 100644 index 00000000..d82f5e2e --- /dev/null +++ b/libsecurity_asn1/lib/SecAsn1Types.h @@ -0,0 +1,241 @@ +/* + * 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. + */ + +/* + * Types for encoding/decoding of ASN.1 using BER/DER (Basic/Distinguished + * Encoding Rules). + */ + +#ifndef _SEC_ASN1_TYPES_H_ +#define _SEC_ASN1_TYPES_H_ + +#include /* Boolean */ +#include +#include + +#include +#if TARGET_OS_EMBEDDED || TARGET_IPHONE_SIMULATOR +/* @@@ We need something that tells us which platform we are building + for that let's us distinguish if we are doing an emulator build. */ + +typedef struct { + size_t Length; + uint8_t *Data; +} SecAsn1Item, SecAsn1Oid; + +typedef struct { + SecAsn1Oid algorithm; + SecAsn1Item parameters; +} SecAsn1AlgId; + +typedef struct { + SecAsn1AlgId algorithm; + SecAsn1Item subjectPublicKey; +} SecAsn1PubKeyInfo; + +#else +#include +#include + +typedef CSSM_DATA SecAsn1Item; +typedef CSSM_OID SecAsn1Oid; +typedef CSSM_X509_ALGORITHM_IDENTIFIER SecAsn1AlgId; +typedef CSSM_X509_SUBJECT_PUBLIC_KEY_INFO SecAsn1PubKeyInfo; + +#endif + +/* + * An array of these structures defines a BER/DER encoding for an object. + * + * The array usually starts with a dummy entry whose kind is SEC_ASN1_SEQUENCE; + * such an array is terminated with an entry where kind == 0. (An array + * which consists of a single component does not require a second dummy + * entry -- the array is only searched as long as previous component(s) + * instruct it.) + */ +typedef struct SecAsn1Template_struct { + /* + * Kind of item being decoded/encoded, including tags and modifiers. + */ + uint32_t kind; + + /* + * This value is the offset from the base of the structure (i.e., the + * (void *) passed as 'src' to SecAsn1EncodeItem, or the 'dst' argument + * passed to SecAsn1CoderRef()) to the field that holds the value being + * decoded/encoded. + */ + uint32_t offset; + + /* + * When kind suggests it (e.g., SEC_ASN1_POINTER, SEC_ASN1_GROUP, + * SEC_ASN1_INLINE, or a component that is *not* a SEC_ASN1_UNIVERSAL), + * this points to a sub-template for nested encoding/decoding. + * OR, iff SEC_ASN1_DYNAMIC is set, then this is a pointer to a pointer + * to a function which will return the appropriate template when called + * at runtime. NOTE! that explicit level of indirection, which is + * necessary because ANSI does not allow you to store a function + * pointer directly as a "void *" so we must store it separately and + * dereference it to get at the function pointer itself. + */ + const void *sub; + + /* + * In the first element of a template array, the value is the size + * of the structure to allocate when this template is being referenced + * by another template via SEC_ASN1_POINTER or SEC_ASN1_GROUP. + * In all other cases, the value is ignored. + */ + uint32_t size; +} SecAsn1Template; + + +/* + * BER/DER values for ASN.1 identifier octets. + */ +#define SEC_ASN1_TAG_MASK 0xff + +/* + * BER/DER universal type tag numbers. + */ +#define SEC_ASN1_TAGNUM_MASK 0x1f +#define SEC_ASN1_BOOLEAN 0x01 +#define SEC_ASN1_INTEGER 0x02 +#define SEC_ASN1_BIT_STRING 0x03 +#define SEC_ASN1_OCTET_STRING 0x04 +#define SEC_ASN1_NULL 0x05 +#define SEC_ASN1_OBJECT_ID 0x06 +#define SEC_ASN1_OBJECT_DESCRIPTOR 0x07 +/* External type and instance-of type 0x08 */ +#define SEC_ASN1_REAL 0x09 +#define SEC_ASN1_ENUMERATED 0x0a +#define SEC_ASN1_EMBEDDED_PDV 0x0b +#define SEC_ASN1_UTF8_STRING 0x0c +/* not used 0x0d */ +/* not used 0x0e */ +/* not used 0x0f */ +#define SEC_ASN1_SEQUENCE 0x10 +#define SEC_ASN1_SET 0x11 +#define SEC_ASN1_NUMERIC_STRING 0x12 +#define SEC_ASN1_PRINTABLE_STRING 0x13 +#define SEC_ASN1_T61_STRING 0x14 +#define SEC_ASN1_VIDEOTEX_STRING 0x15 +#define SEC_ASN1_IA5_STRING 0x16 +#define SEC_ASN1_UTC_TIME 0x17 +#define SEC_ASN1_GENERALIZED_TIME 0x18 +#define SEC_ASN1_GRAPHIC_STRING 0x19 +#define SEC_ASN1_VISIBLE_STRING 0x1a +#define SEC_ASN1_GENERAL_STRING 0x1b +#define SEC_ASN1_UNIVERSAL_STRING 0x1c +/* not used 0x1d */ +#define SEC_ASN1_BMP_STRING 0x1e +#define SEC_ASN1_HIGH_TAG_NUMBER 0x1f +#define SEC_ASN1_TELETEX_STRING SEC_ASN1_T61_STRING + +/* + * Modifiers to type tags. These are also specified by a/the + * standard, and must not be changed. + */ +#define SEC_ASN1_METHOD_MASK 0x20 +#define SEC_ASN1_PRIMITIVE 0x00 +#define SEC_ASN1_CONSTRUCTED 0x20 + +#define SEC_ASN1_CLASS_MASK 0xc0 +#define SEC_ASN1_UNIVERSAL 0x00 +#define SEC_ASN1_APPLICATION 0x40 +#define SEC_ASN1_CONTEXT_SPECIFIC 0x80 +#define SEC_ASN1_PRIVATE 0xc0 + +/* + * Our additions, used for templates. + * These are not defined by any standard; the values are used internally only. + * Just be careful to keep them out of the low 8 bits. + */ +#define SEC_ASN1_OPTIONAL 0x00100 +#define SEC_ASN1_EXPLICIT 0x00200 +#define SEC_ASN1_ANY 0x00400 +#define SEC_ASN1_INLINE 0x00800 +#define SEC_ASN1_POINTER 0x01000 +#define SEC_ASN1_GROUP 0x02000 /* with SET or SEQUENCE means + * SET OF or SEQUENCE OF */ +#define SEC_ASN1_DYNAMIC 0x04000 /* subtemplate is found by calling + * a function at runtime */ +#define SEC_ASN1_SKIP 0x08000 /* skip a field; only for decoding */ +#define SEC_ASN1_INNER 0x10000 /* with ANY means capture the + * contents only (not the id, len, + * or eoc); only for decoding */ +#define SEC_ASN1_SAVE 0x20000 /* stash away the encoded bytes first; + * only for decoding */ +#define SEC_ASN1_SKIP_REST 0x80000 /* skip all following fields; + * only for decoding */ +#define SEC_ASN1_CHOICE 0x100000 /* pick one from a template */ + +/* + * Indicate that a type SEC_ASN1_INTEGER is actually signed. + * The default is unsigned, which causes a leading zero to be + * encoded if the MS bit of the source data is 1. + */ +#define SEC_ASN1_SIGNED_INT 0X800000 + +/* Shorthand/Aliases */ +#define SEC_ASN1_SEQUENCE_OF (SEC_ASN1_GROUP | SEC_ASN1_SEQUENCE) +#define SEC_ASN1_SET_OF (SEC_ASN1_GROUP | SEC_ASN1_SET) +#define SEC_ASN1_ANY_CONTENTS (SEC_ASN1_ANY | SEC_ASN1_INNER) + +/* + * Function used for SEC_ASN1_DYNAMIC. + * "arg" is a pointer to the top-level structure being encoded or + * decoded. + * + * "enc" when true, means that we are encoding (false means decoding) + * + * "buf" For decode only; points to the start of the decoded data for + * the current template. Callee can use the tag at this location + * to infer the returned template. Not used on encode. + * + * "Dest" points to the template-specific item being decoded to + * or encoded from. (This is as opposed to arg, which + * points to the start of the struct associated with the + * current array of templates). + */ + +typedef const SecAsn1Template * SecAsn1TemplateChooser( + void *arg, + Boolean enc, + const char *buf, + void *dest); + +typedef SecAsn1TemplateChooser * SecAsn1TemplateChooserPtr; + + +#endif /* _SEC_ASN1_TYPES_H_ */ diff --git a/libsecurity_asn1/lib/SecNssCoder.cpp b/libsecurity_asn1/lib/SecNssCoder.cpp new file mode 100644 index 00000000..5b077fe9 --- /dev/null +++ b/libsecurity_asn1/lib/SecNssCoder.cpp @@ -0,0 +1,194 @@ +/* + * 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 new file mode 100644 index 00000000..fa16abe5 --- /dev/null +++ b/libsecurity_asn1/lib/SecNssCoder.h @@ -0,0 +1,161 @@ +/* + * 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/X509Templates.c b/libsecurity_asn1/lib/X509Templates.c new file mode 100644 index 00000000..67ac9e79 --- /dev/null +++ b/libsecurity_asn1/lib/X509Templates.c @@ -0,0 +1,222 @@ +/* + * 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@ + * + * X509Templates.c - Common ASN1 templates for use with libNSSDer. + */ + +#include "SecAsn1Templates.h" +#include "X509Templates.h" +#include "keyTemplates.h" +#include +#include + +/* + * Validity + */ +/* + * NSS_Time Template chooser. + */ +static const NSS_TagChoice timeChoices[] = { + { SEC_ASN1_GENERALIZED_TIME, kSecAsn1GeneralizedTimeTemplate} , + { SEC_ASN1_UTC_TIME, kSecAsn1UTCTimeTemplate }, + { 0, NULL} +}; + +static const SecAsn1Template * NSS_TimeChooser( + void *arg, + Boolean enc, + const char *buf, + void *dest) +{ + return SecAsn1TaggedTemplateChooser(arg, enc, buf, dest, timeChoices); +} + +static const SecAsn1TemplateChooserPtr NSS_TimeChooserPtr = NSS_TimeChooser; + +const SecAsn1Template kSecAsn1ValidityTemplate[] = { + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(NSS_Validity) }, + { SEC_ASN1_INLINE | SEC_ASN1_DYNAMIC, + offsetof(NSS_Validity,notBefore.item), + &NSS_TimeChooserPtr }, + { SEC_ASN1_INLINE | SEC_ASN1_DYNAMIC, + offsetof(NSS_Validity,notAfter.item), + &NSS_TimeChooserPtr }, + { 0 } +}; + +/* X509 cert extension */ +const SecAsn1Template kSecAsn1CertExtensionTemplate[] = { + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(NSS_CertExtension) }, + { SEC_ASN1_OBJECT_ID, + offsetof(NSS_CertExtension,extnId) }, + { SEC_ASN1_OPTIONAL | SEC_ASN1_BOOLEAN, /* XXX DER_DEFAULT */ + offsetof(NSS_CertExtension,critical) }, + { SEC_ASN1_OCTET_STRING, + offsetof(NSS_CertExtension,value) }, + { 0, } +}; + +const SecAsn1Template kSecAsn1SequenceOfCertExtensionTemplate[] = { + { SEC_ASN1_SEQUENCE_OF, 0, kSecAsn1CertExtensionTemplate } +}; + +/* TBS Cert */ +const SecAsn1Template kSecAsn1TBSCertificateTemplate[] = { + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(NSS_TBSCertificate) }, + /* optional version, explicit tag 0, default 0 */ + { SEC_ASN1_EXPLICIT | SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | + SEC_ASN1_CONTEXT_SPECIFIC | 0, /* XXX DER_DEFAULT */ + offsetof(NSS_TBSCertificate,version), + kSecAsn1IntegerTemplate }, + /* serial number is SIGNED integer */ + { SEC_ASN1_INTEGER | SEC_ASN1_SIGNED_INT, + offsetof(NSS_TBSCertificate,serialNumber) }, + { SEC_ASN1_INLINE, + offsetof(NSS_TBSCertificate,signature), + kSecAsn1AlgorithmIDTemplate }, + { SEC_ASN1_SAVE, offsetof(NSS_TBSCertificate,derIssuer) }, + { SEC_ASN1_INLINE, + offsetof(NSS_TBSCertificate,issuer), + kSecAsn1NameTemplate }, + { SEC_ASN1_INLINE, + offsetof(NSS_TBSCertificate,validity), + kSecAsn1ValidityTemplate }, + { SEC_ASN1_SAVE, offsetof(NSS_TBSCertificate,derSubject) }, + { SEC_ASN1_INLINE, + offsetof(NSS_TBSCertificate,subject), + kSecAsn1NameTemplate }, + { SEC_ASN1_INLINE, + offsetof(NSS_TBSCertificate,subjectPublicKeyInfo), + kSecAsn1SubjectPublicKeyInfoTemplate }, + { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1, + offsetof(NSS_TBSCertificate,issuerID), + kSecAsn1BitStringTemplate }, + { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 2, + offsetof(NSS_TBSCertificate,subjectID), + kSecAsn1BitStringTemplate }, + { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | + SEC_ASN1_EXPLICIT | 3, + offsetof(NSS_TBSCertificate,extensions), + kSecAsn1SequenceOfCertExtensionTemplate }, + { 0 } +}; + +/* + * For signing and verifying only, treating the TBS portion as an + * opaque ASN_ANY blob. + */ +const SecAsn1Template kSecAsn1SignedCertOrCRLTemplate[] = +{ + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(NSS_SignedCertOrCRL) }, + { SEC_ASN1_ANY, + offsetof(NSS_SignedCertOrCRL,tbsBlob) }, + { SEC_ASN1_ANY, + offsetof(NSS_SignedCertOrCRL,signatureAlgorithm) }, + { SEC_ASN1_BIT_STRING, + offsetof(NSS_SignedCertOrCRL,signature) }, + { 0 } +}; + +/* Fully specified signed certificate */ +const SecAsn1Template kSecAsn1SignedCertTemplate[] = +{ + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(NSS_Certificate) }, + { SEC_ASN1_INLINE, + offsetof(NSS_Certificate,tbs), + kSecAsn1TBSCertificateTemplate }, + { SEC_ASN1_INLINE, + offsetof(NSS_Certificate,signatureAlgorithm), + kSecAsn1AlgorithmIDTemplate }, + { SEC_ASN1_BIT_STRING, + offsetof(NSS_Certificate,signature) }, + { 0 } +}; + +/* Entry in CRL.revokedCerts */ +const SecAsn1Template kSecAsn1RevokedCertTemplate[] = { + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(NSS_RevokedCert) }, + /* serial number - signed itneger, just like in the actual cert */ + { SEC_ASN1_INTEGER | SEC_ASN1_SIGNED_INT, + offsetof(NSS_RevokedCert,userCertificate) }, + { SEC_ASN1_INLINE | SEC_ASN1_DYNAMIC, + offsetof(NSS_RevokedCert,revocationDate.item), + &NSS_TimeChooserPtr }, + { SEC_ASN1_OPTIONAL | SEC_ASN1_SEQUENCE_OF, + offsetof(NSS_RevokedCert,extensions), + kSecAsn1CertExtensionTemplate }, + { 0, } +}; + +const SecAsn1Template kSecAsn1SequenceOfRevokedCertTemplate[] = { + { SEC_ASN1_SEQUENCE_OF, 0, kSecAsn1RevokedCertTemplate } +}; + +/* NSS_TBSCrl (unsigned CRL) */ +const SecAsn1Template kSecAsn1TBSCrlTemplate[] = { + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(NSS_TBSCrl) }, + /* optional version, default 0 */ + { SEC_ASN1_INTEGER | SEC_ASN1_OPTIONAL, offsetof (NSS_TBSCrl, version) }, + { SEC_ASN1_INLINE, + offsetof(NSS_TBSCrl,signature), + kSecAsn1AlgorithmIDTemplate }, + { SEC_ASN1_SAVE, offsetof(NSS_TBSCrl,derIssuer) }, + { SEC_ASN1_INLINE, + offsetof(NSS_TBSCrl,issuer), + kSecAsn1NameTemplate }, + { SEC_ASN1_INLINE | SEC_ASN1_DYNAMIC, + offsetof(NSS_TBSCrl,thisUpdate.item), + &NSS_TimeChooserPtr }, + { SEC_ASN1_INLINE | SEC_ASN1_DYNAMIC | SEC_ASN1_OPTIONAL, + offsetof(NSS_TBSCrl,nextUpdate), + &NSS_TimeChooserPtr }, + { SEC_ASN1_OPTIONAL | SEC_ASN1_SEQUENCE_OF, + offsetof(NSS_TBSCrl,revokedCerts), + kSecAsn1RevokedCertTemplate }, + { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | + SEC_ASN1_EXPLICIT | 0, + offsetof(NSS_TBSCrl,extensions), + kSecAsn1SequenceOfCertExtensionTemplate }, + { 0, } +}; + +/* Fully specified signed CRL */ +const SecAsn1Template kSecAsn1SignedCrlTemplate[] = +{ + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(NSS_Crl) }, + { SEC_ASN1_INLINE, + offsetof(NSS_Crl,tbs), + kSecAsn1TBSCrlTemplate }, + { SEC_ASN1_INLINE, + offsetof(NSS_Crl,signatureAlgorithm), + kSecAsn1AlgorithmIDTemplate }, + { SEC_ASN1_BIT_STRING, + offsetof(NSS_Crl,signature) }, + { 0 } +}; diff --git a/libsecurity_asn1/lib/X509Templates.h b/libsecurity_asn1/lib/X509Templates.h new file mode 100644 index 00000000..10c90114 --- /dev/null +++ b/libsecurity_asn1/lib/X509Templates.h @@ -0,0 +1,199 @@ +/* + * 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@ + * + * X509Templates.h - X.509 Certificate and CRL ASN1 templates + */ + +#ifndef _NSS_X509_TEMPLATES_H_ +#define _NSS_X509_TEMPLATES_H_ + +#include +#include + +/* + * Arrays of SecAsn1Templates are always associated with a specific + * C struct. We attempt to use C structs which are defined in CDSA + * if at all possible; these always start with the CSSM_ prefix. + * Otherwise we define the struct here, with an NSS_ prefix. + * In either case, the name of the C struct is listed in comments + * along with the extern declaration of the SecAsn1Template array. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#pragma mark --- X509 Validity support --- + +/* + * ASN Class : Validity + * C struct : NSS_Validity + * + * The low-level Time values, which are CHOICE of generalized + * time or UTC time, still DER-encoded upon decoding of this object. + */ +/* + * The low-level time values are eitehr Generalized Time + * (SEC_ASN1_GENERALIZED_TIME) or UTC time (SEC_ASN1_UTC_TIME). + */ +typedef NSS_TaggedItem NSS_Time; + +typedef struct { + NSS_Time notBefore; + NSS_Time notAfter; +} NSS_Validity; + +extern const SecAsn1Template kSecAsn1ValidityTemplate[]; + +#pragma mark --- Certificate --- + +/* + * X509 cert extension + * ASN Class : Extension + * C struct : NSS_CertExtension + * + * With a nontrivial amount of extension-specific processing, + * this maps to a CSSM_X509_EXTENSION. + */ +typedef struct { + SecAsn1Item extnId; + SecAsn1Item critical; // optional, default = false + SecAsn1Item value; // OCTET string whose decoded value is + // an id-specific DER-encoded thing +} NSS_CertExtension; + +extern const SecAsn1Template kSecAsn1CertExtensionTemplate[]; +extern const SecAsn1Template kSecAsn1SequenceOfCertExtensionTemplate[]; + +/* + * X.509 certificate object (the unsigned form) + * + * ASN class : TBSCertificate + * C struct : NSS_TBSCertificate + */ +typedef struct { + SecAsn1Item version; // optional + SecAsn1Item serialNumber; + SecAsn1AlgId signature; + NSS_Name issuer; + NSS_Validity validity; + NSS_Name subject; + SecAsn1PubKeyInfo subjectPublicKeyInfo; + SecAsn1Item issuerID; // optional, BITS + SecAsn1Item subjectID; // optional, BITS + NSS_CertExtension **extensions; // optional + + /* + * Additional DER-encoded fields copied (via SEC_ASN1_SAVE) + * during decoding. + */ + SecAsn1Item derIssuer; + SecAsn1Item derSubject; +} NSS_TBSCertificate; + +extern const SecAsn1Template kSecAsn1TBSCertificateTemplate[]; + +/* + * Fully specified signed certificate. + * + * ASN class : Certificate + * C struct : NSS_Certificate + */ +typedef struct { + NSS_TBSCertificate tbs; + SecAsn1AlgId signatureAlgorithm; + SecAsn1Item signature;// BIT STRING, length in bits +} NSS_Certificate; + +extern const SecAsn1Template kSecAsn1SignedCertTemplate[]; + +#pragma mark --- CRL --- + +/* + * ASN class : revokedCertificate + * C struct : NSS_RevokedCert + */ +typedef struct { + SecAsn1Item userCertificate; // serial number + NSS_Time revocationDate; + NSS_CertExtension **extensions; // optional +} NSS_RevokedCert; + +extern const SecAsn1Template kSecAsn1RevokedCertTemplate[]; +extern const SecAsn1Template kSecAsn1SequenceOfRevokedCertTemplate[]; + +/* + * X509 Cert Revocation List (the unsigned form) + * ASN class : TBSCertList + * C struct : NSS_TBSCrl + */ +typedef struct { + SecAsn1Item version; // optional + SecAsn1AlgId signature; + NSS_Name issuer; + NSS_Time thisUpdate; + NSS_Time nextUpdate; // optional + NSS_RevokedCert **revokedCerts; // optional + NSS_CertExtension **extensions; // optional + + /* + * Additional DER-encoded fields copied (via SEC_ASN1_SAVE) + * during decoding. + */ + SecAsn1Item derIssuer; + +} NSS_TBSCrl; + +extern const SecAsn1Template kSecAsn1TBSCrlTemplate[]; + +/* + * Fully specified signed CRL. + * + * ASN class : CertificateList + * C struct : NSS_CRL + */ +typedef struct { + NSS_TBSCrl tbs; + SecAsn1AlgId signatureAlgorithm; + SecAsn1Item signature;// BIT STRING, length in bits +} NSS_Crl; + +extern const SecAsn1Template kSecAsn1SignedCrlTemplate[]; + +/* + * signed data - top-level view of a signed Cert or CRL, for + * signing and verifying only. Treats the TBS and AlgId portions + * as opaque ASN_ANY blobs. + */ +typedef struct { + SecAsn1Item tbsBlob; // ANY, DER encoded cert or CRL + SecAsn1Item signatureAlgorithm; + SecAsn1Item signature;// BIT STRING, length in bits +} NSS_SignedCertOrCRL; + +extern const SecAsn1Template kSecAsn1SignedCertOrCRLTemplate[]; + +#ifdef __cplusplus +} +#endif + +#endif /* _NSS_X509_TEMPLATES_H_ */ diff --git a/libsecurity_asn1/lib/asn1Templates.h b/libsecurity_asn1/lib/asn1Templates.h new file mode 100644 index 00000000..70f6fa47 --- /dev/null +++ b/libsecurity_asn1/lib/asn1Templates.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2005-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@ + * + * asn1Templates.h - Common ASN1 primitive templates for use with SecAsn1Coder. + */ + +#ifndef _ASN1_TEMPLATES_H_ +#define _ASN1_TEMPLATES_H_ + +#warning This is for backwards compatibility. Please use instead. + +#include + +#endif /* _ASN1_TEMPLATES_H_ */ diff --git a/libsecurity_asn1/lib/certExtensionTemplates.c b/libsecurity_asn1/lib/certExtensionTemplates.c new file mode 100644 index 00000000..b15c23be --- /dev/null +++ b/libsecurity_asn1/lib/certExtensionTemplates.c @@ -0,0 +1,322 @@ +/* + * 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@ + * + * certExtensionTemplates.cpp - libnssasn1 structs and templates for cert and + * CRL extensions + * + */ + +#include "certExtensionTemplates.h" +#include "SecAsn1Templates.h" +#include + +/* Basic Constraints */ +const SecAsn1Template kSecAsn1BasicConstraintsTemplate[] = { + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(NSS_BasicConstraints) }, + { SEC_ASN1_BOOLEAN | SEC_ASN1_OPTIONAL, + offsetof(NSS_BasicConstraints,cA) }, + { SEC_ASN1_INTEGER | SEC_ASN1_OPTIONAL, + offsetof(NSS_BasicConstraints, pathLenConstraint) }, + { 0, } +}; + +/* Authority Key Identifier */ + +/* signed integer - SEC_ASN1_SIGNED_INT state gets lost + * in SEC_ASN1_CONTEXT_SPECIFIC processing */ +const SecAsn1Template kSecAsn1SignedIntegerTemplate[] = { + { SEC_ASN1_INTEGER | SEC_ASN1_SIGNED_INT, 0, NULL, sizeof(SecAsn1Item) } +}; + +const SecAsn1Template kSecAsn1AuthorityKeyIdTemplate[] = { + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(NSS_AuthorityKeyId) }, + { SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC | + SEC_ASN1_POINTER | 0, + offsetof(NSS_AuthorityKeyId,keyIdentifier), + kSecAsn1OctetStringTemplate }, + { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | + SEC_ASN1_CONTEXT_SPECIFIC | 1, + offsetof(NSS_AuthorityKeyId,genNames), + kSecAsn1GeneralNamesTemplate }, + /* serial number is SIGNED integer */ + { SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC | 2, + offsetof(NSS_AuthorityKeyId,serialNumber), + kSecAsn1SignedIntegerTemplate}, + { 0 } +}; + +/* Certificate policies */ +const SecAsn1Template kSecAsn1PolicyQualifierTemplate[] = { + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(NSS_PolicyQualifierInfo) }, + { SEC_ASN1_OBJECT_ID, + offsetof(NSS_PolicyQualifierInfo,policyQualifierId) }, + { SEC_ASN1_ANY, offsetof(NSS_PolicyQualifierInfo, qualifier) }, + { 0 } +}; + +const SecAsn1Template kSecAsn1PolicyInformationTemplate[] = { + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(NSS_PolicyInformation) }, + { SEC_ASN1_OBJECT_ID, + offsetof(NSS_PolicyInformation,certPolicyId) }, + { SEC_ASN1_SEQUENCE_OF | SEC_ASN1_OPTIONAL, + offsetof(NSS_PolicyInformation,policyQualifiers), + kSecAsn1PolicyQualifierTemplate }, + { 0 } +}; + +const SecAsn1Template kSecAsn1CertPoliciesTemplate[] = { + { SEC_ASN1_SEQUENCE_OF, + offsetof(NSS_CertPolicies,policies), + kSecAsn1PolicyInformationTemplate }, + { 0 } +}; + +/* CRL Distribution Points */ + +/* + * NOTE WELL: RFC2459, and all the documentation I can find, claims that + * the tag for the DistributionPointName option (tag 0) of a + * DistributionPoint is IMPLICIT and context-specific. However this + * is IMPOSSIBLE - since the underlying type (DistributionPointName) + * also relies upon context-specific tags to resolve a CHOICE. + * The real world indicates that the tag for the DistributionPoint option + * is indeed EXPLICIT. Examination of many certs' cRLDistributionPoints + * extensions shows this, and the NSS reference code also specifies + * an EXPLICIT tag for this field. + */ +const SecAsn1Template kSecAsn1DistributionPointTemplate[] = { + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(NSS_DistributionPoint) }, + { SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC | + SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT | 0, + offsetof(NSS_DistributionPoint,distPointName), + kSecAsn1PointerToAnyTemplate }, + { SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC | 1, + offsetof(NSS_DistributionPoint,reasons), kSecAsn1BitStringTemplate}, + { SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC | + SEC_ASN1_CONSTRUCTED | 2, + offsetof(NSS_DistributionPoint, crlIssuer), + kSecAsn1GeneralNamesTemplate + }, + { 0 } +}; + +const SecAsn1Template kSecAsn1CRLDistributionPointsTemplate[] = { + { SEC_ASN1_SEQUENCE_OF, + offsetof(NSS_CRLDistributionPoints,distPoints), + kSecAsn1DistributionPointTemplate }, + { 0 } +}; + + +/* + * These are the context-specific targets of the DistributionPointName + * option. + */ +const SecAsn1Template kSecAsn1DistPointFullNameTemplate[] = { + {SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_CONSTRUCTED | 0, + offsetof (NSS_GeneralNames,names), kSecAsn1GeneralNamesTemplate} +}; + +const SecAsn1Template kSecAsn1DistPointRDNTemplate[] = { + {SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_CONSTRUCTED | 1, + offsetof (NSS_RDN,atvs), kSecAsn1RDNTemplate} +}; + +/* + * Issuing distribution points + * + * Although the spec says that the DistributionPointName element + * is context-specific, it must be explicit because the underlying + * type - a DistributionPointName - also relies on a context-specific + * tags to resolve a CHOICE. + */ + +/* kludge: ASN decoder doesn't handle + * SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_POINTER + * very well... */ +static const SecAsn1Template kSecAsn1OptBooleanTemplate[] = { + { SEC_ASN1_BOOLEAN | SEC_ASN1_OPTIONAL, 0, NULL, sizeof(SecAsn1Item) } +}; + +static const SecAsn1Template kSecAsn1OptBitStringTemplate[] = { + { SEC_ASN1_BIT_STRING | SEC_ASN1_OPTIONAL, 0, NULL, sizeof(SecAsn1Item) } +}; + +const SecAsn1Template kSecAsn1IssuingDistributionPointTemplate[] = { + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(NSS_IssuingDistributionPoint) }, + { SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC | + SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT | 0, + offsetof(NSS_IssuingDistributionPoint,distPointName), + kSecAsn1PointerToAnyTemplate }, + { SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_POINTER | 1, + offsetof(NSS_IssuingDistributionPoint,onlyUserCerts), + kSecAsn1OptBooleanTemplate}, + { SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_POINTER | 2, + offsetof(NSS_IssuingDistributionPoint,onlyCACerts), + kSecAsn1OptBooleanTemplate}, + { SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_POINTER | 3, + offsetof(NSS_IssuingDistributionPoint,onlySomeReasons), + kSecAsn1OptBitStringTemplate}, + { SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_POINTER | 4, + offsetof(NSS_IssuingDistributionPoint,indirectCRL), + kSecAsn1OptBooleanTemplate}, + { 0 } +}; + + +/* + * Authority Information Access and Subject Information Access. + */ +const SecAsn1Template kSecAsn1AccessDescriptionTemplate[] = { + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(NSS_AccessDescription) }, + { SEC_ASN1_OBJECT_ID, + offsetof(NSS_AccessDescription,accessMethod) }, + /* + * NSS encoder just can't handle direct inline of an NSS_GeneralName here. + */ + { SEC_ASN1_ANY, + offsetof(NSS_AccessDescription, encodedAccessLocation) }, + { 0 } +}; + +const SecAsn1Template kSecAsn1AuthorityInfoAccessTemplate[] = { + { SEC_ASN1_SEQUENCE_OF, + offsetof(NSS_AuthorityInfoAccess,accessDescriptions), + kSecAsn1AccessDescriptionTemplate, + sizeof(NSS_AuthorityInfoAccess) } +}; + +/* + * Qualified Certificate Statements templates. + * + * This is the NSS_QC_Statement.info when NSS_QC_Statement.statementId + * is CSSMOID_OID_QCS_SYNTAX_V2. + */ +const SecAsn1Template kSecAsn1SemanticsInformationTemplate[] = { + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(NSS_SemanticsInformation) }, + { SEC_ASN1_OPTIONAL | SEC_ASN1_POINTER, + offsetof(NSS_SemanticsInformation,semanticsIdentifier), + kSecAsn1ObjectIDTemplate }, + { SEC_ASN1_OPTIONAL | SEC_ASN1_POINTER, + offsetof(NSS_SemanticsInformation, nameRegistrationAuthorities), + kSecAsn1GeneralNamesTemplate }, + { 0 } +}; + +const SecAsn1Template kSecAsn1QC_StatementTemplate[] = { + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(NSS_QC_Statement) }, + { SEC_ASN1_OBJECT_ID, + offsetof(NSS_QC_Statement,statementId) }, + { SEC_ASN1_ANY | SEC_ASN1_OPTIONAL, + offsetof(NSS_QC_Statement, info) }, + { 0 } +}; + +const SecAsn1Template kSecAsn1QC_StatementsTemplate[] = { + { SEC_ASN1_SEQUENCE_OF, + offsetof(NSS_QC_Statements,qcStatements), + kSecAsn1QC_StatementTemplate, + sizeof(NSS_QC_Statements) } +}; + +/* + * NameConstraints templates + */ +const SecAsn1Template kSecAsn1GeneralSubtreeTemplate[] = { + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(NSS_GeneralSubtree) }, + { SEC_ASN1_SEQUENCE, + offsetof(NSS_GeneralSubtree,base), + kSecAsn1GeneralNamesTemplate }, + { SEC_ASN1_INTEGER, + offsetof(NSS_GeneralSubtree,minimum) }, + { SEC_ASN1_INTEGER | SEC_ASN1_OPTIONAL, + offsetof(NSS_GeneralSubtree,maximum) }, + { 0, } +}; + +const SecAsn1Template kSecAsn1GeneralSubtreesTemplate[] = { + { SEC_ASN1_SEQUENCE_OF, + offsetof(NSS_GeneralSubtrees,subtrees), + kSecAsn1GeneralSubtreeTemplate }, + { 0 } +}; + +const SecAsn1Template kSecAsn1NameConstraintsTemplate[] = { + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(NSS_NameConstraints) }, + { SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC | + SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT | 0, + offsetof(NSS_NameConstraints,permittedSubtrees), + kSecAsn1GeneralSubtreesTemplate }, + { SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC | + SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT | 1, + offsetof(NSS_NameConstraints,excludedSubtrees), + kSecAsn1GeneralSubtreesTemplate }, + { 0 } +}; + +/* + * PolicyMappings templates + */ +const SecAsn1Template kSecAsn1PolicyMappingTemplate[] = { + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(NSS_PolicyMapping) }, + { SEC_ASN1_OBJECT_ID, + offsetof(NSS_PolicyMapping,issuerDomainPolicy) }, + { SEC_ASN1_OBJECT_ID, + offsetof(NSS_PolicyMapping,subjectDomainPolicy) }, + { 0 } +}; + +const SecAsn1Template kSecAsn1PolicyMappingsTemplate[] = { + { SEC_ASN1_SEQUENCE_OF, + offsetof(NSS_PolicyMappings,policyMappings), + kSecAsn1PolicyMappingTemplate }, + { 0 } +}; + +/* + * PolicyConstraints templates + */ +const SecAsn1Template kSecAsn1PolicyConstraintsTemplate[] = { + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(NSS_PolicyConstraints) }, + { SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC | + SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT | 0, + offsetof(NSS_PolicyConstraints,requireExplicitPolicy) }, + { SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC | + SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT | 1, + offsetof(NSS_PolicyConstraints,inhibitPolicyMapping) }, + { 0 } +}; + + diff --git a/libsecurity_asn1/lib/certExtensionTemplates.h b/libsecurity_asn1/lib/certExtensionTemplates.h new file mode 100644 index 00000000..644c8fe9 --- /dev/null +++ b/libsecurity_asn1/lib/certExtensionTemplates.h @@ -0,0 +1,274 @@ +/* + * 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@ + * + * certExtensionTemplates.h - libnssasn1 structs and templates for cert and + * CRL extensions + * + */ + +#ifndef _CERT_EXTENSION_TEMPLATES_H_ +#define _CERT_EXTENSION_TEMPLATES_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Basic Constraints + * NSS struct : NSS_BasicConstraints + * CDSA struct : CE_BasicConstraints + */ +typedef struct { + SecAsn1Item cA; // BOOL + SecAsn1Item pathLenConstraint; // INTEGER optional +} NSS_BasicConstraints; + +extern const SecAsn1Template kSecAsn1BasicConstraintsTemplate[]; + +/* + * Key Usage + * NSS struct : SecAsn1Item, BIT STRING - length in bits + * CDSA struct : CE_KeyUsage + */ +#define kSecAsn1KeyUsageTemplate kSecAsn1BitStringTemplate + +/* + * Extended Key Usage + * NSS struct : NSS_ExtKeyUsage + * CDSA struct : CE_ExtendedKeyUsage + */ +typedef struct { + SecAsn1Oid **purposes; +} NSS_ExtKeyUsage; +#define kSecAsn1ExtKeyUsageTemplate kSecAsn1SequenceOfObjectIDTemplate + +/* + * Subject Key Identifier + * NSS struct : SecAsn1Item + * CDSA struct : CE_SubjectKeyID, typedef'd to a SecAsn1Item + */ +#define kSecAsn1SubjectKeyIdTemplate kSecAsn1OctetStringTemplate + +/* + * Authority Key Identifier + * NSS struct : NSS_AuthorityKeyId + * CDSA struct : CE_AuthorityKeyID + * + * All fields are optional. + * NOTE: due to an anomaly in the encoding module, if the first field + * of a sequence is optional, it has to be a POINTER type. + */ +typedef struct { + SecAsn1Item *keyIdentifier; // octet string + NSS_GeneralNames genNames; + SecAsn1Item serialNumber; // integer +} NSS_AuthorityKeyId; + +extern const SecAsn1Template kSecAsn1AuthorityKeyIdTemplate[]; + +/* + * Certificate policies. + * NSS struct : NSS_CertPolicies + * CDSA struct : CE_CertPolicies + */ +typedef struct { + SecAsn1Oid policyQualifierId; // CSSMOID_QT_CPS, CSSMOID_QT_UNOTICE + SecAsn1Item qualifier; // ASN_ANY, not interpreted here +} NSS_PolicyQualifierInfo; + +extern const SecAsn1Template kSecAsn1PolicyQualifierTemplate[]; + +typedef struct { + SecAsn1Oid certPolicyId; + NSS_PolicyQualifierInfo **policyQualifiers; // SEQUENCE OF +} NSS_PolicyInformation; + +extern const SecAsn1Template kSecAsn1PolicyInformationTemplate[]; + +typedef struct { + NSS_PolicyInformation **policies; // SEQUENCE OF +} NSS_CertPolicies; + +extern const SecAsn1Template kSecAsn1CertPoliciesTemplate[]; + +/* + * netscape-cert-type + * NSS struct : SecAsn1Item, BIT STRING - length in bits + * CDSA struct : CE_NetscapeCertType (a uint16) + */ +#define kSecAsn1NetscapeCertTypeTemplate kSecAsn1BitStringTemplate + +/* + * CRL Distribution Points. + * NSS struct : NSS_DistributionPoint, NSS_DistributionPoints + * CDSA struct : CE_CRLDistributionPoint, CE_CRLDistributionPointSyntax + */ + +typedef struct { + SecAsn1Item *distPointName; // ASN_ANY, optional + SecAsn1Item reasons; // BIT_STRING, optional + NSS_GeneralNames crlIssuer; // optional +} NSS_DistributionPoint; + +typedef struct { + NSS_DistributionPoint **distPoints; // SEQUENCE OF +} NSS_CRLDistributionPoints; + +extern const SecAsn1Template kSecAsn1DistributionPointTemplate[]; +extern const SecAsn1Template kSecAsn1CRLDistributionPointsTemplate[]; + +/* + * Resolving the NSS_DistributionPoint.distributionPoint option + * involves inspecting the tag of the ASN_ANY and using one of + * these templates. One the CDSA side the corresponding struct is + * a CE_DistributionPointName. + * + * This one resolves to an NSS_GeneralNames: + */ +#define NSS_DIST_POINT_FULL_NAME_TAG 0 +extern const SecAsn1Template kSecAsn1DistPointFullNameTemplate[]; + +/* + * This one resolves to an NSS_RDN. + */ +#define NSS_DIST_POINT_RDN_TAG 1 +extern const SecAsn1Template kSecAsn1DistPointRDNTemplate[]; + +/* + * Issuing distribution point. + * + * NSS Struct : NSS_IssuingDistributionPoint + * CDSA struct : CE_IssuingDistributionPoint + * + * All fields optional; default for ASN_BOOLs is false. + */ +typedef struct { + /* manually decode to a CE_DistributionPointName */ + SecAsn1Item *distPointName; // ASN_ANY, optional + + SecAsn1Item *onlyUserCerts; // ASN_BOOL + SecAsn1Item *onlyCACerts; // ASN_BOOL + SecAsn1Item *onlySomeReasons; // BIT STRING + SecAsn1Item *indirectCRL; // ASN_BOOL +} NSS_IssuingDistributionPoint; + +extern const SecAsn1Template kSecAsn1IssuingDistributionPointTemplate[]; + +/* + * Authority Information Access, Subject Information Access. + * + * NSS Struct : NSS_AuthorityInfoAccess + * CDSA struct : CE_AuthorityInfoAccess + */ +typedef struct { + SecAsn1Item accessMethod; + + /* NSS encoder just can't handle direct inline of an NSS_GeneralName here. + * After decode and prior to encode this is an encoded GeneralName. + */ + SecAsn1Item encodedAccessLocation; +} NSS_AccessDescription; + +typedef struct { + NSS_AccessDescription **accessDescriptions; +} NSS_AuthorityInfoAccess; + +extern const SecAsn1Template kSecAsn1AccessDescriptionTemplate[]; +extern const SecAsn1Template kSecAsn1AuthorityInfoAccessTemplate[]; + +/* + * Qualified Certificate Statements support + */ +typedef struct { + SecAsn1Oid *semanticsIdentifier; /* optional */ + NSS_GeneralNames *nameRegistrationAuthorities; /* optional */ +} NSS_SemanticsInformation; + +typedef struct { + SecAsn1Oid statementId; + SecAsn1Item info; /* optional, ANY */ +} NSS_QC_Statement; + +typedef struct { + NSS_QC_Statement **qcStatements; +} NSS_QC_Statements; + +extern const SecAsn1Template kSecAsn1SemanticsInformationTemplate[]; +extern const SecAsn1Template kSecAsn1QC_StatementTemplate[]; +extern const SecAsn1Template kSecAsn1QC_StatementsTemplate[]; + +/* + * NameConstraints support + */ +typedef struct { + NSS_GeneralNames base; + SecAsn1Item minimum; // INTEGER default=0 + SecAsn1Item maximum; // INTEGER optional +} NSS_GeneralSubtree; + +typedef struct { + NSS_GeneralSubtree **subtrees; // SEQUENCE OF +} NSS_GeneralSubtrees; + +typedef struct { + NSS_GeneralSubtrees *permittedSubtrees; // optional + NSS_GeneralSubtrees *excludedSubtrees; // optional +} NSS_NameConstraints; + +extern const SecAsn1Template kSecAsn1NameConstraintsTemplate[]; + +/* + * PolicyMappings support + */ +typedef struct { + SecAsn1Oid issuerDomainPolicy; + SecAsn1Oid subjectDomainPolicy; +} NSS_PolicyMapping; + +typedef struct { + NSS_PolicyMapping **policyMappings; // SEQUENCE OF +} NSS_PolicyMappings; + +extern const SecAsn1Template kSecAsn1PolicyMappingsTemplate[]; + +/* + * PolicyConstraints support + */ +typedef struct { + SecAsn1Item requireExplicitPolicy; // INTEGER optional + SecAsn1Item inhibitPolicyMapping; // INTEGER optional +} NSS_PolicyConstraints; + +extern const SecAsn1Template kSecAsn1PolicyConstraintsTemplate[]; + +/* + * InhibitAnyPolicy support + */ +#define kSecAsn1InhibitAnyPolicyTemplate kSecAsn1IntegerTemplate; + +#ifdef __cplusplus +} +#endif + +#endif /* _CERT_EXTENSION_TEMPLATES_H_ */ diff --git a/libsecurity_asn1/lib/csrTemplates.c b/libsecurity_asn1/lib/csrTemplates.c new file mode 100644 index 00000000..9d01f713 --- /dev/null +++ b/libsecurity_asn1/lib/csrTemplates.c @@ -0,0 +1,69 @@ +/* + * 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@ + * + * csrTemplates.cpp - ASN1 templates Cert Signing Requests (per PKCS10). + */ + +#include "SecAsn1Templates.h" +#include +#include "csrTemplates.h" +#include "keyTemplates.h" + +const SecAsn1Template kSecAsn1CertRequestInfoTemplate[] = { + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSCertRequestInfo) }, + { SEC_ASN1_INTEGER, offsetof(NSSCertRequestInfo,version) }, + { SEC_ASN1_INLINE, + offsetof(NSSCertRequestInfo,subject), + kSecAsn1NameTemplate }, + { SEC_ASN1_INLINE, + offsetof(NSSCertRequestInfo,subjectPublicKeyInfo), + kSecAsn1SubjectPublicKeyInfoTemplate }, + { SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0, + offsetof(NSSCertRequestInfo,attributes), + kSecAsn1SetOfAttributeTemplate }, + { 0 } +}; + +const SecAsn1Template kSecAsn1CertRequestTemplate[] = { + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSCertRequest) }, + { SEC_ASN1_INLINE, + offsetof(NSSCertRequest,reqInfo), + kSecAsn1CertRequestInfoTemplate }, + { SEC_ASN1_INLINE, + offsetof(NSSCertRequest,signatureAlgorithm), + kSecAsn1AlgorithmIDTemplate }, + { SEC_ASN1_BIT_STRING, offsetof(NSSCertRequest,signature) }, + { 0 } +}; + +const SecAsn1Template kSecAsn1SignedCertRequestTemplate[] = { + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSS_SignedCertRequest) }, + { SEC_ASN1_ANY, + offsetof(NSS_SignedCertRequest,certRequestBlob), + kSecAsn1CertRequestInfoTemplate }, + { SEC_ASN1_INLINE, + offsetof(NSS_SignedCertRequest,signatureAlgorithm), + kSecAsn1AlgorithmIDTemplate }, + { SEC_ASN1_BIT_STRING, offsetof(NSS_SignedCertRequest,signature) }, + { 0 } +}; + diff --git a/libsecurity_asn1/lib/csrTemplates.h b/libsecurity_asn1/lib/csrTemplates.h new file mode 100644 index 00000000..a97ec5fa --- /dev/null +++ b/libsecurity_asn1/lib/csrTemplates.h @@ -0,0 +1,77 @@ +/* + * 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@ + * + * csrTemplates.h - ASN1 templates Cert Signing Requests (per PKCS10). + */ + +#ifndef _NSS_CSR_TEMPLATES_H_ +#define _NSS_CSR_TEMPLATES_H_ + +#include +#include /* for NSS_Attribute */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * ASN class : CertificationRequestInfo + * C struct : NSSCertRequestInfo + */ +typedef struct { + SecAsn1Item version; + NSS_Name subject; + SecAsn1PubKeyInfo subjectPublicKeyInfo; + NSS_Attribute **attributes; +} NSSCertRequestInfo; + +extern const SecAsn1Template kSecAsn1CertRequestInfoTemplate[]; + +/* + * ASN class : CertificationRequest + * C struct : NSSCertRequest + */ +typedef struct { + NSSCertRequestInfo reqInfo; + SecAsn1AlgId signatureAlgorithm; + SecAsn1Item signature;// BIT STRING, length in bits +} NSSCertRequest; + +extern const SecAsn1Template kSecAsn1CertRequestTemplate[]; + +/* + * This is what we use use to avoid unnecessary setup and teardown of + * a full NSSCertRequest when signing and verifying. + */ +typedef struct { + SecAsn1Item certRequestBlob; // encoded, ASN_ANY + SecAsn1AlgId signatureAlgorithm; + SecAsn1Item signature;// BIT STRING, length in bits +} NSS_SignedCertRequest; + +extern const SecAsn1Template kSecAsn1SignedCertRequestTemplate[]; + +#ifdef __cplusplus +} +#endif + +#endif /* _NSS_CSR_TEMPLATES_H_ */ diff --git a/libsecurity_asn1/lib/keyTemplates.c b/libsecurity_asn1/lib/keyTemplates.c new file mode 100644 index 00000000..4aad23fc --- /dev/null +++ b/libsecurity_asn1/lib/keyTemplates.c @@ -0,0 +1,225 @@ +/* + * 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@ + * + * keyTemplate.cpp - ASN1 templates for asymmetric keys and related + * structs. + */ + +#include "SecAsn1Templates.h" +#include +#include "keyTemplates.h" + +/* AlgorithmIdentifier : SecAsn1AlgId */ +const SecAsn1Template kSecAsn1AlgorithmIDTemplate[] = { + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(SecAsn1AlgId) }, + { SEC_ASN1_OBJECT_ID, + offsetof(SecAsn1AlgId,algorithm), }, + { SEC_ASN1_OPTIONAL | SEC_ASN1_ANY, + offsetof(SecAsn1AlgId,parameters), }, + { 0, } +}; + +/* SubjectPublicKeyInfo : SecAsn1PubKeyInfo */ +const SecAsn1Template kSecAsn1SubjectPublicKeyInfoTemplate[] = { + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(SecAsn1PubKeyInfo) }, + { SEC_ASN1_INLINE, + offsetof(SecAsn1PubKeyInfo,algorithm), + kSecAsn1AlgorithmIDTemplate }, + { SEC_ASN1_BIT_STRING, + offsetof(SecAsn1PubKeyInfo,subjectPublicKey), }, + { 0, } +}; + +/* Attribute : NSS_Attribute */ +const SecAsn1Template kSecAsn1AttributeTemplate[] = { + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(NSS_Attribute) }, + { SEC_ASN1_OBJECT_ID, offsetof(NSS_Attribute, attrType) }, + { SEC_ASN1_SET_OF, offsetof(NSS_Attribute, attrValue), + kSecAsn1AnyTemplate }, + { 0 } +}; + +const SecAsn1Template kSecAsn1SetOfAttributeTemplate[] = { + { SEC_ASN1_SET_OF, 0, kSecAsn1AttributeTemplate }, +}; + +/* PKCS8 PrivateKeyInfo : NSS_PrivateKeyInfo */ +const SecAsn1Template kSecAsn1PrivateKeyInfoTemplate[] = { + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSS_PrivateKeyInfo) }, + { SEC_ASN1_INTEGER, offsetof(NSS_PrivateKeyInfo,version) }, + { SEC_ASN1_INLINE, offsetof(NSS_PrivateKeyInfo,algorithm), + kSecAsn1AlgorithmIDTemplate }, + { SEC_ASN1_OCTET_STRING, offsetof(NSS_PrivateKeyInfo,privateKey) }, + { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | + SEC_ASN1_CONTEXT_SPECIFIC | 0, + offsetof(NSS_PrivateKeyInfo,attributes), + kSecAsn1SetOfAttributeTemplate }, + { 0 } +}; + +/* NSS_EncryptedPrivateKeyInfo */ +const SecAsn1Template kSecAsn1EncryptedPrivateKeyInfoTemplate[] = { + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSS_EncryptedPrivateKeyInfo) }, + { SEC_ASN1_INLINE, + offsetof(NSS_EncryptedPrivateKeyInfo,algorithm), + kSecAsn1AlgorithmIDTemplate }, + { SEC_ASN1_OCTET_STRING, + offsetof(NSS_EncryptedPrivateKeyInfo,encryptedData) }, + { 0 } +}; + +/* DigestInfo: NSS_DigestInfo */ +const SecAsn1Template kSecAsn1DigestInfoTemplate[] = { + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSS_DigestInfo) }, + { SEC_ASN1_INLINE, offsetof(NSS_DigestInfo,digestAlgorithm), + kSecAsn1AlgorithmIDTemplate }, + { SEC_ASN1_OCTET_STRING, offsetof(NSS_DigestInfo,digest) }, + { 0 } +}; + +#pragma mark - +#pragma mark *** RSA *** + +/*** RSA public key, PKCS1 format : NSS_RSAPublicKeyPKCS1 ***/ +const SecAsn1Template kSecAsn1RSAPublicKeyPKCS1Template[] = { + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSS_RSAPublicKeyPKCS1) }, + { SEC_ASN1_INTEGER, offsetof(NSS_RSAPublicKeyPKCS1,modulus) }, + { SEC_ASN1_INTEGER, offsetof(NSS_RSAPublicKeyPKCS1,publicExponent) }, + { 0, } +}; + +/*** RSA private key key, PKCS1 format : NSS_RSAPrivateKeyPKCS1 ***/ +const SecAsn1Template kSecAsn1RSAPrivateKeyPKCS1Template[] = { + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSS_RSAPrivateKeyPKCS1) }, + { SEC_ASN1_INTEGER, offsetof(NSS_RSAPrivateKeyPKCS1,version) }, + { SEC_ASN1_INTEGER, offsetof(NSS_RSAPrivateKeyPKCS1,modulus) }, + { SEC_ASN1_INTEGER, offsetof(NSS_RSAPrivateKeyPKCS1,publicExponent) }, + { SEC_ASN1_INTEGER, offsetof(NSS_RSAPrivateKeyPKCS1,privateExponent) }, + { SEC_ASN1_INTEGER, offsetof(NSS_RSAPrivateKeyPKCS1,prime1) }, + { SEC_ASN1_INTEGER, offsetof(NSS_RSAPrivateKeyPKCS1,prime2) }, + { SEC_ASN1_INTEGER, offsetof(NSS_RSAPrivateKeyPKCS1,exponent1) }, + { SEC_ASN1_INTEGER, offsetof(NSS_RSAPrivateKeyPKCS1,exponent2) }, + { SEC_ASN1_INTEGER, offsetof(NSS_RSAPrivateKeyPKCS1,coefficient) }, + { 0, } +}; + +#pragma mark - +#pragma mark *** Diffie-Hellman *** + +/**** + **** Diffie-Hellman, from PKCS3. + ****/ +const SecAsn1Template kSecAsn1DHParameterTemplate[] = { + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSS_DHParameter) }, + { SEC_ASN1_INTEGER, offsetof(NSS_DHParameter,prime) }, + { SEC_ASN1_INTEGER, offsetof(NSS_DHParameter,base) }, + { SEC_ASN1_INTEGER | SEC_ASN1_OPTIONAL, offsetof(NSS_DHParameter,privateValueLength) }, + { 0, } +}; + +const SecAsn1Template kSecAsn1DHParameterBlockTemplate[] = { + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSS_DHParameterBlock) }, + { SEC_ASN1_OBJECT_ID, offsetof(NSS_DHParameterBlock, oid) }, + { SEC_ASN1_INLINE, + offsetof(NSS_DHParameterBlock, params), + kSecAsn1DHParameterTemplate }, + { 0, } +}; + +const SecAsn1Template kSecAsn1DHPrivateKeyTemplate[] = { + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSS_DHPrivateKey) }, + { SEC_ASN1_OBJECT_ID, offsetof(NSS_DHPrivateKey, dhOid) }, + { SEC_ASN1_INLINE, + offsetof(NSS_DHPrivateKey, params), + kSecAsn1DHParameterTemplate }, + { SEC_ASN1_INTEGER, offsetof(NSS_DHPrivateKey,secretPart) }, + { 0, } +}; + +/* + * Diffie-Hellman, X9.42 style. + */ +const SecAsn1Template kSecAsn1DHValidationParamsTemplate[] = { + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSS_DHValidationParams) }, + { SEC_ASN1_BIT_STRING, offsetof(NSS_DHValidationParams, seed) }, + { SEC_ASN1_INTEGER, offsetof(NSS_DHValidationParams, pGenCounter) }, + { 0, } +}; + +const SecAsn1Template kSecAsn1DHDomainParamsX942Template[] = { + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSS_DHDomainParamsX942) }, + { SEC_ASN1_INTEGER, offsetof(NSS_DHDomainParamsX942, p) }, + { SEC_ASN1_INTEGER, offsetof(NSS_DHDomainParamsX942, g) }, + { SEC_ASN1_INTEGER, offsetof(NSS_DHDomainParamsX942, q) }, + { SEC_ASN1_INTEGER | SEC_ASN1_OPTIONAL, + offsetof(NSS_DHDomainParamsX942, j) }, + { SEC_ASN1_POINTER | SEC_ASN1_OPTIONAL, + offsetof(NSS_DHDomainParamsX942, valParams), + kSecAsn1DHValidationParamsTemplate }, + { 0, } +}; + +const SecAsn1Template kSecAsn1DHAlgorithmIdentifierX942Template[] = { + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSS_DHAlgorithmIdentifierX942) }, + { SEC_ASN1_OBJECT_ID, offsetof(NSS_DHAlgorithmIdentifierX942, oid) }, + { SEC_ASN1_INLINE, + offsetof(NSS_DHAlgorithmIdentifierX942, params), + kSecAsn1DHDomainParamsX942Template }, + { 0, } +}; + +const SecAsn1Template kSecAsn1DHPrivateKeyPKCS8Template[] = { + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSS_DHPrivateKeyPKCS8) }, + { SEC_ASN1_INTEGER, offsetof(NSS_DHPrivateKeyPKCS8,version) }, + { SEC_ASN1_INLINE, offsetof(NSS_DHPrivateKeyPKCS8,algorithm), + kSecAsn1DHAlgorithmIdentifierX942Template }, + { SEC_ASN1_OCTET_STRING, offsetof(NSS_DHPrivateKeyPKCS8,privateKey) }, + { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | + SEC_ASN1_CONTEXT_SPECIFIC | 0, + offsetof(NSS_DHPrivateKeyPKCS8,attributes), + kSecAsn1SetOfAttributeTemplate }, + { 0 } +}; + +const SecAsn1Template kSecAsn1DHPublicKeyX509Template[] = { + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSS_DHPublicKeyX509) }, + { SEC_ASN1_INLINE, offsetof(NSS_DHPublicKeyX509,algorithm), + kSecAsn1DHAlgorithmIdentifierX942Template }, + { SEC_ASN1_BIT_STRING, offsetof(NSS_DHPublicKeyX509, publicKey) }, + { 0 } +}; + +/* ECDSA Private key */ +const SecAsn1Template kSecAsn1ECDSAPrivateKeyInfoTemplate[] = { + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSS_ECDSA_PrivateKey) }, + { SEC_ASN1_INTEGER, offsetof(NSS_ECDSA_PrivateKey,version) }, + { SEC_ASN1_OCTET_STRING, offsetof(NSS_ECDSA_PrivateKey,privateKey) }, + { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT | SEC_ASN1_CONTEXT_SPECIFIC | 0, + offsetof(NSS_ECDSA_PrivateKey,params), kSecAsn1AnyTemplate}, + { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT | SEC_ASN1_CONTEXT_SPECIFIC | 1, + offsetof(NSS_ECDSA_PrivateKey,pubKey), kSecAsn1BitStringTemplate }, + { 0, } +}; + diff --git a/libsecurity_asn1/lib/keyTemplates.h b/libsecurity_asn1/lib/keyTemplates.h new file mode 100644 index 00000000..e77fc603 --- /dev/null +++ b/libsecurity_asn1/lib/keyTemplates.h @@ -0,0 +1,276 @@ +/* + * 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@ + * + * keyTemplate.h - ASN1 templates for asymmetric keys and related + * structs. + */ + +#ifndef _NSS_KEY_TEMPLATES_H_ +#define _NSS_KEY_TEMPLATES_H_ + +#include + +/* + * Arrays of SecAsn1Templates are always associated with a specific + * C struct. We attempt to use C structs which are defined in CDSA + * if at all possible; these always start with the CSSM_ prefix. + * Otherwise we define the struct here, with an NSS_ prefix. + * In either case, the name of the C struct is listed in comments + * along with the extern declaration of the SecAsn1Template array. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * ASN class : AlgorithmIdentifier + * C struct : SecAsn1AlgId + */ +extern const SecAsn1Template kSecAsn1AlgorithmIDTemplate[]; + +/* + * ASN class : SubjectPublicKeyInfo + * C struct : SecAsn1PubKeyInfo + */ +extern const SecAsn1Template kSecAsn1SubjectPublicKeyInfoTemplate[]; + +/* + * ASN class : Attribute + * C struct : NSS_Attribute + */ +typedef struct { + SecAsn1Oid attrType; + SecAsn1Item **attrValue; +} NSS_Attribute; + +extern const SecAsn1Template kSecAsn1AttributeTemplate[]; +extern const SecAsn1Template kSecAsn1SetOfAttributeTemplate[]; + +/* + * PKCS8 private key info + * ASN class : PrivateKeyInfo + * C struct : NSS_PrivateKeyInfo + */ +typedef struct { + SecAsn1Item version; + SecAsn1AlgId algorithm; + SecAsn1Item privateKey; + NSS_Attribute **attributes; +} NSS_PrivateKeyInfo; + +extern const SecAsn1Template kSecAsn1PrivateKeyInfoTemplate[]; + +/* + * PKCS8 Encrypted Private Key Info + * ASN class : EncryptedPrivateKeyInfo + * C struct : NSS_EncryptedPrivateKeyInfo + * + * The decrypted encryptedData field is a DER-encoded + * NSS_PrivateKeyInfo. + */ +typedef struct { + SecAsn1AlgId algorithm; + SecAsn1Item encryptedData; +} NSS_EncryptedPrivateKeyInfo; + +extern const SecAsn1Template kSecAsn1EncryptedPrivateKeyInfoTemplate[]; + +/* + * ASN class : DigestInfo + * C struct : NSS_DigestInfo + */ +typedef struct { + SecAsn1AlgId digestAlgorithm; + SecAsn1Item digest; +} NSS_DigestInfo; + +extern const SecAsn1Template kSecAsn1DigestInfoTemplate[]; + +/* + * Key structs and templates, placed here due to their ubiquitous use. + */ + +#pragma mark *** RSA *** + +/* + * RSA public key, PKCS1 format + * + * ASN class : RSAPublicKey + * C struct : NSS_RSAPublicKeyPKCS1 + */ +typedef struct { + SecAsn1Item modulus; + SecAsn1Item publicExponent; +} NSS_RSAPublicKeyPKCS1; + +extern const SecAsn1Template kSecAsn1RSAPublicKeyPKCS1Template[]; + +/* + * RSA public key, X509 format: NSS_SubjectPublicKeyInfoTemplate + */ + +/* + * RSA private key, PKCS1 format, used by openssl + * + * ASN class : RSAPrivateKey + * C struct : NSS_RSAPrivateKeyPKCS1 + */ +typedef struct { + SecAsn1Item version; + SecAsn1Item modulus; + SecAsn1Item publicExponent; + SecAsn1Item privateExponent; + SecAsn1Item prime1; + SecAsn1Item prime2; + SecAsn1Item exponent1; + SecAsn1Item exponent2; + SecAsn1Item coefficient; +} NSS_RSAPrivateKeyPKCS1; + +extern const SecAsn1Template kSecAsn1RSAPrivateKeyPKCS1Template[]; + +/* + * RSA private key, PKCS8 format: NSS_PrivateKeyInfo; the privateKey + * value is a DER-encoded NSS_RSAPrivateKeyPKCS1. + */ + +#pragma mark *** Diffie-Hellman *** + +/*** from PKCS3 ***/ + +/* + * ASN class : DHParameter + * C struct : NSS_DHParameter + */ +typedef struct { + SecAsn1Item prime; + SecAsn1Item base; + SecAsn1Item privateValueLength; // optional +} NSS_DHParameter; + +extern const SecAsn1Template kSecAsn1DHParameterTemplate[]; + +/* + * ASN class : DHParameterBlock + * C struct : NSS_DHParameterBlock + */ +typedef struct { + SecAsn1Oid oid; // CSSMOID_PKCS3 + NSS_DHParameter params; +} NSS_DHParameterBlock; + +extern const SecAsn1Template kSecAsn1DHParameterBlockTemplate[]; + +/* + * ASN class : DHPrivateKey + * C struct : NSS_DHPrivateKey + */ +typedef struct { + SecAsn1Oid dhOid; // CSSMOID_DH + NSS_DHParameter params; + SecAsn1Item secretPart; +} NSS_DHPrivateKey; + +extern const SecAsn1Template kSecAsn1DHPrivateKeyTemplate[]; + +/* + * ANSI X9.42 style Diffie-Hellman keys. + * + * DomainParameters ::= SEQUENCE { -- Galois field group parameters + * p INTEGER, -- odd prime, p = jq + 1 + * g INTEGER, -- generator, g ^ q = 1 mod p + * q INTEGER, -- prime factor of p-1 + * j INTEGER OPTIONAL, -- cofactor, j >= 2 + * -- required for cofactor method + * valParms ValidationParms OPTIONAL + * } + * + * ValidationParms ::= SEQUENCE { + * seed BIT STRING, -- seed for prime number generation + * pGenCounter INTEGER -- parameter verification + * } + */ +typedef struct { + SecAsn1Item seed; // BIT STRING, length in bits + SecAsn1Item pGenCounter; +} NSS_DHValidationParams; + +typedef struct { + SecAsn1Item p; + SecAsn1Item g; + SecAsn1Item q; + SecAsn1Item j; // OPTIONAL + NSS_DHValidationParams *valParams; // OPTIONAL +} NSS_DHDomainParamsX942; + +/* Custom X9.42 D-H AlgorithmIdentifier */ +typedef struct { + SecAsn1Oid oid; // CSSMOID_ANSI_DH_PUB_NUMBER + NSS_DHDomainParamsX942 params; +} NSS_DHAlgorithmIdentifierX942; + +extern const SecAsn1Template kSecAsn1DHValidationParamsTemplate[]; +extern const SecAsn1Template kSecAsn1DHDomainParamsX942Template[]; +extern const SecAsn1Template kSecAsn1DHAlgorithmIdentifierX942Template[]; + +/* PKCS8 form of D-H private key using X9.42 domain parameters */ +typedef struct { + SecAsn1Item version; + NSS_DHAlgorithmIdentifierX942 algorithm; + /* octet string containing DER-encoded integer */ + SecAsn1Item privateKey; + NSS_Attribute **attributes; // OPTIONAL +} NSS_DHPrivateKeyPKCS8; + +/* X509 form of D-H public key using X9.42 domain parameters */ +typedef struct { + NSS_DHAlgorithmIdentifierX942 algorithm; + /* bit string containing DER-encoded integer representing + * raw public key */ + SecAsn1Item publicKey; // length in BITS +} NSS_DHPublicKeyX509; + +extern const SecAsn1Template kSecAsn1DHPrivateKeyPKCS8Template[]; +extern const SecAsn1Template kSecAsn1DHPublicKeyX509Template[]; + +#pragma mark *** ECDSA *** + +/* + * ECDSA Private key as defined in section C.4 of Certicom SEC1. + * The DER encoding of this is placed in the privateKey field + * of a NSS_PrivateKeyInfo. + */ +typedef struct { + SecAsn1Item version; + SecAsn1Item privateKey; + SecAsn1Item params; /* optional, ANY */ + SecAsn1Item pubKey; /* BITSTRING, optional */ +} NSS_ECDSA_PrivateKey; + +extern const SecAsn1Template kSecAsn1ECDSAPrivateKeyInfoTemplate[]; + +#ifdef __cplusplus +} +#endif + +#endif /* _NSS_RSA_KEY_TEMPLATES_H_ */ diff --git a/libsecurity_asn1/lib/nameTemplates.c b/libsecurity_asn1/lib/nameTemplates.c new file mode 100644 index 00000000..b7e1fee2 --- /dev/null +++ b/libsecurity_asn1/lib/nameTemplates.c @@ -0,0 +1,272 @@ +/* + * 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@ + * + * nameTemplates.c - ASN1 templates for X509 Name, GeneralName, etc. + */ + +#include "SecAsn1Templates.h" +#include "nameTemplates.h" +#include "X509Templates.h" +#include "keyTemplates.h" +#include +#include + +typedef struct { + SecAsn1Oid typeId; + SecAsn1Item value; // unparsed, BER-encoded +} CE_OtherName; + +#pragma mark ----- Generalized NSS_TaggedItem template chooser support ----- + +/* + * Generalized Template chooser. + */ +const SecAsn1Template * SecAsn1TaggedTemplateChooser( + /* Four args passed to specific SecAsn1TemplateChooser */ + void *arg, // currently not used + Boolean enc, + const char *buf, + void *dest, + /* array of tag/template pairs */ + const NSS_TagChoice *chooser) +{ + unsigned char tag = 0; + const SecAsn1Template *templ = NULL; + NSS_TaggedItem *item = (NSS_TaggedItem *)dest; + + assert(item != NULL); + assert((chooser != NULL) && (chooser->templ != NULL)); + + if(enc) { + /* encoding: tag from an NSS_TaggedItem at *dest */ + tag = item->tag; + } + else { + /* decoding: tag from raw bytes being decoded */ + tag = buf[0] & SEC_ASN1_TAGNUM_MASK; + /* and tell caller what's coming */ + item->tag = tag; + } + + /* infer template from tag */ + const NSS_TagChoice *thisChoice; + for(thisChoice=chooser; thisChoice->templ != NULL; thisChoice++) { + if(tag == thisChoice->tag) { + templ = thisChoice->templ; + break; + } + } + if(templ == NULL) { + /* + * Tag not found. On decoding, this is the caller's fault + * and they'll have to deal with it. + * On decode, pick a template guaranteed to cause a decoding + * failure - the template from the first array of + * NSS_TagChoices should do the trick since its tag didn't match. + */ + templ = chooser[0].templ; + } + return templ; +} + +#pragma mark ----- X509 Name, RDN ------ + +/* AttributeTypeAndValue */ + +/* + * NSS_ATV Template chooser. + */ +static const NSS_TagChoice atvChoices[] = { + { SEC_ASN1_PRINTABLE_STRING, kSecAsn1PrintableStringTemplate} , + { SEC_ASN1_TELETEX_STRING, kSecAsn1TeletexStringTemplate }, + { SEC_ASN1_UNIVERSAL_STRING, kSecAsn1UniversalStringTemplate }, + { SEC_ASN1_UTF8_STRING, kSecAsn1UTF8StringTemplate }, + { SEC_ASN1_BMP_STRING, kSecAsn1BMPStringTemplate }, + { SEC_ASN1_IA5_STRING, kSecAsn1IA5StringTemplate }, + { 0, NULL} +}; + +static const SecAsn1Template * NSS_ATVChooser( + void *arg, + Boolean enc, + const char *buf, + void *dest) +{ + return SecAsn1TaggedTemplateChooser(arg, enc, buf, dest, atvChoices); +} + +static const SecAsn1TemplateChooserPtr NSS_ATVChooserPtr = NSS_ATVChooser; + +const SecAsn1Template kSecAsn1ATVTemplate[] = { + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(NSS_ATV) }, + { SEC_ASN1_OBJECT_ID, + offsetof(NSS_ATV,type), }, + { SEC_ASN1_INLINE | SEC_ASN1_DYNAMIC, + offsetof(NSS_ATV,value), + &NSS_ATVChooserPtr }, + { 0, } +}; + +/* RelativeDistinguishedName */ +const SecAsn1Template kSecAsn1RDNTemplate[] = { + { SEC_ASN1_SET_OF, + offsetof(NSS_RDN,atvs), kSecAsn1ATVTemplate, sizeof(NSS_RDN) } +}; + +/* X509 Name */ +const SecAsn1Template kSecAsn1NameTemplate[] = { + { SEC_ASN1_SEQUENCE_OF, + offsetof(NSS_Name,rdns), kSecAsn1RDNTemplate, sizeof(NSS_Name) } +}; + +#pragma mark ----- OtherName, GeneralizedName ----- + +/* + * CE_OtherName.value expressed as ASN_ANY, not en/decoded. + */ +const SecAsn1Template NSS_OtherNameTemplate[] = { + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(CE_OtherName) }, + { SEC_ASN1_OBJECT_ID, + offsetof(CE_OtherName,typeId), }, + { SEC_ASN1_ANY, + offsetof(CE_OtherName,value), }, + { 0, } +}; + +/* + * For decoding an OtherName when it's a context-specific CHOICE + * of a GeneralName. + */ +const SecAsn1Template kSecAsn1GenNameOtherNameTemplate[] = { + { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_CONSTRUCTED | NGT_OtherName, + 0, NSS_OtherNameTemplate, sizeof(CE_OtherName) } +}; + +/* + * NSS_GeneralName template chooser. + * First, a crufty set of templates specific to this context. + * All offsets are zero (the fundamental type is a NSS_TaggedItem). + * + * NOTE WELL: RFC2459 says that all of the choices within a + * GeneralName (which these templates implement) have implicit + * context-specific tags. + * HOWEVER: RFC2538 and the real world indicate that the directoryName + * choice is EXPLICITLY tagged. This causes an extra layer of DER - + * the "thing" is wrapped in a header consisting of the tag byte + * (SEC_ASN1_CONTEXT_SPECIFIC plus context tag plus SEC_ASN1_CONSTRUCTED) + * and the length field. + * + * To actually implement this in the current pile-of-cruft context, + * the directoryName and otherName choices are processed here with + * NSS_InnerAnyTemplate which strips off the explicit tag layer, leaving + * further processing to the app. + * + * I sure hope we don't find certs that actually conform to RFC2459 on + * this. We might have to handle both. Be forewarned. + */ + +/* 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)) + +const SecAsn1Template kSecAsn1OtherNameTemplate[] = { + { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_CONSTRUCTED | NGT_OtherName, + NSS_GEN_NAME_OFFSET, kSecAsn1AnyTemplate, NSS_GEN_NAME_SIZE } +}; +const SecAsn1Template kSecAsn1RFC822NameTemplate[] = { + { SEC_ASN1_CONTEXT_SPECIFIC | NGT_RFC822Name, + NSS_GEN_NAME_OFFSET, kSecAsn1IA5StringTemplate, NSS_GEN_NAME_SIZE } +}; +const SecAsn1Template kSecAsn1DNSNameTemplate[] = { + { SEC_ASN1_CONTEXT_SPECIFIC | NGT_DNSName, + NSS_GEN_NAME_OFFSET, kSecAsn1IA5StringTemplate, NSS_GEN_NAME_SIZE } +}; +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 } +}; +const SecAsn1Template kSecAsn1URITemplate[] = { + { SEC_ASN1_CONTEXT_SPECIFIC | NGT_URI, + NSS_GEN_NAME_OFFSET, kSecAsn1IA5StringTemplate, NSS_GEN_NAME_SIZE } +}; +const SecAsn1Template kSecAsn1IPAddressTemplate[] = { + { SEC_ASN1_CONTEXT_SPECIFIC | NGT_IPAddress, + NSS_GEN_NAME_OFFSET, kSecAsn1OctetStringTemplate, NSS_GEN_NAME_SIZE } +}; +const SecAsn1Template kSecAsn1RegisteredIDTemplate[] = { + { SEC_ASN1_CONTEXT_SPECIFIC | NGT_RegisteredID, + NSS_GEN_NAME_OFFSET, kSecAsn1ObjectIDTemplate, NSS_GEN_NAME_SIZE } +}; + +static const NSS_TagChoice genNameChoices[] = { + { NGT_OtherName, kSecAsn1OtherNameTemplate} , + { NGT_RFC822Name, kSecAsn1RFC822NameTemplate }, + { NGT_DNSName, kSecAsn1DNSNameTemplate }, + { NGT_X400Address, kSecAsn1X400AddressTemplate }, + { NGT_DirectoryName, kSecAsn1DirectoryNameTemplate }, + { NGT_EdiPartyName, kSecAsn1EdiPartyNameTemplate }, + { NGT_URI, kSecAsn1URITemplate }, + { NGT_IPAddress, kSecAsn1IPAddressTemplate }, + { NGT_RegisteredID, kSecAsn1RegisteredIDTemplate }, + { 0, NULL} +}; + +static const SecAsn1Template * NSS_genNameChooser( + void *arg, + Boolean enc, + const char *buf, + void *dest) +{ + return SecAsn1TaggedTemplateChooser(arg, enc, buf, dest, genNameChoices); +} + +static const SecAsn1TemplateChooserPtr NSS_genNameChooserPtr = + NSS_genNameChooser; + +const SecAsn1Template kSecAsn1GeneralNameTemplate[] = { + { SEC_ASN1_DYNAMIC | SEC_ASN1_CONTEXT_SPECIFIC, + offsetof(NSS_GeneralName,item), // Needed? + &NSS_genNameChooserPtr }, + { 0, } // Needed? +}; diff --git a/libsecurity_asn1/lib/nameTemplates.h b/libsecurity_asn1/lib/nameTemplates.h new file mode 100644 index 00000000..c8a21343 --- /dev/null +++ b/libsecurity_asn1/lib/nameTemplates.h @@ -0,0 +1,195 @@ +/* + * 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@ + * + * nameTemplates.h - ASN1 templates for X509 Name, GeneralName, etc. + */ + +#ifndef _NSS_NAME_TEMPLATES_H_ +#define _NSS_NAME_TEMPLATES_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#pragma mark ----- Generalized NSS_TaggedItem template chooser support ----- + +/* + * A tagged item for use with simple CHOICE types implemented + * via SEC_ASN1_DYNAMIC. + */ +typedef struct { + SecAsn1Item item; + unsigned char tag; +} NSS_TaggedItem; + +/* + * Type/template-specific SecAsn1TemplateChooser passes + * an array of these, terminated by a NSS_TagChoice with + * a NULL templ field, to SecAsn1TaggedTemplateChooser(). + */ +typedef struct { + unsigned char tag; + const SecAsn1Template *templ; +} NSS_TagChoice; + +/* + * Generalized Template chooser. + */ +const SecAsn1Template * SecAsn1TaggedTemplateChooser( + /* Four args passed to specific SecAsn1TemplateChooser */ + void *arg, // currently not used + Boolean enc, + const char *buf, + void *dest, + /* array of tag/template pairs */ + const NSS_TagChoice *chooser); + +#pragma mark ----- X509 Name, RDN ------ + +/* + * ASN class : AttributeTypeAndValue + * C struct : NSS_ATV + * Roughly corresponds to a CSSM_X509_TYPE_VALUE_PAIR and used + * in DirectoryString elements. + */ + +/* + * This type and template process, via SEC_ASN1_DYNAMIC. the following + * tagged types: + * + * SEC_ASN1_PRINTABLE_STRING + * SEC_ASN1_TELETEX_STRING + * SEC_ASN1_UNIVERSAL_STRING + * SEC_ASN1_UTF8_STRING + * SEC_ASN1_BMP_STRING + * SEC_ASN1_IA5_STRING + * + * Note that SEC_ASN1_IA5_STRING is not a legal part of a + * DirectoryString, but some certs (e.g. the Thawte serverbasic cert) + * use this type. + */ +typedef struct { + SecAsn1Oid type; + NSS_TaggedItem value; +} NSS_ATV; + +/* + * ASN class : RelativeDistinguishedName + * C struct : NSS_RDN + * + * Corresponds to CSSM_X509_RDN. + */ +typedef struct { + NSS_ATV **atvs; +} NSS_RDN; + +/* + * ASN class : Name + * C struct : NSS_Name + * + * Corresponds to CSSM_X509_NAME. + */ +typedef struct { + NSS_RDN **rdns; +} NSS_Name; + +extern const SecAsn1Template kSecAsn1ATVTemplate[]; +extern const SecAsn1Template kSecAsn1RDNTemplate[]; +extern const SecAsn1Template kSecAsn1NameTemplate[]; + +#pragma mark ----- OtherName, GeneralizedName ----- + +/* + * ASN Class : OtherName + * C struct : CE_OtherName + * + * CE_OtherName.value expressed as ASN_ANY, not en/decoded. + */ +extern const SecAsn1Template kSecAsn1OtherNameTemplate[]; + +/* + * For decoding an OtherName when it's a context-specific CHOICE + * of a GeneralName. + */ +extern const SecAsn1Template kSecAsn1GenNameOtherNameTemplate[]; + +/* + * ASN Class : GeneralName + * C struct : NSS_GeneralName, typedefd to an NSS_TaggedItem + * + * This roughly maps to a CE_GeneralName (from certextensions.h). + * The NSS_TaggedItem mechanism is used to resolve choices down + * to the SecAsn1Item level - i.e., at this level (prior to encoding + * or after decoding), NSS_GeneralName.item either contains a simple + * atomic type (IA5String, Octet string) or is raw, un{de,en}coded + * ASN_ANY. + */ +typedef NSS_TaggedItem NSS_GeneralName; + +/* + * These context-specific tag definitions, for use in + * NSS_GeneralName.tag, are from the ASN definition and map to + * CE_GeneralNameType values from certextensions.h. The values + * happen to be equivalent but apps should not count on that - + * these NSS_GeneralNameTag values are explicitly assigned per + * the ASN spec of a GeneralName. + * + * Shown with each tag is the simple type the tag maps to. + */ +typedef enum { + NGT_OtherName = 0, // ASN_ANY + NGT_RFC822Name = 1, // IA5String + NGT_DNSName = 2, // IA5String + NGT_X400Address = 3, // ASY_ANY + NGT_DirectoryName = 4, // ASN_ANY + NGT_EdiPartyName = 5, // ASN_ANY + NGT_URI = 6, // IA5String + NGT_IPAddress = 7, // OCTET_STRING + NGT_RegisteredID = 8 // OID +} NSS_GeneralNameTag; + +extern const SecAsn1Template kSecAsn1GeneralNameTemplate[]; + +/* + * ASN Class : GeneralNames + * C struct : NSS_GeneralNames + * + * Since the SEC_ANY_DYNAMIC mechanism doesn't work with POINTERs + * or GROUPs (e.g., a sequence of NSS_GeneralName elements), decoding + * an NSS_GeneralNames first requires a decode to an array of + * ANY_ANY blobs as shown here. Use SEC_SequenceOfAnyTemplate for + * that step. Each of the resulting elements is individually + * decoded into an NSS_GeneralName. + */ +typedef struct { + SecAsn1Item **names; /* sequence */ +} NSS_GeneralNames; + +#define kSecAsn1GeneralNamesTemplate kSecAsn1SequenceOfAnyTemplate + +#ifdef __cplusplus +} +#endif + +#endif /* _NSS_NAME_TEMPLATES_H_ */ diff --git a/libsecurity_asn1/lib/nsprPortX.c b/libsecurity_asn1/lib/nsprPortX.c new file mode 100644 index 00000000..838408e6 --- /dev/null +++ b/libsecurity_asn1/lib/nsprPortX.c @@ -0,0 +1,250 @@ +/* + * 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@ + * + * nsprPortX.c - minimal platform dependent NSPR functions to enable + * use of DER libraries + */ + +#ifndef _NSPR_PORT_X_H_ +#define _NSPR_PORT_X_H_ + +#include "prmem.h" +#include "prlock.h" +#include "prerror.h" +#include "prinit.h" +#include "prbit.h" + +#include +#include +#include + +#pragma mark *** Memory *** + +NSPR_API(void *) PR_Malloc(PRSize size) +{ + return malloc(size ? size : 1); +} +NSPR_API(void *) PR_Calloc(PRSize nelem, PRSize elsize) +{ + return calloc(nelem, elsize); +} +NSPR_API(void *) PR_Realloc(void *ptr, PRSize size) +{ + return realloc(ptr, size); +} +NSPR_API(void) PR_Free(void *ptr) +{ + return free(ptr); +} + +#pragma mark *** locks *** + +NSPR_API(PRLock*) PR_NewLock(void) +{ + pthread_mutex_t *pm = PR_Malloc(sizeof(pthread_mutex_t)); + if(pm == NULL) { + return NULL; + } + if(pthread_mutex_init(pm, NULL)) { + PR_Free(pm); + return NULL; + } + return (PRLock*)pm; +} + +NSPR_API(void) PR_DestroyLock(PRLock *lock) +{ + if(lock == NULL) { + return; + } + pthread_mutex_destroy((pthread_mutex_t *)lock); + PR_Free(lock); +} + +NSPR_API(void) PR_Lock(PRLock *lock) +{ + if(lock == NULL) { + return; + } + pthread_mutex_lock((pthread_mutex_t *)lock); +} + +NSPR_API(PRStatus) PR_Unlock(PRLock *lock) +{ + if(lock == NULL) { + return PR_FAILURE; + } + pthread_mutex_unlock((pthread_mutex_t *)lock); + return PR_SUCCESS; +} + +#pragma mark *** get/set error *** + +/* + * key for pthread_{set,get}specific and a lock to ensure it gets + * created once + */ +static pthread_key_t PR_threadKey; +static int PR_threadKeyInitFlag; // we have a PR_threadKey +static int PR_threadKeyErrorFlag; // unable to create PR_threadKey +static pthread_mutex_t PR_threadKeyLock = PTHREAD_MUTEX_INITIALIZER; + +/* + * The thing that gets stored on a per-thread basis. A pointer to + * this is associated with key PR_threadKey. Mallocd in + * PR_getThreadErrInfo(); freed directly by free() as + * PR_threadKey's destructor. + */ +typedef struct { + PRInt32 osError; + PRErrorCode prError; +} PR_threadErrInfo; + +/* + * One-time init of PR_threadKey, returns nonzero on error. + * Does not attempt to init PR_threadKey if doCreate is false and + * a previous call to this routine resulted in error (i.e., this + * is the GetXError() following a failed SetError()). + */ +static PRInt32 PR_initThreadKey( + int doCreate) +{ + PRInt32 prtn = 0; + if(PR_threadKeyInitFlag) { + /* thread safe since we never clear this flag; we're ready to go */ + return 0; + } + pthread_mutex_lock(&PR_threadKeyLock); + if(PR_threadKeyErrorFlag && !doCreate) { + /* no error to get because the last SetXError failed */ + prtn = PR_IO_ERROR; + } + else if(!PR_threadKeyInitFlag) { + prtn = pthread_key_create(&PR_threadKey, free); + if(prtn) { + /* out of pthread_key_t's */ + PR_threadKeyErrorFlag = 1; + } + else { + PR_threadKeyErrorFlag = 0; // in case of retry */ + PR_threadKeyInitFlag = 1; // success + } + } + pthread_mutex_unlock(&PR_threadKeyLock); + return prtn; +} + +/* + * Get current thread's PR_threadErrInfo. Create one if doCreate is + * true and one does not exist. + * + * -- A nonzero *threadKeyError on return indicates that we can + * not create a pthread_key_t; in this case we return NULL. + * -- Note that NULL return with zero threadKeyError and zero + * doCreate indicates "no per-thread error set yet", which is + * not an error. + */ +static PR_threadErrInfo *PR_getThreadErrInfo( + int doCreate, + PRInt32 *threadKeyError) // RETURNED, an OSStatus +{ + *threadKeyError = PR_initThreadKey(doCreate); + if(*threadKeyError) { + return NULL; + } + PR_threadErrInfo *errInfo = pthread_getspecific(PR_threadKey); + if((errInfo == NULL) && doCreate) { + errInfo = (PR_threadErrInfo *)malloc(sizeof(*errInfo)); + if(errInfo == NULL) { + /* + * malloc failure, retriable failure of this routine (not + * a PR_threadKeyErrorFlag style error). + * Note that this is *not* detected in a subsequent + * GetXError() call, but it will allow for somewhat + * graceful recovery in case some memory gets freed + * up. + */ + *threadKeyError = PR_OUT_OF_MEMORY_ERROR; + } + else { + memset(errInfo, 0, sizeof(*errInfo)); + pthread_setspecific(PR_threadKey, errInfo); + } + } + return errInfo; +} + +PR_IMPLEMENT(PRErrorCode) PR_GetError(void) +{ + PRInt32 prtn; + PR_threadErrInfo *errInfo = PR_getThreadErrInfo(0, &prtn); + if(errInfo == NULL) { + /* no error set or per-thread logic uninitialized */ + if(prtn) { + return PR_INSUFFICIENT_RESOURCES_ERROR; + } + else { + return 0; + } + } + else { + return errInfo->prError; + } +} + +PR_IMPLEMENT(PRInt32) PR_GetOSError(void) +{ + PRInt32 prtn; + PR_threadErrInfo *errInfo = PR_getThreadErrInfo(0, &prtn); + if(errInfo == NULL) { + /* no error set or per-thread logic uninitialized */ + return prtn; + } + else { + return errInfo->osError; + } +} + +PR_IMPLEMENT(void) PR_SetError(PRErrorCode code, PRInt32 osErr) +{ + PRInt32 prtn; + PR_threadErrInfo *errInfo = PR_getThreadErrInfo(1, &prtn); + if(errInfo != NULL) { + errInfo->osError = osErr; + errInfo->prError = code; + } + /* else per-thread logic uninitialized */ +} + +#pragma mark *** misc. *** + +/* +** Compute the log of the least power of 2 greater than or equal to n +*/ +NSPR_API(PRIntn) PR_CeilingLog2(PRUint32 i) +{ + PRIntn r; + PR_CEILING_LOG2(r,i); + return r; +} + +#endif /* _NSPR_PORT_X_H_ */ diff --git a/libsecurity_asn1/lib/nssUtils.c b/libsecurity_asn1/lib/nssUtils.c new file mode 100644 index 00000000..d03dc753 --- /dev/null +++ b/libsecurity_asn1/lib/nssUtils.c @@ -0,0 +1,68 @@ +/* + * 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@ + * + * nssUtils.cpp + */ + +#include "nssUtils.h" +#include + +/* + * Compare two SecAsn1Items (or two SecAsn1Oids), return true if identical. + */ +int nssCompareSecAsn1Items( + const SecAsn1Item *data1, + const SecAsn1Item *data2) +{ + if((data1 == NULL) || (data1->Data == NULL) || + (data2 == NULL) || (data2->Data == NULL) || + (data1->Length != data2->Length)) { + return 0; + } + if(data1->Length != data2->Length) { + return 0; + } + return memcmp(data1->Data, data2->Data, data1->Length) == 0; +} + +int nssCompareCssmData( + const SecAsn1Item *data1, + const SecAsn1Item *data2) +{ + return nssCompareSecAsn1Items(data1,data2); +} + +/* + * How many items in a NULL-terminated array of pointers? + */ +unsigned nssArraySize( + const void **array) +{ + unsigned count = 0; + if (array) { + while (*array++) { + count++; + } + } + return count; +} + diff --git a/libsecurity_asn1/lib/nssUtils.h b/libsecurity_asn1/lib/nssUtils.h new file mode 100644 index 00000000..bd09e6c1 --- /dev/null +++ b/libsecurity_asn1/lib/nssUtils.h @@ -0,0 +1,54 @@ +/* + * 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@ + * + * nssUtils.h + */ + +#ifndef _NSS_UTILS_H_ +#define _NSS_UTILS_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* return true if two SecAsn1Items (or two SecAsn1Oids) compare equal */ +int nssCompareSecAsn1Items( + const SecAsn1Item *data1, + const SecAsn1Item *data2); + +int nssCompareCssmData( + const SecAsn1Item *data1, + const SecAsn1Item *data2); + +/* How many items in a NULL-terminated array of pointers? */ +unsigned nssArraySize( + const void **array); + +#ifdef __cplusplus +} +#endif + +#endif /* _NSS_UTILS_H_ */ + diff --git a/libsecurity_asn1/lib/nssilckt.h b/libsecurity_asn1/lib/nssilckt.h new file mode 100644 index 00000000..e0b49902 --- /dev/null +++ b/libsecurity_asn1/lib/nssilckt.h @@ -0,0 +1,220 @@ +/* + * 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. + */ + +/* +** nssilock.h - Instrumented locking functions for NSS +** +** Description: +** nssilock provides instrumentation for locks and monitors in +** the NSS libraries. The instrumentation, when enabled, causes +** each call to the instrumented function to record data about +** the call to an external file. The external file +** subsequently used to extract performance data and other +** statistical information about the operation of locks used in +** the nss library. +** +** To enable compilation with instrumentation, build NSS with +** the compile time switch NEED_NSS_ILOCK defined. +** +** say: "gmake OS_CFLAGS+=-DNEED_NSS_ILOCK" at make time. +** +** At runtime, to enable recording from nssilock, one or more +** environment variables must be set. For each nssILockType to +** be recorded, an environment variable of the form NSS_ILOCK_x +** must be set to 1. For example: +** +** set NSS_ILOCK_Cert=1 +** +** nssilock uses PRLOG is used to record to trace data. The +** PRLogModule name associated with nssilock data is: "nssilock". +** To enable recording of nssilock data you will need to set the +** environment variable NSPR_LOG_MODULES to enable +** recording for the nssilock log module. Similarly, you will +** need to set the environment variable NSPR_LOG_FILE to specify +** the filename to receive the recorded data. See prlog.h for usage. +** Example: +** +** export NSPR_LOG_MODULES=nssilock:6 +** export NSPR_LOG_FILE=xxxLogfile +** +** Operation: +** nssilock wraps calls to NSPR's PZLock and PZMonitor functions +** with similarly named functions: PZ_NewLock(), etc. When NSS is +** built with lock instrumentation enabled, the PZ* functions are +** compiled into NSS; when lock instrumentation is disabled, +** calls to PZ* functions are directly mapped to PR* functions +** and the instrumentation arguments to the PZ* functions are +** compiled away. +** +** +** File Format: +** The format of the external file is implementation +** dependent. Where NSPR's PR_LOG() function is used, the file +** contains data defined for PR_LOG() plus the data written by +** the wrapped function. On some platforms and under some +** circumstances, platform dependent logging or +** instrumentation probes may be used. In any case, the +** relevant data provided by the lock instrumentation is: +** +** lockType, func, address, duration, line, file [heldTime] +** +** where: +** +** lockType: a character representation of nssILockType for the +** call. e.g. ... "cert" +** +** func: the function doing the tracing. e.g. "NewLock" +** +** address: address of the instrumented lock or monitor +** +** duration: is how long was spent in the instrumented function, +** in PRIntervalTime "ticks". +** +** line: the line number within the calling function +** +** file: the file from which the call was made +** +** heldTime: how long the lock/monitor was held. field +** present only for PZ_Unlock() and PZ_ExitMonitor(). +** +** Design Notes: +** The design for lock instrumentation was influenced by the +** need to gather performance data on NSS 3.x. It is intended +** that the effort to modify NSS to use lock instrumentation +** be minimized. Existing calls to locking functions need only +** have their names changed to the instrumentation function +** names. +** +** Private NSS Interface: +** nssilock.h defines a private interface for use by NSS. +** nssilock.h is experimental in nature and is subject to +** change or revocation without notice. ... Don't mess with +** it. +** +*/ + +/* + * $Id: + */ + +#ifndef _NSSILCKT_H_ +#define _NSSILCKT_H_ + +#include "prtypes.h" +#include "prmon.h" +#include "prlock.h" +#include "prcvar.h" + +typedef enum { + nssILockArena = 0, + nssILockSession = 1, + nssILockObject = 2, + nssILockRefLock = 3, + nssILockCert = 4, + nssILockCertDB = 5, + nssILockDBM = 6, + nssILockCache = 7, + nssILockSSL = 8, + nssILockList = 9, + nssILockSlot = 10, + nssILockFreelist = 11, + nssILockOID = 12, + nssILockAttribute = 13, + nssILockPK11cxt = 14, /* pk11context */ + nssILockRWLock = 15, + nssILockOther = 16, + nssILockSelfServ = 17, + nssILockLast /* don't use this one! */ +} nssILockType; + +/* +** Declare operation type enumerator +** enumerations identify the function being performed +*/ +typedef enum { + FlushTT = 0, + NewLock = 1, + Lock = 2, + Unlock = 3, + DestroyLock = 4, + NewCondVar = 5, + WaitCondVar = 6, + NotifyCondVar = 7, + NotifyAllCondVar = 8, + DestroyCondVar = 9, + NewMonitor = 10, + EnterMonitor = 11, + ExitMonitor = 12, + Notify = 13, + NotifyAll = 14, + Wait = 15, + DestroyMonitor = 16 +} nssILockOp; + +/* +** Declare the trace record +*/ +struct pzTrace_s { + PRUint32 threadID; /* PR_GetThreadID() */ + nssILockOp op; /* operation being performed */ + nssILockType ltype; /* lock type identifier */ + PRIntervalTime callTime; /* time spent in function */ + PRIntervalTime heldTime; /* lock held time, or -1 */ + void *lock; /* address of lock structure */ + PRIntn line; /* line number */ + char file[24]; /* filename */ +}; + +PR_BEGIN_EXTERN_C +/* +** conditionally compile in nssilock features +*/ +#if defined(NEED_NSS_ILOCK) + +/* +** declare opaque types. See: nssilock.c +*/ +typedef struct pzlock_s PZLock; +typedef struct pzcondvar_s PZCondVar; +typedef struct pzmonitor_s PZMonitor; + +#else /* NEED_NSS_ILOCK */ + +#define PZLock PRLock +#define PZCondVar PRCondVar +#define PZMonitor PRMonitor + +#endif /* NEED_NSS_ILOCK */ + +PR_END_EXTERN_C +#endif /* _NSSILCKT_H_ */ diff --git a/libsecurity_asn1/lib/nssilock.h b/libsecurity_asn1/lib/nssilock.h new file mode 100644 index 00000000..38b45738 --- /dev/null +++ b/libsecurity_asn1/lib/nssilock.h @@ -0,0 +1,316 @@ +/* + * 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. + */ + +/* +** nssilock.h - Instrumented locking functions for NSS +** +** Description: +** nssilock provides instrumentation for locks and monitors in +** the NSS libraries. The instrumentation, when enabled, causes +** each call to the instrumented function to record data about +** the call to an external file. The external file +** subsequently used to extract performance data and other +** statistical information about the operation of locks used in +** the nss library. +** +** To enable compilation with instrumentation, build NSS with +** the compile time switch NEED_NSS_ILOCK defined. +** +** say: "gmake OS_CFLAGS+=-DNEED_NSS_ILOCK" at make time. +** +** At runtime, to enable recording from nssilock, one or more +** environment variables must be set. For each nssILockType to +** be recorded, an environment variable of the form NSS_ILOCK_x +** must be set to 1. For example: +** +** set NSS_ILOCK_Cert=1 +** +** nssilock uses PRLOG is used to record to trace data. The +** PRLogModule name associated with nssilock data is: "nssilock". +** To enable recording of nssilock data you will need to set the +** environment variable NSPR_LOG_MODULES to enable +** recording for the nssilock log module. Similarly, you will +** need to set the environment variable NSPR_LOG_FILE to specify +** the filename to receive the recorded data. See prlog.h for usage. +** Example: +** +** export NSPR_LOG_MODULES=nssilock:6 +** export NSPR_LOG_FILE=xxxLogfile +** +** Operation: +** nssilock wraps calls to NSPR's PZLock and PZMonitor functions +** with similarly named functions: PZ_NewLock(), etc. When NSS is +** built with lock instrumentation enabled, the PZ* functions are +** compiled into NSS; when lock instrumentation is disabled, +** calls to PZ* functions are directly mapped to PR* functions +** and the instrumentation arguments to the PZ* functions are +** compiled away. +** +** +** File Format: +** The format of the external file is implementation +** dependent. Where NSPR's PR_LOG() function is used, the file +** contains data defined for PR_LOG() plus the data written by +** the wrapped function. On some platforms and under some +** circumstances, platform dependent logging or +** instrumentation probes may be used. In any case, the +** relevant data provided by the lock instrumentation is: +** +** lockType, func, address, duration, line, file [heldTime] +** +** where: +** +** lockType: a character representation of nssILockType for the +** call. e.g. ... "cert" +** +** func: the function doing the tracing. e.g. "NewLock" +** +** address: address of the instrumented lock or monitor +** +** duration: is how long was spent in the instrumented function, +** in PRIntervalTime "ticks". +** +** line: the line number within the calling function +** +** file: the file from which the call was made +** +** heldTime: how long the lock/monitor was held. field +** present only for PZ_Unlock() and PZ_ExitMonitor(). +** +** Design Notes: +** The design for lock instrumentation was influenced by the +** need to gather performance data on NSS 3.x. It is intended +** that the effort to modify NSS to use lock instrumentation +** be minimized. Existing calls to locking functions need only +** have their names changed to the instrumentation function +** names. +** +** Private NSS Interface: +** nssilock.h defines a private interface for use by NSS. +** nssilock.h is experimental in nature and is subject to +** change or revocation without notice. ... Don't mess with +** it. +** +*/ + +/* + * $Id: + */ + +#ifndef _NSSILOCK_H_ +#define _NSSILOCK_H_ + +#include "prtypes.h" +#include "prmon.h" +#include "prlock.h" +#include "prcvar.h" + +#include "nssilckt.h" + +PR_BEGIN_EXTERN_C + +#if defined(NEED_NSS_ILOCK) + +#define PZ_NewLock(t) pz_NewLock((t),__FILE__,__LINE__) +extern PZLock * + pz_NewLock( + nssILockType ltype, + char *file, + PRIntn line + ); + +#define PZ_Lock(k) pz_Lock((k),__FILE__,__LINE__) +extern void + pz_Lock( + PZLock *lock, + char *file, + PRIntn line + ); + +#define PZ_Unlock(k) pz_Unlock((k),__FILE__,__LINE__) +extern PRStatus + pz_Unlock( + PZLock *lock, + char *file, + PRIntn line + ); + +#define PZ_DestroyLock(k) pz_DestroyLock((k),__FILE__,__LINE__) +extern void + pz_DestroyLock( + PZLock *lock, + char *file, + PRIntn line + ); + + +#define PZ_NewCondVar(l) pz_NewCondVar((l),__FILE__,__LINE__) +extern PZCondVar * + pz_NewCondVar( + PZLock *lock, + char *file, + PRIntn line + ); + +#define PZ_DestroyCondVar(v) pz_DestroyCondVar((v),__FILE__,__LINE__) +extern void + pz_DestroyCondVar( + PZCondVar *cvar, + char *file, + PRIntn line + ); + +#define PZ_WaitCondVar(v,t) pz_WaitCondVar((v),(t),__FILE__,__LINE__) +extern PRStatus + pz_WaitCondVar( + PZCondVar *cvar, + PRIntervalTime timeout, + char *file, + PRIntn line + ); + +#define PZ_NotifyCondVar(v) pz_NotifyCondVar((v),__FILE__,__LINE__) +extern PRStatus + pz_NotifyCondVar( + PZCondVar *cvar, + char *file, + PRIntn line + ); + +#define PZ_NotifyAllCondVar(v) pz_NotifyAllCondVar((v),__FILE__,__LINE__) +extern PRStatus + pz_NotifyAllCondVar( + PZCondVar *cvar, + char *file, + PRIntn line + ); + + +#define PZ_NewMonitor(t) pz_NewMonitor((t),__FILE__,__LINE__) +extern PZMonitor * + pz_NewMonitor( + nssILockType ltype, + char *file, + PRIntn line + ); + +#define PZ_DestroyMonitor(m) pz_DestroyMonitor((m),__FILE__,__LINE__) +extern void + pz_DestroyMonitor( + PZMonitor *mon, + char *file, + PRIntn line + ); + +#define PZ_EnterMonitor(m) pz_EnterMonitor((m),__FILE__,__LINE__) +extern void + pz_EnterMonitor( + PZMonitor *mon, + char *file, + PRIntn line + ); + + +#define PZ_ExitMonitor(m) pz_ExitMonitor((m),__FILE__,__LINE__) +extern PRStatus + pz_ExitMonitor( + PZMonitor *mon, + char *file, + PRIntn line + ); + +#define PZ_InMonitor(m) (PZ_GetMonitorEntryCount(m) > 0 ) +#define PZ_GetMonitorEntryCount(m) pz_GetMonitorEntryCount((m),__FILE__,__LINE__) +extern PRIntn + pz_GetMonitorEntryCount( + PZMonitor *mon, + char *file, + PRIntn line + ); + +#define PZ_Wait(m,i) pz_Wait((m),((i)),__FILE__,__LINE__) +extern PRStatus + pz_Wait( + PZMonitor *mon, + PRIntervalTime ticks, + char *file, + PRIntn line + ); + +#define PZ_Notify(m) pz_Notify((m),__FILE__,__LINE__) +extern PRStatus + pz_Notify( + PZMonitor *mon, + char *file, + PRIntn line + ); + +#define PZ_NotifyAll(m) pz_NotifyAll((m),__FILE__,__LINE__) +extern PRStatus + pz_NotifyAll( + PZMonitor *mon, + char *file, + PRIntn line + ); + +#define PZ_TraceFlush() pz_TraceFlush() +extern void pz_TraceFlush( void ); + +#else /* NEED_NSS_ILOCK */ + +#define PZ_NewLock(t) PR_NewLock() +#define PZ_DestroyLock(k) PR_DestroyLock((k)) +#define PZ_Lock(k) PR_Lock((k)) +#define PZ_Unlock(k) PR_Unlock((k)) + +#define PZ_NewCondVar(l) PR_NewCondVar((l)) +#define PZ_DestroyCondVar(v) PR_DestroyCondVar((v)) +#define PZ_WaitCondVar(v,t) PR_WaitCondVar((v),(t)) +#define PZ_NotifyCondVar(v) PR_NotifyCondVar((v)) +#define PZ_NotifyAllCondVar(v) PR_NotifyAllCondVar((v)) + +#define PZ_NewMonitor(t) PR_NewMonitor() +#define PZ_DestroyMonitor(m) PR_DestroyMonitor((m)) +#define PZ_EnterMonitor(m) PR_EnterMonitor((m)) +#define PZ_ExitMonitor(m) PR_ExitMonitor((m)) +#define PZ_InMonitor(m) PR_InMonitor((m)) +#define PZ_Wait(m,t) PR_Wait(((m)),((t))) +#define PZ_Notify(m) PR_Notify((m)) +#define PZ_NotifyAll(m) PR_Notify((m)) +#define PZ_TraceFlush() /* nothing */ + + +#endif /* NEED_NSS_ILOCK */ + +PR_END_EXTERN_C +#endif /* _NSSILOCK_H_ */ diff --git a/libsecurity_asn1/lib/nsslocks.h b/libsecurity_asn1/lib/nsslocks.h new file mode 100644 index 00000000..eb24c805 --- /dev/null +++ b/libsecurity_asn1/lib/nsslocks.h @@ -0,0 +1,67 @@ +/* + * 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. + */ + +/* + * nsslocks.h - threadsafe functions to initialize lock pointers. + * + * NOTE - These are not public interfaces + * + * $Id: nsslocks.h,v 1.1 2003/01/30 22:42:07 dmitch Exp $ + */ + +#ifndef _NSSLOCKS_H_ +#define _NSSLOCKS_H_ + +#include "seccomon.h" +#include "nssilock.h" +#include "prmon.h" + +SEC_BEGIN_PROTOS + +/* Given the address of a (global) pointer to a PZLock, + * atomicly create the lock and initialize the (global) pointer, + * if it is not already created/initialized. + */ + +extern SECStatus nss_InitLock( PZLock **ppLock, nssILockType ltype ); + +/* Given the address of a (global) pointer to a PZMonitor, + * atomicly create the monitor and initialize the (global) pointer, + * if it is not already created/initialized. + */ + +extern SECStatus nss_InitMonitor(PZMonitor **ppMonitor, nssILockType ltype ); + +SEC_END_PROTOS + +#endif diff --git a/libsecurity_asn1/lib/ocspTemplates.c b/libsecurity_asn1/lib/ocspTemplates.c new file mode 100644 index 00000000..798f3212 --- /dev/null +++ b/libsecurity_asn1/lib/ocspTemplates.c @@ -0,0 +1,298 @@ +/* + * 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@ + * + * ocspTemplates.cpp - ASN1 templates OCSP requests and responses. + */ + +#include "ocspTemplates.h" +#include "keyTemplates.h" /* for kSecAsn1AlgorithmIDTemplate */ +#include "SecAsn1Templates.h" +#include +#include + +#pragma mark ----- OCSP Request ----- + +const SecAsn1Template kSecAsn1OCSPCertIDTemplate[] = { + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(SecAsn1OCSPCertID) }, + { SEC_ASN1_INLINE, + offsetof(SecAsn1OCSPCertID, algId), + kSecAsn1AlgorithmIDTemplate }, + { SEC_ASN1_OCTET_STRING, offsetof(SecAsn1OCSPCertID, issuerNameHash) }, + { SEC_ASN1_OCTET_STRING, offsetof(SecAsn1OCSPCertID, issuerPubKeyHash) }, + /* serial number is SIGNED integer */ + { SEC_ASN1_INTEGER | SEC_ASN1_SIGNED_INT, + offsetof(SecAsn1OCSPCertID, serialNumber) }, + { 0 } +}; + +const SecAsn1Template kSecAsn1OCSPRequestTemplate[] = { + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(SecAsn1OCSPRequest) }, + { SEC_ASN1_INLINE, + offsetof(SecAsn1OCSPRequest, reqCert), + kSecAsn1OCSPCertIDTemplate }, + { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | + SEC_ASN1_EXPLICIT | 0, + offsetof(SecAsn1OCSPRequest, extensions), + kSecAsn1SequenceOfCertExtensionTemplate }, + { 0 } +}; + +const SecAsn1Template kSecAsn1OCSPSignatureTemplate[] = { + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(SecAsn1OCSPSignature) }, + { SEC_ASN1_INLINE, + offsetof(SecAsn1OCSPSignature, algId), + kSecAsn1AlgorithmIDTemplate }, + { SEC_ASN1_BIT_STRING, offsetof(SecAsn1OCSPSignature, sig) }, + { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | + SEC_ASN1_EXPLICIT | 0, + offsetof(SecAsn1OCSPSignature, certs), + kSecAsn1SequenceOfAnyTemplate }, + { 0 } +}; + +const SecAsn1Template kSecAsn1OCSPTbsRequestTemplate[] = { + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(SecAsn1OCSPTbsRequest) }, + /* optional version, explicit tag 0, default 0 */ + { SEC_ASN1_EXPLICIT | SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | + SEC_ASN1_CONTEXT_SPECIFIC | 0, + offsetof(SecAsn1OCSPTbsRequest, version), + kSecAsn1PointerToIntegerTemplate }, + { SEC_ASN1_EXPLICIT | SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | + SEC_ASN1_POINTER | SEC_ASN1_CONTEXT_SPECIFIC | 1, + offsetof(SecAsn1OCSPTbsRequest, requestorName), + kSecAsn1GeneralNameTemplate }, + { SEC_ASN1_SEQUENCE_OF, + offsetof(SecAsn1OCSPTbsRequest, requestList), + kSecAsn1OCSPRequestTemplate }, + { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | + SEC_ASN1_EXPLICIT | 2, + offsetof(SecAsn1OCSPTbsRequest, requestExtensions), + kSecAsn1SequenceOfCertExtensionTemplate }, + { 0 } +}; + +const SecAsn1Template kSecAsn1OCSPSignedRequestTemplate[] = { + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(SecAsn1OCSPSignedRequest) }, + { SEC_ASN1_INLINE, + offsetof(SecAsn1OCSPSignedRequest, tbsRequest), + kSecAsn1OCSPTbsRequestTemplate }, + { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | + SEC_ASN1_POINTER | SEC_ASN1_EXPLICIT | 0, + offsetof(SecAsn1OCSPSignedRequest, signature), + kSecAsn1OCSPSignatureTemplate }, + { 0 } +}; + +#pragma mark ----- OCSP Response ----- + +const SecAsn1Template kSecAsn1OCSPRevokedInfoTemplate[] = { + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(SecAsn1OCSPRevokedInfo) }, + { SEC_ASN1_GENERALIZED_TIME, offsetof(SecAsn1OCSPRevokedInfo, revocationTime) }, + { SEC_ASN1_EXPLICIT | SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | + SEC_ASN1_CONTEXT_SPECIFIC | 0, + offsetof(SecAsn1OCSPRevokedInfo, revocationReason) , + kSecAsn1PointerToEnumeratedTemplate }, + { 0 } +}; + +/* three context-specific templates, app picks one of these */ + +/* + * Encode/decode CertStatus separately using one of these †hree templates. + * The result goes into SecAsn1OCSPSingleResponse.certStatus on encode. + */ +const SecAsn1Template kSecAsn1OCSPCertStatusGoodTemplate[] = { + { SEC_ASN1_POINTER | SEC_ASN1_CONTEXT_SPECIFIC | 0, + offsetof(SecAsn1OCSPCertStatus, nullData), + kSecAsn1NullTemplate } +}; + +const SecAsn1Template kSecAsn1OCSPCertStatusRevokedTemplate[] = { + { SEC_ASN1_POINTER | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_CONSTRUCTED | 1, + offsetof(SecAsn1OCSPCertStatus, revokedInfo) , + kSecAsn1OCSPRevokedInfoTemplate } +}; + +const SecAsn1Template kSecAsn1OCSPCertStatusUnknownTemplate[] = { + { SEC_ASN1_CONTEXT_SPECIFIC | 2, + offsetof(SecAsn1OCSPCertStatus, nullData), + kSecAsn1NullTemplate } +}; + +const SecAsn1Template kSecAsn1OCSPSingleResponseTemplate[] = { + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(SecAsn1OCSPSingleResponse) }, + { SEC_ASN1_INLINE, + offsetof(SecAsn1OCSPSingleResponse, certID), + kSecAsn1OCSPCertIDTemplate }, + { SEC_ASN1_ANY, + offsetof(SecAsn1OCSPSingleResponse, certStatus), + kSecAsn1AnyTemplate }, + { SEC_ASN1_GENERALIZED_TIME, offsetof(SecAsn1OCSPSingleResponse, thisUpdate) }, + { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | + SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_EXPLICIT | 0, + offsetof(SecAsn1OCSPSingleResponse, nextUpdate), + kSecAsn1PointerToGeneralizedTimeTemplate }, + { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | + SEC_ASN1_EXPLICIT | 1, + offsetof(SecAsn1OCSPSingleResponse, singleExtensions), + kSecAsn1SequenceOfCertExtensionTemplate }, + { 0 } +}; + +/* + * support for ResponderID CHOICE + */ +const SecAsn1Template kSecAsn1OCSPResponderIDAsNameTemplate[] = { + { SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1, + offsetof(SecAsn1OCSPResponderID, byName), + kSecAsn1AnyTemplate } +}; + +const SecAsn1Template kSecAsn1OCSPResponderIDAsKeyTemplate[] = { + { SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 2, + offsetof(SecAsn1OCSPResponderID, byKey), + kSecAsn1OctetStringTemplate } +}; + +const SecAsn1Template kSecAsn1OCSPResponseDataTemplate[] = { + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(SecAsn1OCSPResponseData) }, + /* optional version, explicit tag 0, default 0 */ + { SEC_ASN1_EXPLICIT | SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | + SEC_ASN1_CONTEXT_SPECIFIC | 0, + offsetof(SecAsn1OCSPResponseData, version), + kSecAsn1PointerToIntegerTemplate }, + { SEC_ASN1_ANY, + offsetof(SecAsn1OCSPResponseData, responderID), + kSecAsn1AnyTemplate }, + { SEC_ASN1_GENERALIZED_TIME, offsetof(SecAsn1OCSPResponseData, producedAt) }, + { SEC_ASN1_SEQUENCE_OF, + offsetof(SecAsn1OCSPResponseData, responses), + kSecAsn1OCSPSingleResponseTemplate }, + { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | + SEC_ASN1_EXPLICIT | 1, + offsetof(SecAsn1OCSPResponseData, responseExtensions), + kSecAsn1SequenceOfCertExtensionTemplate }, + { 0 } +}; + +const SecAsn1Template kSecAsn1OCSPBasicResponseTemplate[] = { + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(SecAsn1OCSPBasicResponse) }, + { SEC_ASN1_ANY, offsetof(SecAsn1OCSPBasicResponse, tbsResponseData) }, + { SEC_ASN1_INLINE, + offsetof(SecAsn1OCSPBasicResponse, algId), + kSecAsn1AlgorithmIDTemplate }, + { SEC_ASN1_BIT_STRING, offsetof(SecAsn1OCSPBasicResponse, sig) }, + { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | + SEC_ASN1_EXPLICIT | 0, + offsetof(SecAsn1OCSPBasicResponse, certs), + kSecAsn1SequenceOfAnyTemplate }, + { 0 } +}; + +const SecAsn1Template kSecAsn1OCSPResponseBytesTemplate[] = { + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(SecAsn1OCSPResponseBytes) }, + { SEC_ASN1_OBJECT_ID, offsetof(SecAsn1OCSPResponseBytes, responseType) }, + { SEC_ASN1_OCTET_STRING, offsetof(SecAsn1OCSPResponseBytes, response) }, + { 0 } +}; + +const SecAsn1Template kSecAsn1OCSPPtrToResponseBytesTemplate[] = { + { SEC_ASN1_POINTER, 0, kSecAsn1OCSPResponseBytesTemplate } +}; + +const SecAsn1Template kSecAsn1OCSPResponseTemplate[] = { + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(SecAsn1OCSPResponse) }, + { SEC_ASN1_ENUMERATED, offsetof(SecAsn1OCSPResponse, responseStatus) }, + { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | + SEC_ASN1_EXPLICIT | 0, + offsetof(SecAsn1OCSPResponse, responseBytes), + kSecAsn1OCSPPtrToResponseBytesTemplate }, + { 0 } +}; + +#pragma mark ---- OCSPD RPC ---- + +const SecAsn1Template kSecAsn1OCSPDRequestTemplate[] = { + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(SecAsn1OCSPDRequest) }, + { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | + SEC_ASN1_EXPLICIT | 0, + offsetof(SecAsn1OCSPDRequest, cacheWriteDisable), + kSecAsn1PointerToBooleanTemplate }, + { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | + SEC_ASN1_EXPLICIT | 1, + offsetof(SecAsn1OCSPDRequest, cacheReadDisable), + kSecAsn1PointerToBooleanTemplate }, + { SEC_ASN1_OCTET_STRING, offsetof(SecAsn1OCSPDRequest, certID) }, + { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | + SEC_ASN1_EXPLICIT | 2, + offsetof(SecAsn1OCSPDRequest, ocspReq), + kSecAsn1PointerToOctetStringTemplate }, + { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | + SEC_ASN1_EXPLICIT | 3, + offsetof(SecAsn1OCSPDRequest, localRespURI), + kSecAsn1PointerToIA5StringTemplate }, + { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | + SEC_ASN1_EXPLICIT | 4, + offsetof(SecAsn1OCSPDRequest, urls), + kSecAsn1SequenceOfIA5StringTemplate }, + { 0 } +}; + +const SecAsn1Template kSecAsn1OCSPDRequestsTemplate[] = { + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(SecAsn1OCSPDRequests) }, + { SEC_ASN1_INTEGER, offsetof(SecAsn1OCSPDRequests, version) }, + { SEC_ASN1_SEQUENCE_OF, + offsetof(SecAsn1OCSPDRequests, requests), + kSecAsn1OCSPDRequestTemplate }, + { 0 } +}; + +const SecAsn1Template kSecAsn1OCSPDReplyTemplate[] = { + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(SecAsn1OCSPDReply) }, + { SEC_ASN1_ANY, offsetof(SecAsn1OCSPDReply, certID) }, + { SEC_ASN1_ANY, offsetof(SecAsn1OCSPDReply, ocspResp) }, + { 0 } +}; + +const SecAsn1Template kSecAsn1OCSPDRepliesTemplate[] = { + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(SecAsn1OCSPReplies) }, + { SEC_ASN1_INTEGER, offsetof(SecAsn1OCSPReplies, version) }, + { SEC_ASN1_SEQUENCE_OF, + offsetof(SecAsn1OCSPReplies, replies), + kSecAsn1OCSPDReplyTemplate }, + { 0 } +}; diff --git a/libsecurity_asn1/lib/ocspTemplates.h b/libsecurity_asn1/lib/ocspTemplates.h new file mode 100644 index 00000000..6124d847 --- /dev/null +++ b/libsecurity_asn1/lib/ocspTemplates.h @@ -0,0 +1,337 @@ +/* + * 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@ + * + * ocspTemplates.h - ASN1 templates OCSP requests and responses. + */ + +#ifndef _OCSP_TEMPLATES_H_ +#define _OCSP_TEMPLATES_H_ + +#include /* NSS_CertExtension */ +#include /* NSS_GeneralName and support */ + +#ifdef __cplusplus +extern "C" { +#endif + +#pragma mark ----- OCSP Request ----- + +/* + * CertID ::= SEQUENCE { + * hashAlgorithm AlgorithmIdentifier, + * issuerNameHash OCTET STRING, -- Hash of Issuer's DN + * issuerKeyHash OCTET STRING, -- Hash of Issuers public key + * serialNumber CertificateSerialNumber } -- i.e., INTEGER + */ +typedef struct { + SecAsn1AlgId algId; + SecAsn1Item issuerNameHash; + SecAsn1Item issuerPubKeyHash; + SecAsn1Item serialNumber; +} SecAsn1OCSPCertID; + +extern const SecAsn1Template kSecAsn1OCSPCertIDTemplate[]; + +/* + * Request ::= SEQUENCE { + * reqCert CertID, + * singleRequestExtensions [0] EXPLICIT Extensions OPTIONAL } + */ +typedef struct { + SecAsn1OCSPCertID reqCert; + NSS_CertExtension **extensions; // optional +} SecAsn1OCSPRequest; + +extern const SecAsn1Template kSecAsn1OCSPRequestTemplate[]; + +/* + * Signature ::= SEQUENCE { + * signatureAlgorithm AlgorithmIdentifier, + * signature BIT STRING, + * certs [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL} + * + * Since we wish to avoid knowing anything about the details of the certs, + * we declare them here as ASN_ANY, get/set as raw data, and leave it to + * the CL to parse them. + */ +typedef struct { + SecAsn1AlgId algId; + SecAsn1Item sig; // length in BITS + SecAsn1Item **certs; // OPTIONAL +} SecAsn1OCSPSignature; + +extern const SecAsn1Template kSecAsn1OCSPSignatureTemplate[]; + +/* + * TBSRequest ::= SEQUENCE { + * version [0] EXPLICIT Version DEFAULT v1, + * requestorName [1] EXPLICIT GeneralName OPTIONAL, + * requestList SEQUENCE OF Request, + * requestExtensions [2] EXPLICIT Extensions OPTIONAL } + */ +typedef struct { + SecAsn1Item *version; // OPTIONAL + NSS_GeneralName *requestorName; // OPTIONAL + SecAsn1OCSPRequest **requestList; + NSS_CertExtension **requestExtensions; // OPTIONAL +} SecAsn1OCSPTbsRequest; + +extern const SecAsn1Template kSecAsn1OCSPTbsRequestTemplate[]; + +/* + * OCSPRequest ::= SEQUENCE { + * tbsRequest TBSRequest, + * optionalSignature [0] EXPLICIT Signature OPTIONAL } + */ +typedef struct { + SecAsn1OCSPTbsRequest tbsRequest; + SecAsn1OCSPSignature *signature; // OPTIONAL +} SecAsn1OCSPSignedRequest; + +extern const SecAsn1Template kSecAsn1OCSPSignedRequestTemplate[]; + +#pragma mark ----- OCSP Response ----- + +/* + * CertStatus ::= CHOICE { + * good [0] IMPLICIT NULL, + * revoked [1] IMPLICIT RevokedInfo, + * unknown [2] IMPLICIT UnknownInfo } + * + * RevokedInfo ::= SEQUENCE { + * revocationTime GeneralizedTime, + * revocationReason [0] EXPLICIT CRLReason OPTIONAL } + * + * UnknownInfo ::= NULL -- this can be replaced with an enumeration + * + * See for enum values of CE_CrlReason. + */ +typedef struct { + SecAsn1Item revocationTime; + SecAsn1Item *revocationReason; // OPTIONAL, CE_CrlReason +} SecAsn1OCSPRevokedInfo; + +typedef union { + SecAsn1OCSPRevokedInfo *revokedInfo; + SecAsn1Item *nullData; +} SecAsn1OCSPCertStatus; + +typedef enum { + CS_Good = 0, + CS_Revoked = 1, + CS_Unknown = 2, + CS_NotParsed = 0xff /* Not in protocol: means value not parsed or seen */ +} SecAsn1OCSPCertStatusTag; + +extern const SecAsn1Template kSecAsn1OCSPRevokedInfoTemplate[]; + +/* + * Encode/decode CertStatus separately using one of these  hree templates. + * The result goes into SecAsn1OCSPSingleResponse.certStatus on encode. + */ +extern const SecAsn1Template kSecAsn1OCSPCertStatusGoodTemplate[]; +extern const SecAsn1Template kSecAsn1OCSPCertStatusRevokedTemplate[]; +extern const SecAsn1Template kSecAsn1OCSPCertStatusUnknownTemplate[]; + +/* + * SingleResponse ::= SEQUENCE { + * certID CertID, + * certStatus CertStatus, + * thisUpdate GeneralizedTime, + * nextUpdate [0] EXPLICIT GeneralizedTime OPTIONAL, + * singleExtensions [1] EXPLICIT Extensions OPTIONAL } + */ +typedef struct { + SecAsn1OCSPCertID certID; + SecAsn1Item certStatus; // ASN_ANY here + SecAsn1Item thisUpdate; // GeneralizedTime + SecAsn1Item *nextUpdate; // GeneralizedTime, OPTIONAL + NSS_CertExtension **singleExtensions; // OPTIONAL +} SecAsn1OCSPSingleResponse; + +extern const SecAsn1Template kSecAsn1OCSPSingleResponseTemplate[]; + +/* + * ResponderID ::= CHOICE { + * byName EXPLICIT [1] Name, + * byKey EXPLICIT [2] KeyHash } + * + * Since our ASN.1 encoder/decoder can't handle CHOICEs very well, we encode + * this separately using one of the following two templates. On encode the + * result if this step of the encode goes into SecAsn1OCSPResponseData.responderID, + * where it's treated as an ANY_ANY when encoding that struct. The reverse happens + * on decode. + */ +typedef union { + SecAsn1Item byName; + SecAsn1Item byKey; // key hash in OCTET STRING +} SecAsn1OCSPResponderID; + +typedef enum { + RIT_Name = 1, + RIT_Key = 2 +} SecAsn1OCSPResponderIDTag; + +extern const SecAsn1Template kSecAsn1OCSPResponderIDAsNameTemplate[]; +extern const SecAsn1Template kSecAsn1OCSPResponderIDAsKeyTemplate[]; + +/* + * ResponseData ::= SEQUENCE { + * version [0] EXPLICIT Version DEFAULT v1, + * responderID ResponderID, + * producedAt GeneralizedTime, + * responses SEQUENCE OF SingleResponse, + * responseExtensions [1] EXPLICIT Extensions OPTIONAL } + */ +typedef struct { + SecAsn1Item *version; // OPTIONAL + SecAsn1Item responderID; // ASN_ANY here, decode/encode separately + SecAsn1Item producedAt; // GeneralizedTime + SecAsn1OCSPSingleResponse **responses; + NSS_CertExtension **responseExtensions; // OPTIONAL +} SecAsn1OCSPResponseData; + +extern const SecAsn1Template kSecAsn1OCSPResponseDataTemplate[]; + +/* + * BasicOCSPResponse ::= SEQUENCE { + * tbsResponseData ResponseData, + * signatureAlgorithm AlgorithmIdentifier, + * signature BIT STRING, + * certs [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL } + * + * Since we ALWAYS encode the tbsResponseData in preparation for signing, + * we declare it as a raw ASN_ANY in the BasicOCSPResponse. + * + * Certs are likewise ASN_ANY since we use the CL to parse and create them. + */ +typedef struct { + SecAsn1Item tbsResponseData; + SecAsn1AlgId algId; + SecAsn1Item sig; // length in BITS + SecAsn1Item **certs; // optional +} SecAsn1OCSPBasicResponse; + +extern const SecAsn1Template kSecAsn1OCSPBasicResponseTemplate[]; + +/* + * ResponseBytes ::= SEQUENCE { + * responseType OBJECT IDENTIFIER, + * response OCTET STRING } + * + * The contents of response are actually an encoded SecAsn1OCSPBasicResponse (at + * least until another response type is defined). + */ +typedef struct { + SecAsn1Oid responseType; + SecAsn1Item response; +} SecAsn1OCSPResponseBytes; + +extern const SecAsn1Template kSecAsn1OCSPResponseBytesTemplate[]; + +/* + * OCSPResponse ::= SEQUENCE { + * responseStatus OCSPResponseStatus, -- an ENUM + * responseBytes [0] EXPLICIT ResponseBytes OPTIONAL } + */ +typedef struct { + SecAsn1Item responseStatus; // see enum below + SecAsn1OCSPResponseBytes *responseBytes; // optional +} SecAsn1OCSPResponse; + +extern const SecAsn1Template kSecAsn1OCSPResponseTemplate[]; + +typedef enum { + RS_Success = 0, + RS_MalformedRequest = 1, + RS_InternalError = 2, + RS_TryLater = 3, + RS_Unused = 4, + RS_SigRequired = 5, + RS_Unauthorized = 6 +} SecAsn1OCSPResponseStatus; + +/* + * This is not part of the OCSP protocol; it's used in the communication between + * the Apple X.509 TP module and the ocspd server. + * + * OCSPDRequest ::= SEQUENCE { + * cacheWriteDisable :: = EXPLICIT [0] BOOL OPTIONAL; -- cache write disable + * -- default FALSE + * cacheWriteDisable :: = EXPLICIT [1] BOOL OPTIONAL; -- cache read disable + * -- default FALSE + * certID ::= OCTET STRING; -- for cache lookup + * ocspReq ::= EXPLICIT [2] OCTET STRING OPTIONAL; -- for net fetch + * localResp ::= EXPLICIT [3] IA5String OPTIONAL; -- for local responder + * urls ::= EXPLICIT [4] SEQUENCE of IA5String OPTIONAL; + * -- for normal net fetch + * }; + */ + +#define OCSPD_REQUEST_VERS 0 + +typedef struct { + SecAsn1Item *cacheWriteDisable; + SecAsn1Item *cacheReadDisable; + SecAsn1Item certID; // DER encoded SecAsn1OCSPCertID + SecAsn1Item *ocspReq; // DER encoded SecAsn1OCSPSignedRequest + SecAsn1Item *localRespURI; // local responder URI + SecAsn1Item **urls; // normal URIs + +} SecAsn1OCSPDRequest; + +/* + * And this is a sequence of them, packaged up and sent to ocspd in one RPC. + */ +typedef struct { + SecAsn1Item version; // OCSPD_REQUEST_VERS + SecAsn1OCSPDRequest **requests; +} SecAsn1OCSPDRequests; + +extern const SecAsn1Template kSecAsn1OCSPDRequestTemplate[]; +extern const SecAsn1Template kSecAsn1OCSPDRequestsTemplate[]; + +/* + * Unordered set of replies from ocsdp; they map back to individual + * SecAsn1OCSPDRequests by the encoded certID (which is obtained from the + * SecAsn1OCSPDRequest, NOT from the OCSP response). + */ +typedef struct { + SecAsn1Item certID; // DER encoded SecAsn1OCSPCertID + SecAsn1Item ocspResp; // DER encoded SecAsn1OCSPResponse +} SecAsn1OCSPDReply; + +#define OCSPD_REPLY_VERS 0 + +typedef struct { + SecAsn1Item version; // OCSPD_REPLY_VERS + SecAsn1OCSPDReply **replies; +} SecAsn1OCSPReplies; + +extern const SecAsn1Template kSecAsn1OCSPDReplyTemplate[]; +extern const SecAsn1Template kSecAsn1OCSPDRepliesTemplate[]; + +#ifdef __cplusplus +} +#endif + +#endif /* _OCSP_TEMPLATES_H_ */ diff --git a/libsecurity_asn1/lib/oidsalg.c b/libsecurity_asn1/lib/oidsalg.c new file mode 100644 index 00000000..3c95a3cb --- /dev/null +++ b/libsecurity_asn1/lib/oidsalg.c @@ -0,0 +1,469 @@ +/* + * 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}, + +/* + * 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_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/libsecurity_asn1/lib/oidsalg.h new file mode 100644 index 00000000..a63dc097 --- /dev/null +++ b/libsecurity_asn1/lib/oidsalg.h @@ -0,0 +1,159 @@ +/* + * Copyright (c) 1999-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@ + * + * oidsalg.h -- OIDs defining crypto algorithms + */ + +#ifndef _OIDS_ALG_H_ +#define _OIDS_ALG_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern const SecAsn1Oid + CSSMOID_MD2 DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_MD4 DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_MD5 DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_RSA DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_MD2WithRSA DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_MD4WithRSA DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_MD5WithRSA DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_SHA1WithRSA DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_SHA224WithRSA DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_SHA256WithRSA DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_SHA384WithRSA DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_SHA512WithRSA DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_SHA1WithRSA_OIW DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_RSAWithOAEP DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_OAEP_MGF1 DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_OAEP_ID_PSPECIFIED DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_DES_CBC DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_ANSI_DH_PUB_NUMBER DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_ANSI_DH_STATIC DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_ANSI_DH_ONE_FLOW DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_ANSI_DH_EPHEM DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_ANSI_DH_HYBRID1 DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_ANSI_DH_HYBRID2 DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_ANSI_DH_HYBRID_ONEFLOW DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_ANSI_MQV1 DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_ANSI_MQV2 DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_ANSI_DH_STATIC_SHA1 DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_ANSI_DH_ONE_FLOW_SHA1 DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_ANSI_DH_EPHEM_SHA1 DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_ANSI_DH_HYBRID1_SHA1 DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_ANSI_DH_HYBRID2_SHA1 DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_ANSI_MQV1_SHA1 DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_ANSI_MQV2_SHA1 DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_PKCS3 DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_DH DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_DSA DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, // BSAFE only + CSSMOID_DSA_CMS DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, // X509/CMS + CSSMOID_DSA_JDK DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, // JDK 1.1 + CSSMOID_SHA1WithDSA DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, // BSAFE + CSSMOID_SHA1WithDSA_CMS DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, // X509/CMS + CSSMOID_SHA1WithDSA_JDK DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, // JDK 1.1 + CSSMOID_SHA1 DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_SHA224 DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_SHA256 DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_SHA384 DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_SHA512 DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_ecPublicKey DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_ECDSA_WithSHA1 DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_ECDSA_WithSHA224 DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_ECDSA_WithSHA256 DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_ECDSA_WithSHA384 DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_ECDSA_WithSHA512 DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_ECDSA_WithSpecified DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_APPLE_ISIGN DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_APPLE_X509_BASIC DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_APPLE_TP_SSL DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_APPLE_TP_LOCAL_CERT_GEN DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_APPLE_TP_CSR_GEN DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_APPLE_TP_REVOCATION_CRL DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_APPLE_TP_REVOCATION_OCSP DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_APPLE_TP_SMIME DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_APPLE_TP_EAP DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_APPLE_TP_CODE_SIGN DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_APPLE_TP_SW_UPDATE_SIGNING DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_APPLE_TP_IP_SEC DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_APPLE_TP_ICHAT DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_APPLE_TP_RESOURCE_SIGN DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_APPLE_TP_PKINIT_CLIENT DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_APPLE_TP_PKINIT_SERVER DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_APPLE_TP_CODE_SIGNING DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_APPLE_TP_PACKAGE_SIGNING DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_APPLE_TP_MACAPPSTORE_RECEIPT DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_APPLE_TP_APPLEID_SHARING DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_APPLE_TP_TIMESTAMPING 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, + CSSMOID_APPLE_FEE_SHA1 DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_APPLE_FEED DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_APPLE_FEEDEXP DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_APPLE_ECDSA DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_DOTMAC_CERT DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_DOTMAC_CERT_REQ DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_DOTMAC_CERT_REQ_IDENTITY DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_DOTMAC_CERT_REQ_EMAIL_SIGN DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_DOTMAC_CERT_REQ_EMAIL_ENCRYPT DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_DOTMAC_CERT_REQ_ARCHIVE_LIST DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_DOTMAC_CERT_REQ_ARCHIVE_STORE DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_DOTMAC_CERT_REQ_ARCHIVE_FETCH DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_DOTMAC_CERT_REQ_ARCHIVE_REMOVE DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_DOTMAC_CERT_REQ_SHARED_SERVICES DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_DOTMAC_CERT_REQ_VALUE_USERNAME DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_DOTMAC_CERT_REQ_VALUE_PASSWORD DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_DOTMAC_CERT_REQ_VALUE_HOSTNAME DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_DOTMAC_CERT_REQ_VALUE_RENEW DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_DOTMAC_CERT_REQ_VALUE_ASYNC DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_DOTMAC_CERT_REQ_VALUE_IS_PENDING DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_PKCS5_DIGEST_ALG DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_PKCS5_ENCRYPT_ALG DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_PKCS5_HMAC_SHA1 DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_PKCS5_pbeWithMD2AndDES DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_PKCS5_pbeWithMD2AndRC2 DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_PKCS5_pbeWithMD5AndDES DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_PKCS5_pbeWithMD5AndRC2 DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_PKCS5_pbeWithSHA1AndDES DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_PKCS5_pbeWithSHA1AndRC2 DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_PKCS5_PBKDF2 DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_PKCS5_PBES2 DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_PKCS5_PBMAC1 DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_PKCS5_RC2_CBC DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_PKCS5_DES_EDE3_CBC DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_PKCS5_RC5_CBC DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_PKCS12_pbeWithSHAAnd128BitRC4 DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_PKCS12_pbeWithSHAAnd40BitRC4 DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_PKCS12_pbeWithSHAAnd3Key3DESCBC DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_PKCS12_pbeWithSHAAnd2Key3DESCBC DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_PKCS12_pbeWithSHAAnd128BitRC2CBC DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_PKCS12_pbewithSHAAnd40BitRC2CBC DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +#ifdef __cplusplus +} +#endif + +#endif /* _OIDS_ALG_H_ */ diff --git a/libsecurity_asn1/lib/oidsattr.c b/libsecurity_asn1/lib/oidsattr.c new file mode 100644 index 00000000..83127a75 --- /dev/null +++ b/libsecurity_asn1/lib/oidsattr.c @@ -0,0 +1,506 @@ +/* + * Copyright (c) 2000-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@ + */ + + +/* + * oidsattr.c - Cert/CRL related OIDs. + */ + +#include +#include + + +/* + * Directory name component identifiers. + */ +static const uint8_t + OID_ObjectClass[] = { OID_ATTR_TYPE, 0 }, + OID_AliasedEntryName[] = { OID_ATTR_TYPE, 1 }, + OID_KnowledgeInformation[] = { OID_ATTR_TYPE, 2 }, + OID_CommonName[] = { OID_ATTR_TYPE, 3 }, + OID_Surname[] = { OID_ATTR_TYPE, 4 }, + OID_SerialNumber[] = { OID_ATTR_TYPE, 5 }, + OID_CountryName[] = { OID_ATTR_TYPE, 6 }, + OID_LocalityName[] = { OID_ATTR_TYPE, 7 }, + OID_StateProvinceName[] = { OID_ATTR_TYPE, 8 }, + OID_CollectiveStateProvinceName[] = { OID_ATTR_TYPE, 8, 1 }, + OID_StreetAddress[] = { OID_ATTR_TYPE, 9 }, + OID_CollectiveStreetAddress[] = { OID_ATTR_TYPE, 9, 1 }, + OID_OrganizationName[] = { OID_ATTR_TYPE, 10 }, + OID_CollectiveOrganizationName[] = { OID_ATTR_TYPE, 10, 1 }, + OID_OrganizationalUnitName[] = { OID_ATTR_TYPE, 11 }, + OID_CollectiveOrganizationalUnitName[] + = { OID_ATTR_TYPE, 11, 1 }, + OID_Title[] = { OID_ATTR_TYPE, 12 }, + OID_Description[] = { OID_ATTR_TYPE, 13 }, + OID_SearchGuide[] = { OID_ATTR_TYPE, 14 }, + OID_BusinessCategory[] = { OID_ATTR_TYPE, 15 }, + OID_PostalAddress[] = { OID_ATTR_TYPE, 16 }, + OID_CollectivePostalAddress[] = { OID_ATTR_TYPE, 16, 1 }, + OID_PostalCode[] = { OID_ATTR_TYPE, 17 }, + OID_CollectivePostalCode[] = { OID_ATTR_TYPE, 17, 1 }, + OID_PostOfficeBox[] = { OID_ATTR_TYPE, 18 }, + OID_CollectivePostOfficeBox[] = { OID_ATTR_TYPE, 18, 1 }, + OID_PhysicalDeliveryOfficeName[] = { OID_ATTR_TYPE, 19 }, + OID_CollectivePhysicalDeliveryOfficeName[] + = { OID_ATTR_TYPE, 19, 1 }, + OID_TelephoneNumber[] = { OID_ATTR_TYPE, 20 }, + OID_CollectiveTelephoneNumber[] = { OID_ATTR_TYPE, 20, 1 }, + OID_TelexNumber[] = { OID_ATTR_TYPE, 21 }, + OID_CollectiveTelexNumber[] = { OID_ATTR_TYPE, 21, 1 }, + OID_TelexTerminalIdentifier[] = { OID_ATTR_TYPE, 22 }, + OID_CollectiveTelexTerminalIdentifier[] + = { OID_ATTR_TYPE, 22, 1 }, + OID_FacsimileTelephoneNumber[] = { OID_ATTR_TYPE, 23 }, + OID_CollectiveFacsimileTelephoneNumber[] + = { OID_ATTR_TYPE, 23, 1 }, + OID_X_121Address[] = { OID_ATTR_TYPE, 24 }, + OID_InternationalISDNNumber[] = { OID_ATTR_TYPE, 25 }, + OID_CollectiveInternationalISDNNumber[] + = { OID_ATTR_TYPE, 25, 1 }, + OID_RegisteredAddress[] = { OID_ATTR_TYPE, 26 }, + OID_DestinationIndicator[] = { OID_ATTR_TYPE, 27 }, + OID_PreferredDeliveryMethod[] = { OID_ATTR_TYPE, 28 }, + OID_PresentationAddress[] = { OID_ATTR_TYPE, 29 }, + OID_SupportedApplicationContext[] = { OID_ATTR_TYPE, 30 }, + OID_Member[] = { OID_ATTR_TYPE, 31 }, + OID_Owner[] = { OID_ATTR_TYPE, 32 }, + OID_RoleOccupant[] = { OID_ATTR_TYPE, 33 }, + OID_SeeAlso[] = { OID_ATTR_TYPE, 34 }, + OID_UserPassword[] = { OID_ATTR_TYPE, 35 }, + OID_UserCertificate[] = { OID_ATTR_TYPE, 36 }, + OID_CACertificate[] = { OID_ATTR_TYPE, 37 }, + OID_AuthorityRevocationList[] = { OID_ATTR_TYPE, 38 }, + OID_CertificateRevocationList[] = { OID_ATTR_TYPE, 39 }, + OID_CrossCertificatePair[] = { OID_ATTR_TYPE, 40 }, + OID_Name[] = { OID_ATTR_TYPE, 41 }, + OID_GivenName[] = { OID_ATTR_TYPE, 42 }, + OID_Initials[] = { OID_ATTR_TYPE, 43 }, + OID_GenerationQualifier[] = { OID_ATTR_TYPE, 44 }, + OID_UniqueIdentifier[] = { OID_ATTR_TYPE, 45 }, + OID_DNQualifier[] = { OID_ATTR_TYPE, 46 }, + OID_EnhancedSearchGuide[] = { OID_ATTR_TYPE, 47 }, + OID_ProtocolInformation[] = { OID_ATTR_TYPE, 48 }, + OID_DistinguishedName[] = { OID_ATTR_TYPE, 49 }, + OID_UniqueMember[] = { OID_ATTR_TYPE, 50 }, + OID_HouseIdentifier[] = { OID_ATTR_TYPE, 51 } +; + +const SecAsn1Oid +CSSMOID_ObjectClass = { OID_ATTR_TYPE_LENGTH+1, (uint8_t *)OID_ObjectClass}, +CSSMOID_AliasedEntryName = { OID_ATTR_TYPE_LENGTH+1, (uint8_t *)OID_AliasedEntryName}, +CSSMOID_KnowledgeInformation = { OID_ATTR_TYPE_LENGTH+1, (uint8_t *)OID_KnowledgeInformation}, +CSSMOID_CommonName = { OID_ATTR_TYPE_LENGTH+1, (uint8_t *)OID_CommonName}, +CSSMOID_Surname = { OID_ATTR_TYPE_LENGTH+1, (uint8_t *)OID_Surname}, +CSSMOID_SerialNumber = { OID_ATTR_TYPE_LENGTH+1, (uint8_t *)OID_SerialNumber}, +CSSMOID_CountryName = { OID_ATTR_TYPE_LENGTH+1, (uint8_t *)OID_CountryName}, +CSSMOID_LocalityName = { OID_ATTR_TYPE_LENGTH+1, (uint8_t *)OID_LocalityName}, +CSSMOID_StateProvinceName = { OID_ATTR_TYPE_LENGTH+1, (uint8_t *)OID_StateProvinceName}, +CSSMOID_CollectiveStateProvinceName + = { OID_ATTR_TYPE_LENGTH+2, (uint8_t *)OID_CollectiveStateProvinceName}, +CSSMOID_StreetAddress = { OID_ATTR_TYPE_LENGTH+1, (uint8_t *)OID_StreetAddress}, +CSSMOID_CollectiveStreetAddress = { OID_ATTR_TYPE_LENGTH+2, (uint8_t *)OID_CollectiveStreetAddress}, +CSSMOID_OrganizationName = { OID_ATTR_TYPE_LENGTH+1, (uint8_t *)OID_OrganizationName}, +CSSMOID_CollectiveOrganizationName + = { OID_ATTR_TYPE_LENGTH+2, (uint8_t *)OID_CollectiveOrganizationName}, +CSSMOID_OrganizationalUnitName = { OID_ATTR_TYPE_LENGTH+1, (uint8_t *)OID_OrganizationalUnitName}, +CSSMOID_CollectiveOrganizationalUnitName + = { OID_ATTR_TYPE_LENGTH+2, (uint8_t *)OID_CollectiveOrganizationalUnitName}, +CSSMOID_Title = { OID_ATTR_TYPE_LENGTH+1, (uint8_t *)OID_Title}, +CSSMOID_Description = { OID_ATTR_TYPE_LENGTH+1, (uint8_t *)OID_Description}, +CSSMOID_SearchGuide = { OID_ATTR_TYPE_LENGTH+1, (uint8_t *)OID_SearchGuide}, +CSSMOID_BusinessCategory = { OID_ATTR_TYPE_LENGTH+1, (uint8_t *)OID_BusinessCategory}, +CSSMOID_PostalAddress = { OID_ATTR_TYPE_LENGTH+1, (uint8_t *)OID_PostalAddress}, +CSSMOID_CollectivePostalAddress = { OID_ATTR_TYPE_LENGTH+2, (uint8_t *)OID_CollectivePostalAddress}, +CSSMOID_PostalCode = { OID_ATTR_TYPE_LENGTH+1, (uint8_t *)OID_PostalCode}, +CSSMOID_CollectivePostalCode = { OID_ATTR_TYPE_LENGTH+2, (uint8_t *)OID_CollectivePostalCode}, +CSSMOID_PostOfficeBox = { OID_ATTR_TYPE_LENGTH+1, (uint8_t *)OID_PostOfficeBox}, +CSSMOID_CollectivePostOfficeBox = { OID_ATTR_TYPE_LENGTH+2, (uint8_t *)OID_CollectivePostOfficeBox}, +CSSMOID_PhysicalDeliveryOfficeName + = { OID_ATTR_TYPE_LENGTH+1, (uint8_t *)OID_PhysicalDeliveryOfficeName}, +CSSMOID_CollectivePhysicalDeliveryOfficeName + = { OID_ATTR_TYPE_LENGTH+2, (uint8_t *)OID_CollectivePhysicalDeliveryOfficeName}, +CSSMOID_TelephoneNumber = { OID_ATTR_TYPE_LENGTH+1, (uint8_t *)OID_TelephoneNumber}, +CSSMOID_CollectiveTelephoneNumber + = { OID_ATTR_TYPE_LENGTH+2, (uint8_t *)OID_CollectiveTelephoneNumber}, +CSSMOID_TelexNumber = { OID_ATTR_TYPE_LENGTH+1, (uint8_t *)OID_TelexNumber}, +CSSMOID_CollectiveTelexNumber = { OID_ATTR_TYPE_LENGTH+2, (uint8_t *)OID_CollectiveTelexNumber}, +CSSMOID_TelexTerminalIdentifier = { OID_ATTR_TYPE_LENGTH+1, (uint8_t *)OID_TelexTerminalIdentifier}, +CSSMOID_CollectiveTelexTerminalIdentifier + = { OID_ATTR_TYPE_LENGTH+2, (uint8_t *)OID_CollectiveTelexTerminalIdentifier}, +CSSMOID_FacsimileTelephoneNumber= { OID_ATTR_TYPE_LENGTH+1, (uint8_t *)OID_FacsimileTelephoneNumber}, +CSSMOID_CollectiveFacsimileTelephoneNumber + = { OID_ATTR_TYPE_LENGTH+2, (uint8_t *)OID_CollectiveFacsimileTelephoneNumber}, +CSSMOID_X_121Address = { OID_ATTR_TYPE_LENGTH+1, (uint8_t *)OID_X_121Address}, +CSSMOID_InternationalISDNNumber = { OID_ATTR_TYPE_LENGTH+1, (uint8_t *)OID_InternationalISDNNumber}, +CSSMOID_CollectiveInternationalISDNNumber + = { OID_ATTR_TYPE_LENGTH+2, (uint8_t *)OID_CollectiveInternationalISDNNumber}, +CSSMOID_RegisteredAddress = { OID_ATTR_TYPE_LENGTH+1, (uint8_t *)OID_RegisteredAddress}, +CSSMOID_DestinationIndicator = { OID_ATTR_TYPE_LENGTH+1, (uint8_t *)OID_DestinationIndicator}, +CSSMOID_PreferredDeliveryMethod = { OID_ATTR_TYPE_LENGTH+1, (uint8_t *)OID_PreferredDeliveryMethod}, +CSSMOID_PresentationAddress = { OID_ATTR_TYPE_LENGTH+1, (uint8_t *)OID_PresentationAddress}, +CSSMOID_SupportedApplicationContext + = { OID_ATTR_TYPE_LENGTH+1, (uint8_t *)OID_SupportedApplicationContext}, +CSSMOID_Member = { OID_ATTR_TYPE_LENGTH+1, (uint8_t *)OID_Member}, +CSSMOID_Owner = { OID_ATTR_TYPE_LENGTH+1, (uint8_t *)OID_Owner}, +CSSMOID_RoleOccupant = { OID_ATTR_TYPE_LENGTH+1, (uint8_t *)OID_RoleOccupant}, +CSSMOID_SeeAlso = { OID_ATTR_TYPE_LENGTH+1, (uint8_t *)OID_SeeAlso}, +CSSMOID_UserPassword = { OID_ATTR_TYPE_LENGTH+1, (uint8_t *)OID_UserPassword}, +CSSMOID_UserCertificate = { OID_ATTR_TYPE_LENGTH+1, (uint8_t *)OID_UserCertificate}, +CSSMOID_CACertificate = { OID_ATTR_TYPE_LENGTH+1, (uint8_t *)OID_CACertificate}, +CSSMOID_AuthorityRevocationList = { OID_ATTR_TYPE_LENGTH+1, (uint8_t *)OID_AuthorityRevocationList}, +CSSMOID_CertificateRevocationList + = { OID_ATTR_TYPE_LENGTH+1, (uint8_t *)OID_CertificateRevocationList}, +CSSMOID_CrossCertificatePair = { OID_ATTR_TYPE_LENGTH+1, (uint8_t *)OID_CrossCertificatePair}, +CSSMOID_Name = { OID_ATTR_TYPE_LENGTH+1, (uint8_t *)OID_Name}, +CSSMOID_GivenName = { OID_ATTR_TYPE_LENGTH+1, (uint8_t *)OID_GivenName}, +CSSMOID_Initials = { OID_ATTR_TYPE_LENGTH+1, (uint8_t *)OID_Initials}, +CSSMOID_GenerationQualifier = { OID_ATTR_TYPE_LENGTH+1, (uint8_t *)OID_GenerationQualifier}, +CSSMOID_UniqueIdentifier = { OID_ATTR_TYPE_LENGTH+1, (uint8_t *)OID_UniqueIdentifier}, +CSSMOID_DNQualifier = { OID_ATTR_TYPE_LENGTH+1, (uint8_t *)OID_DNQualifier}, +CSSMOID_EnhancedSearchGuide = { OID_ATTR_TYPE_LENGTH+1, (uint8_t *)OID_EnhancedSearchGuide}, +CSSMOID_ProtocolInformation = { OID_ATTR_TYPE_LENGTH+1, (uint8_t *)OID_ProtocolInformation}, +CSSMOID_DistinguishedName = { OID_ATTR_TYPE_LENGTH+1, (uint8_t *)OID_DistinguishedName}, +CSSMOID_UniqueMember = { OID_ATTR_TYPE_LENGTH+1, (uint8_t *)OID_UniqueMember}, +CSSMOID_HouseIdentifier = { OID_ATTR_TYPE_LENGTH+1, (uint8_t *)OID_HouseIdentifier} +; + + +/* From PKCS 9 */ +static const uint8_t + OID_EmailAddress[] = { OID_PKCS_9, 1 }, + OID_UnstructuredName[] = { OID_PKCS_9, 2 }, + OID_ContentType[] = { OID_PKCS_9, 3 }, + OID_MessageDigest[] = { OID_PKCS_9, 4 }, + OID_SigningTime[] = { OID_PKCS_9, 5 }, + OID_CounterSignature[] = { OID_PKCS_9, 6 }, + OID_ChallengePassword[] = { OID_PKCS_9, 7 }, + OID_UnstructuredAddress[] = { OID_PKCS_9, 8 }, + OID_ExtendedCertificateAttributes[] = { OID_PKCS_9, 9 } +; + +const SecAsn1Oid +CSSMOID_EmailAddress = {OID_PKCS_9_LENGTH+1, (uint8_t *)OID_EmailAddress}, +CSSMOID_UnstructuredName = {OID_PKCS_9_LENGTH+1, (uint8_t *)OID_UnstructuredName}, +CSSMOID_ContentType = {OID_PKCS_9_LENGTH+1, (uint8_t *)OID_ContentType}, +CSSMOID_MessageDigest = {OID_PKCS_9_LENGTH+1, (uint8_t *)OID_MessageDigest}, +CSSMOID_SigningTime = {OID_PKCS_9_LENGTH+1, (uint8_t *)OID_SigningTime}, +CSSMOID_CounterSignature = {OID_PKCS_9_LENGTH+1, (uint8_t *)OID_CounterSignature}, +CSSMOID_ChallengePassword = {OID_PKCS_9_LENGTH+1, (uint8_t *)OID_ChallengePassword}, +CSSMOID_UnstructuredAddress = {OID_PKCS_9_LENGTH+1, (uint8_t *)OID_UnstructuredAddress}, +CSSMOID_ExtendedCertificateAttributes = {OID_PKCS_9_LENGTH+1, (uint8_t *)OID_ExtendedCertificateAttributes}; + +/* PKIX */ +static const uint8_t + OID_QT_CPS[] = { OID_QT, 1 }, + OID_QT_UNOTICE[] = { OID_QT, 2 }, + _OID_AD_OCSP[] = { OID_AD_OCSP }, + OID_AD_CA_ISSUERS[] = { OID_AD, 2 }, + OID_AD_TIME_STAMPING[] = { OID_AD, 3 }, + OID_AD_CA_REPOSITORY[] = { OID_AD, 5 }, + OID_PDA_DATE_OF_BIRTH[] = { OID_PDA, 1 }, + OID_PDA_PLACE_OF_BIRTH[] = { OID_PDA, 2 }, + OID_PDA_GENDER[] = { OID_PDA, 3 }, + OID_PDA_COUNTRY_CITIZEN[] = { OID_PDA, 4 }, + OID_PDA_COUNTRY_RESIDENCE[] = { OID_PDA, 5 }, + OID_QCS_SYNTAX_V1[] = { OID_QCS, 1 }, + OID_QCS_SYNTAX_V2[] = { OID_QCS, 2 } +; + +/* 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 } +; + +const SecAsn1Oid +CSSMOID_QT_CPS = {OID_QT_LENGTH+1, (uint8_t *)OID_QT_CPS}, +CSSMOID_QT_UNOTICE = {OID_QT_LENGTH+1, (uint8_t *)OID_QT_UNOTICE}, +CSSMOID_AD_OCSP = {OID_AD_LENGTH+1, (uint8_t *)_OID_AD_OCSP}, +CSSMOID_AD_CA_ISSUERS = {OID_AD_LENGTH+1, (uint8_t *)OID_AD_CA_ISSUERS}, +CSSMOID_AD_TIME_STAMPING = {OID_AD_LENGTH+1, (uint8_t *)OID_AD_TIME_STAMPING}, +CSSMOID_AD_CA_REPOSITORY = {OID_AD_LENGTH+1, (uint8_t *)OID_AD_CA_REPOSITORY}, +CSSMOID_PDA_DATE_OF_BIRTH = {OID_PDA_LENGTH+1, (uint8_t *)OID_PDA_DATE_OF_BIRTH}, +CSSMOID_PDA_PLACE_OF_BIRTH = {OID_PDA_LENGTH+1, (uint8_t *)OID_PDA_PLACE_OF_BIRTH}, +CSSMOID_PDA_GENDER = {OID_PDA_LENGTH+1, (uint8_t *)OID_PDA_GENDER}, +CSSMOID_PDA_COUNTRY_CITIZEN = {OID_PDA_LENGTH+1, (uint8_t *)OID_PDA_COUNTRY_CITIZEN}, +CSSMOID_PDA_COUNTRY_RESIDENCE = {OID_PDA_LENGTH+1, (uint8_t *)OID_PDA_COUNTRY_RESIDENCE}, +CSSMOID_OID_QCS_SYNTAX_V1 = {OID_QCS_LENGTH+1, (uint8_t *)OID_QCS_SYNTAX_V1}, +CSSMOID_OID_QCS_SYNTAX_V2 = {OID_QCS_LENGTH+1, (uint8_t *)OID_QCS_SYNTAX_V2} +; + +const SecAsn1Oid +CSSMOID_ETSI_QCS_QC_COMPLIANCE = {OID_ETSI_QCS_LENGTH + 1, + (uint8_t *)OID_ETSI_QCS_QC_COMPLICANCE}, +CSSMOID_ETSI_QCS_QC_LIMIT_VALUE = {OID_ETSI_QCS_LENGTH + 1, + (uint8_t *)OID_ETSI_QCS_QC_LIMIT_VALUE}, +CSSMOID_ETSI_QCS_QC_RETENTION = {OID_ETSI_QCS_LENGTH + 1, + (uint8_t *)OID_ETSI_QCS_QC_COMPLICANCE}, +CSSMOID_ETSI_QCS_QC_SSCD = {OID_ETSI_QCS_LENGTH + 1, + (uint8_t *)OID_ETSI_QCS_QC_COMPLICANCE} +; + +#define OID_PKCS12_BagTypes OID_PKCS_12,10,1 +#define OID_PKCS12_BagTypesLength OID_PKCS_12_LENGTH+2 + +#define ID_PKCS9_CertTypes OID_PKCS_9, 22 +#define OID_PKCS9_CertTypesLength OID_PKCS_9_LENGTH+1 +#define ID_PKCS9_CrlTypes OID_PKCS_9, 23 +#define OID_PKCS9_CrlTypesLength OID_PKCS_9_LENGTH+1 + +static const uint8_t + OID_PKCS7_Data[] = { OID_PKCS_7, 1}, + OID_PKCS7_SignedData[] = { OID_PKCS_7, 2}, + OID_PKCS7_EnvelopedData[] = { OID_PKCS_7, 3}, + OID_PKCS7_SignedAndEnvelopedData[] = { OID_PKCS_7, 4}, + OID_PKCS7_DigestedData[] = { OID_PKCS_7, 5}, + OID_PKCS7_EncryptedData[] = { OID_PKCS_7, 6}, + OID_PKCS7_DataWithAttributes[] = { OID_PKCS_7, 7}, + OID_PKCS7_EncryptedPrivateKeyInfo[] = { OID_PKCS_7, 8}, + + OID_PKCS9_FriendlyName[] = { OID_PKCS_9, 20}, + OID_PKCS9_LocalKeyId[] = { OID_PKCS_9, 21}, + OID_PKCS9_CertTypes[] = { ID_PKCS9_CertTypes }, + OID_PKCS9_CrlTypes[] = { ID_PKCS9_CrlTypes }, + OID_PKCS9_X509Certificate[] = { ID_PKCS9_CertTypes, 1 }, + OID_PKCS9_SdsiCertificate[] = { ID_PKCS9_CertTypes, 2 }, + OID_PKCS9_X509Crl[] = { ID_PKCS9_CrlTypes, 1 }, + + OID_PKCS12_keyBag[] = { OID_PKCS12_BagTypes, 1}, + OID_PKCS12_shroundedKeyBag[] = { OID_PKCS12_BagTypes, 2}, + OID_PKCS12_certBag[] = { OID_PKCS12_BagTypes, 3}, + OID_PKCS12_crlBag[] = { OID_PKCS12_BagTypes, 4}, + OID_PKCS12_secretBag[] = { OID_PKCS12_BagTypes, 5}, + OID_PKCS12_safeContentsBag[] = { OID_PKCS12_BagTypes, 6} +; + +/* + -- ContentTypes + {iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-9(9) smime(16) ct(1)} + + -- Attributes + {iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-9(9) smime(16) aa(2)} + + -- eContentType for a time-stamp token + + id-ct-TSTInfo OBJECT IDENTIFIER ::= { iso(1) member-body(2) + us(840) rsadsi(113549) pkcs(1) pkcs-9(9) smime(16) ct(1) 4} + + id-aa-timeStampToken OBJECT IDENTIFIER ::= { iso(1) member-body(2) + us(840) rsadsi(113549) pkcs(1) pkcs-9(9) smime(16) aa(2) 14 } +*/ + +#define ID_PKCS9_SMIME OID_PKCS_9, 16 +#define OID_PKCS9_SMIMELength OID_PKCS_9_LENGTH+1 +#define ID_PKCS9_CONTENT_TYPES ID_PKCS9_SMIME, 1 +#define OID_PKCS9_CT_Length OID_PKCS9_SMIMELength+1 +#define ID_PKCS9_ATTRIBUTES ID_PKCS9_SMIME, 2 +#define OID_PKCS9_Attrs_Length OID_PKCS9_SMIMELength+1 + +static const uint8_t + OID_ID_CT_TSTInfo[] = { ID_PKCS9_CONTENT_TYPES, 4 }, + OID_TimeStampToken[] = { ID_PKCS9_ATTRIBUTES, 14 }; + +const SecAsn1Oid +CSSMOID_PKCS9_Id_Ct_TSTInfo = {OID_PKCS9_CT_Length + 1, + (uint8_t *)OID_ID_CT_TSTInfo }, +CSSMOID_PKCS9_TimeStampToken = {OID_PKCS9_Attrs_Length + 1, + (uint8_t *)OID_TimeStampToken }; + + +const SecAsn1Oid +CSSMOID_PKCS7_Data = {OID_PKCS_7_LENGTH + 1, + (uint8_t *)OID_PKCS7_Data }, +CSSMOID_PKCS7_SignedData = {OID_PKCS_7_LENGTH + 1, + (uint8_t *)OID_PKCS7_SignedData }, +CSSMOID_PKCS7_EnvelopedData = {OID_PKCS_7_LENGTH + 1, + (uint8_t *)OID_PKCS7_EnvelopedData }, +CSSMOID_PKCS7_SignedAndEnvelopedData = {OID_PKCS_7_LENGTH + 1, + (uint8_t *)OID_PKCS7_SignedAndEnvelopedData }, +CSSMOID_PKCS7_DigestedData = {OID_PKCS_7_LENGTH + 1, + (uint8_t *)OID_PKCS7_DigestedData }, +CSSMOID_PKCS7_EncryptedData = {OID_PKCS_7_LENGTH + 1, + (uint8_t *)OID_PKCS7_EncryptedData }, +CSSMOID_PKCS7_DataWithAttributes = {OID_PKCS_7_LENGTH + 1, + (uint8_t *)OID_PKCS7_DataWithAttributes }, +CSSMOID_PKCS7_EncryptedPrivateKeyInfo = {OID_PKCS_7_LENGTH + 1, + (uint8_t *)OID_PKCS7_EncryptedPrivateKeyInfo }, + +CSSMOID_PKCS9_FriendlyName = {OID_PKCS_9_LENGTH + 1, + (uint8_t *)OID_PKCS9_FriendlyName }, +CSSMOID_PKCS9_LocalKeyId = {OID_PKCS_9_LENGTH + 1, + (uint8_t *)OID_PKCS9_LocalKeyId }, +CSSMOID_PKCS9_CertTypes = {OID_PKCS_9_LENGTH + 1, + (uint8_t *)OID_PKCS9_CertTypes }, +CSSMOID_PKCS9_CrlTypes = {OID_PKCS_9_LENGTH + 1, + (uint8_t *)OID_PKCS9_CrlTypes }, +CSSMOID_PKCS9_X509Certificate = {OID_PKCS9_CertTypesLength + 1, + (uint8_t *)OID_PKCS9_X509Certificate }, +CSSMOID_PKCS9_SdsiCertificate = {OID_PKCS9_CertTypesLength + 1, + (uint8_t *)OID_PKCS9_SdsiCertificate }, +CSSMOID_PKCS9_X509Crl = {OID_PKCS9_CrlTypesLength + 1, + (uint8_t *)OID_PKCS9_X509Crl }, + + +CSSMOID_PKCS12_keyBag = {OID_PKCS12_BagTypesLength + 1, + (uint8_t *)OID_PKCS12_keyBag }, +CSSMOID_PKCS12_shroudedKeyBag = {OID_PKCS12_BagTypesLength + 1, + (uint8_t *)OID_PKCS12_shroundedKeyBag }, +CSSMOID_PKCS12_certBag = {OID_PKCS12_BagTypesLength + 1, + (uint8_t *)OID_PKCS12_certBag }, +CSSMOID_PKCS12_crlBag = {OID_PKCS12_BagTypesLength + 1, + (uint8_t *)OID_PKCS12_crlBag }, +CSSMOID_PKCS12_secretBag = {OID_PKCS12_BagTypesLength + 1, + (uint8_t *)OID_PKCS12_secretBag }, +CSSMOID_PKCS12_safeContentsBag = {OID_PKCS12_BagTypesLength + 1, + (uint8_t *)OID_PKCS12_safeContentsBag } + +; + +/* Kerberos PKINIT CMS ContentInfo types */ + +static const uint8_t + OID_KERBv5_PKINIT_AUTH_DATA[] = { OID_KERBv5_PKINIT, 1 }, + OID_KERBv5_PKINIT_DH_KEY_DATA[] = { OID_KERBv5_PKINIT, 2 }, + OID_KERBv5_PKINIT_RKEY_DATA[] = { OID_KERBv5_PKINIT, 3 }; + +const SecAsn1Oid +CSSMOID_KERBv5_PKINIT_AUTH_DATA = { OID_KERBv5_PKINIT_LEN + 1, + (uint8_t *)OID_KERBv5_PKINIT_AUTH_DATA }, +CSSMOID_KERBv5_PKINIT_DH_KEY_DATA = { OID_KERBv5_PKINIT_LEN + 1, + (uint8_t *)OID_KERBv5_PKINIT_DH_KEY_DATA }, +CSSMOID_KERBv5_PKINIT_RKEY_DATA = { OID_KERBv5_PKINIT_LEN + 1, + (uint8_t *)OID_KERBv5_PKINIT_RKEY_DATA }; + +/* + * Additional OIDS for LDAP support + */ + +static const uint8_t + OID_ITU_RFCDATA_2342_UCL_DIRECTORYPILOT_ATTRIBUTES_USERID_Data[] = {OID_ITU_RFCDATA_2342_UCL_DIRECTORYPILOT_ATTRIBUTES_USERID}; + +const SecAsn1Oid +CSSMOID_UserID = {OID_ITU_RFCDATA_2342_UCL_DIRECTORYPILOT_ATTRIBUTES_USERID_LENGTH, (uint8_t *)OID_ITU_RFCDATA_2342_UCL_DIRECTORYPILOT_ATTRIBUTES_USERID_Data}; + +static const uint8_t + OID_ITU_RFCDATA_2342_UCL_DIRECTORYPILOT_ATTRIBUTES_DOMAINCOMPONENT_Data[] = {OID_ITU_RFCDATA_2342_UCL_DIRECTORYPILOT_ATTRIBUTES_DOMAINCOMPONENT}; + +const SecAsn1Oid +CSSMOID_DomainComponent = {OID_ITU_RFCDATA_2342_UCL_DIRECTORYPILOT_ATTRIBUTES_DOMAINCOMPONENT_LENGTH, (uint8_t *)OID_ITU_RFCDATA_2342_UCL_DIRECTORYPILOT_ATTRIBUTES_DOMAINCOMPONENT_Data}; + +/* ANSI X9.62 and Certicom elliptic curve OIDs */ +static const uint8_t + OID_X9_62[] = { OID_ANSI_X9_62 }, + OID_X9_62_FieldType[] = { OID_ANSI_X9_62_FIELD_TYPE }, + OID_X9_62_PubKeyType[] = { OID_ANSI_X9_62_PUBKEY_TYPE }, + OID_X9_62_EllCurve[] = { OID_ANSI_X9_62_ELL_CURVE }, + OID_X9_62_C_TwoCurve[] = { OID_ANSI_X9_62_C_TWO_CURVE }, + OID_X9_62_PrimeCurve[] = { OID_ANSI_X9_62_PRIME_CURVE }, + OID_X9_62_SigType[] = { OID_ANSI_X9_62_SIG_TYPE }, + + /* these two defined in ANSI X9.62 but renamed in common usage */ + OID_secp192r1[] = { OID_ANSI_X9_62_PRIME_CURVE, 1 }, + OID_secp256r1[] = { OID_ANSI_X9_62_PRIME_CURVE, 7 }, + /* remainder defined in Certicom SEC 2 */ + OID_Certicom[] = { OID_CERTICOM }, + OID_CerticomEllCurve[] = { OID_CERTICOM_ELL_CURVE }, + /* curves over prime-order fields */ + OID_secp112r1[] = { OID_CERTICOM_ELL_CURVE, 6 }, + OID_secp112r2[] = { OID_CERTICOM_ELL_CURVE, 7 }, + OID_secp128r1[] = { OID_CERTICOM_ELL_CURVE, 28 }, + OID_secp128r2[] = { OID_CERTICOM_ELL_CURVE, 29 }, + OID_secp160k1[] = { OID_CERTICOM_ELL_CURVE, 9 }, + OID_secp160r1[] = { OID_CERTICOM_ELL_CURVE, 8 }, + OID_secp160r2[] = { OID_CERTICOM_ELL_CURVE, 30 }, + OID_secp192k1[] = { OID_CERTICOM_ELL_CURVE, 31 }, + OID_secp224k1[] = { OID_CERTICOM_ELL_CURVE, 32 }, + OID_secp224r1[] = { OID_CERTICOM_ELL_CURVE, 33 }, + OID_secp256k1[] = { OID_CERTICOM_ELL_CURVE, 10 }, + OID_secp384r1[] = { OID_CERTICOM_ELL_CURVE, 34 }, + OID_secp521r1[] = { OID_CERTICOM_ELL_CURVE, 35 }, + /* curves over characteristic 2 fields */ + OID_sect113r1[] = { OID_CERTICOM_ELL_CURVE, 4 }, + OID_sect113r2[] = { OID_CERTICOM_ELL_CURVE, 5 }, + OID_sect131r1[] = { OID_CERTICOM_ELL_CURVE, 22 }, + OID_sect131r2[] = { OID_CERTICOM_ELL_CURVE, 23 }, + OID_sect163k1[] = { OID_CERTICOM_ELL_CURVE, 1 }, + OID_sect163r1[] = { OID_CERTICOM_ELL_CURVE, 2 }, + OID_sect163r2[] = { OID_CERTICOM_ELL_CURVE, 15 }, + OID_sect193r1[] = { OID_CERTICOM_ELL_CURVE, 24 }, + OID_sect193r2[] = { OID_CERTICOM_ELL_CURVE, 25 }, + OID_sect233k1[] = { OID_CERTICOM_ELL_CURVE, 26 }, + OID_sect233r1[] = { OID_CERTICOM_ELL_CURVE, 27 }, + OID_sect239k1[] = { OID_CERTICOM_ELL_CURVE, 3 }, + OID_sect283k1[] = { OID_CERTICOM_ELL_CURVE, 16 }, + OID_sect283r1[] = { OID_CERTICOM_ELL_CURVE, 17 }, + OID_sect409k1[] = { OID_CERTICOM_ELL_CURVE, 36 }, + OID_sect409r1[] = { OID_CERTICOM_ELL_CURVE, 37 }, + OID_sect571k1[] = { OID_CERTICOM_ELL_CURVE, 38 }, + OID_sect571r1[] = { OID_CERTICOM_ELL_CURVE, 39 } +; + +const SecAsn1Oid + CSSMOID_X9_62 = {OID_ANSI_X9_42_LEN, (uint8_t *)OID_X9_62 }, + CSSMOID_X9_62_FieldType = {OID_ANSI_X9_42_LEN+1, (uint8_t *)OID_X9_62_FieldType }, + CSSMOID_X9_62_PubKeyType = {OID_ANSI_X9_42_LEN+1, (uint8_t *)OID_X9_62_PubKeyType }, + CSSMOID_X9_62_EllCurve = {OID_ANSI_X9_42_LEN+1, (uint8_t *)OID_X9_62_EllCurve }, + CSSMOID_X9_62_C_TwoCurve = {OID_ANSI_X9_62_ELL_CURVE_LEN+1, (uint8_t *)OID_X9_62_C_TwoCurve }, + CSSMOID_X9_62_PrimeCurve = {OID_ANSI_X9_62_ELL_CURVE_LEN+1, (uint8_t *)OID_X9_62_PrimeCurve }, + CSSMOID_X9_62_SigType = {OID_ANSI_X9_42_LEN+1, (uint8_t *)OID_X9_62_SigType }, + CSSMOID_secp192r1 = {OID_ANSI_X9_62_ELL_CURVE_LEN+2, (uint8_t *)OID_secp192r1 }, + CSSMOID_secp256r1 = {OID_ANSI_X9_62_ELL_CURVE_LEN+2, (uint8_t *)OID_secp256r1 }, + CSSMOID_Certicom = {OID_CERTICOM_LEN, (uint8_t *)OID_Certicom }, + CSSMOID_CerticomEllCurve = {OID_CERTICOM_ELL_CURVE_LEN, (uint8_t *)OID_CerticomEllCurve }, + CSSMOID_secp112r1 = {OID_CERTICOM_ELL_CURVE_LEN+1, (uint8_t *)OID_secp112r1 }, + CSSMOID_secp112r2 = {OID_CERTICOM_ELL_CURVE_LEN+1, (uint8_t *)OID_secp112r2 }, + CSSMOID_secp128r1 = {OID_CERTICOM_ELL_CURVE_LEN+1, (uint8_t *)OID_secp128r1 }, + CSSMOID_secp128r2 = {OID_CERTICOM_ELL_CURVE_LEN+1, (uint8_t *)OID_secp128r2 }, + CSSMOID_secp160k1 = {OID_CERTICOM_ELL_CURVE_LEN+1, (uint8_t *)OID_secp160k1 }, + CSSMOID_secp160r1 = {OID_CERTICOM_ELL_CURVE_LEN+1, (uint8_t *)OID_secp160r1 }, + CSSMOID_secp160r2 = {OID_CERTICOM_ELL_CURVE_LEN+1, (uint8_t *)OID_secp160r2 }, + CSSMOID_secp192k1 = {OID_CERTICOM_ELL_CURVE_LEN+1, (uint8_t *)OID_secp192k1 }, + CSSMOID_secp224k1 = {OID_CERTICOM_ELL_CURVE_LEN+1, (uint8_t *)OID_secp224k1 }, + CSSMOID_secp224r1 = {OID_CERTICOM_ELL_CURVE_LEN+1, (uint8_t *)OID_secp224r1 }, + CSSMOID_secp256k1 = {OID_CERTICOM_ELL_CURVE_LEN+1, (uint8_t *)OID_secp256k1 }, + CSSMOID_secp384r1 = {OID_CERTICOM_ELL_CURVE_LEN+1, (uint8_t *)OID_secp384r1 }, + CSSMOID_secp521r1 = {OID_CERTICOM_ELL_CURVE_LEN+1, (uint8_t *)OID_secp521r1 }, + CSSMOID_sect113r1 = {OID_CERTICOM_ELL_CURVE_LEN+1, (uint8_t *)OID_sect113r1 }, + CSSMOID_sect113r2 = {OID_CERTICOM_ELL_CURVE_LEN+1, (uint8_t *)OID_sect113r2 }, + CSSMOID_sect131r1 = {OID_CERTICOM_ELL_CURVE_LEN+1, (uint8_t *)OID_sect131r1 }, + CSSMOID_sect131r2 = {OID_CERTICOM_ELL_CURVE_LEN+1, (uint8_t *)OID_sect131r2 }, + CSSMOID_sect163k1 = {OID_CERTICOM_ELL_CURVE_LEN+1, (uint8_t *)OID_sect163k1 }, + CSSMOID_sect163r1 = {OID_CERTICOM_ELL_CURVE_LEN+1, (uint8_t *)OID_sect163r1 }, + CSSMOID_sect163r2 = {OID_CERTICOM_ELL_CURVE_LEN+1, (uint8_t *)OID_sect163r2 }, + CSSMOID_sect193r1 = {OID_CERTICOM_ELL_CURVE_LEN+1, (uint8_t *)OID_sect193r1 }, + CSSMOID_sect193r2 = {OID_CERTICOM_ELL_CURVE_LEN+1, (uint8_t *)OID_sect193r2 }, + CSSMOID_sect233k1 = {OID_CERTICOM_ELL_CURVE_LEN+1, (uint8_t *)OID_sect233k1 }, + CSSMOID_sect233r1 = {OID_CERTICOM_ELL_CURVE_LEN+1, (uint8_t *)OID_sect233r1 }, + CSSMOID_sect239k1 = {OID_CERTICOM_ELL_CURVE_LEN+1, (uint8_t *)OID_sect239k1 }, + CSSMOID_sect283k1 = {OID_CERTICOM_ELL_CURVE_LEN+1, (uint8_t *)OID_sect283k1 }, + CSSMOID_sect283r1 = {OID_CERTICOM_ELL_CURVE_LEN+1, (uint8_t *)OID_sect283r1 }, + CSSMOID_sect409k1 = {OID_CERTICOM_ELL_CURVE_LEN+1, (uint8_t *)OID_sect409k1 }, + CSSMOID_sect409r1 = {OID_CERTICOM_ELL_CURVE_LEN+1, (uint8_t *)OID_sect409r1 }, + CSSMOID_sect571k1 = {OID_CERTICOM_ELL_CURVE_LEN+1, (uint8_t *)OID_sect571k1 }, + CSSMOID_sect571r1 = {OID_CERTICOM_ELL_CURVE_LEN+1, (uint8_t *)OID_sect571r1 }; diff --git a/libsecurity_asn1/lib/oidsattr.h b/libsecurity_asn1/lib/oidsattr.h new file mode 100644 index 00000000..2a98b499 --- /dev/null +++ b/libsecurity_asn1/lib/oidsattr.h @@ -0,0 +1,225 @@ +/* + * 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@ + * + * oidsattr.h -- Cert/CRL related OIDs. + */ + +#include +#include + +#ifndef _CDSA_OIDSATTR_H_ +#define _CDSA_OIDSATTR_H_ + +/* + * Directory name component identifiers. + */ +extern const SecAsn1Oid + CSSMOID_ObjectClass DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_AliasedEntryName DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_KnowledgeInformation DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_CommonName DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_Surname DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_SerialNumber DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_CountryName DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_LocalityName DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_StateProvinceName DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_CollectiveStateProvinceName DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_StreetAddress DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_CollectiveStreetAddress DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_OrganizationName DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_CollectiveOrganizationName DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_OrganizationalUnitName DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_CollectiveOrganizationalUnitName DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_Title DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_Description DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_SearchGuide DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_BusinessCategory DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_PostalAddress DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_CollectivePostalAddress DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_PostalCode DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_CollectivePostalCode DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_PostOfficeBox DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_CollectivePostOfficeBox DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_PhysicalDeliveryOfficeName DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_CollectivePhysicalDeliveryOfficeName DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_TelephoneNumber DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_CollectiveTelephoneNumber DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_TelexNumber DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_CollectiveTelexNumber DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_TelexTerminalIdentifier DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_CollectiveTelexTerminalIdentifier DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_FacsimileTelephoneNumber DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_CollectiveFacsimileTelephoneNumber DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_X_121Address DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_InternationalISDNNumber DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_CollectiveInternationalISDNNumber DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_RegisteredAddress DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_DestinationIndicator DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_PreferredDeliveryMethod DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_PresentationAddress DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_SupportedApplicationContext DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_Member DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_Owner DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_RoleOccupant DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_SeeAlso DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_UserPassword DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_UserCertificate DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_CACertificate DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_AuthorityRevocationList DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_CertificateRevocationList DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_CrossCertificatePair DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_Name DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_GivenName DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_Initials DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_GenerationQualifier DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_UniqueIdentifier DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_DNQualifier DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_EnhancedSearchGuide DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_ProtocolInformation DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_DistinguishedName DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_UniqueMember DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_HouseIdentifier DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* PKCS 9 */ +extern const SecAsn1Oid + CSSMOID_EmailAddress DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_UnstructuredName DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_ContentType DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_MessageDigest DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_SigningTime DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_CounterSignature DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_ChallengePassword DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_UnstructuredAddress DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_ExtendedCertificateAttributes DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +extern const SecAsn1Oid + CSSMOID_PKCS9_Id_Ct_TSTInfo DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_PKCS9_TimeStampToken DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* PKIX */ +extern const SecAsn1Oid + CSSMOID_QT_CPS DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_QT_UNOTICE DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_AD_OCSP DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_AD_CA_ISSUERS DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_AD_TIME_STAMPING DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_AD_CA_REPOSITORY DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_PDA_DATE_OF_BIRTH DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_PDA_PLACE_OF_BIRTH DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_PDA_GENDER DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_PDA_COUNTRY_CITIZEN DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_PDA_COUNTRY_RESIDENCE DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_OID_QCS_SYNTAX_V1 DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_OID_QCS_SYNTAX_V2 DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* ETSI */ +extern const SecAsn1Oid + CSSMOID_ETSI_QCS_QC_COMPLIANCE DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_ETSI_QCS_QC_LIMIT_VALUE DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_ETSI_QCS_QC_RETENTION DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_ETSI_QCS_QC_SSCD DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* PKCS7 */ +extern const SecAsn1Oid + CSSMOID_PKCS7_Data DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_PKCS7_SignedData DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_PKCS7_EnvelopedData DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_PKCS7_SignedAndEnvelopedData DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_PKCS7_DigestedData DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_PKCS7_EncryptedData DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_PKCS7_DataWithAttributes DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_PKCS7_EncryptedPrivateKeyInfo DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + +/* PKCS8 */ + CSSMOID_PKCS9_FriendlyName DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_PKCS9_LocalKeyId DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_PKCS9_CertTypes DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_PKCS9_CrlTypes DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_PKCS9_X509Certificate DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_PKCS9_SdsiCertificate DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_PKCS9_X509Crl DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + +/* PKCS12 */ + CSSMOID_PKCS12_keyBag DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_PKCS12_shroudedKeyBag DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_PKCS12_certBag DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_PKCS12_crlBag DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_PKCS12_secretBag DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_PKCS12_safeContentsBag DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + +/* RFC 2798 (LDAP) */ + CSSMOID_UserID DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + +/* RFC 1275 (X.500) */ + CSSMOID_DomainComponent DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + +/* Kerberos PKINIT CMS ContentInfo types */ + CSSMOID_KERBv5_PKINIT_AUTH_DATA DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_KERBv5_PKINIT_DH_KEY_DATA DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_KERBv5_PKINIT_RKEY_DATA DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* Elliptic Curve OIDs from X9.62 and Certicom SEC 2 */ +extern const SecAsn1Oid + CSSMOID_X9_62 DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_X9_62_FieldType DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_X9_62_PubKeyType DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_X9_62_EllCurve DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_X9_62_C_TwoCurve DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_X9_62_PrimeCurve DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_X9_62_SigType DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_secp192r1 DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_secp256r1 DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_Certicom DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_CerticomEllCurve DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_secp112r1 DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_secp112r2 DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_secp128r1 DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_secp128r2 DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_secp160k1 DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_secp160r1 DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_secp160r2 DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_secp192k1 DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_secp224k1 DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_secp224r1 DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_secp256k1 DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_secp384r1 DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_secp521r1 DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_sect113r1 DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_sect113r2 DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_sect131r1 DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_sect131r2 DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_sect163k1 DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_sect163r1 DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_sect163r2 DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_sect193r1 DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_sect193r2 DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_sect233k1 DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_sect233r1 DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_sect239k1 DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_sect283k1 DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_sect283r1 DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_sect409k1 DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_sect409r1 DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_sect571k1 DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_sect571r1 DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +#endif /* _CDSA_OIDSATTR_H_*/ diff --git a/libsecurity_asn1/lib/oidsbase.h b/libsecurity_asn1/lib/oidsbase.h new file mode 100644 index 00000000..1dbaa516 --- /dev/null +++ b/libsecurity_asn1/lib/oidsbase.h @@ -0,0 +1,356 @@ +/* + * 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/oidsocsp.c b/libsecurity_asn1/lib/oidsocsp.c new file mode 100644 index 00000000..d28744f4 --- /dev/null +++ b/libsecurity_asn1/lib/oidsocsp.c @@ -0,0 +1,41 @@ +/* + * 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@ + */ + + +/* + File: oidsocsp.cpp + + Contains: Object Identifiers for OCSP + */ + +#include "oidsbase.h" +#include "oidsocsp.h" + +SECASN1OID_DEF(OID_PKIX_OCSP, OID_AD_OCSP); +SECASN1OID_DEF(OID_PKIX_OCSP_BASIC, OID_AD_OCSP, 1); +SECASN1OID_DEF(OID_PKIX_OCSP_NONCE, OID_AD_OCSP, 2); +SECASN1OID_DEF(OID_PKIX_OCSP_CRL, OID_AD_OCSP, 3); +SECASN1OID_DEF(OID_PKIX_OCSP_RESPONSE, OID_AD_OCSP, 4); +SECASN1OID_DEF(OID_PKIX_OCSP_NOCHECK, OID_AD_OCSP, 5); +SECASN1OID_DEF(OID_PKIX_OCSP_ARCHIVE_CUTOFF, OID_AD_OCSP, 6); +SECASN1OID_DEF(OID_PKIX_OCSP_SERVICE_LOCATOR, OID_AD_OCSP, 7); diff --git a/libsecurity_asn1/lib/oidsocsp.h b/libsecurity_asn1/lib/oidsocsp.h new file mode 100644 index 00000000..5db1c207 --- /dev/null +++ b/libsecurity_asn1/lib/oidsocsp.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@ + * + * oidsocsp.h -- Object Identifiers for OCSP + */ + +#ifndef _OIDSOCSP_H_ +#define _OIDSOCSP_H_ 1 + +#ifdef __cplusplus +extern "C" { +#endif + +#include "SecAsn1Types.h" + +extern const SecAsn1Oid + /* OCSP */ + OID_PKIX_OCSP, + OID_PKIX_OCSP_BASIC, + OID_PKIX_OCSP_NONCE, + OID_PKIX_OCSP_CRL, + OID_PKIX_OCSP_RESPONSE, + OID_PKIX_OCSP_NOCHECK, + OID_PKIX_OCSP_ARCHIVE_CUTOFF, + OID_PKIX_OCSP_SERVICE_LOCATOR; + +#ifdef __cplusplus +} +#endif + +#endif /* _OIDSOCSP_H_ */ diff --git a/libsecurity_asn1/lib/osKeyTemplates.c b/libsecurity_asn1/lib/osKeyTemplates.c new file mode 100644 index 00000000..726f3968 --- /dev/null +++ b/libsecurity_asn1/lib/osKeyTemplates.c @@ -0,0 +1,163 @@ +/* + * 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@ + */ +/* + * osKeyTemplate.h - ASN1 templates for openssl asymmetric keys + */ + +#include "osKeyTemplates.h" +#include + +/**** + **** DSA support + ****/ + +/* X509 style DSA algorithm parameters */ +const SecAsn1Template kSecAsn1DSAAlgParamsTemplate[] = { + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSS_DSAAlgParams) }, + { SEC_ASN1_INTEGER, offsetof(NSS_DSAAlgParams,p) }, + { SEC_ASN1_INTEGER, offsetof(NSS_DSAAlgParams,q) }, + { SEC_ASN1_INTEGER, offsetof(NSS_DSAAlgParams,g) }, + { 0, } +}; + +/* BSAFE style DSA algorithm parameters */ +const SecAsn1Template kSecAsn1DSAAlgParamsBSAFETemplate[] = { + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSS_DSAAlgParamsBSAFE) }, + { SEC_ASN1_INTEGER, offsetof(NSS_DSAAlgParamsBSAFE,keySizeInBits) }, + { SEC_ASN1_INTEGER, offsetof(NSS_DSAAlgParamsBSAFE,p) }, + { SEC_ASN1_INTEGER, offsetof(NSS_DSAAlgParamsBSAFE,q) }, + { SEC_ASN1_INTEGER, offsetof(NSS_DSAAlgParamsBSAFE,g) }, + { 0, } +}; + +/* DSA X509-style AlgorithmID */ +const SecAsn1Template kSecAsn1DSAAlgorithmIdX509Template[] = { + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSS_DSAAlgorithmIdX509) }, + { SEC_ASN1_OBJECT_ID, offsetof(NSS_DSAAlgorithmIdX509, algorithm) }, + /* per CMS, this is optional */ + { SEC_ASN1_POINTER | SEC_ASN1_OPTIONAL, + offsetof(NSS_DSAAlgorithmIdX509,params), + kSecAsn1DSAAlgParamsTemplate }, + { 0, } +}; + +/* DSA BSAFE-style AlgorithmID */ +const SecAsn1Template kSecAsn1DSAAlgorithmIdBSAFETemplate[] = { + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSS_DSAAlgorithmIdBSAFE) }, + { SEC_ASN1_OBJECT_ID, offsetof(NSS_DSAAlgorithmIdBSAFE, algorithm) }, + { SEC_ASN1_INLINE, + offsetof(NSS_DSAAlgorithmIdBSAFE,params), + kSecAsn1DSAAlgParamsBSAFETemplate }, + { 0, } +}; + +/**** + **** DSA public keys + ****/ + +/* DSA public key, openssl/X509 format */ +const SecAsn1Template kSecAsn1DSAPublicKeyX509Template[] = { + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSS_DSAPublicKeyX509) }, + { SEC_ASN1_INLINE, + offsetof(NSS_DSAPublicKeyX509, dsaAlg), + kSecAsn1DSAAlgorithmIdX509Template }, + { SEC_ASN1_BIT_STRING, + offsetof(NSS_DSAPublicKeyX509, publicKey), }, + { 0, } +}; + +/* DSA public key, BSAFE/FIPS186 format */ +const SecAsn1Template kSecAsn1DSAPublicKeyBSAFETemplate[] = { + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSS_DSAPublicKeyBSAFE) }, + { SEC_ASN1_INLINE, + offsetof(NSS_DSAPublicKeyBSAFE, dsaAlg), + kSecAsn1DSAAlgorithmIdBSAFETemplate }, + { SEC_ASN1_BIT_STRING, + offsetof(NSS_DSAPublicKeyBSAFE, publicKey), }, + { 0, } +}; + +/**** + **** DSA private keys + ****/ + +/* DSA Private key, openssl custom format */ +const SecAsn1Template kSecAsn1DSAPrivateKeyOpensslTemplate[] = { + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSS_DSAPrivateKeyOpenssl) }, + { SEC_ASN1_INTEGER, offsetof(NSS_DSAPrivateKeyOpenssl,version) }, + { SEC_ASN1_INTEGER, offsetof(NSS_DSAPrivateKeyOpenssl,p) }, + { SEC_ASN1_INTEGER, offsetof(NSS_DSAPrivateKeyOpenssl,q) }, + { SEC_ASN1_INTEGER, offsetof(NSS_DSAPrivateKeyOpenssl,g) }, + { SEC_ASN1_INTEGER, offsetof(NSS_DSAPrivateKeyOpenssl,pub) }, + { SEC_ASN1_INTEGER, offsetof(NSS_DSAPrivateKeyOpenssl,priv) }, + { 0, } +}; + +/* + * DSA private key, BSAFE/FIPS186 style. + * This is basically a DSA-specific NSS_PrivateKeyInfo. + * + * NSS_DSAPrivateKeyBSAFE.privateKey is an octet string containing + * the DER encoding of this. + */ +const SecAsn1Template kSecAsn1DSAPrivateKeyOctsTemplate[] = { + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSS_DSAPrivateKeyOcts) }, + { SEC_ASN1_INTEGER, offsetof(NSS_DSAPrivateKeyOcts,privateKey) }, + { 0, } +}; + +const SecAsn1Template kSecAsn1DSAPrivateKeyBSAFETemplate[] = { + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSS_DSAPrivateKeyBSAFE) }, + { SEC_ASN1_INTEGER, offsetof(NSS_DSAPrivateKeyBSAFE,version) }, + { SEC_ASN1_INLINE, + offsetof(NSS_DSAPrivateKeyBSAFE, dsaAlg), + kSecAsn1DSAAlgorithmIdBSAFETemplate }, + { SEC_ASN1_OCTET_STRING, offsetof(NSS_DSAPrivateKeyBSAFE,privateKey) }, + { 0, } +}; + +/* + * DSA Private Key, PKCS8/SMIME style. + */ +const SecAsn1Template kSecAsn1DSAPrivateKeyPKCS8Template[] = { + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSS_DSAPrivateKeyPKCS8) }, + { SEC_ASN1_INTEGER, offsetof(NSS_DSAPrivateKeyPKCS8,version) }, + { SEC_ASN1_INLINE, + offsetof(NSS_DSAPrivateKeyPKCS8, dsaAlg), + kSecAsn1DSAAlgorithmIdX509Template }, + { SEC_ASN1_OCTET_STRING, offsetof(NSS_DSAPrivateKeyPKCS8,privateKey) }, + { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | + SEC_ASN1_CONTEXT_SPECIFIC | 0, + offsetof(NSS_DSAPrivateKeyPKCS8,attributes), + kSecAsn1SetOfAttributeTemplate }, + { 0, } +}; + +const SecAsn1Template kSecAsn1DSASignatureTemplate[] = { + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSS_DSASignature) }, + { SEC_ASN1_INTEGER, offsetof(NSS_DSASignature,r) }, + { SEC_ASN1_INTEGER, offsetof(NSS_DSASignature,s) }, + { 0, } +}; + + diff --git a/libsecurity_asn1/lib/osKeyTemplates.h b/libsecurity_asn1/lib/osKeyTemplates.h new file mode 100644 index 00000000..2df01047 --- /dev/null +++ b/libsecurity_asn1/lib/osKeyTemplates.h @@ -0,0 +1,208 @@ +/* + * 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@ + */ +/* + * osKeyTemplate.h - ASN1 templates for openssl asymmetric keys + */ + +#ifndef _OS_KEY_TEMPLATES_H_ +#define _OS_KEY_TEMPLATES_H_ + +#include + +/* + * Arrays of SecAsn1Template are always associated with a specific + * C struct. We attempt to use C structs which are defined in CDSA + * if at all possible; these always start with the CSSM_ prefix. + * Otherwise we define the struct here, with an NSS_ prefix. + * In either case, the name of the C struct is listed in comments + * along with the extern declaration of the SecAsn1Template array. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/*** + *** Note: RSA and Diffie-Hellman keys and structs are in + *** security_asn1/keyTemplates.h. + ***/ + +#pragma mark *** DSA *** + +/* + * Note that most of the DSA structs are hand rolled and are not + * expressed in ASN1 in any doc that I'm aware of. + */ + +/**** + **** DSA support + ****/ + +/* + * DSA algorithm parameters. Used in CDSA key generation context as + * well as the parameters in an X509-formatted DSA public key. + */ +typedef struct { + SecAsn1Item p; + SecAsn1Item q; + SecAsn1Item g; +} NSS_DSAAlgParams; + +extern const SecAsn1Template kSecAsn1DSAAlgParamsTemplate[]; + +/* + * DSA algorithm parameters, BSAFE style. Only used in FIPS186 format + * public and private keys. + */ +typedef struct { + SecAsn1Item keySizeInBits; + SecAsn1Item p; + SecAsn1Item q; + SecAsn1Item g; +} NSS_DSAAlgParamsBSAFE; + +extern const SecAsn1Template kSecAsn1DSAAlgParamsBSAFETemplate[]; + +/* + * DSA X509-style AlgorithmID. Avoids ASN_ANY processing via direct + * insertion of the appropriate parameters. + */ +typedef struct { + SecAsn1Oid algorithm; + NSS_DSAAlgParams *params; // optional +} NSS_DSAAlgorithmIdX509; + +extern const SecAsn1Template kSecAsn1DSAAlgorithmIdX509Template[]; + +/* + * DSA AlgorithmID, BSAFE style. Avoids ASN_ANY + * processing via direct insertion of the appropriate parameters. + */ +typedef struct { + SecAsn1Oid algorithm; + NSS_DSAAlgParamsBSAFE params; +} NSS_DSAAlgorithmIdBSAFE; + +extern const SecAsn1Template kSecAsn1DSAAlgorithmIdBSAFETemplate[]; + +/**** + **** DSA public keys + ****/ + +/* + * DSA public key, openssl/X509 format. + * + * The publicKey is actually the DER encoding of an ASN + * integer, wrapped in a BIT STRING. + */ +typedef struct { + NSS_DSAAlgorithmIdX509 dsaAlg; + SecAsn1Item publicKey; // BIT string - Length in bits +} NSS_DSAPublicKeyX509; + +extern const SecAsn1Template kSecAsn1DSAPublicKeyX509Template[]; + +/* + * DSA public key, BSAFE/FIPS186 format. + * The public key is the DER encoding of an ASN integer, wrapped + * in a bit string. + */ +typedef struct { + NSS_DSAAlgorithmIdBSAFE dsaAlg; + SecAsn1Item publicKey; // BIT string - Length in bits +} NSS_DSAPublicKeyBSAFE; + +extern const SecAsn1Template kSecAsn1DSAPublicKeyBSAFETemplate[]; + +/**** + **** DSA private keys + ****/ + +/* + * DSA Private key, openssl custom format. + */ +typedef struct { + SecAsn1Item version; + SecAsn1Item p; + SecAsn1Item q; + SecAsn1Item g; + SecAsn1Item pub; + SecAsn1Item priv; +} NSS_DSAPrivateKeyOpenssl; + +extern const SecAsn1Template kSecAsn1DSAPrivateKeyOpensslTemplate[]; + +/* + * DSA private key, BSAFE/FIPS186 style. + * This is basically a DSA-specific NSS_PrivateKeyInfo. + * + * NSS_DSAPrivateKeyBSAFE.privateKey is an octet string containing + * the DER encoding of this. + */ +typedef struct { + SecAsn1Item privateKey; +} NSS_DSAPrivateKeyOcts; + +extern const SecAsn1Template kSecAsn1DSAPrivateKeyOctsTemplate[]; + +typedef struct { + SecAsn1Item version; + NSS_DSAAlgorithmIdBSAFE dsaAlg; + /* octet string containing a DER-encoded NSS_DSAPrivateKeyOcts */ + SecAsn1Item privateKey; +} NSS_DSAPrivateKeyBSAFE; + +extern const SecAsn1Template kSecAsn1DSAPrivateKeyBSAFETemplate[]; + +/* + * DSA Private Key, PKCS8/SMIME style. Doesn't have keySizeInBits + * in the alg params; has version in the top-level struct; the + * private key itself is a DER-encoded integer wrapped in an + * octet string. + */ +typedef struct { + SecAsn1Item version; + NSS_DSAAlgorithmIdX509 dsaAlg; + /* octet string containing DER-encoded integer */ + SecAsn1Item privateKey; + NSS_Attribute **attributes; // optional +} NSS_DSAPrivateKeyPKCS8; + +extern const SecAsn1Template kSecAsn1DSAPrivateKeyPKCS8Template[]; + +/* + * DSA Signature. + */ +typedef struct { + SecAsn1Item r; + SecAsn1Item s; +} NSS_DSASignature; + +extern const SecAsn1Template kSecAsn1DSASignatureTemplate[]; + +#ifdef __cplusplus +} +#endif + + +#endif /* _OS_KEY_TEMPLATES_H_ */ diff --git a/libsecurity_asn1/lib/pkcs12Templates.c b/libsecurity_asn1/lib/pkcs12Templates.c new file mode 100644 index 00000000..313dda40 --- /dev/null +++ b/libsecurity_asn1/lib/pkcs12Templates.c @@ -0,0 +1,289 @@ +/* + * 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.cpp + */ + +#include +#include "pkcs12Templates.h" +#include "nssUtils.h" +#include "SecAsn1Templates.h" +#include "oidsattr.h" + +const SecAsn1Template NSS_P12_MacDataTemplate[] = { + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(NSS_P12_MacData) }, + { SEC_ASN1_INLINE, + offsetof(NSS_P12_MacData,mac), + NSS_P7_DigestInfoTemplate }, + { SEC_ASN1_OCTET_STRING, + offsetof(NSS_P12_MacData,macSalt) }, + /* iterations is unsigned - right? */ + { SEC_ASN1_INTEGER | SEC_ASN1_OPTIONAL, + offsetof(NSS_P12_MacData,iterations) }, + { 0, } +}; + +const SecAsn1Template pointerToMacDataTemplate[] = { + { SEC_ASN1_POINTER, 0, NSS_P12_MacDataTemplate } +}; + +/* raw PFX with unprocessed authSafe */ +const SecAsn1Template NSS_P12_RawPFXTemplate[] = { + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(NSS_P12_RawPFX) }, + { SEC_ASN1_INTEGER, + offsetof(NSS_P12_RawPFX,version) }, + { SEC_ASN1_INLINE, + offsetof(NSS_P12_RawPFX, authSafe), + NSS_P7_RawContentInfoTemplate }, + { SEC_ASN1_POINTER | SEC_ASN1_OPTIONAL, + offsetof(NSS_P12_RawPFX, macData), + NSS_P12_MacDataTemplate }, + { 0, } +}; + +/* PFX with decoded authSafe */ +const SecAsn1Template NSS_P12_DecodedPFXTemplate[] = { + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(NSS_P12_DecodedPFX) }, + { SEC_ASN1_INTEGER, + offsetof(NSS_P12_DecodedPFX,version) }, + { SEC_ASN1_INLINE, + offsetof(NSS_P12_DecodedPFX, authSafe), + NSS_P7_DecodedContentInfoTemplate }, + { SEC_ASN1_POINTER | SEC_ASN1_OPTIONAL, + offsetof(NSS_P12_DecodedPFX, macData), + NSS_P12_MacDataTemplate }, + { 0, } +}; + +/* AuthenticatedSafe */ +const SecAsn1Template NSS_P12_AuthenticatedSafeTemplate[] = { + { SEC_ASN1_SEQUENCE_OF, + offsetof(NSS_P12_AuthenticatedSafe, info), + NSS_P7_DecodedContentInfoTemplate, + sizeof(NSS_P12_AuthenticatedSafe) } +}; + +/* + * Individual SafeBag type-specific templates here when we write 'em + */ +const SecAsn1Template NSS_P12_PtrToShroudedKeyBagTemplate[] = { + { SEC_ASN1_POINTER, 0, kSecAsn1EncryptedPrivateKeyInfoTemplate } +}; + +/* + * CertBag via SEC_ASN1_DYNAMIC + */ +static const SecAsn1Template * NSS_P12_CertBagChooser( + void *arg, // --> NSS_P12_CertBag + Boolean enc, + const char *buf, // on decode, tag byte + void *dest) // --> NSS_P12_CertBag.bagValue +{ + NSS_P12_CertBag *bag = (NSS_P12_CertBag *)arg; + const SecAsn1Template *templ = NULL; + NSS_P12_CertBagType type = CT_Unknown; + SecAsn1Oid *oid = &bag->bagType; + + if(nssCompareSecAsn1Items(oid, &CSSMOID_PKCS9_X509Certificate)) { + templ = kSecAsn1OctetStringTemplate; + type = CT_X509; + } + else if(nssCompareSecAsn1Items(oid, &CSSMOID_PKCS9_SdsiCertificate)) { + templ = kSecAsn1IA5StringTemplate; + type = CT_SDSI; + } + else { + /* punt */ + templ = kSecAsn1AnyTemplate; + } + if(!enc) { + bag->type = type; + } + return templ; +} + +static const SecAsn1TemplateChooserPtr NSS_P12_CertBagChooserPtr = + NSS_P12_CertBagChooser; + +const SecAsn1Template NSS_P12_CertBagTemplate[] = { + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(NSS_P12_CertBag) }, + { SEC_ASN1_OBJECT_ID, + offsetof(NSS_P12_CertBag,bagType) }, + /* these come in with a tag of 0xA0, context/constructed, + * though I don't know why they are flagged as constructed */ + { SEC_ASN1_DYNAMIC | SEC_ASN1_CONTEXT_SPECIFIC | + SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED | 0, + offsetof(NSS_P12_CertBag, certValue), + &NSS_P12_CertBagChooserPtr }, + { 0, } +}; + +const SecAsn1Template NSS_P12_PtrToCertBagTemplate[] = { + { SEC_ASN1_POINTER, 0, NSS_P12_CertBagTemplate } +}; + +/* + * CrlBag via SEC_ASN1_DYNAMIC + */ +static const SecAsn1Template * NSS_P12_CrlBagChooser( + void *arg, // --> NSS_P12_CrlBag + Boolean enc, + const char *buf, // on decode, tag byte + void *dest) // --> NSS_P12_CertBag.bagValue +{ + NSS_P12_CrlBag *bag = (NSS_P12_CrlBag *)arg; + const SecAsn1Template *templ = NULL; + NSS_P12_CrlBagType type = CRT_Unknown; + SecAsn1Oid *oid = &bag->bagType; + + if(nssCompareSecAsn1Items(oid, &CSSMOID_PKCS9_X509Crl)) { + templ = kSecAsn1OctetStringTemplate; + type = CRT_X509; + } + else { + /* punt */ + templ = kSecAsn1AnyTemplate; + } + if(!enc) { + bag->type = type; + } + return templ; +} + +static const SecAsn1TemplateChooserPtr NSS_P12_CrlBagChooserPtr = + NSS_P12_CrlBagChooser; + +const SecAsn1Template NSS_P12_CrlBagTemplate[] = { + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(NSS_P12_CrlBag) }, + { SEC_ASN1_OBJECT_ID, + offsetof(NSS_P12_CrlBag,bagType) }, + /* these come in with a tag of 0xA0, context/constructed, + * though I don't know why they are flagged as constructed */ + { SEC_ASN1_DYNAMIC | SEC_ASN1_CONTEXT_SPECIFIC | + SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED | 0, + offsetof(NSS_P12_CrlBag, crlValue), + &NSS_P12_CrlBagChooserPtr }, + { 0, } +}; + +const SecAsn1Template NSS_P12_PtrToCrlBagTemplate[] = { + { SEC_ASN1_POINTER, 0, NSS_P12_CrlBagTemplate } +}; + + +/* the stub templates for unimplemented BagTypes */ +#define NSS_P12_PtrToKeyBagTemplate kSecAsn1PointerToAnyTemplate +#define NSS_P12_PtrToSecretBagTemplate kSecAsn1PointerToAnyTemplate +#define NSS_P12_PtrToSafeContentsBagTemplate kSecAsn1PointerToAnyTemplate + + +/* + * SafeBag via SEC_ASN1_DYNAMIC + */ +static const SecAsn1Template * NSS_P12_SafeBagChooser( + void *arg, // --> NSS_P12_SafeBag + Boolean enc, + const char *buf, // on decode, tag byte + void *dest) // --> NSS_P12_SafeBag.bagValue +{ + NSS_P12_SafeBag *bag = (NSS_P12_SafeBag *)arg; + const SecAsn1Template *templ = NULL; + NSS_P12_SB_Type type = BT_None; + SecAsn1Oid *oid = &bag->bagId; + + if(nssCompareSecAsn1Items(oid, &CSSMOID_PKCS12_keyBag)) { + templ = NSS_P12_PtrToKeyBagTemplate; + type = BT_KeyBag; + } + else if(nssCompareSecAsn1Items(oid, &CSSMOID_PKCS12_shroudedKeyBag)) { + templ = NSS_P12_PtrToShroudedKeyBagTemplate; + type = BT_ShroudedKeyBag; + } + else if(nssCompareSecAsn1Items(oid, &CSSMOID_PKCS12_certBag)) { + templ = NSS_P12_PtrToCertBagTemplate; + type = BT_CertBag; + } + else if(nssCompareSecAsn1Items(oid, &CSSMOID_PKCS12_crlBag)) { + templ = NSS_P12_PtrToCrlBagTemplate; + type = BT_CrlBag; + } + else if(nssCompareSecAsn1Items(oid, &CSSMOID_PKCS12_secretBag)) { + templ = NSS_P12_PtrToSecretBagTemplate; + type = BT_SecretBag; + } + else if(nssCompareSecAsn1Items(oid, &CSSMOID_PKCS12_safeContentsBag)) { + templ = NSS_P12_PtrToSafeContentsBagTemplate; + type = BT_SafeContentsBag; + } + /* add more here when we implement them */ + else { + templ = kSecAsn1PointerToAnyTemplate; + } + if(!enc) { + bag->type = type; + } + return templ; +} + +static const SecAsn1TemplateChooserPtr NSS_P12_SafeBagChooserPtr = + NSS_P12_SafeBagChooser; + +const SecAsn1Template NSS_P12_SafeBagTemplate[] = { + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(NSS_P12_SafeBag) }, + { SEC_ASN1_OBJECT_ID, + offsetof(NSS_P12_SafeBag,bagId) }, + { SEC_ASN1_DYNAMIC | SEC_ASN1_CONSTRUCTED | + SEC_ASN1_EXPLICIT | SEC_ASN1_CONTEXT_SPECIFIC | 0, + offsetof(NSS_P12_SafeBag,bagValue), + &NSS_P12_SafeBagChooserPtr }, + { SEC_ASN1_OPTIONAL | SEC_ASN1_SET_OF, + offsetof(NSS_P12_SafeBag,bagAttrs), + kSecAsn1AttributeTemplate }, + { 0 } +}; + +const SecAsn1Template NSS_P12_SafeContentsTemplate[] = { + { SEC_ASN1_SEQUENCE_OF, + offsetof(NSS_P12_SafeContents, bags), + NSS_P12_SafeBagTemplate, + sizeof(NSS_P12_SafeContents) } +}; + +const SecAsn1Template NSS_P12_PBE_ParamsTemplate[] = { + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(NSS_P12_PBE_Params) }, + { SEC_ASN1_OCTET_STRING, + offsetof(NSS_P12_PBE_Params,salt) }, + /* iterations is unsigned - right? */ + { SEC_ASN1_INTEGER, + offsetof(NSS_P12_PBE_Params,iterations) }, + { 0 } +}; + + diff --git a/libsecurity_asn1/lib/pkcs12Templates.h b/libsecurity_asn1/lib/pkcs12Templates.h new file mode 100644 index 00000000..b5d6523e --- /dev/null +++ b/libsecurity_asn1/lib/pkcs12Templates.h @@ -0,0 +1,284 @@ +/* + * 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.c b/libsecurity_asn1/lib/pkcs7Templates.c new file mode 100644 index 00000000..afde23ba --- /dev/null +++ b/libsecurity_asn1/lib/pkcs7Templates.c @@ -0,0 +1,162 @@ +/* + * 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.cpp + */ + +#include +#include "pkcs7Templates.h" +#include "keyTemplates.h" /* NSS_AlgorithmIDTemplate */ +#include "SecAsn1Templates.h" +#include "nssUtils.h" +#include "oidsattr.h" + +const SecAsn1Template NSS_P7_DigestInfoTemplate[] = { + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(NSS_P7_DigestInfo) }, + { SEC_ASN1_INLINE, + offsetof(NSS_P7_DigestInfo,digestAlgorithm), + kSecAsn1AlgorithmIDTemplate }, + { SEC_ASN1_OCTET_STRING, + offsetof(NSS_P7_DigestInfo,digest) }, + { 0 } +}; + +/* + * Uninterpreted ContentInfo, with content stripped from its + * EXPLICIT CONTEXT_SPECIFIC wrapper + */ +const SecAsn1Template NSS_P7_RawContentInfoTemplate[] = { + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(NSS_P7_RawContentInfo) }, + { SEC_ASN1_OBJECT_ID, + offsetof(NSS_P7_RawContentInfo,contentType) }, + { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_EXPLICIT | + SEC_ASN1_CONSTRUCTED | SEC_ASN1_OPTIONAL | 0, + offsetof(NSS_P7_RawContentInfo,content), + kSecAsn1AnyTemplate }, + { 0 } +}; + +/* + * Individual ContentInfo.content templates + */ +const SecAsn1Template NSS_P7_EncrContentInfoTemplate[] = { + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(NSS_P7_EncrContentInfo) }, + { SEC_ASN1_OBJECT_ID, + offsetof(NSS_P7_EncrContentInfo,contentType) }, + { SEC_ASN1_INLINE, + offsetof(NSS_P7_EncrContentInfo,encrAlg), + kSecAsn1AlgorithmIDTemplate }, + { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_OPTIONAL | 0, + offsetof(NSS_P7_EncrContentInfo,encrContent), + kSecAsn1OctetStringTemplate }, + { 0 } +}; + +const SecAsn1Template NSS_P7_EncryptedDataTemplate[] = { + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(NSS_P7_EncryptedData) }, + { SEC_ASN1_INTEGER, + offsetof(NSS_P7_EncryptedData,version) }, + { SEC_ASN1_INLINE, + offsetof(NSS_P7_EncryptedData,contentInfo), + NSS_P7_EncrContentInfoTemplate }, + { 0 } +}; + +const SecAsn1Template NSS_P7_PtrToEncryptedDataTemplate[] = { + { SEC_ASN1_POINTER, 0, NSS_P7_EncryptedDataTemplate } +}; + +/* + * Decoded ContentInfo via SEC_ASN1_DYNAMIC + */ + +static const SecAsn1Template * NSS_P7_ContentInfoChooser( + void *arg, // --> NSS_P7_DecodedContentInfo + Boolean enc, + const char *buf, // on decode, tag byte + void *dest) // --> NSS_P7_DecodedContentInfo.content +{ + NSS_P7_DecodedContentInfo *dci = + (NSS_P7_DecodedContentInfo *)arg; + const SecAsn1Template *templ = NULL; + NSS_P7_CI_Type type = CT_None; + + if(nssCompareSecAsn1Items(&dci->contentType, + &CSSMOID_PKCS7_Data)) { + templ = kSecAsn1PointerToOctetStringTemplate; + type = CT_Data; + } + else if(nssCompareSecAsn1Items(&dci->contentType, + &CSSMOID_PKCS7_EncryptedData)) { + templ = NSS_P7_PtrToEncryptedDataTemplate; + type = CT_EncryptedData; + } + else if(nssCompareSecAsn1Items(&dci->contentType, + &CSSMOID_PKCS7_SignedData)) { + templ = NSS_P7_PtrToSignedDataTemplate; + type = CT_SignedData; + } + else if(nssCompareSecAsn1Items(&dci->contentType, + &CSSMOID_PKCS7_EnvelopedData)) { + templ = NSS_P7_PtrToEnvelDataTemplate; + type = CT_EnvData; + } + else if(nssCompareSecAsn1Items(&dci->contentType, + &CSSMOID_PKCS7_SignedAndEnvelopedData)) { + templ = NSS_P7_PtrToSignEnvelDataTemplate; + type = CT_SignedEnvData; + } + else if(nssCompareSecAsn1Items(&dci->contentType, + &CSSMOID_PKCS7_DigestedData)) { + templ = NSS_P7_PtrToDigestedDataTemplate; + type = CT_DigestData; + } + /* add more here when we implement them */ + else { + return kSecAsn1PointerToAnyTemplate; + } + if(!enc) { + dci->type = type; + } + return templ; +} + +static const SecAsn1TemplateChooserPtr NSS_P7_ContentInfoChooserPtr = + NSS_P7_ContentInfoChooser; + +const SecAsn1Template NSS_P7_DecodedContentInfoTemplate[] = { + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(NSS_P7_DecodedContentInfo) }, + { SEC_ASN1_OBJECT_ID, + offsetof(NSS_P7_DecodedContentInfo,contentType) }, + { SEC_ASN1_OPTIONAL | SEC_ASN1_DYNAMIC | + SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED | + SEC_ASN1_CONTEXT_SPECIFIC | 0, + offsetof(NSS_P7_DecodedContentInfo,content), + &NSS_P7_ContentInfoChooserPtr }, + { 0 } +}; diff --git a/libsecurity_asn1/lib/pkcs7Templates.h b/libsecurity_asn1/lib/pkcs7Templates.h new file mode 100644 index 00000000..05fe8f15 --- /dev/null +++ b/libsecurity_asn1/lib/pkcs7Templates.h @@ -0,0 +1,165 @@ +/* + * 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[]; + +#pragma 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 + +#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 { + 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/libsecurity_asn1/lib/plarena.c new file mode 100644 index 00000000..44d2df72 --- /dev/null +++ b/libsecurity_asn1/lib/plarena.c @@ -0,0 +1,381 @@ +/* + * 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@ + */ +/* + * 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. + */ + +/* + * Lifetime-based fast allocation, inspired by much prior art, including + * "Fast Allocation and Deallocation of Memory Based on Object Lifetimes" + * David R. Hanson, Software -- Practice and Experience, Vol. 20(1). + */ +#include +#include +#include "plarena.h" +#include "prmem.h" +#include "prbit.h" +#include "prlog.h" +#include "prinit.h" + +#ifdef PL_ARENAMETER +static PLArenaStats *arena_stats_list; + +#define COUNT(pool,what) (pool)->stats.what++ +#else +#define COUNT(pool,what) /* nothing */ +#endif + +#define PL_ARENA_DEFAULT_ALIGN sizeof(double) + +PR_IMPLEMENT(void) PL_InitArenaPool( + PLArenaPool *pool, const char *name, PRUint32 size, PRUint32 align) +{ +#if !defined (__GNUC__) +#pragma unused (name) +#endif + + if (align == 0) + align = PL_ARENA_DEFAULT_ALIGN; + pool->mask = PR_BITMASK(PR_CeilingLog2(align)); + pool->first.next = NULL; + pool->first.base = pool->first.avail = pool->first.limit = + (PRUword)PL_ARENA_ALIGN(pool, &pool->first + 1); + pool->current = &pool->first; + pool->arenasize = size; +#ifdef PL_ARENAMETER + memset(&pool->stats, 0, sizeof pool->stats); + pool->stats.name = strdup(name); + pool->stats.next = arena_stats_list; + arena_stats_list = &pool->stats; +#endif +} + + +/* +** PL_ArenaAllocate() -- allocate space from an arena pool +** +** Description: PL_ArenaAllocate() allocates space from an arena +** pool. +** +** First, try to satisfy the request from arenas starting at +** pool->current. Then try to allocate a new arena from the heap. +** +** Returns: pointer to allocated space or NULL +** +** Notes: The original implementation had some difficult to +** solve bugs; the code was difficult to read. Sometimes it's +** just easier to rewrite it. I did that. larryh. +** +** See also: bugzilla: 45343. +** +*/ + +PR_IMPLEMENT(void *) PL_ArenaAllocate(PLArenaPool *pool, PRUint32 nb) +{ + PLArena *a; + char *rp; /* returned pointer */ + + PR_ASSERT((nb & pool->mask) == 0); + + nb = (PRUint32)PL_ARENA_ALIGN(pool, nb); /* force alignment */ + + /* attempt to allocate from arenas at pool->current */ + { + a = pool->current; + do { + if ( a->avail +nb <= a->limit ) { + pool->current = a; + rp = (char *)a->avail; + a->avail += nb; + return rp; + } + } while( NULL != (a = a->next) ); + } + + /* attempt to allocate from the heap */ + { + PRSize sz = PR_MAX(pool->arenasize, nb); + sz += sizeof(*a) + pool->mask; /* header and alignment slop */ + a = (PLArena*)PR_MALLOC(sz); + if ( NULL != a ) { + a->limit = (PRUword)a + sz; + a->base = a->avail = (PRUword)PL_ARENA_ALIGN(pool, a + 1); + rp = (char *)a->avail; + a->avail += nb; + /* the newly allocated arena is linked after pool->current + * and becomes pool->current */ + a->next = pool->current->next; + pool->current->next = a; + pool->current = a; + if ( NULL == pool->first.next ) + pool->first.next = a; + PL_COUNT_ARENA(pool,++); + COUNT(pool, nmallocs); + return(rp); + } + } + + /* we got to here, and there's no memory to allocate */ + return(NULL); +} /* --- end PL_ArenaAllocate() --- */ + +/* + * Grow, a.k.a. realloc. The PL_ARENA_GROW macro has already handled + * the possible grow-in-place action in which the current PLArena is the + * source of the incoming pointer, and there is room in that arena for + * the requested size. + */ +PR_IMPLEMENT(void *) PL_ArenaGrow( + PLArenaPool *pool, void *p, PRUint32 origSize, PRUint32 incr) +{ + void *newp; + PLArena *thisArena; + PLArena *lastArena; + PRUint32 origAlignSize; // bytes currently reserved for caller + PRUint32 newSize; // bytes actually mallocd here + + /* expand at least by 2x */ + origAlignSize = PL_ARENA_ALIGN(pool, origSize); + newSize = PR_MAX(origAlignSize+incr, 2*origAlignSize); + newSize = PL_ARENA_ALIGN(pool, newSize); + PL_ARENA_ALLOCATE(newp, pool, newSize); + if (newp == NULL) { + return NULL; + } + + /* + * Trim back the memory we just allocated to the amount our caller really + * needs, leaving the remainder for grow-in-place on subsequent calls + * to PL_ARENA_GROW. + */ + PRUint32 newAlignSize = PL_ARENA_ALIGN(pool, origSize+incr); + PR_ASSERT(pool->current->avail == ((PRUword)newp + newSize)); + pool->current->avail = (PRUword)newp + newAlignSize; + PR_ASSERT(pool->current->avail <= pool->current->limit); + + /* "realloc" */ + memcpy(newp, p, origSize); + + /* + * Free old memory only if it's the entire outstanding allocated + * memory associated with one of our known PLArenas. + */ + lastArena = &pool->first; /* pool->first always empty */ + thisArena = lastArena->next; /* so, start here */ + + PRUword origPtr = (PRUword)p; + while(thisArena != NULL) { + if(origPtr == thisArena->base) { + if((origPtr + origAlignSize) == thisArena->avail) { + /* unlink */ + lastArena->next = thisArena->next; + + /* and free */ + PL_CLEAR_ARENA(thisArena); + PL_COUNT_ARENA(pool,--); + PR_DELETE(thisArena); + break; + } + } + lastArena = thisArena; + thisArena = thisArena->next; + } + /* + * Note: inability to free is not an error; it just causes a temporary leak + * of the old buffer (until the arena pool is freed, of course). + */ + return newp; +} + +/* + * Free tail arenas linked after head, which may not be the true list head. + * Reset pool->current to point to head in case it pointed at a tail arena. + */ +static void FreeArenaList(PLArenaPool *pool, PLArena *head, PRBool reallyFree) +{ + PLArena **ap, *a; + + ap = &head->next; + a = *ap; + if (!a) + return; + + do { + *ap = a->next; + PL_CLEAR_ARENA(a); + PL_COUNT_ARENA(pool,--); + PR_DELETE(a); + } while ((a = *ap) != 0); + + pool->current = head; +} + +PR_IMPLEMENT(void) PL_ArenaRelease(PLArenaPool *pool, char *mark) +{ + #if ARENA_MARK_ENABLE + PLArena *a; + + for (a = pool->first.next; a; a = a->next) { + if (PR_UPTRDIFF(mark, a->base) < PR_UPTRDIFF(a->avail, a->base)) { + a->avail = (PRUword)PL_ARENA_ALIGN(pool, mark); + FreeArenaList(pool, a, PR_FALSE); + return; + } + } + #endif /* ARENA_MARK_ENABLE */ +} + +PR_IMPLEMENT(void) PL_FreeArenaPool(PLArenaPool *pool) +{ + FreeArenaList(pool, &pool->first, PR_FALSE); + COUNT(pool, ndeallocs); +} + +PR_IMPLEMENT(void) PL_FinishArenaPool(PLArenaPool *pool) +{ + FreeArenaList(pool, &pool->first, PR_TRUE); +#ifdef PL_ARENAMETER + { + PLArenaStats *stats, **statsp; + + if (pool->stats.name) + PR_DELETE(pool->stats.name); + for (statsp = &arena_stats_list; (stats = *statsp) != 0; + statsp = &stats->next) { + if (stats == &pool->stats) { + *statsp = stats->next; + return; + } + } + } +#endif +} + +PR_IMPLEMENT(void) PL_CompactArenaPool(PLArenaPool *ap) +{ +} + +PR_IMPLEMENT(void) PL_ArenaFinish(void) +{ +} + +#ifdef PL_ARENAMETER +PR_IMPLEMENT(void) PL_ArenaCountAllocation(PLArenaPool *pool, PRUint32 nb) +{ + pool->stats.nallocs++; + pool->stats.nbytes += nb; + if (nb > pool->stats.maxalloc) + pool->stats.maxalloc = nb; + pool->stats.variance += nb * nb; +} + +PR_IMPLEMENT(void) PL_ArenaCountInplaceGrowth( + PLArenaPool *pool, PRUint32 size, PRUint32 incr) +{ + pool->stats.ninplace++; +} + +PR_IMPLEMENT(void) PL_ArenaCountGrowth( + PLArenaPool *pool, PRUint32 size, PRUint32 incr) +{ + pool->stats.ngrows++; + pool->stats.nbytes += incr; + pool->stats.variance -= size * size; + size += incr; + if (size > pool->stats.maxalloc) + pool->stats.maxalloc = size; + pool->stats.variance += size * size; +} + +PR_IMPLEMENT(void) PL_ArenaCountRelease(PLArenaPool *pool, char *mark) +{ + pool->stats.nreleases++; +} + +PR_IMPLEMENT(void) PL_ArenaCountRetract(PLArenaPool *pool, char *mark) +{ + pool->stats.nfastrels++; +} + +#include +#include + +PR_IMPLEMENT(void) PL_DumpArenaStats(FILE *fp) +{ + PLArenaStats *stats; + double mean, variance; + + for (stats = arena_stats_list; stats; stats = stats->next) { + if (stats->nallocs != 0) { + mean = (double)stats->nbytes / stats->nallocs; + variance = fabs(stats->variance / stats->nallocs - mean * mean); + } else { + mean = variance = 0; + } + + fprintf(fp, "\n%s allocation statistics:\n", stats->name); + fprintf(fp, " number of arenas: %u\n", stats->narenas); + fprintf(fp, " number of allocations: %u\n", stats->nallocs); + fprintf(fp, " number of free arena reclaims: %u\n", stats->nreclaims); + fprintf(fp, " number of malloc calls: %u\n", stats->nmallocs); + fprintf(fp, " number of deallocations: %u\n", stats->ndeallocs); + fprintf(fp, " number of allocation growths: %u\n", stats->ngrows); + fprintf(fp, " number of in-place growths: %u\n", stats->ninplace); + fprintf(fp, "number of released allocations: %u\n", stats->nreleases); + fprintf(fp, " number of fast releases: %u\n", stats->nfastrels); + fprintf(fp, " total bytes allocated: %u\n", stats->nbytes); + fprintf(fp, " mean allocation size: %g\n", mean); + fprintf(fp, " standard deviation: %g\n", sqrt(variance)); + fprintf(fp, " maximum allocation size: %u\n", stats->maxalloc); + } +} +#endif /* PL_ARENAMETER */ diff --git a/libsecurity_asn1/lib/plarena.h b/libsecurity_asn1/lib/plarena.h new file mode 100644 index 00000000..944deb45 --- /dev/null +++ b/libsecurity_asn1/lib/plarena.h @@ -0,0 +1,216 @@ +/* -*- 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 plarena_h___ +#define plarena_h___ +/* + * Lifetime-based fast allocation, inspired by much prior art, including + * "Fast Allocation and Deallocation of Memory Based on Object Lifetimes" + * David R. Hanson, Software -- Practice and Experience, Vol. 20(1). + * + * Also supports LIFO allocation (PL_ARENA_MARK/PL_ARENA_RELEASE). + */ +#include "prtypes.h" +#include "plarenas.h" + +PR_BEGIN_EXTERN_C + +typedef struct PLArena PLArena; + +struct PLArena { + PLArena *next; /* next arena for this lifetime */ + PRUword base; /* aligned base address, follows this header */ + PRUword limit; /* one beyond last byte in arena */ + PRUword avail; /* points to next available byte */ +}; + +#ifdef PL_ARENAMETER +typedef struct PLArenaStats PLArenaStats; + +struct PLArenaStats { + PLArenaStats *next; /* next in arenaStats list */ + char *name; /* name for debugging */ + PRUint32 narenas; /* number of arenas in pool */ + PRUint32 nallocs; /* number of PL_ARENA_ALLOCATE() calls */ + PRUint32 nreclaims; /* number of reclaims from freeArenas */ + PRUint32 nmallocs; /* number of malloc() calls */ + PRUint32 ndeallocs; /* number of lifetime deallocations */ + PRUint32 ngrows; /* number of PL_ARENA_GROW() calls */ + PRUint32 ninplace; /* number of in-place growths */ + PRUint32 nreleases; /* number of PL_ARENA_RELEASE() calls */ + PRUint32 nfastrels; /* number of "fast path" releases */ + PRUint32 nbytes; /* total bytes allocated */ + PRUint32 maxalloc; /* maximum allocation size in bytes */ + PRFloat64 variance; /* size variance accumulator */ +}; +#endif + +struct PLArenaPool { + PLArena first; /* first arena in pool list */ + PLArena *current; /* arena from which to allocate space */ + PRSize arenasize; /* net exact size of a new arena */ + PRUword mask; /* alignment mask (power-of-2 - 1) */ +#ifdef PL_ARENAMETER + PLArenaStats stats; +#endif +}; + +/* + * If the including .c file uses only one power-of-2 alignment, it may define + * PL_ARENA_CONST_ALIGN_MASK to the alignment mask and save a few instructions + * per ALLOCATE and GROW. + */ +#ifdef PL_ARENA_CONST_ALIGN_MASK +#define PL_ARENA_ALIGN(pool, n) (((PRUword)(n) + PL_ARENA_CONST_ALIGN_MASK) \ + & ~PL_ARENA_CONST_ALIGN_MASK) + +#define PL_INIT_ARENA_POOL(pool, name, size) \ + PL_InitArenaPool(pool, name, size, PL_ARENA_CONST_ALIGN_MASK + 1) +#else +#define PL_ARENA_ALIGN(pool, n) (typeof(n))(((PRUword)(n) + (pool)->mask) & ~(pool)->mask) +#endif + +#define PL_ARENA_ALLOCATE(p, pool, nb) \ + PR_BEGIN_MACRO \ + PLArena *_a = (pool)->current; \ + PRUint32 _nb = PL_ARENA_ALIGN(pool, nb); \ + PRUword _p = _a->avail; \ + PRUword _q = _p + _nb; \ + if (_q > _a->limit) \ + _p = (PRUword)PL_ArenaAllocate(pool, _nb); \ + else \ + _a->avail = _q; \ + p = (void *)_p; \ + PL_ArenaCountAllocation(pool, nb); \ + PR_END_MACRO + +#define PL_ARENA_GROW(p, pool, size, incr) \ + PR_BEGIN_MACRO \ + PLArena *_a = (pool)->current; \ + PRUword _p = _a->avail; \ + PRUword _q = (PRUword)p + size + incr; \ + if (_p == (PRUword)(p) + PL_ARENA_ALIGN(pool, size) && \ + _q <= _a->limit) { \ + _a->avail = PL_ARENA_ALIGN(pool, _q); \ + PL_ArenaCountInplaceGrowth(pool, size, incr); \ + } else { \ + p = PL_ArenaGrow(pool, p, size, incr); \ + } \ + PL_ArenaCountGrowth(pool, size, incr); \ + PR_END_MACRO + +#define PL_ARENA_MARK(pool) ((void *) (pool)->current->avail) +#define PR_UPTRDIFF(p,q) ((PRUword)(p) - (PRUword)(q)) + +#ifdef DEBUG +#define PL_FREE_PATTERN 0xDA +#define PL_CLEAR_UNUSED(a) (PR_ASSERT((a)->avail <= (a)->limit), \ + memset((void*)(a)->avail, PL_FREE_PATTERN, \ + (a)->limit - (a)->avail)) +#define PL_CLEAR_ARENA(a) memset((void*)(a), PL_FREE_PATTERN, \ + (a)->limit - (PRUword)(a)) +#else +#define PL_CLEAR_UNUSED(a) +#define PL_CLEAR_ARENA(a) +#endif + +#if ARENA_MARK_ENABLE + +#define PL_ARENA_RELEASE(pool, mark) \ + PR_BEGIN_MACRO \ + char *_m = (char *)(mark); \ + PLArena *_a = (pool)->current; \ + if (PR_UPTRDIFF(_m, _a->base) <= PR_UPTRDIFF(_a->avail, _a->base)) { \ + _a->avail = (PRUword)PL_ARENA_ALIGN(pool, _m); \ + PL_CLEAR_UNUSED(_a); \ + PL_ArenaCountRetract(pool, _m); \ + } else { \ + PL_ArenaRelease(pool, _m); \ + } \ + PL_ArenaCountRelease(pool, _m); \ + PR_END_MACRO + +#else /* !ARENA_MARK_ENABLE */ + +#define PL_ARENA_RELEASE(pool, mark) + +#endif /* ARENA_MARK_ENABLE */ + +#ifdef PL_ARENAMETER +#define PL_COUNT_ARENA(pool,op) ((pool)->stats.narenas op) +#else +#define PL_COUNT_ARENA(pool,op) +#endif + +#define PL_ARENA_DESTROY(pool, a, pnext) \ + PR_BEGIN_MACRO \ + PL_COUNT_ARENA(pool,--); \ + if ((pool)->current == (a)) (pool)->current = &(pool)->first; \ + *(pnext) = (a)->next; \ + PL_CLEAR_ARENA(a); \ + free(a); \ + (a) = 0; \ + PR_END_MACRO + +#ifdef PL_ARENAMETER + +#include + +PR_EXTERN(void) PL_ArenaCountAllocation(PLArenaPool *pool, PRUint32 nb); + +PR_EXTERN(void) PL_ArenaCountInplaceGrowth( + PLArenaPool *pool, PRUint32 size, PRUint32 incr); + +PR_EXTERN(void) PL_ArenaCountGrowth( + PLArenaPool *pool, PRUint32 size, PRUint32 incr); + +PR_EXTERN(void) PL_ArenaCountRelease(PLArenaPool *pool, char *mark); + +PR_EXTERN(void) PL_ArenaCountRetract(PLArenaPool *pool, char *mark); + +PR_EXTERN(void) PL_DumpArenaStats(FILE *fp); + +#else /* !PL_ARENAMETER */ + +#define PL_ArenaCountAllocation(ap, nb) /* nothing */ +#define PL_ArenaCountInplaceGrowth(ap, size, incr) /* nothing */ +#define PL_ArenaCountGrowth(ap, size, incr) /* nothing */ +#define PL_ArenaCountRelease(ap, mark) /* nothing */ +#define PL_ArenaCountRetract(ap, mark) /* nothing */ + +#endif /* !PL_ARENAMETER */ + +PR_END_EXTERN_C + +#endif /* plarena_h___ */ diff --git a/libsecurity_asn1/lib/plarenas.h b/libsecurity_asn1/lib/plarenas.h new file mode 100644 index 00000000..9101a8f1 --- /dev/null +++ b/libsecurity_asn1/lib/plarenas.h @@ -0,0 +1,117 @@ +/* -*- 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 requiored 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. + */ + +#if defined(PLARENAS_H) +#else /* defined(PLARENAS_H) */ +#define PLARENAS_H + +#include + +/* global enable/disable of mark/release mechanism */ +#define ARENA_MARK_ENABLE 0 + +PR_BEGIN_EXTERN_C + +typedef struct PLArenaPool PLArenaPool; + +/* +** Allocate an arena pool as specified by the parameters. +** +** This is equivelant to allocating the space yourself and then +** calling PL_InitArenaPool(). +** +** This function may fail (and return a NULL) for a variety of +** reasons. The reason for a particular failure can be discovered +** by calling PR_GetError(). +*/ +#if 0 /* Not implemented */ +PR_EXTERN(PLArenaPool*) PL_AllocArenaPool( + const char *name, PRUint32 size, PRUint32 align); +#endif + +/* +** Destroy an arena pool previously allocated by PL_AllocArenaPool(). +** +** This function may fail if the arena is not empty and the caller +** wishes to check for empty upon descruction. +*/ +#if 0 /* Not implemented */ +PR_EXTERN(PRStatus) PL_DestroyArenaPool(PLArenaPool *pool, PRBool checkEmpty); +#endif + + +/* +** Initialize an arena pool with the given name for debugging and metering, +** with a minimum size per arena of size bytes. +**/ +PR_EXTERN(void) PL_InitArenaPool( + PLArenaPool *pool, const char *name, PRUint32 size, PRUint32 align); + +/* +** Finish using arenas, freeing all memory associated with them. +**/ +PR_EXTERN(void) PL_ArenaFinish(void); + +/* +** Free the arenas in pool. The user may continue to allocate from pool +** after calling this function. There is no need to call PL_InitArenaPool() +** again unless PL_FinishArenaPool(pool) has been called. +**/ +PR_EXTERN(void) PL_FreeArenaPool(PLArenaPool *pool); + +/* +** Free the arenas in pool and finish using it altogether. +**/ +PR_EXTERN(void) PL_FinishArenaPool(PLArenaPool *pool); + +/* +** Compact all of the arenas in a pool so that no space is wasted. +**/ +PR_EXTERN(void) PL_CompactArenaPool(PLArenaPool *pool); + +/* +** Friend functions used by the PL_ARENA_*() macros. +**/ +PR_EXTERN(void *) PL_ArenaAllocate(PLArenaPool *pool, PRUint32 nb); + +PR_EXTERN(void *) PL_ArenaGrow( + PLArenaPool *pool, void *p, PRUint32 size, PRUint32 incr); + +PR_EXTERN(void) PL_ArenaRelease(PLArenaPool *pool, char *mark); + +PR_END_EXTERN_C + +#endif /* defined(PLARENAS_H) */ + +/* plarenas */ diff --git a/libsecurity_asn1/lib/plstr.h b/libsecurity_asn1/lib/plstr.h new file mode 100644 index 00000000..928b25bc --- /dev/null +++ b/libsecurity_asn1/lib/plstr.h @@ -0,0 +1,467 @@ +/* -*- 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): + * Roland Mainz + * + * 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 _plstr_h +#define _plstr_h + +/* + * plstr.h + * + * This header file exports the API to the NSPR portable library or string- + * handling functions. + * + * This API was not designed as an "optimal" or "ideal" string library; it + * was based on the good ol' unix string.3 functions, and was written to + * + * 1) replace the libc functions, for cross-platform consistancy, + * 2) complete the API on platforms lacking common functions (e.g., + * strcase*), and + * 3) to implement some obvious "closure" functions that I've seen + * people hacking around in our code. + * + * Point number three largely means that most functions have an "strn" + * limited-length version, and all comparison routines have a non-case- + * sensitive version available. + */ + +#include + +PR_BEGIN_EXTERN_C +/* + * PL_strlen + * + * Returns the length of the provided string, not including the trailing '\0'. + */ + +PR_EXTERN(PRUint32) +PL_strlen(const char *str); + +/* + * PL_strnlen + * + * Returns the length of the provided string, not including the trailing '\0', + * up to the indicated maximum. The string will not be examined beyond the + * maximum; if no terminating '\0' is found, the maximum will be returned. + */ + +PR_EXTERN(PRUint32) +PL_strnlen(const char *str, PRUint32 max); + +/* + * PL_strcpy + * + * Copies the source string, up to and including the trailing '\0', into the + * destination buffer. It does not (can not) verify that the destination + * buffer is large enough. It returns the "dest" argument. + */ + +PR_EXTERN(char *) +PL_strcpy(char *dest, const char *src); + +/* + * PL_strncpy + * + * Copies the source string into the destination buffer, up to and including + * the trailing '\0' or up to and including the max'th character, whichever + * comes first. It does not (can not) verify that the destination buffer is + * large enough. If the source string is longer than the maximum length, + * the result will *not* be null-terminated (JLRU). + */ + +PR_EXTERN(char *) +PL_strncpy(char *dest, const char *src, PRUint32 max); + +/* + * PL_strncpyz + * + * Copies the source string into the destination buffer, up to and including + * the trailing '\0' or up but not including the max'th character, whichever + * comes first. It does not (can not) verify that the destination buffer is + * large enough. The destination string is always terminated with a '\0', + * unlike the traditional libc implementation. It returns the "dest" argument. + * + * NOTE: If you call this with a source "abcdefg" and a max of 5, the + * destination will end up with "abcd\0" (i.e., it's strlen length will be 4)! + * + * This means you can do this: + * + * char buffer[ SOME_SIZE ]; + * PL_strncpyz(buffer, src, sizeof(buffer)); + * + * and the result will be properly terminated. + */ + +PR_EXTERN(char *) +PL_strncpyz(char *dest, const char *src, PRUint32 max); + +/* + * PL_strdup + * + * Returns a pointer to a malloc'd extent of memory containing a duplicate + * of the argument string. The size of the allocated extent is one greater + * than the length of the argument string, because of the terminator. A + * null argument, like a zero-length argument, will result in a pointer to + * a one-byte extent containing the null value. This routine returns null + * upon malloc failure. + */ + +PR_EXTERN(char *) +PL_strdup(const char *s); + +/* + * PL_strfree + * + * Free memory allocated by PL_strdup + */ + +PR_EXTERN(void) +PL_strfree(char *s); + +/* + * PL_strndup + * + * Returns a pointer to a malloc'd extent of memory containing a duplicate + * of the argument string, up to the maximum specified. If the argument + * string has a length greater than the value of the specified maximum, the + * return value will be a pointer to an extent of memory of length one + * greater than the maximum specified. A null string, a zero-length string, + * or a zero maximum will all result in a pointer to a one-byte extent + * containing the null value. This routine returns null upon malloc failure. + */ + +PR_EXTERN(char *) +PL_strndup(const char *s, PRUint32 max); + +/* + * PL_strcat + * + * Appends a copy of the string pointed to by the second argument to the + * end of the string pointed to by the first. The destination buffer is + * not (can not be) checked for sufficient size. A null destination + * argument returns null; otherwise, the first argument is returned. + */ + +PR_EXTERN(char *) +PL_strcat(char *dst, const char *src); + +/* + * PL_strncat + * + * Appends a copy of the string pointed to by the second argument, up to + * the maximum size specified, to the end of the string pointed to by the + * first. The destination buffer is not (can not be) checked for sufficient + * size. A null destination argument returns null; otherwise, the first + * argument is returned. If the maximum size limits the copy, then the + * result will *not* be null-terminated (JLRU). A null destination + * returns null; otherwise, the destination argument is returned. + */ + +PR_EXTERN(char *) +PL_strncat(char *dst, const char *src, PRUint32 max); + +/* + * PL_strcatn + * + * Appends a copy of the string pointed to by the third argument, to the + * end of the string pointed to by the first. The second argument specifies + * the maximum size of the destination buffer, including the null termination. + * If the existing string in dst is longer than the max, no action is taken. + * The resulting string will be null-terminated. A null destination returns + * null; otherwise, the destination argument is returned. + */ + +PR_EXTERN(char *) +PL_strcatn(char *dst, PRUint32 max, const char *src); + +/* + * PL_strcmp + * + * Returns an integer, the sign of which -- positive, zero, or negative -- + * reflects the lexical sorting order of the two strings indicated. The + * result is positive if the first string comes after the second. The + * NSPR implementation is not i18n. + */ + +PR_EXTERN(PRIntn) +PL_strcmp(const char *a, const char *b); + +/* + * PL_strncmp + * + * Returns an integer, the sign of which -- positive, zero, or negative -- + * reflects the lexical sorting order of the two strings indicated, up to + * the maximum specified. The result is positive if the first string comes + * after the second. The NSPR implementation is not i18n. If the maximum + * is zero, only the existance or non-existance (pointer is null) of the + * strings is compared. + */ + +PR_EXTERN(PRIntn) +PL_strncmp(const char *a, const char *b, PRUint32 max); + +/* + * PL_strcasecmp + * + * Returns an integer, the sign of which -- positive, zero or negative -- + * reflects the case-insensitive lexical sorting order of the two strings + * indicated. The result is positive if the first string comes after the + * second. The NSPR implementation is not i18n. + */ + +PR_EXTERN(PRIntn) +PL_strcasecmp(const char *a, const char *b); + +/* + * PL_strncasecmp + * + * Returns an integer, the sign of which -- positive, zero or negative -- + * reflects the case-insensitive lexical sorting order of the first n characters + * of the two strings indicated. The result is positive if the first string comes + * after the second. The NSPR implementation is not i18n. + */ + +PR_EXTERN(PRIntn) +PL_strncasecmp(const char *a, const char *b, PRUint32 max); + +/* + * PL_strchr + * + * Returns a pointer to the first instance of the specified character in the + * provided string. It returns null if the character is not found, or if the + * provided string is null. The character may be the null character. + */ + +PR_EXTERN(char *) +PL_strchr(const char *s, char c); + +/* + * PL_strrchr + * + * Returns a pointer to the last instance of the specified character in the + * provided string. It returns null if the character is not found, or if the + * provided string is null. The character may be the null character. + */ + +PR_EXTERN(char *) +PL_strrchr(const char *s, char c); + +/* + * PL_strnchr + * + * Returns a pointer to the first instance of the specified character within the + * first n characters of the provided string. It returns null if the character + * is not found, or if the provided string is null. The character may be the + * null character. + */ + +PR_EXTERN(char *) +PL_strnchr(const char *s, char c, PRUint32 n); + +/* + * PL_strnrchr + * + * Returns a pointer to the last instance of the specified character within the + * first n characters of the provided string. It returns null if the character is + * not found, or if the provided string is null. The character may be the null + * character. + */ + +PR_EXTERN(char *) +PL_strnrchr(const char *s, char c, PRUint32 n); + +/* + * NOTE: Looking for strcasechr, strcaserchr, strncasechr, or strncaserchr? + * Use strpbrk, strprbrk, strnpbrk or strnprbrk. + */ + +/* + * PL_strpbrk + * + * Returns a pointer to the first instance in the first string of any character + * (not including the terminating null character) of the second string. It returns + * null if either string is null. + */ + +PR_EXTERN(char *) +PL_strpbrk(const char *s, const char *list); + +/* + * PL_strprbrk + * + * Returns a pointer to the last instance in the first string of any character + * (not including the terminating null character) of the second string. It returns + * null if either string is null. + */ + +PR_EXTERN(char *) +PL_strprbrk(const char *s, const char *list); + +/* + * PL_strnpbrk + * + * Returns a pointer to the first instance (within the first n characters) of any + * character (not including the terminating null character) of the second string. + * It returns null if either string is null. + */ + +PR_EXTERN(char *) +PL_strnpbrk(const char *s, const char *list, PRUint32 n); + +/* + * PL_strnprbrk + * + * Returns a pointer to the last instance (within the first n characters) of any + * character (not including the terminating null character) of the second string. + * It returns null if either string is null. + */ + +PR_EXTERN(char *) +PL_strnprbrk(const char *s, const char *list, PRUint32 n); + +/* + * PL_strstr + * + * Returns a pointer to the first instance of the little string within the + * big one. It returns null if either string is null. + */ + +PR_EXTERN(char *) +PL_strstr(const char *big, const char *little); + +/* + * PL_strrstr + * + * Returns a pointer to the last instance of the little string within the big one. + * It returns null if either string is null. + */ + +PR_EXTERN(char *) +PL_strrstr(const char *big, const char *little); + +/* + * PL_strnstr + * + * Returns a pointer to the first instance of the little string within the first + * n characters of the big one. It returns null if either string is null. It + * returns null if the length of the little string is greater than n. + */ + +PR_EXTERN(char *) +PL_strnstr(const char *big, const char *little, PRUint32 n); + +/* + * PL_strnrstr + * + * Returns a pointer to the last instance of the little string within the first + * n characters of the big one. It returns null if either string is null. It + * returns null if the length of the little string is greater than n. + */ + +PR_EXTERN(char *) +PL_strnrstr(const char *big, const char *little, PRUint32 max); + +/* + * PL_strcasestr + * + * Returns a pointer to the first instance of the little string within the big one, + * ignoring case. It returns null if either string is null. + */ + +PR_EXTERN(char *) +PL_strcasestr(const char *big, const char *little); + +/* + * PL_strcaserstr + * + * Returns a pointer to the last instance of the little string within the big one, + * ignoring case. It returns null if either string is null. + */ + +PR_EXTERN(char *) +PL_strcaserstr(const char *big, const char *little); + +/* + * PL_strncasestr + * + * Returns a pointer to the first instance of the listtle string within the first + * n characters of the big one, ignoring case. It returns null if either string is + * null. It returns null if the length of the little string is greater than n. + */ + +PR_EXTERN(char *) +PL_strncasestr(const char *big, const char *little, PRUint32 max); + +/* + * PL_strncaserstr + * + * Returns a pointer to the last instance of the little string within the first + * n characters of the big one, ignoring case. It returns null if either string is + * null. It returns null if the length of the little string is greater than n. + */ + +PR_EXTERN(char *) +PL_strncaserstr(const char *big, const char *little, PRUint32 max); + +/* + * PL_strtok_r + * + * Splits the string s1 into tokens, separated by one or more characters + * from the separator string s2. The argument lasts points to a + * user-supplied char * pointer in which PL_strtok_r stores information + * for it to continue scanning the same string. + * + * In the first call to PL_strtok_r, s1 points to a string and the value + * of *lasts is ignored. PL_strtok_r returns a pointer to the first + * token, writes '\0' into the character following the first token, and + * updates *lasts. + * + * In subsequent calls, s1 is null and lasts must stay unchanged from the + * previous call. The separator string s2 may be different from call to + * call. PL_strtok_r returns a pointer to the next token in s1. When no + * token remains in s1, PL_strtok_r returns null. + */ + +PR_EXTERN(char *) +PL_strtok_r(char *s1, const char *s2, char **lasts); + +/* + * Things not (yet?) included: strspn/strcspn, strsep. + * memchr, memcmp, memcpy, memccpy, index, rindex, bcmp, bcopy, bzero. + * Any and all i18n/l10n stuff. + */ + +PR_END_EXTERN_C + +#endif /* _plstr_h */ diff --git a/libsecurity_asn1/lib/prbit.h b/libsecurity_asn1/lib/prbit.h new file mode 100644 index 00000000..b1600f07 --- /dev/null +++ b/libsecurity_asn1/lib/prbit.h @@ -0,0 +1,108 @@ +/* -*- 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 prbit_h___ +#define prbit_h___ + +#include "prtypes.h" +PR_BEGIN_EXTERN_C + +/* +** A prbitmap_t is a long integer that can be used for bitmaps +*/ +typedef unsigned long prbitmap_t; + +#define PR_TEST_BIT(_map,_bit) \ + ((_map)[(_bit)>>PR_BITS_PER_LONG_LOG2] & (1L << ((_bit) & (PR_BITS_PER_LONG-1)))) +#define PR_SET_BIT(_map,_bit) \ + ((_map)[(_bit)>>PR_BITS_PER_LONG_LOG2] |= (1L << ((_bit) & (PR_BITS_PER_LONG-1)))) +#define PR_CLEAR_BIT(_map,_bit) \ + ((_map)[(_bit)>>PR_BITS_PER_LONG_LOG2] &= ~(1L << ((_bit) & (PR_BITS_PER_LONG-1)))) + +/* +** Compute the log of the least power of 2 greater than or equal to n +*/ +NSPR_API(PRIntn) PR_CeilingLog2(PRUint32 i); + +/* +** Compute the log of the greatest power of 2 less than or equal to n +*/ +NSPR_API(PRIntn) PR_FloorLog2(PRUint32 i); + +/* +** Macro version of PR_CeilingLog2: Compute the log of the least power of +** 2 greater than or equal to _n. The result is returned in _log2. +*/ +#define PR_CEILING_LOG2(_log2,_n) \ + PR_BEGIN_MACRO \ + PRUint32 j_ = (PRUint32)(_n); \ + (_log2) = 0; \ + if ((j_) & ((j_)-1)) \ + (_log2) += 1; \ + if ((j_) >> 16) \ + (_log2) += 16, (j_) >>= 16; \ + if ((j_) >> 8) \ + (_log2) += 8, (j_) >>= 8; \ + if ((j_) >> 4) \ + (_log2) += 4, (j_) >>= 4; \ + if ((j_) >> 2) \ + (_log2) += 2, (j_) >>= 2; \ + if ((j_) >> 1) \ + (_log2) += 1; \ + PR_END_MACRO + +/* +** Macro version of PR_FloorLog2: Compute the log of the greatest power of +** 2 less than or equal to _n. The result is returned in _log2. +** +** This is equivalent to finding the highest set bit in the word. +*/ +#define PR_FLOOR_LOG2(_log2,_n) \ + PR_BEGIN_MACRO \ + PRUint32 j_ = (PRUint32)(_n); \ + (_log2) = 0; \ + if ((j_) >> 16) \ + (_log2) += 16, (j_) >>= 16; \ + if ((j_) >> 8) \ + (_log2) += 8, (j_) >>= 8; \ + if ((j_) >> 4) \ + (_log2) += 4, (j_) >>= 4; \ + if ((j_) >> 2) \ + (_log2) += 2, (j_) >>= 2; \ + if ((j_) >> 1) \ + (_log2) += 1; \ + PR_END_MACRO + +PR_END_EXTERN_C +#endif /* prbit_h___ */ diff --git a/libsecurity_asn1/lib/prcpucfg.h b/libsecurity_asn1/lib/prcpucfg.h new file mode 100644 index 00000000..799dc52b --- /dev/null +++ b/libsecurity_asn1/lib/prcpucfg.h @@ -0,0 +1,192 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * 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 the Initial Developer are Copyright (C) 1998-2000 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef nspr_cpucfg___ +#define nspr_cpucfg___ + +#ifndef XP_MAC +#define XP_MAC +#endif + +#undef IS_LITTLE_ENDIAN +#define IS_BIG_ENDIAN 1 + +#define HAVE_LONG_LONG + +#define PR_AF_INET6 30 /* same as AF_INET6 */ +#ifdef __x86_64__ +#define IS_64 +#endif + +#ifndef HAVE_LONG_LONG +#define HAVE_LONG_LONG +#endif +#undef HAVE_ALIGNED_DOUBLES +#define HAVE_ALIGNED_LONGLONGS 1 + +#ifdef IS_64 + +#define PR_BYTES_PER_BYTE 1 +#define PR_BYTES_PER_SHORT 2 +#define PR_BYTES_PER_INT 4 +#define PR_BYTES_PER_INT64 8 +#define PR_BYTES_PER_LONG 8 +#define PR_BYTES_PER_FLOAT 4 +#define PR_BYTES_PER_DOUBLE 8 +#define PR_BYTES_PER_WORD 8 +#define PR_BYTES_PER_DWORD 8 + +#define PR_BITS_PER_BYTE 8 +#define PR_BITS_PER_SHORT 16 +#define PR_BITS_PER_INT 32 +#define PR_BITS_PER_INT64 64 +#define PR_BITS_PER_LONG 64 +#define PR_BITS_PER_FLOAT 32 +#define PR_BITS_PER_DOUBLE 64 +#define PR_BITS_PER_WORD 64 +#define PR_BITS_PER_DWORD 64 + +#define PR_BITS_PER_BYTE_LOG2 3 +#define PR_BITS_PER_SHORT_LOG2 4 +#define PR_BITS_PER_INT_LOG2 5 +#define PR_BITS_PER_INT64_LOG2 6 +#define PR_BITS_PER_LONG_LOG2 6 +#define PR_BITS_PER_FLOAT_LOG2 5 +#define PR_BITS_PER_DOUBLE_LOG2 6 +#define PR_BITS_PER_WORD_LOG2 6 +#define PR_BITS_PER_DWORD_LOG2 6 + +#define PR_ALIGN_OF_SHORT 2 +#define PR_ALIGN_OF_INT 4 +#define PR_ALIGN_OF_LONG 8 +#define PR_ALIGN_OF_INT64 8 +#define PR_ALIGN_OF_FLOAT 4 +#define PR_ALIGN_OF_DOUBLE 8 +#define PR_ALIGN_OF_POINTER 8 +#define PR_ALIGN_OF_WORD 8 +#define PR_ALIGN_OF_DWORD 8 + +#else /* IS_64 */ + +#define PR_BYTES_PER_BYTE 1 +#define PR_BYTES_PER_SHORT 2 +#define PR_BYTES_PER_INT 4 +#define PR_BYTES_PER_INT64 8 +#define PR_BYTES_PER_LONG 4 +#define PR_BYTES_PER_FLOAT 4 +#define PR_BYTES_PER_DOUBLE 8 +#define PR_BYTES_PER_WORD 4 +#define PR_BYTES_PER_DWORD 8 +#define PR_BYTES_PER_WORD_LOG2 2 +#define PR_BYTES_PER_DWORD_LOG2 3 + +#define PR_BITS_PER_BYTE 8 +#define PR_BITS_PER_SHORT 16 +#define PR_BITS_PER_INT 32 +#define PR_BITS_PER_INT64 64 +#define PR_BITS_PER_LONG 32 +#define PR_BITS_PER_FLOAT 32 +#define PR_BITS_PER_DOUBLE 64 +#define PR_BITS_PER_WORD 32 +#define PR_BITS_PER_DWORD 64 + +#define PR_BITS_PER_BYTE_LOG2 3 +#define PR_BITS_PER_SHORT_LOG2 4 +#define PR_BITS_PER_INT_LOG2 5 +#define PR_BITS_PER_INT64_LOG2 6 +#define PR_BITS_PER_LONG_LOG2 5 +#define PR_BITS_PER_FLOAT_LOG2 5 +#define PR_BITS_PER_DOUBLE_LOG2 6 +#define PR_BITS_PER_WORD_LOG2 5 + +#define PR_ALIGN_OF_SHORT 2 +#define PR_ALIGN_OF_INT 4 +#define PR_ALIGN_OF_LONG 4 +#define PR_ALIGN_OF_INT64 4 +#define PR_ALIGN_OF_FLOAT 4 +#define PR_ALIGN_OF_DOUBLE 4 +#define PR_ALIGN_OF_POINTER 4 +#define PR_ALIGN_OF_WORD 4 + +#endif /* IS_64 */ + +#ifndef NO_NSPR_10_SUPPORT + +#define BYTES_PER_BYTE PR_BYTES_PER_BYTE +#define BYTES_PER_SHORT PR_BYTES_PER_SHORT +#define BYTES_PER_INT PR_BYTES_PER_INT +#define BYTES_PER_INT64 PR_BYTES_PER_INT64 +#define BYTES_PER_LONG PR_BYTES_PER_LONG +#define BYTES_PER_FLOAT PR_BYTES_PER_FLOAT +#define BYTES_PER_DOUBLE PR_BYTES_PER_DOUBLE +#define BYTES_PER_WORD PR_BYTES_PER_WORD +#define BYTES_PER_DWORD PR_BYTES_PER_DWORD + +#define BITS_PER_BYTE PR_BITS_PER_BYTE +#define BITS_PER_SHORT PR_BITS_PER_SHORT +#define BITS_PER_INT PR_BITS_PER_INT +#define BITS_PER_INT64 PR_BITS_PER_INT64 +#define BITS_PER_LONG PR_BITS_PER_LONG +#define BITS_PER_FLOAT PR_BITS_PER_FLOAT +#define BITS_PER_DOUBLE PR_BITS_PER_DOUBLE +#define BITS_PER_WORD PR_BITS_PER_WORD + +#define BITS_PER_BYTE_LOG2 PR_BITS_PER_BYTE_LOG2 +#define BITS_PER_SHORT_LOG2 PR_BITS_PER_SHORT_LOG2 +#define BITS_PER_INT_LOG2 PR_BITS_PER_INT_LOG2 +#define BITS_PER_INT64_LOG2 PR_BITS_PER_INT64_LOG2 +#define BITS_PER_LONG_LOG2 PR_BITS_PER_LONG_LOG2 +#define BITS_PER_FLOAT_LOG2 PR_BITS_PER_FLOAT_LOG2 +#define BITS_PER_DOUBLE_LOG2 PR_BITS_PER_DOUBLE_LOG2 +#define BITS_PER_WORD_LOG2 PR_BITS_PER_WORD_LOG2 + +#define ALIGN_OF_SHORT PR_ALIGN_OF_SHORT +#define ALIGN_OF_INT PR_ALIGN_OF_INT +#define ALIGN_OF_LONG PR_ALIGN_OF_LONG +#define ALIGN_OF_INT64 PR_ALIGN_OF_INT64 +#define ALIGN_OF_FLOAT PR_ALIGN_OF_FLOAT +#define ALIGN_OF_DOUBLE PR_ALIGN_OF_DOUBLE +#define ALIGN_OF_POINTER PR_ALIGN_OF_POINTER +#define ALIGN_OF_WORD PR_ALIGN_OF_WORD + +#define BYTES_PER_WORD_LOG2 PR_BYTES_PER_WORD_LOG2 +#define BYTES_PER_DWORD_LOG2 PR_BYTES_PER_DWORD_LOG2 +#define WORDS_PER_DWORD_LOG2 PR_WORDS_PER_DWORD_LOG2 + +#endif /* NO_NSPR_10_SUPPORT */ + +#endif /* nspr_cpucfg___ */ diff --git a/libsecurity_asn1/lib/prcvar.h b/libsecurity_asn1/lib/prcvar.h new file mode 100644 index 00000000..9657415f --- /dev/null +++ b/libsecurity_asn1/lib/prcvar.h @@ -0,0 +1,123 @@ +/* -*- 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 prcvar_h___ +#define prcvar_h___ + +#include +#include + +PR_BEGIN_EXTERN_C + +typedef struct PRCondVar PRCondVar; + +/* +** Create a new condition variable. +** +** "lock" is the lock used to protect the condition variable. +** +** Condition variables are synchronization objects that threads can use +** to wait for some condition to occur. +** +** This may fail if memory is tight or if some operating system resource +** is low. In such cases, a NULL will be returned. +*/ +NSPR_API(PRCondVar*) PR_NewCondVar(PRLock *lock); + +/* +** Destroy a condition variable. There must be no thread +** waiting on the condvar. The caller is responsible for guaranteeing +** that the condvar is no longer in use. +** +*/ +NSPR_API(void) PR_DestroyCondVar(PRCondVar *cvar); + +/* +** The thread that waits on a condition is blocked in a "waiting on +** condition" state until another thread notifies the condition or a +** caller specified amount of time expires. The lock associated with +** the condition variable will be released, which must have be held +** prior to the call to wait. +** +** Logically a notified thread is moved from the "waiting on condition" +** state and made "ready." When scheduled, it will attempt to reacquire +** the lock that it held when wait was called. +** +** The timeout has two well known values, PR_INTERVAL_NO_TIMEOUT and +** PR_INTERVAL_NO_WAIT. The former value requires that a condition be +** notified (or the thread interrupted) before it will resume from the +** wait. If the timeout has a value of PR_INTERVAL_NO_WAIT, the effect +** is to release the lock, possibly causing a rescheduling within the +** runtime, then immediately attempting to reacquire the lock and resume. +** +** Any other value for timeout will cause the thread to be rescheduled +** either due to explicit notification or an expired interval. The latter +** must be determined by treating time as one part of the monitored data +** being protected by the lock and tested explicitly for an expired +** interval. +** +** Returns PR_FAILURE if the caller has not locked the lock associated +** with the condition variable or the thread was interrupted (PR_Interrupt()). +** The particular reason can be extracted with PR_GetError(). +*/ +NSPR_API(PRStatus) PR_WaitCondVar(PRCondVar *cvar, PRIntervalTime timeout); + +/* +** Notify ONE thread that is currently waiting on 'cvar'. Which thread is +** dependent on the implementation of the runtime. Common sense would dictate +** that all threads waiting on a single condition have identical semantics, +** therefore which one gets notified is not significant. +** +** The calling thead must hold the lock that protects the condition, as +** well as the invariants that are tightly bound to the condition, when +** notify is called. +** +** Returns PR_FAILURE if the caller has not locked the lock associated +** with the condition variable. +*/ +NSPR_API(PRStatus) PR_NotifyCondVar(PRCondVar *cvar); + +/* +** Notify all of the threads waiting on the condition variable. The order +** that the threads are notified is indeterminant. The lock that protects +** the condition must be held. +** +** Returns PR_FAILURE if the caller has not locked the lock associated +** with the condition variable. +*/ +NSPR_API(PRStatus) PR_NotifyAllCondVar(PRCondVar *cvar); + +PR_END_EXTERN_C + +#endif /* prcvar_h___ */ diff --git a/libsecurity_asn1/lib/prenv.h b/libsecurity_asn1/lib/prenv.h new file mode 100644 index 00000000..acf79522 --- /dev/null +++ b/libsecurity_asn1/lib/prenv.h @@ -0,0 +1,154 @@ +/* -*- 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 requiored 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 prenv_h___ +#define prenv_h___ + +#include + +/*******************************************************************************/ +/*******************************************************************************/ +/****************** THESE FUNCTIONS MAY NOT BE THREAD SAFE *********************/ +/*******************************************************************************/ +/*******************************************************************************/ + +PR_BEGIN_EXTERN_C + +/* +** PR_GetEnv() -- Retrieve value of environment variable +** +** Description: +** PR_GetEnv() is modeled on Unix getenv(). +** +** +** Inputs: +** var -- The name of the environment variable +** +** Returns: +** The value of the environment variable 'var' or NULL if +** the variable is undefined. +** +** Restrictions: +** You'd think that a POSIX getenv(), putenv() would be +** consistently implemented everywhere. Surprise! It is not. On +** some platforms, a putenv() where the argument is of +** the form "name" causes the named environment variable to +** be un-set; that is: a subsequent getenv() returns NULL. On +** other platforms, the putenv() fails, on others, it is a +** no-op. Similarly, a putenv() where the argument is of the +** form "name=" causes the named environment variable to be +** un-set; a subsequent call to getenv() returns NULL. On +** other platforms, a subsequent call to getenv() returns a +** pointer to a null-string (a byte of zero). +** +** PR_GetEnv(), PR_SetEnv() provide a consistent behavior +** across all supported platforms. There are, however, some +** restrictions and some practices you must use to achieve +** consistent results everywhere. +** +** When manipulating the environment there is no way to un-set +** an environment variable across all platforms. We suggest +** you interpret the return of a pointer to null-string to +** mean the same as a return of NULL from PR_GetEnv(). +** +** A call to PR_SetEnv() where the parameter is of the form +** "name" will return PR_FAILURE; the environment remains +** unchanged. A call to PR_SetEnv() where the parameter is +** of the form "name=" may un-set the envrionment variable on +** some platforms; on others it may set the value of the +** environment variable to the null-string. +** +** For example, to test for NULL return or return of the +** null-string from PR_GetEnv(), use the following code +** fragment: +** +** char *val = PR_GetEnv("foo"); +** if ((NULL == val) || ('\0' == *val)) { +** ... interpret this as un-set ... +** } +** +** The caller must ensure that the string passed +** to PR_SetEnv() is persistent. That is: The string should +** not be on the stack, where it can be overwritten +** on return from the function calling PR_SetEnv(). +** Similarly, the string passed to PR_SetEnv() must not be +** overwritten by other actions of the process. ... Some +** platforms use the string by reference rather than copying +** it into the environment space. ... You have been warned! +** +** Use of platform-native functions that manipulate the +** environment (getenv(), putenv(), +** SetEnvironmentVariable(), etc.) must not be used with +** NSPR's similar functions. The platform-native functions +** may not be thread safe and/or may operate on different +** conceptual environment space than that operated upon by +** NSPR's functions or other environment manipulating +** functions on the same platform. (!) +** +*/ +NSPR_API(char*) PR_GetEnv(const char *var); + +/* +** PR_SetEnv() -- set, unset or change an environment variable +** +** Description: +** PR_SetEnv() is modeled on the Unix putenv() function. +** +** Inputs: +** string -- pointer to a caller supplied +** constant, persistent string of the form name=value. Where +** name is the name of the environment variable to be set or +** changed; value is the value assigned to the variable. +** +** Returns: +** PRStatus. +** +** Restrictions: +** See the Restrictions documented in the description of +** PR_GetEnv() in this header file. +** +** +*/ +NSPR_API(PRStatus) PR_SetEnv(const char *string); + +/* +** DEPRECATED. Use PR_SetEnv() instead. +*/ +#ifdef XP_MAC +NSPR_API(PRIntn) PR_PutEnv(const char *string); +#endif + +PR_END_EXTERN_C + +#endif /* prenv_h___ */ diff --git a/libsecurity_asn1/lib/prerr.h b/libsecurity_asn1/lib/prerr.h new file mode 100644 index 00000000..5bb6c9e8 --- /dev/null +++ b/libsecurity_asn1/lib/prerr.h @@ -0,0 +1,275 @@ +/* -*- 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 prerr_h___ +#define prerr_h___ + +/* + * + * prerr.h + * This file is automatically generated; please do not edit it. + */ + +/* Memory allocation attempt failed */ +#define PR_OUT_OF_MEMORY_ERROR (-6000L) + +/* Invalid file descriptor */ +#define PR_BAD_DESCRIPTOR_ERROR (-5999L) + +/* The operation would have blocked */ +#define PR_WOULD_BLOCK_ERROR (-5998L) + +/* Invalid memory address argument */ +#define PR_ACCESS_FAULT_ERROR (-5997L) + +/* Invalid function for file type */ +#define PR_INVALID_METHOD_ERROR (-5996L) + +/* Invalid memory address argument */ +#define PR_ILLEGAL_ACCESS_ERROR (-5995L) + +/* Some unknown error has occurred */ +#define PR_UNKNOWN_ERROR (-5994L) + +/* Operation interrupted by another thread */ +#define PR_PENDING_INTERRUPT_ERROR (-5993L) + +/* function not implemented */ +#define PR_NOT_IMPLEMENTED_ERROR (-5992L) + +/* I/O function error */ +#define PR_IO_ERROR (-5991L) + +/* I/O operation timed out */ +#define PR_IO_TIMEOUT_ERROR (-5990L) + +/* I/O operation on busy file descriptor */ +#define PR_IO_PENDING_ERROR (-5989L) + +/* The directory could not be opened */ +#define PR_DIRECTORY_OPEN_ERROR (-5988L) + +/* Invalid function argument */ +#define PR_INVALID_ARGUMENT_ERROR (-5987L) + +/* Network address not available (in use?) */ +#define PR_ADDRESS_NOT_AVAILABLE_ERROR (-5986L) + +/* Network address type not supported */ +#define PR_ADDRESS_NOT_SUPPORTED_ERROR (-5985L) + +/* Already connected */ +#define PR_IS_CONNECTED_ERROR (-5984L) + +/* Network address is invalid */ +#define PR_BAD_ADDRESS_ERROR (-5983L) + +/* Local Network address is in use */ +#define PR_ADDRESS_IN_USE_ERROR (-5982L) + +/* Connection refused by peer */ +#define PR_CONNECT_REFUSED_ERROR (-5981L) + +/* Network address is presently unreachable */ +#define PR_NETWORK_UNREACHABLE_ERROR (-5980L) + +/* Connection attempt timed out */ +#define PR_CONNECT_TIMEOUT_ERROR (-5979L) + +/* Network file descriptor is not connected */ +#define PR_NOT_CONNECTED_ERROR (-5978L) + +/* Failure to load dynamic library */ +#define PR_LOAD_LIBRARY_ERROR (-5977L) + +/* Failure to unload dynamic library */ +#define PR_UNLOAD_LIBRARY_ERROR (-5976L) + +/* Symbol not found in any of the loaded dynamic libraries */ +#define PR_FIND_SYMBOL_ERROR (-5975L) + +/* Insufficient system resources */ +#define PR_INSUFFICIENT_RESOURCES_ERROR (-5974L) + +/* A directory lookup on a network address has failed */ +#define PR_DIRECTORY_LOOKUP_ERROR (-5973L) + +/* Attempt to access a TPD key that is out of range */ +#define PR_TPD_RANGE_ERROR (-5972L) + +/* Process open FD table is full */ +#define PR_PROC_DESC_TABLE_FULL_ERROR (-5971L) + +/* System open FD table is full */ +#define PR_SYS_DESC_TABLE_FULL_ERROR (-5970L) + +/* Network operation attempted on non-network file descriptor */ +#define PR_NOT_SOCKET_ERROR (-5969L) + +/* TCP-specific function attempted on a non-TCP file descriptor */ +#define PR_NOT_TCP_SOCKET_ERROR (-5968L) + +/* TCP file descriptor is already bound */ +#define PR_SOCKET_ADDRESS_IS_BOUND_ERROR (-5967L) + +/* Access Denied */ +#define PR_NO_ACCESS_RIGHTS_ERROR (-5966L) + +/* The requested operation is not supported by the platform */ +#define PR_OPERATION_NOT_SUPPORTED_ERROR (-5965L) + +/* The host operating system does not support the protocol requested */ +#define PR_PROTOCOL_NOT_SUPPORTED_ERROR (-5964L) + +/* Access to the remote file has been severed */ +#define PR_REMOTE_FILE_ERROR (-5963L) + +/* The value requested is too large to be stored in the data buffer provided */ +#define PR_BUFFER_OVERFLOW_ERROR (-5962L) + +/* TCP connection reset by peer */ +#define PR_CONNECT_RESET_ERROR (-5961L) + +/* Unused */ +#define PR_RANGE_ERROR (-5960L) + +/* The operation would have deadlocked */ +#define PR_DEADLOCK_ERROR (-5959L) + +/* The file is already locked */ +#define PR_FILE_IS_LOCKED_ERROR (-5958L) + +/* Write would result in file larger than the system allows */ +#define PR_FILE_TOO_BIG_ERROR (-5957L) + +/* The device for storing the file is full */ +#define PR_NO_DEVICE_SPACE_ERROR (-5956L) + +/* Unused */ +#define PR_PIPE_ERROR (-5955L) + +/* Unused */ +#define PR_NO_SEEK_DEVICE_ERROR (-5954L) + +/* Cannot perform a normal file operation on a directory */ +#define PR_IS_DIRECTORY_ERROR (-5953L) + +/* Symbolic link loop */ +#define PR_LOOP_ERROR (-5952L) + +/* File name is too long */ +#define PR_NAME_TOO_LONG_ERROR (-5951L) + +/* File not found */ +#define PR_FILE_NOT_FOUND_ERROR (-5950L) + +/* Cannot perform directory operation on a normal file */ +#define PR_NOT_DIRECTORY_ERROR (-5949L) + +/* Cannot write to a read-only file system */ +#define PR_READ_ONLY_FILESYSTEM_ERROR (-5948L) + +/* Cannot delete a directory that is not empty */ +#define PR_DIRECTORY_NOT_EMPTY_ERROR (-5947L) + +/* Cannot delete or rename a file object while the file system is busy */ +#define PR_FILESYSTEM_MOUNTED_ERROR (-5946L) + +/* Cannot rename a file to a file system on another device */ +#define PR_NOT_SAME_DEVICE_ERROR (-5945L) + +/* The directory object in the file system is corrupted */ +#define PR_DIRECTORY_CORRUPTED_ERROR (-5944L) + +/* Cannot create or rename a filename that already exists */ +#define PR_FILE_EXISTS_ERROR (-5943L) + +/* Directory is full. No additional filenames may be added */ +#define PR_MAX_DIRECTORY_ENTRIES_ERROR (-5942L) + +/* The required device was in an invalid state */ +#define PR_INVALID_DEVICE_STATE_ERROR (-5941L) + +/* The device is locked */ +#define PR_DEVICE_IS_LOCKED_ERROR (-5940L) + +/* No more entries in the directory */ +#define PR_NO_MORE_FILES_ERROR (-5939L) + +/* Encountered end of file */ +#define PR_END_OF_FILE_ERROR (-5938L) + +/* Seek error */ +#define PR_FILE_SEEK_ERROR (-5937L) + +/* The file is busy */ +#define PR_FILE_IS_BUSY_ERROR (-5936L) + +/* The I/O operation was aborted */ +#define PR_OPERATION_ABORTED_ERROR (-5935L) + +/* Operation is still in progress (probably a non-blocking connect) */ +#define PR_IN_PROGRESS_ERROR (-5934L) + +/* Operation has already been initiated (probably a non-blocking connect) */ +#define PR_ALREADY_INITIATED_ERROR (-5933L) + +/* The wait group is empty */ +#define PR_GROUP_EMPTY_ERROR (-5932L) + +/* Object state improper for request */ +#define PR_INVALID_STATE_ERROR (-5931L) + +/* Network is down */ +#define PR_NETWORK_DOWN_ERROR (-5930L) + +/* Socket shutdown */ +#define PR_SOCKET_SHUTDOWN_ERROR (-5929L) + +/* Connection aborted */ +#define PR_CONNECT_ABORTED_ERROR (-5928L) + +/* Host is unreachable */ +#define PR_HOST_UNREACHABLE_ERROR (-5927L) + +/* The library is not loaded */ +#define PR_LIBRARY_NOT_LOADED_ERROR (-5926L) + +/* Placeholder for the end of the list */ +#define PR_MAX_ERROR (-5925L) + +extern void nspr_InitializePRErrorTable(void); +#define ERROR_TABLE_BASE_nspr (-6000L) + +#endif /* prerr_h___ */ diff --git a/libsecurity_asn1/lib/prerror.h b/libsecurity_asn1/lib/prerror.h new file mode 100644 index 00000000..0db93fb0 --- /dev/null +++ b/libsecurity_asn1/lib/prerror.h @@ -0,0 +1,323 @@ +/* -*- 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 prerror_h___ +#define prerror_h___ + +#include + +PR_BEGIN_EXTERN_C + +typedef PRInt32 PRErrorCode; + +#define PR_NSPR_ERROR_BASE -6000 + +#include "prerr.h" + +/* +** Set error will preserve an error condition within a thread context. +** The values stored are the NSPR (platform independent) translation of +** the error. Also, if available, the platform specific oserror is stored. +** If there is no appropriate OS error number, a zero my be supplied. +*/ +NSPR_API(void) PR_SetError(PRErrorCode errorCode, PRInt32 oserr); + +/* +** The text value specified may be NULL. If it is not NULL and the text length +** is zero, the string is assumed to be a null terminated C string. Otherwise +** the text is assumed to be the length specified and possibly include NULL +** characters (e.g., a multi-national string). +** +** The text will be copied into to thread structure and remain there +** until the next call to PR_SetError. +*/ +NSPR_API(void) PR_SetErrorText( + PRIntn textLength, const char *text); + +/* +** Return the current threads last set error code. +*/ +NSPR_API(PRErrorCode) PR_GetError(void); + +/* +** Return the current threads last set os error code. This is used for +** machine specific code that desires the underlying os error. +*/ +NSPR_API(PRInt32) PR_GetOSError(void); + +/* +** Get the length of the error text. If a zero is returned, then there +** is no text. Otherwise, the value returned is sufficient to contain +** the error text currently available. +*/ +NSPR_API(PRInt32) PR_GetErrorTextLength(void); + +/* +** Copy the current threads current error text. Then actual number of bytes +** copied is returned as the result. If the result is zero, the 'text' area +** is unaffected. +*/ +NSPR_API(PRInt32) PR_GetErrorText(char *text); + + +/* +Copyright (C) 1987, 1988 Student Information Processing Board of the +Massachusetts Institute of Technology. + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, provided +that the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation, and that the names of M.I.T. and the M.I.T. S.I.P.B. not be +used in advertising or publicity pertaining to distribution of the software +without specific, written prior permission. M.I.T. and the M.I.T. S.I.P.B. +make no representations about the suitability of this software for any +purpose. It is provided "as is" without express or implied warranty. +*/ + + +/* + * NOTE: + * The interfaces for error-code-translation described in the rest of + * this file are preliminary in the 3.1 release of nspr and are subject + * to change in future releases. + */ + +/* +** Description: Localizable error code to string function. +** +** +** NSPR provides a mechanism for converting an error code to a +** descriptive string, in a caller-specified language. +** +** Error codes themselves are 32 bit (signed) integers. Typically, +** the high order 24 bits are an identifier of which error table the +** error code is from, and the low order 8 bits are a sequential error +** number within the table. NSPR supports error tables whose first +** error code is not a multiple of 256, such error code assignments +** should be avoided when possible. +** +** Error table 0 is defined to match the UNIX system call error table +** (sys_errlist); this allows errno values to be used directly in the +** library. Other error table numbers are typically formed by +** compacting together the first four characters of the error table +** name. The mapping between characters in the name and numeric +** values in the error code are defined in a system-independent +** fashion, so that two systems that can pass integral values between +** them can reliably pass error codes without loss of meaning; this +** should work even if the character sets used are not the +** same. (However, if this is to be done, error table 0 should be +** avoided, since the local system call error tables may differ.) +** +** Libraries defining error codes need only provide a table mapping +** error code numbers to names and default English descriptions, +** calling a routine to install the table, making it ``known'' to NSPR +** library. Once installed, a table may not be removed. Any error +** code the library generates can be converted to the corresponding +** error message. There is also a default format for error codes +** accidentally returned before making the table known, which is of +** the form "unknown code foo 32", where "foo" would be the name of +** the table. +** +** Normally, the error code conversion routine only supports the +** languages "i-default" and "en", returning the error-table-provided +** English description for both languages. The application may +** provide a localization plugin, allowing support for additional +** languages. +** +**/ + +/**********************************************************************/ +/************************* TYPES AND CONSTANTS ************************/ +/**********************************************************************/ + +/* + * PRLanguageCode -- + * + * NSPR represents a language code as a non-negative integer. + * Languages 0 is always "i-default" the language you get without + * explicit negotiation. Language 1 is always "en", English + * which has been explicitly negotiated. Additional language + * codes are defined by an application-provided localization plugin. + */ +typedef PRUint32 PRLanguageCode; +#define PR_LANGUAGE_I_DEFAULT 0 /* i-default, the default language */ +#define PR_LANGUAGE_EN 1 /* English, explicitly negotiated */ + +/* + * struct PRErrorMessage -- + * + * An error message in an error table. + */ +struct PRErrorMessage { + const char * name; /* Macro name for error */ + const char * en_text; /* Default English text */ +}; + +/* + * struct PRErrorTable -- + * + * An error table, provided by a library. + */ +struct PRErrorTable { + const struct PRErrorMessage * msgs; /* Array of error information */ + const char *name; /* Name of error table source */ + PRErrorCode base; /* Error code for first error in table */ + int n_msgs; /* Number of codes in table */ +}; + +/* + * struct PRErrorCallbackPrivate -- + * + * A private structure for the localization plugin + */ +struct PRErrorCallbackPrivate; + +/* + * struct PRErrorCallbackTablePrivate -- + * + * A data structure under which the localization plugin may store information, + * associated with an error table, that is private to itself. + */ +struct PRErrorCallbackTablePrivate; + +/* + * PRErrorCallbackLookupFn -- + * + * A function of PRErrorCallbackLookupFn type is a localization + * plugin callback which converts an error code into a description + * in the requested language. The callback is provided the + * appropriate error table, private data for the plugin and the table. + * The callback returns the appropriate UTF-8 encoded description, or NULL + * if no description can be found. + */ +typedef const char * +PRErrorCallbackLookupFn(PRErrorCode code, PRLanguageCode language, + const struct PRErrorTable *table, + struct PRErrorCallbackPrivate *cb_private, + struct PRErrorCallbackTablePrivate *table_private); + +/* + * PRErrorCallbackNewTableFn -- + * + * A function PRErrorCallbackNewTableFn type is a localization plugin + * callback which is called once with each error table registered + * with NSPR. The callback is provided with the error table and + * the plugin's private structure. The callback returns any table private + * data it wishes to associate with the error table. Does not need to be thread + * safe. + */ +typedef struct PRErrorCallbackTablePrivate * +PRErrorCallbackNewTableFn(const struct PRErrorTable *table, + struct PRErrorCallbackPrivate *cb_private); + +/**********************************************************************/ +/****************************** FUNCTIONS *****************************/ +/**********************************************************************/ + +/*********************************************************************** +** FUNCTION: PR_ErrorToString +** DESCRIPTION: +** Returns the UTF-8 message for an error code in +** the requested language. May return the message +** in the default language if a translation in the requested +** language is not available. The returned string is +** valid for the duration of the process. Never returns NULL. +** +***********************************************************************/ +NSPR_API(const char *) PR_ErrorToString(PRErrorCode code, + PRLanguageCode language); + + +/*********************************************************************** +** FUNCTION: PR_ErrorToName +** DESCRIPTION: +** Returns the macro name for an error code, or NULL +** if the error code is not known. The returned string is +** valid for the duration of the process. +** +** Does not work for error table 0, the system error codes. +** +***********************************************************************/ +NSPR_API(const char *) PR_ErrorToName(PRErrorCode code); + + +/*********************************************************************** +** FUNCTION: PR_ErrorLanguages +** DESCRIPTION: +** Returns the RFC 1766 language tags for the language +** codes PR_ErrorToString() supports. The returned array is valid +** for the duration of the process. Never returns NULL. The first +** item in the returned array is the language tag for PRLanguageCode 0, +** the second is for PRLanguageCode 1, and so on. The array is terminated +** with a null pointer. +** +***********************************************************************/ +NSPR_API(const char * const *) PR_ErrorLanguages(void); + + +/*********************************************************************** +** FUNCTION: PR_ErrorInstallTable +** DESCRIPTION: +** Registers an error table with NSPR. Must be done exactly once per +** table. Memory pointed to by `table' must remain valid for the life +** of the process. +** +** NOT THREAD SAFE! +** +***********************************************************************/ +NSPR_API(PRErrorCode) PR_ErrorInstallTable(const struct PRErrorTable *table); + + +/*********************************************************************** +** FUNCTION: PR_ErrorInstallCallback +** DESCRIPTION: +** Registers an error localization plugin with NSPR. May be called +** at most one time. `languages' contains the language codes supported +** by this plugin. Languages 0 and 1 must be "i-default" and "en" +** respectively. `lookup' and `newtable' contain pointers to +** the plugin callback functions. `cb_private' contains any information +** private to the plugin functions. +** +** NOT THREAD SAFE! +** +***********************************************************************/ +NSPR_API(void) PR_ErrorInstallCallback(const char * const * languages, + PRErrorCallbackLookupFn *lookup, + PRErrorCallbackNewTableFn *newtable, + struct PRErrorCallbackPrivate *cb_private); + +PR_END_EXTERN_C + +#endif /* prerror_h___ */ diff --git a/libsecurity_asn1/lib/prinit.h b/libsecurity_asn1/lib/prinit.h new file mode 100644 index 00000000..adfb76f4 --- /dev/null +++ b/libsecurity_asn1/lib/prinit.h @@ -0,0 +1,240 @@ +/* -*- 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 prinit_h___ +#define prinit_h___ + +#include "prthread.h" +#include "prtypes.h" +/* dmitch - WHY THIS!? #include "prwin16.h" */ +#include + +PR_BEGIN_EXTERN_C + +/************************************************************************/ +/**************************IDENTITY AND VERSIONING***********************/ +/************************************************************************/ + +/* +** NSPR's name, this should persist until at least the turn of the +** century. +*/ +#define PR_NAME "NSPR" + +/* +** NSPR's version is used to determine the likelihood that the version you +** used to build your component is anywhere close to being compatible with +** what is in the underlying library. +** +** The format of the version string is +** ".[.] []" +*/ +#define PR_VERSION "4.3 Beta" +#define PR_VMAJOR 4 +#define PR_VMINOR 3 +#define PR_VPATCH 0 +#define PR_BETA PR_TRUE + +/* +** PRVersionCheck +** +** The basic signature of the function that is called to provide version +** checking. The result will be a boolean that indicates the likelihood +** that the underling library will perform as the caller expects. +** +** The only argument is a string, which should be the verson identifier +** of the library in question. That string will be compared against an +** equivalent string that represents the actual build version of the +** exporting library. +** +** The result will be the logical union of the directly called library +** and all dependent libraries. +*/ + +typedef PRBool (*PRVersionCheck)(const char*); + +/* +** PR_VersionCheck +** +** NSPR's existance proof of the version check function. +** +** Note that NSPR has no cooperating dependencies. +*/ + +NSPR_API(PRBool) PR_VersionCheck(const char *importedVersion); + + +/************************************************************************/ +/*******************************INITIALIZATION***************************/ +/************************************************************************/ + +/* +** Initialize the runtime. Attach a thread object to the currently +** executing native thread of type "type". +** +** The specificaiton of 'maxPTDs' is ignored. +*/ +NSPR_API(void) PR_Init( + PRThreadType type, PRThreadPriority priority, PRUintn maxPTDs); + +/* +** And alternate form of initialization, one that may become the default if +** not the only mechanism, provides a method to get the NSPR runtime init- +** ialized and place NSPR between the caller and the runtime library. This +** allows main() to be treated as any other thread root function, signalling +** its compeletion by returning and allowing the runtime to coordinate the +** completion of the other threads of the runtime. +** +** The priority of the main (or primordial) thread will be PR_PRIORITY_NORMAL. +** The thread may adjust its own priority by using PR_SetPriority(), though +** at this time the support for priorities is somewhat weak. +** +** The specificaiton of 'maxPTDs' is ignored. +** +** The value returned by PR_Initialize is the value returned from the root +** function, 'prmain'. +*/ + +typedef PRIntn (PR_CALLBACK *PRPrimordialFn)(PRIntn argc, char **argv); + +NSPR_API(PRIntn) PR_Initialize( + PRPrimordialFn prmain, PRIntn argc, char **argv, PRUintn maxPTDs); + +/* +** Return PR_TRUE if PR_Init has already been called. +*/ +NSPR_API(PRBool) PR_Initialized(void); + +/* + * Perform a graceful shutdown of NSPR. PR_Cleanup() may be called by + * the primordial thread near the end of the main() function. + * + * PR_Cleanup() attempts to synchronize the natural termination of + * process. It does that by blocking the caller, if and only if it is + * the primordial thread, until the number of user threads has dropped + * to zero. When the primordial thread returns from main(), the process + * will immediately and silently exit. That is, it will (if necessary) + * forcibly terminate any existing threads and exit without significant + * blocking and there will be no error messages or core files. + * + * PR_Cleanup() returns PR_SUCCESS if NSPR is successfully shutdown, + * or PR_FAILURE if the calling thread of this function is not the + * primordial thread. + */ +NSPR_API(PRStatus) PR_Cleanup(void); + +/* +** Disable Interrupts +** Disables timer signals used for pre-emptive scheduling. +*/ +NSPR_API(void) PR_DisableClockInterrupts(void); + +/* +** Enables Interrupts +** Enables timer signals used for pre-emptive scheduling. +*/ +NSPR_API(void) PR_EnableClockInterrupts(void); + +/* +** Block Interrupts +** Blocks the timer signal used for pre-emptive scheduling +*/ +NSPR_API(void) PR_BlockClockInterrupts(void); + +/* +** Unblock Interrupts +** Unblocks the timer signal used for pre-emptive scheduling +*/ +NSPR_API(void) PR_UnblockClockInterrupts(void); + +/* +** Create extra virtual processor threads. Generally used with MP systems. +*/ +NSPR_API(void) PR_SetConcurrency(PRUintn numCPUs); + +/* +** Control the method and size of the file descriptor (PRFileDesc*) +** cache used by the runtime. Setting 'high' to zero is for performance, +** any other value probably for debugging (see memo on FD caching). +*/ +NSPR_API(PRStatus) PR_SetFDCacheSize(PRIntn low, PRIntn high); + +/* + * Cause an immediate, nongraceful, forced termination of the process. + * It takes a PRIntn argument, which is the exit status code of the + * process. + */ +NSPR_API(void) PR_ProcessExit(PRIntn status); + +/* +** Abort the process in a non-graceful manner. This will cause a core file, +** call to the debugger or other moral equivalent as well as causing the +** entire process to stop. +*/ +NSPR_API(void) PR_Abort(void); + +/* + **************************************************************** + * + * Module initialization: + * + **************************************************************** + */ +#ifndef __APPLE__ +/* deleted in favor of ModuleNexus */ +typedef struct PRCallOnceType { + PRIntn initialized; + PRInt32 inProgress; + PRStatus status; +} PRCallOnceType; + +typedef PRStatus (PR_CALLBACK *PRCallOnceFN)(void); + +typedef PRStatus (PR_CALLBACK *PRCallOnceWithArgFN)(void *arg); + +NSPR_API(PRStatus) PR_CallOnce( + PRCallOnceType *once, + PRCallOnceFN func +); + +NSPR_API(PRStatus) PR_CallOnceWithArg( + PRCallOnceType *once, + PRCallOnceWithArgFN func, + void *arg +); +#endif /* __APPLE__ */ + +PR_END_EXTERN_C + +#endif /* prinit_h___ */ diff --git a/libsecurity_asn1/lib/prinrval.h b/libsecurity_asn1/lib/prinrval.h new file mode 100644 index 00000000..298c3ad6 --- /dev/null +++ b/libsecurity_asn1/lib/prinrval.h @@ -0,0 +1,172 @@ +/* -*- 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. + */ + +/* +** File: prinrval.h +** Description: API to interval timing functions of NSPR. +** +** +** NSPR provides interval times that are independent of network time +** of day values. Interval times are (in theory) accurate regardless +** of host processing requirements and also very cheap to acquire. It +** is expected that getting an interval time while in a synchronized +** function (holding one's lock). +**/ + +#if !defined(prinrval_h) +#define prinrval_h + +#include + +PR_BEGIN_EXTERN_C + +/**********************************************************************/ +/************************* TYPES AND CONSTANTS ************************/ +/**********************************************************************/ + +typedef PRUint32 PRIntervalTime; + +/*********************************************************************** +** DEFINES: PR_INTERVAL_MIN +** PR_INTERVAL_MAX +** DESCRIPTION: +** These two constants define the range (in ticks / second) of the +** platform dependent type, PRIntervalTime. These constants bound both +** the period and the resolution of a PRIntervalTime. +***********************************************************************/ +#define PR_INTERVAL_MIN 1000UL +#define PR_INTERVAL_MAX 100000UL + +/*********************************************************************** +** DEFINES: PR_INTERVAL_NO_WAIT +** PR_INTERVAL_NO_TIMEOUT +** DESCRIPTION: +** Two reserved constants are defined in the PRIntervalTime namespace. +** They are used to indicate that the process should wait no time (return +** immediately) or wait forever (never time out), respectively. +***********************************************************************/ +#define PR_INTERVAL_NO_WAIT 0UL +#define PR_INTERVAL_NO_TIMEOUT 0xffffffffUL + +/**********************************************************************/ +/****************************** FUNCTIONS *****************************/ +/**********************************************************************/ + +/*********************************************************************** +** FUNCTION: PR_IntervalNow +** DESCRIPTION: +** Return the value of NSPR's free running interval timer. That timer +** can be used to establish epochs and determine intervals (be computing +** the difference between two times). +** INPUTS: void +** OUTPUTS: void +** RETURN: PRIntervalTime +** +** SIDE EFFECTS: +** None +** RESTRICTIONS: +** The units of PRIntervalTime are platform dependent. They are chosen +** such that they are appropriate for the host OS, yet provide sufficient +** resolution and period to be useful to clients. +** MEMORY: N/A +** ALGORITHM: Platform dependent +***********************************************************************/ +NSPR_API(PRIntervalTime) PR_IntervalNow(void); + +/*********************************************************************** +** FUNCTION: PR_TicksPerSecond +** DESCRIPTION: +** Return the number of ticks per second for PR_IntervalNow's clock. +** The value will be in the range [PR_INTERVAL_MIN..PR_INTERVAL_MAX]. +** INPUTS: void +** OUTPUTS: void +** RETURN: PRUint32 +** +** SIDE EFFECTS: +** None +** RESTRICTIONS: +** None +** MEMORY: N/A +** ALGORITHM: N/A +***********************************************************************/ +NSPR_API(PRUint32) PR_TicksPerSecond(void); + +/*********************************************************************** +** FUNCTION: PR_SecondsToInterval +** PR_MillisecondsToInterval +** PR_MicrosecondsToInterval +** DESCRIPTION: +** Convert standard clock units to platform dependent intervals. +** INPUTS: PRUint32 +** OUTPUTS: void +** RETURN: PRIntervalTime +** +** SIDE EFFECTS: +** None +** RESTRICTIONS: +** Conversion may cause overflow, which is not reported. +** MEMORY: N/A +** ALGORITHM: N/A +***********************************************************************/ +NSPR_API(PRIntervalTime) PR_SecondsToInterval(PRUint32 seconds); +NSPR_API(PRIntervalTime) PR_MillisecondsToInterval(PRUint32 milli); +NSPR_API(PRIntervalTime) PR_MicrosecondsToInterval(PRUint32 micro); + +/*********************************************************************** +** FUNCTION: PR_IntervalToSeconds +** PR_IntervalToMilliseconds +** PR_IntervalToMicroseconds +** DESCRIPTION: +** Convert platform dependent intervals to standard clock units. +** INPUTS: PRIntervalTime +** OUTPUTS: void +** RETURN: PRUint32 +** +** SIDE EFFECTS: +** None +** RESTRICTIONS: +** Conversion may cause overflow, which is not reported. +** MEMORY: N/A +** ALGORITHM: N/A +***********************************************************************/ +NSPR_API(PRUint32) PR_IntervalToSeconds(PRIntervalTime ticks); +NSPR_API(PRUint32) PR_IntervalToMilliseconds(PRIntervalTime ticks); +NSPR_API(PRUint32) PR_IntervalToMicroseconds(PRIntervalTime ticks); + +PR_END_EXTERN_C + + +#endif /* !defined(prinrval_h) */ + +/* prinrval.h */ diff --git a/libsecurity_asn1/lib/prlock.h b/libsecurity_asn1/lib/prlock.h new file mode 100644 index 00000000..f37e1fca --- /dev/null +++ b/libsecurity_asn1/lib/prlock.h @@ -0,0 +1,123 @@ +/* -*- 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. + */ + +/* +** File: prlock.h +** Description: API to basic locking functions of NSPR. +** +** +** NSPR provides basic locking mechanisms for thread synchronization. Locks +** are lightweight resource contention controls that prevent multiple threads +** from accessing something (code/data) simultaneously. +**/ + +#ifndef prlock_h___ +#define prlock_h___ + +#include + +PR_BEGIN_EXTERN_C + +/**********************************************************************/ +/************************* TYPES AND CONSTANTS ************************/ +/**********************************************************************/ + +/* + * PRLock -- + * + * NSPR represents the lock as an opaque entity to the client of the + * API. All routines operate on a pointer to this opaque entity. + */ + +#if defined(__APPLE_) & defined(__GNUC__) +/* dmitch - actually a pthread_mutex_t */ +typedef void PRLock; +#else +typedef struct PRLock PRLock; +#endif + +/**********************************************************************/ +/****************************** FUNCTIONS *****************************/ +/**********************************************************************/ + +/*********************************************************************** +** FUNCTION: PR_NewLock +** DESCRIPTION: +** Returns a pointer to a newly created opaque lock object. +** INPUTS: void +** OUTPUTS: void +** RETURN: PRLock* +** If the lock can not be created because of resource constraints, NULL +** is returned. +** +***********************************************************************/ +NSPR_API(PRLock*) PR_NewLock(void); + +/*********************************************************************** +** FUNCTION: PR_DestroyLock +** DESCRIPTION: +** Destroys a given opaque lock object. +** INPUTS: PRLock *lock +** Lock to be freed. +** OUTPUTS: void +** RETURN: None +***********************************************************************/ +NSPR_API(void) PR_DestroyLock(PRLock *lock); + +/*********************************************************************** +** FUNCTION: PR_Lock +** DESCRIPTION: +** Lock a lock. +** INPUTS: PRLock *lock +** Lock to locked. +** OUTPUTS: void +** RETURN: None +***********************************************************************/ +NSPR_API(void) PR_Lock(PRLock *lock); + +/*********************************************************************** +** FUNCTION: PR_Unlock +** DESCRIPTION: +** Unlock a lock. Unlocking an unlocked lock has undefined results. +** INPUTS: PRLock *lock +** Lock to unlocked. +** OUTPUTS: void +** RETURN: PR_STATUS +** Returns PR_FAILURE if the caller does not own the lock. +***********************************************************************/ +NSPR_API(PRStatus) PR_Unlock(PRLock *lock); + +PR_END_EXTERN_C + +#endif /* prlock_h___ */ diff --git a/libsecurity_asn1/lib/prlog.h b/libsecurity_asn1/lib/prlog.h new file mode 100644 index 00000000..c0b3b841 --- /dev/null +++ b/libsecurity_asn1/lib/prlog.h @@ -0,0 +1,262 @@ +/* -*- 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 prlog_h___ +#define prlog_h___ + +#include + +PR_BEGIN_EXTERN_C + +/* +** prlog.h -- Declare interfaces to NSPR's Logging service +** +** NSPR provides a logging service that is used by NSPR itself and is +** available to client programs. +** +** To use the service from a client program, you should create a +** PRLogModuleInfo structure by calling PR_NewLogModule(). After +** creating the LogModule, you can write to the log using the PR_LOG() +** macro. +** +** Initialization of the log service is handled by NSPR initialization. +** +** At execution time, you must enable the log service. To enable the +** log service, set the environment variable: NSPR_LOG_MODULES +** variable. +** +** NSPR_LOG_MODULES variable has the form: +** +** :[, :]* +** +** Where: +** is the name passed to PR_NewLogModule(). +** is a numeric constant, e.g. 5. This value is the maximum +** value of a log event, enumerated by PRLogModuleLevel, that you want +** written to the log. +** +** For example: to record all events of greater value than or equal to +** PR_LOG_ERROR for a LogModule names "gizmo", say: +** +** set NSPR_LOG_MODULES=gizmo:2 +** +** Note that you must specify the numeric value of PR_LOG_ERROR. +** +** Special LogModule names are provided for controlling NSPR's log +** service at execution time. These controls should be set in the +** NSPR_LOG_MODULES environment variable at execution time to affect +** NSPR's log service for your application. +** +** The special LogModule "all" enables all LogModules. To enable all +** LogModule calls to PR_LOG(), say: +** +** set NSPR_LOG_MODULES=all:5 +** +** The special LogModule name "sync" tells the NSPR log service to do +** unbuffered logging. +** +** The special LogModule name "bufsize:" tells NSPR to set the +** log buffer to . +** +** The environment variable NSPR_LOG_FILE specifies the log file to use +** unless the default of "stderr" is acceptable. For MS Windows +** systems, NSPR_LOG_FILE can be set to a special value: "WinDebug" +** (case sensitive). This value causes PR_LOG() output to be written +** using the Windows API OutputDebugString(). OutputDebugString() +** writes to the debugger window; some people find this helpful. +** +** +** To put log messages in your programs, use the PR_LOG macro: +** +** PR_LOG(, , (, *)); +** +** Where is the address of a PRLogModuleInfo structure, and +** is one of the levels defined by the enumeration: +** PRLogModuleLevel. is a printf() style of argument list. That +** is: (fmtstring, ...). +** +** Example: +** +** main() { +** PRIntn one = 1; +** PRLogModuleInfo * myLm = PR_NewLogModule("gizmo"); +** PR_LOG( myLm, PR_LOG_ALWAYS, ("Log this! %d\n", one)); +** return; +** } +** +** Note the use of printf() style arguments as the third agrument(s) to +** PR_LOG(). +** +** After compiling and linking you application, set the environment: +** +** set NSPR_LOG_MODULES=gizmo:5 +** set NSPR_LOG_FILE=logfile.txt +** +** When you execute your application, the string "Log this! 1" will be +** written to the file "logfile.txt". +** +** Note to NSPR engineers: a number of PRLogModuleInfo structures are +** defined and initialized in prinit.c. See this module for ideas on +** what to log where. +** +*/ + +typedef enum PRLogModuleLevel { + PR_LOG_NONE = 0, /* nothing */ + PR_LOG_ALWAYS = 1, /* always printed */ + PR_LOG_ERROR = 2, /* error messages */ + PR_LOG_WARNING = 3, /* warning messages */ + PR_LOG_DEBUG = 4, /* debug messages */ + + PR_LOG_NOTICE = PR_LOG_DEBUG, /* notice messages */ + PR_LOG_WARN = PR_LOG_WARNING, /* warning messages */ + PR_LOG_MIN = PR_LOG_DEBUG, /* minimal debugging messages */ + PR_LOG_MAX = PR_LOG_DEBUG /* maximal debugging messages */ +} PRLogModuleLevel; + +/* +** One of these structures is created for each module that uses logging. +** "name" is the name of the module +** "level" is the debugging level selected for that module +*/ +typedef struct PRLogModuleInfo { + const char *name; + PRLogModuleLevel level; + struct PRLogModuleInfo *next; +} PRLogModuleInfo; + +/* +** Create a new log module. +*/ +NSPR_API(PRLogModuleInfo*) PR_NewLogModule(const char *name); + +/* +** Set the file to use for logging. Returns PR_FALSE if the file cannot +** be created +*/ +NSPR_API(PRBool) PR_SetLogFile(const char *name); + +/* +** Set the size of the logging buffer. If "buffer_size" is zero then the +** logging becomes "synchronous" (or unbuffered). +*/ +NSPR_API(void) PR_SetLogBuffering(PRIntn buffer_size); + +/* +** Print a string to the log. "fmt" is a PR_snprintf format type. All +** messages printed to the log are preceeded by the name of the thread +** and a time stamp. Also, the routine provides a missing newline if one +** is not provided. +*/ +NSPR_API(void) PR_LogPrint(const char *fmt, ...); + +/* +** Flush the log to its file. +*/ +NSPR_API(void) PR_LogFlush(void); + +/* +** Windoze 16 can't support a large static string space for all of the +** various debugging strings so logging is not enabled for it. +*/ +#if (defined(DEBUG) || defined(FORCE_PR_LOG)) && !defined(WIN16) +#define PR_LOGGING 1 + +#define PR_LOG_TEST(_module,_level) \ + ((_module)->level >= (_level)) + +/* +** Log something. +** "module" is the address of a PRLogModuleInfo structure +** "level" is the desired logging level +** "args" is a variable length list of arguments to print, in the following +** format: ("printf style format string", ...) +*/ +#define PR_LOG(_module,_level,_args) \ + PR_BEGIN_MACRO \ + if (PR_LOG_TEST(_module,_level)) { \ + PR_LogPrint _args; \ + } \ + PR_END_MACRO + +#else /* (defined(DEBUG) || defined(FORCE_PR_LOG)) && !defined(WIN16) */ + +#undef PR_LOGGING +#define PR_LOG_TEST(module,level) 0 +#define PR_LOG(module,level,args) + +#endif /* (defined(DEBUG) || defined(FORCE_PR_LOG)) && !defined(WIN16) */ + +#ifndef NO_NSPR_10_SUPPORT + +#ifdef PR_LOGGING +#define PR_LOG_BEGIN PR_LOG +#define PR_LOG_END PR_LOG +#define PR_LOG_DEFINE PR_NewLogModule +#else +#define PR_LOG_BEGIN(module,level,args) +#define PR_LOG_END(module,level,args) +#define PR_LOG_DEFINE(_name) NULL +#endif /* PR_LOGGING */ + +#endif /* NO_NSPR_10_SUPPORT */ + +#if !defined(NDEBUG) || defined(FORCE_PR_ASSERT) + +#ifdef __APPLE__ + +#include + +#define PR_ASSERT(_exp) assert(_exp) +#define PR_NOT_REACHED(_reas) assert(0) + +#else +NSPR_API(void) PR_Assert(const char *s, const char *file, PRIntn ln); +#define PR_ASSERT(_expr) \ + ((_expr)?((void)0):PR_Assert(# _expr,__FILE__,__LINE__)) + +#define PR_NOT_REACHED(_reasonStr) \ + PR_Assert(_reasonStr,__FILE__,__LINE__) +#endif + +#else + +#define PR_ASSERT(expr) ((void) 0) +#define PR_NOT_REACHED(reasonStr) + +#endif /* defined(DEBUG) || defined(FORCE_PR_ASSERT) */ + +PR_END_EXTERN_C + +#endif /* prlog_h___ */ diff --git a/libsecurity_asn1/lib/prlong.h b/libsecurity_asn1/lib/prlong.h new file mode 100644 index 00000000..dd45456c --- /dev/null +++ b/libsecurity_asn1/lib/prlong.h @@ -0,0 +1,425 @@ +/* -*- 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. + */ + +/* +** File: prlong.h +** Description: Portable access to 64 bit numerics +** +** Long-long (64-bit signed integer type) support. Some C compilers +** don't support 64 bit integers yet, so we use these macros to +** support both machines that do and don't. +**/ +#ifndef prlong_h___ +#define prlong_h___ + +#include + +PR_BEGIN_EXTERN_C + +/*********************************************************************** +** DEFINES: LL_MaxInt +** LL_MinInt +** LL_Zero +** DESCRIPTION: +** Various interesting constants and static variable +** initializer +***********************************************************************/ +#if defined(HAVE_WATCOM_BUG_2) +PRInt64 __pascal __loadds __export + LL_MaxInt(void); +PRInt64 __pascal __loadds __export + LL_MinInt(void); +PRInt64 __pascal __loadds __export + LL_Zero(void); +#else +NSPR_API(PRInt64) LL_MaxInt(void); +NSPR_API(PRInt64) LL_MinInt(void); +NSPR_API(PRInt64) LL_Zero(void); +#endif + +#define LL_MAXINT LL_MaxInt() +#define LL_MININT LL_MinInt() +#define LL_ZERO LL_Zero() + +#if defined(HAVE_LONG_LONG) + +#if PR_BYTES_PER_LONG == 8 +#define LL_INIT(hi, lo) ((hi ## L << 32) + lo ## L) +#elif (defined(WIN32) || defined(WIN16)) && !defined(__GNUC__) +#define LL_INIT(hi, lo) ((hi ## i64 << 32) + lo ## i64) +#else +#define LL_INIT(hi, lo) ((hi ## LL << 32) + lo ## LL) +#endif + +/*********************************************************************** +** MACROS: LL_* +** DESCRIPTION: +** The following macros define portable access to the 64 bit +** math facilities. +** +***********************************************************************/ + +/*********************************************************************** +** MACROS: LL_ +** +** LL_IS_ZERO Test for zero +** LL_EQ Test for equality +** LL_NE Test for inequality +** LL_GE_ZERO Test for zero or positive +** LL_CMP Compare two values +***********************************************************************/ +#define LL_IS_ZERO(a) ((a) == 0) +#define LL_EQ(a, b) ((a) == (b)) +#define LL_NE(a, b) ((a) != (b)) +#define LL_GE_ZERO(a) ((a) >= 0) +#define LL_CMP(a, op, b) ((PRInt64)(a) op (PRInt64)(b)) +#define LL_UCMP(a, op, b) ((PRUint64)(a) op (PRUint64)(b)) + +/*********************************************************************** +** MACROS: LL_ +** +** LL_AND Logical and +** LL_OR Logical or +** LL_XOR Logical exclusion +** LL_OR2 A disgusting deviation +** LL_NOT Negation (one's complement) +***********************************************************************/ +#define LL_AND(r, a, b) ((r) = (a) & (b)) +#define LL_OR(r, a, b) ((r) = (a) | (b)) +#define LL_XOR(r, a, b) ((r) = (a) ^ (b)) +#define LL_OR2(r, a) ((r) = (r) | (a)) +#define LL_NOT(r, a) ((r) = ~(a)) + +/*********************************************************************** +** MACROS: LL_ +** +** LL_NEG Negation (two's complement) +** LL_ADD Summation (two's complement) +** LL_SUB Difference (two's complement) +***********************************************************************/ +#define LL_NEG(r, a) ((r) = -(a)) +#define LL_ADD(r, a, b) ((r) = (a) + (b)) +#define LL_SUB(r, a, b) ((r) = (a) - (b)) + +/*********************************************************************** +** MACROS: LL_ +** +** LL_MUL Product (two's complement) +** LL_DIV Quotient (two's complement) +** LL_MOD Modulus (two's complement) +***********************************************************************/ +#define LL_MUL(r, a, b) ((r) = (a) * (b)) +#define LL_DIV(r, a, b) ((r) = (a) / (b)) +#define LL_MOD(r, a, b) ((r) = (a) % (b)) + +/*********************************************************************** +** MACROS: LL_ +** +** LL_SHL Shift left [0..64] bits +** LL_SHR Shift right [0..64] bits with sign extension +** LL_USHR Unsigned shift right [0..64] bits +** LL_ISHL Signed shift left [0..64] bits +***********************************************************************/ +#define LL_SHL(r, a, b) ((r) = (PRInt64)(a) << (b)) +#define LL_SHR(r, a, b) ((r) = (PRInt64)(a) >> (b)) +#define LL_USHR(r, a, b) ((r) = (PRUint64)(a) >> (b)) +#define LL_ISHL(r, a, b) ((r) = (PRInt64)(a) << (b)) + +/*********************************************************************** +** MACROS: LL_ +** +** LL_L2I Convert to signed 32 bit +** LL_L2UI Convert to unsigned 32 bit +** LL_L2F Convert to floating point +** LL_L2D Convert to floating point +** LL_I2L Convert signed to 64 bit +** LL_UI2L Convert unsigned to 64 bit +** LL_F2L Convert float to 64 bit +** LL_D2L Convert float to 64 bit +***********************************************************************/ +#define LL_L2I(i, l) ((i) = (PRInt32)(l)) +#define LL_L2UI(ui, l) ((ui) = (PRUint32)(l)) +#define LL_L2F(f, l) ((f) = (PRFloat64)(l)) +#define LL_L2D(d, l) ((d) = (PRFloat64)(l)) + +#define LL_I2L(l, i) ((l) = (PRInt64)(i)) +#define LL_UI2L(l, ui) ((l) = (PRInt64)(ui)) +#define LL_F2L(l, f) ((l) = (PRInt64)(f)) +#define LL_D2L(l, d) ((l) = (PRInt64)(d)) + +/*********************************************************************** +** MACROS: LL_UDIVMOD +** DESCRIPTION: +** Produce both a quotient and a remainder given an unsigned +** INPUTS: PRUint64 a: The dividend of the operation +** PRUint64 b: The quotient of the operation +** OUTPUTS: PRUint64 *qp: pointer to quotient +** PRUint64 *rp: pointer to remainder +***********************************************************************/ +#define LL_UDIVMOD(qp, rp, a, b) \ + (*(qp) = ((PRUint64)(a) / (b)), \ + *(rp) = ((PRUint64)(a) % (b))) + +#else /* !HAVE_LONG_LONG */ + +#ifdef IS_LITTLE_ENDIAN +#define LL_INIT(hi, lo) {PR_INT32(lo), PR_INT32(hi)} +#else +#define LL_INIT(hi, lo) {PR_INT32(hi), PR_INT32(lo)} +#endif + +#define LL_IS_ZERO(a) (((a).hi == 0) && ((a).lo == 0)) +#define LL_EQ(a, b) (((a).hi == (b).hi) && ((a).lo == (b).lo)) +#define LL_NE(a, b) (((a).hi != (b).hi) || ((a).lo != (b).lo)) +#define LL_GE_ZERO(a) (((a).hi >> 31) == 0) + +#define LL_CMP(a, op, b) (((a).hi == (b).hi) ? ((a).lo op (b).lo) : \ + ((PRInt32)(a).hi op (PRInt32)(b).hi)) +#define LL_UCMP(a, op, b) (((a).hi == (b).hi) ? ((a).lo op (b).lo) : \ + ((a).hi op (b).hi)) + +#define LL_AND(r, a, b) ((r).lo = (a).lo & (b).lo, \ + (r).hi = (a).hi & (b).hi) +#define LL_OR(r, a, b) ((r).lo = (a).lo | (b).lo, \ + (r).hi = (a).hi | (b).hi) +#define LL_XOR(r, a, b) ((r).lo = (a).lo ^ (b).lo, \ + (r).hi = (a).hi ^ (b).hi) +#define LL_OR2(r, a) ((r).lo = (r).lo | (a).lo, \ + (r).hi = (r).hi | (a).hi) +#define LL_NOT(r, a) ((r).lo = ~(a).lo, \ + (r).hi = ~(a).hi) + +#define LL_NEG(r, a) ((r).lo = -(PRInt32)(a).lo, \ + (r).hi = -(PRInt32)(a).hi - ((r).lo != 0)) +#define LL_ADD(r, a, b) { \ + PRInt64 _a, _b; \ + _a = a; _b = b; \ + (r).lo = _a.lo + _b.lo; \ + (r).hi = _a.hi + _b.hi + ((r).lo < _b.lo); \ +} + +#define LL_SUB(r, a, b) { \ + PRInt64 _a, _b; \ + _a = a; _b = b; \ + (r).lo = _a.lo - _b.lo; \ + (r).hi = _a.hi - _b.hi - (_a.lo < _b.lo); \ +} + +#define LL_MUL(r, a, b) { \ + PRInt64 _a, _b; \ + _a = a; _b = b; \ + LL_MUL32(r, _a.lo, _b.lo); \ + (r).hi += _a.hi * _b.lo + _a.lo * _b.hi; \ +} + +#define _lo16(a) ((a) & PR_BITMASK(16)) +#define _hi16(a) ((a) >> 16) + +#define LL_MUL32(r, a, b) { \ + PRUint32 _a1, _a0, _b1, _b0, _y0, _y1, _y2, _y3; \ + _a1 = _hi16(a), _a0 = _lo16(a); \ + _b1 = _hi16(b), _b0 = _lo16(b); \ + _y0 = _a0 * _b0; \ + _y1 = _a0 * _b1; \ + _y2 = _a1 * _b0; \ + _y3 = _a1 * _b1; \ + _y1 += _hi16(_y0); /* can't carry */ \ + _y1 += _y2; /* might carry */ \ + if (_y1 < _y2) \ + _y3 += (PRUint32)(PR_BIT(16)); /* propagate */ \ + (r).lo = (_lo16(_y1) << 16) + _lo16(_y0); \ + (r).hi = _y3 + _hi16(_y1); \ +} + +#define LL_UDIVMOD(qp, rp, a, b) ll_udivmod(qp, rp, a, b) + +NSPR_API(void) ll_udivmod(PRUint64 *qp, PRUint64 *rp, PRUint64 a, PRUint64 b); + +#define LL_DIV(r, a, b) { \ + PRInt64 _a, _b; \ + PRUint32 _negative = (PRInt32)(a).hi < 0; \ + if (_negative) { \ + LL_NEG(_a, a); \ + } else { \ + _a = a; \ + } \ + if ((PRInt32)(b).hi < 0) { \ + _negative ^= 1; \ + LL_NEG(_b, b); \ + } else { \ + _b = b; \ + } \ + LL_UDIVMOD(&(r), 0, _a, _b); \ + if (_negative) \ + LL_NEG(r, r); \ +} + +#define LL_MOD(r, a, b) { \ + PRInt64 _a, _b; \ + PRUint32 _negative = (PRInt32)(a).hi < 0; \ + if (_negative) { \ + LL_NEG(_a, a); \ + } else { \ + _a = a; \ + } \ + if ((PRInt32)(b).hi < 0) { \ + LL_NEG(_b, b); \ + } else { \ + _b = b; \ + } \ + LL_UDIVMOD(0, &(r), _a, _b); \ + if (_negative) \ + LL_NEG(r, r); \ +} + +#define LL_SHL(r, a, b) { \ + if (b) { \ + PRInt64 _a; \ + _a = a; \ + if ((b) < 32) { \ + (r).lo = _a.lo << ((b) & 31); \ + (r).hi = (_a.hi << ((b) & 31)) | (_a.lo >> (32 - (b))); \ + } else { \ + (r).lo = 0; \ + (r).hi = _a.lo << ((b) & 31); \ + } \ + } else { \ + (r) = (a); \ + } \ +} + +/* a is an PRInt32, b is PRInt32, r is PRInt64 */ +#define LL_ISHL(r, a, b) { \ + if (b) { \ + PRInt64 _a; \ + _a.lo = (a); \ + _a.hi = 0; \ + if ((b) < 32) { \ + (r).lo = (a) << ((b) & 31); \ + (r).hi = ((a) >> (32 - (b))); \ + } else { \ + (r).lo = 0; \ + (r).hi = (a) << ((b) & 31); \ + } \ + } else { \ + (r).lo = (a); \ + (r).hi = 0; \ + } \ +} + +#define LL_SHR(r, a, b) { \ + if (b) { \ + PRInt64 _a; \ + _a = a; \ + if ((b) < 32) { \ + (r).lo = (_a.hi << (32 - (b))) | (_a.lo >> ((b) & 31)); \ + (r).hi = (PRInt32)_a.hi >> ((b) & 31); \ + } else { \ + (r).lo = (PRInt32)_a.hi >> ((b) & 31); \ + (r).hi = (PRInt32)_a.hi >> 31; \ + } \ + } else { \ + (r) = (a); \ + } \ +} + +#define LL_USHR(r, a, b) { \ + if (b) { \ + PRInt64 _a; \ + _a = a; \ + if ((b) < 32) { \ + (r).lo = (_a.hi << (32 - (b))) | (_a.lo >> ((b) & 31)); \ + (r).hi = _a.hi >> ((b) & 31); \ + } else { \ + (r).lo = _a.hi >> ((b) & 31); \ + (r).hi = 0; \ + } \ + } else { \ + (r) = (a); \ + } \ +} + +#define LL_L2I(i, l) ((i) = (l).lo) +#define LL_L2UI(ui, l) ((ui) = (l).lo) +#define LL_L2F(f, l) { double _d; LL_L2D(_d, l); (f) = (PRFloat64)_d; } + +#define LL_L2D(d, l) { \ + int _negative; \ + PRInt64 _absval; \ + \ + _negative = (l).hi >> 31; \ + if (_negative) { \ + LL_NEG(_absval, l); \ + } else { \ + _absval = l; \ + } \ + (d) = (double)_absval.hi * 4.294967296e9 + _absval.lo; \ + if (_negative) \ + (d) = -(d); \ +} + +#define LL_I2L(l, i) { PRInt32 _i = ((PRInt32)(i)) >> 31; (l).lo = (i); (l).hi = _i; } +#define LL_UI2L(l, ui) ((l).lo = (ui), (l).hi = 0) +#define LL_F2L(l, f) { double _d = (double)f; LL_D2L(l, _d); } + +#define LL_D2L(l, d) { \ + int _negative; \ + double _absval, _d_hi; \ + PRInt64 _lo_d; \ + \ + _negative = ((d) < 0); \ + _absval = _negative ? -(d) : (d); \ + \ + (l).hi = _absval / 4.294967296e9; \ + (l).lo = 0; \ + LL_L2D(_d_hi, l); \ + _absval -= _d_hi; \ + _lo_d.hi = 0; \ + if (_absval < 0) { \ + _lo_d.lo = -_absval; \ + LL_SUB(l, l, _lo_d); \ + } else { \ + _lo_d.lo = _absval; \ + LL_ADD(l, l, _lo_d); \ + } \ + \ + if (_negative) \ + LL_NEG(l, l); \ +} + +#endif /* !HAVE_LONG_LONG */ + +PR_END_EXTERN_C + +#endif /* prlong_h___ */ diff --git a/libsecurity_asn1/lib/prmem.h b/libsecurity_asn1/lib/prmem.h new file mode 100644 index 00000000..937dac79 --- /dev/null +++ b/libsecurity_asn1/lib/prmem.h @@ -0,0 +1,156 @@ +/* -*- 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. + */ + +/* +** File: prmem.h +** Description: API to NSPR 2.0 memory management functions +** +*/ +#ifndef prmem_h___ +#define prmem_h___ + +#include +#include +#include + +PR_BEGIN_EXTERN_C + +/* +** Thread safe memory allocation. +** +** NOTE: pr wraps up malloc, free, calloc, realloc so they are already +** thread safe (and are not declared here - look in stdlib.h). +*/ + +/* +** PR_Malloc, PR_Calloc, PR_Realloc, and PR_Free have the same signatures +** as their libc equivalent malloc, calloc, realloc, and free, and have +** the same semantics. (Note that the argument type size_t is replaced +** by PRUint32.) Memory allocated by PR_Malloc, PR_Calloc, or PR_Realloc +** must be freed by PR_Free. +*/ + +NSPR_API(void *) PR_Malloc(PRSize size); + +NSPR_API(void *) PR_Calloc(PRSize nelem, PRSize elsize); + +NSPR_API(void *) PR_Realloc(void *ptr, PRSize size); + +NSPR_API(void) PR_Free(void *ptr); + +/* +** The following are some convenience macros defined in terms of +** PR_Malloc, PR_Calloc, PR_Realloc, and PR_Free. +*/ + +/*********************************************************************** +** FUNCTION: PR_MALLOC() +** DESCRIPTION: +** PR_NEW() allocates an untyped item of size _size from the heap. +** INPUTS: _size: size in bytes of item to be allocated +** OUTPUTS: untyped pointer to the node allocated +** RETURN: pointer to node or error returned from malloc(). +***********************************************************************/ +#define PR_MALLOC(_bytes) (PR_Malloc((_bytes))) + +/*********************************************************************** +** FUNCTION: PR_NEW() +** DESCRIPTION: +** PR_NEW() allocates an item of type _struct from the heap. +** INPUTS: _struct: a data type +** OUTPUTS: pointer to _struct +** RETURN: pointer to _struct or error returns from malloc(). +***********************************************************************/ +#define PR_NEW(_struct) ((_struct *) PR_MALLOC(sizeof(_struct))) + +/*********************************************************************** +** FUNCTION: PR_REALLOC() +** DESCRIPTION: +** PR_REALLOC() re-allocates _ptr bytes from the heap as a _size +** untyped item. +** INPUTS: _ptr: pointer to node to reallocate +** _size: size of node to allocate +** OUTPUTS: pointer to node allocated +** RETURN: pointer to node allocated +***********************************************************************/ +#define PR_REALLOC(_ptr, _size) (PR_Realloc((_ptr), (_size))) + +/*********************************************************************** +** FUNCTION: PR_CALLOC() +** DESCRIPTION: +** PR_CALLOC() allocates a _size bytes untyped item from the heap +** and sets the allocated memory to all 0x00. +** INPUTS: _size: size of node to allocate +** OUTPUTS: pointer to node allocated +** RETURN: pointer to node allocated +***********************************************************************/ +#define PR_CALLOC(_size) (PR_Calloc(1, (_size))) + +/*********************************************************************** +** FUNCTION: PR_NEWZAP() +** DESCRIPTION: +** PR_NEWZAP() allocates an item of type _struct from the heap +** and sets the allocated memory to all 0x00. +** INPUTS: _struct: a data type +** OUTPUTS: pointer to _struct +** RETURN: pointer to _struct +***********************************************************************/ +#define PR_NEWZAP(_struct) ((_struct*)PR_Calloc(1, sizeof(_struct))) + +/*********************************************************************** +** FUNCTION: PR_DELETE() +** DESCRIPTION: +** PR_DELETE() unallocates an object previosly allocated via PR_NEW() +** or PR_NEWZAP() to the heap. +** INPUTS: pointer to previously allocated object +** OUTPUTS: the referenced object is returned to the heap +** RETURN: void +***********************************************************************/ +#define PR_DELETE(_ptr) { PR_Free(_ptr); (_ptr) = NULL; } + +/*********************************************************************** +** FUNCTION: PR_FREEIF() +** DESCRIPTION: +** PR_FREEIF() conditionally unallocates an object previously allocated +** vial PR_NEW() or PR_NEWZAP(). If the pointer to the object is +** equal to zero (0), the object is not released. +** INPUTS: pointer to previously allocated object +** OUTPUTS: the referenced object is conditionally returned to the heap +** RETURN: void +***********************************************************************/ +#define PR_FREEIF(_ptr) if (_ptr) PR_DELETE(_ptr) + +PR_END_EXTERN_C + +#endif /* prmem_h___ */ diff --git a/libsecurity_asn1/lib/prmon.h b/libsecurity_asn1/lib/prmon.h new file mode 100644 index 00000000..a457f624 --- /dev/null +++ b/libsecurity_asn1/lib/prmon.h @@ -0,0 +1,110 @@ +/* -*- 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 prmon_h___ +#define prmon_h___ + +#include +#include + +PR_BEGIN_EXTERN_C + +typedef struct PRMonitor PRMonitor; + +/* +** Create a new monitor. Monitors are re-entrant locks with a single built-in +** condition variable. +** +** This may fail if memory is tight or if some operating system resource +** is low. +*/ +NSPR_API(PRMonitor*) PR_NewMonitor(void); + +/* +** Destroy a monitor. The caller is responsible for guaranteeing that the +** monitor is no longer in use. There must be no thread waiting on the monitor's +** condition variable and that the lock is not held. +** +*/ +NSPR_API(void) PR_DestroyMonitor(PRMonitor *mon); + +/* +** Enter the lock associated with the monitor. If the calling thread currently +** is in the monitor, the call to enter will silently succeed. In either case, +** it will increment the entry count by one. +*/ +NSPR_API(void) PR_EnterMonitor(PRMonitor *mon); + +/* +** Decrement the entry count associated with the monitor. If the decremented +** entry count is zero, the monitor is exited. Returns PR_FAILURE if the +** calling thread has not entered the monitor. +*/ +NSPR_API(PRStatus) PR_ExitMonitor(PRMonitor *mon); + +/* +** Wait for a notify on the monitor's condition variable. Sleep for "ticks" +** amount of time (if "ticks" is PR_INTERVAL_NO_TIMEOUT then the sleep is +** indefinite). +** +** While the thread is waiting it exits the monitor (as if it called +** PR_ExitMonitor as many times as it had called PR_EnterMonitor). When +** the wait has finished the thread regains control of the monitors lock +** with the same entry count as before the wait began. +** +** The thread waiting on the monitor will be resumed when the monitor is +** notified (assuming the thread is the next in line to receive the +** notify) or when the "ticks" timeout elapses. +** +** Returns PR_FAILURE if the caller has not entered the monitor. +*/ +NSPR_API(PRStatus) PR_Wait(PRMonitor *mon, PRIntervalTime ticks); + +/* +** Notify a thread waiting on the monitor's condition variable. If a thread +** is waiting on the condition variable (using PR_Wait) then it is awakened +** and attempts to reenter the monitor. +*/ +NSPR_API(PRStatus) PR_Notify(PRMonitor *mon); + +/* +** Notify all of the threads waiting on the monitor's condition variable. +** All of threads waiting on the condition are scheduled to reenter the +** monitor. +*/ +NSPR_API(PRStatus) PR_NotifyAll(PRMonitor *mon); + +PR_END_EXTERN_C + +#endif /* prmon_h___ */ diff --git a/libsecurity_asn1/lib/protypes.h b/libsecurity_asn1/lib/protypes.h new file mode 100644 index 00000000..33ef7a3a --- /dev/null +++ b/libsecurity_asn1/lib/protypes.h @@ -0,0 +1,251 @@ +/* -*- 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. + */ + +/* + * This header typedefs the old 'native' types to the new PRs. + * These definitions are scheduled to be eliminated at the earliest + * possible time. The NSPR API is implemented and documented using + * the new definitions. + */ + +#if !defined(PROTYPES_H) +#define PROTYPES_H + +typedef PRUintn uintn; +#ifndef _XP_Core_ +typedef PRIntn intn; +#endif + +/* + * It is trickier to define uint, int8, uint8, int16, uint16, + * int32, uint32, int64, and uint64 because some of these int + * types are defined by standard header files on some platforms. + * Our strategy here is to include all such standard headers + * first, and then define these int types only if they are not + * defined by those standard headers. + */ + +/* + * BeOS defines all the int types below in its standard header + * file SupportDefs.h. + */ +#ifdef XP_BEOS +#include +#endif + +/* + * OpenVMS defines all the int types below in its standard + * header files ints.h and types.h. + */ +#ifdef VMS +#include +#include +#endif + +/* + * SVR4 typedef of uint is commonly found on UNIX machines. + * + * On AIX 4.3, sys/inttypes.h (which is included by sys/types.h) + * defines the types int8, int16, int32, and int64. + */ +#ifdef XP_UNIX +#include +#endif + +/* model.h on HP-UX defines int8, int16, and int32. */ +#ifdef HPUX +#include +#endif + +/* + * uint + */ + +#if !defined(XP_BEOS) && !defined(VMS) \ + && !defined(XP_UNIX) & !defined(__APPLE__) || defined(NTO) +typedef PRUintn uint; +#endif + +/* + * uint64 + */ + +#if !defined(XP_BEOS) && !defined(VMS) && !defined(__APPLE__) +typedef PRUint64 uint64; +#endif + +/* + * uint32 + */ + +#if !defined(XP_BEOS) && !defined(VMS) && !defined(__APPLE__) +#if !defined(XP_MAC) && !defined(_WIN32) && !defined(XP_OS2) && !defined(NTO) +typedef PRUint32 uint32; +#else +typedef unsigned long uint32; +#endif +#endif + +/* + * uint16 + */ + +#if !defined(XP_BEOS) && !defined(VMS) && !defined(__APPLE__) +typedef PRUint16 uint16; +#endif + +/* + * uint8 + */ + +#if !defined(XP_BEOS) && !defined(VMS) && !defined(__APPLE__) +typedef PRUint8 uint8; +#endif + +/* + * int64 + */ + +#if !defined(XP_BEOS) && !defined(VMS) \ + && !defined(_PR_AIX_HAVE_BSD_INT_TYPES) +typedef PRInt64 int64; +#endif + +/* + * int32 + */ + +#if !defined(XP_BEOS) && !defined(VMS) \ + && !defined(_PR_AIX_HAVE_BSD_INT_TYPES) \ + && !defined(HPUX) +#if !defined(WIN32) || !defined(_WINSOCK2API_) /* defines its own "int32" */ +#if !defined(XP_MAC) && !defined(_WIN32) && !defined(XP_OS2) && !defined(NTO) +typedef PRInt32 int32; +#else +typedef long int32; +#endif +#endif +#endif + +/* + * int16 + */ + +#if !defined(XP_BEOS) && !defined(VMS) \ + && !defined(_PR_AIX_HAVE_BSD_INT_TYPES) \ + && !defined(HPUX) +typedef PRInt16 int16; +#endif + +/* + * int8 + */ + +#if !defined(XP_BEOS) && !defined(VMS) \ + && !defined(_PR_AIX_HAVE_BSD_INT_TYPES) \ + && !defined(HPUX) +typedef PRInt8 int8; +#endif + +typedef PRFloat64 float64; +typedef PRUptrdiff uptrdiff_t; +typedef PRUword uprword_t; +typedef PRWord prword_t; + + +/* Re: prbit.h */ +#define TEST_BIT PR_TEST_BIT +#define SET_BIT PR_SET_BIT +#define CLEAR_BIT PR_CLEAR_BIT + +/* Re: prarena.h->plarena.h */ +#define PRArena PLArena +#define PRArenaPool PLArenaPool +#define PRArenaStats PLArenaStats +#define PR_ARENA_ALIGN PL_ARENA_ALIGN +#define PR_INIT_ARENA_POOL PL_INIT_ARENA_POOL +#define PR_ARENA_ALLOCATE PL_ARENA_ALLOCATE +#define PR_ARENA_GROW PL_ARENA_GROW +#define PR_ARENA_MARK PL_ARENA_MARK +#define PR_CLEAR_UNUSED PL_CLEAR_UNUSED +#define PR_CLEAR_ARENA PL_CLEAR_ARENA +#define PR_ARENA_RELEASE PL_ARENA_RELEASE +#define PR_COUNT_ARENA PL_COUNT_ARENA +#define PR_ARENA_DESTROY PL_ARENA_DESTROY +#define PR_InitArenaPool PL_InitArenaPool +#define PR_FreeArenaPool PL_FreeArenaPool +#define PR_FinishArenaPool PL_FinishArenaPool +#define PR_CompactArenaPool PL_CompactArenaPool +#define PR_ArenaFinish PL_ArenaFinish +#define PR_ArenaAllocate PL_ArenaAllocate +#define PR_ArenaGrow PL_ArenaGrow +#define PR_ArenaRelease PL_ArenaRelease +#define PR_ArenaCountAllocation PL_ArenaCountAllocation +#define PR_ArenaCountInplaceGrowth PL_ArenaCountInplaceGrowth +#define PR_ArenaCountGrowth PL_ArenaCountGrowth +#define PR_ArenaCountRelease PL_ArenaCountRelease +#define PR_ArenaCountRetract PL_ArenaCountRetract + +/* Re: prhash.h->plhash.h */ +#define PRHashEntry PLHashEntry +#define PRHashTable PLHashTable +#define PRHashNumber PLHashNumber +#define PRHashFunction PLHashFunction +#define PRHashComparator PLHashComparator +#define PRHashEnumerator PLHashEnumerator +#define PRHashAllocOps PLHashAllocOps +#define PR_NewHashTable PL_NewHashTable +#define PR_HashTableDestroy PL_HashTableDestroy +#define PR_HashTableRawLookup PL_HashTableRawLookup +#define PR_HashTableRawAdd PL_HashTableRawAdd +#define PR_HashTableRawRemove PL_HashTableRawRemove +#define PR_HashTableAdd PL_HashTableAdd +#define PR_HashTableRemove PL_HashTableRemove +#define PR_HashTableEnumerateEntries PL_HashTableEnumerateEntries +#define PR_HashTableLookup PL_HashTableLookup +#define PR_HashTableDump PL_HashTableDump +#define PR_HashString PL_HashString +#define PR_CompareStrings PL_CompareStrings +#define PR_CompareValues PL_CompareValues + +#if defined(XP_MAC) +#ifndef TRUE /* Mac standard is lower case true */ + #define TRUE 1 +#endif +#ifndef FALSE /* Mac standard is lower case false */ + #define FALSE 0 +#endif +#endif + +#endif /* !defined(PROTYPES_H) */ diff --git a/libsecurity_asn1/lib/prthread.h b/libsecurity_asn1/lib/prthread.h new file mode 100644 index 00000000..334116ce --- /dev/null +++ b/libsecurity_asn1/lib/prthread.h @@ -0,0 +1,283 @@ +/* -*- 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 prthread_h___ +#define prthread_h___ + +/* +** API for NSPR threads. On some architectures (MAC and WIN16 +** notably) pre-emptibility is not guaranteed. Hard priority scheduling +** is not guaranteed, so programming using priority based synchronization +** is a no-no. +** +** NSPR threads are scheduled based loosly on their client set priority. +** In general, a thread of a higher priority has a statistically better +** chance of running relative to threads of lower priority. However, +** NSPR uses multiple strategies to provide execution vehicles for thread +** abstraction of various host platforms. As it turns out, there is little +** NSPR can do to affect the scheduling attributes of "GLOBAL" threads. +** However, a semblance of GLOBAL threads is used to implement "LOCAL" +** threads. An arbitrary number of such LOCAL threads can be assigned to +** a single GLOBAL thread. +** +** For scheduling, NSPR will attempt to run the highest priority LOCAL +** thread associated with a given GLOBAL thread. It is further assumed +** that the host OS will apply some form of "fair" scheduling on the +** GLOBAL threads. +** +** Threads have a "system flag" which when set indicates the thread +** doesn't count for determining when the process should exit (the +** process exits when the last user thread exits). +** +** Threads also have a "scope flag" which controls whether the threads +** are scheduled in the local scope or scheduled by the OS globally. This +** indicates whether a thread is permanently bound to a native OS thread. +** An unbound thread competes for scheduling resources in the same process. +** +** Another flag is "state flag" which control whether the thread is joinable. +** It allows other threads to wait for the created thread to reach completion. +** +** Threads can have "per-thread-data" attached to them. Each thread has a +** per-thread error number and error string which are updated when NSPR +** operations fail. +*/ +#include "prtypes.h" +#include "prinrval.h" + +PR_BEGIN_EXTERN_C + +typedef struct PRThread PRThread; +typedef struct PRThreadStack PRThreadStack; + +typedef enum PRThreadType { + PR_USER_THREAD, + PR_SYSTEM_THREAD +} PRThreadType; + +typedef enum PRThreadScope { + PR_LOCAL_THREAD, + PR_GLOBAL_THREAD, + PR_GLOBAL_BOUND_THREAD +} PRThreadScope; + +typedef enum PRThreadState { + PR_JOINABLE_THREAD, + PR_UNJOINABLE_THREAD +} PRThreadState; + +typedef enum PRThreadPriority +{ + PR_PRIORITY_FIRST = 0, /* just a placeholder */ + PR_PRIORITY_LOW = 0, /* the lowest possible priority */ + PR_PRIORITY_NORMAL = 1, /* most common expected priority */ + PR_PRIORITY_HIGH = 2, /* slightly more aggressive scheduling */ + PR_PRIORITY_URGENT = 3, /* it does little good to have more than one */ + PR_PRIORITY_LAST = 3 /* this is just a placeholder */ +} PRThreadPriority; + +/* +** Create a new thread: +** "type" is the type of thread to create +** "start(arg)" will be invoked as the threads "main" +** "priority" will be created thread's priority +** "scope" will specify whether the thread is local or global +** "state" will specify whether the thread is joinable or not +** "stackSize" the size of the stack, in bytes. The value can be zero +** and then a machine specific stack size will be chosen. +** +** This can return NULL if some kind of error occurs, such as if memory is +** tight. +** +** If you want the thread to start up waiting for the creator to do +** something, enter a lock before creating the thread and then have the +** threads start routine enter and exit the same lock. When you are ready +** for the thread to run, exit the lock. +** +** If you want to detect the completion of the created thread, the thread +** should be created joinable. Then, use PR_JoinThread to synchrnoize the +** termination of another thread. +** +** When the start function returns the thread exits. If it is the last +** PR_USER_THREAD to exit then the process exits. +*/ +NSPR_API(PRThread*) PR_CreateThread(PRThreadType type, + void (PR_CALLBACK *start)(void *arg), + void *arg, + PRThreadPriority priority, + PRThreadScope scope, + PRThreadState state, + PRUint32 stackSize); + +/* +** Wait for thread termination: +** "thread" is the target thread +** +** This can return PR_FAILURE if no joinable thread could be found +** corresponding to the specified target thread. +** +** The calling thread is blocked until the target thread completes. +** Several threads cannot wait for the same thread to complete; one thread +** will operate successfully and others will terminate with an error PR_FAILURE. +** The calling thread will not be blocked if the target thread has already +** terminated. +*/ +NSPR_API(PRStatus) PR_JoinThread(PRThread *thread); + +/* +** Return the current thread object for the currently running code. +** Never returns NULL. +*/ +NSPR_API(PRThread*) PR_GetCurrentThread(void); +#ifndef NO_NSPR_10_SUPPORT +#define PR_CurrentThread() PR_GetCurrentThread() /* for nspr1.0 compat. */ +#endif /* NO_NSPR_10_SUPPORT */ + +/* +** Get the priority of "thread". +*/ +NSPR_API(PRThreadPriority) PR_GetThreadPriority(const PRThread *thread); + +/* +** Change the priority of the "thread" to "priority". +*/ +NSPR_API(void) PR_SetThreadPriority(PRThread *thread, PRThreadPriority priority); + +/* +** This routine returns a new index for per-thread-private data table. +** The index is visible to all threads within a process. This index can +** be used with the PR_SetThreadPrivate() and PR_GetThreadPrivate() routines +** to save and retrieve data associated with the index for a thread. +** +** Each index is associationed with a destructor function ('dtor'). The function +** may be specified as NULL when the index is created. If it is not NULL, the +** function will be called when: +** - the thread exits and the private data for the associated index +** is not NULL, +** - new thread private data is set and the current private data is +** not NULL. +** +** The index independently maintains specific values for each binding thread. +** A thread can only get access to its own thread-specific-data. +** +** Upon a new index return the value associated with the index for all threads +** is NULL, and upon thread creation the value associated with all indices for +** that thread is NULL. +** +** Returns PR_FAILURE if the total number of indices will exceed the maximun +** allowed. +*/ +typedef void (PR_CALLBACK *PRThreadPrivateDTOR)(void *priv); + +NSPR_API(PRStatus) PR_NewThreadPrivateIndex( + PRUintn *newIndex, PRThreadPrivateDTOR destructor); + +/* +** Define some per-thread-private data. +** "tpdIndex" is an index into the per-thread private data table +** "priv" is the per-thread-private data +** +** If the per-thread private data table has a previously registered +** destructor function and a non-NULL per-thread-private data value, +** the destructor function is invoked. +** +** This can return PR_FAILURE if the index is invalid. +*/ +NSPR_API(PRStatus) PR_SetThreadPrivate(PRUintn tpdIndex, void *priv); + +/* +** Recover the per-thread-private data for the current thread. "tpdIndex" is +** the index into the per-thread private data table. +** +** The returned value may be NULL which is indistinguishable from an error +** condition. +** +** A thread can only get access to its own thread-specific-data. +*/ +NSPR_API(void*) PR_GetThreadPrivate(PRUintn tpdIndex); + +/* +** This routine sets the interrupt request for a target thread. The interrupt +** request remains in the thread's state until it is delivered exactly once +** or explicitly canceled. +** +** A thread that has been interrupted will fail all NSPR blocking operations +** that return a PRStatus (I/O, waiting on a condition, etc). +** +** PR_Interrupt may itself fail if the target thread is invalid. +*/ +NSPR_API(PRStatus) PR_Interrupt(PRThread *thread); + +/* +** Clear the interrupt request for the calling thread. If no such request +** is pending, this operation is a noop. +*/ +NSPR_API(void) PR_ClearInterrupt(void); + +/* +** Block the interrupt for the calling thread. +*/ +NSPR_API(void) PR_BlockInterrupt(void); + +/* +** Unblock the interrupt for the calling thread. +*/ +NSPR_API(void) PR_UnblockInterrupt(void); + +/* +** Make the current thread sleep until "ticks" time amount of time +** has expired. If "ticks" is PR_INTERVAL_NO_WAIT then the call is +** equivalent to calling PR_Yield. Calling PR_Sleep with an argument +** equivalent to PR_INTERVAL_NO_TIMEOUT is an error and will result +** in a PR_FAILURE error return. +*/ +NSPR_API(PRStatus) PR_Sleep(PRIntervalTime ticks); + +/* +** Get the scoping of this thread. +*/ +NSPR_API(PRThreadScope) PR_GetThreadScope(const PRThread *thread); + +/* +** Get the type of this thread. +*/ +NSPR_API(PRThreadType) PR_GetThreadType(const PRThread *thread); + +/* +** Get the join state of this thread. +*/ +NSPR_API(PRThreadState) PR_GetThreadState(const PRThread *thread); + +PR_END_EXTERN_C + +#endif /* prthread_h___ */ diff --git a/libsecurity_asn1/lib/prtime.h b/libsecurity_asn1/lib/prtime.h new file mode 100644 index 00000000..0e09f2f3 --- /dev/null +++ b/libsecurity_asn1/lib/prtime.h @@ -0,0 +1,295 @@ +/* -*- 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. + */ + +/* + *---------------------------------------------------------------------- + * + * prtime.h -- + * + * NSPR date and time functions + * + *----------------------------------------------------------------------- + */ + +#ifndef prtime_h___ +#define prtime_h___ + +#include + +PR_BEGIN_EXTERN_C + +/**********************************************************************/ +/************************* TYPES AND CONSTANTS ************************/ +/**********************************************************************/ + +#define PR_MSEC_PER_SEC 1000UL +#define PR_USEC_PER_SEC 1000000UL +#define PR_NSEC_PER_SEC 1000000000UL +#define PR_USEC_PER_MSEC 1000UL +#define PR_NSEC_PER_MSEC 1000000UL + +/* + * PRTime -- + * + * NSPR represents basic time as 64-bit signed integers relative + * to midnight (00:00:00), January 1, 1970 Greenwich Mean Time (GMT). + * (GMT is also known as Coordinated Universal Time, UTC.) + * The units of time are in microseconds. Negative times are allowed + * to represent times prior to the January 1970 epoch. Such values are + * intended to be exported to other systems or converted to human + * readable form. + * + * Notes on porting: PRTime corresponds to time_t in ANSI C. NSPR 1.0 + * simply uses PRInt64. + */ + +typedef PRInt64 PRTime; + +/* + * Time zone and daylight saving time corrections applied to GMT to + * obtain the local time of some geographic location + */ + +typedef struct PRTimeParameters { + PRInt32 tp_gmt_offset; /* the offset from GMT in seconds */ + PRInt32 tp_dst_offset; /* contribution of DST in seconds */ +} PRTimeParameters; + +/* + * PRExplodedTime -- + * + * Time broken down into human-readable components such as year, month, + * day, hour, minute, second, and microsecond. Time zone and daylight + * saving time corrections may be applied. If they are applied, the + * offsets from the GMT must be saved in the 'tm_params' field so that + * all the information is available to reconstruct GMT. + * + * Notes on porting: PRExplodedTime corrresponds to struct tm in + * ANSI C, with the following differences: + * - an additional field tm_usec; + * - replacing tm_isdst by tm_params; + * - the month field is spelled tm_month, not tm_mon; + * - we use absolute year, AD, not the year since 1900. + * The corresponding type in NSPR 1.0 is called PRTime. Below is + * a table of date/time type correspondence in the three APIs: + * API time since epoch time in components + * ANSI C time_t struct tm + * NSPR 1.0 PRInt64 PRTime + * NSPR 2.0 PRTime PRExplodedTime + */ + +typedef struct PRExplodedTime { + PRInt32 tm_usec; /* microseconds past tm_sec (0-99999) */ + PRInt32 tm_sec; /* seconds past tm_min (0-61, accomodating + up to two leap seconds) */ + PRInt32 tm_min; /* minutes past tm_hour (0-59) */ + PRInt32 tm_hour; /* hours past tm_day (0-23) */ + PRInt32 tm_mday; /* days past tm_mon (1-31, note that it + starts from 1) */ + PRInt32 tm_month; /* months past tm_year (0-11, Jan = 0) */ + PRInt16 tm_year; /* absolute year, AD (note that we do not + count from 1900) */ + + PRInt8 tm_wday; /* calculated day of the week + (0-6, Sun = 0) */ + PRInt16 tm_yday; /* calculated day of the year + (0-365, Jan 1 = 0) */ + + PRTimeParameters tm_params; /* time parameters used by conversion */ +} PRExplodedTime; + +/* + * PRTimeParamFn -- + * + * A function of PRTimeParamFn type returns the time zone and + * daylight saving time corrections for some geographic location, + * given the current time in GMT. The input argument gmt should + * point to a PRExplodedTime that is in GMT, i.e., whose + * tm_params contains all 0's. + * + * For any time zone other than GMT, the computation is intended to + * consist of two steps: + * - Figure out the time zone correction, tp_gmt_offset. This number + * usually depends on the geographic location only. But it may + * also depend on the current time. For example, all of China + * is one time zone right now. But this situation may change + * in the future. + * - Figure out the daylight saving time correction, tp_dst_offset. + * This number depends on both the geographic location and the + * current time. Most of the DST rules are expressed in local + * current time. If so, one should apply the time zone correction + * to GMT before applying the DST rules. + */ + +typedef PRTimeParameters (PR_CALLBACK *PRTimeParamFn)(const PRExplodedTime *gmt); + +/**********************************************************************/ +/****************************** FUNCTIONS *****************************/ +/**********************************************************************/ + +/* + * The PR_Now routine returns the current time relative to the + * epoch, midnight, January 1, 1970 UTC. The units of the returned + * value are microseconds since the epoch. + * + * The values returned are not guaranteed to advance in a linear fashion + * due to the application of time correction protocols which synchronize + * computer clocks to some external time source. Consequently it should + * not be depended on for interval timing. + * + * The implementation is machine dependent. + * Cf. time_t time(time_t *tp) in ANSI C. + */ +#if defined(HAVE_WATCOM_BUG_2) +PRTime __pascal __export __loadds +#else +NSPR_API(PRTime) +#endif +PR_Now(void); + +/* + * Expand time binding it to time parameters provided by PRTimeParamFn. + * The calculation is envisoned to proceed in the following steps: + * - From given PRTime, calculate PRExplodedTime in GMT + * - Apply the given PRTimeParamFn to the GMT that we just calculated + * to obtain PRTimeParameters. + * - Add the PRTimeParameters offsets to GMT to get the local time + * as PRExplodedTime. + */ + +NSPR_API(void) PR_ExplodeTime( + PRTime usecs, PRTimeParamFn params, PRExplodedTime *exploded); + +/* Reverse operation of PR_ExplodeTime */ +#if defined(HAVE_WATCOM_BUG_2) +PRTime __pascal __export __loadds +#else +NSPR_API(PRTime) +#endif +PR_ImplodeTime(const PRExplodedTime *exploded); + +/* + * Adjust exploded time to normalize field overflows after manipulation. + * Note that the following fields of PRExplodedTime should not be + * manipulated: + * - tm_month and tm_year: because the number of days in a month and + * number of days in a year are not constant, it is ambiguous to + * manipulate the month and year fields, although one may be tempted + * to. For example, what does "a month from January 31st" mean? + * - tm_wday and tm_yday: these fields are calculated by NSPR. Users + * should treat them as "read-only". + */ + +NSPR_API(void) PR_NormalizeTime( + PRExplodedTime *exploded, PRTimeParamFn params); + +/**********************************************************************/ +/*********************** TIME PARAMETER FUNCTIONS *********************/ +/**********************************************************************/ + +/* Time parameters that suit current host machine */ +NSPR_API(PRTimeParameters) PR_LocalTimeParameters(const PRExplodedTime *gmt); + +/* Time parameters that represent Greenwich Mean Time */ +NSPR_API(PRTimeParameters) PR_GMTParameters(const PRExplodedTime *gmt); + +/* + * Time parameters that represent the US Pacific Time Zone, with the + * current daylight saving time rules (for testing only) + */ +NSPR_API(PRTimeParameters) PR_USPacificTimeParameters(const PRExplodedTime *gmt); + +/* + * This parses a time/date string into a PRTime + * (microseconds after "1-Jan-1970 00:00:00 GMT"). + * It returns PR_SUCCESS on success, and PR_FAILURE + * if the time/date string can't be parsed. + * + * Many formats are handled, including: + * + * 14 Apr 89 03:20:12 + * 14 Apr 89 03:20 GMT + * Fri, 17 Mar 89 4:01:33 + * Fri, 17 Mar 89 4:01 GMT + * Mon Jan 16 16:12 PDT 1989 + * Mon Jan 16 16:12 +0130 1989 + * 6 May 1992 16:41-JST (Wednesday) + * 22-AUG-1993 10:59:12.82 + * 22-AUG-1993 10:59pm + * 22-AUG-1993 12:59am + * 22-AUG-1993 12:59 PM + * Friday, August 04, 1995 3:54 PM + * 06/21/95 04:24:34 PM + * 20/06/95 21:07 + * 95-06-08 19:32:48 EDT + * + * If the input string doesn't contain a description of the timezone, + * we consult the `default_to_gmt' to decide whether the string should + * be interpreted relative to the local time zone (PR_FALSE) or GMT (PR_TRUE). + * The correct value for this argument depends on what standard specified + * the time string which you are parsing. + */ + +NSPR_API(PRStatus) PR_ParseTimeString ( + const char *string, + PRBool default_to_gmt, + PRTime *result); + +/* + * FIXME: should we also have a formatting function, such as asctime, ctime, + * and strftime in standard C library? But this would involve + * internationalization issues. Might want to provide a US English version. + */ + +/**********************************************************************/ +/*********************** OLD COMPATIBILITYFUNCTIONS *******************/ +/**********************************************************************/ +#ifndef NO_NSPR_10_SUPPORT + +/* Format a time value into a buffer. Same semantics as strftime() */ +NSPR_API(PRUint32) PR_FormatTime(char *buf, int buflen, const char *fmt, + const PRExplodedTime *tm); + +/* Format a time value into a buffer. Time is always in US English format, regardless + * of locale setting. + */ +NSPR_API(PRUint32) +PR_FormatTimeUSEnglish( char* buf, PRUint32 bufSize, + const char* format, const PRExplodedTime* tm ); + +#endif /* NO_NSPR_10_SUPPORT */ + +PR_END_EXTERN_C + +#endif /* prtime_h___ */ diff --git a/libsecurity_asn1/lib/prtypes.h b/libsecurity_asn1/lib/prtypes.h new file mode 100644 index 00000000..6c65d0fd --- /dev/null +++ b/libsecurity_asn1/lib/prtypes.h @@ -0,0 +1,560 @@ +/* -*- 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. + */ + +/* +** File: prtypes.h +** Description: Definitions of NSPR's basic types +** +** Prototypes and macros used to make up for deficiencies in ANSI environments +** that we have found. +** +** Since we do not wrap and all the other standard headers, authors +** of portable code will not know in general that they need these definitions. +** Instead of requiring these authors to find the dependent uses in their code +** and take the following steps only in those C files, we take steps once here +** for all C files. +**/ + +#ifndef prtypes_h___ +#define prtypes_h___ + +#ifdef MDCPUCFG +#include MDCPUCFG +#else +#include +#endif + +#include + +/*********************************************************************** +** MACROS: PR_EXTERN +** PR_IMPLEMENT +** DESCRIPTION: +** These are only for externally visible routines and globals. For +** internal routines, just use "extern" for type checking and that +** will not export internal cross-file or forward-declared symbols. +** Define a macro for declaring procedures return types. We use this to +** deal with windoze specific type hackery for DLL definitions. Use +** PR_EXTERN when the prototype for the method is declared. Use +** PR_IMPLEMENT for the implementation of the method. +** +** Example: +** in dowhim.h +** PR_EXTERN( void ) DoWhatIMean( void ); +** in dowhim.c +** PR_IMPLEMENT( void ) DoWhatIMean( void ) { return; } +** +** +***********************************************************************/ +#if defined(WIN32) + +#if defined(__GNUC__) +#undef _declspec +#define _declspec(x) __declspec(x) +#endif + +#define PR_EXPORT(__type) extern _declspec(dllexport) __type +#define PR_EXPORT_DATA(__type) extern _declspec(dllexport) __type +#define PR_IMPORT(__type) _declspec(dllimport) __type +#define PR_IMPORT_DATA(__type) _declspec(dllimport) __type + +#define PR_EXTERN(__type) extern _declspec(dllexport) __type +#define PR_IMPLEMENT(__type) _declspec(dllexport) __type +#define PR_EXTERN_DATA(__type) extern _declspec(dllexport) __type +#define PR_IMPLEMENT_DATA(__type) _declspec(dllexport) __type + +#define PR_CALLBACK +#define PR_CALLBACK_DECL +#define PR_STATIC_CALLBACK(__x) static __x + +#elif defined(XP_BEOS) + +#define PR_EXPORT(__type) extern __declspec(dllexport) __type +#define PR_EXPORT_DATA(__type) extern __declspec(dllexport) __type +#define PR_IMPORT(__type) extern __declspec(dllexport) __type +#define PR_IMPORT_DATA(__type) extern __declspec(dllexport) __type + +#define PR_EXTERN(__type) extern __declspec(dllexport) __type +#define PR_IMPLEMENT(__type) __declspec(dllexport) __type +#define PR_EXTERN_DATA(__type) extern __declspec(dllexport) __type +#define PR_IMPLEMENT_DATA(__type) __declspec(dllexport) __type + +#define PR_CALLBACK +#define PR_CALLBACK_DECL +#define PR_STATIC_CALLBACK(__x) static __x + +#elif defined(WIN16) + +#define PR_CALLBACK_DECL __cdecl + +#if defined(_WINDLL) +#define PR_EXPORT(__type) extern __type _cdecl _export _loadds +#define PR_IMPORT(__type) extern __type _cdecl _export _loadds +#define PR_EXPORT_DATA(__type) extern __type _export +#define PR_IMPORT_DATA(__type) extern __type _export + +#define PR_EXTERN(__type) extern __type _cdecl _export _loadds +#define PR_IMPLEMENT(__type) __type _cdecl _export _loadds +#define PR_EXTERN_DATA(__type) extern __type _export +#define PR_IMPLEMENT_DATA(__type) __type _export + +#define PR_CALLBACK __cdecl __loadds +#define PR_STATIC_CALLBACK(__x) static __x PR_CALLBACK + +#else /* this must be .EXE */ +#define PR_EXPORT(__type) extern __type _cdecl _export +#define PR_IMPORT(__type) extern __type _cdecl _export +#define PR_EXPORT_DATA(__type) extern __type _export +#define PR_IMPORT_DATA(__type) extern __type _export + +#define PR_EXTERN(__type) extern __type _cdecl _export +#define PR_IMPLEMENT(__type) __type _cdecl _export +#define PR_EXTERN_DATA(__type) extern __type _export +#define PR_IMPLEMENT_DATA(__type) __type _export + +#define PR_CALLBACK __cdecl __loadds +#define PR_STATIC_CALLBACK(__x) __x PR_CALLBACK +#endif /* _WINDLL */ + +#elif defined(XP_MAC) + + #if defined __GNUC__ + /* Darwin */ + #define PR_EXPORT(__type) extern __type + #define PR_EXPORT_DATA(__type) extern __type + #define PR_IMPORT(__type) extern __type + #define PR_IMPORT_DATA(__type) extern __type + + #define PR_EXTERN(__type) extern __type + #define PR_IMPLEMENT(__type) __type + #define PR_EXTERN_DATA(__type) extern __type + #define PR_IMPLEMENT_DATA(__type) __type + #define PR_CALLBACK + #define PR_CALLBACK_DECL + #define PR_STATIC_CALLBACK(__x) static __x + + #else + /* MacOS 9 */ + #define PR_EXPORT(__type) extern __declspec(export) __type + #define PR_EXPORT_DATA(__type) extern __declspec(export) __type + #define PR_IMPORT(__type) extern __declspec(export) __type + #define PR_IMPORT_DATA(__type) extern __declspec(export) __type + + #define PR_EXTERN(__type) extern __declspec(export) __type + #define PR_IMPLEMENT(__type) __declspec(export) __type + #define PR_EXTERN_DATA(__type) extern __declspec(export) __type + #define PR_IMPLEMENT_DATA(__type) __declspec(export) __type + + #define PR_CALLBACK + #define PR_CALLBACK_DECL + #define PR_STATIC_CALLBACK(__x) static __x + #endif /* __GNUC__ */ +#elif defined(XP_OS2_VACPP) + +#define PR_EXPORT(__type) extern __type +#define PR_EXPORT_DATA(__type) extern __type +#define PR_IMPORT(__type) extern __type +#define PR_IMPORT_DATA(__type) extern __type + +#define PR_EXTERN(__type) extern __type +#define PR_IMPLEMENT(__type) __type +#define PR_EXTERN_DATA(__type) extern __type +#define PR_IMPLEMENT_DATA(__type) __type +#define PR_CALLBACK _Optlink +#define PR_CALLBACK_DECL +#define PR_STATIC_CALLBACK(__x) static __x PR_CALLBACK + +#else /* Unix */ + +#define PR_EXPORT(__type) extern __type +#define PR_EXPORT_DATA(__type) extern __type +#define PR_IMPORT(__type) extern __type +#define PR_IMPORT_DATA(__type) extern __type + +#define PR_EXTERN(__type) extern __type +#define PR_IMPLEMENT(__type) __type +#define PR_EXTERN_DATA(__type) extern __type +#define PR_IMPLEMENT_DATA(__type) __type +#define PR_CALLBACK +#define PR_CALLBACK_DECL +#define PR_STATIC_CALLBACK(__x) static __x + +#endif + +#if defined(_NSPR_BUILD_) +#define NSPR_API(__type) PR_EXPORT(__type) +#define NSPR_DATA_API(__type) PR_EXPORT_DATA(__type) +#else +#define NSPR_API(__type) PR_IMPORT(__type) +#define NSPR_DATA_API(__type) PR_IMPORT_DATA(__type) +#endif + +/*********************************************************************** +** MACROS: PR_BEGIN_MACRO +** PR_END_MACRO +** DESCRIPTION: +** Macro body brackets so that macros with compound statement definitions +** behave syntactically more like functions when called. +***********************************************************************/ +#define PR_BEGIN_MACRO do { +#define PR_END_MACRO } while (0) + +/*********************************************************************** +** MACROS: PR_BEGIN_EXTERN_C +** PR_END_EXTERN_C +** DESCRIPTION: +** Macro shorthands for conditional C++ extern block delimiters. +***********************************************************************/ +#ifdef __cplusplus +#define PR_BEGIN_EXTERN_C extern "C" { +#define PR_END_EXTERN_C } +#else +#define PR_BEGIN_EXTERN_C +#define PR_END_EXTERN_C +#endif + +/*********************************************************************** +** MACROS: PR_BIT +** PR_BITMASK +** DESCRIPTION: +** Bit masking macros. XXX n must be <= 31 to be portable +***********************************************************************/ +#define PR_BIT(n) ((PRUint32)1 << (n)) +#define PR_BITMASK(n) (PR_BIT(n) - 1) + +/*********************************************************************** +** MACROS: PR_ROUNDUP +** PR_MIN +** PR_MAX +** PR_ABS +** DESCRIPTION: +** Commonly used macros for operations on compatible types. +***********************************************************************/ +#define PR_ROUNDUP(x,y) ((((x)+((y)-1))/(y))*(y)) +#define PR_MIN(x,y) ((x)<(y)?(x):(y)) +#define PR_MAX(x,y) ((x)>(y)?(x):(y)) +#define PR_ABS(x) ((x)<0?-(x):(x)) + +PR_BEGIN_EXTERN_C + +/************************************************************************ +** TYPES: PRUint8 +** PRInt8 +** DESCRIPTION: +** The int8 types are known to be 8 bits each. There is no type that +** is equivalent to a plain "char". +************************************************************************/ +#if PR_BYTES_PER_BYTE == 1 +typedef unsigned char PRUint8; +/* +** Some cfront-based C++ compilers do not like 'signed char' and +** issue the warning message: +** warning: "signed" not implemented (ignored) +** For these compilers, we have to define PRInt8 as plain 'char'. +** Make sure that plain 'char' is indeed signed under these compilers. +*/ +#if (defined(HPUX) && defined(__cplusplus) \ + && !defined(__GNUC__) && __cplusplus < 199707L) \ + || (defined(SCO) && defined(__cplusplus) \ + && !defined(__GNUC__) && __cplusplus == 1L) +typedef char PRInt8; +#else +typedef signed char PRInt8; +#endif +#else +#error No suitable type for PRInt8/PRUint8 +#endif + +/************************************************************************ + * MACROS: PR_INT8_MAX + * PR_INT8_MIN + * PR_UINT8_MAX + * DESCRIPTION: + * The maximum and minimum values of a PRInt8 or PRUint8. +************************************************************************/ + +#define PR_INT8_MAX 127 +#define PR_INT8_MIN (-128) +#define PR_UINT8_MAX 255U + +/************************************************************************ +** TYPES: PRUint16 +** PRInt16 +** DESCRIPTION: +** The int16 types are known to be 16 bits each. +************************************************************************/ +#if PR_BYTES_PER_SHORT == 2 +typedef unsigned short PRUint16; +typedef short PRInt16; +#else +#error No suitable type for PRInt16/PRUint16 +#endif + +/************************************************************************ + * MACROS: PR_INT16_MAX + * PR_INT16_MIN + * PR_UINT16_MAX + * DESCRIPTION: + * The maximum and minimum values of a PRInt16 or PRUint16. +************************************************************************/ + +#define PR_INT16_MAX 32767 +#define PR_INT16_MIN (-32768) +#define PR_UINT16_MAX 65535U + +/************************************************************************ +** TYPES: PRUint32 +** PRInt32 +** DESCRIPTION: +** The int32 types are known to be 32 bits each. +************************************************************************/ +#if PR_BYTES_PER_INT == 4 +typedef unsigned int PRUint32; +typedef int PRInt32; +#define PR_INT32(x) x +#define PR_UINT32(x) x ## U +#elif PR_BYTES_PER_LONG == 4 +typedef unsigned long PRUint32; +typedef long PRInt32; +#define PR_INT32(x) x ## L +#define PR_UINT32(x) x ## UL +#else +#error No suitable type for PRInt32/PRUint32 +#endif + +/************************************************************************ + * MACROS: PR_INT32_MAX + * PR_INT32_MIN + * PR_UINT32_MAX + * DESCRIPTION: + * The maximum and minimum values of a PRInt32 or PRUint32. +************************************************************************/ + +#define PR_INT32_MAX PR_INT32(2147483647) +#define PR_INT32_MIN (-PR_INT32_MAX - 1) +#define PR_UINT32_MAX PR_UINT32(4294967295) + +/************************************************************************ +** TYPES: PRUint64 +** PRInt64 +** DESCRIPTION: +** The int64 types are known to be 64 bits each. Care must be used when +** declaring variables of type PRUint64 or PRInt64. Different hardware +** architectures and even different compilers have varying support for +** 64 bit values. The only guaranteed portability requires the use of +** the LL_ macros (see prlong.h). +************************************************************************/ +#ifdef HAVE_LONG_LONG +#if PR_BYTES_PER_LONG == 8 +typedef long PRInt64; +typedef unsigned long PRUint64; +#elif defined(WIN16) +typedef __int64 PRInt64; +typedef unsigned __int64 PRUint64; +#elif defined(WIN32) && !defined(__GNUC__) +typedef __int64 PRInt64; +typedef unsigned __int64 PRUint64; +#else +typedef long long PRInt64; +typedef unsigned long long PRUint64; +#endif /* PR_BYTES_PER_LONG == 8 */ +#else /* !HAVE_LONG_LONG */ +typedef struct { +#ifdef IS_LITTLE_ENDIAN + PRUint32 lo, hi; +#else + PRUint32 hi, lo; +#endif +} PRInt64; +typedef PRInt64 PRUint64; +#endif /* !HAVE_LONG_LONG */ + +/************************************************************************ +** TYPES: PRUintn +** PRIntn +** DESCRIPTION: +** The PRIntn types are most appropriate for automatic variables. They are +** guaranteed to be at least 16 bits, though various architectures may +** define them to be wider (e.g., 32 or even 64 bits). These types are +** never valid for fields of a structure. +************************************************************************/ +#if PR_BYTES_PER_INT >= 2 +typedef int PRIntn; +typedef unsigned int PRUintn; +#else +#error 'sizeof(int)' not sufficient for platform use +#endif + +/************************************************************************ +** TYPES: PRFloat64 +** DESCRIPTION: +** NSPR's floating point type is always 64 bits. +************************************************************************/ +typedef double PRFloat64; + +/************************************************************************ +** TYPES: PRSize +** DESCRIPTION: +** A type for representing the size of objects. +************************************************************************/ +typedef size_t PRSize; + + +/************************************************************************ +** TYPES: PROffset32, PROffset64 +** DESCRIPTION: +** A type for representing byte offsets from some location. +************************************************************************/ +typedef PRInt32 PROffset32; +typedef PRInt64 PROffset64; + +/************************************************************************ +** TYPES: PRPtrDiff +** DESCRIPTION: +** A type for pointer difference. Variables of this type are suitable +** for storing a pointer or pointer sutraction. +************************************************************************/ +typedef ptrdiff_t PRPtrdiff; + +/************************************************************************ +** TYPES: PRUptrdiff +** DESCRIPTION: +** A type for pointer difference. Variables of this type are suitable +** for storing a pointer or pointer sutraction. +************************************************************************/ +typedef unsigned long PRUptrdiff; + +/************************************************************************ +** TYPES: PRBool +** DESCRIPTION: +** Use PRBool for variables and parameter types. Use PR_FALSE and PR_TRUE +** for clarity of target type in assignments and actual arguments. Use +** 'if (bool)', 'while (!bool)', '(bool) ? x : y' etc., to test booleans +** juast as you would C int-valued conditions. +************************************************************************/ +typedef PRIntn PRBool; +#define PR_TRUE 1 +#define PR_FALSE 0 + +/************************************************************************ +** TYPES: PRPackedBool +** DESCRIPTION: +** Use PRPackedBOol within structs where bitfields are not desireable +** but minimum and consistant overhead matters. +************************************************************************/ +typedef PRUint8 PRPackedBool; + +/* +** Status code used by some routines that have a single point of failure or +** special status return. +*/ +typedef enum { PR_FAILURE = -1, PR_SUCCESS = 0 } PRStatus; + +#ifdef MOZ_UNICODE +/* + * EXPERIMENTAL: This type may be removed in a future release. + */ +#ifndef __PRUNICHAR__ +#define __PRUNICHAR__ +#if defined(WIN32) || defined(XP_MAC) +typedef wchar_t PRUnichar; +#else +typedef PRUint16 PRUnichar; +#endif +#endif +#endif /* MOZ_UNICODE */ + +/* +** WARNING: The undocumented data types PRWord and PRUword are +** only used in the garbage collection and arena code. Do not +** use PRWord and PRUword in new code. +** +** A PRWord is an integer that is the same size as a void*. +** It implements the notion of a "word" in the Java Virtual +** Machine. (See Sec. 3.4 "Words", The Java Virtual Machine +** Specification, Addison-Wesley, September 1996. +** http://java.sun.com/docs/books/vmspec/index.html.) +*/ +typedef long PRWord; +typedef size_t PRUword; + +#if defined(NO_NSPR_10_SUPPORT) +#else +/********* ???????????????? FIX ME ??????????????????????????? *****/ +/********************** Some old definitions until pr=>ds transition is done ***/ +/********************** Also, we are still using NSPR 1.0. GC ******************/ +/* +** Fundamental NSPR macros, used nearly everywhere. +*/ + +#define PR_PUBLIC_API PR_IMPLEMENT + +/* +** Macro body brackets so that macros with compound statement definitions +** behave syntactically more like functions when called. +*/ +#define NSPR_BEGIN_MACRO do { +#define NSPR_END_MACRO } while (0) + +/* +** Macro shorthands for conditional C++ extern block delimiters. +*/ +#ifdef NSPR_BEGIN_EXTERN_C +#undef NSPR_BEGIN_EXTERN_C +#endif +#ifdef NSPR_END_EXTERN_C +#undef NSPR_END_EXTERN_C +#endif + +#ifdef __cplusplus +#define NSPR_BEGIN_EXTERN_C extern "C" { +#define NSPR_END_EXTERN_C } +#else +#define NSPR_BEGIN_EXTERN_C +#define NSPR_END_EXTERN_C +#endif + +#ifdef XP_MAC +#include "protypes.h" +#else +#include "obsolete/protypes.h" +#endif + +/********* ????????????? End Fix me ?????????????????????????????? *****/ +#endif /* NO_NSPR_10_SUPPORT */ + +PR_END_EXTERN_C + +#endif /* prtypes_h___ */ + diff --git a/libsecurity_asn1/lib/prvrsion.h b/libsecurity_asn1/lib/prvrsion.h new file mode 100644 index 00000000..3bb3b144 --- /dev/null +++ b/libsecurity_asn1/lib/prvrsion.h @@ -0,0 +1,134 @@ +/* -*- 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. + */ + + +/* author: jstewart */ + +#if defined(_PRVERSION_H) +#else +#define _PRVERSION_H + +#include + +PR_BEGIN_EXTERN_C + +/* All components participating in the PR version protocol must expose + * a structure and a function. The structure is defined below and named + * according to the naming conventions outlined further below. The function + * is called libVersionPoint and returns a pointer to this structure. + */ + +/* on NT, always pack the structure the same. */ +#ifdef _WIN32 +#pragma pack(push, 8) +#endif + +typedef struct { + /* + * The first field defines which version of this structure is in use. + * At this time, only version 2 is specified. If this value is not + * 2, you must read no further into the structure. + */ + PRInt32 version; + + /* for Version 2, this is the body format. */ + PRInt64 buildTime; /* 64 bits - usecs since midnight, 1/1/1970 */ + char * buildTimeString;/* a human readable version of the time */ + + PRUint8 vMajor; /* Major version of this component */ + PRUint8 vMinor; /* Minor version of this component */ + PRUint8 vPatch; /* Patch level of this component */ + + PRBool beta; /* true if this is a beta component */ + PRBool debug; /* true if this is a debug component */ + PRBool special; /* true if this component is a special build */ + + char * filename; /* The original filename */ + char * description; /* description of this component */ + char * security; /* level of security in this component */ + char * copyright; /* The copyright for this file */ + char * comment; /* free form field for misc usage */ + char * specialString; /* the special variant for this build */ +} PRVersionDescription; + +/* on NT, restore the previous packing */ +#ifdef _WIN32 +#pragma pack(pop) +#endif + +/* + * All components must define an entrypoint named libVersionPoint which + * is of type versionEntryPointType. + * + * For example, for a library named libfoo, we would have: + * + * PRVersionDescription prVersionDescription_libfoo = + * { + * ... + * }; + * + * PR_IMPLEMENT(const PRVersionDescription*) libVersionPoint(void) + * { + * return &prVersionDescription_libfoo; + * } + */ +typedef const PRVersionDescription *(*versionEntryPointType)(void); + +/* + * Where you declare your libVersionPoint, do it like this: + * PR_IMPLEMENT(const PRVersionDescription *) libVersionPoint(void) { + * fill it in... + * } + */ + +/* + * NAMING CONVENTION FOR struct + * + * all components should also expose a static PRVersionDescription + * The name of the struct should be calculated as follows: + * Take the value of filename. (If filename is not specified, calculate + * a short, unique string.) Convert all non-alphanumeric characters + * to '_'. To this, prepend "PRVersionDescription_". Thus for libfoo.so, + * the symbol name is "PRVersionDescription_libfoo_so". + * so the file should have + * PRVersionDescription PRVersionDescription_libfoo_so { fill it in }; + * on NT, this file should be declspec export. + */ + +PR_END_EXTERN_C + +#endif /* defined(_PRVERSION_H) */ + +/* prvrsion.h */ + diff --git a/libsecurity_asn1/lib/secErrorStr.c b/libsecurity_asn1/lib/secErrorStr.c new file mode 100644 index 00000000..482edaa1 --- /dev/null +++ b/libsecurity_asn1/lib/secErrorStr.c @@ -0,0 +1,208 @@ +/* + * 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@ + * + * secErrorStr.c - ASCII string version of NSS Sec layer error codes + */ +#include "secerr.h" +#include + +typedef struct { + PRErrorCode value; + const char *name; +} SecErrorNameValuePair; + +/* one entry in an array of SecErrorNameValuePairs */ +#define SNVP(err) {err, #err} + +/* the NULL entry which terminates the SecErrorNameValuePair list */ +#define SNVP_END {0, NULL} + +static const SecErrorNameValuePair errValues[] = +{ + /* FIXME: we really don't need all of these, but they're not + * compiled for NDEBUG builds. */ + #ifndef NDEBUG + SNVP(SEC_ERROR_IO), + SNVP(SEC_ERROR_LIBRARY_FAILURE), + SNVP(SEC_ERROR_BAD_DATA ), + SNVP(SEC_ERROR_OUTPUT_LEN), + SNVP(SEC_ERROR_INPUT_LEN), + SNVP(SEC_ERROR_INVALID_ARGS), + SNVP(SEC_ERROR_INVALID_ALGORITHM), + SNVP(SEC_ERROR_INVALID_AVA), + SNVP(SEC_ERROR_INVALID_TIME), + SNVP(SEC_ERROR_BAD_DER), + SNVP(SEC_ERROR_BAD_SIGNATURE ), + SNVP(SEC_ERROR_EXPIRED_CERTIFICATE), + SNVP(SEC_ERROR_REVOKED_CERTIFICATE), + SNVP(SEC_ERROR_UNKNOWN_ISSUER ), + SNVP(SEC_ERROR_BAD_KEY), + SNVP(SEC_ERROR_BAD_PASSWORD), + SNVP(SEC_ERROR_RETRY_PASSWORD), + SNVP(SEC_ERROR_NO_NODELOCK ), + SNVP(SEC_ERROR_BAD_DATABASE), + SNVP(SEC_ERROR_NO_MEMORY), + SNVP(SEC_ERROR_UNTRUSTED_ISSUER), + SNVP(SEC_ERROR_UNTRUSTED_CERT), + SNVP(SEC_ERROR_DUPLICATE_CERT), + SNVP(SEC_ERROR_DUPLICATE_CERT_NAME), + SNVP(SEC_ERROR_ADDING_CERT), + SNVP(SEC_ERROR_FILING_KEY), + SNVP(SEC_ERROR_NO_KEY), + SNVP(SEC_ERROR_CERT_VALID), + SNVP(SEC_ERROR_CERT_NOT_VALID), + SNVP(SEC_ERROR_CERT_NO_RESPONSE), + SNVP(SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE), + SNVP(SEC_ERROR_CRL_EXPIRED), + SNVP(SEC_ERROR_CRL_BAD_SIGNATURE), + SNVP(SEC_ERROR_CRL_INVALID), + SNVP(SEC_ERROR_EXTENSION_VALUE_INVALID), + SNVP(SEC_ERROR_EXTENSION_NOT_FOUND), + SNVP(SEC_ERROR_CA_CERT_INVALID), + SNVP(SEC_ERROR_PATH_LEN_CONSTRAINT_INVALID), + SNVP(SEC_ERROR_CERT_USAGES_INVALID), + SNVP(SEC_INTERNAL_ONLY), + SNVP(SEC_ERROR_INVALID_KEY), + SNVP(SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION), + SNVP(SEC_ERROR_OLD_CRL), + SNVP(SEC_ERROR_NO_EMAIL_CERT), + SNVP(SEC_ERROR_NO_RECIPIENT_CERTS_QUERY), + SNVP(SEC_ERROR_NOT_A_RECIPIENT), + SNVP(SEC_ERROR_PKCS7_KEYALG_MISMATCH), + SNVP(SEC_ERROR_PKCS7_BAD_SIGNATURE), + SNVP(SEC_ERROR_UNSUPPORTED_KEYALG), + SNVP(SEC_ERROR_DECRYPTION_DISALLOWED), + SNVP(XP_SEC_FORTEZZA_BAD_CARD), + SNVP(XP_SEC_FORTEZZA_NO_CARD), + SNVP(XP_SEC_FORTEZZA_NONE_SELECTED ), + SNVP(XP_SEC_FORTEZZA_MORE_INFO ), + SNVP(XP_SEC_FORTEZZA_PERSON_NOT_FOUND ), + SNVP(XP_SEC_FORTEZZA_NO_MORE_INFO), + SNVP(XP_SEC_FORTEZZA_BAD_PIN), + SNVP(XP_SEC_FORTEZZA_PERSON_ERROR), + SNVP(SEC_ERROR_NO_KRL), + SNVP(SEC_ERROR_KRL_EXPIRED), + SNVP(SEC_ERROR_KRL_BAD_SIGNATURE), + SNVP(SEC_ERROR_REVOKED_KEY ), + SNVP(SEC_ERROR_KRL_INVALID), + SNVP(SEC_ERROR_NEED_RANDOM), + SNVP(SEC_ERROR_NO_MODULE), + SNVP(SEC_ERROR_NO_TOKEN), + SNVP(SEC_ERROR_READ_ONLY), + SNVP(SEC_ERROR_NO_SLOT_SELECTED), + SNVP(SEC_ERROR_CERT_NICKNAME_COLLISION), + SNVP(SEC_ERROR_KEY_NICKNAME_COLLISION), + SNVP(SEC_ERROR_SAFE_NOT_CREATED), + SNVP(SEC_ERROR_BAGGAGE_NOT_CREATED), + SNVP(XP_JAVA_REMOVE_PRINCIPAL_ERROR), + SNVP(XP_JAVA_DELETE_PRIVILEGE_ERROR), + SNVP(XP_JAVA_CERT_NOT_EXISTS_ERROR ), + SNVP(SEC_ERROR_BAD_EXPORT_ALGORITHM), + SNVP(SEC_ERROR_EXPORTING_CERTIFICATES), + SNVP(SEC_ERROR_IMPORTING_CERTIFICATES), + SNVP(SEC_ERROR_PKCS12_DECODING_PFX), + SNVP(SEC_ERROR_PKCS12_INVALID_MAC), + SNVP(SEC_ERROR_PKCS12_UNSUPPORTED_MAC_ALGORITHM), + SNVP(SEC_ERROR_PKCS12_UNSUPPORTED_TRANSPORT_MODE), + SNVP(SEC_ERROR_PKCS12_CORRUPT_PFX_STRUCTURE), + SNVP(SEC_ERROR_PKCS12_UNSUPPORTED_PBE_ALGORITHM), + SNVP(SEC_ERROR_PKCS12_UNSUPPORTED_VERSION ), + SNVP(SEC_ERROR_PKCS12_PRIVACY_PASSWORD_INCORRECT), + SNVP(SEC_ERROR_PKCS12_CERT_COLLISION), + SNVP(SEC_ERROR_USER_CANCELLED), + SNVP(SEC_ERROR_PKCS12_DUPLICATE_DATA), + SNVP(SEC_ERROR_MESSAGE_SEND_ABORTED), + SNVP(SEC_ERROR_INADEQUATE_KEY_USAGE), + SNVP(SEC_ERROR_INADEQUATE_CERT_TYPE), + SNVP(SEC_ERROR_CERT_ADDR_MISMATCH), + SNVP(SEC_ERROR_PKCS12_UNABLE_TO_IMPORT_KEY), + SNVP(SEC_ERROR_PKCS12_IMPORTING_CERT_CHAIN), + SNVP(SEC_ERROR_PKCS12_UNABLE_TO_LOCATE_OBJECT_BY_NAME), + SNVP(SEC_ERROR_PKCS12_UNABLE_TO_EXPORT_KEY), + SNVP(SEC_ERROR_PKCS12_UNABLE_TO_WRITE), + SNVP(SEC_ERROR_PKCS12_UNABLE_TO_READ), + SNVP(SEC_ERROR_PKCS12_KEY_DATABASE_NOT_INITIALIZED), + SNVP(SEC_ERROR_KEYGEN_FAIL), + SNVP(SEC_ERROR_INVALID_PASSWORD), + SNVP(SEC_ERROR_RETRY_OLD_PASSWORD), + SNVP(SEC_ERROR_BAD_NICKNAME), + SNVP(SEC_ERROR_NOT_FORTEZZA_ISSUER), + SNVP(SEC_ERROR_CANNOT_MOVE_SENSITIVE_KEY), + SNVP(SEC_ERROR_JS_INVALID_MODULE_NAME), + SNVP(SEC_ERROR_JS_INVALID_DLL), + SNVP(SEC_ERROR_JS_ADD_MOD_FAILURE), + SNVP(SEC_ERROR_JS_DEL_MOD_FAILURE), + SNVP(SEC_ERROR_OLD_KRL), + SNVP(SEC_ERROR_CKL_CONFLICT), + SNVP(SEC_ERROR_CERT_NOT_IN_NAME_SPACE), + SNVP(SEC_ERROR_KRL_NOT_YET_VALID), + SNVP(SEC_ERROR_CRL_NOT_YET_VALID), + SNVP(SEC_ERROR_UNKNOWN_CERT), + SNVP(SEC_ERROR_UNKNOWN_SIGNER), + SNVP(SEC_ERROR_CERT_BAD_ACCESS_LOCATION ), + SNVP(SEC_ERROR_OCSP_UNKNOWN_RESPONSE_TYPE), + SNVP(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE), + SNVP(SEC_ERROR_OCSP_MALFORMED_REQUEST), + SNVP(SEC_ERROR_OCSP_SERVER_ERROR), + SNVP(SEC_ERROR_OCSP_TRY_SERVER_LATER), + SNVP(SEC_ERROR_OCSP_REQUEST_NEEDS_SIG), + SNVP(SEC_ERROR_OCSP_UNAUTHORIZED_REQUEST), + SNVP(SEC_ERROR_OCSP_UNKNOWN_RESPONSE_STATUS), + SNVP(SEC_ERROR_OCSP_UNKNOWN_CERT), + SNVP(SEC_ERROR_OCSP_NOT_ENABLED), + SNVP(SEC_ERROR_OCSP_NO_DEFAULT_RESPONDER), + SNVP(SEC_ERROR_OCSP_MALFORMED_RESPONSE ), + SNVP(SEC_ERROR_OCSP_UNAUTHORIZED_RESPONSE), + SNVP(SEC_ERROR_OCSP_FUTURE_RESPONSE ), + SNVP(SEC_ERROR_OCSP_OLD_RESPONSE), + SNVP(SEC_ERROR_DIGEST_NOT_FOUND), + SNVP(SEC_ERROR_UNSUPPORTED_MESSAGE_TYPE), + SNVP(SEC_ERROR_MODULE_STUCK), + SNVP(SEC_ERROR_BAD_TEMPLATE), + SNVP(SEC_ERROR_CRL_NOT_FOUND), + SNVP(SEC_ERROR_REUSED_ISSUER_AND_SERIAL ), + SNVP(SEC_ERROR_BUSY), + #endif /* NDEBUG */ + SNVP_END +}; + +/* + * Given a PRErrorCode, obtain a const C string. Not copied, not + * to be freed by caller. + */ +const char *SECErrorString(PRErrorCode err) +{ + static char badStr[100]; + const SecErrorNameValuePair *nvp = errValues; + + while(nvp->name != NULL) { + if(nvp->value == err) { + return nvp->name; + } + nvp++; + } + + /* Not found, not thread safe */ + sprintf(badStr, "UNKNOWN (%d(d)", err); + return badStr; + +} diff --git a/libsecurity_asn1/lib/secasn1.h b/libsecurity_asn1/lib/secasn1.h new file mode 100644 index 00000000..6ff361f2 --- /dev/null +++ b/libsecurity_asn1/lib/secasn1.h @@ -0,0 +1,219 @@ +/* + * 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 for encoding/decoding of ASN.1 using BER/DER (Basic/Distinguished + * Encoding Rules). The routines are found in and used extensively by the + * security library, but exported for other use. + * + * $Id: secasn1.h,v 1.8 2004/05/13 15:29:13 dmitch Exp $ + */ + +#ifndef _SECASN1_H_ +#define _SECASN1_H_ + +#include + +#include +#include +#include + + +/************************************************************************/ +SEC_BEGIN_PROTOS + +/* + * XXX These function prototypes need full, explanatory comments. + */ + +/* +** Decoding. +*/ + +extern SEC_ASN1DecoderContext *SEC_ASN1DecoderStart(PRArenaPool *pool, + void *dest, + const SecAsn1Template *t, + /* + * __APPLE__ addenda: + * + * Only needed if first element will + * be SEC_ASN1_DYNAMIC + */ + const char *buf); + +/* XXX char or unsigned char? */ +extern SECStatus SEC_ASN1DecoderUpdate(SEC_ASN1DecoderContext *cx, + const char *buf, + size_t len); + +extern SECStatus SEC_ASN1DecoderFinish(SEC_ASN1DecoderContext *cx); + +/* Higher level code detected an error, abort the rest of the processing */ +extern void SEC_ASN1DecoderAbort(SEC_ASN1DecoderContext *cx, int error); + +extern void SEC_ASN1DecoderSetFilterProc(SEC_ASN1DecoderContext *cx, + SEC_ASN1WriteProc fn, + void *arg, PRBool no_store); + +extern void SEC_ASN1DecoderClearFilterProc(SEC_ASN1DecoderContext *cx); + +extern void SEC_ASN1DecoderSetNotifyProc(SEC_ASN1DecoderContext *cx, + SEC_ASN1NotifyProc fn, + void *arg); + +extern void SEC_ASN1DecoderClearNotifyProc(SEC_ASN1DecoderContext *cx); + +extern SECStatus SEC_ASN1Decode(PRArenaPool *pool, void *dest, + const SecAsn1Template *t, + const char *buf, size_t len); + +extern SECStatus SEC_ASN1DecodeItem(PRArenaPool *pool, void *dest, + const SecAsn1Template *t, + const SecAsn1Item *item); + +extern SECStatus SEC_QuickDERDecodeItem(PRArenaPool* arena, void* dest, + const SecAsn1Template* templateEntry, + SecAsn1Item* src); + +/* +** Encoding. +*/ + +extern SEC_ASN1EncoderContext *SEC_ASN1EncoderStart(const void *src, + const SecAsn1Template *t, + SEC_ASN1WriteProc fn, + void *output_arg); + +/* XXX char or unsigned char? */ +extern SECStatus SEC_ASN1EncoderUpdate(SEC_ASN1EncoderContext *cx, + const char *buf, + unsigned long len); + +extern void SEC_ASN1EncoderFinish(SEC_ASN1EncoderContext *cx); + +/* Higher level code detected an error, abort the rest of the processing */ +extern void SEC_ASN1EncoderAbort(SEC_ASN1EncoderContext *cx, int error); + +extern void SEC_ASN1EncoderSetNotifyProc(SEC_ASN1EncoderContext *cx, + SEC_ASN1NotifyProc fn, + void *arg); + +extern void SEC_ASN1EncoderClearNotifyProc(SEC_ASN1EncoderContext *cx); + +extern void SEC_ASN1EncoderSetStreaming(SEC_ASN1EncoderContext *cx); + +extern void SEC_ASN1EncoderClearStreaming(SEC_ASN1EncoderContext *cx); + +extern void sec_ASN1EncoderSetDER(SEC_ASN1EncoderContext *cx); + +extern void sec_ASN1EncoderClearDER(SEC_ASN1EncoderContext *cx); + +extern void SEC_ASN1EncoderSetTakeFromBuf(SEC_ASN1EncoderContext *cx); + +extern void SEC_ASN1EncoderClearTakeFromBuf(SEC_ASN1EncoderContext *cx); + +extern SECStatus SEC_ASN1Encode(const void *src, + const SecAsn1Template *t, + SEC_ASN1WriteProc output_proc, + void *output_arg); + +extern SecAsn1Item * SEC_ASN1EncodeItem(PRArenaPool *pool, SecAsn1Item *dest, + const void *src, const SecAsn1Template *t); + +extern SecAsn1Item * SEC_ASN1EncodeInteger(PRArenaPool *pool, + SecAsn1Item *dest, long value); + +extern SecAsn1Item * SEC_ASN1EncodeUnsignedInteger(PRArenaPool *pool, + SecAsn1Item *dest, + unsigned long value); + +extern SECStatus SEC_ASN1DecodeInteger(SecAsn1Item *src, + unsigned long *value); + +/* +** Utilities. +*/ + +/* + * We have a length that needs to be encoded; how many bytes will the + * encoding take? + */ +extern int SEC_ASN1LengthLength (unsigned long len); + +/* encode the length and return the number of bytes we encoded. Buffer + * must be pre allocated */ +extern int SEC_ASN1EncodeLength(unsigned char *buf,unsigned long value); + +/* + * Find the appropriate subtemplate for the given template. + * This may involve calling a "chooser" function, or it may just + * be right there. In either case, it is expected to *have* a + * subtemplate; this is asserted in debug builds (in non-debug + * builds, NULL will be returned). + * + * "thing" is a pointer to the structure being encoded/decoded + * "encoding", when true, means that we are in the process of encoding + * (as opposed to in the process of decoding) + */ +extern const SecAsn1Template * +SEC_ASN1GetSubtemplate ( + const SecAsn1Template *inTemplate, + void *thing, + PRBool encoding, + const char *buf); /* __APPLE__ addenda: for decode only */ + +extern SecAsn1Item *sec_asn1e_allocate_item ( + PRArenaPool *poolp, + SecAsn1Item *dest, + unsigned long len); + +/* + * These two are exported for use by SecNssEncodeItem() + */ +extern void sec_asn1e_encode_item_count ( + void *arg, + const char *buf, + size_t len, + int depth, + SEC_ASN1EncodingPart data_kind); + +extern void sec_asn1e_encode_item_store ( + void *arg, + const char *buf, + size_t len, + int depth, + SEC_ASN1EncodingPart data_kind); + + +SEC_END_PROTOS +#endif /* _SECASN1_H_ */ diff --git a/libsecurity_asn1/lib/secasn1d.c b/libsecurity_asn1/lib/secasn1d.c new file mode 100644 index 00000000..8f20af23 --- /dev/null +++ b/libsecurity_asn1/lib/secasn1d.c @@ -0,0 +1,3155 @@ +/* + * 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 for DEcoding ASN.1 data based on BER/DER (Basic/Distinguished + * Encoding Rules). + * + * $Id: secasn1d.c,v 1.16 2004/05/13 15:29:13 dmitch Exp $ + */ + +#include "secasn1.h" +#include "secerr.h" +#include "assert.h" + +#ifdef NDEBUG +#define DEBUG_DECASN1 0 +#else +#define DEBUG_DECASN1 1 +#endif + +#if DEBUG_DECASN1 +#include +#define dprintf(args...) printf(args) +#else +#define dprintf(args...) +#endif /* DEBUG_DECASN1 */ + +typedef enum { + beforeIdentifier, + duringIdentifier, + afterIdentifier, + beforeLength, + duringLength, + afterLength, + beforeBitString, + duringBitString, + duringConstructedString, + duringGroup, + duringLeaf, + duringSaveEncoding, + duringSequence, + afterConstructedString, + afterGroup, + afterExplicit, + afterImplicit, + afterInline, + afterPointer, + afterSaveEncoding, + beforeEndOfContents, + duringEndOfContents, + afterEndOfContents, + beforeChoice, + duringChoice, + afterChoice, + notInUse +} sec_asn1d_parse_place; + +#ifndef NDEBUG +#define DEBUG_ASN1D_STATES 1 +/* tweakable by debugger, debug only */ +int doDumpStates = 0; +#else /* DEBUG_ASN1D_STATES 0 */ +#endif /* DEBUG_ASN1D_STATES */ + +#if DEBUG_ASN1D_STATES +static const char *place_names[] = { + "beforeIdentifier", + "duringIdentifier", + "afterIdentifier", + "beforeLength", + "duringLength", + "afterLength", + "beforeBitString", + "duringBitString", + "duringConstructedString", + "duringGroup", + "duringLeaf", + "duringSaveEncoding", + "duringSequence", + "afterConstructedString", + "afterGroup", + "afterExplicit", + "afterImplicit", + "afterInline", + "afterPointer", + "afterSaveEncoding", + "beforeEndOfContents", + "duringEndOfContents", + "afterEndOfContents", + "beforeChoice", + "duringChoice", + "afterChoice", + "notInUse" +}; + +static const char * const class_names[] = { + "UNIVERSAL", + "APPLICATION", + "CONTEXT_SPECIFIC", + "PRIVATE" +}; + +static const char * const method_names[] = { "PRIMITIVE", "CONSTRUCTED" }; + +static const char * const type_names[] = { + "END_OF_CONTENTS", + "BOOLEAN", + "INTEGER", + "BIT_STRING", + "OCTET_STRING", + "NULL", + "OBJECT_ID", + "OBJECT_DESCRIPTOR", + "(type 08)", + "REAL", + "ENUMERATED", + "EMBEDDED", + "UTF8_STRING", + "(type 0d)", + "(type 0e)", + "(type 0f)", + "SEQUENCE", + "SET", + "NUMERIC_STRING", + "PRINTABLE_STRING", + "T61_STRING", + "VIDEOTEXT_STRING", + "IA5_STRING", + "UTC_TIME", + "GENERALIZED_TIME", + "GRAPHIC_STRING", + "VISIBLE_STRING", + "GENERAL_STRING", + "UNIVERSAL_STRING", + "(type 1d)", + "BMP_STRING", + "HIGH_TAG_VALUE" +}; + +static const char * const flag_names[] = { /* flags, right to left */ + "OPTIONAL", + "EXPLICIT", + "ANY", + "INLINE", + "POINTER", + "GROUP", + "DYNAMIC", + "SKIP", + "INNER", + "SAVE", + "", /* decoder ignores "MAY_STREAM", */ + "SKIP_REST", + "CHOICE", + "NO_STREAM", + "DEBUG_BREAK", + "unknown 08", + "unknown 10", + "unknown 20", + "unknown 40", + "unknown 80" +}; + +static int /* bool */ +formatKind(unsigned long kind, char * buf) +{ + int i; + unsigned long k = kind & SEC_ASN1_TAGNUM_MASK; + unsigned long notag = kind & (SEC_ASN1_CHOICE | SEC_ASN1_POINTER | + SEC_ASN1_INLINE | SEC_ASN1_ANY | SEC_ASN1_SAVE); + + buf[0] = 0; + if ((kind & SEC_ASN1_CLASS_MASK) != SEC_ASN1_UNIVERSAL) { + sprintf(buf, " %s", class_names[(kind & SEC_ASN1_CLASS_MASK) >> 6] ); + buf += strlen(buf); + } + if (kind & SEC_ASN1_METHOD_MASK) { + sprintf(buf, " %s", method_names[1]); + buf += strlen(buf); + } + if ((kind & SEC_ASN1_CLASS_MASK) == SEC_ASN1_UNIVERSAL) { + if (k || !notag) { + sprintf(buf, " %s", type_names[k] ); + if ((k == SEC_ASN1_SET || k == SEC_ASN1_SEQUENCE) && + (kind & SEC_ASN1_GROUP)) { + buf += strlen(buf); + sprintf(buf, "_OF"); + } + } + } else { + sprintf(buf, " [%lu]", k); + } + buf += strlen(buf); + + for (k = kind >> 8, i = 0; k; k >>= 1, ++i) { + if (k & 1) { + sprintf(buf, " %s", flag_names[i]); + buf += strlen(buf); + } + } + return notag != 0; +} + +#endif /* DEBUG_ASN1D_STATES */ + +typedef enum { + allDone, + decodeError, + keepGoing, + needBytes +} sec_asn1d_parse_status; + +struct subitem { + const void *data; + unsigned long len; /* only used for substrings */ + struct subitem *next; +}; + +typedef struct sec_asn1d_state_struct { + SEC_ASN1DecoderContext *top; + const SecAsn1Template *theTemplate; + void *dest; + + void *our_mark; /* free on completion */ + + struct sec_asn1d_state_struct *parent; /* aka prev */ + struct sec_asn1d_state_struct *child; /* aka next */ + + sec_asn1d_parse_place place; + + /* + * XXX explain the next fields as clearly as possible... + */ + unsigned char found_tag_modifiers; + unsigned char expect_tag_modifiers; + unsigned long check_tag_mask; + unsigned long found_tag_number; + unsigned long expect_tag_number; + unsigned long underlying_kind; + + unsigned long contents_length; + unsigned long pending; + unsigned long consumed; + + int depth; + + /* + * Bit strings have their length adjusted -- the first octet of the + * contents contains a value between 0 and 7 which says how many bits + * at the end of the octets are not actually part of the bit string; + * when parsing bit strings we put that value here because we need it + * later, for adjustment of the length (when the whole string is done). + */ + unsigned int bit_string_unused_bits; + + /* + * The following are used for indefinite-length constructed strings. + */ + struct subitem *subitems_head; + struct subitem *subitems_tail; + + PRPackedBool + allocate, /* when true, need to allocate the destination */ + endofcontents, /* this state ended up parsing end-of-contents octets */ + explicit, /* we are handling an explicit header */ + indefinite, /* the current item has indefinite-length encoding */ + missing, /* an optional field that was not present */ + optional, /* the template says this field may be omitted */ + substring; /* this is a substring of a constructed string */ +} sec_asn1d_state; + +#define IS_HIGH_TAG_NUMBER(n) ((n) == SEC_ASN1_HIGH_TAG_NUMBER) +#define LAST_TAG_NUMBER_BYTE(b) (((b) & 0x80) == 0) +#define TAG_NUMBER_BITS 7 +#define TAG_NUMBER_MASK 0x7f + +#define LENGTH_IS_SHORT_FORM(b) (((b) & 0x80) == 0) +#define LONG_FORM_LENGTH(b) ((b) & 0x7f) + +#define HIGH_BITS(field,cnt) ((field) >> ((sizeof(field) * 8) - (cnt))) + + +/* + * An "outsider" will have an opaque pointer to this, created by calling + * SEC_ASN1DecoderStart(). It will be passed back in to all subsequent + * calls to SEC_ASN1DecoderUpdate(), and when done it is passed to + * SEC_ASN1DecoderFinish(). + */ +struct sec_DecoderContext_struct { + PRArenaPool *our_pool; /* for our internal allocs */ + PRArenaPool *their_pool; /* for destination structure allocs */ +#ifdef SEC_ASN1D_FREE_ON_ERROR /* + * XXX see comment below (by same + * ifdef) that explains why this + * does not work (need more smarts + * in order to free back to mark) + */ + /* + * XXX how to make their_mark work in the case where they do NOT + * give us a pool pointer? + */ + void *their_mark; /* free on error */ +#endif + + sec_asn1d_state *current; + sec_asn1d_parse_status status; + + SEC_ASN1NotifyProc notify_proc; /* call before/after handling field */ + void *notify_arg; /* argument to notify_proc */ + PRBool during_notify; /* true during call to notify_proc */ + + SEC_ASN1WriteProc filter_proc; /* pass field bytes to this */ + void *filter_arg; /* argument to that function */ + PRBool filter_only; /* do not allocate/store fields */ +}; + + +/* + * XXX this is a fairly generic function that may belong elsewhere + */ +static void * +sec_asn1d_alloc (PRArenaPool *poolp, unsigned long len) +{ + void *thing; + + if (poolp != NULL) { + /* + * Allocate from the pool. + */ + thing = PORT_ArenaAlloc (poolp, len); + } else { + /* + * Allocate generically. + */ + thing = PORT_Alloc (len); + } + + return thing; +} + + +/* + * XXX this is a fairly generic function that may belong elsewhere + */ +static void * +sec_asn1d_zalloc (PRArenaPool *poolp, unsigned long len) +{ + void *thing; + + thing = sec_asn1d_alloc (poolp, len); + if (thing != NULL) + PORT_Memset (thing, 0, len); + return thing; +} + + +static sec_asn1d_state * +sec_asn1d_push_state (SEC_ASN1DecoderContext *cx, + const SecAsn1Template *theTemplate, + void *dest, PRBool new_depth) +{ + sec_asn1d_state *state, *new_state; + + state = cx->current; + + PORT_Assert (state == NULL || state->child == NULL); + + if (state != NULL) { + PORT_Assert (state->our_mark == NULL); + state->our_mark = PORT_ArenaMark (cx->our_pool); + } + + new_state = (sec_asn1d_state*)sec_asn1d_zalloc (cx->our_pool, + sizeof(*new_state)); + if (new_state == NULL) { + dprintf("decodeError: zalloc failure\n"); + goto loser; + } + + new_state->top = cx; + new_state->parent = state; + new_state->theTemplate = theTemplate; + new_state->place = notInUse; + if (dest != NULL) + new_state->dest = (char *)dest + theTemplate->offset; + + if (state != NULL) { + new_state->depth = state->depth; + if (new_depth) { + if (++new_state->depth > SEC_ASN1D_MAX_DEPTH) { + PORT_SetError (SEC_ERROR_BAD_DER); + goto loser; + } + } + state->child = new_state; + } + + cx->current = new_state; + return new_state; + +loser: + cx->status = decodeError; + if (state != NULL) { + PORT_ArenaRelease(cx->our_pool, state->our_mark); + state->our_mark = NULL; + } + return NULL; +} + + +static void +sec_asn1d_scrub_state (sec_asn1d_state *state) +{ + /* + * Some default "scrubbing". + * XXX right set of initializations? + */ + state->place = beforeIdentifier; + state->endofcontents = PR_FALSE; + state->indefinite = PR_FALSE; + state->missing = PR_FALSE; + + PORT_Assert (state->consumed == 0); +} + + +static sec_asn1d_state * +sec_asn1d_get_enclosing_construct(sec_asn1d_state *state) +{ + for (state = state->parent; state; state = state->parent) { + sec_asn1d_parse_place place = state->place; + if (place != afterImplicit && + place != afterPointer && + place != afterInline && + place != afterSaveEncoding && + place != duringSaveEncoding && + place != duringChoice) { + + /* we've walked up the stack to a state that represents + ** the enclosing construct. + */ + break; + } + } + return state; +} + + +static PRBool +sec_asn1d_parent_allows_EOC(sec_asn1d_state *state) +{ + /* get state of enclosing construct. */ + state = sec_asn1d_get_enclosing_construct(state); + if (state) { + sec_asn1d_parse_place place = state->place; + /* Is it one of the types that permits an unexpected EOC? */ + int eoc_permitted = + (place == duringGroup || + place == duringConstructedString || + state->child->optional); + return (state->indefinite && eoc_permitted) ? PR_TRUE : PR_FALSE; + } + return PR_FALSE; +} + + +static void +sec_asn1d_notify_before (SEC_ASN1DecoderContext *cx, void *dest, int depth) +{ + if (cx->notify_proc == NULL) + return; + + cx->during_notify = PR_TRUE; + (* cx->notify_proc) (cx->notify_arg, PR_TRUE, dest, depth); + cx->during_notify = PR_FALSE; +} + + +static void +sec_asn1d_notify_after (SEC_ASN1DecoderContext *cx, void *dest, int depth) +{ + if (cx->notify_proc == NULL) + return; + + cx->during_notify = PR_TRUE; + (* cx->notify_proc) (cx->notify_arg, PR_FALSE, dest, depth); + cx->during_notify = PR_FALSE; +} + + +static sec_asn1d_state * +sec_asn1d_init_state_based_on_template (sec_asn1d_state *state, + #ifdef __APPLE__ + const char *buf /* for SEC_ASN1GetSubtemplate() */ + #endif + ) +{ + PRBool explicit, optional, universal; + unsigned char expect_tag_modifiers; + unsigned long encode_kind, under_kind; + unsigned long check_tag_mask, expect_tag_number; + #ifdef __APPLE__ + unsigned long dynamic; + #endif + + + /* XXX Check that both of these tests are really needed/appropriate. */ + if (state == NULL || state->top->status == decodeError) + return state; + + encode_kind = state->theTemplate->kind; + + if (encode_kind & SEC_ASN1_SAVE) { + /* + * This is a "magic" field that saves away all bytes, allowing + * the immediately following field to still be decoded from this + * same spot -- sort of a fork. + */ + /* check that there are no extraneous bits */ + PORT_Assert (encode_kind == SEC_ASN1_SAVE); + if (state->top->filter_only) { + /* + * If we are not storing, then we do not do the SAVE field + * at all. Just move ahead to the "real" field instead, + * doing the appropriate notify calls before and after. + */ + sec_asn1d_notify_after (state->top, state->dest, state->depth); + /* + * Since we are not storing, allow for our current dest value + * to be NULL. (This might not actually occur, but right now I + * cannot convince myself one way or the other.) If it is NULL, + * assume that our parent dest can help us out. + */ + if (state->dest == NULL) + state->dest = state->parent->dest; + else + state->dest = + (char *)state->dest - state->theTemplate->offset; + state->theTemplate++; + if (state->dest != NULL) + state->dest = + (char *)state->dest + state->theTemplate->offset; + sec_asn1d_notify_before (state->top, state->dest, state->depth); + encode_kind = state->theTemplate->kind; + PORT_Assert ((encode_kind & SEC_ASN1_SAVE) == 0); + } else { + sec_asn1d_scrub_state (state); + state->place = duringSaveEncoding; + state = sec_asn1d_push_state (state->top, kSecAsn1AnyTemplate, + state->dest, PR_FALSE); + if (state != NULL) + state = sec_asn1d_init_state_based_on_template (state, + buf /* __APPLE__ */); + return state; + } + } + + + universal = ((encode_kind & SEC_ASN1_CLASS_MASK) == SEC_ASN1_UNIVERSAL) + ? PR_TRUE : PR_FALSE; + + explicit = (encode_kind & SEC_ASN1_EXPLICIT) ? PR_TRUE : PR_FALSE; + encode_kind &= ~SEC_ASN1_EXPLICIT; + + optional = (encode_kind & SEC_ASN1_OPTIONAL) ? PR_TRUE : PR_FALSE; + encode_kind &= ~SEC_ASN1_OPTIONAL; + + #ifdef __APPLE__ + dynamic = (encode_kind & SEC_ASN1_DYNAMIC) ? PR_TRUE : PR_FALSE; + encode_kind &= ~SEC_ASN1_DYNAMIC; + #endif + + PORT_Assert (!(explicit && universal)); /* bad templates */ + + encode_kind &= ~SEC_ASN1_DYNAMIC; + encode_kind &= ~SEC_ASN1_MAY_STREAM; + + if( encode_kind & SEC_ASN1_CHOICE ) { +#if 0 /* XXX remove? */ + sec_asn1d_state *child = sec_asn1d_push_state(state->top, state->theTemplate, state->dest, PR_FALSE); + if( (sec_asn1d_state *)NULL == child ) { + return (sec_asn1d_state *)NULL; + } + + child->allocate = state->allocate; + child->place = beforeChoice; + return child; +#else + state->place = beforeChoice; + return state; +#endif + } + + if ((encode_kind & (SEC_ASN1_POINTER | SEC_ASN1_INLINE)) || (!universal + && !explicit)) { + const SecAsn1Template *subt; + void *dest; + PRBool child_allocate; + void *subDest; + + PORT_Assert ((encode_kind & (SEC_ASN1_ANY | SEC_ASN1_SKIP)) == 0); + + sec_asn1d_scrub_state (state); + child_allocate = PR_FALSE; + + if (encode_kind & SEC_ASN1_POINTER) { + /* + * A POINTER means we need to allocate the destination for + * this field. But, since it may also be an optional field, + * we defer the allocation until later; we just record that + * it needs to be done. + * + * There are two possible scenarios here -- one is just a + * plain POINTER (kind of like INLINE, except with allocation) + * and the other is an implicitly-tagged POINTER. We don't + * need to do anything special here for the two cases, but + * since the template definition can be tricky, we do check + * that there are no extraneous bits set in encode_kind. + * + * XXX The same conditions which assert should set an error. + */ + if (universal) { + /* + * "universal" means this entry is a standalone POINTER; + * there should be no other bits set in encode_kind. + */ + PORT_Assert (encode_kind == SEC_ASN1_POINTER); + } else { + /* + * If we get here we have an implicitly-tagged field + * that needs to be put into a POINTER. The subtemplate + * will determine how to decode the field, but encode_kind + * describes the (implicit) tag we are looking for. + * The non-tag bits of encode_kind will be ignored by + * the code below; none of them should be set, however, + * except for the POINTER bit itself -- so check that. + */ + PORT_Assert ((encode_kind & ~SEC_ASN1_TAG_MASK) + == SEC_ASN1_POINTER); + } + if (!state->top->filter_only) + child_allocate = PR_TRUE; + dest = NULL; + state->place = afterPointer; + } else { + dest = state->dest; + if (encode_kind & SEC_ASN1_INLINE) { + /* check that there are no extraneous bits */ + /* FIXME - why are optional and inline mutually + * exclusive? Delete this assert and see what happens... + PORT_Assert (encode_kind == SEC_ASN1_INLINE && !optional); + */ + state->place = afterInline; + } else { + state->place = afterImplicit; + } + } + + state->optional = optional; + + subDest = state->dest; + #if defined(__APPLE__) + /* + * We might be starting the processing of a group or a + * set, in which case state->dest is NULL. Get parent's dest, + * or grandparent's, etc... just for the use by + * SEC_ASN1GetSubtemplate (specifically, by dynamic + * choosers) + */ + sec_asn1d_state *tempState = state; + while(subDest == NULL) { + sec_asn1d_state *parent = tempState->parent; + if(parent == NULL) { + /* Oh well. Not going to work for this template. */ + break; + } + subDest = parent->dest; + tempState = parent; + } + #endif /* __APPLE__ */ + subt = SEC_ASN1GetSubtemplate (state->theTemplate, subDest, + PR_FALSE, buf /* __APPLE__ */); + state = sec_asn1d_push_state (state->top, subt, dest, PR_FALSE); + if (state == NULL) + return NULL; + + state->allocate = child_allocate; + + if (universal + #ifdef __APPLE__ + /* Dynamic: restart with new template */ + || dynamic + #endif + ) { + state = sec_asn1d_init_state_based_on_template (state, + buf /* __APPLE__ */); + if (state != NULL) { + /* + * If this field is optional, we need to record that on + * the pushed child so it won't fail if the field isn't + * found. I can't think of a way that this new state + * could already have optional set (which we would wipe + * out below if our local optional is not set) -- but + * just to be sure, assert that it isn't set. + */ + PORT_Assert (!state->optional); + state->optional = optional; + } + return state; + } + + under_kind = state->theTemplate->kind; + under_kind &= ~SEC_ASN1_MAY_STREAM; + } else if (explicit) { + /* + * For explicit, we only need to match the encoding tag next, + * then we will push another state to handle the entire inner + * part. In this case, there is no underlying kind which plays + * any part in the determination of the outer, explicit tag. + * So we just set under_kind to 0, which is not a valid tag, + * and the rest of the tag matching stuff should be okay. + */ + under_kind = 0; + } else { + /* + * Nothing special; the underlying kind and the given encoding + * information are the same. + */ + under_kind = encode_kind; + } + + /* XXX is this the right set of bits to test here? */ + PORT_Assert ((under_kind & (SEC_ASN1_EXPLICIT + | SEC_ASN1_MAY_STREAM + | SEC_ASN1_INLINE | SEC_ASN1_POINTER)) == 0); + + if (encode_kind & (SEC_ASN1_ANY | SEC_ASN1_SKIP)) { + PORT_Assert (encode_kind == under_kind); + if (encode_kind & SEC_ASN1_SKIP) { + PORT_Assert (!optional); + PORT_Assert (encode_kind == SEC_ASN1_SKIP); + state->dest = NULL; + } + check_tag_mask = 0; + expect_tag_modifiers = 0; + expect_tag_number = 0; + } else { + check_tag_mask = SEC_ASN1_TAG_MASK; + expect_tag_modifiers = (unsigned char)encode_kind & SEC_ASN1_TAG_MASK + & ~SEC_ASN1_TAGNUM_MASK; + /* + * XXX This assumes only single-octet identifiers. To handle + * the HIGH TAG form we would need to do some more work, especially + * in how to specify them in the template, because right now we + * do not provide a way to specify more *tag* bits in encode_kind. + */ + expect_tag_number = encode_kind & SEC_ASN1_TAGNUM_MASK; + + switch (under_kind & SEC_ASN1_TAGNUM_MASK) { + case SEC_ASN1_SET: + /* + * XXX A plain old SET (as opposed to a SET OF) is not + * implemented. + * If it ever is, remove this assert... + */ + PORT_Assert ((under_kind & SEC_ASN1_GROUP) != 0); + /* fallthru */ + case SEC_ASN1_SEQUENCE: + expect_tag_modifiers |= SEC_ASN1_CONSTRUCTED; + break; + case SEC_ASN1_BIT_STRING: + case SEC_ASN1_BMP_STRING: + case SEC_ASN1_GENERALIZED_TIME: + case SEC_ASN1_IA5_STRING: + case SEC_ASN1_OCTET_STRING: + case SEC_ASN1_PRINTABLE_STRING: + case SEC_ASN1_T61_STRING: + case SEC_ASN1_UNIVERSAL_STRING: + case SEC_ASN1_UTC_TIME: + case SEC_ASN1_UTF8_STRING: + case SEC_ASN1_VISIBLE_STRING: + check_tag_mask &= ~SEC_ASN1_CONSTRUCTED; + break; + } + } + + state->check_tag_mask = check_tag_mask; + state->expect_tag_modifiers = expect_tag_modifiers; + state->expect_tag_number = expect_tag_number; + state->underlying_kind = under_kind; + state->explicit = explicit; + state->optional = optional; + sec_asn1d_scrub_state (state); + + return state; +} + + +static unsigned long +sec_asn1d_parse_identifier (sec_asn1d_state *state, + const char *buf, unsigned long len) +{ + unsigned char byte; + unsigned char tag_number; + + PORT_Assert (state->place == beforeIdentifier); + + if (len == 0) { + state->top->status = needBytes; + return 0; + } + + byte = (unsigned char) *buf; +#ifdef DEBUG_ASN1D_STATES + if (doDumpStates > 0) { + char kindBuf[256]; + formatKind(byte, kindBuf); + printf("Found tag %02x %s\n", byte, kindBuf); + } +#endif + tag_number = byte & SEC_ASN1_TAGNUM_MASK; + + if (IS_HIGH_TAG_NUMBER (tag_number)) { + state->place = duringIdentifier; + state->found_tag_number = 0; + /* + * Actually, we have no idea how many bytes are pending, but we + * do know that it is at least 1. That is all we know; we have + * to look at each byte to know if there is another, etc. + */ + state->pending = 1; + } else { + if (byte == 0 && sec_asn1d_parent_allows_EOC(state)) { + /* + * Our parent has indefinite-length encoding, and the + * entire tag found is 0, so it seems that we have hit the + * end-of-contents octets. To handle this, we just change + * our state to that which expects to get the bytes of the + * end-of-contents octets and let that code re-read this byte + * so that our categorization of field types is correct. + * After that, our parent will then deal with everything else. + */ + state->place = duringEndOfContents; + state->pending = 2; + state->found_tag_number = 0; + state->found_tag_modifiers = 0; + /* + * We might be an optional field that is, as we now find out, + * missing. Give our parent a clue that this happened. + */ + if (state->optional) + state->missing = PR_TRUE; + return 0; + } + state->place = afterIdentifier; + state->found_tag_number = tag_number; + } + state->found_tag_modifiers = byte & ~SEC_ASN1_TAGNUM_MASK; + + return 1; +} + + +static unsigned long +sec_asn1d_parse_more_identifier (sec_asn1d_state *state, + const char *buf, unsigned long len) +{ + unsigned char byte; + int count; + + PORT_Assert (state->pending == 1); + PORT_Assert (state->place == duringIdentifier); + + if (len == 0) { + state->top->status = needBytes; + return 0; + } + + count = 0; + + while (len && state->pending) { + if (HIGH_BITS (state->found_tag_number, TAG_NUMBER_BITS) != 0) { + /* + * The given high tag number overflows our container; + * just give up. This is not likely to *ever* happen. + */ + PORT_SetError (SEC_ERROR_BAD_DER); + state->top->status = decodeError; + dprintf("decodeError: parse_more_id high bits oflow\n"); + return 0; + } + + state->found_tag_number <<= TAG_NUMBER_BITS; + + byte = (unsigned char) buf[count++]; + state->found_tag_number |= (byte & TAG_NUMBER_MASK); + + len--; + if (LAST_TAG_NUMBER_BYTE (byte)) + state->pending = 0; + } + + if (state->pending == 0) + state->place = afterIdentifier; + + return count; +} + + +static void +sec_asn1d_confirm_identifier (sec_asn1d_state *state) +{ + PRBool match; + + PORT_Assert (state->place == afterIdentifier); + + match = (PRBool)(((state->found_tag_modifiers & state->check_tag_mask) + == state->expect_tag_modifiers) + && ((state->found_tag_number & state->check_tag_mask) + == state->expect_tag_number)); + if (match) { + state->place = beforeLength; + } else { + if (state->optional) { + state->missing = PR_TRUE; + state->place = afterEndOfContents; + } else { + PORT_SetError (SEC_ERROR_BAD_DER); + state->top->status = decodeError; + //dprintf("decodeError: sec_asn1d_confirm_identifier\n"); + } + } +} + + +static unsigned long +sec_asn1d_parse_length (sec_asn1d_state *state, + const char *buf, unsigned long len) +{ + unsigned char byte; + + PORT_Assert (state->place == beforeLength); + + if (len == 0) { + state->top->status = needBytes; + return 0; + } + + /* + * The default/likely outcome. It may get adjusted below. + */ + state->place = afterLength; + + byte = (unsigned char) *buf; + + if (LENGTH_IS_SHORT_FORM (byte)) { + state->contents_length = byte; + } else { + state->contents_length = 0; + state->pending = LONG_FORM_LENGTH (byte); + if (state->pending == 0) { + state->indefinite = PR_TRUE; + } else { + state->place = duringLength; + } + } + + /* If we're parsing an ANY, SKIP, or SAVE template, and + ** the object being saved is definite length encoded and constructed, + ** there's no point in decoding that construct's members. + ** So, just forget it's constructed and treat it as primitive. + ** (SAVE appears as an ANY at this point) + */ + if (!state->indefinite && + (state->underlying_kind & (SEC_ASN1_ANY | SEC_ASN1_SKIP))) { + state->found_tag_modifiers &= ~SEC_ASN1_CONSTRUCTED; + } + + return 1; +} + + +static unsigned long +sec_asn1d_parse_more_length (sec_asn1d_state *state, + const char *buf, unsigned long len) +{ + int count; + + PORT_Assert (state->pending > 0); + PORT_Assert (state->place == duringLength); + + if (len == 0) { + state->top->status = needBytes; + return 0; + } + + count = 0; + + while (len && state->pending) { + if (HIGH_BITS (state->contents_length, 9) != 0) { + /* + * The given full content length overflows our container; + * just give up. + */ + PORT_SetError (SEC_ERROR_BAD_DER); + state->top->status = decodeError; + dprintf("decodeError: sec_asn1d_parse_more_length\n"); + return 0; + } + + state->contents_length <<= 8; + state->contents_length |= (unsigned char) buf[count++]; + + len--; + state->pending--; + } + + if (state->pending == 0) + state->place = afterLength; + + return count; +} + + +static void +sec_asn1d_prepare_for_contents (sec_asn1d_state *state, + #ifdef __APPLE__ + const char *buf /* needed for SEC_ASN1GetSubtemplate */ + #endif + ) +{ + SecAsn1Item *item; + PRArenaPool *poolp; + unsigned long alloc_len; + +#ifdef DEBUG_ASN1D_STATES + if (doDumpStates > 0) { + printf("Found Length %lu %s\n", state->contents_length, + state->indefinite ? "indefinite" : ""); + } +#endif + + /* + * XXX I cannot decide if this allocation should exclude the case + * where state->endofcontents is true -- figure it out! + */ + if (state->allocate) { + void *dest; + + PORT_Assert (state->dest == NULL); + /* + * We are handling a POINTER or a member of a GROUP, and need to + * allocate for the data structure. + */ + dest = sec_asn1d_zalloc (state->top->their_pool, + state->theTemplate->size); + if (dest == NULL) { + dprintf("decodeError: sec_asn1d_prepare_for_contents zalloc\n"); + state->top->status = decodeError; + return; + } + /* FIXME _ we're losing the dest pointer after this! */ + state->dest = (char *)dest + state->theTemplate->offset; + + /* + * For a member of a GROUP, our parent will later put the + * pointer wherever it belongs. But for a POINTER, we need + * to record the destination now, in case notify or filter + * procs need access to it -- they cannot find it otherwise, + * until it is too late (for one-pass processing). + */ + if (state->parent->place == afterPointer) { + void **placep; + + placep = state->parent->dest; + *placep = dest; + } + } + + /* + * Remember, length may be indefinite here! In that case, + * both contents_length and pending will be zero. + */ + state->pending = state->contents_length; + + /* If this item has definite length encoding, and + ** is enclosed by a definite length constructed type, + ** make sure it isn't longer than the remaining space in that + ** constructed type. + */ + if (state->contents_length > 0) { + sec_asn1d_state *parent = sec_asn1d_get_enclosing_construct(state); + if (parent && !parent->indefinite && + state->consumed + state->contents_length > parent->pending) { + PORT_SetError (SEC_ERROR_BAD_DER); + state->top->status = decodeError; + return; + } + } + + /* + * An EXPLICIT is nothing but an outer header, which we have + * already parsed and accepted. Now we need to do the inner + * header and its contents. + */ + if (state->explicit) { + state->place = afterExplicit; + state = sec_asn1d_push_state (state->top, + SEC_ASN1GetSubtemplate(state->theTemplate, + state->dest, + PR_FALSE, + buf /* __APPLE__ */), + state->dest, PR_TRUE); + if (state != NULL) + state = sec_asn1d_init_state_based_on_template (state, + buf /* __APPLE__ */); + return; + } + + /* + * For GROUP (SET OF, SEQUENCE OF), even if we know the length here + * we cannot tell how many items we will end up with ... so push a + * state that can keep track of "children" (the individual members + * of the group; we will allocate as we go and put them all together + * at the end. + */ + if (state->underlying_kind & SEC_ASN1_GROUP) { + /* XXX If this assertion holds (should be able to confirm it via + * inspection, too) then move this code into the switch statement + * below under cases SET_OF and SEQUENCE_OF; it will be cleaner. + */ + PORT_Assert (state->underlying_kind == SEC_ASN1_SET_OF + || state->underlying_kind == SEC_ASN1_SEQUENCE_OF + || state->underlying_kind == (SEC_ASN1_SEQUENCE_OF|SEC_ASN1_DYNAMIC) + || state->underlying_kind == (SEC_ASN1_SET_OF|SEC_ASN1_DYNAMIC) + ); + if (state->contents_length != 0 || state->indefinite) { + const SecAsn1Template *subt; + + state->place = duringGroup; + subt = SEC_ASN1GetSubtemplate (state->theTemplate, state->dest, + PR_FALSE, buf /* __APPLE__ */); + state = sec_asn1d_push_state (state->top, subt, NULL, PR_TRUE); + if (state != NULL) { + if (!state->top->filter_only) + state->allocate = PR_TRUE; /* XXX propogate this? */ + /* + * Do the "before" field notification for next in group. + */ + sec_asn1d_notify_before (state->top, state->dest, state->depth); + state = sec_asn1d_init_state_based_on_template (state, + buf /* __APPLE__ */); + } + } else { + /* + * A group of zero; we are done. + * Set state to afterGroup and let that code plant the NULL. + */ + state->place = afterGroup; + } + return; + } + + switch (state->underlying_kind) { + case SEC_ASN1_SEQUENCE: + /* + * We need to push a child to handle the individual fields. + */ + state->place = duringSequence; + state = sec_asn1d_push_state (state->top, state->theTemplate + 1, + state->dest, PR_TRUE); + if (state != NULL) { + /* + * Do the "before" field notification. + */ + sec_asn1d_notify_before (state->top, state->dest, state->depth); + state = sec_asn1d_init_state_based_on_template (state, + buf /* __APPLE__ */); + } + break; + + case SEC_ASN1_SET: /* XXX SET is not really implemented */ + /* + * XXX A plain SET requires special handling; scanning of a + * template to see where a field should go (because by definition, + * they are not in any particular order, and you have to look at + * each tag to disambiguate what the field is). We may never + * implement this because in practice, it seems to be unused. + */ + dprintf("decodeError: prepare for contents SEC_ASN1_SET\n"); + PORT_Assert(0); + PORT_SetError (SEC_ERROR_BAD_DER); /* XXX */ + state->top->status = decodeError; + break; + + case SEC_ASN1_NULL: + /* + * The NULL type, by definition, is "nothing", content length of zero. + * An indefinite-length encoding is not alloweed. + */ + if (state->contents_length || state->indefinite) { + dprintf("decodeError: prepare for contents indefinite NULL\n"); + PORT_SetError (SEC_ERROR_BAD_DER); + state->top->status = decodeError; + break; + } + if (state->dest != NULL) { + item = (SecAsn1Item *)(state->dest); + item->Data = NULL; + item->Length = 0; + } + state->place = afterEndOfContents; + break; + + case SEC_ASN1_BMP_STRING: + /* Error if length is not divisable by 2 */ + if (state->contents_length % 2) { + dprintf("decodeError: prepare for contents odd length BMP_STRING\n"); + PORT_SetError (SEC_ERROR_BAD_DER); + state->top->status = decodeError; + break; + } + /* otherwise, handle as other string types */ + goto regular_string_type; + + case SEC_ASN1_UNIVERSAL_STRING: + /* Error if length is not divisable by 4 */ + if (state->contents_length % 4) { + dprintf("decodeError: prepare for contents odd length UNIV_STRING\n"); + PORT_SetError (SEC_ERROR_BAD_DER); + state->top->status = decodeError; + break; + } + /* otherwise, handle as other string types */ + goto regular_string_type; + + case SEC_ASN1_SKIP: + case SEC_ASN1_ANY: + case SEC_ASN1_ANY_CONTENTS: + /* + * These are not (necessarily) strings, but they need nearly + * identical handling (especially when we need to deal with + * constructed sub-pieces), so we pretend they are. + */ + /* fallthru */ +regular_string_type: + case SEC_ASN1_BIT_STRING: + case SEC_ASN1_IA5_STRING: + case SEC_ASN1_OCTET_STRING: + case SEC_ASN1_PRINTABLE_STRING: + case SEC_ASN1_T61_STRING: + case SEC_ASN1_UTC_TIME: + case SEC_ASN1_UTF8_STRING: + case SEC_ASN1_VISIBLE_STRING: + /* + * We are allocating for a primitive or a constructed string. + * If it is a constructed string, it may also be indefinite-length. + * If it is primitive, the length can (legally) be zero. + * Our first order of business is to allocate the memory for + * the string, if we can (if we know the length). + */ + item = (SecAsn1Item *)(state->dest); + + /* + * If the item is a definite-length constructed string, then + * the contents_length is actually larger than what we need + * (because it also counts each intermediate header which we + * will be throwing away as we go), but it is a perfectly good + * upper bound that we just allocate anyway, and then concat + * as we go; we end up wasting a few extra bytes but save a + * whole other copy. + */ + alloc_len = state->contents_length; + poolp = NULL; /* quiet compiler warnings about unused... */ + + if (item == NULL || state->top->filter_only) { + if (item != NULL) { + item->Data = NULL; + item->Length = 0; + } + alloc_len = 0; + } else if (state->substring) { + /* + * If we are a substring of a constructed string, then we may + * not have to allocate anything (because our parent, the + * actual constructed string, did it for us). If we are a + * substring and we *do* have to allocate, that means our + * parent is an indefinite-length, so we allocate from our pool; + * later our parent will copy our string into the aggregated + * whole and free our pool allocation. + */ + if (item->Data == NULL) { + PORT_Assert (item->Length == 0); + poolp = state->top->our_pool; + } else { + alloc_len = 0; + } + } else { + item->Length = 0; + item->Data = NULL; + poolp = state->top->their_pool; + } + + if (alloc_len || ((! state->indefinite) + && (state->subitems_head != NULL))) { + struct subitem *subitem; + unsigned long len; + + 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 + * in the saved contents. + */ + if (state->subitems_head != NULL) { + PORT_Assert (state->underlying_kind == SEC_ASN1_ANY); + for (subitem = state->subitems_head; + subitem != NULL; subitem = subitem->next) + alloc_len += subitem->len; + } + + item->Data = (unsigned char*)sec_asn1d_zalloc (poolp, alloc_len); + if (item->Data == NULL) { + dprintf("decodeError: prepare for contents zalloc\n"); + state->top->status = decodeError; + break; + } + + len = 0; + for (subitem = state->subitems_head; + subitem != NULL; subitem = subitem->next) { + PORT_Memcpy (item->Data + len, subitem->data, subitem->len); + len += subitem->len; + } + item->Length = len; + + /* + * Because we use arenas and have a mark set, we later free + * everything we have allocated, so this does *not* present + * a memory leak (it is just temporarily left dangling). + */ + state->subitems_head = state->subitems_tail = NULL; + } + + if (state->contents_length == 0 && (! state->indefinite)) { + /* + * A zero-length simple or constructed string; we are done. + */ + state->place = afterEndOfContents; + } else if (state->found_tag_modifiers & SEC_ASN1_CONSTRUCTED) { + const SecAsn1Template *sub; + + switch (state->underlying_kind) { + case SEC_ASN1_ANY: + case SEC_ASN1_ANY_CONTENTS: + sub = kSecAsn1AnyTemplate; + break; + case SEC_ASN1_BIT_STRING: + sub = kSecAsn1BitStringTemplate; + break; + case SEC_ASN1_BMP_STRING: + sub = kSecAsn1BMPStringTemplate; + break; + case SEC_ASN1_GENERALIZED_TIME: + sub = kSecAsn1GeneralizedTimeTemplate; + break; + case SEC_ASN1_IA5_STRING: + sub = kSecAsn1IA5StringTemplate; + break; + case SEC_ASN1_OCTET_STRING: + sub = kSecAsn1OctetStringTemplate; + break; + case SEC_ASN1_PRINTABLE_STRING: + sub = kSecAsn1PrintableStringTemplate; + break; + case SEC_ASN1_T61_STRING: + sub = kSecAsn1T61StringTemplate; + break; + case SEC_ASN1_UNIVERSAL_STRING: + sub = kSecAsn1UniversalStringTemplate; + break; + case SEC_ASN1_UTC_TIME: + sub = kSecAsn1UTCTimeTemplate; + break; + case SEC_ASN1_UTF8_STRING: + sub = kSecAsn1UTF8StringTemplate; + break; + case SEC_ASN1_VISIBLE_STRING: + sub = kSecAsn1VisibleStringTemplate; + break; + case SEC_ASN1_SKIP: + sub = kSecAsn1SkipTemplate; + break; + default: /* redundant given outer switch cases, but */ + PORT_Assert(0); /* the compiler does not seem to know that, */ + sub = NULL; /* so just do enough to quiet it. */ + break; + } + + state->place = duringConstructedString; + state = sec_asn1d_push_state (state->top, sub, item, PR_TRUE); + if (state != NULL) { + state->substring = PR_TRUE; /* XXX propogate? */ + state = sec_asn1d_init_state_based_on_template (state, + buf /* __APPLE__ */); + } + } else if (state->indefinite) { + /* + * An indefinite-length string *must* be constructed! + */ + dprintf("decodeError: prepare for contents indefinite not construncted\n"); + PORT_SetError (SEC_ERROR_BAD_DER); + state->top->status = decodeError; + } else { + /* + * A non-zero-length simple string. + */ + if (state->underlying_kind == SEC_ASN1_BIT_STRING) + state->place = beforeBitString; + else + state->place = duringLeaf; + } + break; + + default: + /* + * We are allocating for a simple leaf item. + */ + if (state->contents_length) { + if (state->dest != NULL) { + item = (SecAsn1Item *)(state->dest); + item->Length = 0; + if (state->top->filter_only) { + item->Data = NULL; + } else { + item->Data = (unsigned char*) + sec_asn1d_zalloc (state->top->their_pool, + state->contents_length); + if (item->Data == NULL) { + dprintf("decodeError: prepare for contents zalloc\n"); + state->top->status = decodeError; + return; + } + } + } + state->place = duringLeaf; + } else { + /* + * An indefinite-length or zero-length item is not allowed. + * (All legal cases of such were handled above.) + */ + dprintf("decodeError: prepare for contents indefinite zero len \n"); + PORT_SetError (SEC_ERROR_BAD_DER); + state->top->status = decodeError; + } + } +} + + +static void +sec_asn1d_free_child (sec_asn1d_state *state, PRBool error) +{ + if (state->child != NULL) { + PORT_Assert (error || state->child->consumed == 0); + PORT_Assert (state->our_mark != NULL); + PORT_ArenaRelease (state->top->our_pool, state->our_mark); + if (error && state->top->their_pool == NULL) { + /* + * XXX We need to free anything allocated. + * At this point, we failed in the middle of decoding. But we + * can't free the data we previously allocated with PR_Malloc + * unless we keep track of every pointer. So instead we have a + * memory leak when decoding fails half-way, unless an arena is + * used. See bug 95311 . + */ + } + state->child = NULL; + state->our_mark = NULL; + } else { + /* + * It is important that we do not leave a mark unreleased/unmarked. + * But I do not think we should ever have one set in this case, only + * if we had a child (handled above). So check for that. If this + * assertion should ever get hit, then we probably need to add code + * here to release back to our_mark (and then set our_mark to NULL). + */ + PORT_Assert (state->our_mark == NULL); + } + state->place = beforeEndOfContents; +} + + +/* We have just saved an entire encoded ASN.1 object (type) for a SAVE +** template, and now in the next template, we are going to decode that +** saved data by calling SEC_ASN1DecoderUpdate recursively. +** If that recursive call fails with needBytes, it is a fatal error, +** because the encoded object should have been complete. +** If that recursive call fails with decodeError, it will have already +** cleaned up the state stack, so we must bail out quickly. +** +** These checks of the status returned by the recursive call are now +** done in the caller of this function, immediately after it returns. +*/ +static void +sec_asn1d_reuse_encoding (sec_asn1d_state *state) +{ + sec_asn1d_state *child; + unsigned long consumed; + SecAsn1Item *item; + void *dest; + + + child = state->child; + PORT_Assert (child != NULL); + + consumed = child->consumed; + child->consumed = 0; + + item = (SecAsn1Item *)(state->dest); + PORT_Assert (item != NULL); + + PORT_Assert (item->Length == consumed); + + /* + * Free any grandchild. + */ + sec_asn1d_free_child (child, PR_FALSE); + + /* + * Notify after the SAVE field. + */ + sec_asn1d_notify_after (state->top, state->dest, state->depth); + + /* + * Adjust to get new dest and move forward. + */ + dest = (char *)state->dest - state->theTemplate->offset; + state->theTemplate++; + child->dest = (char *)dest + state->theTemplate->offset; + child->theTemplate = state->theTemplate; + + /* + * Notify before the "real" field. + */ + PORT_Assert (state->depth == child->depth); + sec_asn1d_notify_before (state->top, child->dest, child->depth); + + /* + * This will tell DecoderUpdate to return when it is done. + */ + state->place = afterSaveEncoding; + + /* + * We already have a child; "push" it by making it current. + */ + state->top->current = child; + + /* + * And initialize it so it is ready to parse. + */ + (void) sec_asn1d_init_state_based_on_template(child, + (char *) item->Data /* __APPLE__ */); + + /* + * Now parse that out of our data. + */ + if (SEC_ASN1DecoderUpdate (state->top, + (char *) item->Data, item->Length) != SECSuccess) + return; + if (state->top->status == needBytes) { + return; + } + + PORT_Assert (state->top->current == state); + PORT_Assert (state->child == child); + + /* + * That should have consumed what we consumed before. + */ + PORT_Assert (consumed == child->consumed); + child->consumed = 0; + + /* + * Done. + */ + state->consumed += consumed; + child->place = notInUse; + state->place = afterEndOfContents; +} + + +static unsigned long +sec_asn1d_parse_leaf (sec_asn1d_state *state, + const char *buf, unsigned long len) +{ + SecAsn1Item *item; + unsigned long bufLen; + + if (len == 0) { + state->top->status = needBytes; + return 0; + } + + if (state->pending < len) + len = state->pending; + + bufLen = len; + + item = (SecAsn1Item *)(state->dest); + if (item != NULL && item->Data != NULL) { + /* Strip leading zeroes when target is unsigned integer */ + if (state->underlying_kind == SEC_ASN1_INTEGER && /* INTEGER */ + item->Length == 0 && /* MSB */ + #ifdef __APPLE__ + !(state->underlying_kind & SEC_ASN1_SIGNED_INT)) + #else + item->type == siUnsignedInteger) /* unsigned */ + #endif + { + while (len > 1 && buf[0] == 0) { /* leading 0 */ + buf++; + len--; + } + } + PORT_Memcpy (item->Data + item->Length, buf, len); + item->Length += len; + } + state->pending -= bufLen; + if (state->pending == 0) + state->place = beforeEndOfContents; + + return bufLen; +} + + +static unsigned long +sec_asn1d_parse_bit_string (sec_asn1d_state *state, + const char *buf, unsigned long len) +{ + unsigned char byte; + + /*PORT_Assert (state->pending > 0); */ + PORT_Assert (state->place == beforeBitString); + + if ((state->pending == 0) || (state->contents_length == 1)) { + if (state->dest != NULL) { + SecAsn1Item *item = (SecAsn1Item *)(state->dest); + item->Data = NULL; + item->Length = 0; + state->place = beforeEndOfContents; + } + if(state->contents_length == 1) { + /* skip over (unused) remainder byte */ + return 1; + } + else { + return 0; + } + } + + if (len == 0) { + state->top->status = needBytes; + return 0; + } + + byte = (unsigned char) *buf; + if (byte > 7) { + dprintf("decodeError: parse_bit_string remainder oflow\n"); + PORT_SetError (SEC_ERROR_BAD_DER); + state->top->status = decodeError; + return 0; + } + + state->bit_string_unused_bits = byte; + state->place = duringBitString; + state->pending -= 1; + + return 1; +} + + +static unsigned long +sec_asn1d_parse_more_bit_string (sec_asn1d_state *state, + const char *buf, unsigned long len) +{ + PORT_Assert (state->place == duringBitString); + if (state->pending == 0) { + /* An empty bit string with some unused bits is invalid. */ + if (state->bit_string_unused_bits) { + PORT_SetError (SEC_ERROR_BAD_DER); + state->top->status = decodeError; + } else { + /* An empty bit string with no unused bits is OK. */ + state->place = beforeEndOfContents; + } + return 0; + } + + len = sec_asn1d_parse_leaf (state, buf, len); + if (state->place == beforeEndOfContents && state->dest != NULL) { + SecAsn1Item *item; + + item = (SecAsn1Item *)(state->dest); + if (item->Length) + item->Length = (item->Length << 3) - state->bit_string_unused_bits; + } + + return len; +} + + +/* + * XXX All callers should be looking at return value to detect + * out-of-memory errors (and stop!). + */ +static struct subitem * +sec_asn1d_add_to_subitems (sec_asn1d_state *state, + const void *data, unsigned long len, + PRBool copy_data) +{ + struct subitem *thing; + + thing = (struct subitem*)sec_asn1d_zalloc (state->top->our_pool, + sizeof (struct subitem)); + if (thing == NULL) { + dprintf("decodeError: zalloc\n"); + state->top->status = decodeError; + return NULL; + } + + if (copy_data) { + void *copy; + copy = sec_asn1d_alloc (state->top->our_pool, len); + if (copy == NULL) { + dprintf("decodeError: alloc\n"); + state->top->status = decodeError; + return NULL; + } + PORT_Memcpy (copy, data, len); + thing->data = copy; + } else { + thing->data = data; + } + thing->len = len; + thing->next = NULL; + + if (state->subitems_head == NULL) { + PORT_Assert (state->subitems_tail == NULL); + state->subitems_head = state->subitems_tail = thing; + } else { + state->subitems_tail->next = thing; + state->subitems_tail = thing; + } + + return thing; +} + + +static void +sec_asn1d_record_any_header (sec_asn1d_state *state, + const char *buf, + unsigned long len) +{ + SecAsn1Item *item; + + item = (SecAsn1Item *)(state->dest); + if (item != NULL && item->Data != NULL) { + PORT_Assert (state->substring); + PORT_Memcpy (item->Data + item->Length, buf, len); + item->Length += len; + } else { + sec_asn1d_add_to_subitems (state, buf, len, PR_TRUE); + } +} + + +/* + * We are moving along through the substrings of a constructed string, + * and have just finished parsing one -- we need to save our child data + * (if the child was not already writing directly into the destination) + * and then move forward by one. + * + * We also have to detect when we are done: + * - a definite-length encoding stops when our pending value hits 0 + * - an indefinite-length encoding stops when our child is empty + * (which means it was the end-of-contents octets) + */ +static void +sec_asn1d_next_substring (sec_asn1d_state *state) +{ + sec_asn1d_state *child; + SecAsn1Item *item; + unsigned long child_consumed; + PRBool done; + + PORT_Assert (state->place == duringConstructedString); + PORT_Assert (state->child != NULL); + + child = state->child; + + child_consumed = child->consumed; + child->consumed = 0; + state->consumed += child_consumed; + + done = PR_FALSE; + + if (state->pending) { + PORT_Assert (!state->indefinite); + if( child_consumed > state->pending ) { + dprintf("decodeError: next_substring consumed > pend\n"); + PORT_SetError (SEC_ERROR_BAD_DER); + state->top->status = decodeError; + return; + } + + state->pending -= child_consumed; + if (state->pending == 0) + done = PR_TRUE; + } else { + PORT_Assert (state->indefinite); + + item = (SecAsn1Item *)(child->dest); + if (item != NULL && item->Data != NULL) { + /* + * Save the string away for later concatenation. + */ + PORT_Assert (item->Data != NULL); + sec_asn1d_add_to_subitems (state, item->Data, item->Length, PR_FALSE); + /* + * Clear the child item for the next round. + */ + item->Data = NULL; + item->Length = 0; + } + + /* + * If our child was just our end-of-contents octets, we are done. + */ + if (child->endofcontents) + done = PR_TRUE; + } + + /* + * Stop or do the next one. + */ + if (done) { + child->place = notInUse; + state->place = afterConstructedString; + } else { + sec_asn1d_scrub_state (child); + state->top->current = child; + } +} + + +/* + * We are doing a SET OF or SEQUENCE OF, and have just finished an item. + */ +static void +sec_asn1d_next_in_group (sec_asn1d_state *state, + const char *buf /* __APPLE__ */) +{ + sec_asn1d_state *child; + unsigned long child_consumed; + + PORT_Assert (state->place == duringGroup); + PORT_Assert (state->child != NULL); + + child = state->child; + + child_consumed = child->consumed; + child->consumed = 0; + state->consumed += child_consumed; + + /* + * If our child was just our end-of-contents octets, we are done. + */ + #ifdef __APPLE__ + /* + * Without the check for !child->indefinite, this path could + * be taken erroneously if the child is indefinite! + */ + if(child->endofcontents && !child->indefinite) { + #else + if (child->endofcontents) { + #endif /* __APPLE__ */ + /* XXX I removed the PORT_Assert (child->dest == NULL) because there + * was a bug in that a template that was a sequence of which also had + * a child of a sequence of, in an indefinite group was not working + * properly. This fix seems to work, (added the if statement below), + * and nothing appears broken, but I am putting this note here just + * in case. */ + /* + * XXX No matter how many times I read that comment, + * I cannot figure out what case he was fixing. I believe what he + * did was deliberate, so I am loathe to touch it. I need to + * understand how it could ever be that child->dest != NULL but + * child->endofcontents is true, and why it is important to check + * that state->subitems_head is NULL. This really needs to be + * figured out, as I am not sure if the following code should be + * compensating for "offset", as is done a little farther below + * in the more normal case. + */ + PORT_Assert (state->indefinite); + PORT_Assert (state->pending == 0); + if(child->dest && !state->subitems_head) { + sec_asn1d_add_to_subitems (state, child->dest, 0, PR_FALSE); + child->dest = NULL; + } + + child->place = notInUse; + state->place = afterGroup; + return; + } + + /* + * Do the "after" field notification for next in group. + */ + sec_asn1d_notify_after (state->top, child->dest, child->depth); + + /* + * Save it away (unless we are not storing). + */ + if (child->dest != NULL) { + void *dest; + + dest = child->dest; + dest = (char *)dest - child->theTemplate->offset; + sec_asn1d_add_to_subitems (state, dest, 0, PR_FALSE); + child->dest = NULL; + } + + /* + * Account for those bytes; see if we are done. + */ + if (state->pending) { + PORT_Assert (!state->indefinite); + if( child_consumed > state->pending ) { + dprintf("decodeError: next_in_group consumed > pend\n"); + PORT_SetError (SEC_ERROR_BAD_DER); + state->top->status = decodeError; + return; + } + + state->pending -= child_consumed; + if (state->pending == 0) { + child->place = notInUse; + state->place = afterGroup; + return; + } + } + + /* + * Do the "before" field notification for next item in group. + */ + sec_asn1d_notify_before (state->top, child->dest, child->depth); + + /* + * Now we do the next one. + */ + sec_asn1d_scrub_state (child); + + /* Initialize child state from the template */ + sec_asn1d_init_state_based_on_template(child, buf /* __APPLE__ */); + + state->top->current = child; +} + + +/* + * We are moving along through a sequence; move forward by one, + * (detecting end-of-sequence when it happens). + * XXX The handling of "missing" is ugly. Fix it. + */ +static void +sec_asn1d_next_in_sequence (sec_asn1d_state *state, + const char *buf /* __APPLE__ */) +{ + sec_asn1d_state *child; + unsigned long child_consumed; + PRBool child_missing; + + PORT_Assert (state->place == duringSequence); + PORT_Assert (state->child != NULL); + + child = state->child; + + /* + * Do the "after" field notification. + */ + sec_asn1d_notify_after (state->top, child->dest, child->depth); + + child_missing = (PRBool) child->missing; + child_consumed = child->consumed; + child->consumed = 0; + + /* + * Take care of accounting. + */ + if (child_missing) { + PORT_Assert (child->optional); + } else { + state->consumed += child_consumed; + /* + * Free any grandchild. + */ + sec_asn1d_free_child (child, PR_FALSE); + if (state->pending) { + PORT_Assert (!state->indefinite); + if( child_consumed > state->pending ) { + dprintf("decodeError: next_in_seq consumed > pend\n"); + PORT_SetError (SEC_ERROR_BAD_DER); + state->top->status = decodeError; + return; + } + state->pending -= child_consumed; + if (state->pending == 0) { + child->theTemplate++; + while (child->theTemplate->kind != 0) { + if ((child->theTemplate->kind & SEC_ASN1_OPTIONAL) == 0) { + dprintf("decodeError: next_in_seq child not opt\n"); + PORT_SetError (SEC_ERROR_BAD_DER); + state->top->status = decodeError; + return; + } + child->theTemplate++; + } + child->place = notInUse; + state->place = afterEndOfContents; + return; + } + } + } + + /* + * Move forward. + */ + child->theTemplate++; + if (child->theTemplate->kind == 0) { + /* + * We are done with this sequence. + */ + child->place = notInUse; + if (state->pending) { + dprintf("decodeError: next_in_seq notInUse still pending\n"); + PORT_SetError (SEC_ERROR_BAD_DER); + state->top->status = decodeError; + } else if (child_missing) { + /* + * We got to the end, but have a child that started parsing + * and ended up "missing". The only legitimate reason for + * this is that we had one or more optional fields at the + * end of our sequence, and we were encoded indefinite-length, + * so when we went looking for those optional fields we + * found our end-of-contents octets instead. + * (Yes, this is ugly; dunno a better way to handle it.) + * So, first confirm the situation, and then mark that we + * are done. + */ + if (state->indefinite && child->endofcontents) { + PORT_Assert (child_consumed == 2); + if( child_consumed != 2 ) { + dprintf("decodeError: next_in_seq indef len != 2\n"); + PORT_SetError (SEC_ERROR_BAD_DER); + state->top->status = decodeError; + } else { + state->consumed += child_consumed; + state->place = afterEndOfContents; + } + } else { + dprintf("decodeError: next_in_seq !indef, child missing\n"); + PORT_SetError (SEC_ERROR_BAD_DER); + state->top->status = decodeError; + } + } else { + /* + * We have to finish out, maybe reading end-of-contents octets; + * let the normal logic do the right thing. + */ + state->place = beforeEndOfContents; + } + } else { + unsigned char child_found_tag_modifiers = 0; + unsigned long child_found_tag_number = 0; + + /* + * Reset state and push. + */ + if (state->dest != NULL) + child->dest = (char *)state->dest + child->theTemplate->offset; + + /* + * Do the "before" field notification. + */ + sec_asn1d_notify_before (state->top, child->dest, child->depth); + + if (child_missing) { /* if previous child was missing, copy the tag data we already have */ + child_found_tag_modifiers = child->found_tag_modifiers; + child_found_tag_number = child->found_tag_number; + } + state->top->current = child; + child = sec_asn1d_init_state_based_on_template (child, + buf /* __APPLE__ */); + if (child_missing) { + child->place = afterIdentifier; + child->found_tag_modifiers = child_found_tag_modifiers; + child->found_tag_number = child_found_tag_number; + child->consumed = child_consumed; + if (child->underlying_kind == SEC_ASN1_ANY + && !child->top->filter_only) { + /* + * If the new field is an ANY, and we are storing, then + * we need to save the tag out. We would have done this + * already in the normal case, but since we were looking + * for an optional field, and we did not find it, we only + * now realize we need to save the tag. + */ + unsigned char identifier; + + /* + * Check that we did not end up with a high tag; for that + * we need to re-encode the tag into multiple bytes in order + * to store it back to look like what we parsed originally. + * In practice this does not happen, but for completeness + * sake it should probably be made to work at some point. + */ + PORT_Assert (child_found_tag_number < SEC_ASN1_HIGH_TAG_NUMBER); + identifier = (unsigned char)(child_found_tag_modifiers | child_found_tag_number); + sec_asn1d_record_any_header (child, (char *) &identifier, 1); + } + } + } +} + + +static void +sec_asn1d_concat_substrings (sec_asn1d_state *state) +{ + PORT_Assert (state->place == afterConstructedString); + + if (state->subitems_head != NULL) { + struct subitem *substring; + unsigned long alloc_len, item_len; + unsigned char *where; + SecAsn1Item *item; + PRBool is_bit_string; + + item_len = 0; + is_bit_string = (state->underlying_kind == SEC_ASN1_BIT_STRING) + ? PR_TRUE : PR_FALSE; + + substring = state->subitems_head; + while (substring != NULL) { + /* + * All bit-string substrings except the last one should be + * a clean multiple of 8 bits. + */ + if (is_bit_string && (substring->next == NULL) + && (substring->len & 0x7)) { + dprintf("decodeError: sec_asn1d_concat_substrings align\n"); + PORT_SetError (SEC_ERROR_BAD_DER); + state->top->status = decodeError; + return; + } + item_len += substring->len; + substring = substring->next; + } + + if (is_bit_string) { +#ifdef XP_WIN16 /* win16 compiler gets an internal error otherwise */ + alloc_len = (((long)item_len + 7) / 8); +#else + alloc_len = ((item_len + 7) >> 3); +#endif + } else { + /* + * Add 2 for the end-of-contents octets of an indefinite-length + * ANY that is *not* also an INNER. Because we zero-allocate + * below, all we need to do is increase the length here. + */ + if (state->underlying_kind == SEC_ASN1_ANY && state->indefinite) + item_len += 2; + alloc_len = item_len; + } + + item = (SecAsn1Item *)(state->dest); + PORT_Assert (item != NULL); + PORT_Assert (item->Data == NULL); + item->Data = (unsigned char*)sec_asn1d_zalloc (state->top->their_pool, + alloc_len); + if (item->Data == NULL) { + dprintf("decodeError: zalloc\n"); + state->top->status = decodeError; + return; + } + item->Length = item_len; + + where = item->Data; + substring = state->subitems_head; + while (substring != NULL) { + if (is_bit_string) + item_len = (substring->len + 7) >> 3; + else + item_len = substring->len; + PORT_Memcpy (where, substring->data, item_len); + where += item_len; + substring = substring->next; + } + + /* + * Because we use arenas and have a mark set, we later free + * everything we have allocated, so this does *not* present + * a memory leak (it is just temporarily left dangling). + */ + state->subitems_head = state->subitems_tail = NULL; + } + + state->place = afterEndOfContents; +} + + +static void +sec_asn1d_concat_group (sec_asn1d_state *state) +{ + const void ***placep; + + PORT_Assert (state->place == afterGroup); + + placep = (const void***)state->dest; + PORT_Assert(state->subitems_head == NULL || placep != NULL); + if (placep != NULL) { + struct subitem *item; + const void **group; + int count; + + count = 0; + item = state->subitems_head; + while (item != NULL) { + PORT_Assert (item->next != NULL || item == state->subitems_tail); + count++; + item = item->next; + } + + group = (const void**)sec_asn1d_zalloc (state->top->their_pool, + (count + 1) * (sizeof(void *))); + if (group == NULL) { + dprintf("decodeError: zalloc\n"); + state->top->status = decodeError; + return; + } + + *placep = group; + + item = state->subitems_head; + while (item != NULL) { + *group++ = item->data; + item = item->next; + } + *group = NULL; + + /* + * Because we use arenas and have a mark set, we later free + * everything we have allocated, so this does *not* present + * a memory leak (it is just temporarily left dangling). + */ + state->subitems_head = state->subitems_tail = NULL; + } + + state->place = afterEndOfContents; +} + +/* + * For those states that push a child to handle a subtemplate, + * "absorb" that child (transfer necessary information). + */ +static void +sec_asn1d_absorb_child (sec_asn1d_state *state) +{ + /* + * There is absolutely supposed to be a child there. + */ + PORT_Assert (state->child != NULL); + + /* + * Inherit the missing status of our child, and do the ugly + * backing-up if necessary. + */ + state->missing = state->child->missing; + if (state->missing) { + state->found_tag_number = state->child->found_tag_number; + state->found_tag_modifiers = state->child->found_tag_modifiers; + state->endofcontents = state->child->endofcontents; + } + + /* + * Add in number of bytes consumed by child. + * (Only EXPLICIT should have already consumed bytes itself.) + */ + PORT_Assert (state->place == afterExplicit || state->consumed == 0); + state->consumed += state->child->consumed; + + /* + * Subtract from bytes pending; this only applies to a definite-length + * EXPLICIT field. + */ + if (state->pending) { + PORT_Assert (!state->indefinite); + PORT_Assert (state->place == afterExplicit); + + /* + * If we had a definite-length explicit, then what the child + * consumed should be what was left pending. + */ + if (state->pending != state->child->consumed) { + if (state->pending < state->child->consumed) { + dprintf("decodeError: absorb_child pending < consumed\n"); + PORT_SetError (SEC_ERROR_BAD_DER); + state->top->status = decodeError; + return; + } + /* + * Okay, this is a hack. It *should* be an error whether + * pending is too big or too small, but it turns out that + * we had a bug in our *old* DER encoder that ended up + * counting an explicit header twice in the case where + * the underlying type was an ANY. So, because we cannot + * prevent receiving these (our own certificate server can + * send them to us), we need to be lenient and accept them. + * To do so, we need to pretend as if we read all of the + * bytes that the header said we would find, even though + * we actually came up short. + */ + state->consumed += (state->pending - state->child->consumed); + } + state->pending = 0; + } + + /* + * Indicate that we are done with child. + */ + state->child->consumed = 0; + + /* + * And move on to final state. + * (Technically everybody could move to afterEndOfContents except + * for an indefinite-length EXPLICIT; for simplicity though we assert + * that but let the end-of-contents code do the real determination.) + */ + PORT_Assert (state->place == afterExplicit || (! state->indefinite)); + state->place = beforeEndOfContents; +} + + +static void +sec_asn1d_prepare_for_end_of_contents (sec_asn1d_state *state) +{ + PORT_Assert (state->place == beforeEndOfContents); + + if (state->indefinite) { + state->place = duringEndOfContents; + state->pending = 2; + } else { + state->place = afterEndOfContents; + } +} + + +static unsigned long +sec_asn1d_parse_end_of_contents (sec_asn1d_state *state, + const char *buf, unsigned long len) +{ + unsigned int i; + + PORT_Assert (state->pending <= 2); + PORT_Assert (state->place == duringEndOfContents); + + if (len == 0) { + state->top->status = needBytes; + return 0; + } + + if (state->pending < len) + len = state->pending; + + for (i = 0; i < len; i++) { + if (buf[i] != 0) { + /* + * We expect to find only zeros; if not, just give up. + */ + dprintf("decodeError: end of contents non zero\n"); + PORT_SetError (SEC_ERROR_BAD_DER); + state->top->status = decodeError; + return 0; + } + } + + state->pending -= len; + + if (state->pending == 0) { + state->place = afterEndOfContents; + state->endofcontents = PR_TRUE; + } + + return len; +} + + +static void +sec_asn1d_pop_state (sec_asn1d_state *state) +{ +#if 0 /* XXX I think this should always be handled explicitly by parent? */ + /* + * Account for our child. + */ + if (state->child != NULL) { + state->consumed += state->child->consumed; + if (state->pending) { + PORT_Assert (!state->indefinite); + if( state->child->consumed > state->pending ) { + dprintf("decodeError: pop_state pending < consumed\n"); + PORT_SetError (SEC_ERROR_BAD_DER); + state->top->status = decodeError; + } else { + state->pending -= state->child->consumed; + } + } + state->child->consumed = 0; + } +#endif /* XXX */ + + /* + * Free our child. + */ + sec_asn1d_free_child (state, PR_FALSE); + + /* + * Just make my parent be the current state. It will then clean + * up after me and free me (or reuse me). + */ + state->top->current = state->parent; +} + +static sec_asn1d_state * +sec_asn1d_before_choice (sec_asn1d_state *state, const char *buf /* __APPLE__ */) +{ + sec_asn1d_state *child; + + if( state->allocate ) { + void *dest; + + dest = sec_asn1d_zalloc(state->top->their_pool, + state->theTemplate->size); + if( (void *)NULL == dest ) { + dprintf("decodeError: zalloc\n"); + state->top->status = decodeError; + return (sec_asn1d_state *)NULL; + } + + state->dest = (char *)dest + state->theTemplate->offset; + } + + child = sec_asn1d_push_state(state->top, state->theTemplate + 1, + (char *)state->dest - state->theTemplate->offset, + PR_FALSE); + if( (sec_asn1d_state *)NULL == child ) { + return (sec_asn1d_state *)NULL; + } + + sec_asn1d_scrub_state(child); + child = sec_asn1d_init_state_based_on_template(child, + buf /* __APPLE__ */); + if( (sec_asn1d_state *)NULL == child ) { + return (sec_asn1d_state *)NULL; + } + + child->optional = PR_TRUE; + + state->place = duringChoice; + + return child; +} + +static sec_asn1d_state * +sec_asn1d_during_choice (sec_asn1d_state *state, const char *buf /* __APPLE__ */) +{ + sec_asn1d_state *child = state->child; + + PORT_Assert((sec_asn1d_state *)NULL != child); + + if( child->missing ) { + unsigned char child_found_tag_modifiers = 0; + unsigned long child_found_tag_number = 0; + void * dest; + + state->consumed += child->consumed; + + if (child->endofcontents) { + /* This choice is probably the first item in a GROUP + ** (e.g. SET_OF) that was indefinite-length encoded. + ** We're actually at the end of that GROUP. + ** We look up the stack to be sure that we find + ** a state with indefinite length encoding before we + ** find a state (like a SEQUENCE) that is definite. + */ + child->place = notInUse; + state->place = afterChoice; + state->endofcontents = PR_TRUE; /* propagate this up */ + if (sec_asn1d_parent_allows_EOC(state)) + return state; + dprintf("decodeError: during_choice child at EOC by parent does not allow EOC\n"); + PORT_SetError(SEC_ERROR_BAD_DER); + state->top->status = decodeError; + return NULL; + } + + dest = (char *)child->dest - child->theTemplate->offset; + child->theTemplate++; + + if( 0 == child->theTemplate->kind ) { + /* Ran out of choices */ + dprintf("decodeError: during_choice ran out of choice\n"); + PORT_SetError(SEC_ERROR_BAD_DER); + state->top->status = decodeError; + return (sec_asn1d_state *)NULL; + } + child->dest = (char *)dest + child->theTemplate->offset; + + /* cargo'd from next_in_sequence innards */ + if( state->pending ) { + PORT_Assert(!state->indefinite); + if( child->consumed > state->pending ) { + dprintf("decodeError: during_choice consumed > pending\n"); + PORT_SetError (SEC_ERROR_BAD_DER); + state->top->status = decodeError; + return NULL; + } + state->pending -= child->consumed; + if( 0 == state->pending ) { + /* XXX uh.. not sure if I should have stopped this + * from happening before. */ + PORT_Assert(0); + PORT_SetError(SEC_ERROR_BAD_DER); + dprintf("decodeError: during_choice !pending\n"); + state->top->status = decodeError; + return (sec_asn1d_state *)NULL; + } + } + + child->consumed = 0; + sec_asn1d_scrub_state(child); + + /* move it on top again */ + state->top->current = child; + + child_found_tag_modifiers = child->found_tag_modifiers; + child_found_tag_number = child->found_tag_number; + + child = sec_asn1d_init_state_based_on_template(child, buf /* __APPLE__*/); + if( (sec_asn1d_state *)NULL == child ) { + return (sec_asn1d_state *)NULL; + } + + /* copy our findings to the new top */ + child->found_tag_modifiers = child_found_tag_modifiers; + child->found_tag_number = child_found_tag_number; + + child->optional = PR_TRUE; + child->place = afterIdentifier; + + return child; + } + if( (void *)NULL != state->dest ) { + /* Store the enum */ + int *which = (int *)state->dest; + *which = (int)child->theTemplate->size; + } + + child->place = notInUse; + + state->place = afterChoice; + return state; +} + +static void +sec_asn1d_after_choice (sec_asn1d_state *state) +{ + state->consumed += state->child->consumed; + state->child->consumed = 0; + state->place = afterEndOfContents; + sec_asn1d_pop_state(state); +} + +#if 0 +unsigned long +sec_asn1d_uinteger(SecAsn1Item *src) +{ + unsigned long value; + int len; + + if (src->Length > 5 || (src->Length > 4 && src->Data[0] == 0)) + return 0; + + value = 0; + len = src->Length; + while (len) { + value <<= 8; + value |= src->Data[--len]; + } + return value; +} +#endif + +SECStatus +SEC_ASN1DecodeInteger(SecAsn1Item *src, unsigned long *value) +{ + unsigned long v; + unsigned int i; + + if (src == NULL) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + + if (src->Length > sizeof(unsigned long)) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + + if (src->Data == NULL) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + + if (src->Data[0] & 0x80) + v = -1; /* signed and negative - start with all 1's */ + else + v = 0; + + for (i= 0; i < src->Length; i++) { + /* shift in next byte */ + v <<= 8; + v |= src->Data[i]; + } + *value = v; + return SECSuccess; +} + +#ifdef DEBUG_ASN1D_STATES +static void +dump_states(SEC_ASN1DecoderContext *cx) +{ + sec_asn1d_state *state; + char kindBuf[256]; + + for (state = cx->current; state->parent; state = state->parent) { + ; + } + + for (; state; state = state->child) { + int i; + for (i = 0; i < state->depth; i++) { + printf(" "); + } + + i = formatKind(state->theTemplate->kind, kindBuf); + printf("%s: tmpl %p, kind%s", + (state == cx->current) ? "STATE" : "State", + state->theTemplate, + kindBuf); + printf(" %s", (state->place <= notInUse) + ? place_names[ state->place ] + : "(undefined)"); + if (!i) + printf(", expect 0x%02lx", + state->expect_tag_number | state->expect_tag_modifiers); + + printf("%s%s%s %lu\n", + state->indefinite ? ", indef" : "", + state->missing ? ", miss" : "", + state->endofcontents ? ", EOC" : "", + state->pending + ); + } + + return; +} +#endif /* DEBUG_ASN1D_STATES */ + +SECStatus +SEC_ASN1DecoderUpdate (SEC_ASN1DecoderContext *cx, + const char *buf, size_t len) +{ + sec_asn1d_state *state = NULL; + unsigned long consumed; + SEC_ASN1EncodingPart what; + sec_asn1d_state *stateEnd = cx->current; + + if (cx->status == needBytes) + cx->status = keepGoing; + + while (cx->status == keepGoing) { + state = cx->current; + what = SEC_ASN1_Contents; + consumed = 0; + #if DEBUG_ASN1D_STATES + if (doDumpStates > 1) { + printf("\nPLACE = %s, next byte = 0x%02x, %p[%lu]\n", + (state->place <= notInUse) ? + place_names[ state->place ] : "(undefined)", + (unsigned int)((unsigned char *)buf)[ consumed ], + buf, consumed); + dump_states(cx); + } + #endif /* DEBUG_ASN1D_STATES */ + switch (state->place) { + case beforeIdentifier: + consumed = sec_asn1d_parse_identifier (state, buf, len); + what = SEC_ASN1_Identifier; + break; + case duringIdentifier: + consumed = sec_asn1d_parse_more_identifier (state, buf, len); + what = SEC_ASN1_Identifier; + break; + case afterIdentifier: + sec_asn1d_confirm_identifier (state); + break; + case beforeLength: + consumed = sec_asn1d_parse_length (state, buf, len); + what = SEC_ASN1_Length; + break; + case duringLength: + consumed = sec_asn1d_parse_more_length (state, buf, len); + what = SEC_ASN1_Length; + break; + case afterLength: + sec_asn1d_prepare_for_contents (state, buf); + break; + case beforeBitString: + consumed = sec_asn1d_parse_bit_string (state, buf, len); + break; + case duringBitString: + consumed = sec_asn1d_parse_more_bit_string (state, buf, len); + break; + case duringConstructedString: + sec_asn1d_next_substring (state); + break; + case duringGroup: + sec_asn1d_next_in_group (state, buf); + break; + case duringLeaf: + consumed = sec_asn1d_parse_leaf (state, buf, len); + break; + case duringSaveEncoding: + sec_asn1d_reuse_encoding (state); + if (cx->status == decodeError) { + /* recursive call has already popped all states from stack. + ** Bail out quickly. + */ + return SECFailure; + } + if (cx->status == needBytes) { + /* recursive call wanted more data. Fatal. Clean up below. */ + PORT_SetError (SEC_ERROR_BAD_DER); + cx->status = decodeError; + } + break; + case duringSequence: + sec_asn1d_next_in_sequence (state, buf); + break; + case afterConstructedString: + sec_asn1d_concat_substrings (state); + break; + case afterExplicit: + case afterImplicit: + case afterInline: + case afterPointer: + sec_asn1d_absorb_child (state); + break; + case afterGroup: + sec_asn1d_concat_group (state); + break; + case afterSaveEncoding: + /* SEC_ASN1DecoderUpdate has called itself recursively to + ** decode SAVEd encoded data, and now is done decoding that. + ** Return to the calling copy of SEC_ASN1DecoderUpdate. + */ + return SECSuccess; + case beforeEndOfContents: + sec_asn1d_prepare_for_end_of_contents (state); + break; + case duringEndOfContents: + consumed = sec_asn1d_parse_end_of_contents (state, buf, len); + what = SEC_ASN1_EndOfContents; + break; + case afterEndOfContents: + sec_asn1d_pop_state (state); + break; + case beforeChoice: + state = sec_asn1d_before_choice(state, buf); + break; + case duringChoice: + state = sec_asn1d_during_choice(state, buf); + break; + case afterChoice: + sec_asn1d_after_choice(state); + break; + case notInUse: + default: + /* This is not an error, but rather a plain old BUG! */ + PORT_Assert (0); + PORT_SetError (SEC_ERROR_BAD_DER); + dprintf("decodeError: decoder update bad state->place\n"); + cx->status = decodeError; + break; + } + + if (cx->status == decodeError) + break; + + /* We should not consume more than we have. */ + PORT_Assert (consumed <= len); + if( consumed > len ) { + dprintf("decodeError: decoder update consumed > len\n"); + PORT_SetError (SEC_ERROR_BAD_DER); + cx->status = decodeError; + break; + } + + /* It might have changed, so we have to update our local copy. */ + state = cx->current; + + /* If it is NULL, we have popped all the way to the top. */ + if (state == NULL) { + PORT_Assert (consumed == 0); + #if 0 + /* XXX I want this here, but it seems that we have situations (like + * downloading a pkcs7 cert chain from some issuers) that give us a + * length which is greater than the entire encoding. So, we cannot + * have this be an error. + */ + if (len > 0) { + dprintf("decodeError: decoder update nonzero len\n"); + PORT_SetError (SEC_ERROR_BAD_DER); + cx->status = decodeError; + } + else + #endif + cx->status = allDone; + break; + } + else if (state->theTemplate->kind == SEC_ASN1_SKIP_REST) { + cx->status = allDone; + break; + } + + if (consumed == 0) + continue; + + /* + * The following check is specifically looking for an ANY + * that is *not* also an INNER, because we need to save aside + * all bytes in that case -- the contents parts will get + * handled like all other contents, and the end-of-contents + * bytes are added by the concat code, but the outer header + * bytes need to get saved too, so we do them explicitly here. + */ + if (state->underlying_kind == SEC_ASN1_ANY + && !cx->filter_only && (what == SEC_ASN1_Identifier + || what == SEC_ASN1_Length)) { + sec_asn1d_record_any_header (state, buf, consumed); + } + + /* + * We had some number of good, accepted bytes. If the caller + * has registered to see them, pass them along. + */ + if (state->top->filter_proc != NULL) { + int depth; + + depth = state->depth; + if (what == SEC_ASN1_EndOfContents && !state->indefinite) { + PORT_Assert (state->parent != NULL + && state->parent->indefinite); + depth--; + PORT_Assert (depth == state->parent->depth); + } + (* state->top->filter_proc) (state->top->filter_arg, + buf, consumed, depth, what); + } + + state->consumed += consumed; + buf += consumed; + len -= consumed; + } /* main decode loop */ + + if (cx->status == decodeError) { + while (state != NULL && stateEnd->parent!=state) { + sec_asn1d_free_child (state, PR_TRUE); + state = state->parent; + } +#ifdef SEC_ASN1D_FREE_ON_ERROR /* + * XXX This does not work because we can + * end up leaving behind dangling pointers + * to stuff that was allocated. In order + * to make this really work (which would + * be a good thing, I think), we need to + * keep track of every place/pointer that + * was allocated and make sure to NULL it + * out before we then free back to the mark. + */ + if (cx->their_pool != NULL) { + PORT_Assert (cx->their_mark != NULL); + PORT_ArenaRelease (cx->their_pool, cx->their_mark); + } +#endif + return SECFailure; + } + +#if 0 + /* XXX This is what I want, but cannot have because it seems we + * have situations (like when downloading a pkcs7 cert chain from + * some issuers) that give us a total length which is greater than + * the entire encoding. So, we have to allow allDone to have a + * remaining length greater than zero. I wanted to catch internal + * bugs with this, noticing when we do not have the right length. + * Oh well. + */ + PORT_Assert (len == 0 + && (cx->status == needBytes || cx->status == allDone)); +#else + PORT_Assert ((len == 0 && cx->status == needBytes) + || cx->status == allDone); +#endif + return SECSuccess; +} + + +SECStatus +SEC_ASN1DecoderFinish (SEC_ASN1DecoderContext *cx) +{ + SECStatus rv; + + if (cx->status == needBytes) { + #ifdef __APPLE__ + /* + * Special case: need more bytes, but this field and all + * subsequent fields are optional. I'm surprised this case is + * not handled in the original NSS code, and this workaround + * is a bit of a hack... + */ + sec_asn1d_state *state = cx->current; + assert(state != NULL); + if(state->place == beforeIdentifier) { + int allOptional = 1; + const SecAsn1Template *templ = state->theTemplate; + while(templ->kind != 0) { + if(!(templ->kind & SEC_ASN1_OPTIONAL)) { + allOptional = 0; + break; + } + templ++; + } + if(allOptional) { + /* letting this one slide */ + rv = SECSuccess; + } + else { + PORT_SetError (SEC_ERROR_BAD_DER); + rv = SECFailure; + } + } + else { + PORT_SetError (SEC_ERROR_BAD_DER); + rv = SECFailure; + } + #else + PORT_SetError (SEC_ERROR_BAD_DER); + rv = SECFailure; + #endif /* __APPLE__ */ + } else { + rv = SECSuccess; + } + + /* + * XXX anything else that needs to be finished? + */ + + PORT_FreeArena (cx->our_pool, PR_FALSE); + + return rv; +} + + +SEC_ASN1DecoderContext * +SEC_ASN1DecoderStart (PRArenaPool *their_pool, void *dest, + const SecAsn1Template *theTemplate + #ifdef __APPLE__ + , + /* only needed if first element will be SEC_ASN1_DYNAMIC */ + const char *buf + #endif + ) +{ + PRArenaPool *our_pool; + SEC_ASN1DecoderContext *cx; + + our_pool = PORT_NewArena (SEC_ASN1_DEFAULT_ARENA_SIZE); + if (our_pool == NULL) + return NULL; + + cx = (SEC_ASN1DecoderContext*)PORT_ArenaZAlloc (our_pool, sizeof(*cx)); + if (cx == NULL) { + PORT_FreeArena (our_pool, PR_FALSE); + return NULL; + } + + cx->our_pool = our_pool; + if (their_pool != NULL) { + cx->their_pool = their_pool; +#ifdef SEC_ASN1D_FREE_ON_ERROR + cx->their_mark = PORT_ArenaMark (their_pool); +#endif + } + + cx->status = needBytes; + + if (sec_asn1d_push_state(cx, theTemplate, dest, PR_FALSE) == NULL + || sec_asn1d_init_state_based_on_template (cx->current, + buf /* __APPLE__ */) == NULL) { + /* + * Trouble initializing (probably due to failed allocations) + * requires that we just give up. + */ + PORT_FreeArena (our_pool, PR_FALSE); + return NULL; + } + + return cx; +} + + +void +SEC_ASN1DecoderSetFilterProc (SEC_ASN1DecoderContext *cx, + SEC_ASN1WriteProc fn, void *arg, + PRBool only) +{ + /* check that we are "between" fields here */ + PORT_Assert (cx->during_notify); + + cx->filter_proc = fn; + cx->filter_arg = arg; + cx->filter_only = only; +} + + +void +SEC_ASN1DecoderClearFilterProc (SEC_ASN1DecoderContext *cx) +{ + /* check that we are "between" fields here */ + PORT_Assert (cx->during_notify); + + cx->filter_proc = NULL; + cx->filter_arg = NULL; + cx->filter_only = PR_FALSE; +} + + +void +SEC_ASN1DecoderSetNotifyProc (SEC_ASN1DecoderContext *cx, + SEC_ASN1NotifyProc fn, void *arg) +{ + cx->notify_proc = fn; + cx->notify_arg = arg; +} + + +void +SEC_ASN1DecoderClearNotifyProc (SEC_ASN1DecoderContext *cx) +{ + cx->notify_proc = NULL; + cx->notify_arg = NULL; /* not necessary; just being clean */ +} + + +void +SEC_ASN1DecoderAbort(SEC_ASN1DecoderContext *cx, int error) +{ + PORT_Assert(cx); + PORT_SetError(error); + cx->status = decodeError; +} + + +SECStatus +SEC_ASN1Decode (PRArenaPool *poolp, void *dest, + const SecAsn1Template *theTemplate, + const char *buf, size_t len) +{ + SEC_ASN1DecoderContext *dcx; + SECStatus urv, frv; + + dcx = SEC_ASN1DecoderStart (poolp, dest, theTemplate, + buf /* __APPLE__ */); + if (dcx == NULL) + return SECFailure; + + urv = SEC_ASN1DecoderUpdate (dcx, buf, len); + frv = SEC_ASN1DecoderFinish (dcx); + + if (urv != SECSuccess) + return urv; + + return frv; +} + + +SECStatus +SEC_ASN1DecodeItem (PRArenaPool *poolp, void *dest, + const SecAsn1Template *theTemplate, + const SecAsn1Item *item) +{ + return SEC_ASN1Decode (poolp, dest, theTemplate, + (const char *) item->Data, item->Length); +} + + diff --git a/libsecurity_asn1/lib/secasn1e.c b/libsecurity_asn1/lib/secasn1e.c new file mode 100644 index 00000000..e7d608f8 --- /dev/null +++ b/libsecurity_asn1/lib/secasn1e.c @@ -0,0 +1,1639 @@ +/* + * 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 for ENcoding ASN.1 data based on BER/DER (Basic/Distinguished + * Encoding Rules). + * + * $Id: secasn1e.c,v 1.7 2004/05/13 15:29:13 dmitch Exp $ + */ + +#include "secasn1.h" + +typedef enum { + beforeHeader, + duringContents, + duringGroup, + duringSequence, + afterContents, + afterImplicit, + afterInline, + afterPointer, + afterChoice, + notInUse +} sec_asn1e_parse_place; + +typedef enum { + allDone, + encodeError, + keepGoing, + needBytes +} sec_asn1e_parse_status; + +typedef struct sec_asn1e_state_struct { + SEC_ASN1EncoderContext *top; + const SecAsn1Template *theTemplate; + void *src; + + struct sec_asn1e_state_struct *parent; /* aka prev */ + struct sec_asn1e_state_struct *child; /* aka next */ + + sec_asn1e_parse_place place; /* where we are in encoding process */ + + /* + * XXX explain the next fields as clearly as possible... + */ + unsigned char tag_modifiers; + unsigned char tag_number; + unsigned long underlying_kind; + + int depth; + + PRBool explicit, /* we are handling an explicit header */ + indefinite, /* need end-of-contents */ + is_string, /* encoding a simple string or an ANY */ + may_stream, /* when streaming, do indefinite encoding */ + optional, /* omit field if it has no contents */ + ignore_stream /* ignore streaming value of sub-template */ + #ifdef __APPLE__ + , + signedInt /* signed alternate to SEC_ASN1_INTEGER */ + #endif + ; +} sec_asn1e_state; + +/* + * An "outsider" will have an opaque pointer to this, created by calling + * SEC_ASN1EncoderStart(). It will be passed back in to all subsequent + * calls to SEC_ASN1EncoderUpdate() and related routines, and when done + * it is passed to SEC_ASN1EncoderFinish(). + */ +struct sec_EncoderContext_struct { + PRArenaPool *our_pool; /* for our internal allocs */ + + sec_asn1e_state *current; + sec_asn1e_parse_status status; + + PRBool streaming; + PRBool from_buf; + + SEC_ASN1NotifyProc notify_proc; /* call before/after handling field */ + void *notify_arg; /* argument to notify_proc */ + PRBool during_notify; /* true during call to notify_proc */ + + SEC_ASN1WriteProc output_proc; /* pass encoded bytes to this */ + void *output_arg; /* argument to that function */ +}; + + +static sec_asn1e_state * +sec_asn1e_push_state (SEC_ASN1EncoderContext *cx, + const SecAsn1Template *theTemplate, + const void *src, PRBool new_depth) +{ + sec_asn1e_state *state, *new_state; + + state = cx->current; + + new_state = (sec_asn1e_state*)PORT_ArenaZAlloc (cx->our_pool, + sizeof(*new_state)); + if (new_state == NULL) { + cx->status = encodeError; + return NULL; + } + + new_state->top = cx; + new_state->parent = state; + new_state->theTemplate = theTemplate; + new_state->place = notInUse; + if (src != NULL) + new_state->src = (char *)src + theTemplate->offset; + + if (state != NULL) { + new_state->depth = state->depth; + if (new_depth) + new_state->depth++; + state->child = new_state; + } + + cx->current = new_state; + return new_state; +} + + +static void +sec_asn1e_scrub_state (sec_asn1e_state *state) +{ + /* + * Some default "scrubbing". + * XXX right set of initializations? + */ + state->place = beforeHeader; + state->indefinite = PR_FALSE; +} + + +static void +sec_asn1e_notify_before (SEC_ASN1EncoderContext *cx, void *src, int depth) +{ + if (cx->notify_proc == NULL) + return; + + cx->during_notify = PR_TRUE; + (* cx->notify_proc) (cx->notify_arg, PR_TRUE, src, depth); + cx->during_notify = PR_FALSE; +} + + +static void +sec_asn1e_notify_after (SEC_ASN1EncoderContext *cx, void *src, int depth) +{ + if (cx->notify_proc == NULL) + return; + + cx->during_notify = PR_TRUE; + (* cx->notify_proc) (cx->notify_arg, PR_FALSE, src, depth); + cx->during_notify = PR_FALSE; +} + + +static sec_asn1e_state * +sec_asn1e_init_state_based_on_template (sec_asn1e_state *state) +{ + PRBool explicit, is_string, may_stream, optional, universal, ignore_stream; + unsigned char tag_modifiers; + unsigned long encode_kind, under_kind; + unsigned long tag_number; + #ifdef __APPLE__ + PRBool signedInt, dynamic; + #endif + + encode_kind = state->theTemplate->kind; + + universal = ((encode_kind & SEC_ASN1_CLASS_MASK) == SEC_ASN1_UNIVERSAL) + ? PR_TRUE : PR_FALSE; + + explicit = (encode_kind & SEC_ASN1_EXPLICIT) ? PR_TRUE : PR_FALSE; + encode_kind &= ~SEC_ASN1_EXPLICIT; + + optional = (encode_kind & SEC_ASN1_OPTIONAL) ? PR_TRUE : PR_FALSE; + encode_kind &= ~SEC_ASN1_OPTIONAL; + + PORT_Assert (!(explicit && universal)); /* bad templates */ + + may_stream = (encode_kind & SEC_ASN1_MAY_STREAM) ? PR_TRUE : PR_FALSE; + encode_kind &= ~SEC_ASN1_MAY_STREAM; + + ignore_stream = (encode_kind & SEC_ASN1_NO_STREAM) ? PR_TRUE : PR_FALSE; + encode_kind &= ~SEC_ASN1_NO_STREAM; + + #ifdef __APPLE__ + signedInt = (encode_kind & SEC_ASN1_SIGNED_INT) ? PR_TRUE : PR_FALSE; + encode_kind &= ~SEC_ASN1_SIGNED_INT; + #endif + + #ifdef __APPLE__ + dynamic = (encode_kind & SEC_ASN1_DYNAMIC) ? PR_TRUE : PR_FALSE; + #endif + encode_kind &= ~SEC_ASN1_DYNAMIC; + + if( encode_kind & SEC_ASN1_CHOICE ) { + under_kind = SEC_ASN1_CHOICE; + } else + + if ((encode_kind & (SEC_ASN1_POINTER | SEC_ASN1_INLINE)) || (!universal + && !explicit)) { + const SecAsn1Template *subt; + void *src; + + PORT_Assert ((encode_kind & (SEC_ASN1_ANY | SEC_ASN1_SKIP)) == 0); + + sec_asn1e_scrub_state (state); + + if (encode_kind & SEC_ASN1_POINTER) { + /* + * XXX This used to PORT_Assert (encode_kind == SEC_ASN1_POINTER); + * but that was too restrictive. This needs to be fixed, + * probably copying what the decoder now checks for, and + * adding a big comment here to explain what the checks mean. + */ + src = *(void **)state->src; + state->place = afterPointer; + if (src == NULL) { + /* + * If this is optional, but NULL, then the field does + * not need to be encoded. In this case we are done; + * we do not want to push a subtemplate. + */ + if (optional) + return state; + + /* + * XXX this is an error; need to figure out + * how to handle this + */ + } + } else { + src = state->src; + if (encode_kind & SEC_ASN1_INLINE) { + /* check that there are no extraneous bits */ + PORT_Assert (encode_kind == SEC_ASN1_INLINE && !optional); + state->place = afterInline; + } else { + /* + * Save the tag modifiers and tag number here before moving + * on to the next state in case this is a member of a + * SEQUENCE OF + */ + state->tag_modifiers = (unsigned char)encode_kind & SEC_ASN1_TAG_MASK + & ~SEC_ASN1_TAGNUM_MASK; + state->tag_number = (unsigned char)encode_kind & SEC_ASN1_TAGNUM_MASK; + + state->place = afterImplicit; + state->optional = optional; + } + } + + subt = SEC_ASN1GetSubtemplate (state->theTemplate, state->src, PR_TRUE, + NULL /* __APPLE__ */); + state = sec_asn1e_push_state (state->top, subt, src, PR_FALSE); + if (state == NULL) + return NULL; + + if (universal) { + /* + * This is a POINTER or INLINE; just init based on that + * and we are done. + */ + return sec_asn1e_init_state_based_on_template (state); + } + + /* + * This is an implicit, non-universal (meaning, application-private + * or context-specific) field. This results in a "magic" tag but + * encoding based on the underlying type. We pushed a new state + * that is based on the subtemplate (the underlying type), but + * now we will sort of alias it to give it some of our properties + * (tag, optional status, etc.). + */ + + under_kind = state->theTemplate->kind; + if (under_kind & SEC_ASN1_MAY_STREAM) { + if (!ignore_stream) + may_stream = PR_TRUE; + under_kind &= ~SEC_ASN1_MAY_STREAM; + } + } else { + under_kind = encode_kind; + } + + /* + * Sanity check that there are no unwanted bits marked in under_kind. + * These bits were either removed above (after we recorded them) or + * they simply should not be found (signalling a bad/broken template). + * XXX is this the right set of bits to test here? (i.e. need to add + * or remove any?) + */ + PORT_Assert ((under_kind & (/*SEC_ASN1_EXPLICIT | */SEC_ASN1_OPTIONAL + | SEC_ASN1_SKIP | SEC_ASN1_INNER + | SEC_ASN1_DYNAMIC | SEC_ASN1_MAY_STREAM + | SEC_ASN1_INLINE | SEC_ASN1_POINTER)) == 0); + + if (encode_kind & SEC_ASN1_ANY) { + PORT_Assert (encode_kind == under_kind); + tag_modifiers = 0; + tag_number = 0; + is_string = PR_TRUE; + } else { + tag_modifiers = (unsigned char)encode_kind & SEC_ASN1_TAG_MASK & + ~SEC_ASN1_TAGNUM_MASK; + /* + * XXX This assumes only single-octet identifiers. To handle + * the HIGH TAG form we would need to do some more work, especially + * in how to specify them in the template, because right now we + * do not provide a way to specify more *tag* bits in encode_kind. + */ + + #ifdef __APPLE__ + /* + * Apple change: if this is a DYNAMIC template, use the tag number + * from the subtemplate's kind + */ + if(dynamic) { + tag_number = state->theTemplate->kind & SEC_ASN1_TAGNUM_MASK; + explicit = (state->theTemplate->kind & SEC_ASN1_EXPLICIT) ? PR_TRUE : PR_FALSE; + tag_modifiers |= (state->theTemplate->kind & SEC_ASN1_CONSTRUCTED); + } + else + #endif /* __APPLE__ */ + tag_number = encode_kind & SEC_ASN1_TAGNUM_MASK; + + is_string = PR_FALSE; + switch (under_kind & SEC_ASN1_TAGNUM_MASK) { + case SEC_ASN1_SET: + /* + * XXX A plain old SET (as opposed to a SET OF) is not implemented. + * If it ever is, remove this assert... + */ + PORT_Assert ((under_kind & SEC_ASN1_GROUP) != 0); + /* fallthru */ + case SEC_ASN1_SEQUENCE: + tag_modifiers |= SEC_ASN1_CONSTRUCTED; + break; + case SEC_ASN1_BIT_STRING: + case SEC_ASN1_BMP_STRING: + case SEC_ASN1_GENERALIZED_TIME: + case SEC_ASN1_IA5_STRING: + case SEC_ASN1_OCTET_STRING: + case SEC_ASN1_PRINTABLE_STRING: + case SEC_ASN1_T61_STRING: + case SEC_ASN1_UNIVERSAL_STRING: + case SEC_ASN1_UTC_TIME: + case SEC_ASN1_UTF8_STRING: + case SEC_ASN1_VISIBLE_STRING: + /* + * We do not yet know if we will be constructing the string, + * so we have to wait to do this final tag modification. + */ + is_string = PR_TRUE; + break; + } + } + + state->tag_modifiers = tag_modifiers; + state->tag_number = (unsigned char)tag_number; + state->underlying_kind = under_kind; + state->explicit = explicit; + state->may_stream = may_stream; + state->is_string = is_string; + state->optional = optional; + state->ignore_stream = ignore_stream; + #ifdef __APPLE__ + state->signedInt = signedInt; + #endif + + sec_asn1e_scrub_state (state); + + return state; +} + + +static void +sec_asn1e_write_part (sec_asn1e_state *state, + const char *buf, size_t len, + SEC_ASN1EncodingPart part) +{ + SEC_ASN1EncoderContext *cx; + + cx = state->top; + (* cx->output_proc) (cx->output_arg, buf, len, state->depth, part); +} + + +/* + * XXX This assumes only single-octet identifiers. To handle + * the HIGH TAG form we would need to modify this interface and + * teach it to properly encode the special form. + */ +static void +sec_asn1e_write_identifier_bytes (sec_asn1e_state *state, unsigned char value) +{ + char byte; + + byte = (char) value; + sec_asn1e_write_part (state, &byte, 1, SEC_ASN1_Identifier); +} + +int +SEC_ASN1EncodeLength(unsigned char *buf,unsigned long value) { + int lenlen; + + lenlen = SEC_ASN1LengthLength (value); + if (lenlen == 1) { + buf[0] = value; + } else { + int i; + + i = lenlen - 1; + buf[0] = 0x80 | i; + while (i) { + buf[i--] = value; + value >>= 8; + } + PORT_Assert (value == 0); + } + return lenlen; +} + +static void +sec_asn1e_write_length_bytes (sec_asn1e_state *state, unsigned long value, + PRBool indefinite) +{ + int lenlen; + unsigned char buf[sizeof(unsigned long) + 1]; + + if (indefinite) { + PORT_Assert (value == 0); + buf[0] = 0x80; + lenlen = 1; + } else { + lenlen = SEC_ASN1EncodeLength(buf,value); + } + + sec_asn1e_write_part (state, (char *) buf, lenlen, SEC_ASN1_Length); +} + + +static void +sec_asn1e_write_contents_bytes (sec_asn1e_state *state, + const char *buf, unsigned long len) +{ + sec_asn1e_write_part (state, buf, len, SEC_ASN1_Contents); +} + + +static void +sec_asn1e_write_end_of_contents_bytes (sec_asn1e_state *state) +{ + const char eoc[2] = {0, 0}; + + sec_asn1e_write_part (state, eoc, 2, SEC_ASN1_EndOfContents); +} + +static int +sec_asn1e_which_choice +( + void *src, + const SecAsn1Template *theTemplate +) +{ + int rv; + unsigned int which = *(unsigned int *)src; + + for( rv = 1, theTemplate++; theTemplate->kind != 0; rv++, theTemplate++ ) { + if( which == theTemplate->size ) { + return rv; + } + } + + return 0; +} + +static unsigned long +sec_asn1e_contents_length (const SecAsn1Template *theTemplate, void *src, + PRBool ignoresubstream, PRBool *noheaderp) +{ + unsigned long encode_kind, underlying_kind; + PRBool explicit, optional, universal, may_stream; + unsigned long len; + #ifdef __APPLE__ + PRBool signedInt; + #endif + + /* + * This function currently calculates the length in all cases + * except the following: when writing out the contents of a + * template that belongs to a state where it was a sub-template + * with the SEC_ASN1_MAY_STREAM bit set and it's parent had the + * optional bit set. The information that the parent is optional + * and that we should return the length of 0 when that length is + * present since that means the optional field is no longer present. + * So we add the ignoresubstream flag which is passed in when + * writing the contents, but for all recursive calls to + * sec_asn1e_contents_length, we pass PR_FALSE, because this + * function correctly calculates the length for children templates + * from that point on. Confused yet? At least you didn't have + * to figure it out. ;) -javi + */ + encode_kind = theTemplate->kind; + + universal = ((encode_kind & SEC_ASN1_CLASS_MASK) == SEC_ASN1_UNIVERSAL) + ? PR_TRUE : PR_FALSE; + + explicit = (encode_kind & SEC_ASN1_EXPLICIT) ? PR_TRUE : PR_FALSE; + encode_kind &= ~SEC_ASN1_EXPLICIT; + + optional = (encode_kind & SEC_ASN1_OPTIONAL) ? PR_TRUE : PR_FALSE; + encode_kind &= ~SEC_ASN1_OPTIONAL; + + PORT_Assert (!(explicit && universal)); /* bad templates */ + + may_stream = (encode_kind & SEC_ASN1_MAY_STREAM) ? PR_TRUE : PR_FALSE; + encode_kind &= ~SEC_ASN1_MAY_STREAM; + + /* Just clear this to get it out of the way; we do not need it here */ + encode_kind &= ~SEC_ASN1_DYNAMIC; + encode_kind &= ~SEC_ASN1_NO_STREAM; + + if( encode_kind & SEC_ASN1_CHOICE ) { + void *src2; + int indx = sec_asn1e_which_choice(src, theTemplate); + if( 0 == indx ) { + /* XXX set an error? "choice not found" */ + /* state->top->status = encodeError; */ + return 0; + } + + src2 = (void *)((char *)src - theTemplate->offset + theTemplate[indx].offset); + + return sec_asn1e_contents_length(&theTemplate[indx], src2, + PR_FALSE, noheaderp); + } + + if ((encode_kind & (SEC_ASN1_POINTER | SEC_ASN1_INLINE)) || !universal) { + + /* XXX any bits we want to disallow (PORT_Assert against) here? */ + + theTemplate = SEC_ASN1GetSubtemplate (theTemplate, src, PR_TRUE, + NULL /* __APPLE__ */); + + if (encode_kind & SEC_ASN1_POINTER) { + /* + * XXX This used to PORT_Assert (encode_kind == SEC_ASN1_POINTER); + * but that was too restrictive. This needs to be fixed, + * probably copying what the decoder now checks for, and + * adding a big comment here to explain what the checks mean. + * Alternatively, the check here could be omitted altogether + * just letting sec_asn1e_init_state_based_on_template + * do it, since that routine can do better error handling, too. + */ + src = *(void **)src; + if (src == NULL) { + if (optional) + *noheaderp = PR_TRUE; + else + *noheaderp = PR_FALSE; + return 0; + } + } else if (encode_kind & SEC_ASN1_INLINE) { + /* check that there are no extraneous bits */ + PORT_Assert (encode_kind == SEC_ASN1_INLINE && !optional); + } + + src = (char *)src + theTemplate->offset; + + if (explicit) { + len = sec_asn1e_contents_length (theTemplate, src, PR_FALSE, + noheaderp); + if (len == 0 && optional) { + *noheaderp = PR_TRUE; + } else if (*noheaderp) { + /* Okay, *we* do not want to add in a header, but our caller still does. */ + *noheaderp = PR_FALSE; + } else { + /* if the inner content exists, our length is + * len(identifier) + len(length) + len(innercontent) + * XXX we currently assume len(identifier) == 1; + * to support a high-tag-number this would need to be smarter. + */ + len += 1 + SEC_ASN1LengthLength (len); + } + return len; + } + + underlying_kind = theTemplate->kind; + underlying_kind &= ~SEC_ASN1_MAY_STREAM; + /* XXX Should we recurse here? */ + } else { + underlying_kind = encode_kind; + } + + #ifdef __APPLE__ + signedInt = (underlying_kind & SEC_ASN1_SIGNED_INT) ? + PR_TRUE : PR_FALSE; + #endif + + /* This is only used in decoding; it plays no part in encoding. */ + if (underlying_kind & SEC_ASN1_SAVE) { + /* check that there are no extraneous bits */ + PORT_Assert (underlying_kind == SEC_ASN1_SAVE); + *noheaderp = PR_TRUE; + return 0; + } + + /* Having any of these bits is not expected here... */ + PORT_Assert ((underlying_kind & (SEC_ASN1_EXPLICIT | SEC_ASN1_OPTIONAL + | SEC_ASN1_INLINE | SEC_ASN1_POINTER + | SEC_ASN1_DYNAMIC | SEC_ASN1_MAY_STREAM + | SEC_ASN1_SAVE | SEC_ASN1_SKIP)) == 0); + + if( underlying_kind & SEC_ASN1_CHOICE ) { + void *src2; + int indx = sec_asn1e_which_choice(src, theTemplate); + if( 0 == indx ) { + /* XXX set an error? "choice not found" */ + /* state->top->status = encodeError; */ + return 0; + } + + src2 = (void *)((char *)src - theTemplate->offset + theTemplate[indx].offset); + len = sec_asn1e_contents_length(&theTemplate[indx], src2, PR_FALSE, + noheaderp); + } else + + switch (underlying_kind) { + case SEC_ASN1_SEQUENCE_OF: + case SEC_ASN1_SET_OF: + { + const SecAsn1Template *tmpt; + void *sub_src; + unsigned long sub_len; + void **group; + + len = 0; + + group = *(void ***)src; + if (group == NULL) + break; + + tmpt = SEC_ASN1GetSubtemplate (theTemplate, src, PR_TRUE, + NULL /* __APPLE__ */); + + for (; *group != NULL; group++) { + sub_src = (char *)(*group) + tmpt->offset; + sub_len = sec_asn1e_contents_length (tmpt, sub_src, PR_FALSE, + noheaderp); + len += sub_len; + /* + * XXX The 1 below is the presumed length of the identifier; + * to support a high-tag-number this would need to be smarter. + */ + if (!*noheaderp) + len += 1 + SEC_ASN1LengthLength (sub_len); + } + } + break; + + case SEC_ASN1_SEQUENCE: + case SEC_ASN1_SET: + { + const SecAsn1Template *tmpt; + void *sub_src; + unsigned long sub_len; + + len = 0; + for (tmpt = theTemplate + 1; tmpt->kind; tmpt++) { + sub_src = (char *)src + tmpt->offset; + sub_len = sec_asn1e_contents_length (tmpt, sub_src, PR_FALSE, + noheaderp); + len += sub_len; + /* + * XXX The 1 below is the presumed length of the identifier; + * to support a high-tag-number this would need to be smarter. + */ + if (!*noheaderp) + len += 1 + SEC_ASN1LengthLength (sub_len); + } + } + break; + + case SEC_ASN1_BIT_STRING: + /* convert bit length to byte */ + len = (((SecAsn1Item *)src)->Length + 7) >> 3; + /* bit string contents involve an extra octet */ + if (len) + len++; + break; + + case SEC_ASN1_INTEGER: + /* ASN.1 INTEGERs are signed. + * If the source is an unsigned integer, the encoder will need + * to handle the conversion here. + */ + { + unsigned char *buf = ((SecAsn1Item *)src)->Data; + #ifndef __APPLE__ + SecAsn1ItemType integerType = ((SecAsn1Item *)src)->type; + #endif + len = ((SecAsn1Item *)src)->Length; + while (len > 0) { + if (*buf != 0) { + #ifdef __APPLE__ + if (*buf & 0x80 && !signedInt) { + #else + if (*buf & 0x80 && integerType == siUnsignedInteger) { + #endif // __APPLE__ + len++; /* leading zero needed to make number signed */ + } + break; /* reached beginning of number */ + } + if (len == 1) { + break; /* the number 0 */ + } + if (buf[1] & 0x80) { + break; /* leading zero already present */ + } + /* extraneous leading zero, keep going */ + buf++; + len--; + } + } + break; + + default: + len = ((SecAsn1Item *)src)->Length; + if (may_stream && len == 0 && !ignoresubstream) + len = 1; /* if we're streaming, we may have a secitem w/len 0 as placeholder */ + break; + } + + if ((len == 0 && optional) || underlying_kind == SEC_ASN1_ANY) + *noheaderp = PR_TRUE; + else + *noheaderp = PR_FALSE; + + return len; +} + + +static void +sec_asn1e_write_header (sec_asn1e_state *state) +{ + unsigned long contents_length; + unsigned char tag_number, tag_modifiers; + PRBool noheader; + + PORT_Assert (state->place == beforeHeader); + + tag_number = state->tag_number; + tag_modifiers = state->tag_modifiers; + + if (state->underlying_kind == SEC_ASN1_ANY) { + state->place = duringContents; + return; + } + + if( state->underlying_kind & SEC_ASN1_CHOICE ) { + int indx = sec_asn1e_which_choice(state->src, state->theTemplate); + if( 0 == indx ) { + /* XXX set an error? "choice not found" */ + state->top->status = encodeError; + return; + } + + state->place = afterChoice; + state = sec_asn1e_push_state(state->top, &state->theTemplate[indx], + (char *)state->src - state->theTemplate->offset, + PR_TRUE); + + if( (sec_asn1e_state *)NULL != state ) { + /* + * Do the "before" field notification. + */ + sec_asn1e_notify_before (state->top, state->src, state->depth); + state = sec_asn1e_init_state_based_on_template (state); + } + + return; + } + + /* + * We are doing a definite-length encoding. First we have to + * walk the data structure to calculate the entire contents length. + */ + contents_length = sec_asn1e_contents_length (state->theTemplate, + state->src, + state->ignore_stream, + &noheader); + /* + * We might be told explicitly not to put out a header. + * But it can also be the case, via a pushed subtemplate, that + * sec_asn1e_contents_length could not know that this field is + * really optional. So check for that explicitly, too. + */ + if (noheader || (contents_length == 0 && state->optional)) { + state->place = afterContents; + if (state->top->streaming && state->may_stream && state->top->from_buf) + /* we did not find an optional indefinite string, so we don't encode it. + * However, if TakeFromBuf is on, we stop here anyway to give our caller + * a chance to intercept at the same point where we would stop if the + * field were present. */ + state->top->status = needBytes; + return; + } + + if (state->top->streaming && state->may_stream + && (state->top->from_buf || !state->is_string)) { + /* + * We need to put out an indefinite-length encoding. + */ + state->indefinite = PR_TRUE; + /* + * The only universal types that can be constructed are SETs, + * SEQUENCEs, and strings; so check that it is one of those, + * or that it is not universal (e.g. context-specific). + */ + PORT_Assert ((tag_number == SEC_ASN1_SET) + || (tag_number == SEC_ASN1_SEQUENCE) + || ((tag_modifiers & SEC_ASN1_CLASS_MASK) != 0) + || state->is_string); + tag_modifiers |= SEC_ASN1_CONSTRUCTED; + contents_length = 0; + } + + sec_asn1e_write_identifier_bytes (state, (unsigned char)(tag_number | tag_modifiers)); + sec_asn1e_write_length_bytes (state, contents_length, state->indefinite); + + if (contents_length == 0 && !state->indefinite) { + /* + * If no real contents to encode, then we are done with this field. + */ + state->place = afterContents; + return; + } + + /* + * An EXPLICIT is nothing but an outer header, which we have already + * written. Now we need to do the inner header and contents. + */ + if (state->explicit) { + state->place = afterContents; + state = sec_asn1e_push_state (state->top, + SEC_ASN1GetSubtemplate(state->theTemplate, + state->src, + PR_TRUE, + NULL /* __APPLE__ */), + state->src, PR_TRUE); + if (state != NULL) + state = sec_asn1e_init_state_based_on_template (state); + return; + } + + switch (state->underlying_kind) { + case SEC_ASN1_SET_OF: + case SEC_ASN1_SEQUENCE_OF: + /* + * We need to push a child to handle each member. + */ + { + void **group; + const SecAsn1Template *subt; + + group = *(void ***)state->src; + if (group == NULL || *group == NULL) { + /* + * Group is empty; we are done. + */ + state->place = afterContents; + return; + } + state->place = duringGroup; + subt = SEC_ASN1GetSubtemplate (state->theTemplate, state->src, + PR_TRUE, NULL /* __APPLE__ */); + state = sec_asn1e_push_state (state->top, subt, *group, PR_TRUE); + if (state != NULL) + state = sec_asn1e_init_state_based_on_template (state); + } + break; + + case SEC_ASN1_SEQUENCE: + case SEC_ASN1_SET: + /* + * We need to push a child to handle the individual fields. + */ + state->place = duringSequence; + state = sec_asn1e_push_state (state->top, state->theTemplate + 1, + state->src, PR_TRUE); + if (state != NULL) { + /* + * Do the "before" field notification. + */ + sec_asn1e_notify_before (state->top, state->src, state->depth); + state = sec_asn1e_init_state_based_on_template (state); + } + break; + + default: + /* + * I think we do not need to do anything else. + * XXX Correct? + */ + state->place = duringContents; + break; + } +} + + +static void +sec_asn1e_write_contents (sec_asn1e_state *state, + const char *buf, unsigned long len) +{ + PORT_Assert (state->place == duringContents); + + if (state->top->from_buf) { + /* + * Probably they just turned on "take from buf", but have not + * yet given us any bytes. If there is nothing in the buffer + * then we have nothing to do but return and wait. + */ + if (buf == NULL || len == 0) { + state->top->status = needBytes; + return; + } + /* + * We are streaming, reading from a passed-in buffer. + * This means we are encoding a simple string or an ANY. + * For the former, we need to put out a substring, with its + * own identifier and length. For an ANY, we just write it + * out as is (our caller is required to ensure that it + * is a properly encoded entity). + */ + PORT_Assert (state->is_string); /* includes ANY */ + if (state->underlying_kind != SEC_ASN1_ANY) { + unsigned char identifier; + + /* + * Create the identifier based on underlying_kind. We cannot + * use tag_number and tag_modifiers because this can be an + * implicitly encoded field. In that case, the underlying + * substrings *are* encoded with their real tag. + */ + identifier = (unsigned char)state->underlying_kind & SEC_ASN1_TAG_MASK; + /* + * The underlying kind should just be a simple string; there + * should be no bits like CONTEXT_SPECIFIC or CONSTRUCTED set. + */ + PORT_Assert ((identifier & SEC_ASN1_TAGNUM_MASK) == identifier); + /* + * Write out the tag and length for the substring. + */ + sec_asn1e_write_identifier_bytes (state, identifier); + if (state->underlying_kind == SEC_ASN1_BIT_STRING) { + char byte; + /* + * Assume we have a length in bytes but we need to output + * a proper bit string. This interface only works for bit + * strings that are full multiples of 8. If support for + * real, variable length bit strings is needed then the + * caller will have to know to pass in a bit length instead + * of a byte length and then this code will have to + * perform the encoding necessary (length written is length + * in bytes plus 1, and the first octet of string is the + * number of bits remaining between the end of the bit + * string and the next byte boundary). + */ + sec_asn1e_write_length_bytes (state, len + 1, PR_FALSE); + byte = 0; + sec_asn1e_write_contents_bytes (state, &byte, 1); + } else { + sec_asn1e_write_length_bytes (state, len, PR_FALSE); + } + } + sec_asn1e_write_contents_bytes (state, buf, len); + state->top->status = needBytes; + } else { + switch (state->underlying_kind) { + case SEC_ASN1_SET: + case SEC_ASN1_SEQUENCE: + PORT_Assert (0); + break; + + case SEC_ASN1_BIT_STRING: + { + SecAsn1Item *item; + char rem; + + item = (SecAsn1Item *)state->src; + len = (item->Length + 7) >> 3; + rem = (unsigned char)((len << 3) - item->Length); /* remaining bits */ + sec_asn1e_write_contents_bytes (state, &rem, 1); + sec_asn1e_write_contents_bytes (state, (char *) item->Data, + len); + } + break; + + case SEC_ASN1_BMP_STRING: + /* The number of bytes must be divisable by 2 */ + if ((((SecAsn1Item *)state->src)->Length) % 2) { + SEC_ASN1EncoderContext *cx; + + cx = state->top; + cx->status = encodeError; + break; + } + /* otherwise, fall through to write the content */ + goto process_string; + + case SEC_ASN1_UNIVERSAL_STRING: + /* The number of bytes must be divisable by 4 */ + if ((((SecAsn1Item *)state->src)->Length) % 4) { + SEC_ASN1EncoderContext *cx; + + cx = state->top; + cx->status = encodeError; + break; + } + /* otherwise, fall through to write the content */ + goto process_string; + + case SEC_ASN1_INTEGER: + /* ASN.1 INTEGERs are signed. If the source is an unsigned + * integer, the encoder will need to handle the conversion here. + */ + { + size_t blen; + unsigned char *intbuf; + #ifdef __APPLE__ + PRBool signedInt = state->signedInt; + #else + SECItemType integerType = ((SecAsn1Item *)state->src)->type; + #endif + blen = ((SecAsn1Item *)state->src)->Length; + intbuf = ((SecAsn1Item *)state->src)->Data; + while (blen > 0) { + #ifdef __APPLE__ + if (*intbuf & 0x80 && !signedInt) { + #else + if (*intbuf & 0x80 && integerType == siUnsignedInteger) { + #endif + char zero = 0; /* write a leading 0 */ + sec_asn1e_write_contents_bytes(state, &zero, 1); + /* and then the remaining buffer */ + sec_asn1e_write_contents_bytes(state, + (char *)intbuf, blen); + break; + } + /* Check three possibilities: + * 1. No leading zeros, msb of MSB is not 1; + * 2. The number is zero itself; + * 3. Encoding a signed integer with a leading zero, + * keep the zero so that the number is positive. + */ + if (*intbuf != 0 || + blen == 1 || + #ifdef __APPLE__ + (intbuf[1] & 0x80 && signedInt) ) + #else + (intbuf[1] & 0x80 && integerType != siUnsignedInteger) ) + #endif + { + sec_asn1e_write_contents_bytes(state, + (char *)intbuf, blen); + break; + } + /* byte is 0, continue */ + intbuf++; + blen--; + } + } + /* done with this content */ + break; + +process_string: + default: + { + SecAsn1Item *item; + + item = (SecAsn1Item *)state->src; + sec_asn1e_write_contents_bytes (state, (char *) item->Data, + item->Length); + } + break; + } + state->place = afterContents; + } +} + + +/* + * We are doing a SET OF or SEQUENCE OF, and have just finished an item. + */ +static void +sec_asn1e_next_in_group (sec_asn1e_state *state) +{ + sec_asn1e_state *child; + void **group; + void *member; + + PORT_Assert (state->place == duringGroup); + PORT_Assert (state->child != NULL); + + child = state->child; + + group = *(void ***)state->src; + + /* + * Find placement of current item. + */ + member = (char *)(state->child->src) - child->theTemplate->offset; + while (*group != member) + group++; + + /* + * Move forward to next item. + */ + group++; + if (*group == NULL) { + /* + * That was our last one; we are done now. + */ + child->place = notInUse; + state->place = afterContents; + return; + } + child->src = (char *)(*group) + child->theTemplate->offset; + + /* + * Re-"push" child. + */ + sec_asn1e_scrub_state (child); + state->top->current = child; +} + + +/* + * We are moving along through a sequence; move forward by one, + * (detecting end-of-sequence when it happens). + */ +static void +sec_asn1e_next_in_sequence (sec_asn1e_state *state) +{ + sec_asn1e_state *child; + + PORT_Assert (state->place == duringSequence); + PORT_Assert (state->child != NULL); + + child = state->child; + + /* + * Do the "after" field notification. + */ + sec_asn1e_notify_after (state->top, child->src, child->depth); + + /* + * Move forward. + */ + child->theTemplate++; + if (child->theTemplate->kind == 0) { + /* + * We are done with this sequence. + */ + child->place = notInUse; + state->place = afterContents; + return; + } + + /* + * Reset state and push. + */ + + child->src = (char *)state->src + child->theTemplate->offset; + + /* + * Do the "before" field notification. + */ + sec_asn1e_notify_before (state->top, child->src, child->depth); + + state->top->current = child; + (void) sec_asn1e_init_state_based_on_template (child); +} + + +static void +sec_asn1e_after_contents (sec_asn1e_state *state) +{ + PORT_Assert (state->place == afterContents); + + if (state->indefinite) + sec_asn1e_write_end_of_contents_bytes (state); + + /* + * Just make my parent be the current state. It will then clean + * up after me and free me (or reuse me). + */ + state->top->current = state->parent; +} + + +/* + * This function is called whether or not we are streaming; if we + * *are* streaming, our caller can also instruct us to take bytes + * from the passed-in buffer (at buf, for length len, which is likely + * bytes but could even mean bits if the current field is a bit string). + * If we have been so instructed, we will gobble up bytes from there + * (rather than from our src structure) and output them, and then + * we will just return, expecting to be called again -- either with + * more bytes or after our caller has instructed us that we are done + * (for now) with the buffer. + */ +SECStatus +SEC_ASN1EncoderUpdate (SEC_ASN1EncoderContext *cx, + const char *buf, unsigned long len) +{ + sec_asn1e_state *state; + + if (cx->status == needBytes) { + PORT_Assert (buf != NULL && len != 0); + cx->status = keepGoing; + } + + while (cx->status == keepGoing) { + state = cx->current; + switch (state->place) { + case beforeHeader: + sec_asn1e_write_header (state); + break; + case duringContents: + sec_asn1e_write_contents (state, buf, len); + break; + case duringGroup: + sec_asn1e_next_in_group (state); + break; + case duringSequence: + sec_asn1e_next_in_sequence (state); + break; + case afterContents: + sec_asn1e_after_contents (state); + break; + case afterImplicit: + case afterInline: + case afterPointer: + case afterChoice: + /* + * These states are more documentation than anything. + * They just need to force a pop. + */ + PORT_Assert (!state->indefinite); + state->place = afterContents; + break; + case notInUse: + default: + /* This is not an error, but rather a plain old BUG! */ + PORT_Assert (0); + cx->status = encodeError; + break; + } + + if (cx->status == encodeError) + break; + + /* It might have changed, so we have to update our local copy. */ + state = cx->current; + + /* If it is NULL, we have popped all the way to the top. */ + if (state == NULL) { + cx->status = allDone; + break; + } + } + + if (cx->status == encodeError) { + return SECFailure; + } + + return SECSuccess; +} + + +void +SEC_ASN1EncoderFinish (SEC_ASN1EncoderContext *cx) +{ + /* + * XXX anything else that needs to be finished? + */ + + PORT_FreeArena (cx->our_pool, PR_FALSE); +} + + +SEC_ASN1EncoderContext * +SEC_ASN1EncoderStart (const void *src, const SecAsn1Template *theTemplate, + SEC_ASN1WriteProc output_proc, void *output_arg) +{ + PRArenaPool *our_pool; + SEC_ASN1EncoderContext *cx; + + our_pool = PORT_NewArena (SEC_ASN1_DEFAULT_ARENA_SIZE); + if (our_pool == NULL) + return NULL; + + cx = (SEC_ASN1EncoderContext*)PORT_ArenaZAlloc (our_pool, sizeof(*cx)); + if (cx == NULL) { + PORT_FreeArena (our_pool, PR_FALSE); + return NULL; + } + + cx->our_pool = our_pool; + cx->output_proc = output_proc; + cx->output_arg = output_arg; + + cx->status = keepGoing; + + if (sec_asn1e_push_state(cx, theTemplate, src, PR_FALSE) == NULL + || sec_asn1e_init_state_based_on_template (cx->current) == NULL) { + /* + * Trouble initializing (probably due to failed allocations) + * requires that we just give up. + */ + PORT_FreeArena (our_pool, PR_FALSE); + return NULL; + } + + return cx; +} + + +/* + * XXX Do we need a FilterProc, too? + */ + + +void +SEC_ASN1EncoderSetNotifyProc (SEC_ASN1EncoderContext *cx, + SEC_ASN1NotifyProc fn, void *arg) +{ + cx->notify_proc = fn; + cx->notify_arg = arg; +} + + +void +SEC_ASN1EncoderClearNotifyProc (SEC_ASN1EncoderContext *cx) +{ + cx->notify_proc = NULL; + cx->notify_arg = NULL; /* not necessary; just being clean */ +} + + +void +SEC_ASN1EncoderAbort(SEC_ASN1EncoderContext *cx, int error) +{ + PORT_Assert(cx); + PORT_SetError(error); + cx->status = encodeError; +} + + +void +SEC_ASN1EncoderSetStreaming (SEC_ASN1EncoderContext *cx) +{ + /* XXX is there a way to check that we are "between" fields here? */ + + cx->streaming = PR_TRUE; +} + + +void +SEC_ASN1EncoderClearStreaming (SEC_ASN1EncoderContext *cx) +{ + /* XXX is there a way to check that we are "between" fields here? */ + + cx->streaming = PR_FALSE; +} + + +void +SEC_ASN1EncoderSetTakeFromBuf (SEC_ASN1EncoderContext *cx) +{ + /* + * XXX is there a way to check that we are "between" fields here? this + * needs to include a check for being in between groups of items in + * a SET_OF or SEQUENCE_OF. + */ + PORT_Assert (cx->streaming); + + cx->from_buf = PR_TRUE; +} + + +void +SEC_ASN1EncoderClearTakeFromBuf (SEC_ASN1EncoderContext *cx) +{ + /* we should actually be taking from buf *now* */ + PORT_Assert (cx->from_buf); + if (! cx->from_buf) /* if not, just do nothing */ + return; + + cx->from_buf = PR_FALSE; + + if (cx->status == needBytes) { + cx->status = keepGoing; + cx->current->place = afterContents; + } +} + + +SECStatus +SEC_ASN1Encode (const void *src, const SecAsn1Template *theTemplate, + SEC_ASN1WriteProc output_proc, void *output_arg) +{ + SEC_ASN1EncoderContext *ecx; + SECStatus rv; + + ecx = SEC_ASN1EncoderStart (src, theTemplate, output_proc, output_arg); + if (ecx == NULL) + return SECFailure; + + rv = SEC_ASN1EncoderUpdate (ecx, NULL, 0); + + SEC_ASN1EncoderFinish (ecx); + return rv; +} + + +/* + * XXX depth and data_kind are unused; is there a PC way to silence warnings? + * (I mean "politically correct", not anything to do with intel/win platform) + */ +void +sec_asn1e_encode_item_count (void *arg, const char *buf, size_t len, + int depth, SEC_ASN1EncodingPart data_kind) +{ + size_t *count; + + count = (unsigned long*)arg; + PORT_Assert (count != NULL); + + *count += len; +} + + +/* XXX depth and data_kind are unused; is there a PC way to silence warnings? */ +void +sec_asn1e_encode_item_store (void *arg, const char *buf, size_t len, + int depth, SEC_ASN1EncodingPart data_kind) +{ + SecAsn1Item *dest; + + dest = (SecAsn1Item*)arg; + PORT_Assert (dest != NULL); + + PORT_Memcpy (dest->Data + dest->Length, buf, len); + dest->Length += len; +} + + +/* + * Allocate an entire SecAsn1Item, or just the data part of it, to hold + * "len" bytes of stuff. Allocate from the given pool, if specified, + * otherwise just do a vanilla PORT_Alloc. + * + * XXX This seems like a reasonable general-purpose function (for SECITEM_)? + */ +SecAsn1Item * +sec_asn1e_allocate_item (PRArenaPool *poolp, SecAsn1Item *dest, unsigned long len) +{ + if (poolp != NULL) { + void *release; + + release = PORT_ArenaMark (poolp); + if (dest == NULL) + dest = (SecAsn1Item*)PORT_ArenaAlloc (poolp, sizeof(SecAsn1Item)); + if (dest != NULL) { + dest->Data = (unsigned char*)PORT_ArenaAlloc (poolp, len); + if (dest->Data == NULL) { + dest = NULL; + } + } + if (dest == NULL) { + /* one or both allocations failed; release everything */ + PORT_ArenaRelease (poolp, release); + } else { + /* everything okay; unmark the arena */ + PORT_ArenaUnmark (poolp, release); + } + } else { + SecAsn1Item *indest; + + indest = dest; + if (dest == NULL) + dest = (SecAsn1Item*)PORT_Alloc (sizeof(SecAsn1Item)); + if (dest != NULL) { + #ifndef __APPLE__ + dest->type = siBuffer; + #endif + dest->Data = (unsigned char*)PORT_Alloc (len); + if (dest->Data == NULL) { + if (indest == NULL) + PORT_Free (dest); + dest = NULL; + } + } + } + + return dest; +} + + +SecAsn1Item * +SEC_ASN1EncodeItem (PRArenaPool *poolp, SecAsn1Item *dest, const void *src, + const SecAsn1Template *theTemplate) +{ + unsigned long encoding_length; + SECStatus rv; + + PORT_Assert (dest == NULL || dest->Data == NULL); + + encoding_length = 0; + rv = SEC_ASN1Encode (src, theTemplate, + sec_asn1e_encode_item_count, &encoding_length); + if (rv != SECSuccess) + return NULL; + + dest = sec_asn1e_allocate_item (poolp, dest, encoding_length); + if (dest == NULL) + return NULL; + + /* XXX necessary? This really just checks for a bug in the allocate fn */ + PORT_Assert (dest->Data != NULL); + if (dest->Data == NULL) + return NULL; + + dest->Length = 0; + (void) SEC_ASN1Encode (src, theTemplate, sec_asn1e_encode_item_store, dest); + + PORT_Assert (encoding_length == dest->Length); + return dest; +} + + +static SecAsn1Item * +sec_asn1e_integer(PRArenaPool *poolp, SecAsn1Item *dest, unsigned long value, + PRBool make_unsigned) +{ + unsigned long copy; + unsigned char sign; + int len = 0; + + /* + * Determine the length of the encoded value (minimum of 1). + */ + copy = value; + do { + len++; + sign = (unsigned char)(copy & 0x80); + copy >>= 8; + } while (copy); + + /* + * If this is an unsigned encoding, and the high bit of the last + * byte we counted was set, we need to add one to the length so + * we put a high-order zero byte in the encoding. + */ + if (sign && make_unsigned) + len++; + + /* + * Allocate the item (if necessary) and the data pointer within. + */ + dest = sec_asn1e_allocate_item (poolp, dest, len); + if (dest == NULL) + return NULL; + + /* + * Store the value, byte by byte, in the item. + */ + dest->Length = len; + while (len) { + dest->Data[--len] = (unsigned char)value; + value >>= 8; + } + PORT_Assert (value == 0); + + return dest; +} + + +SecAsn1Item * +SEC_ASN1EncodeInteger(PRArenaPool *poolp, SecAsn1Item *dest, long value) +{ + return sec_asn1e_integer (poolp, dest, (unsigned long) value, PR_FALSE); +} + + +extern SecAsn1Item * +SEC_ASN1EncodeUnsignedInteger(PRArenaPool *poolp, + SecAsn1Item *dest, unsigned long value) +{ + return sec_asn1e_integer (poolp, dest, value, PR_TRUE); +} diff --git a/libsecurity_asn1/lib/secasn1t.h b/libsecurity_asn1/lib/secasn1t.h new file mode 100644 index 00000000..5415f736 --- /dev/null +++ b/libsecurity_asn1/lib/secasn1t.h @@ -0,0 +1,143 @@ +/* + * 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. + */ + +/* + * Private (SPI) types libsecurity_asn1.h. + */ + +#ifndef _SECASN1T_H_ +#define _SECASN1T_H_ + +#include /* Boolean */ +#include +#include /* public types */ + + +/* default size used for allocation of encoding/decoding stuff */ +#define SEC_ASN1_DEFAULT_ARENA_SIZE (2048) + +/* + * Tempalte flags we don't export in the public API in SecAsn1Types.h + */ +#define SEC_ASN1_MAY_STREAM 0x40000 /* field or one of its sub-fields may + * stream in and so should encode as + * indefinite-length when streaming + * has been indicated; only for + * encoding */ +#define SEC_ASN1_NO_STREAM 0X200000 /* This entry will not stream + * even if the sub-template says + * streaming is possible. Helps + * to solve ambiguities with potential + * streaming entries that are + * optional */ + +/* Maximum depth of nested SEQUENCEs and SETs */ +#define SEC_ASN1D_MAX_DEPTH 32 + +#define SEC_ASN1_GET(x) x +#define SEC_ASN1_SUB(x) x +#define SEC_ASN1_XTRN 0 +#define SEC_ASN1_MKSUB(x) + +#define SEC_ASN1_CHOOSER_DECLARE(x) \ +extern const SecAsn1Template * NSS_Get_##x (void *arg, Boolean enc); + +#define SEC_ASN1_CHOOSER_IMPLEMENT(x) \ +const SecAsn1Template * NSS_Get_##x(void * arg, Boolean enc) \ +{ return x; } + +/* +** Opaque object used by the decoder to store state. +*/ +typedef struct sec_DecoderContext_struct SEC_ASN1DecoderContext; + +/* +** Opaque object used by the encoder to store state. +*/ +typedef struct sec_EncoderContext_struct SEC_ASN1EncoderContext; + +/* + * This is used to describe to a filter function the bytes that are + * being passed to it. This is only useful when the filter is an "outer" + * one, meaning it expects to get *all* of the bytes not just the + * contents octets. + */ +typedef enum { + SEC_ASN1_Identifier = 0, + SEC_ASN1_Length = 1, + SEC_ASN1_Contents = 2, + SEC_ASN1_EndOfContents = 3 +} SEC_ASN1EncodingPart; + +/* + * Type of the function pointer used either for decoding or encoding, + * when doing anything "funny" (e.g. manipulating the data stream) + */ +typedef void (* SEC_ASN1NotifyProc)(void *arg, Boolean before, + void *dest, int real_depth); + +/* + * Type of the function pointer used for grabbing encoded bytes. + * This can be used during either encoding or decoding, as follows... + * + * When decoding, this can be used to filter the encoded bytes as they + * are parsed. This is what you would do if you wanted to process the data + * along the way (like to decrypt it, or to perform a hash on it in order + * to do a signature check later). See SEC_ASN1DecoderSetFilterProc(). + * When processing only part of the encoded bytes is desired, you "watch" + * for the field(s) you are interested in with a "notify proc" (see + * SEC_ASN1DecoderSetNotifyProc()) and for even finer granularity (e.g. to + * ignore all by the contents bytes) you pay attention to the "data_kind" + * parameter. + * + * When encoding, this is the specification for the output function which + * will receive the bytes as they are encoded. The output function can + * perform any postprocessing necessary (like hashing (some of) the data + * to create a digest that gets included at the end) as well as shoving + * the data off wherever it needs to go. (In order to "tune" any processing, + * you can set a "notify proc" as described above in the decoding case.) + * + * The parameters: + * - "arg" is an opaque pointer that you provided at the same time you + * specified a function of this type + * - "data" is a buffer of length "len", containing the encoded bytes + * - "depth" is how deep in a nested encoding we are (it is not usually + * valuable, but can be useful sometimes so I included it) + * - "data_kind" tells you if these bytes are part of the ASN.1 encoded + * octets for identifier, length, contents, or end-of-contents + */ +typedef void (* SEC_ASN1WriteProc)(void *arg, + const char *data, size_t len, + int depth, SEC_ASN1EncodingPart data_kind); + +#endif /* _SECASN1T_H_ */ diff --git a/libsecurity_asn1/lib/secasn1u.c b/libsecurity_asn1/lib/secasn1u.c new file mode 100644 index 00000000..30e630be --- /dev/null +++ b/libsecurity_asn1/lib/secasn1u.c @@ -0,0 +1,115 @@ +/* + * 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. + */ + +/* + * Utility routines to complement the ASN.1 encoding and decoding functions. + * + * $Id: secasn1u.c,v 1.3 2004/05/13 15:29:13 dmitch Exp $ + */ + +#include "secasn1.h" + + +/* + * We have a length that needs to be encoded; how many bytes will the + * encoding take? + * + * The rules are that 0 - 0x7f takes one byte (the length itself is the + * entire encoding); everything else takes one plus the number of bytes + * in the length. + */ +int +SEC_ASN1LengthLength (unsigned long len) +{ + int lenlen = 1; + + if (len > 0x7f) { + do { + lenlen++; + len >>= 8; + } while (len); + } + + return lenlen; +} + + +/* + * XXX Move over (and rewrite as appropriate) the rest of the + * stuff in dersubr.c! + */ + + +/* + * Find the appropriate subtemplate for the given template. + * This may involve calling a "chooser" function, or it may just + * be right there. In either case, it is expected to *have* a + * subtemplate; this is asserted in debug builds (in non-debug + * builds, NULL will be returned). + * + * "thing" is a pointer to the structure being encoded/decoded + * "encoding", when true, means that we are in the process of encoding + * (as opposed to in the process of decoding) + */ +const SecAsn1Template * +SEC_ASN1GetSubtemplate ( + const SecAsn1Template *theTemplate, + void *thing, + PRBool encoding + #ifdef __APPLE__ + , + const char *buf // for decode only + #endif + ) +{ + const SecAsn1Template *subt = NULL; + + PORT_Assert (theTemplate->sub != NULL); + if (theTemplate->sub != NULL) { + if (theTemplate->kind & SEC_ASN1_DYNAMIC) { + SecAsn1TemplateChooserPtr chooserp; + + chooserp = *(SecAsn1TemplateChooserPtr *) theTemplate->sub; + if (chooserp) { + void *dest = thing; + if (thing != NULL) { + thing = (char *)thing - theTemplate->offset; + } + subt = (* chooserp)(thing, encoding, buf, dest); + } + } else { + subt = (SecAsn1Template*)theTemplate->sub; + } + } + return subt; +} diff --git a/libsecurity_asn1/lib/seccomon.h b/libsecurity_asn1/lib/seccomon.h new file mode 100644 index 00000000..ef4a54aa --- /dev/null +++ b/libsecurity_asn1/lib/seccomon.h @@ -0,0 +1,125 @@ +/* + * 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. + */ + +/* + * seccomon.h - common data structures for security libraries + * + * This file should have lowest-common-denominator datastructures + * for security libraries. It should not be dependent on any other + * headers, and should not require linking with any libraries. + * + * $Id: seccomon.h,v 1.4 2004/03/23 21:31:41 mb Exp $ + */ + +#ifndef _SECCOMMON_H_ +#define _SECCOMMON_H_ + +#include + + +#ifdef __cplusplus +# define SEC_BEGIN_PROTOS extern "C" { +# define SEC_END_PROTOS } +#else +# define SEC_BEGIN_PROTOS +# define SEC_END_PROTOS +#endif + +#include + +#ifdef __APPLE__ + +#include + +/* + * Encode directly to/from SecAsn1Item. + * Avoid the need for SECItemStr.type; see SEC_ANS1_SIGNED_INT + * in secasn1t.h. + */ +typedef SecAsn1Item SECItem; +#else +/* Original NSS */ +typedef enum { + siBuffer = 0, + siClearDataBuffer = 1, + siCipherDataBuffer = 2, + siDERCertBuffer = 3, + siEncodedCertBuffer = 4, + siDERNameBuffer = 5, + siEncodedNameBuffer = 6, + siAsciiNameString = 7, + siAsciiString = 8, + siDEROID = 9, + siUnsignedInteger = 10, + siUTCTime = 11, + siGeneralizedTime = 12 +} SECItemType; + +typedef struct SECItemStr SECItem; + +struct SECItemStr { + SECItemType type; + unsigned char *data; + unsigned int len; +}; +#endif /* __APPLE__ */ + +/* +** A status code. Status's are used by procedures that return status +** values. Again the motivation is so that a compiler can generate +** warnings when return values are wrong. Correct testing of status codes: +** +** SECStatus rv; +** rv = some_function (some_argument); +** if (rv != SECSuccess) +** do_an_error_thing(); +** +*/ +typedef enum _SECStatus { + SECWouldBlock = -2, + SECFailure = -1, + SECSuccess = 0 +} SECStatus; + +/* +** A comparison code. Used for procedures that return comparision +** values. Again the motivation is so that a compiler can generate +** warnings when return values are wrong. +*/ +typedef enum _SECComparison { + SECLessThan = -1, + SECEqual = 0, + SECGreaterThan = 1 +} SECComparison; + +#endif /* _SECCOMMON_H_ */ diff --git a/libsecurity_asn1/lib/secerr.h b/libsecurity_asn1/lib/secerr.h new file mode 100644 index 00000000..21feb92f --- /dev/null +++ b/libsecurity_asn1/lib/secerr.h @@ -0,0 +1,206 @@ +/* + * 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 __SEC_ERR_H_ +#define __SEC_ERR_H_ + +#include + +PR_BEGIN_EXTERN_C + +#define SEC_ERROR_BASE (-0x2000) +#define SEC_ERROR_LIMIT (SEC_ERROR_BASE + 1000) + +#define IS_SEC_ERROR(code) \ + (((code) >= SEC_ERROR_BASE) && ((code) < SEC_ERROR_LIMIT)) + +#ifndef NO_SECURITY_ERROR_ENUM +typedef enum { +SEC_ERROR_IO = SEC_ERROR_BASE + 0, +SEC_ERROR_LIBRARY_FAILURE = SEC_ERROR_BASE + 1, +SEC_ERROR_BAD_DATA = SEC_ERROR_BASE + 2, +SEC_ERROR_OUTPUT_LEN = SEC_ERROR_BASE + 3, +SEC_ERROR_INPUT_LEN = SEC_ERROR_BASE + 4, +SEC_ERROR_INVALID_ARGS = SEC_ERROR_BASE + 5, +SEC_ERROR_INVALID_ALGORITHM = SEC_ERROR_BASE + 6, +SEC_ERROR_INVALID_AVA = SEC_ERROR_BASE + 7, +SEC_ERROR_INVALID_TIME = SEC_ERROR_BASE + 8, +SEC_ERROR_BAD_DER = SEC_ERROR_BASE + 9, +SEC_ERROR_BAD_SIGNATURE = SEC_ERROR_BASE + 10, +SEC_ERROR_EXPIRED_CERTIFICATE = SEC_ERROR_BASE + 11, +SEC_ERROR_REVOKED_CERTIFICATE = SEC_ERROR_BASE + 12, +SEC_ERROR_UNKNOWN_ISSUER = SEC_ERROR_BASE + 13, +SEC_ERROR_BAD_KEY = SEC_ERROR_BASE + 14, +SEC_ERROR_BAD_PASSWORD = SEC_ERROR_BASE + 15, +SEC_ERROR_RETRY_PASSWORD = SEC_ERROR_BASE + 16, +SEC_ERROR_NO_NODELOCK = SEC_ERROR_BASE + 17, +SEC_ERROR_BAD_DATABASE = SEC_ERROR_BASE + 18, +SEC_ERROR_NO_MEMORY = SEC_ERROR_BASE + 19, +SEC_ERROR_UNTRUSTED_ISSUER = SEC_ERROR_BASE + 20, +SEC_ERROR_UNTRUSTED_CERT = SEC_ERROR_BASE + 21, +SEC_ERROR_DUPLICATE_CERT = (SEC_ERROR_BASE + 22), +SEC_ERROR_DUPLICATE_CERT_NAME = (SEC_ERROR_BASE + 23), +SEC_ERROR_ADDING_CERT = (SEC_ERROR_BASE + 24), +SEC_ERROR_FILING_KEY = (SEC_ERROR_BASE + 25), +SEC_ERROR_NO_KEY = (SEC_ERROR_BASE + 26), +SEC_ERROR_CERT_VALID = (SEC_ERROR_BASE + 27), +SEC_ERROR_CERT_NOT_VALID = (SEC_ERROR_BASE + 28), +SEC_ERROR_CERT_NO_RESPONSE = (SEC_ERROR_BASE + 29), +SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE = (SEC_ERROR_BASE + 30), +SEC_ERROR_CRL_EXPIRED = (SEC_ERROR_BASE + 31), +SEC_ERROR_CRL_BAD_SIGNATURE = (SEC_ERROR_BASE + 32), +SEC_ERROR_CRL_INVALID = (SEC_ERROR_BASE + 33), +SEC_ERROR_EXTENSION_VALUE_INVALID = (SEC_ERROR_BASE + 34), +SEC_ERROR_EXTENSION_NOT_FOUND = (SEC_ERROR_BASE + 35), +SEC_ERROR_CA_CERT_INVALID = (SEC_ERROR_BASE + 36), +SEC_ERROR_PATH_LEN_CONSTRAINT_INVALID = (SEC_ERROR_BASE + 37), +SEC_ERROR_CERT_USAGES_INVALID = (SEC_ERROR_BASE + 38), +SEC_INTERNAL_ONLY = (SEC_ERROR_BASE + 39), +SEC_ERROR_INVALID_KEY = (SEC_ERROR_BASE + 40), +SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION = (SEC_ERROR_BASE + 41), +SEC_ERROR_OLD_CRL = (SEC_ERROR_BASE + 42), +SEC_ERROR_NO_EMAIL_CERT = (SEC_ERROR_BASE + 43), +SEC_ERROR_NO_RECIPIENT_CERTS_QUERY = (SEC_ERROR_BASE + 44), +SEC_ERROR_NOT_A_RECIPIENT = (SEC_ERROR_BASE + 45), +SEC_ERROR_PKCS7_KEYALG_MISMATCH = (SEC_ERROR_BASE + 46), +SEC_ERROR_PKCS7_BAD_SIGNATURE = (SEC_ERROR_BASE + 47), +SEC_ERROR_UNSUPPORTED_KEYALG = (SEC_ERROR_BASE + 48), +SEC_ERROR_DECRYPTION_DISALLOWED = (SEC_ERROR_BASE + 49), +/* Fortezza Alerts */ +XP_SEC_FORTEZZA_BAD_CARD = (SEC_ERROR_BASE + 50), +XP_SEC_FORTEZZA_NO_CARD = (SEC_ERROR_BASE + 51), +XP_SEC_FORTEZZA_NONE_SELECTED = (SEC_ERROR_BASE + 52), +XP_SEC_FORTEZZA_MORE_INFO = (SEC_ERROR_BASE + 53), +XP_SEC_FORTEZZA_PERSON_NOT_FOUND = (SEC_ERROR_BASE + 54), +XP_SEC_FORTEZZA_NO_MORE_INFO = (SEC_ERROR_BASE + 55), +XP_SEC_FORTEZZA_BAD_PIN = (SEC_ERROR_BASE + 56), +XP_SEC_FORTEZZA_PERSON_ERROR = (SEC_ERROR_BASE + 57), +SEC_ERROR_NO_KRL = (SEC_ERROR_BASE + 58), +SEC_ERROR_KRL_EXPIRED = (SEC_ERROR_BASE + 59), +SEC_ERROR_KRL_BAD_SIGNATURE = (SEC_ERROR_BASE + 60), +SEC_ERROR_REVOKED_KEY = (SEC_ERROR_BASE + 61), +SEC_ERROR_KRL_INVALID = (SEC_ERROR_BASE + 62), +SEC_ERROR_NEED_RANDOM = (SEC_ERROR_BASE + 63), +SEC_ERROR_NO_MODULE = (SEC_ERROR_BASE + 64), +SEC_ERROR_NO_TOKEN = (SEC_ERROR_BASE + 65), +SEC_ERROR_READ_ONLY = (SEC_ERROR_BASE + 66), +SEC_ERROR_NO_SLOT_SELECTED = (SEC_ERROR_BASE + 67), +SEC_ERROR_CERT_NICKNAME_COLLISION = (SEC_ERROR_BASE + 68), +SEC_ERROR_KEY_NICKNAME_COLLISION = (SEC_ERROR_BASE + 69), +SEC_ERROR_SAFE_NOT_CREATED = (SEC_ERROR_BASE + 70), +SEC_ERROR_BAGGAGE_NOT_CREATED = (SEC_ERROR_BASE + 71), +XP_JAVA_REMOVE_PRINCIPAL_ERROR = (SEC_ERROR_BASE + 72), +XP_JAVA_DELETE_PRIVILEGE_ERROR = (SEC_ERROR_BASE + 73), +XP_JAVA_CERT_NOT_EXISTS_ERROR = (SEC_ERROR_BASE + 74), +SEC_ERROR_BAD_EXPORT_ALGORITHM = (SEC_ERROR_BASE + 75), +SEC_ERROR_EXPORTING_CERTIFICATES = (SEC_ERROR_BASE + 76), +SEC_ERROR_IMPORTING_CERTIFICATES = (SEC_ERROR_BASE + 77), +SEC_ERROR_PKCS12_DECODING_PFX = (SEC_ERROR_BASE + 78), +SEC_ERROR_PKCS12_INVALID_MAC = (SEC_ERROR_BASE + 79), +SEC_ERROR_PKCS12_UNSUPPORTED_MAC_ALGORITHM = (SEC_ERROR_BASE + 80), +SEC_ERROR_PKCS12_UNSUPPORTED_TRANSPORT_MODE = (SEC_ERROR_BASE + 81), +SEC_ERROR_PKCS12_CORRUPT_PFX_STRUCTURE = (SEC_ERROR_BASE + 82), +SEC_ERROR_PKCS12_UNSUPPORTED_PBE_ALGORITHM = (SEC_ERROR_BASE + 83), +SEC_ERROR_PKCS12_UNSUPPORTED_VERSION = (SEC_ERROR_BASE + 84), +SEC_ERROR_PKCS12_PRIVACY_PASSWORD_INCORRECT = (SEC_ERROR_BASE + 85), +SEC_ERROR_PKCS12_CERT_COLLISION = (SEC_ERROR_BASE + 86), +SEC_ERROR_USER_CANCELLED = (SEC_ERROR_BASE + 87), +SEC_ERROR_PKCS12_DUPLICATE_DATA = (SEC_ERROR_BASE + 88), +SEC_ERROR_MESSAGE_SEND_ABORTED = (SEC_ERROR_BASE + 89), +SEC_ERROR_INADEQUATE_KEY_USAGE = (SEC_ERROR_BASE + 90), +SEC_ERROR_INADEQUATE_CERT_TYPE = (SEC_ERROR_BASE + 91), +SEC_ERROR_CERT_ADDR_MISMATCH = (SEC_ERROR_BASE + 92), +SEC_ERROR_PKCS12_UNABLE_TO_IMPORT_KEY = (SEC_ERROR_BASE + 93), +SEC_ERROR_PKCS12_IMPORTING_CERT_CHAIN = (SEC_ERROR_BASE + 94), +SEC_ERROR_PKCS12_UNABLE_TO_LOCATE_OBJECT_BY_NAME = (SEC_ERROR_BASE + 95), +SEC_ERROR_PKCS12_UNABLE_TO_EXPORT_KEY = (SEC_ERROR_BASE + 96), +SEC_ERROR_PKCS12_UNABLE_TO_WRITE = (SEC_ERROR_BASE + 97), +SEC_ERROR_PKCS12_UNABLE_TO_READ = (SEC_ERROR_BASE + 98), +SEC_ERROR_PKCS12_KEY_DATABASE_NOT_INITIALIZED = (SEC_ERROR_BASE + 99), +SEC_ERROR_KEYGEN_FAIL = (SEC_ERROR_BASE + 100), +SEC_ERROR_INVALID_PASSWORD = (SEC_ERROR_BASE + 101), +SEC_ERROR_RETRY_OLD_PASSWORD = (SEC_ERROR_BASE + 102), +SEC_ERROR_BAD_NICKNAME = (SEC_ERROR_BASE + 103), +SEC_ERROR_NOT_FORTEZZA_ISSUER = (SEC_ERROR_BASE + 104), +SEC_ERROR_CANNOT_MOVE_SENSITIVE_KEY = (SEC_ERROR_BASE + 105), +SEC_ERROR_JS_INVALID_MODULE_NAME = (SEC_ERROR_BASE + 106), +SEC_ERROR_JS_INVALID_DLL = (SEC_ERROR_BASE + 107), +SEC_ERROR_JS_ADD_MOD_FAILURE = (SEC_ERROR_BASE + 108), +SEC_ERROR_JS_DEL_MOD_FAILURE = (SEC_ERROR_BASE + 109), +SEC_ERROR_OLD_KRL = (SEC_ERROR_BASE + 110), +SEC_ERROR_CKL_CONFLICT = (SEC_ERROR_BASE + 111), +SEC_ERROR_CERT_NOT_IN_NAME_SPACE = (SEC_ERROR_BASE + 112), +SEC_ERROR_KRL_NOT_YET_VALID = (SEC_ERROR_BASE + 113), +SEC_ERROR_CRL_NOT_YET_VALID = (SEC_ERROR_BASE + 114), +SEC_ERROR_UNKNOWN_CERT = (SEC_ERROR_BASE + 115), +SEC_ERROR_UNKNOWN_SIGNER = (SEC_ERROR_BASE + 116), +SEC_ERROR_CERT_BAD_ACCESS_LOCATION = (SEC_ERROR_BASE + 117), +SEC_ERROR_OCSP_UNKNOWN_RESPONSE_TYPE = (SEC_ERROR_BASE + 118), +SEC_ERROR_OCSP_BAD_HTTP_RESPONSE = (SEC_ERROR_BASE + 119), +SEC_ERROR_OCSP_MALFORMED_REQUEST = (SEC_ERROR_BASE + 120), +SEC_ERROR_OCSP_SERVER_ERROR = (SEC_ERROR_BASE + 121), +SEC_ERROR_OCSP_TRY_SERVER_LATER = (SEC_ERROR_BASE + 122), +SEC_ERROR_OCSP_REQUEST_NEEDS_SIG = (SEC_ERROR_BASE + 123), +SEC_ERROR_OCSP_UNAUTHORIZED_REQUEST = (SEC_ERROR_BASE + 124), +SEC_ERROR_OCSP_UNKNOWN_RESPONSE_STATUS = (SEC_ERROR_BASE + 125), +SEC_ERROR_OCSP_UNKNOWN_CERT = (SEC_ERROR_BASE + 126), +SEC_ERROR_OCSP_NOT_ENABLED = (SEC_ERROR_BASE + 127), +SEC_ERROR_OCSP_NO_DEFAULT_RESPONDER = (SEC_ERROR_BASE + 128), +SEC_ERROR_OCSP_MALFORMED_RESPONSE = (SEC_ERROR_BASE + 129), +SEC_ERROR_OCSP_UNAUTHORIZED_RESPONSE = (SEC_ERROR_BASE + 130), +SEC_ERROR_OCSP_FUTURE_RESPONSE = (SEC_ERROR_BASE + 131), +SEC_ERROR_OCSP_OLD_RESPONSE = (SEC_ERROR_BASE + 132), +/* smime stuff */ +SEC_ERROR_DIGEST_NOT_FOUND = (SEC_ERROR_BASE + 133), +SEC_ERROR_UNSUPPORTED_MESSAGE_TYPE = (SEC_ERROR_BASE + 134), +SEC_ERROR_MODULE_STUCK = (SEC_ERROR_BASE + 135), +SEC_ERROR_BAD_TEMPLATE = (SEC_ERROR_BASE + 136), +SEC_ERROR_CRL_NOT_FOUND = (SEC_ERROR_BASE + 137), +SEC_ERROR_REUSED_ISSUER_AND_SERIAL = (SEC_ERROR_BASE + 138), +SEC_ERROR_BUSY = (SEC_ERROR_BASE + 139), +SEC_ERROR_NO_USER_INTERACTION = (SEC_ERROR_BASE + 140) +} SECErrorCodes; +#endif /* NO_SECURITY_ERROR_ENUM */ + +#ifdef __APPLE__ +/* + * Given a PRErrorCode, obtain a const C string. Not copied, not + * to be freed by caller. + */ +const char *SECErrorString(PRErrorCode err); + +#endif /* __APPLE__ */ + +PR_END_EXTERN_C + +#endif /* __SEC_ERR_H_ */ diff --git a/libsecurity_asn1/lib/secport.c b/libsecurity_asn1/lib/secport.c new file mode 100644 index 00000000..50a8b8ff --- /dev/null +++ b/libsecurity_asn1/lib/secport.c @@ -0,0 +1,632 @@ +/* + * 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. + */ + +/* + * secport.c - portability interfaces for security libraries + * + * This file abstracts out libc functionality that libsec depends on + * + * NOTE - These are not public interfaces + * + * $Id: secport.c,v 1.5 2004/10/27 20:36:36 dmitch Exp $ + */ + +#include "seccomon.h" +#include "prmem.h" +#include "prerror.h" +#include "plarena.h" +#include "secerr.h" +#include "prmon.h" +#include "nsslocks.h" +#include "secport.h" +#include "prvrsion.h" +#include "prenv.h" + +#ifdef DEBUG +//#define THREADMARK +#endif /* DEBUG */ + +#ifdef THREADMARK +#include "prthread.h" +#endif /* THREADMARK */ + +#if defined(XP_UNIX) || defined(XP_MAC) || defined(XP_OS2) || defined(XP_BEOS) +#include +#else +#include "wtypes.h" +#endif + +#define SET_ERROR_CODE /* place holder for code to set PR error code. */ + +#ifdef THREADMARK +typedef struct threadmark_mark_str { + struct threadmark_mark_str *next; + void *mark; +} threadmark_mark; + +#endif /* THREADMARK */ + +/* The value of this magic must change each time PORTArenaPool changes. */ +#define ARENAPOOL_MAGIC 0xB8AC9BDF + +/* enable/disable mutex in PORTArenaPool */ +#define ARENA_POOL_LOCK 0 + +typedef struct PORTArenaPool_str { + PLArenaPool arena; + PRUint32 magic; + #if ARENA_POOL_LOCK + PRLock * lock; + #endif +#ifdef THREADMARK + PRThread *marking_thread; + threadmark_mark *first_mark; +#endif +} PORTArenaPool; + + +/* count of allocation failures. */ +unsigned long port_allocFailures; + +#ifndef __APPLE__ +/* locations for registering Unicode conversion functions. + * XXX is this the appropriate location? or should they be + * moved to client/server specific locations? + */ +PORTCharConversionFunc ucs4Utf8ConvertFunc; +PORTCharConversionFunc ucs2Utf8ConvertFunc; +PORTCharConversionWSwapFunc ucs2AsciiConvertFunc; +#endif /* __APPLE__ */ + +void * +PORT_Alloc(size_t bytes) +{ + void *rv; + + /* Always allocate a non-zero amount of bytes */ + rv = (void *)PR_Malloc(bytes ? bytes : 1); + if (!rv) { + ++port_allocFailures; + PORT_SetError(SEC_ERROR_NO_MEMORY); + } + return rv; +} + +void * +PORT_Realloc(void *oldptr, size_t bytes) +{ + void *rv; + + rv = (void *)PR_Realloc(oldptr, bytes); + if (!rv) { + ++port_allocFailures; + PORT_SetError(SEC_ERROR_NO_MEMORY); + } + return rv; +} + +void * +PORT_ZAlloc(size_t bytes) +{ + void *rv; + + /* Always allocate a non-zero amount of bytes */ + rv = (void *)PR_Calloc(1, bytes ? bytes : 1); + if (!rv) { + ++port_allocFailures; + PORT_SetError(SEC_ERROR_NO_MEMORY); + } + return rv; +} + +void +PORT_Free(void *ptr) +{ + if (ptr) { + PR_Free(ptr); + } +} + +void +PORT_ZFree(void *ptr, size_t len) +{ + if (ptr) { + memset(ptr, 0, len); + PR_Free(ptr); + } +} + +char * +PORT_Strdup(const char *str) +{ + size_t len = PORT_Strlen(str)+1; + char *newstr; + + newstr = (char *)PORT_Alloc(len); + if (newstr) { + PORT_Memcpy(newstr, str, len); + } + return newstr; +} + +void +PORT_SetError(int value) +{ + PR_SetError(value, 0); + return; +} + +int +PORT_GetError(void) +{ + return(PR_GetError()); +} + +/********************* Arena code follows *****************************/ + +PLArenaPool * +PORT_NewArena(unsigned long chunksize) +{ + PORTArenaPool *pool; + + /* 64 bits cast: Safe. We only use chunksize 1024. */ + PORT_Assert(chunksize<=PR_UINT32_MAX); + + pool = PORT_ZNew(PORTArenaPool); + if (!pool) { + return NULL; + } + pool->magic = ARENAPOOL_MAGIC; + #if ARENA_POOL_LOCK + pool->lock = PZ_NewLock(nssILockArena); + if (!pool->lock) { + ++port_allocFailures; + PORT_Free(pool); + return NULL; + } + #endif + PL_InitArenaPool(&pool->arena, "security", (PRUint32) chunksize, (PRUint32)sizeof(double)); + return(&pool->arena); +} + +void * +PORT_ArenaAlloc(PLArenaPool *arena, size_t size) +{ + void *p; + + PORTArenaPool *pool = (PORTArenaPool *)arena; + + PORT_Assert(size<=PR_UINT32_MAX); + + /* Is it one of ours? Assume so and check the magic */ + if (ARENAPOOL_MAGIC == pool->magic ) { + #if ARENA_POOL_LOCK + PZ_Lock(pool->lock); + #ifdef THREADMARK + /* Most likely one of ours. Is there a thread id? */ + if (pool->marking_thread && + pool->marking_thread != PR_GetCurrentThread() ) { + /* Another thread holds a mark in this arena */ + PZ_Unlock(pool->lock); + PORT_SetError(SEC_ERROR_NO_MEMORY); + PORT_Assert(0); + return NULL; + } /* tid != null */ + #endif /* THREADMARK */ + #endif /* ARENA_POOL_LOCK */ + PL_ARENA_ALLOCATE(p, arena, (PRUint32)size); + #if ARENA_POOL_LOCK + PZ_Unlock(pool->lock); + #endif + } else { + PL_ARENA_ALLOCATE(p, arena, (PRUint32)size); + } + + if (!p) { + ++port_allocFailures; + PORT_SetError(SEC_ERROR_NO_MEMORY); + } + + return(p); +} + +void * +PORT_ArenaZAlloc(PLArenaPool *arena, size_t size) +{ + void *p = PORT_ArenaAlloc(arena, size); + + if (p) { + PORT_Memset(p, 0, size); + } + + return(p); +} + +/* XXX - need to zeroize!! - jsw */ +void +PORT_FreeArena(PLArenaPool *arena, PRBool zero) +{ + PORTArenaPool *pool = (PORTArenaPool *)arena; + #if ARENA_POOL_LOCK + PRLock * lock = (PRLock *)0; + #endif + size_t len = sizeof *arena; + extern const PRVersionDescription * libVersionPoint(void); + #ifndef __APPLE__ + static const PRVersionDescription * pvd; + #endif + static PRBool doFreeArenaPool = PR_FALSE; + + if (ARENAPOOL_MAGIC == pool->magic ) { + len = sizeof *pool; + #if ARENA_POOL_LOCK + lock = pool->lock; + PZ_Lock(lock); + #endif + } + #ifndef __APPLE__ + /* dmitch - not needed */ + if (!pvd) { + /* Each of NSPR's DLLs has a function libVersionPoint(). + ** We could do a lot of extra work to be sure we're calling the + ** one in the DLL that holds PR_FreeArenaPool, but instead we + ** rely on the fact that ALL NSPR DLLs in the same directory + ** must be from the same release, and we call which ever one we get. + */ + /* no need for thread protection here */ + pvd = libVersionPoint(); + if ((pvd->vMajor > 4) || + (pvd->vMajor == 4 && pvd->vMinor > 1) || + (pvd->vMajor == 4 && pvd->vMinor == 1 && pvd->vPatch >= 1)) { + const char *ev = PR_GetEnv("NSS_DISABLE_ARENA_FREE_LIST"); + if (!ev) doFreeArenaPool = PR_TRUE; + } + } + #endif + if (doFreeArenaPool) { + PL_FreeArenaPool(arena); + } else { + PL_FinishArenaPool(arena); + } + #if ARENA_POOL_LOCK + if (lock) { + PZ_Unlock(lock); + PZ_DestroyLock(lock); + } + #endif + PORT_ZFree(arena, len); +} + +void * +PORT_ArenaGrow(PLArenaPool *arena, void *ptr, size_t oldsize, size_t newsize) +{ + PORTArenaPool *pool = (PORTArenaPool *)arena; + PORT_Assert(newsize >= oldsize); + PORT_Assert(oldsize <= PR_UINT32_MAX); + PORT_Assert(newsize <= PR_UINT32_MAX); + + if (ARENAPOOL_MAGIC == pool->magic ) { + #if ARENA_POOL_LOCK + PZ_Lock(pool->lock); + #endif + /* Do we do a THREADMARK check here? */ + PL_ARENA_GROW(ptr, arena, (PRUint32)oldsize, (PRUint32)( newsize - oldsize ) ); + #if ARENA_POOL_LOCK + PZ_Unlock(pool->lock); + #endif + } else { + PL_ARENA_GROW(ptr, arena, (PRUint32)oldsize, (PRUint32)( newsize - oldsize ) ); + } + + return(ptr); +} + +void * +PORT_ArenaMark(PLArenaPool *arena) +{ +#if ARENA_MARK_ENABLE + void * result; + + PORTArenaPool *pool = (PORTArenaPool *)arena; + if (ARENAPOOL_MAGIC == pool->magic ) { + PZ_Lock(pool->lock); +#ifdef THREADMARK + { + threadmark_mark *tm, **pw; + PRThread * currentThread = PR_GetCurrentThread(); + + if (! pool->marking_thread ) { + /* First mark */ + pool->marking_thread = currentThread; + } else if (currentThread != pool->marking_thread ) { + PZ_Unlock(pool->lock); + PORT_SetError(SEC_ERROR_NO_MEMORY); + PORT_Assert(0); + return NULL; + } + + result = PL_ARENA_MARK(arena); + PL_ARENA_ALLOCATE(tm, arena, sizeof(threadmark_mark)); + if (!tm) { + PZ_Unlock(pool->lock); + PORT_SetError(SEC_ERROR_NO_MEMORY); + return NULL; + } + + tm->mark = result; + tm->next = (threadmark_mark *)NULL; + + pw = &pool->first_mark; + while( *pw ) { + pw = &(*pw)->next; + } + + *pw = tm; + } +#else /* THREADMARK */ + result = PL_ARENA_MARK(arena); +#endif /* THREADMARK */ + PZ_Unlock(pool->lock); + } else { + /* a "pure" NSPR arena */ + result = PL_ARENA_MARK(arena); + } + return result; +#else + /* Some code in libsecurity_smime really checks for a nonzero + * return here, so... */ + return (void *)-1; +#endif +} + +void +PORT_ArenaRelease(PLArenaPool *arena, void *mark) +{ +#if ARENA_MARK_ENABLE + PORTArenaPool *pool = (PORTArenaPool *)arena; + if (ARENAPOOL_MAGIC == pool->magic ) { + PZ_Lock(pool->lock); +#ifdef THREADMARK + { + threadmark_mark **pw, *tm; + + if (PR_GetCurrentThread() != pool->marking_thread ) { + PZ_Unlock(pool->lock); + PORT_SetError(SEC_ERROR_NO_MEMORY); + PORT_Assert(0); + return /* no error indication available */ ; + } + + pw = &pool->first_mark; + while( *pw && (mark != (*pw)->mark) ) { + pw = &(*pw)->next; + } + + if (! *pw ) { + /* bad mark */ + PZ_Unlock(pool->lock); + PORT_SetError(SEC_ERROR_NO_MEMORY); + PORT_Assert(0); + return /* no error indication available */ ; + } + + tm = *pw; + *pw = (threadmark_mark *)NULL; + + PL_ARENA_RELEASE(arena, mark); + + if (! pool->first_mark ) { + pool->marking_thread = (PRThread *)NULL; + } + } +#else /* THREADMARK */ + PL_ARENA_RELEASE(arena, mark); +#endif /* THREADMARK */ + PZ_Unlock(pool->lock); + } else { + PL_ARENA_RELEASE(arena, mark); + } +#endif /* ARENA_MARK_ENABLE */ +} + +void +PORT_ArenaUnmark(PLArenaPool *arena, void *mark) +{ +#if ARENA_MARK_ENABLE +#ifdef THREADMARK + PORTArenaPool *pool = (PORTArenaPool *)arena; + if (ARENAPOOL_MAGIC == pool->magic ) { + threadmark_mark **pw, *tm; + + PZ_Lock(pool->lock); + + if (PR_GetCurrentThread() != pool->marking_thread ) { + PZ_Unlock(pool->lock); + PORT_SetError(SEC_ERROR_NO_MEMORY); + PORT_Assert(0); + return /* no error indication available */ ; + } + + pw = &pool->first_mark; + while( ((threadmark_mark *)NULL != *pw) && (mark != (*pw)->mark) ) { + pw = &(*pw)->next; + } + + if ((threadmark_mark *)NULL == *pw ) { + /* bad mark */ + PZ_Unlock(pool->lock); + PORT_SetError(SEC_ERROR_NO_MEMORY); + PORT_Assert(0); + return /* no error indication available */ ; + } + + tm = *pw; + *pw = (threadmark_mark *)NULL; + + if (! pool->first_mark ) { + pool->marking_thread = (PRThread *)NULL; + } + + PZ_Unlock(pool->lock); + } +#endif /* THREADMARK */ +#endif /* ARENA_MARK_ENABLE */ +} + +char * +PORT_ArenaStrdup(PLArenaPool *arena, const char *str) { + size_t len = PORT_Strlen(str)+1; + char *newstr; + + newstr = (char*)PORT_ArenaAlloc(arena,len); + if (newstr) { + PORT_Memcpy(newstr,str,len); + } + return newstr; +} + +/********************** end of arena functions ***********************/ + +#ifndef __APPLE__ + +/****************** unicode conversion functions ***********************/ +/* + * NOTE: These conversion functions all assume that the multibyte + * characters are going to be in NETWORK BYTE ORDER, not host byte + * order. This is because the only time we deal with UCS-2 and UCS-4 + * are when the data was received from or is going to be sent out + * over the wire (in, e.g. certificates). + */ + +void +PORT_SetUCS4_UTF8ConversionFunction(PORTCharConversionFunc convFunc) +{ + ucs4Utf8ConvertFunc = convFunc; +} + +void +PORT_SetUCS2_ASCIIConversionFunction(PORTCharConversionWSwapFunc convFunc) +{ + ucs2AsciiConvertFunc = convFunc; +} + +void +PORT_SetUCS2_UTF8ConversionFunction(PORTCharConversionFunc convFunc) +{ + ucs2Utf8ConvertFunc = convFunc; +} + +//#ifndef __APPLE__ +/* dmitch - not needed */ +PRBool +PORT_UCS4_UTF8Conversion(PRBool toUnicode, unsigned char *inBuf, + unsigned int inBufLen, unsigned char *outBuf, + unsigned int maxOutBufLen, unsigned int *outBufLen) +{ + if(!ucs4Utf8ConvertFunc) { + return sec_port_ucs4_utf8_conversion_function(toUnicode, + inBuf, inBufLen, outBuf, maxOutBufLen, outBufLen); + } + + return (*ucs4Utf8ConvertFunc)(toUnicode, inBuf, inBufLen, outBuf, + maxOutBufLen, outBufLen); +} + +PRBool +PORT_UCS2_UTF8Conversion(PRBool toUnicode, unsigned char *inBuf, + unsigned int inBufLen, unsigned char *outBuf, + unsigned int maxOutBufLen, unsigned int *outBufLen) +{ + if(!ucs2Utf8ConvertFunc) { + return sec_port_ucs2_utf8_conversion_function(toUnicode, + inBuf, inBufLen, outBuf, maxOutBufLen, outBufLen); + } + + return (*ucs2Utf8ConvertFunc)(toUnicode, inBuf, inBufLen, outBuf, + maxOutBufLen, outBufLen); +} +//#endif /* __APPLE__ */ + +PRBool +PORT_UCS2_ASCIIConversion(PRBool toUnicode, unsigned char *inBuf, + unsigned int inBufLen, unsigned char *outBuf, + unsigned int maxOutBufLen, unsigned int *outBufLen, + PRBool swapBytes) +{ + if(!ucs2AsciiConvertFunc) { + return PR_FALSE; + } + + return (*ucs2AsciiConvertFunc)(toUnicode, inBuf, inBufLen, outBuf, + maxOutBufLen, outBufLen, swapBytes); +} + + +/* Portable putenv. Creates/replaces an environment variable of the form + * envVarName=envValue + */ +int +NSS_PutEnv(const char * envVarName, const char * envValue) +{ +#if defined(XP_MAC) || defined(_WIN32_WCE) + return SECFailure; +#else + SECStatus result = SECSuccess; + char * encoded; + int putEnvFailed; +#ifdef _WIN32 + PRBool setOK; + + setOK = SetEnvironmentVariable(envVarName, envValue); + if (!setOK) { + SET_ERROR_CODE + return SECFailure; + } +#endif + + encoded = (char *)PORT_ZAlloc(strlen(envVarName) + 2 + strlen(envValue)); + strcpy(encoded, envVarName); + strcat(encoded, "="); + strcat(encoded, envValue); + + putEnvFailed = putenv(encoded); /* adopt. */ + if (putEnvFailed) { + SET_ERROR_CODE + result = SECFailure; + PORT_Free(encoded); + } + return result; +#endif +} +#endif /* __APPLE__ */ + diff --git a/libsecurity_asn1/lib/secport.h b/libsecurity_asn1/lib/secport.h new file mode 100644 index 00000000..373cf0b4 --- /dev/null +++ b/libsecurity_asn1/lib/secport.h @@ -0,0 +1,290 @@ +/* + * 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. + */ + +/* + * secport.h - portability interfaces for security libraries + * + * This file abstracts out libc functionality that libsec depends on + * + * NOTE - These are not public interfaces + * + * $Id: secport.h,v 1.3 2004/10/22 19:11:36 dmitch Exp $ + */ + +#ifndef _SECPORT_H_ +#define _SECPORT_H_ + +/* + * define XP_MAC, XP_WIN, XP_BEOS, or XP_UNIX, in case they are not defined + * by anyone else + */ +#ifdef macintosh +# ifndef XP_MAC +# define XP_MAC 1 +# endif +#endif + +#ifdef _WINDOWS +# ifndef XP_WIN +# define XP_WIN +# endif +#if defined(_WIN32) || defined(WIN32) +# ifndef XP_WIN32 +# define XP_WIN32 +# endif +#else +# ifndef XP_WIN16 +# define XP_WIN16 +# endif +#endif +#endif + +#ifdef __BEOS__ +# ifndef XP_BEOS +# define XP_BEOS +# endif +#endif + +#ifdef unix +# ifndef XP_UNIX +# define XP_UNIX +# endif +#endif + +#if defined(__WATCOMC__) || defined(__WATCOM_CPLUSPLUS__) +#include "watcomfx.h" +#endif + +#if defined(_WIN32_WCE) +#include +#include +#elif defined( XP_MAC ) +#include +#include /* for time_t below */ +#else +#include +#endif + +#ifdef notdef +#ifdef XP_MAC +#include "NSString.h" +#endif +#endif + +#include +#include +#if defined(_WIN32_WCE) +#include /* WinCE puts some stddef symbols here. */ +#else +#include +#endif +#include +#include "prtypes.h" +#include "prlog.h" /* for PR_ASSERT */ +#include "plarenas.h" +#include "plstr.h" + +/* + * HACK for NSS 2.8 to allow Admin to compile without source changes. + */ +#ifndef SEC_BEGIN_PROTOS +#include "seccomon.h" +#endif + +SEC_BEGIN_PROTOS + +extern void *PORT_Alloc(size_t len); +extern void *PORT_Realloc(void *old, size_t len); +extern void *PORT_AllocBlock(size_t len); +extern void *PORT_ReallocBlock(void *old, size_t len); +extern void PORT_FreeBlock(void *ptr); +extern void *PORT_ZAlloc(size_t len); +extern void PORT_Free(void *ptr); +extern void PORT_ZFree(void *ptr, size_t len); +extern time_t PORT_Time(void); +extern void PORT_SetError(int value); +extern int PORT_GetError(void); + +extern PLArenaPool *PORT_NewArena(unsigned long chunksize); +extern void *PORT_ArenaAlloc(PLArenaPool *arena, size_t size); +extern void *PORT_ArenaZAlloc(PLArenaPool *arena, size_t size); +extern void PORT_FreeArena(PLArenaPool *arena, PRBool zero); +extern void *PORT_ArenaGrow(PLArenaPool *arena, void *ptr, + size_t oldsize, size_t newsize); +extern void *PORT_ArenaMark(PLArenaPool *arena); +extern void PORT_ArenaRelease(PLArenaPool *arena, void *mark); +extern void PORT_ArenaUnmark(PLArenaPool *arena, void *mark); + +extern char *PORT_ArenaStrdup(PLArenaPool *arena, const char *str); + +#ifdef __cplusplus +} +#endif + +#define PORT_Assert PR_ASSERT +#define PORT_ZNew(type) (type*)PORT_ZAlloc(sizeof(type)) +#define PORT_New(type) (type*)PORT_Alloc(sizeof(type)) +#define PORT_ArenaNew(poolp, type) \ + (type*) PORT_ArenaAlloc(poolp, sizeof(type)) +#define PORT_ArenaZNew(poolp, type) \ + (type*) PORT_ArenaZAlloc(poolp, sizeof(type)) +#define PORT_NewArray(type, num) \ + (type*) PORT_Alloc (sizeof(type)*(num)) +#define PORT_ZNewArray(type, num) \ + (type*) PORT_ZAlloc (sizeof(type)*(num)) +#define PORT_ArenaNewArray(poolp, type, num) \ + (type*) PORT_ArenaAlloc (poolp, sizeof(type)*(num)) +#define PORT_ArenaZNewArray(poolp, type, num) \ + (type*) PORT_ArenaZAlloc (poolp, sizeof(type)*(num)) + +/* Please, keep these defines sorted alphbetically. Thanks! */ + +#ifdef XP_STRING_FUNCS + +#define PORT_Atoi XP_ATOI + +#define PORT_Memcmp XP_MEMCMP +#define PORT_Memcpy XP_MEMCPY +#define PORT_Memmove XP_MEMMOVE +#define PORT_Memset XP_MEMSET + +#define PORT_Strcasecmp XP_STRCASECMP +#define PORT_Strcat XP_STRCAT +#define PORT_Strchr XP_STRCHR +#define PORT_Strrchr XP_STRRCHR +#define PORT_Strcmp XP_STRCMP +#define PORT_Strcpy XP_STRCPY +#define PORT_Strdup XP_STRDUP +#define PORT_Strlen(s) XP_STRLEN(s) +#define PORT_Strncasecmp XP_STRNCASECMP +#define PORT_Strncat strncat +#define PORT_Strncmp XP_STRNCMP +#define PORT_Strncpy strncpy +#define PORT_Strstr XP_STRSTR +#define PORT_Strtok XP_STRTOK_R + +#define PORT_Tolower XP_TO_LOWER + +#else /* XP_STRING_FUNCS */ + +#define PORT_Atoi atoi + +#define PORT_Memcmp memcmp +#define PORT_Memcpy memcpy +#ifndef SUNOS4 +#define PORT_Memmove memmove +#else /*SUNOS4*/ +#define PORT_Memmove(s,ct,n) bcopy ((ct), (s), (n)) +#endif/*SUNOS4*/ +#define PORT_Memset memset + +#define PORT_Strcasecmp PL_strcasecmp +#define PORT_Strcat strcat +#define PORT_Strchr strchr +#define PORT_Strrchr strrchr +#define PORT_Strcmp strcmp +#define PORT_Strcpy strcpy +extern char *PORT_Strdup(const char *s); +#define PORT_Strlen(s) strlen(s) +#define PORT_Strncasecmp PL_strncasecmp +#define PORT_Strncat strncat +#define PORT_Strncmp strncmp +#define PORT_Strncpy strncpy +#define PORT_Strstr strstr +#define PORT_Strtok strtok + +#define PORT_Tolower tolower + +#endif /* XP_STRING_FUNCS */ + +#ifndef __APPLE__ + +typedef PRBool (PR_CALLBACK * PORTCharConversionWSwapFunc) (PRBool toUnicode, + unsigned char *inBuf, unsigned int inBufLen, + unsigned char *outBuf, unsigned int maxOutBufLen, + unsigned int *outBufLen, PRBool swapBytes); + +typedef PRBool (PR_CALLBACK * PORTCharConversionFunc) (PRBool toUnicode, + unsigned char *inBuf, unsigned int inBufLen, + unsigned char *outBuf, unsigned int maxOutBufLen, + unsigned int *outBufLen); + +#ifdef __cplusplus +extern "C" { +#endif + +void PORT_SetUCS4_UTF8ConversionFunction(PORTCharConversionFunc convFunc); +void PORT_SetUCS2_ASCIIConversionFunction(PORTCharConversionWSwapFunc convFunc); +PRBool PORT_UCS4_UTF8Conversion(PRBool toUnicode, unsigned char *inBuf, + unsigned int inBufLen, unsigned char *outBuf, + unsigned int maxOutBufLen, unsigned int *outBufLen); +PRBool PORT_UCS2_ASCIIConversion(PRBool toUnicode, unsigned char *inBuf, + unsigned int inBufLen, unsigned char *outBuf, + unsigned int maxOutBufLen, unsigned int *outBufLen, + PRBool swapBytes); +void PORT_SetUCS2_UTF8ConversionFunction(PORTCharConversionFunc convFunc); +PRBool PORT_UCS2_UTF8Conversion(PRBool toUnicode, unsigned char *inBuf, + unsigned int inBufLen, unsigned char *outBuf, + unsigned int maxOutBufLen, unsigned int *outBufLen); + +PR_EXTERN(PRBool) +sec_port_ucs4_utf8_conversion_function +( + PRBool toUnicode, + unsigned char *inBuf, + unsigned int inBufLen, + unsigned char *outBuf, + unsigned int maxOutBufLen, + unsigned int *outBufLen +); + +PR_EXTERN(PRBool) +sec_port_ucs2_utf8_conversion_function +( + PRBool toUnicode, + unsigned char *inBuf, + unsigned int inBufLen, + unsigned char *outBuf, + unsigned int maxOutBufLen, + unsigned int *outBufLen +); + +extern int NSS_PutEnv(const char * envVarName, const char * envValue); + +#ifdef __cplusplus +} +#endif + +#endif /* __APPLE__ */ + +#endif /* _SECPORT_H_ */ diff --git a/libsecurity_asn1/lib/security_asn1.exp b/libsecurity_asn1/lib/security_asn1.exp new file mode 100644 index 00000000..599c680c --- /dev/null +++ b/libsecurity_asn1/lib/security_asn1.exp @@ -0,0 +1,166 @@ +_SecAsn1AllocCopy +_SecAsn1AllocCopyItem +_SecAsn1AllocItem +_SecAsn1CoderCreate +_SecAsn1CoderRelease +_SecAsn1Decode +_SecAsn1DecodeData +_SecAsn1EncodeItem +_SecAsn1Malloc +_kSecAsn1AnyTemplate +_kSecAsn1BMPStringTemplate +_kSecAsn1BitStringTemplate +_kSecAsn1BooleanTemplate +_kSecAsn1EnumeratedTemplate +_kSecAsn1GeneralizedTimeTemplate +_kSecAsn1IA5StringTemplate +_kSecAsn1IntegerTemplate +_kSecAsn1NullTemplate +_kSecAsn1ObjectIDTemplate +_kSecAsn1OctetStringTemplate +_kSecAsn1PointerToAnyTemplate +_kSecAsn1PointerToBMPStringTemplate +_kSecAsn1PointerToBitStringTemplate +_kSecAsn1PointerToBooleanTemplate +_kSecAsn1PointerToEnumeratedTemplate +_kSecAsn1PointerToGeneralizedTimeTemplate +_kSecAsn1PointerToIA5StringTemplate +_kSecAsn1PointerToIntegerTemplate +_kSecAsn1PointerToNullTemplate +_kSecAsn1PointerToObjectIDTemplate +_kSecAsn1PointerToOctetStringTemplate +_kSecAsn1PointerToPrintableStringTemplate +_kSecAsn1PointerToT61StringTemplate +_kSecAsn1PointerToTeletexStringTemplate +_kSecAsn1PointerToUTCTimeTemplate +_kSecAsn1PointerToUTF8StringTemplate +_kSecAsn1PointerToUniversalStringTemplate +_kSecAsn1PointerToVisibleStringTemplate +_kSecAsn1PrintableStringTemplate +_kSecAsn1SequenceOfAnyTemplate +_kSecAsn1SequenceOfBMPStringTemplate +_kSecAsn1SequenceOfBitStringTemplate +_kSecAsn1SequenceOfBooleanTemplate +_kSecAsn1SequenceOfEnumeratedTemplate +_kSecAsn1SequenceOfGeneralizedTimeTemplate +_kSecAsn1SequenceOfIA5StringTemplate +_kSecAsn1SequenceOfIntegerTemplate +_kSecAsn1SequenceOfNullTemplate +_kSecAsn1SequenceOfObjectIDTemplate +_kSecAsn1SequenceOfOctetStringTemplate +_kSecAsn1SequenceOfPrintableStringTemplate +_kSecAsn1SequenceOfT61StringTemplate +_kSecAsn1SequenceOfTeletexStringTemplate +_kSecAsn1SequenceOfUTCTimeTemplate +_kSecAsn1SequenceOfUTF8StringTemplate +_kSecAsn1SequenceOfUniversalStringTemplate +_kSecAsn1SequenceOfVisibleStringTemplate +_kSecAsn1SetOfAnyTemplate +_kSecAsn1SetOfBMPStringTemplate +_kSecAsn1SetOfBitStringTemplate +_kSecAsn1SetOfBooleanTemplate +_kSecAsn1SetOfEnumeratedTemplate +_kSecAsn1SetOfGeneralizedTimeTemplate +_kSecAsn1SetOfIA5StringTemplate +_kSecAsn1SetOfIntegerTemplate +_kSecAsn1SetOfNullTemplate +_kSecAsn1SetOfObjectIDTemplate +_kSecAsn1SetOfOctetStringTemplate +_kSecAsn1SetOfPrintableStringTemplate +_kSecAsn1SetOfT61StringTemplate +_kSecAsn1SetOfTeletexStringTemplate +_kSecAsn1SetOfUTCTimeTemplate +_kSecAsn1SetOfUTF8StringTemplate +_kSecAsn1SetOfUniversalStringTemplate +_kSecAsn1SetOfVisibleStringTemplate +_kSecAsn1SkipTemplate +_kSecAsn1T61StringTemplate +_kSecAsn1TeletexStringTemplate +_kSecAsn1UTCTimeTemplate +_kSecAsn1UTF8StringTemplate +_kSecAsn1UniversalStringTemplate +_kSecAsn1UnsignedIntegerTemplate +_kSecAsn1VisibleStringTemplate +_kSecAsn1CertExtensionTemplate +_kSecAsn1RevokedCertTemplate +_kSecAsn1SequenceOfCertExtensionTemplate +_kSecAsn1SequenceOfRevokedCertTemplate +_kSecAsn1SignedCertOrCRLTemplate +_kSecAsn1SignedCertTemplate +_kSecAsn1SignedCrlTemplate +_kSecAsn1TBSCertificateTemplate +_kSecAsn1TBSCrlTemplate +_kSecAsn1ValidityTemplate +_kSecAsn1AccessDescriptionTemplate +_kSecAsn1AuthorityInfoAccessTemplate +_kSecAsn1AuthorityKeyIdTemplate +_kSecAsn1BasicConstraintsTemplate +_kSecAsn1CRLDistributionPointsTemplate +_kSecAsn1CertPoliciesTemplate +_kSecAsn1DistPointFullNameTemplate +_kSecAsn1DistPointRDNTemplate +_kSecAsn1DistributionPointTemplate +_kSecAsn1IssuingDistributionPointTemplate +_kSecAsn1PolicyInformationTemplate +_kSecAsn1PolicyQualifierTemplate +_kSecAsn1CertRequestInfoTemplate +_kSecAsn1CertRequestTemplate +_kSecAsn1SignedCertRequestTemplate +_kSecAsn1AlgorithmIDTemplate +_kSecAsn1AttributeTemplate +_kSecAsn1DHAlgorithmIdentifierX942Template +_kSecAsn1DHDomainParamsX942Template +_kSecAsn1DHParameterBlockTemplate +_kSecAsn1DHParameterTemplate +_kSecAsn1DHPrivateKeyPKCS8Template +_kSecAsn1DHPrivateKeyTemplate +_kSecAsn1DHPublicKeyX509Template +_kSecAsn1DHValidationParamsTemplate +_kSecAsn1DigestInfoTemplate +_kSecAsn1EncryptedPrivateKeyInfoTemplate +_kSecAsn1PrivateKeyInfoTemplate +_kSecAsn1RSAPrivateKeyPKCS1Template +_kSecAsn1RSAPublicKeyPKCS1Template +_kSecAsn1SetOfAttributeTemplate +_kSecAsn1SubjectPublicKeyInfoTemplate +_kSecAsn1ATVTemplate +_kSecAsn1GenNameOtherNameTemplate +_kSecAsn1GeneralNameTemplate +_kSecAsn1NameTemplate +_kSecAsn1OtherNameTemplate +_kSecAsn1RDNTemplate +_SecAsn1TaggedTemplateChooser +_kSecAsn1DSAAlgParamsTemplate +_kSecAsn1DSAAlgParamsBSAFETemplate +_kSecAsn1DSAAlgorithmIdX509Template +_kSecAsn1DSAAlgorithmIdBSAFETemplate +_kSecAsn1DSAPublicKeyX509Template +_kSecAsn1DSAPublicKeyBSAFETemplate +_kSecAsn1DSAPrivateKeyOpensslTemplate +_kSecAsn1DSAPrivateKeyOctsTemplate +_kSecAsn1DSAPrivateKeyBSAFETemplate +_kSecAsn1DSAPrivateKeyPKCS8Template +_kSecAsn1DSASignatureTemplate +_kSecAsn1OCSPBasicResponseTemplate +_kSecAsn1OCSPCertIDTemplate +_kSecAsn1OCSPCertStatusGoodTemplate +_kSecAsn1OCSPCertStatusRevokedTemplate +_kSecAsn1OCSPCertStatusUnknownTemplate +_kSecAsn1OCSPRequestTemplate +_kSecAsn1OCSPResponderIDAsNameTemplate +_kSecAsn1OCSPResponderIDAsKeyTemplate +_kSecAsn1OCSPResponseBytesTemplate +_kSecAsn1OCSPResponseDataTemplate +_kSecAsn1OCSPResponseTemplate +_kSecAsn1OCSPRevokedInfoTemplate +_kSecAsn1OCSPSignatureTemplate +_kSecAsn1OCSPSignedRequestTemplate +_kSecAsn1OCSPSingleResponseTemplate +_kSecAsn1OCSPTbsRequestTemplate +_kSecAsn1OCSPDRequestTemplate +_kSecAsn1OCSPDRequestsTemplate +_kSecAsn1OCSPDReplyTemplate +_kSecAsn1OCSPDRepliesTemplate +_kSecAsn1SemanticsInformationTemplate +_kSecAsn1QC_StatementTemplate +_kSecAsn1QC_StatementsTemplate diff --git a/libsecurity_asn1/libsecurity_asn1.xcodeproj/project.pbxproj b/libsecurity_asn1/libsecurity_asn1.xcodeproj/project.pbxproj new file mode 100644 index 00000000..1c1d7679 --- /dev/null +++ b/libsecurity_asn1/libsecurity_asn1.xcodeproj/project.pbxproj @@ -0,0 +1,459 @@ +// !$*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 */; }; + 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 = 0430; + }; + 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 = 18B647F714D9FD4500F538BF /* lib.xcconfig */; + buildSettings = { + }; + name = Debug; + }; + 795CA80D0D3801A700BAE6A2 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 18B647F614D9FD4500F538BF /* debug.xcconfig */; + buildSettings = { + LIBRARY_STYLE = STATIC; + }; + name = Debug; + }; + 795CA8180D3801A900BAE6A2 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 18B647F714D9FD4500F538BF /* lib.xcconfig */; + buildSettings = { + }; + name = Release; + }; + 795CA81C0D3801A900BAE6A2 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 18B647F814D9FD4500F538BF /* release.xcconfig */; + buildSettings = { + 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/libsecurity_asn1/security_asn1 new file mode 120000 index 00000000..945c9b46 --- /dev/null +++ b/libsecurity_asn1/security_asn1 @@ -0,0 +1 @@ +. \ No newline at end of file diff --git a/libsecurity_authorization/APPLE_LICENSE b/libsecurity_authorization/APPLE_LICENSE new file mode 100644 index 00000000..71fe6fd7 --- /dev/null +++ b/libsecurity_authorization/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/libsecurity_authorization/Info-security_authorization.plist b/libsecurity_authorization/Info-security_authorization.plist new file mode 100644 index 00000000..0c67376e --- /dev/null +++ b/libsecurity_authorization/Info-security_authorization.plist @@ -0,0 +1,5 @@ + + + + + diff --git a/libsecurity_authorization/lib/AuthSession.h b/libsecurity_authorization/lib/AuthSession.h new file mode 100644 index 00000000..dd218be0 --- /dev/null +++ b/libsecurity_authorization/lib/AuthSession.h @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2000-2003 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@ + */ + + +/* + * AuthSession.h + * AuthSession - APIs for managing login, authorization, and security Sessions. + */ +#if !defined(__AuthSession__) +#define __AuthSession__ 1 + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +/*! + @header AuthSession + + The Session API provides specialized applications access to Session management and inquiry + functions. This is a specialized API that should not be of interest to most people. + + The Security subsystem separates all processes into Security "sessions". Each process is in + exactly one session, and session membership inherits across fork/exec. Sessions form boundaries + for security-related state such as authorizations, keychain lock status, and the like. + Typically, each successful login (whether graphical or through ssh & friends) creates + a separate session. System daemons (started at system startup) belong to the "root session" + which has no user nor graphics access. + + Sessions are identified with SecuritySessionIds. A session has a set of attributes + that are set on creation and can be retrieved with SessionGetInfo(). + + There are similar session concepts in the system, related but not necessarily + completely congruous. In particular, graphics sessions track security sessions + (but only for graphic logins). +*/ + + +/*! + @typedef SecuritySessionId + These are externally visible identifiers for authorization sessions. + Different sessions have different identifiers; beyond that, you can't + tell anything from these values. + SessionIds can be compared for equality as you'd expect, but you should be careful + to use attribute bits wherever appropriate. +*/ +typedef UInt32 SecuritySessionId; + + +/*! + @enum SecuritySessionId + Here are some special values for SecuritySessionId. You may specify those + on input to SessionAPI functions. They will never be returned from such + functions. + + Note: -2 is reserved (see 4487137). +*/ +enum { + noSecuritySession = 0, /* definitely not a valid SecuritySessionId */ + callerSecuritySession = ((SecuritySessionId)-1) /* the Session I (the caller) am in */ +}; + + +/*! + @enum SessionAttributeBits + Each Session has a set of attribute bits. You can get those from the + SessionGetInfo API function. + */ +typedef UInt32 SessionAttributeBits; + +enum { + sessionIsRoot = 0x0001, /* is the root session (startup/system programs) */ + sessionHasGraphicAccess = 0x0010, /* graphic subsystem (CoreGraphics et al) available */ + sessionHasTTY = 0x0020, /* /dev/tty is available */ + sessionIsRemote = 0x1000, /* session was established over the network */ +}; + + +/*! + @enum SessionCreationFlags + These flags control how a new session is created by SessionCreate. + They have no permanent meaning beyond that. + */ +typedef UInt32 SessionCreationFlags; + +enum { + sessionKeepCurrentBootstrap = 0x8000 /* caller has allocated sub-bootstrap (expert use only) */ +}; + + +/*! + @enum SessionStatus + Error codes returned by AuthSession API. + Note that the AuthSession APIs can also return Authorization API error codes. +*/ +enum { + errSessionSuccess = 0, /* all is well */ + errSessionInvalidId = -60500, /* invalid session id specified */ + errSessionInvalidAttributes = -60501, /* invalid set of requested attribute bits */ + errSessionAuthorizationDenied = -60502, /* you are not allowed to do this */ + errSessionValueNotSet = -60503, /* the session attribute you requested has not been set */ + + errSessionInternal = errAuthorizationInternal, /* internal error */ + errSessionInvalidFlags = errAuthorizationInvalidFlags /* invalid flags/options */ +}; + + +/*! + @function SessionGetInfo + Obtain information about a session. You can ask about any session whose + identifier you know. Use the callerSecuritySession constant to ask about + your own session (the one your process is in). + + @param session (input) The Session you are asking about. Can be one of the + special constants defined above. + + @param sessionId (output/optional) The actual SecuritySessionId for the session you asked about. + Will never be one of those constants. + + @param attributes (output/optional) Receives the attribute bits for the session. + + @result An OSStatus indicating success (noErr) or an error cause. + + errSessionInvalidId -60500 Invalid session id specified + +*/ +OSStatus SessionGetInfo(SecuritySessionId session, + SecuritySessionId *sessionId, + SessionAttributeBits *attributes); + + +/*! + @function SessionCreate + This (very specialized) function creates a security session. + Upon completion, the new session contains the calling process (and none other). + You cannot create a session for someone else, and cannot avoid being placed + into the new session. This is (currently) the only call that changes a process's + session membership. + By default, a new bootstrap subset port is created for the calling process. The process + acquires this new port as its bootstrap port, which all its children will inherit. + If you happen to have created the subset port on your own, you can pass the + sessionKeepCurrentBootstrap flag, and SessionCreate will use it. Note however that + you cannot supersede a prior SessionCreate call that way; only a single SessionCreate + call is allowed for each Session (however made). + This call will discard any security information established for the calling process. + In particular, any authorization handles acquired will become invalid, and so will any + keychain related information. We recommend that you call SessionCreate before + making any other security-related calls that establish rights of any kind, to the + extent this is practical. Also, we strongly recommend that you do not perform + security-related calls in any other threads while calling SessionCreate. + + @param flags Flags controlling how the session is created. + + @param attributes The set of attribute bits to set for the new session. + Not all bits can be set this way. + + @result An OSStatus indicating success (noErr) or an error cause. + + errSessionInvalidAttributes -60501 Attempt to set invalid attribute bits + errSessionAuthorizationDenied -60502 Attempt to re-initialize a session + errSessionInvalidFlags -60011 Attempt to specify unsupported flag bits + +*/ +OSStatus SessionCreate(SessionCreationFlags flags, + SessionAttributeBits attributes); + + +#if defined(__cplusplus) +} +#endif + +#endif /* ! __AuthSession__ */ diff --git a/libsecurity_authorization/lib/Authorization.cpp b/libsecurity_authorization/lib/Authorization.cpp new file mode 100644 index 00000000..54915313 --- /dev/null +++ b/libsecurity_authorization/lib/Authorization.cpp @@ -0,0 +1,491 @@ +/* + * 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@ + */ + + +// +// Authorization.cpp +// +// This file is the unified implementation of the Authorization and AuthSession APIs. +// +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +using namespace SecurityServer; +using namespace MachPlusPlus; + + +// +// Shared cached client object +// +class AuthClient : public SecurityServer::ClientSession { +public: + AuthClient() + : SecurityServer::ClientSession(Allocator::standard(), Allocator::standard()) + { } +}; + +static ModuleNexus server; + + +// +// Create an Authorization +// +OSStatus AuthorizationCreate(const AuthorizationRights *rights, + const AuthorizationEnvironment *environment, + AuthorizationFlags flags, + AuthorizationRef *authorization) +{ + BEGIN_API + AuthorizationBlob result; + server().authCreate(rights, environment, flags, result); + if (authorization) + { + *authorization = + (AuthorizationRef) new(server().returnAllocator) AuthorizationBlob(result); + } + else + { + // If no authorizationRef is desired free the one we just created. + server().authRelease(result, flags); + } + END_API(CSSM) +} + + +// +// Free an authorization reference +// +OSStatus AuthorizationFree(AuthorizationRef authorization, AuthorizationFlags flags) +{ + BEGIN_API + AuthorizationBlob *auth = (AuthorizationBlob *)authorization; + server().authRelease(Required(auth, errAuthorizationInvalidRef), flags); + server().returnAllocator.free(auth); + END_API(CSSM) +} + + +// +// Augment and/or interrogate an authorization +// +OSStatus AuthorizationCopyRights(AuthorizationRef authorization, + const AuthorizationRights *rights, + const AuthorizationEnvironment *environment, + AuthorizationFlags flags, + AuthorizationRights **authorizedRights) +{ + BEGIN_API + AuthorizationBlob *auth = (AuthorizationBlob *)authorization; + server().authCopyRights(Required(auth, errAuthorizationInvalidRef), + rights, environment, flags, authorizedRights); + END_API(CSSM) +} + + +// +// Augment and/or interrogate an authorization asynchronously +// +void AuthorizationCopyRightsAsync(AuthorizationRef authorization, + const AuthorizationRights *rights, + const AuthorizationEnvironment *environment, + AuthorizationFlags flags, + AuthorizationAsyncCallback callbackBlock) +{ + __block AuthorizationRights *blockAuthorizedRights = NULL; + + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + OSStatus status = AuthorizationCopyRights(authorization, rights, environment, flags, &blockAuthorizedRights); + callbackBlock(status, blockAuthorizedRights); + }); +} + + +// +// Retrieve side-band information from an authorization +// +OSStatus AuthorizationCopyInfo(AuthorizationRef authorization, + AuthorizationString tag, + AuthorizationItemSet **info) +{ + BEGIN_API + AuthorizationBlob *auth = (AuthorizationBlob *)authorization; + server().authCopyInfo(Required(auth, errAuthorizationInvalidRef), + tag, Required(info)); + END_API(CSSM) +} + + +// +// Externalize and internalize authorizations +// +OSStatus AuthorizationMakeExternalForm(AuthorizationRef authorization, + AuthorizationExternalForm *extForm) +{ + BEGIN_API + AuthorizationBlob *auth = (AuthorizationBlob *)authorization; + server().authExternalize(Required(auth, errAuthorizationInvalidRef), *extForm); + END_API(CSSM) +} + +OSStatus AuthorizationCreateFromExternalForm(const AuthorizationExternalForm *extForm, + AuthorizationRef *authorization) +{ + BEGIN_API + AuthorizationBlob result; + server().authInternalize(*extForm, result); + Required(authorization, errAuthorizationInvalidRef) = + (AuthorizationRef) new(server().returnAllocator) AuthorizationBlob(result); + + END_API(CSSM) +} + + +// +// Free an ItemSet structure returned from an API call. This is a local operation. +// Since we allocate returned ItemSets as compact blobs, this is just a simple +// free() call. +// +OSStatus AuthorizationFreeItemSet(AuthorizationItemSet *set) +{ + BEGIN_API + server().returnAllocator.free(set); + return errAuthorizationSuccess; + END_API(CSSM) +} + + +// +// This no longer talks to securityd; it is a kernel function. +// +OSStatus SessionGetInfo(SecuritySessionId requestedSession, + SecuritySessionId *sessionId, + SessionAttributeBits *attributes) +{ + BEGIN_API + CommonCriteria::AuditInfo session; + if (requestedSession == callerSecuritySession) + session.get(); + else + session.get(requestedSession); + if (sessionId) + *sessionId = session.sessionId(); + if (attributes) + *attributes = session.flags(); + END_API(CSSM) +} + + +// +// Create a new session. +// This no longer talks to securityd; it is a kernel function. +// Securityd will pick up the new session when we next talk to it. +// +OSStatus SessionCreate(SessionCreationFlags flags, + SessionAttributeBits attributes) +{ + BEGIN_API + + // we don't support the session creation flags anymore + if (flags) + Syslog::warning("SessionCreate flags=0x%x unsupported (ignored)", flags); + CommonCriteria::AuditInfo session; + session.create(attributes); + + // retrieve the (new) session id and set it into the process environment + session.get(); + char idString[80]; + snprintf(idString, sizeof(idString), "%x", session.sessionId()); + setenv("SECURITYSESSIONID", idString, 1); + + END_API(CSSM) +} + + +// +// Get and set the distinguished uid (optionally) associated with the session. +// +OSStatus SessionSetDistinguishedUser(SecuritySessionId session, uid_t user) +{ + BEGIN_API + CommonCriteria::AuditInfo session; + session.get(); + session.ai_auid = user; + session.set(); + END_API(CSSM) +} + + +OSStatus SessionGetDistinguishedUser(SecuritySessionId session, uid_t *user) +{ + BEGIN_API + CommonCriteria::AuditInfo session; + session.get(); + Required(user) = session.uid(); + END_API(CSSM) +} + +OSStatus _SessionSetUserPreferences(SecuritySessionId session); + +void SessionUserPreferencesChanged(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo) +{ + _SessionSetUserPreferences(uintptr_t(observer)); +} + +OSStatus _SessionSetUserPreferences(SecuritySessionId session) +{ + BEGIN_API + CFStringRef appleLanguagesStr = CFSTR("AppleLanguages"); + CFStringRef controlTintStr = CFSTR("AppleAquaColorVariant"); + CFStringRef keyboardUIModeStr = CFSTR("AppleKeyboardUIMode"); + CFStringRef textDirectionStr = CFSTR("AppleTextDirection"); + CFStringRef hitoolboxAppIDStr = CFSTR("com.apple.HIToolbox"); + CFNotificationCenterRef center = CFNotificationCenterGetDistributedCenter(); + + CFRef userPrefsDict(CFDictionaryCreateMutable(NULL, 10, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)); + CFRef globalPrefsDict(CFDictionaryCreateMutable(NULL, 10, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)); + + if (!userPrefsDict || !globalPrefsDict) + return errSessionValueNotSet; + + CFRef appleLanguagesArray(static_cast(CFPreferencesCopyAppValue(appleLanguagesStr, kCFPreferencesCurrentApplication))); + if (appleLanguagesArray) + CFDictionarySetValue(globalPrefsDict, appleLanguagesStr, appleLanguagesArray); + + CFRef controlTintNumber(static_cast(CFPreferencesCopyAppValue(controlTintStr, kCFPreferencesCurrentApplication))); + if (controlTintNumber) + CFDictionarySetValue(globalPrefsDict, controlTintStr, controlTintNumber); + + CFRef keyboardUIModeNumber(static_cast(CFPreferencesCopyAppValue(keyboardUIModeStr, kCFPreferencesCurrentApplication))); + if (keyboardUIModeNumber) + CFDictionarySetValue(globalPrefsDict, keyboardUIModeStr, keyboardUIModeNumber); + + CFRef textDirectionNumber(static_cast(CFPreferencesCopyAppValue(textDirectionStr, kCFPreferencesCurrentApplication))); + if (textDirectionNumber) + CFDictionarySetValue(globalPrefsDict, textDirectionStr, textDirectionNumber); + + if (CFDictionaryGetCount(globalPrefsDict) > 0) + CFDictionarySetValue(userPrefsDict, kCFPreferencesAnyApplication, globalPrefsDict); + + CFPreferencesSynchronize(hitoolboxAppIDStr, kCFPreferencesCurrentUser, + kCFPreferencesCurrentHost); + CFRef hitoolboxPrefsDict(static_cast(CFPreferencesCopyMultiple(NULL, hitoolboxAppIDStr, kCFPreferencesCurrentUser, kCFPreferencesCurrentHost))); + if (hitoolboxPrefsDict) { + CFDictionarySetValue(userPrefsDict, hitoolboxAppIDStr, hitoolboxPrefsDict); + CFNotificationCenterPostNotification(center, CFSTR("com.apple.securityagent.InputPrefsChanged"), CFSTR("com.apple.loginwindow"), hitoolboxPrefsDict, true); + } + + CFRef userPrefsData(CFPropertyListCreateXMLData(NULL, userPrefsDict)); + if (!userPrefsData) + return errSessionValueNotSet; + server().setSessionUserPrefs(session, CFDataGetLength(userPrefsData), CFDataGetBytePtr(userPrefsData)); + + END_API(CSSM) +} + +OSStatus SessionSetUserPreferences(SecuritySessionId session) +{ + OSStatus status = _SessionSetUserPreferences(session); + if (noErr == status) { + CFNotificationCenterRef center = CFNotificationCenterGetDistributedCenter(); + // We've succeeded in setting up a static set of prefs, now set up + CFNotificationCenterAddObserver(center, (void*)session, SessionUserPreferencesChanged, CFSTR("com.apple.Carbon.TISNotifySelectedKeyboardInputSourceChanged"), NULL, CFNotificationSuspensionBehaviorDeliverImmediately); + CFNotificationCenterAddObserver(center, (void*)session, SessionUserPreferencesChanged, CFSTR("com.apple.Carbon.TISNotifyEnabledKeyboardInputSourcesChanged"), NULL, CFNotificationSuspensionBehaviorDeliverImmediately); + } + return status; +} + + +// +// Modify Authorization rules +// + +// +// AuthorizationRightGet +// +OSStatus AuthorizationRightGet(const char *rightName, CFDictionaryRef *rightDefinition) +{ + BEGIN_API; + Required(rightName); + CssmDataContainer definition(server().returnAllocator); + + server().authorizationdbGet(rightName, definition, server().returnAllocator); + // convert rightDefinition to dictionary + + if (rightDefinition) + { + CFRef data(CFDataCreate(NULL, static_cast(definition.data()), definition.length())); + if (!data) + CssmError::throwMe(errAuthorizationInternal); + + CFRef rightDict(static_cast(CFPropertyListCreateFromXMLData(NULL, data, kCFPropertyListImmutable, NULL))); + if (!rightDict + || CFGetTypeID(rightDict) != CFDictionaryGetTypeID()) + CssmError::throwMe(errAuthorizationInternal); + + CFRetain(rightDict); + *rightDefinition = rightDict; + } + + END_API(CSSM); +} + +// +// AuthorizationRightSet +// +OSStatus AuthorizationRightSet(AuthorizationRef authRef, + const char *rightName, CFTypeRef rightDefinition, + CFStringRef descriptionKey, CFBundleRef bundle, CFStringRef tableName) +{ + BEGIN_API; + Required(rightName); + AuthorizationBlob *auth = (AuthorizationBlob *)authRef; + + CFRef rightDefinitionDict; + if (rightDefinition && (CFGetTypeID(rightDefinition) == CFStringGetTypeID())) + { + rightDefinitionDict = CFDictionaryCreateMutable(NULL, 10, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + if (!rightDefinitionDict) + CssmError::throwMe(errAuthorizationInternal); + CFDictionarySetValue(rightDefinitionDict, CFSTR(kAuthorizationRightRule), rightDefinition); + } + else + if (rightDefinition && (CFGetTypeID(rightDefinition) == CFDictionaryGetTypeID())) + { + rightDefinitionDict = CFDictionaryCreateMutableCopy(NULL, 0, static_cast(rightDefinition)); + if (!rightDefinitionDict) + CssmError::throwMe(errAuthorizationInternal); + } + else + CssmError::throwMe(errAuthorizationDenied); + + if (rightDefinitionDict) + CFRelease(rightDefinitionDict); // we just assigned things that were already retained + + if (descriptionKey) + { + CFRef localizedDescriptions(CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)); + + if (!localizedDescriptions) + CssmError::throwMe(errAuthorizationInternal); + + // assigning to perform a retain on either + CFRef clientBundle; clientBundle = bundle ? bundle : CFBundleGetMainBundle(); + + // looks like a list of CFStrings: English us_en etc. + CFRef localizations(CFBundleCopyBundleLocalizations(clientBundle)); + + if (localizations) + { + // for every CFString in localizations do + CFIndex locIndex, allLocs = CFArrayGetCount(localizations); + for (locIndex = 0; locIndex < allLocs; locIndex++) + { + CFStringRef oneLocalization = static_cast(CFArrayGetValueAtIndex(localizations, locIndex)); + + if (!oneLocalization) + continue; + + // @@@ no way to get "Localized" and "strings" as constants? + CFRef locURL(CFBundleCopyResourceURLForLocalization(clientBundle, tableName ? tableName : CFSTR("Localizable"), CFSTR("strings"), NULL /*subDirName*/, oneLocalization)); + + if (!locURL) + continue; + + CFDataRef tableData = NULL; + SInt32 errCode; + CFStringRef errStr; + CFPropertyListRef stringTable; + + CFURLCreateDataAndPropertiesFromResource(CFGetAllocator(clientBundle), locURL, &tableData, NULL, NULL, &errCode); + + if (errCode) + { + if (NULL != tableData) { + CFRelease(tableData); + } + continue; + } + + stringTable = CFPropertyListCreateFromXMLData(CFGetAllocator(clientBundle), tableData, kCFPropertyListImmutable, &errStr); + if (errStr != NULL) { + CFRelease(errStr); + errStr = NULL; + } + CFRelease(tableData); + + CFStringRef value = static_cast(CFDictionaryGetValue(static_cast(stringTable), descriptionKey)); + if (value == NULL || CFEqual(value, CFSTR(""))) { + CFRelease(stringTable); + continue; + } else { + // oneLocalization/value into our dictionary + CFDictionarySetValue(localizedDescriptions, oneLocalization, value); + CFRelease(stringTable); + } + } + } + + // add the description as the default localization into the dictionary + CFDictionarySetValue(localizedDescriptions, CFSTR(""), descriptionKey); + + // stuff localization table into rule definition + CFDictionarySetValue(rightDefinitionDict, CFSTR(kAuthorizationRuleParameterDefaultPrompt), localizedDescriptions); + + } + + // serialize cfdictionary with data into rightDefinitionXML + CFRef rightDefinitionXML(CFPropertyListCreateXMLData(NULL, rightDefinitionDict)); + + server().authorizationdbSet(Required(auth), rightName, CFDataGetLength(rightDefinitionXML), CFDataGetBytePtr(rightDefinitionXML)); + + END_API(CSSM); +} + +// +// AuthorizationRightRemove +// +OSStatus AuthorizationRightRemove(AuthorizationRef authRef, const char *rightName) +{ + BEGIN_API; + Required(rightName); + AuthorizationBlob *auth = (AuthorizationBlob *)authRef; + server().authorizationdbRemove(Required(auth), rightName); + END_API(CSSM); +} + diff --git a/libsecurity_authorization/lib/Authorization.h b/libsecurity_authorization/lib/Authorization.h new file mode 100644 index 00000000..fde3207d --- /dev/null +++ b/libsecurity_authorization/lib/Authorization.h @@ -0,0 +1,462 @@ +/* + * 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@ + */ + + +/* + * Authorization.h -- APIs for implementing access control in applications + * and daemons. + */ + +#ifndef _SECURITY_AUTHORIZATION_H_ +#define _SECURITY_AUTHORIZATION_H_ + +#include +#include +#include + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +/*! + @header Authorization + Version 1.0 10/16/2000 + + The Authorization API contains all the APIs that a application or tool that need pre-authorization or need an authorization desision made. + + A typical use cases are a preference panel that would start off calling AuthorizationCreate() (without UI) to get an authorization object. Then call AuthorizationCopyRights() to figure out what is currently allowed. + + If any of the operations that the preference panel wishes to perform are currently not allowed the lock icon in the window would show up in the locked state. Otherwise it would show up unlocked. + + When the user locks the lock AuthorizationFree() is called with the kAuthorizationFlagDestroyRights to destroy any authorization rights that have been aquired. + + When the user unlocks the lock AuthorizationCreate() is called with the kAuthorizationFlagInteractionAllowed and kAuthorizationFlagExtendRights flags to obtain all required rights. The old authorization object can be freed by calling AuthorizationFree() with no flags. + +*/ + + + +/*! + @defined kAuthorizationEmptyEnvironment + Parameter to specify to AuthorizationCreate when no environment is being provided. +*/ +#define kAuthorizationEmptyEnvironment NULL + + +/*! + @enum AuthorizationStatus + Error codes returned by Authorization API. +*/ + +/* + 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. + + errAuthorizationSuccess can't include a string as it's also errSecSuccess in libsecurity_keychain/lib/SecBase.h +*/ + +enum { + errAuthorizationSuccess = 0, + errAuthorizationInvalidSet = -60001, /* The authorization rights are invalid. */ + errAuthorizationInvalidRef = -60002, /* The authorization reference is invalid. */ + errAuthorizationInvalidTag = -60003, /* The authorization tag is invalid. */ + errAuthorizationInvalidPointer = -60004, /* The returned authorization is invalid. */ + errAuthorizationDenied = -60005, /* The authorization was denied. */ + errAuthorizationCanceled = -60006, /* The authorization was cancelled by the user. */ + errAuthorizationInteractionNotAllowed = -60007, /* The authorization was denied since no user interaction was possible. */ + errAuthorizationInternal = -60008, /* Unable to obtain authorization for this operation. */ + errAuthorizationExternalizeNotAllowed = -60009, /* The authorization is not allowed to be converted to an external format. */ + errAuthorizationInternalizeNotAllowed = -60010, /* The authorization is not allowed to be created from an external format. */ + errAuthorizationInvalidFlags = -60011, /* The provided option flag(s) are invalid for this authorization operation. */ + errAuthorizationToolExecuteFailure = -60031, /* The specified program could not be executed. */ + errAuthorizationToolEnvironmentError = -60032, /* An invalid status was returned during execution of a privileged tool. */ + errAuthorizationBadAddress = -60033, /* The requested socket address is invalid (must be 0-1023 inclusive). */ +}; + + +/*! + @enum AuthorizationFlags + Optional flags passed in to serveral Authorization APIs. See the description of AuthorizationCreate, AuthorizationCopyRights and AuthorizationFree for a description of how they affect those calls. +*/ +enum { + kAuthorizationFlagDefaults = 0, + kAuthorizationFlagInteractionAllowed = (1 << 0), + kAuthorizationFlagExtendRights = (1 << 1), + kAuthorizationFlagPartialRights = (1 << 2), + kAuthorizationFlagDestroyRights = (1 << 3), + kAuthorizationFlagPreAuthorize = (1 << 4), + + // private bits (do not use) + kAuthorizationFlagNoData = (1 << 20) +}; + + +/*! + @typedef AuthorizationFlags + Optional flags passed in to AuthorizationCreate. +*/ +typedef UInt32 AuthorizationFlags; + + +/*! + @enum AuthorizationRightFlags + Flags returned in the flags field of ItemSet Items when calling AuthorizationCopyRights(). +*/ +enum { + kAuthorizationFlagCanNotPreAuthorize = (1 << 0) +}; + + +/*! + @typedef AuthorizationRef + Opaque reference to an authorization object. +*/ +typedef const struct AuthorizationOpaqueRef *AuthorizationRef; + + +/*! + @typedef AuthorizationString + A zero terminated string in UTF-8 encoding. +*/ +typedef const char *AuthorizationString; + + +/*! + @struct AuthorizationItem + Each AuthorizationItem describes a single string-named item with optional + parameter value. The value must be contiguous memory of valueLength bytes; + internal structure is defined separately for each name. + + @field name name of the item, as an AuthorizationString. Mandatory. + @field valueLength Number of bytes in parameter value. Must be 0 if no parameter value. + @field value Pointer to the optional parameter value associated with name. + Must be NULL if no parameter value. + @field flags Reserved field. Must be set to 0 on creation. Do not modify after that. +*/ +typedef struct { + AuthorizationString name; + size_t valueLength; + void *value; + UInt32 flags; +} AuthorizationItem; + + +/*! + @struct AuthorizationItemSet + An AuthorizationItemSet structure represents a set of zero or more AuthorizationItems. Since it is a set it should not contain any identical AuthorizationItems. + + @field count Number of items identified by items. + @field items Pointer to an array of items. +*/ +typedef struct { + UInt32 count; + AuthorizationItem *items; +} AuthorizationItemSet; + + + +/*! + @struct AuthorizationExternalForm + An AuthorizationExternalForm structure can hold the externalized form of + an AuthorizationRef. As such, it can be transmitted across IPC channels + to other processes, which can re-internalize it to recover a valid AuthorizationRef + handle. + The data contained in an AuthorizationExternalForm should be considered opaque. + + SECURITY NOTE: Applications should take care to not disclose the AuthorizationExternalForm to + potential attackers since it would authorize rights to them. +*/ +enum { + kAuthorizationExternalFormLength = 32 +}; + +typedef struct { + char bytes[kAuthorizationExternalFormLength]; +} AuthorizationExternalForm; + + + +/*! + @typedef AuthorizationRights + An AuthorizationItemSet representing a set of rights each with an associated argument (value). + Each argument value is as defined for the specific right they belong to. Argument values may not contain pointers as the should be copyable to different address spaces. +*/ +typedef AuthorizationItemSet AuthorizationRights; + + +/*! + @typedef AuthorizationEnvironment + An AuthorizationItemSet representing environmental information of potential use + to authorization decisions. +*/ +typedef AuthorizationItemSet AuthorizationEnvironment; + + +/*! + @function AuthorizationCreate + Create a new autorization object which can be used in other authorization calls. When the authorization is no longer needed AuthorizationFree should be called. + + When the kAuthorizationFlagInteractionAllowed flag is set, user interaction will happen when required. Failing to set this flag will result in this call failing with a errAuthorizationInteractionNotAllowed status when interaction is required. + + Setting the kAuthorizationFlagExtendRights flag will extend the currently available rights. If this flag is set the returned AuthorizationRef will grant all the rights requested when errAuthorizationSuccess is returned. If this flag is not set the operation will almost certainly succeed, but no attempt will be made to make the requested rights availible. + Call AuthorizationCopyRights to figure out which of the requested rights are granted by the returned AuthorizationRef. + + Setting the kAuthorizationFlagPartialRights flag will cause this call to succeed if only some of the requested rights are being granted by the returned AuthorizationRef. Unless this flag is set this API will fail if not all the requested rights could be obtained. + + Setting the kAuthorizationFlagDestroyRights flag will prevent any rights obtained during this call from being preserved after returning from this API (This is most useful when the authorization parameter is NULL and the caller doesn't want to affect the session state in any way). + + Setting the kAuthorizationFlagPreAuthorize flag will pre authorize the requested rights so that at a later time -- by calling AuthorizationMakeExternalForm() follow by AuthorizationCreateFromExternalForm() -- the obtained rights can be used in a different process. Rights that can't be preauthorized will be treated as if they were authorized for the sake of returning an error (in other words if all rights are either authorized or could not be preauthorized this call will still succeed). + The rights which could not be preauthorized are not currently authorized and may fail to authorize when a later call to AuthorizationCopyRights() is made, unless the kAuthorizationFlagExtendRights and kAuthorizationFlagInteractionAllowed flags are set. Even then they might still fail if the user does not supply the correct credentials. + The reason for passing in this flag is to provide correct audit trail information and to avoid unnecessary user interaction. + + @param rights (input/optional) An AuthorizationItemSet containing rights for which authorization is being requested. If none are specified the resulting AuthorizationRef will authorize nothing at all. + @param environment (input/optional) An AuthorizationItemSet containing enviroment state used when making the autorization decision. See the AuthorizationEnvironment type for details. + @param flags (input) options specified by the AuthorizationFlags enum. set all unused bits to zero to allow for future expansion. + @param authorization (output optional) A pointer to an AuthorizationRef to be returned. When the returned AuthorizationRef is no longer needed AuthorizationFree should be called to prevent anyone from using the aquired rights. If NULL is specified no new rights are returned, but the system will attempt to authorize all the requested rights and return the appropriate status. + + @result errAuthorizationSuccess 0 authorization or all requested rights succeeded. + + errAuthorizationDenied -60005 The authorization for one or more of the requested rights was denied. + + errAuthorizationCanceled -60006 The authorization was cancelled by the user. + + errAuthorizationInteractionNotAllowed -60007 The authorization was denied since no interaction with the user was allowed. +*/ +OSStatus AuthorizationCreate(const AuthorizationRights *rights, + const AuthorizationEnvironment *environment, + AuthorizationFlags flags, + AuthorizationRef *authorization); + + +/*! + @function AuthorizationFree + Destroy an AutorizationRef object. If the kAuthorizationFlagDestroyRights flag is passed, + any rights associated with the authorization are lost. Otherwise, only local resources + are released, and the rights may still be available to other clients. + + Setting the kAuthorizationFlagDestroyRights flag will prevent any rights that were obtained by the specified authorization object to be preserved after returning from this API. This effectivaly locks down all potentially shared authorizations. + + @param authorization (input) The authorization object on which this operation is performed. + + @param flags (input) Bit mask of option flags to this call. + + @result errAuthorizationSuccess 0 No error. + + errAuthorizationInvalidRef -60002 The authorization parameter is invalid. +*/ +OSStatus AuthorizationFree(AuthorizationRef authorization, AuthorizationFlags flags); + + +/*! + @function AuthorizationCopyRights + Given a set of rights, return the subset that is currently authorized + by the AuthorizationRef given. + + When the kAuthorizationFlagInteractionAllowed flag is set, user interaction will happen when required. Failing to set this flag will result in this call failing with a errAuthorizationInteractionNotAllowed status when interaction is required. + + Setting the kAuthorizationFlagExtendRights flag will extend the currently available rights. + + Setting the kAuthorizationFlagPartialRights flag will cause this call to succeed if only some of the requested rights are being granted by the returned AuthorizationRef. Unless this flag is set this API will fail if not all the requested rights could be obtained. + + Setting the kAuthorizationFlagDestroyRights flag will prevent any additional rights obtained during this call from being preserved after returning from this API. + + Setting the kAuthorizationFlagPreAuthorize flag will pre authorize the requested rights so that at a later time -- by calling AuthorizationMakeExternalForm() follow by AuthorizationCreateFromExternalForm() -- the obtained rights can be used in a different process. Rights that can't be preauthorized will be treated as if they were authorized for the sake of returning an error (in other words if all rights are either authorized or could not be preauthorized this call will still succeed), and they will be returned in authorizedRights with their kAuthorizationFlagCanNotPreAuthorize bit in the flags field set to 1. + The rights which could not be preauthorized are not currently authorized and may fail to authorize when a later call to AuthorizationCopyRights() is made, unless the kAuthorizationFlagExtendRights and kAuthorizationFlagInteractionAllowed flags are set. Even then they might still fail if the user does not supply the correct credentials. + The reason for passing in this flag is to provide correct audit trail information and to avoid unnecessary user interaction. + + Setting the kAuthorizationFlagPreAuthorize flag will pre authorize the requested rights so that at a later time -- by calling AuthorizationMakeExternalForm() follow by AuthorizationCreateFromExternalForm() -- the obtained rights can be used in a different process. When this flags is specified rights that can't be preauthorized will be returned as if they were authorized with their kAuthorizationFlagCanNotPreAuthorize bit in the flags field set to 1. These rights are not currently authorized and may fail to authorize later unless kAuthorizationFlagExtendRights and kAuthorizationFlagInteractionAllowed flags are set when the actual authorization is done. And even then they might still fail if the user does not supply the correct credentials. + + @param authorization (input) The authorization object on which this operation is performed. + @param rights (input) A rights set (see AuthorizationCreate). + @param environment (input/optional) An AuthorizationItemSet containing enviroment state used when making the autorization decision. See the AuthorizationEnvironment type for details. + @param flags (input) options specified by the AuthorizationFlags enum. set all unused bits to zero to allow for future expansion. + @param authorizedRights (output/optional) A pointer to a newly allocated AuthorizationInfoSet in which the authorized subset of rights are returned (authorizedRights should be deallocated by calling AuthorizationFreeItemSet() when it is no longer needed). If NULL the only information returned is the status. Note that if the kAuthorizationFlagPreAuthorize flag was specified rights that could not be preauthorized are returned in authorizedRights, but their flags contains the kAuthorizationFlagCanNotPreAuthorize bit. + + @result errAuthorizationSuccess 0 No error. + + errAuthorizationInvalidRef -60002 The authorization parameter is invalid. + + errAuthorizationInvalidSet -60001 The rights parameter is invalid. + + errAuthorizationInvalidPointer -60004 The authorizedRights parameter is invalid. +*/ +OSStatus AuthorizationCopyRights(AuthorizationRef authorization, + const AuthorizationRights *rights, + const AuthorizationEnvironment *environment, + AuthorizationFlags flags, + AuthorizationRights **authorizedRights); + + +#ifdef __BLOCKS__ + +/*! + @typedef AuthorizationAsyncCallback + Callback block passed to AuthorizationCopyRightsAsync. + + @param err (output) The result of the AuthorizationCopyRights call. + @param blockAuthorizedRights (output) The authorizedRights from the AuthorizationCopyRights call to be deallocated by calling AuthorizationFreeItemSet() when it is no longer needed. +*/ +typedef void (^AuthorizationAsyncCallback)(OSStatus err, AuthorizationRights *blockAuthorizedRights); + +/*! + @function AuthorizationCopyRightsAsync + An asynchronous version of AuthorizationCopyRights. + + @param callbackBlock (input) The callback block to be called upon completion. +*/ +void AuthorizationCopyRightsAsync(AuthorizationRef authorization, + const AuthorizationRights *rights, + const AuthorizationEnvironment *environment, + AuthorizationFlags flags, + AuthorizationAsyncCallback callbackBlock); + + +#endif /* __BLOCKS__ */ + + +/*! + @function AuthorizationCopyInfo + Returns sideband information (e.g. access credentials) obtained from a call to AuthorizationCreate. The format of this data depends of the tag specified. + + @param authorization (input) The authorization object on which this operation is performed. + @param tag (input/optional) An optional string tag specifing which sideband information should be returned. When NULL is specified all available information is returned. + @param flags (input) options specified by the AuthorizationFlags enum. set all unused bits to zero to allow for future expansion. + @param info (output) A pointer to a newly allocated AuthorizationInfoSet in which the requested sideband infomation is returned (info should be deallocated by calling AuthorizationFreeItemSet() when it is no longer needed). + + @result errAuthorizationSuccess 0 No error. + + errAuthorizationInvalidRef -60002 The authorization parameter is invalid. + + errAuthorizationInvalidTag -60003 The tag parameter is invalid. + + errAuthorizationInvalidPointer -60004 The info parameter is invalid. +*/ +OSStatus AuthorizationCopyInfo(AuthorizationRef authorization, + AuthorizationString tag, + AuthorizationItemSet **info); + + +/*! + @function AuthorizationMakeExternalForm + Turn an Authorization into an external "byte blob" form so it can be + transmitted to another process. + Note that *storing* the external form somewhere will probably not do what + you want, since authorizations are bounded by sessions, processes, and possibly + time limits. This is for online transmission of authorizations. + + @param authorization The (valid) authorization reference to externalize + @param extForm Pointer to an AuthorizationExternalForm variable to fill. + + @result errAuthorizationSuccess 0 No error. + + errAuthorizationExternalizeNotAllowed -60009 Externalizing this authorization is not allowed. + + errAuthorizationInvalidRef -60002 The authorization parameter is invalid. + + +*/ +OSStatus AuthorizationMakeExternalForm(AuthorizationRef authorization, + AuthorizationExternalForm *extForm); + + +/*! + @function AuthorizationCreateFromExternalForm + Internalize the external "byte blob" form of an authorization reference. + + @param extForm Pointer to an AuthorizationExternalForm value. + @param authorization Will be filled with a valid AuthorizationRef on success. + + @result errAuthorizationInternalizeNotAllowed -60010 Internalizing this authorization is not allowed. +*/ +OSStatus AuthorizationCreateFromExternalForm(const AuthorizationExternalForm *extForm, + AuthorizationRef *authorization); + + +/*! + @function AuthorizationFreeItemSet + Release the memory allocated for an AuthorizationItemSet that was allocated + by an API call. + + @param set The AuthorizationItemSet to deallocate. + + @result errAuthorizationSuccess 0 No error. + + errAuthorizationInvalidSet -60001 The set parameter is invalid. +*/ +OSStatus AuthorizationFreeItemSet(AuthorizationItemSet *set); + + +/*! + @function AuthorizationExecuteWithPrivileges + Run an executable tool with enhanced privileges after passing + suitable authorization procedures. + + @param authorization An authorization reference that is used to authorize + access to the enhanced privileges. It is also passed to the tool for + further access control. + @param pathToTool Full pathname to the tool that should be executed + with enhanced privileges. + @param options Option bits (reserved). Must be zero. + @param arguments An argv-style vector of strings to be passed to the tool. + @param communicationsPipe Assigned a UNIX stdio FILE pointer for + a bidirectional pipe to communicate with the tool. The tool will have + this pipe as its standard I/O channels (stdin/stdout). If NULL, do not + establish a communications pipe. + + @discussion This function has been deprecated and should no longer be used. + Use a launchd-launched helper tool and/or the Service Mangement framework + for this functionality. + */ +OSStatus AuthorizationExecuteWithPrivileges(AuthorizationRef authorization, + const char *pathToTool, + AuthorizationFlags options, + char * const *arguments, + FILE **communicationsPipe) __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_1,__MAC_10_7,__IPHONE_NA,__IPHONE_NA); + + +/*! + @function AuthorizationCopyPrivilegedReference + From within a tool launched via the AuthorizationExecuteWithPrivileges function + ONLY, retrieve the AuthorizationRef originally passed to that function. + While AuthorizationExecuteWithPrivileges already verified the authorization to + launch your tool, the tool may want to avail itself of any additional pre-authorizations + the caller may have obtained through that reference. + + @discussion This function has been deprecated and should no longer be used. + Use a launchd-launched helper tool and/or the Service Mangement framework + for this functionality. + */ +OSStatus AuthorizationCopyPrivilegedReference(AuthorizationRef *authorization, + AuthorizationFlags flags) __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_1,__MAC_10_7,__IPHONE_NA,__IPHONE_NA); + + +#if defined(__cplusplus) +} +#endif + +#endif /* !_SECURITY_AUTHORIZATION_H_ */ diff --git a/libsecurity_authorization/lib/AuthorizationDB.h b/libsecurity_authorization/lib/AuthorizationDB.h new file mode 100644 index 00000000..326f870d --- /dev/null +++ b/libsecurity_authorization/lib/AuthorizationDB.h @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2003 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@ + */ + +/* + * AuthorizationDB.h -- APIs for managing the authorization policy database + * and daemons. + */ + +#ifndef _SECURITY_AUTHORIZATIONDB_H_ +#define _SECURITY_AUTHORIZATIONDB_H_ + +#include +#include + +#if defined(__cplusplus) +extern "C" { +#endif + +/*! + @header AuthorizationDB + Version 1.0 + + This API allows for any programs to get, modify, delete and add new right definitions to the policy database. Meta-rights specify whether and what authorization is required to make these modifications. + + AuthorizationRightSet(authRef, "com.ifoo.ifax.send", CFSTR(kRuleIsAdmin), CFSTR("You must authenticate to send a fax."), NULL, NULL) + + add a rule for letting admins send faxes using a canned rule, delegating to a pre-specified rule that authorizes everyone who is an admin. + + AuthorizationRightSet(authRef, "com.ifoo.ifax.send", [[CFSTR(kRightRule), CFSTR(kRuleIsAdmin)], [CFSTR(kRightComment), CFSTR("authorizes sending of 1 fax message")]], CFSTR("Authorize sending of a fax"), NULL, NULL) + + add identical rule, but specify additional attributes this time. + + Keep in mind while specifying a comment to be specific about what you need to authorize for (1 fax), in terms of a general message for user. The means of proof required for kRuleIsAdmin (enter username/password for example) should not be included here, since it could be configured differently. Also note that the "authRef" variable used in each of the above examples must be a vaild AuthorizationRef obtained from AuthorizationCreate(). + +*/ + +/*! @define kRightRule + rule delegation key. Instead of specifying exact behavior some canned rules + are shipped that may be switched by configurable security. +*/ +#define kAuthorizationRightRule "rule" + +/*! @defined kRuleIsAdmin + canned rule values for use with rule delegation definitions: require user to be an admin. +*/ +#define kAuthorizationRuleIsAdmin "is-admin" + +/*! @defined kRuleAuthenticateAsSessionUser + canned rule value for use with rule delegation definitions: require user to authenticate as the session owner (logged-in user). +*/ +#define kAuthorizationRuleAuthenticateAsSessionUser "authenticate-session-owner" + +/*! @defined kRuleAuthenticateAsAdmin + Canned rule value for use with rule delegation definitions: require user to authenticate as admin. +*/ +#define kAuthorizationRuleAuthenticateAsAdmin "authenticate-admin" + +/*! @defined kAuthorizationRuleClassAllow + Class that allows anything. +*/ +#define kAuthorizationRuleClassAllow "allow" + +/*! @defined kAuthorizationRuleClassDeny + Class that denies anything. +*/ +#define kAuthorizationRuleClassDeny "deny" + +/*! @defined kAuthorizationComment + comments for the administrator on what is being customized here; + as opposed to (localized) descriptions presented to the user. +*/ +#define kAuthorizationComment "comment" + + + +/*! + @function AuthorizationRightGet + + Retrieves a right definition as a dictionary. There are no restrictions to keep anyone from retrieving these definitions. + + @param rightName (input) the rightname (ASCII). Wildcard rightname definitions are okay. + @param rightDefinition (output/optional) the dictionary with all keys defining the right. See documented keys. Passing in NULL will just check if there is a definition. The caller is responsible for releasing the returned dictionary. + + @result errAuthorizationSuccess 0 No error. + + errAuthorizationDenied -60005 No definition found. + +*/ +OSStatus AuthorizationRightGet(const char *rightName, + CFDictionaryRef *rightDefinition); + +/*! + @function AuthorizationRightSet + + Create or update a right entry. Only normal rights can be registered (wildcard rights are denied); wildcard rights are considered to be put in by an administrator putting together a site configuration. + + @param authRef (input) authRef to authorize modifications. + @param rightName (input) the rightname (ASCII). Wildcard rightnames are not okay. + @param rightDefinition (input) a CFString of the name of a rule to use (delegate) or CFDictionary containing keys defining one. + @param descriptionKey (input/optional) a CFString to use as a key for looking up localized descriptions. If no localization is found this will be the description itself. + @param bundle (input/optional) a bundle to get localizations from if not the main bundle. + @param localeTableName (input/optional) stringtable name to get localizations from. + + @result errAuthorizationSuccess 0 added right definition successfully. + + errAuthorizationDenied -60005 Unable to create or update right definition. + + errAuthorizationCanceled -60006 Authorization was canceled by user. + + errAuthorizationInteractionNotAllowed -60007 Interaction was required but not possible. + +*/ +OSStatus AuthorizationRightSet(AuthorizationRef authRef, + const char *rightName, + CFTypeRef rightDefinition, + CFStringRef descriptionKey, + CFBundleRef bundle, + CFStringRef localeTableName); + + + +/*! + @function AuthorizationRightRemove + + Request to remove a right from the policy database. + + @param authRef (input) authRef, to be used to authorize this action. + @param rightName (input) the rightname (ASCII). Wildcard rightnames are not okay. + +*/ +OSStatus AuthorizationRightRemove(AuthorizationRef authRef, + const char *rightName); + + +#if defined(__cplusplus) +} +#endif + +#endif /* !_SECURITY_AUTHORIZATIONDB_H_ */ + diff --git a/libsecurity_authorization/lib/AuthorizationPlugin.h b/libsecurity_authorization/lib/AuthorizationPlugin.h new file mode 100644 index 00000000..46ed15e2 --- /dev/null +++ b/libsecurity_authorization/lib/AuthorizationPlugin.h @@ -0,0 +1,309 @@ +/* + * Copyright (c) 2001-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@ + */ + + +/* + * AuthorizationPlugin.h + * AuthorizationPlugin -- APIs for implementing authorization plugins. + */ + +#ifndef _SECURITY_AUTHORIZATIONPLUGIN_H_ +#define _SECURITY_AUTHORIZATIONPLUGIN_H_ + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +/*! + @header AuthorizationPlugin + + The AuthorizationPlugin API allows the creation of plugins that can participate + in authorization decisions. Using the AuthorizationDB API the system can be configured + to use these plugins. Plugins are loaded into a separate process, the pluginhost, to + isolate the process of authorization from the client. There are two types of pluginhosts. + One runs as an anonymous user and can be used to communicate with the user, for example + to ask for a password. Another one runs with root privileges to perform privileged + operations that may be required. + + A typical use is to implement additional policies that cannot be expressed in the + authorization configuration. + + Plugins implement a handshake function called AuthorizationPluginCreate with which + their interface (AuthorizationPluginInterface) and the engine's interface + (AuthorizationCallbacks) are exchanged. Plugins are asked to create + Mechanisms, which are the basic element as authorizations are performed. + + Mechanisms are invoked when it is time for them to make a decision. A decision is + made by setting a single result (AuthorizationResult). Mechanisms in the + authorization can communicate auxiliary information by setting and/or getting hints + and setting and/or getting context data. Hints are advisory and don't need to be + looked at, nor are they preserved as part of the authorization result. Context data + becomes part of the result of the authorization. + + Context data is tagged with a flag that describes whether the information is returned + to the authorization client upon request (AuthorizationCopyInfo() in Authorization.h) + or whether it's private to the mechanisms making a decision. + +*/ + + +/*! + @typedef AuthorizationValue + Auxiliary data is passed between the engine and the mechanism as AuthorizationValues +*/ +typedef struct AuthorizationValue +{ + size_t length; + void *data; +} AuthorizationValue; + +/*! + @typedef AuthorizationValueVector + A vector of AuthorizationValues. Used to communicate arguments passed from the + configuration file authorization(5). +*/ +typedef struct AuthorizationValueVector +{ + UInt32 count; + AuthorizationValue *values; +} AuthorizationValueVector; + +/*! + @typedef + Data produced as context during the authorization evaluation is tagged. + If data is set to be extractable (kAuthorizationContextFlagExtractable), it will be possible for the client of authorization to obtain the value of this attribute using AuthorizationCopyInfo(). + If data is marked as volatile (kAuthorizationContextFlagVolatile), this value will not be remembered in the AuthorizationRef. + Sticky data (kAuthorizationContextFlagSticky) persists through a failed or interrupted evaluation. It can be used to propagate an error condition from a downstream plugin to an upstream one. It is not remembered in the AuthorizationRef. +*/ +typedef UInt32 AuthorizationContextFlags; +enum +{ + kAuthorizationContextFlagExtractable = (1 << 0), + kAuthorizationContextFlagVolatile = (1 << 1), + kAuthorizationContextFlagSticky = (1 << 2) +}; + + +/*! + @typedef AuthorizationMechanismId + The mechanism id specified in the configuration is passed to the plugin to create the appropriate mechanism. +*/ +typedef const AuthorizationString AuthorizationMechanismId; + +/*! + @typedef AuthorizationPluginId + Not used by plugin writers. Loaded plugins are identified by their name. + */ +typedef const AuthorizationString AuthorizationPluginId; + +/*! + @typedef AuthorizationPluginRef + Handle passed back by the plugin writer when creating a plugin. Any pluginhost will only instantiate one instance. The handle is used when creating mechanisms. +*/ +typedef void *AuthorizationPluginRef; + +/*! + @typedef AuthorizationMechanismRef + Handle passed back by the plugin writer when creating an an instance of a mechanism in a plugin. One instance will be created for any authorization. +*/ +typedef void *AuthorizationMechanismRef; + +/*! + @typedef AuthorizationEngineRef + Handle passed from the engine to an instance of a mechanism in a plugin (corresponds to a particular AuthorizationMechanismRef). +*/ +typedef struct __OpaqueAuthorizationEngine *AuthorizationEngineRef; + +/*! + @typedef AuthorizationSessionId + A unique value for an AuthorizationSession being evaluated, provided by the authorization engine. + A session is represented by a top level call to an Authorization API. +*/ +typedef void *AuthorizationSessionId; + +/*! + @typedef AuthorizationResult + Type for SetResult(). See AuthorizationResultConstants for all allowed values. +*/ +typedef UInt32 AuthorizationResult; + +/*! + @enum AuthorizationResultConstants + Possible values for SetResult() in AuthorizationCallbacks. + + @constant kAuthorizationResultAllow the operation succeeded and authorization should be granted as far as this mechanism is concerned. + @constant kAuthorizationResultDeny the operation succeeded but authorization should be denied as far as this mechanism is concerned. + @constant kAuthorizationResultUndefined the operation failed for some reason and should not be retried for this session. + @constant kAuthorizationResultUserCanceled the user has requested that the evaluation be terminated. +*/ +enum { + kAuthorizationResultAllow, + kAuthorizationResultDeny, + kAuthorizationResultUndefined, + kAuthorizationResultUserCanceled, +}; + +/*! + @enum + Version of the interface (AuthorizationPluginInterface) implemented by the plugin. + The value is matched to the definition in this file. +*/ +enum { + kAuthorizationPluginInterfaceVersion = 0 +}; + +/*! + @enum + Version of the callback structure (AuthorizationCallbacks) passed to the plugin. + The value is matched to the definition in this file. The engine may provide a newer + interface. +*/ +enum { + kAuthorizationCallbacksVersion = 0 +}; + + +/*! + @struct + Callback API provided by the AuthorizationEngine. + + @field version Engine callback version. + @field SetResult Set a result after a call to AuthorizationSessionInvoke. + @field RequestInterrupt Request authorization engine to interrupt all mechamisms invoked after this mechamism has called SessionSetResult and then call AuthorizationSessionInvoke again. + @field DidDeactivate Respond to the Deactivate request. + @field GetContextValue Read value from context. AuthorizationValue does not own data. + @field SetContextValue Write value to context. AuthorizationValue and data are copied. + @field GetHintValue Read value from hints. AuthorizationValue does not own data. + @field SetHintValue Write value to hints. AuthorizationValue and data are copied. + @field GetArguments Read arguments passed. AuthorizationValueVector does not own data. + @field GetSessionId Read SessionId. +*/ +typedef struct AuthorizationCallbacks { + + /* Engine callback version. */ + UInt32 version; + + /* Set a result after a call to AuthorizationSessionInvoke. */ + OSStatus (*SetResult)(AuthorizationEngineRef inEngine, AuthorizationResult inResult); + + /* Request authorization engine to interrupt all mechamisms invoked after + this mechamism has called SessionSetResult and then call + AuthorizationSessionInvoke again. */ + OSStatus (*RequestInterrupt)(AuthorizationEngineRef inEngine); + + /* Respond to the Deactivate request. */ + OSStatus (*DidDeactivate)(AuthorizationEngineRef inEngine); + + /* Read value from context. AuthorizationValue does not own data. */ + OSStatus (*GetContextValue)(AuthorizationEngineRef inEngine, + AuthorizationString inKey, + AuthorizationContextFlags *outContextFlags, + const AuthorizationValue **outValue); + + /* Write value to context. AuthorizationValue and data are copied. */ + OSStatus (*SetContextValue)(AuthorizationEngineRef inEngine, + AuthorizationString inKey, + AuthorizationContextFlags inContextFlags, + const AuthorizationValue *inValue); + + /* Read value from hints. AuthorizationValue does not own data. */ + OSStatus (*GetHintValue)(AuthorizationEngineRef inEngine, + AuthorizationString inKey, + const AuthorizationValue **outValue); + + /* Write value to hints. AuthorizationValue and data are copied. */ + OSStatus (*SetHintValue)(AuthorizationEngineRef inEngine, + AuthorizationString inKey, + const AuthorizationValue *inValue); + + /* Read arguments passed. AuthorizationValueVector does not own data. */ + OSStatus (*GetArguments)(AuthorizationEngineRef inEngine, + const AuthorizationValueVector **outArguments); + + /* Read SessionId. */ + OSStatus (*GetSessionId)(AuthorizationEngineRef inEngine, + AuthorizationSessionId *outSessionId); + +} AuthorizationCallbacks; + + +/*! + @struct + Interface that must be implemented by each plugin. + + @field version Must be set to kAuthorizationPluginInterfaceVersion + @field PluginDestroy Plugin should clean up and release any resources it is holding. + @field MechanismCreate The plugin should create a mechanism named mechanismId. The mechanism needs to use the AuthorizationEngineRef for the callbacks and pass back a AuthorizationMechanismRef for itself. MechanismDestroy will be called when it is no longer needed. + @field MechanismInvoke Invoke an instance of a mechanism. It should call SetResult during or after returning from this function. + @field MechanismDeactivate Mechanism should respond with a DidDeactivate as soon as possible + @field MechanismDestroy Mechanism should clean up and release any resources it is holding +*/ +typedef struct AuthorizationPluginInterface +{ + /* Must be set to kAuthorizationPluginInterfaceVersion. */ + UInt32 version; + + /* Notify a plugin that it is about to be unloaded so it get a chance to clean up and release any resources it is holding. */ + OSStatus (*PluginDestroy)(AuthorizationPluginRef inPlugin); + + /* The plugin should create a mechanism named mechanismId. The mechanism needs to use the + AuthorizationEngineRef for the callbacks and pass back an AuthorizationMechanismRef for + itself. MechanismDestroy will be called when it is no longer needed. */ + OSStatus (*MechanismCreate)(AuthorizationPluginRef inPlugin, + AuthorizationEngineRef inEngine, + AuthorizationMechanismId mechanismId, + AuthorizationMechanismRef *outMechanism); + + /* Invoke an instance of a mechanism. It should call SetResult during or after returning from this function. */ + OSStatus (*MechanismInvoke)(AuthorizationMechanismRef inMechanism); + + /* Mechanism should respond with a DidDeactivate as soon as possible. */ + OSStatus (*MechanismDeactivate)(AuthorizationMechanismRef inMechanism); + + /* Mechanism should clean up and release any resources it is holding. */ + OSStatus (*MechanismDestroy)(AuthorizationMechanismRef inMechanism); + +} AuthorizationPluginInterface; + + +/*! + @function AuthorizationPluginCreate + + Initialize a plugin after it gets loaded. This is the main entry point to a plugin. This function will only be called once. + After all Mechanism instances have been destroyed outPluginInterface->PluginDestroy will be called. + + @param callbacks (input) A pointer to an AuthorizationCallbacks which contains the callbacks implemented by the AuthorizationEngine. + @param outPlugin (output) On successful completion should contain a valid AuthorizationPluginRef. This will be passed in to any subsequent calls the engine makes to outPluginInterface->MechanismCreate and outPluginInterface->PluginDestroy. + @param outPluginInterface (output) On successful completion should contain a pointer to a AuthorizationPluginInterface that will stay valid until outPluginInterface->PluginDestroy is called. */ +OSStatus AuthorizationPluginCreate(const AuthorizationCallbacks *callbacks, + AuthorizationPluginRef *outPlugin, + const AuthorizationPluginInterface **outPluginInterface); + +#if defined(__cplusplus) +} +#endif + +#endif /* _SECURITY_AUTHORIZATIONPLUGIN_H_ */ diff --git a/libsecurity_authorization/lib/AuthorizationPriv.h b/libsecurity_authorization/lib/AuthorizationPriv.h new file mode 100644 index 00000000..596df4a5 --- /dev/null +++ b/libsecurity_authorization/lib/AuthorizationPriv.h @@ -0,0 +1,101 @@ +/* + * 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@ + */ + + +/* + * AuthorizationPriv.h -- Authorization SPIs + * Private APIs for implementing access control in applications and daemons. + * + */ + +#ifndef _SECURITY_AUTHORIZATIONPRIV_H_ +#define _SECURITY_AUTHORIZATIONPRIV_H_ + +#include +#include +#include // uid_t + +#if defined(__cplusplus) +extern "C" { +#endif + + +/*! + @header AuthorizationPriv + Version 1.1 04/2003 + + This header contains private APIs for authorization services. + This is the private extension of , a public header file. +*/ + +/*! + @enum Private (for now) AuthorizationFlags +*/ +enum { + kAuthorizationFlagLeastPrivileged = (1 << 5) +}; + +/*! + @function SessionSetDistinguishedUser + This function allows the creator of a (new) security session to associate an arbitrary + UNIX user identity (uid) with the session. This uid can be retrieved with + SessionGetDistinguishedUser by anyone who knows the session's id, and may also + be used by the system for identification (but not authentication) purposes. + + This call can only be made by the process that created the session, and only + once. + + This is a private API, and is subject to change. + + @param session (input) Session-id for which to set the uid. Can be one of the + special constants defined in AuthSession.h. + @param user (input) The uid to set. + */ +OSStatus SessionSetDistinguishedUser(SecuritySessionId session, uid_t user); + + +/*! + @function SessionGetDistinguishedUser + Retrieves the distinguished uid of a session as set by the session creator + using the SessionSetDistinguishedUser call. + + @param session (input) Session-id for which to set the uid. Can be one of the + special constants defined in AuthSession.h. + @param user (output) Will receive the uid. Unchanged on error. + */ +OSStatus SessionGetDistinguishedUser(SecuritySessionId session, uid_t *user); + +/*! + @function SessionSetUserPreferences + Set preferences from current application context for session (for use during agent interactions). + + @param session (input) Session-id for which to set the user preferences. Can be one of the special constants defined in AuthSession.h. + */ +OSStatus SessionSetUserPreferences(SecuritySessionId session); + + +#if defined(__cplusplus) +} +#endif + +#endif /* !_SECURITY_AUTHORIZATIONPRIV_H_ */ diff --git a/libsecurity_authorization/lib/AuthorizationTags.h b/libsecurity_authorization/lib/AuthorizationTags.h new file mode 100644 index 00000000..22876b79 --- /dev/null +++ b/libsecurity_authorization/lib/AuthorizationTags.h @@ -0,0 +1,80 @@ +/* + * 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@ + */ + + +/* + * AuthorizationTags.h -- Right tags for implementing access control in + * applications and daemons + */ + +#ifndef _SECURITY_AUTHORIZATIONTAGS_H_ +#define _SECURITY_AUTHORIZATIONTAGS_H_ + + +/*! + @header AuthorizationTags + + This header defines some of the supported rights tags to be used in the Authorization API. +*/ + + +/*! + @define kAuthorizationEnvironmentUsername + The name of the AuthorizationItem that should be passed into the environment when specifying a username. The value and valueLength should contain the username itself. +*/ +#define kAuthorizationEnvironmentUsername "username" + +/*! + @define kAuthorizationEnvironmentPassword + The name of the AuthorizationItem that should be passed into the environment when specifying a password for a given username. The value and valueLength should contain the actual password data. +*/ +#define kAuthorizationEnvironmentPassword "password" + +/*! + @define kAuthorizationEnvironmentShared + The name of the AuthorizationItem that should be passed into the environment when specifying a username and password. Adding this entry to the environment will cause the username/password to be added to the shared credential pool of the calling applications session. This means that further calls by other applications in this session will automatically have this credential availible to them. The value is ignored. +*/ +#define kAuthorizationEnvironmentShared "shared" + +/*! + @define kAuthorizationRightExecute + The name of the AuthorizationItem that should be passed into the rights when preauthorizing for a call to AuthorizationExecuteWithPrivileges(). + + You need to aquire this right to be able to perform a AuthorizationExecuteWithPrivileges() operation. In addtion to this right you should obtain whatever rights the tool you are executing with privileges need to perform it's operation on your behalf. Currently no options are supported but you should pass in the full path of the tool you wish to execute in the value and valueLength fields. In the future we will limit the right to only execute the requested path, and we will display this information to the user. +*/ +#define kAuthorizationRightExecute "system.privilege.admin" + +/*! + @define kAuthorizationEnvironmentPrompt + The name of the AuthorizationItem that should be passed into the environment when specifying a invocation specific additional text. The value should be a localized UTF8 string. +*/ +#define kAuthorizationEnvironmentPrompt "prompt" + +/*! + @define kAuthorizationEnvironmentIcon + The name of the AuthorizationItem that should be passed into the environment when specifying an alternate icon to be used. The value should be a full path to and image NSImage can deal with. +*/ +#define kAuthorizationEnvironmentIcon "icon" + + +#endif /* !_SECURITY_AUTHORIZATIONTAGS_H_ */ diff --git a/libsecurity_authorization/lib/AuthorizationTagsPriv.h b/libsecurity_authorization/lib/AuthorizationTagsPriv.h new file mode 100644 index 00000000..9fb80b42 --- /dev/null +++ b/libsecurity_authorization/lib/AuthorizationTagsPriv.h @@ -0,0 +1,299 @@ +/* + * 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@ + */ + + +/* + * AuthorizationTagsPriv.h -- private Authorization tags + * + */ + +#ifndef _SECURITY_AUTHORIZATIONTAGSPRIV_H_ +#define _SECURITY_AUTHORIZATIONTAGSPRIV_H_ + +/*! + @header AuthorizationTagsPriv + Version 1.0 10/2003 + + This header contains private details for authorization services. +*/ + + +/* + * meta-rightname prefixes that configure authorization for policy changes + */ + +/*! + @defined kConfigRightAdd + meta-rightname for prefix adding rights. +*/ +#define kAuthorizationConfigRightAdd "config.add." +/*! + @defined kConfigRightModify + meta-rightname prefix for modifying rights. +*/ +#define kAuthorizationConfigRightModify "config.modify." +/*! + @defined kConfigRightRemove + meta-rightname prefix for removing rights. +*/ +#define kAuthorizationConfigRightRemove "config.remove." +/*! + @defined kConfigRight + meta-rightname prefix. +*/ +#define kConfigRight "config." + +/* + * Other rights + */ + +/*! @defined kAuthorizationRightScreensaver + the right requested to unlock the screen +*/ +#define kAuthorizationRightScreensaver "system.login.screensaver" + +/*! @defined LOGIN_KC_CREATION_RIGHT + the right used to invoke the right mechanisms to (re)create a login + keychain +*/ +#define LOGIN_KC_CREATION_RIGHT "system.keychain.create.loginkc" + +/* + * Miscellaneous rules + */ + +/*! + @defined kRuleIsRoot + canned rule for daemon to daemon convincing (see AuthorizationDB.h for + public ones) +*/ +#define kAuthorizationRuleIsRoot "is-root" + +/* + * Rule classes + */ + +/*! @defined kAuthorizationRuleClass + Specifying rule class +*/ +#define kAuthorizationRuleClass "class" + +/*! @defined kAuthorizationRuleClassUser + Specifying user class +*/ +#define kAuthorizationRuleClassUser "user" + +/*! @defined kAuthorizationRuleClassMechanisms + Specifying evaluate-mechanisms class +*/ +#define kAuthorizationRuleClassMechanisms "evaluate-mechanisms" + +/* + * Rule attributes to specify above classes + */ + +/*! @defined kAuthorizationRuleParameterGroup + string, group specification for user rules. +*/ +#define kAuthorizationRuleParameterGroup "group" + +/*! @defined kAuthorizationRuleParameterKofN + number, k specification for k-of-n +*/ +#define kAuthorizationRuleParameterKofN "k-of-n" + +/*! @defined kAuthorizationRuleParameterRules + rules specification for rule delegation (incl. k-of-n) +*/ +#define kAuthorizationRuleParameterRules "rules" + +/*! @defined kAuthorizationRuleParameterMechanisms + mechanism specification, a sequence of mechanisms to be evaluated +*/ +#define kAuthorizationRuleParameterMechanisms "mechanisms" + +/*! @defined kAuthorizationRightParameterTimeout + Timeout if any when a remembered right expires. + Special values: + - not specified retains previous behavior: most privileged, credential- + based. + - zero grants the right once (can be achieved with zero credential + timeout, needed?) + - all other values are interpreted as number of seconds since granted. +*/ +#define kAuthorizationRightParameterTimeout "timeout-right" + +/*! @defined kAuthorizationRuleParameterCredentialTimeout + Timeout if any for the use of cached credentials when authorizing rights. + - not specified allows for any credentials regardless of age; rights + will be remembered in authorizations, removing a credential does not + stop it from granting this right, specifying a zero timeout for the + right will delegate it back to requiring a credential. + - all other values are interpreted as number of seconds since the + credential was created + - zero only allows for the use of credentials created "now" + (this is deprecated by means of specifying zero for kRightTimeout) +*/ +#define kAuthorizationRuleParameterCredentialTimeout "timeout" + +/*! @defined kAuthorizationRuleParameterCredentialShared + boolean that indicates whether credentials acquired during + authorization are added to the shared pool. +*/ +#define kAuthorizationRuleParameterCredentialShared "shared" + +/*! @defined kAuthorizationRuleParameterAllowRoot + boolean that indicates whether to grant a right purely because the + caller is root +*/ +#define kAuthorizationRuleParameterAllowRoot "allow-root" + +/*! @defined kAuthorizationRuleParameterCredentialSessionOwner + boolean that indicates whether to grant a right based on a valid + session-owner credential +*/ +#define kAuthorizationRuleParameterCredentialSessionOwner "session-owner" + +/*! @defined kAuthorizationRuleParameterDefaultPrompt + dictionary of localization-name and localized prompt pairs +*/ +#define kAuthorizationRuleParameterDefaultPrompt "default-prompt" + +/*! @defined kAuthorizationRuleParameterDefaultButton + dictionary of localization-name and localized button name pairs + */ +#define kAuthorizationRuleParameterDefaultButton "default-button" + +/*! @defined kAuthorizationRuleParameterDescription + string, default description of right. Usually localized versions are + added using the AuthorizationDBSet call (@see AuthorizationDB.h). +*/ +#define kAuthorizationRuleParameterDescription "description" + +/*! @defined kAuthorizationRuleParameterButton + string, name of the default button. Usually localized versions are + added using the AuthorizationDBSet call (@see AuthorizationDB.h). + */ +#define kAuthorizationRuleParameterButton "button" + +/*! @defined kAuthorizationRuleParameterAuthenticateUser + boolean that indicates whether to authenticate the user requesting + authorization +*/ +#define kAuthorizationRuleParameterAuthenticateUser "authenticate-user" + +/*! @defined kAuthorizationRuleParameterExtractPassword + boolean that indicates that the password should be extracted to the context + */ +#define kAuthorizationRuleParameterExtractPassword "extract-password" + +/* + * Hints for internal Authorization use + */ + +/* passed between securityd and agent */ +#define AGENT_HINT_SUGGESTED_USER "suggested-user" +#define AGENT_HINT_SUGGESTED_USER_LONG "suggested-realname" +#define AGENT_HINT_REQUIRE_USER_IN_GROUP "require-user-in-group" +#define AGENT_HINT_CUSTOM_PROMPT "prompt" +#define AGENT_HINT_AUTHORIZE_RIGHT "authorize-right" +#define AGENT_HINT_CLIENT_PID "client-pid" +#define AGENT_HINT_CLIENT_UID "client-uid" +#define AGENT_HINT_CLIENT_VALIDITY "client-signature-validity" +#define AGENT_HINT_CREATOR_PID "creator-pid" +#define AGENT_HINT_CREATOR_AUDIT_TOKEN "creator-audit-token" +#define AGENT_HINT_CLIENT_TYPE "client-type" +#define AGENT_HINT_CLIENT_PATH "client-path" +#define AGENT_HINT_CLIENT_NAME "client-name" +#define AGENT_HINT_TRIES "tries" +#define AGENT_HINT_RETRY_REASON "reason" +#define AGENT_HINT_AUTHORIZE_RULE "authorize-rule" +#define AGENT_HINT_TOKEN_NAME "token-name" + +/* passed by loginwindow to securityd and agent */ +#define AGENT_HINT_IMMEDIATE_LAUNCH "immediate-agent" + +/* keychain panels */ +// ACLowner etc. code identity panel + +// Application Path is needed at this stage for identifying the application +// for which the ACL entry is about to be updated +#define AGENT_HINT_APPLICATION_PATH "application-path" +#define AGENT_HINT_ACL_TAG "acl-tag" +#define AGENT_HINT_GROUPKEY "group-key" +#define AGENT_HINT_ACL_MISMATCH "acl-mismatch" +#define AGENT_HINT_KEYCHAIN_ITEM_NAME "keychain-item-name" +#define AGENT_HINT_KEYCHAIN_PATH "keychain-path" +#define AGENT_HINT_WINDOW_LEVEL "window-level" + +/* Login Keychain Creation hint keys */ +#define AGENT_HINT_ATTR_NAME "loginKCCreate:attributeName" +#define AGENT_HINT_LOGIN_KC_NAME "loginKCCreate:pathName" +#define AGENT_HINT_LOGIN_KC_EXISTS_IN_KC_FOLDER "loginKCCreate:exists" +#define AGENT_HINT_LOGIN_KC_USER_NAME "loginKCCreate:userName" +#define AGENT_HINT_LOGIN_KC_CUST_STR1 "loginKCCreate:customStr1" +#define AGENT_HINT_LOGIN_KC_CUST_STR2 "loginKCCreate:customStr2" +#define AGENT_HINT_LOGIN_KC_USER_HAS_OTHER_KCS_STR "loginKCCreate:moreThanOneKeychainExists" + +/* Keychain synchronization */ +// iDisk keychain blob metainfo dictionary; follows "defaults" naming +#define AGENT_HINT_KCSYNC_DICT "com.apple.keychainsync.dictionary" + +/* + * Context values for specific internal clients + */ + +/* passed from mechanisms to loginwindow */ +#define kAuthorizationEnvironmentTokenSubserviceID "token-subservice-uid" + +// remote home directory specification +#define AGENT_CONTEXT_AFP_DIR "afp_dir" +// home directory (where it's locally mounted) +#define AGENT_CONTEXT_HOME "home" +#define AGENT_CONTEXT_UID "uid" +#define AGENT_CONTEXT_GID "gid" +// kerberos principal; decoded from auth-authority specification +#define AGENT_CONTEXT_KERBEROSPRINCIPAL "kerberos-principal" +// tell loginwindow where we're mounted +// (this should really be equal to our homedirectory according to HOME +#define AGENT_CONTEXT_MOUNTPOINT "mountpoint" + +/* authorization context passed from agent to securityd */ +#define AGENT_USERNAME "username" +#define AGENT_PASSWORD "password" +#define AGENT_CONTEXT_NEW_PASSWORD "new-password" +#define AGENT_CONTEXT_AUTO_LOGIN "auto-login" +#define AGENT_CONTEXT_USER_CONSENT "user-consent" + +#define AGENT_HINT_SHOW_ADD_TO_KEYCHAIN "show-add-to-keychain" +/* can be in hints or context */ +#define AGENT_ADD_TO_KEYCHAIN "add-to-keychain" + +#define AGENT_CONTEXT_AUTHENTICATION_FAILURE "authentication-failure" + +/* keychain panels */ +// ACLowner etc. code identity panel +#define AGENT_CONTEXT_REMEMBER_ACTION "remember-action" +#define AGENT_CONTEXT_ALLOW "allow" + +#endif /* !_SECURITY_AUTHORIZATIONTAGSPRIV_H_ */ diff --git a/libsecurity_authorization/lib/privPort.h b/libsecurity_authorization/lib/privPort.h new file mode 100644 index 00000000..cd98665f --- /dev/null +++ b/libsecurity_authorization/lib/privPort.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2003 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@ + */ + + +// +// privPort.h - shared definitions between port server client and server side +// +#ifndef _H_PRIVPORT +#define _H_PRIVPORT + + + +// +// UNIX domain port name for server connection +// +#define kPrivilegedPortBinder "/var/run/bindprivport" + + +// +// Authorization Rights used +// +#define ACCEPTRIGHT "system.privilege.port.accept" +#define CONNECTRIGHT "system.privilege.port.connect" + + +// +// Structure of a request +// +struct Request { + AuthorizationExternalForm authForm; + struct sockaddr_in requestedName; +}; + +struct Reply { + OSStatus status; +}; + + +#endif //_H_PRIVPORT diff --git a/libsecurity_authorization/lib/security_authorization.exp b/libsecurity_authorization/lib/security_authorization.exp new file mode 100644 index 00000000..8a88e4e7 --- /dev/null +++ b/libsecurity_authorization/lib/security_authorization.exp @@ -0,0 +1,40 @@ +# +# 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@ +# +_AuthorizationCopyInfo +_AuthorizationCopyPrivilegedReference +_AuthorizationCopyRights +_AuthorizationCopyRightsAsync +_AuthorizationCreate +_AuthorizationCreateFromExternalForm +_AuthorizationExecuteWithPrivileges +_AuthorizationFree +_AuthorizationFreeItemSet +_AuthorizationMakeExternalForm +_AuthorizationRightGet +_AuthorizationRightRemove +_AuthorizationRightSet +_SessionCreate +_SessionGetInfo +_SessionSetDistinguishedUser +_SessionGetDistinguishedUser +_SessionSetUserPreferences diff --git a/libsecurity_authorization/lib/trampolineClient.cpp b/libsecurity_authorization/lib/trampolineClient.cpp new file mode 100644 index 00000000..e25befd9 --- /dev/null +++ b/libsecurity_authorization/lib/trampolineClient.cpp @@ -0,0 +1,237 @@ +/* + * 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@ + */ + + +// +// trampolineClient - Authorization trampoline client-side implementation +// +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// +// Where is the trampoline itself? +// +#if !defined(TRAMPOLINE) +# define TRAMPOLINE "/usr/libexec/security_authtrampoline" /* fallback */ +#endif + + +// +// A few names for clarity's sake +// +enum { + READ = 0, // read end of standard UNIX pipe + WRITE = 1 // write end of standard UNIX pipe +}; + + +// +// Local (static) functions +// +static const char **argVector(const char *trampoline, + const char *tool, const char *commFd, + char *const *arguments); + + +// +// The public client API function. +// +OSStatus AuthorizationExecuteWithPrivileges(AuthorizationRef authorization, + const char *pathToTool, + AuthorizationFlags flags, + char *const *arguments, + FILE **communicationsPipe) +{ + // report the caller to the authorities + aslmsg m = asl_new(ASL_TYPE_MSG); + asl_set(m, "com.apple.message.domain", "com.apple.libsecurity_authorization.AuthorizationExecuteWithPrivileges"); + asl_set(m, "com.apple.message.signature", getprogname()); + asl_log(NULL, m, ASL_LEVEL_NOTICE, "AuthorizationExecuteWithPrivileges!"); + asl_free(m); + + // flags are currently reserved + if (flags != 0) + return errAuthorizationInvalidFlags; + + // externalize the authorization + AuthorizationExternalForm extForm; + if (OSStatus err = AuthorizationMakeExternalForm(authorization, &extForm)) + return err; + + // create the mailbox file + FILE *mbox = tmpfile(); + if (!mbox) + return errAuthorizationInternal; + if (fwrite(&extForm, sizeof(extForm), 1, mbox) != 1) { + fclose(mbox); + return errAuthorizationInternal; + } + fflush(mbox); + + // make text representation of the temp-file descriptor + char mboxFdText[20]; + snprintf(mboxFdText, sizeof(mboxFdText), "auth %d", fileno(mbox)); + + // make a notifier pipe + int notify[2]; + if (pipe(notify)) { + fclose(mbox); + return errAuthorizationToolExecuteFailure; + } + + // make the communications pipe if requested + int comm[2]; + if (communicationsPipe && socketpair(AF_UNIX, SOCK_STREAM, 0, comm)) { + close(notify[READ]); close(notify[WRITE]); + fclose(mbox); + return errAuthorizationToolExecuteFailure; + } + + // do the standard forking tango... + int delay = 1; + for (int n = 5;; n--, delay *= 2) { + switch (fork()) { + case -1: // error + if (errno == EAGAIN) { + // potentially recoverable resource shortage + if (n > 0) { + secdebug("authexec", "resource shortage (EAGAIN), delaying %d seconds", delay); + sleep(delay); + continue; + } + } + secdebug("authexec", "fork failed (errno=%d)", errno); + close(notify[READ]); close(notify[WRITE]); + return errAuthorizationToolExecuteFailure; + + default: { // parent + // close foreign side of pipes + close(notify[WRITE]); + if (communicationsPipe) + close(comm[WRITE]); + + // close mailbox file (child has it open now) + fclose(mbox); + + // get status notification from child + OSStatus status; + secdebug("authexec", "parent waiting for status"); + ssize_t rc = read(notify[READ], &status, sizeof(status)); + status = n2h(status); + switch (rc) { + default: // weird result of read: post error + secdebug("authexec", "unexpected read return value %ld", long(rc)); + status = errAuthorizationToolEnvironmentError; + // fall through + case sizeof(status): // read succeeded: child reported an error + secdebug("authexec", "parent received status=%d", (int)status); + close(notify[READ]); + if (communicationsPipe) { close(comm[READ]); close(comm[WRITE]); } + return status; + case 0: // end of file: exec succeeded + close(notify[READ]); + if (communicationsPipe) + *communicationsPipe = fdopen(comm[READ], "r+"); + secdebug("authexec", "parent resumes (no error)"); + return noErr; + } + } + + case 0: // child + // close foreign side of pipes + close(notify[READ]); + if (communicationsPipe) + close(comm[READ]); + + // fd 1 (stdout) holds the notify write end + dup2(notify[WRITE], 1); + close(notify[WRITE]); + + // fd 0 (stdin) holds either the comm-link write-end or /dev/null + if (communicationsPipe) { + dup2(comm[WRITE], 0); + close(comm[WRITE]); + } else { + close(0); + open("/dev/null", O_RDWR); + } + + // where is the trampoline? +#if defined(NDEBUG) + const char *trampoline = TRAMPOLINE; +#else //!NDEBUG + const char *trampoline = getenv("AUTHORIZATIONTRAMPOLINE"); + if (!trampoline) + trampoline = TRAMPOLINE; +#endif //NDEBUG + + // okay, execute the trampoline + secdebug("authexec", "child exec(%s:%s)", + trampoline, pathToTool); + if (const char **argv = argVector(trampoline, pathToTool, mboxFdText, arguments)) + execv(trampoline, (char *const*)argv); + secdebug("authexec", "trampoline exec failed (errno=%d)", errno); + + // execute failed - tell the parent + { + OSStatus error = errAuthorizationToolExecuteFailure; + error = h2n(error); + write(1, &error, sizeof(error)); + _exit(1); + } + } + } +} + + +// +// Build an argv vector +// +static const char **argVector(const char *trampoline, const char *pathToTool, + const char *mboxFdText, char *const *arguments) +{ + int length = 0; + if (arguments) { + for (char *const *p = arguments; *p; p++) + length++; + } + if (const char **args = (const char **)malloc(sizeof(const char *) * (length + 4))) { + args[0] = trampoline; + args[1] = pathToTool; + args[2] = mboxFdText; + if (arguments) + for (int n = 0; arguments[n]; n++) + args[n + 3] = arguments[n]; + args[length + 3] = NULL; + return args; + } + return NULL; +} diff --git a/libsecurity_authorization/lib/trampolineServer.cpp b/libsecurity_authorization/lib/trampolineServer.cpp new file mode 100644 index 00000000..343dab1e --- /dev/null +++ b/libsecurity_authorization/lib/trampolineServer.cpp @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2000-2001 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@ + */ + + +// +// trampolineServer.cpp - tool-side trampoline support functions +// +#include +#include +#include + + +// +// In a tool launched via AuthorizationCopyPrivilegedReference, retrieve a copy +// of the AuthorizationRef that started it all. +// +OSStatus AuthorizationCopyPrivilegedReference(AuthorizationRef *authorization, + AuthorizationFlags flags) +{ + // flags are currently reserved + if (flags != 0) + return errAuthorizationInvalidFlags; + + // retrieve hex form of external form from environment + const char *mboxFdText = getenv("__AUTHORIZATION"); + if (!mboxFdText) + return errAuthorizationInvalidRef; + + // retrieve mailbox file and read external form + AuthorizationExternalForm extForm; + int fd; + if (sscanf(mboxFdText, "auth %d", &fd) != 1) + return errAuthorizationInvalidRef; + if (lseek(fd, 0, SEEK_SET) || + read(fd, &extForm, sizeof(extForm)) != sizeof(extForm)) { + close(fd); + return errAuthorizationInvalidRef; + } + + // internalize the authorization + AuthorizationRef auth; + if (OSStatus error = AuthorizationCreateFromExternalForm(&extForm, &auth)) + return error; + + // well, here you go + *authorization = auth; + return noErr; +} diff --git a/libsecurity_authorization/libsecurity_authorization.xcodeproj/project.pbxproj b/libsecurity_authorization/libsecurity_authorization.xcodeproj/project.pbxproj new file mode 100644 index 00000000..ed32c93d --- /dev/null +++ b/libsecurity_authorization/libsecurity_authorization.xcodeproj/project.pbxproj @@ -0,0 +1,285 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 40BC5D9B053230FA009E6ADA /* Authorization.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2A593D3052E3AC700AF1EE3 /* Authorization.cpp */; }; + 4C481F05058161C400846F0C /* trampolineClient.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C481F03058161C400846F0C /* trampolineClient.cpp */; }; + 4C481F06058161C400846F0C /* trampolineServer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C481F04058161C400846F0C /* trampolineServer.cpp */; }; + 4CF36FB3058138F800834D11 /* AuthorizationTags.h in Headers */ = {isa = PBXBuildFile; fileRef = 40BC5D9605322F76009E6ADA /* AuthorizationTags.h */; settings = {ATTRIBUTES = (); }; }; + 4CF36FB4058138F800834D11 /* AuthSession.h in Headers */ = {isa = PBXBuildFile; fileRef = 40BC5D9805322F76009E6ADA /* AuthSession.h */; settings = {ATTRIBUTES = (); }; }; + 4CF36FB5058138F800834D11 /* Authorization.h in Headers */ = {isa = PBXBuildFile; fileRef = 40BC5D9005322F76009E6ADA /* Authorization.h */; settings = {ATTRIBUTES = (); }; }; + 4CF36FB6058138F800834D11 /* AuthorizationDB.h in Headers */ = {isa = PBXBuildFile; fileRef = 40BC5D9305322F76009E6ADA /* AuthorizationDB.h */; settings = {ATTRIBUTES = (); }; }; + 4CF36FB70581390400834D11 /* AuthorizationPlugin.h in Headers */ = {isa = PBXBuildFile; fileRef = 40BC5D9405322F76009E6ADA /* AuthorizationPlugin.h */; settings = {ATTRIBUTES = (); }; }; + 4CF36FB80581390400834D11 /* AuthorizationTagsPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 40C767090534CCDB008AC043 /* AuthorizationTagsPriv.h */; settings = {ATTRIBUTES = (); }; }; + 4CF36FB90581390400834D11 /* AuthorizationPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 40BC5D9505322F76009E6ADA /* AuthorizationPriv.h */; settings = {ATTRIBUTES = (); }; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 182BB336146F100D000BF1F3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 18446158146E92F800B12992 /* libsecurity_utilities.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = C2C9C69D0CECBE8400B3FE07; + remoteInfo = libsecurity_utilitiesDTrace; + }; + 1844615D146E92F900B12992 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 18446158146E92F800B12992 /* libsecurity_utilities.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 4CA2A53A0523D32800978A7B; + remoteInfo = libsecurity_utilities; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 18446154146E928E00B12992 /* base.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = base.xcconfig; sourceTree = ""; }; + 18446155146E928E00B12992 /* debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = debug.xcconfig; sourceTree = ""; }; + 18446156146E928E00B12992 /* lib.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = lib.xcconfig; sourceTree = ""; }; + 18446157146E928E00B12992 /* release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = release.xcconfig; sourceTree = ""; }; + 18446158146E92F800B12992 /* libsecurity_utilities.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libsecurity_utilities.xcodeproj; path = ../libsecurity_utilities/libsecurity_utilities.xcodeproj; sourceTree = ""; }; + 40BC5D9005322F76009E6ADA /* Authorization.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = Authorization.h; path = lib/Authorization.h; sourceTree = ""; }; + 40BC5D9305322F76009E6ADA /* AuthorizationDB.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = AuthorizationDB.h; path = lib/AuthorizationDB.h; sourceTree = ""; }; + 40BC5D9405322F76009E6ADA /* AuthorizationPlugin.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = AuthorizationPlugin.h; path = lib/AuthorizationPlugin.h; sourceTree = ""; }; + 40BC5D9505322F76009E6ADA /* AuthorizationPriv.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = AuthorizationPriv.h; path = lib/AuthorizationPriv.h; sourceTree = ""; }; + 40BC5D9605322F76009E6ADA /* AuthorizationTags.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = AuthorizationTags.h; path = lib/AuthorizationTags.h; sourceTree = ""; }; + 40BC5D9805322F76009E6ADA /* AuthSession.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = AuthSession.h; path = lib/AuthSession.h; sourceTree = ""; }; + 40C767090534CCDB008AC043 /* AuthorizationTagsPriv.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = AuthorizationTagsPriv.h; path = lib/AuthorizationTagsPriv.h; sourceTree = ""; }; + 4C481F03058161C400846F0C /* trampolineClient.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = trampolineClient.cpp; path = lib/trampolineClient.cpp; sourceTree = ""; }; + 4C481F04058161C400846F0C /* trampolineServer.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = trampolineServer.cpp; path = lib/trampolineServer.cpp; sourceTree = ""; }; + 4C6848A005815EE4003AC7B2 /* privPort.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = privPort.h; path = lib/privPort.h; sourceTree = ""; }; + 4CA1FEBE052A3C8100F22E42 /* libsecurity_authorization.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libsecurity_authorization.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 4CCB0023058005D500981D43 /* security_authorization.exp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.exports; name = security_authorization.exp; path = lib/security_authorization.exp; sourceTree = ""; }; + C2A593D3052E3AC700AF1EE3 /* Authorization.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Authorization.cpp; path = lib/Authorization.cpp; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 4CA1FEBB052A3C8100F22E42 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 18446153146E928E00B12992 /* config */ = { + isa = PBXGroup; + children = ( + 18446154146E928E00B12992 /* base.xcconfig */, + 18446155146E928E00B12992 /* debug.xcconfig */, + 18446156146E928E00B12992 /* lib.xcconfig */, + 18446157146E928E00B12992 /* release.xcconfig */, + ); + name = config; + path = ../config; + sourceTree = ""; + }; + 18446159146E92F800B12992 /* Products */ = { + isa = PBXGroup; + children = ( + 1844615E146E92F900B12992 /* libsecurity_utilities.a */, + ); + name = Products; + sourceTree = ""; + }; + 4CA1FEA7052A3C3800F22E42 = { + isa = PBXGroup; + children = ( + 18446158146E92F800B12992 /* libsecurity_utilities.xcodeproj */, + C2A593CE052E3A8400AF1EE3 /* lib */, + 18446153146E928E00B12992 /* config */, + 4CA1FEBF052A3C8100F22E42 /* Products */, + ); + sourceTree = ""; + }; + 4CA1FEBF052A3C8100F22E42 /* Products */ = { + isa = PBXGroup; + children = ( + 4CA1FEBE052A3C8100F22E42 /* libsecurity_authorization.a */, + ); + name = Products; + sourceTree = ""; + }; + C2A593CE052E3A8400AF1EE3 /* lib */ = { + isa = PBXGroup; + children = ( + 40C767090534CCDB008AC043 /* AuthorizationTagsPriv.h */, + 40BC5D9005322F76009E6ADA /* Authorization.h */, + 40BC5D9305322F76009E6ADA /* AuthorizationDB.h */, + 40BC5D9505322F76009E6ADA /* AuthorizationPriv.h */, + 40BC5D9805322F76009E6ADA /* AuthSession.h */, + 40BC5D9605322F76009E6ADA /* AuthorizationTags.h */, + C2A593D3052E3AC700AF1EE3 /* Authorization.cpp */, + 40BC5D9405322F76009E6ADA /* AuthorizationPlugin.h */, + 4C6848A005815EE4003AC7B2 /* privPort.h */, + 4CCB0023058005D500981D43 /* security_authorization.exp */, + 4C481F03058161C400846F0C /* trampolineClient.cpp */, + 4C481F04058161C400846F0C /* trampolineServer.cpp */, + ); + name = lib; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 4CA1FEB9052A3C8100F22E42 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 4CF36FB3058138F800834D11 /* AuthorizationTags.h in Headers */, + 4CF36FB4058138F800834D11 /* AuthSession.h in Headers */, + 4CF36FB80581390400834D11 /* AuthorizationTagsPriv.h in Headers */, + 4CF36FB90581390400834D11 /* AuthorizationPriv.h in Headers */, + 4CF36FB5058138F800834D11 /* Authorization.h in Headers */, + 4CF36FB6058138F800834D11 /* AuthorizationDB.h in Headers */, + 4CF36FB70581390400834D11 /* AuthorizationPlugin.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 4CA1FEBD052A3C8100F22E42 /* libsecurity_authorization */ = { + isa = PBXNativeTarget; + buildConfigurationList = C27AD2B30987FCDD001272E0 /* Build configuration list for PBXNativeTarget "libsecurity_authorization" */; + buildPhases = ( + 4CA1FEB9052A3C8100F22E42 /* Headers */, + 4CA1FEBA052A3C8100F22E42 /* Sources */, + 4CA1FEBB052A3C8100F22E42 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + 182BB337146F100D000BF1F3 /* PBXTargetDependency */, + ); + name = libsecurity_authorization; + productInstallPath = /usr/local/lib; + productName = libsecurityd; + productReference = 4CA1FEBE052A3C8100F22E42 /* libsecurity_authorization.a */; + productType = "com.apple.product-type.library.static"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 4CA1FEAB052A3C3800F22E42 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0420; + }; + buildConfigurationList = C27AD2B70987FCDD001272E0 /* Build configuration list for PBXProject "libsecurity_authorization" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 1; + knownRegions = ( + English, + Japanese, + French, + German, + ); + mainGroup = 4CA1FEA7052A3C3800F22E42; + productRefGroup = 4CA1FEBF052A3C8100F22E42 /* Products */; + projectDirPath = ""; + projectReferences = ( + { + ProductGroup = 18446159146E92F800B12992 /* Products */; + ProjectRef = 18446158146E92F800B12992 /* libsecurity_utilities.xcodeproj */; + }, + ); + projectRoot = ""; + targets = ( + 4CA1FEBD052A3C8100F22E42 /* libsecurity_authorization */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXReferenceProxy section */ + 1844615E146E92F900B12992 /* libsecurity_utilities.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libsecurity_utilities.a; + remoteRef = 1844615D146E92F900B12992 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; +/* End PBXReferenceProxy section */ + +/* Begin PBXSourcesBuildPhase section */ + 4CA1FEBA052A3C8100F22E42 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 40BC5D9B053230FA009E6ADA /* Authorization.cpp in Sources */, + 4C481F05058161C400846F0C /* trampolineClient.cpp in Sources */, + 4C481F06058161C400846F0C /* trampolineServer.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 182BB337146F100D000BF1F3 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = libsecurity_utilitiesDTrace; + targetProxy = 182BB336146F100D000BF1F3 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + C27AD2B40987FCDD001272E0 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 18446155146E928E00B12992 /* debug.xcconfig */; + buildSettings = { + }; + name = Debug; + }; + C27AD2B60987FCDD001272E0 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 18446157146E928E00B12992 /* release.xcconfig */; + buildSettings = { + }; + name = Release; + }; + C27AD2B80987FCDD001272E0 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 18446156146E928E00B12992 /* lib.xcconfig */; + buildSettings = { + }; + name = Debug; + }; + C27AD2BA0987FCDD001272E0 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 18446156146E928E00B12992 /* lib.xcconfig */; + buildSettings = { + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + C27AD2B30987FCDD001272E0 /* Build configuration list for PBXNativeTarget "libsecurity_authorization" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C27AD2B40987FCDD001272E0 /* Debug */, + C27AD2B60987FCDD001272E0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C27AD2B70987FCDD001272E0 /* Build configuration list for PBXProject "libsecurity_authorization" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C27AD2B80987FCDD001272E0 /* Debug */, + C27AD2BA0987FCDD001272E0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 4CA1FEAB052A3C3800F22E42 /* Project object */; +} diff --git a/libsecurity_cdsa_client/Info-security_cdsa_client.plist b/libsecurity_cdsa_client/Info-security_cdsa_client.plist new file mode 100644 index 00000000..0c67376e --- /dev/null +++ b/libsecurity_cdsa_client/Info-security_cdsa_client.plist @@ -0,0 +1,5 @@ + + + + + diff --git a/libsecurity_cdsa_client/lib/DLDBList.cpp b/libsecurity_cdsa_client/lib/DLDBList.cpp new file mode 100644 index 00000000..1deb70d9 --- /dev/null +++ b/libsecurity_cdsa_client/lib/DLDBList.cpp @@ -0,0 +1,53 @@ +/* + * 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. + */ + + +/* + DLDbList.cpp +*/ + +#include "DLDBList.h" + +using namespace CssmClient; + +//---------------------------------------------------------------------- +// DLDbList implementation +//---------------------------------------------------------------------- + +void DLDbList::add(const DLDbIdentifier& dldbIdentifier) // Adds at end if not in list +{ + for (DLDbList::const_iterator ix=begin();ix!=end();ix++) + if (*ix==dldbIdentifier) // already in list + return; + push_back(dldbIdentifier); + changed(true); +} + +void DLDbList::remove(const DLDbIdentifier& dldbIdentifier) // Removes from list +{ + for (DLDbList::iterator ix=begin();ix!=end();ix++) + if (*ix==dldbIdentifier) // found in list + { + erase(ix); + changed(true); + break; + } +} + +void DLDbList::save() +{ +} diff --git a/libsecurity_cdsa_client/lib/DLDBList.h b/libsecurity_cdsa_client/lib/DLDBList.h new file mode 100644 index 00000000..ffca3e2a --- /dev/null +++ b/libsecurity_cdsa_client/lib/DLDBList.h @@ -0,0 +1,74 @@ +/* + * 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. + */ + + +/* + DLDbList.h + + This implements a vector of DLDbIdentifiers. A DLDbIdentifier contains all of the + information needed to find a particular DB within a particular DL. This file + does not depend on CoreFoundation but does depend on CDSA headers. +*/ + +#ifndef _H_CDSA_CLIENT_DLDBLIST +#define _H_CDSA_CLIENT_DLDBLIST 1 + +#include +#include +#include + +namespace Security +{ + +namespace CssmClient +{ + +//------------------------------------------------------------------------------------- +// +// Lists of DL/DBs +// +//------------------------------------------------------------------------------------- + + +// +// DLDbList +// +class DLDbList : public vector +{ +public: + DLDbList() : mChanged(false) {} + virtual ~DLDbList() {} + + // API + virtual void add(const DLDbIdentifier& dldbIdentifier); // Adds at end if not in list + virtual void remove(const DLDbIdentifier& dldbIdentifier); // Removes from list + virtual void save(); + + bool hasChanged() const { return mChanged; } + +protected: + void changed(bool hasChanged) { mChanged=hasChanged; } + +private: + bool mChanged; +}; + +}; // end namespace CssmClient + +} // end namespace Security + +#endif // _H_CDSA_CLIENT_DLDBLIST diff --git a/libsecurity_cdsa_client/lib/aclclient.cpp b/libsecurity_cdsa_client/lib/aclclient.cpp new file mode 100644 index 00000000..b2c8a383 --- /dev/null +++ b/libsecurity_cdsa_client/lib/aclclient.cpp @@ -0,0 +1,324 @@ +/* + * Copyright (c) 2000-2001,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. + */ + + +// +// aclclient +// +#include +#include +#include +#include +#include + + +namespace Security { +namespace CssmClient { + +static inline void check(CSSM_RETURN rc) +{ + ObjectImpl::check(rc); +} + + +// +// AclBearer methods (trivial) +// +AclBearer::~AclBearer() +{ } + + +// +// Variant forms of AclBearer implemented in terms of its canonical virtual methods +// +void AclBearer::addAcl(const AclEntryInput &input, const CSSM_ACCESS_CREDENTIALS *cred) +{ + changeAcl(AclEdit(input), cred); +} + +void AclBearer::changeAcl(CSSM_ACL_HANDLE handle, const AclEntryInput &input, + const CSSM_ACCESS_CREDENTIALS *cred) +{ + changeAcl(AclEdit(handle, input), cred); +} + +void AclBearer::deleteAcl(CSSM_ACL_HANDLE handle, const CSSM_ACCESS_CREDENTIALS *cred) +{ + changeAcl(AclEdit(handle), cred); +} + +void AclBearer::deleteAcl(const char *tag, const CSSM_ACCESS_CREDENTIALS *cred) +{ + AutoAclEntryInfoList entries; + getAcl(entries, tag); + for (uint32 n = 0; n < entries.count(); n++) + deleteAcl(entries[n].handle(), cred); +} + + +// +// KeyAclBearer implementation +// +void KeyAclBearer::getAcl(AutoAclEntryInfoList &aclInfos, const char *selectionTag) const +{ + aclInfos.allocator(allocator); + check(CSSM_GetKeyAcl(csp, &key, reinterpret_cast(selectionTag), aclInfos, aclInfos)); +} + +void KeyAclBearer::changeAcl(const CSSM_ACL_EDIT &aclEdit, const CSSM_ACCESS_CREDENTIALS *cred) +{ + check(CSSM_ChangeKeyAcl(csp, AccessCredentials::needed(cred), &aclEdit, &key)); +} + +void KeyAclBearer::getOwner(AutoAclOwnerPrototype &owner) const +{ + owner.allocator(allocator); + check(CSSM_GetKeyOwner(csp, &key, owner)); +} + +void KeyAclBearer::changeOwner(const CSSM_ACL_OWNER_PROTOTYPE &newOwner, + const CSSM_ACCESS_CREDENTIALS *cred) +{ + check(CSSM_ChangeKeyOwner(csp, AccessCredentials::needed(cred), &key, &newOwner)); +} + + +// +// A single global structure containing pseudo-static data +// +struct Statics { + Statics(); + Allocator &alloc; + + AutoCredentials nullCred; + AutoCredentials promptCred; + AutoCredentials unlockCred; + AutoCredentials cancelCred; + AutoCredentials promptedPINCred; + AutoCredentials promptedPINItemCred; + + AclOwnerPrototype anyOwner; + AclEntryInfo anyAcl; +}; + +namespace { + ModuleNexus statics; +} + + +// +// Make pseudo-statics. +// Note: This is an eternal object. It is not currently destroyed +// if the containing code is unloaded. +// +Statics::Statics() + : alloc(Allocator::standard()), + nullCred(alloc, 1), + promptCred(alloc, 3), + unlockCred(alloc, 1), + cancelCred(alloc, 1), + promptedPINCred(alloc, 1), + promptedPINItemCred(alloc, 1), + anyOwner(TypedList(alloc, CSSM_ACL_SUBJECT_TYPE_ANY)), + anyAcl(AclEntryPrototype(TypedList(alloc, CSSM_ACL_SUBJECT_TYPE_ANY), 1)) +{ + // nullCred: nothing at all + // contains: + // an empty THRESHOLD sample to match threshold subjects with "free" subjects + nullCred.sample(0) = TypedList(alloc, CSSM_SAMPLE_TYPE_THRESHOLD); + + // 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())); + + // unlockCred: ??? + unlockCred.sample(0) = TypedList(alloc, CSSM_SAMPLE_TYPE_KEYCHAIN_LOCK, + new(alloc) ListElement(CSSM_SAMPLE_TYPE_KEYCHAIN_PROMPT)); + + cancelCred.sample(0) = TypedList(alloc, CSSM_SAMPLE_TYPE_KEYCHAIN_LOCK, + new(alloc) ListElement(CSSM_WORDID_CANCELED)); + + /* + We don't set this: + + promptedPINCred.tag("PIN1"); + + here to avoid triggering code in TokenDatabase::getAcl in securityd that + would always show a PIN unlock dialog. This credential is used for an + unlock of the database, i.e. a dbauthenticate call to unlock the card. + */ + promptedPINCred.sample(0) = TypedList(alloc, CSSM_SAMPLE_TYPE_PROMPTED_PASSWORD, + new(alloc) ListElement(alloc, CssmData())); + + /* + This credential is used for items like non-repudiation keys that always + require an explicit entry of the PIN. We set this so that Token::authenticate + will recognize the number of the PIN we need to unlock. + */ + promptedPINItemCred.tag("PIN1"); + promptedPINItemCred.sample(0) = TypedList(alloc, CSSM_SAMPLE_TYPE_PROMPTED_PASSWORD, + new(alloc) ListElement(alloc, CssmData())); +} + + +// +// Make and break AclFactories +// +AclFactory::AclFactory() +{ } + +AclFactory::~AclFactory() +{ } + + +// +// Return basic pseudo-static values +// +const AccessCredentials *AclFactory::nullCred() const +{ return &statics().nullCred; } + +const AccessCredentials *AclFactory::promptCred() const +{ return &statics().promptCred; } + +const AccessCredentials *AclFactory::unlockCred() const +{ return &statics().unlockCred; } + + +const AccessCredentials *AclFactory::cancelCred() const +{ return &statics().cancelCred; } + +const AccessCredentials *AclFactory::promptedPINCred() const +{ return &statics().promptedPINCred; } + +const AccessCredentials *AclFactory::promptedPINItemCred() const +{ return &statics().promptedPINItemCred; } + + +// +// Manage the (pseudo) credentials used to explicitly provide a passphrase to a keychain. +// Use the eternal unlockCred() for normal (protected prompt) unlocking. +// +AclFactory::KeychainCredentials::~KeychainCredentials () +{ + DataWalkers::chunkFree(mCredentials, allocator); +} + +AclFactory::PassphraseUnlockCredentials::PassphraseUnlockCredentials (const CssmData& password, + Allocator& allocator) : KeychainCredentials(allocator) +{ + mCredentials->sample(0) = TypedList(allocator, CSSM_SAMPLE_TYPE_KEYCHAIN_LOCK, + new (allocator) ListElement (CSSM_SAMPLE_TYPE_PASSWORD), + new (allocator) ListElement (CssmAutoData(allocator, password).release())); +} + + +// +// Manage the (pseudo) credentials used to explicitly change a keychain's passphrase +// +AclFactory::PasswordChangeCredentials::PasswordChangeCredentials (const CssmData& password, + Allocator& allocator) : KeychainCredentials(allocator) +{ + mCredentials->sample(0) = TypedList(allocator, CSSM_SAMPLE_TYPE_KEYCHAIN_CHANGE_LOCK, + new (allocator) ListElement (CSSM_SAMPLE_TYPE_PASSWORD), + new (allocator) ListElement (CssmAutoData(allocator, password).release())); +} + + +// +// Wide open ("ANY") CSSM forms for owner and ACL entry +// +const AclOwnerPrototype &AclFactory::anyOwner() const +{ return statics().anyOwner; } + +const AclEntryInfo &AclFactory::anyAcl() const +{ return statics().anyAcl; } + + +// +// Create an ANY style AclEntryInput. +// This can be used to explicitly request wide-open authorization on a new CSSM object. +// +AclFactory::AnyResourceContext::AnyResourceContext(const CSSM_ACCESS_CREDENTIALS *cred) + : mAny(CSSM_ACL_SUBJECT_TYPE_ANY), mTag(CSSM_ACL_AUTHORIZATION_ANY) +{ + // set up an ANY/EVERYTHING AclEntryInput + input().proto().subject() += &mAny; + AuthorizationGroup &authGroup = input().proto().authorization(); + authGroup.NumberOfAuthTags = 1; + authGroup.AuthTags = &mTag; + + // install the cred (not copied) + credentials(cred); +} + + +// +// CSSM ACL makers +// +AclFactory::Subject::Subject(Allocator &alloc, CSSM_ACL_SUBJECT_TYPE type) + : TypedList(alloc, type) +{ } + + +AclFactory::PWSubject::PWSubject(Allocator &alloc) + : Subject(alloc, CSSM_ACL_SUBJECT_TYPE_PASSWORD) +{ } + +AclFactory::PWSubject::PWSubject(Allocator &alloc, const CssmData &secret) + : Subject(alloc, CSSM_ACL_SUBJECT_TYPE_PASSWORD) +{ + append(new(alloc) ListElement(alloc, secret)); +} + +AclFactory::PromptPWSubject::PromptPWSubject(Allocator &alloc, const CssmData &prompt) + : Subject(alloc, CSSM_ACL_SUBJECT_TYPE_PROMPTED_PASSWORD) +{ + append(new(alloc) ListElement(alloc, prompt)); +} + +AclFactory::PromptPWSubject::PromptPWSubject(Allocator &alloc, const CssmData &prompt, const CssmData &secret) + : Subject(alloc, CSSM_ACL_SUBJECT_TYPE_PROMPTED_PASSWORD) +{ + append(new(alloc) ListElement(alloc, prompt)); + append(new(alloc) ListElement(alloc, secret)); +} + +AclFactory::ProtectedPWSubject::ProtectedPWSubject(Allocator &alloc) + : Subject(alloc, CSSM_ACL_SUBJECT_TYPE_PROTECTED_PASSWORD) +{ } + +AclFactory::PinSubject::PinSubject(Allocator &alloc, uint32 slot) + : Subject(alloc, CSSM_ACL_SUBJECT_TYPE_PREAUTH) +{ + append(new(alloc) ListElement(CSSM_ACL_AUTHORIZATION_PREAUTH(slot))); +} + +AclFactory::PinSourceSubject::PinSourceSubject(Allocator &alloc, const TypedList &form) + : Subject(alloc, CSSM_ACL_SUBJECT_TYPE_PREAUTH_SOURCE) +{ + append(new(alloc) ListElement(form)); +} + + +} // end namespace CssmClient +} // end namespace Security diff --git a/libsecurity_cdsa_client/lib/aclclient.h b/libsecurity_cdsa_client/lib/aclclient.h new file mode 100644 index 00000000..b3db4856 --- /dev/null +++ b/libsecurity_cdsa_client/lib/aclclient.h @@ -0,0 +1,199 @@ +/* + * Copyright (c) 2000-2001,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. + */ + + +// +// aclclient +// +#ifndef _H_CDSA_CLIENT_ACLCLIENT +#define _H_CDSA_CLIENT_ACLCLIENT 1 + +#include +#include +#include +#include +#include + +namespace Security { +namespace CssmClient { + +class CSP; + + +// +// Any client-side object that has CSSM-layer ACLs shall be +// derived from AclBearer and implement its methods accordingly. +// Note the (shared/virtual) RefCount - you should handle AclBearer +// references via RefPointers. +// All the non-pure methods are implemented (in AclBearer) in terms of +// the pure virtual methods; they just restate the problem in various ways. +// +class AclBearer : public virtual RefCount { +public: + virtual ~AclBearer(); + + // Acl manipulation + virtual void getAcl(AutoAclEntryInfoList &aclInfos, + const char *selectionTag = NULL) const = 0; + virtual void changeAcl(const CSSM_ACL_EDIT &aclEdit, + const CSSM_ACCESS_CREDENTIALS *cred = NULL) = 0; + + void addAcl(const AclEntryInput &input, const CSSM_ACCESS_CREDENTIALS *cred = NULL); + void changeAcl(CSSM_ACL_HANDLE handle, const AclEntryInput &input, + const CSSM_ACCESS_CREDENTIALS *cred = NULL); + void deleteAcl(CSSM_ACL_HANDLE handle, const CSSM_ACCESS_CREDENTIALS *cred = NULL); + void deleteAcl(const char *tag = NULL, const CSSM_ACCESS_CREDENTIALS *cred = NULL); + + // Acl owner manipulation + virtual void getOwner(AutoAclOwnerPrototype &owner) const = 0; + virtual void changeOwner(const CSSM_ACL_OWNER_PROTOTYPE &newOwner, + const CSSM_ACCESS_CREDENTIALS *cred = NULL) = 0; +}; + + +// +// An AclBearer applied to a raw CSSM key +// +class KeyAclBearer : public AclBearer { +public: + KeyAclBearer(CSSM_CSP_HANDLE cspH, CSSM_KEY &theKey, Allocator &alloc) + : csp(cspH), key(theKey), allocator(alloc) { } + + const CSSM_CSP_HANDLE csp; + CSSM_KEY &key; + Allocator &allocator; + +protected: + void getAcl(AutoAclEntryInfoList &aclInfos, + const char *selectionTag = NULL) const; + void changeAcl(const CSSM_ACL_EDIT &aclEdit, + const CSSM_ACCESS_CREDENTIALS *cred = NULL); + void getOwner(AutoAclOwnerPrototype &owner) const; + void changeOwner(const CSSM_ACL_OWNER_PROTOTYPE &newOwner, + const CSSM_ACCESS_CREDENTIALS *cred = NULL); +}; + + +// +// An AclFactory helps create and maintain CSSM-layer AccessCredentials +// and matching samples. There is state in an AclFactory, though simple +// uses may not care about it. +// +class AclFactory { +public: + AclFactory(); + virtual ~AclFactory(); + + // these values are owned by the AclFactory and persist + // until it is destroyed. You don't own the memory. + const AccessCredentials *nullCred() const; // conforming empty + const AccessCredentials *promptCred() const; // enable interactive prompting + const AccessCredentials *unlockCred() const; + const AccessCredentials *cancelCred() const; + const AccessCredentials *promptedPINCred() const; + const AccessCredentials *promptedPINItemCred() const; + + const AclOwnerPrototype &anyOwner() const; // wide-open owner + const AclEntryInfo &anyAcl() const; // wide-open ACL entry (authorizes anything) + +protected: + class KeychainCredentials { + public: + KeychainCredentials(Allocator &alloc) + : allocator(alloc), mCredentials(new AutoCredentials(alloc)) { } + virtual ~KeychainCredentials(); + + Allocator &allocator; + + operator const AccessCredentials* () const { return mCredentials; } + + protected: + AutoCredentials *mCredentials; + }; + +public: + // create a self-managed AccessCredentials to explicitly provide a keychain passphrase + class PassphraseUnlockCredentials : public KeychainCredentials { + public: + PassphraseUnlockCredentials (const CssmData& password, Allocator& allocator); + }; + + // create a self-managed AccessCredentials to change a keychain passphrase + class PasswordChangeCredentials : public KeychainCredentials { + public: + PasswordChangeCredentials (const CssmData& password, Allocator& allocator); + }; + +public: + class AnyResourceContext : public ResourceControlContext { + public: + AnyResourceContext(const CSSM_ACCESS_CREDENTIALS *cred = NULL); + + private: + ListElement mAny; + CSSM_ACL_AUTHORIZATION_TAG mTag; + }; + +public: + // + // Subject makers. Contents are chunk-allocated with the Allocator given + // + struct Subject : public TypedList { + Subject(Allocator &alloc, CSSM_ACL_SUBJECT_TYPE type); + }; + + // an ANY subject, allocated dynamically for you + struct AnySubject : public Subject { + AnySubject(Allocator &alloc) : Subject(alloc, CSSM_ACL_SUBJECT_TYPE_ANY) { } + }; + + // a "nobody" subject (something guaranteed never to match) + struct NobodySubject : public Subject { + NobodySubject(Allocator &alloc) : Subject(alloc, CSSM_ACL_SUBJECT_TYPE_COMMENT) { } + }; + + // password subjects + struct PWSubject : public Subject { + PWSubject(Allocator &alloc); // no secret + PWSubject(Allocator &alloc, const CssmData &secret); // this secret + }; + + struct PromptPWSubject : public Subject { + PromptPWSubject(Allocator &alloc, const CssmData &prompt); + PromptPWSubject(Allocator &alloc, const CssmData &prompt, const CssmData &secret); + }; + + struct ProtectedPWSubject : public Subject { + ProtectedPWSubject(Allocator &alloc); + }; + + // PIN (pre-auth) reference, origin side + struct PinSubject : public Subject { + PinSubject(Allocator &alloc, uint32 slot); + }; + + // PIN (pre-auth) source site + struct PinSourceSubject : public Subject { + PinSourceSubject(Allocator &alloc, const TypedList &form); + }; +}; + + +} // end namespace CssmClient +} // end namespace Security + +#endif // _H_CDSA_CLIENT_ACLCLIENT diff --git a/libsecurity_cdsa_client/lib/clclient.cpp b/libsecurity_cdsa_client/lib/clclient.cpp new file mode 100644 index 00000000..33e0c55d --- /dev/null +++ b/libsecurity_cdsa_client/lib/clclient.cpp @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2000-2002 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. + */ + + +// +// clclient - client interface to CSSM CLs and their operations +// +#include + +using namespace CssmClient; + + +// +// Manage CL attachments +// +CLImpl::CLImpl(const Guid &guid) : AttachmentImpl(guid, CSSM_SERVICE_CL) +{ +} + +CLImpl::CLImpl(const Module &module) : AttachmentImpl(module, CSSM_SERVICE_CL) +{ +} + +CLImpl::~CLImpl() +{ +} + + +// +// A BuildCertGroup +// +BuildCertGroup::BuildCertGroup(CSSM_CERT_TYPE ctype, CSSM_CERT_ENCODING encoding, + CSSM_CERTGROUP_TYPE type, Allocator &alloc) + : certificates(NumCerts, GroupList.CertList) +{ + clearPod(); + CertType = ctype; + CertEncoding = encoding; + CertGroupType = type; +} diff --git a/libsecurity_cdsa_client/lib/clclient.h b/libsecurity_cdsa_client/lib/clclient.h new file mode 100644 index 00000000..4b2bbf75 --- /dev/null +++ b/libsecurity_cdsa_client/lib/clclient.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2000-2002 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. + */ + + +// +// clclient - client interface to CSSM CLs and their operations +// +#ifndef _H_CDSA_CLIENT_CLCLIENT +#define _H_CDSA_CLIENT_CLCLIENT 1 + +#include +#include + + +namespace Security { +namespace CssmClient { + + +// +// A CL attachment +// +class CLImpl : public AttachmentImpl +{ +public: + CLImpl(const Guid &guid); + CLImpl(const Module &module); + virtual ~CLImpl(); + +}; + +class CL : public Attachment +{ +public: + typedef CLImpl Impl; + + explicit CL(Impl *impl) : Attachment(impl) {} + CL(const Guid &guid) : Attachment(new Impl(guid)) {} + CL(const Module &module) : Attachment(new Impl(module)) {} + + Impl *operator ->() const { return &impl(); } + Impl &operator *() const { return impl(); } +}; + + +// +// A self-building CertGroup. +// This is a CertGroup, but it's NOT A PODWRAPPER (it's larger). +// +class BuildCertGroup : public CertGroup { +public: + BuildCertGroup(CSSM_CERT_TYPE ctype, CSSM_CERT_ENCODING encoding, + CSSM_CERTGROUP_TYPE type, Allocator &alloc = Allocator::standard()); + + CssmVector certificates; +}; + + +} // end namespace CssmClient +} // end namespace Security + +#endif // _H_CDSA_CLIENT_CLCLIENT diff --git a/libsecurity_cdsa_client/lib/cryptoclient.cpp b/libsecurity_cdsa_client/lib/cryptoclient.cpp new file mode 100644 index 00000000..e271f311 --- /dev/null +++ b/libsecurity_cdsa_client/lib/cryptoclient.cpp @@ -0,0 +1,142 @@ +/* + * 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. + */ + + +// +// cryptoclient - client interface to CSSM CSP encryption/decryption operations +// +#include + +using namespace CssmClient; + + +Crypt::Crypt(const CSP &csp, CSSM_ALGORITHMS alg) + : Context(csp, alg), mMode(CSSM_ALGMODE_NONE), mInitVector(NULL), + mPadding(CSSM_PADDING_NONE) +{ +} + +void Crypt::key(const Key &key) +{ + mKey = key; + set(CSSM_ATTRIBUTE_KEY, static_cast(key)); +} + + +void +Crypt::activate() +{ + if (!mActive) + { + // Key is required unless we have a NULL algorithm (cleartext wrap/unwrap), + // in which case we'll make a symmetric context (it shouldn't matter then). + if (!mKey && mAlgorithm != CSSM_ALGID_NONE) + CssmError::throwMe(CSSMERR_CSP_MISSING_ATTR_KEY); + if (!mKey || mKey->keyClass() == CSSM_KEYCLASS_SESSION_KEY) + { // symmetric key + check(CSSM_CSP_CreateSymmetricContext(attachment()->handle(), mAlgorithm, + mMode, neededCred(), mKey, mInitVector, mPadding, NULL, + &mHandle)); + } + else + { + check(CSSM_CSP_CreateAsymmetricContext(attachment()->handle(), mAlgorithm, + neededCred(), mKey, mPadding, &mHandle)); + //@@@ stick mode and initVector explicitly into the context? + } + mActive = true; + } +} + + +// +// Manage encryption contexts +// +CSSM_SIZE +Encrypt::encrypt(const CssmData *in, uint32 inCount, + CssmData *out, uint32 outCount, CssmData &remData) +{ + unstaged(); + CSSM_SIZE total; + check(CSSM_EncryptData(handle(), in, inCount, out, outCount, &total, &remData)); + return total; +} + +void +Encrypt::init() +{ + check(CSSM_EncryptDataInit(handle())); + mStaged = true; +} + +CSSM_SIZE +Encrypt::encrypt(const CssmData *in, uint32 inCount, + CssmData *out, uint32 outCount) +{ + staged(); + CSSM_SIZE total; + check(CSSM_EncryptDataUpdate(handle(), in, inCount, out, outCount, &total)); + return total; +} + +void +Encrypt::final(CssmData &remData) +{ + staged(); + check(CSSM_EncryptDataFinal(handle(), &remData)); + mStaged = false; +} + + +// +// Manage Decryption contexts +// + +CSSM_SIZE +Decrypt::decrypt(const CssmData *in, uint32 inCount, + CssmData *out, uint32 outCount, CssmData &remData) +{ + unstaged(); + CSSM_SIZE total; + check(CSSM_DecryptData(handle(), in, inCount, out, outCount, &total, &remData)); + return total; +} + +void +Decrypt::init() +{ + check(CSSM_DecryptDataInit(handle())); + mStaged = true; +} + +CSSM_SIZE +Decrypt::decrypt(const CssmData *in, uint32 inCount, + CssmData *out, uint32 outCount) +{ + staged(); + CSSM_SIZE total; + check(CSSM_DecryptDataUpdate(handle(), in, inCount, out, outCount, &total)); + return total; +} + +void +Decrypt::final(CssmData &remData) +{ + staged(); + check(CSSM_DecryptDataFinal(handle(), &remData)); + mStaged = false; +} diff --git a/libsecurity_cdsa_client/lib/cryptoclient.h b/libsecurity_cdsa_client/lib/cryptoclient.h new file mode 100644 index 00000000..18ab4b79 --- /dev/null +++ b/libsecurity_cdsa_client/lib/cryptoclient.h @@ -0,0 +1,115 @@ +/* + * 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. + */ + + +// +// cryptoclient - client interface to CSSM CSP encryption/decryption operations +// +#ifndef _H_CDSA_CLIENT_CRYPTOCLIENT +#define _H_CDSA_CLIENT_CRYPTOCLIENT 1 + +#include +#include + +namespace Security { +namespace CssmClient { + + +// +// Common features of various cryptographic operations contexts. +// These all use symmetric or asymmetric contexts. +// +class Crypt : public Context { +public: + Crypt(const CSP &csp, CSSM_ALGORITHMS alg); + +public: + // Context attributes + CSSM_ENCRYPT_MODE mode() const { return mMode; } + void mode(CSSM_ENCRYPT_MODE m) { mMode = m; set(CSSM_ATTRIBUTE_MODE, m); } + Key key() const { return mKey; } + void key(const Key &k); + const CssmData &initVector() const { return *mInitVector; } + void initVector(const CssmData &v) { mInitVector = &v; set(CSSM_ATTRIBUTE_INIT_VECTOR, v); } + CSSM_PADDING padding() const { return mPadding; } + void padding(CSSM_PADDING p) { mPadding = p; set(CSSM_ATTRIBUTE_PADDING, p); } + +protected: + void activate(); + +protected: + CSSM_ENCRYPT_MODE mMode; + Key mKey; + const CssmData *mInitVector; + CSSM_PADDING mPadding; +}; + + + +// +// An encryption context +// +class Encrypt : public Crypt +{ +public: + Encrypt(const CSP &csp, CSSM_ALGORITHMS alg) : Crypt(csp, alg) {}; + +public: + // integrated + CSSM_SIZE encrypt(const CssmData *in, uint32 inCount, CssmData *out, uint32 outCount, + CssmData &remData); + CSSM_SIZE encrypt(const CssmData &in, CssmData &out, CssmData &remData) + { return encrypt(&in, 1, &out, 1, remData); } + + // staged update + void init(); // Optional + CSSM_SIZE encrypt(const CssmData *in, uint32 inCount, CssmData *out, uint32 outCount); + CSSM_SIZE encrypt(const CssmData &in, CssmData &out) + { return encrypt(&in, 1, &out, 1); } + // staged final + void final(CssmData &remData); +}; + +// +// An Decryption context +// +class Decrypt : public Crypt +{ +public: + Decrypt(const CSP &csp, CSSM_ALGORITHMS alg) : Crypt(csp, alg) {}; + +public: + // integrated + CSSM_SIZE decrypt(const CssmData *in, uint32 inCount, CssmData *out, uint32 outCount, + CssmData &remData); + CSSM_SIZE decrypt(const CssmData &in, CssmData &out, CssmData &remData) + { return decrypt(&in, 1, &out, 1, remData); } + + // staged update + void init(); // Optional + CSSM_SIZE decrypt(const CssmData *in, uint32 inCount, CssmData *out, uint32 outCount); + CSSM_SIZE decrypt(const CssmData &in, CssmData &out) + { return decrypt(&in, 1, &out, 1); } + // staged final + void final(CssmData &remData); +}; + + +} // end namespace CssmClient +} // end namespace Security + +#endif // _H_CDSA_CLIENT_CRYPTOCLIENT diff --git a/libsecurity_cdsa_client/lib/cspclient.cpp b/libsecurity_cdsa_client/lib/cspclient.cpp new file mode 100644 index 00000000..8e4a313f --- /dev/null +++ b/libsecurity_cdsa_client/lib/cspclient.cpp @@ -0,0 +1,260 @@ +/* + * Copyright (c) 2000-2002 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. + */ + + +// +// cspclient - client interface to CSSM CSPs and their operations +// +#include + +namespace Security { +namespace CssmClient { + + +// +// Manage CSP attachments +// +CSPImpl::CSPImpl(const Guid &guid) : AttachmentImpl(guid, CSSM_SERVICE_CSP) +{ +} + +CSPImpl::CSPImpl(const Module &module) : AttachmentImpl(module, CSSM_SERVICE_CSP) +{ +} + +CSPImpl::~CSPImpl() +{ +} + + +// +// Delete a key explicitly +// +void CSPImpl::freeKey(CssmKey &key, const AccessCredentials *cred, bool permanent) +{ + check(CSSM_FreeKey(handle(), cred, &key, permanent)); +} + + +// +// Manage generic context objects +// +Context::Context(const CSP &csp, CSSM_ALGORITHMS alg) +: ObjectImpl(csp), mAlgorithm(alg), mStaged(false), mCred(NULL) +{ +} + +Context::~Context() +{ + try + { + deactivate(); + } catch(...) {} +} + +void Context::init() +{ + CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); +} + +void Context::deactivate() +{ + if (mActive) + { + mActive = false; + check(CSSM_DeleteContext(mHandle)); + } +} + + +void Context::algorithm(CSSM_ALGORITHMS alg) +{ + if (isActive()) + abort(); //@@@ can't (currently?) change algorithm with active context + mAlgorithm = alg; +} + + +void Context::cred(const CSSM_ACCESS_CREDENTIALS *cred) +{ + mCred = AccessCredentials::overlay(cred); + set(CSSM_ATTRIBUTE_ACCESS_CREDENTIALS, *mCred); +} + + +// +// Query context operation output sizes. +// +uint32 Context::getOutputSize(uint32 inputSize, bool encrypt /*= true*/) +{ + CSSM_QUERY_SIZE_DATA data; + data.SizeInputBlock = inputSize; + getOutputSize(data, 1, encrypt); + return data.SizeOutputBlock; +} + +void Context::getOutputSize(CSSM_QUERY_SIZE_DATA &sizes, uint32 count, bool encrypt /*= true*/) +{ + check(CSSM_QuerySize(handle(), encrypt, count, &sizes)); +} + + +// +// The override() method of Context is an expert feature. It replaces the entire +// context with a context object provided. It is up to the caller to keep this context +// consistent with the purpose of the Context subclass he is (mis)using. +// This feature is currently used by the SecurityServer. +// +void Context::override(const Security::Context &ctx) +{ + if (!isActive()) { + // make a valid context object (it doesn't matter what kind - keep it cheap) + check(CSSM_CSP_CreateDigestContext(attachment()->handle(), CSSM_ALGID_NONE, &mHandle)); + } + // now replace everything with the context data provided + check(CSSM_SetContext(mHandle, &ctx)); + mActive = true; // now active +} + + +// +// RccContexts +// +const ResourceControlContext &RccBearer::compositeRcc() const +{ + // explicitly specified RCC wins + if (mRcc) + return *mRcc; + + // cobble one up from the pieces + if (mOwner) + mWorkRcc.input() = *mOwner; + else + mWorkRcc.clearPod(); + mWorkRcc.credentials(mOpCred); + return mWorkRcc; +} + + +void RccBearer::owner(const CSSM_ACL_ENTRY_PROTOTYPE *owner) +{ + if (owner) { + mWorkInput = *owner; + this->owner(mWorkInput); + } else + this->owner((AclEntryInput*)NULL); +} + + +// +// Manage PassThrough contexts +// + +// +// Invoke passThrough +// +void +PassThrough::operator() (uint32 passThroughId, const void *inData, void **outData) +{ + check(CSSM_CSP_PassThrough(handle(), passThroughId, inData, outData)); +} + +void PassThrough::activate() +{ + if (!mActive) { + check(CSSM_CSP_CreatePassThroughContext(attachment()->handle(), mKey, &mHandle)); + mActive = true; + } +} + + +// +// Manage Digest contexts +// +void Digest::activate() +{ + if (!mActive) { + check(CSSM_CSP_CreateDigestContext(attachment()->handle(), mAlgorithm, &mHandle)); + mActive = true; + } +} + + +void Digest::digest(const CssmData *data, uint32 count, CssmData &digest) +{ + activate(); + if (mStaged) + Error::throwMe(CSSMERR_CSP_STAGED_OPERATION_IN_PROGRESS); + check(CSSM_DigestData(handle(), data, count, &digest)); +} + +void Digest::digest(const CssmData *data, uint32 count) +{ + activate(); + if (!mStaged) { + check(CSSM_DigestDataInit(handle())); + mStaged = true; + } + check(CSSM_DigestDataUpdate(handle(), data, count)); +} + +void Digest::operator () (CssmData &digest) +{ + if (!mStaged) + Error::throwMe(CSSMERR_CSP_STAGED_OPERATION_NOT_STARTED); + check(CSSM_DigestDataFinal(handle(), &digest)); + mStaged = false; +} + + +// +// Random number generation +// +void Random::seed(const CssmCryptoData &seedData) +{ + mSeed = &seedData; + set(CSSM_ATTRIBUTE_SEED, seedData); +} + +void Random::size(uint32 sz) +{ + mSize = sz; + set(CSSM_ATTRIBUTE_OUTPUT_SIZE, sz); +} + + +void Random::activate() +{ + if (!mActive) { + check(CSSM_CSP_CreateRandomGenContext(attachment()->handle(), mAlgorithm, + mSeed, mSize, &mHandle)); + mActive = true; + } +} + + +void Random::generate(CssmData &data, uint32 newSize) +{ + if (newSize) + size(newSize); + activate(); + assert(!mStaged); // not a stage-able operation + check(CSSM_GenerateRandom(handle(), &data)); +} + +} // end namespace CssmClient +} // end namespace Security diff --git a/libsecurity_cdsa_client/lib/cspclient.h b/libsecurity_cdsa_client/lib/cspclient.h new file mode 100644 index 00000000..2ffe7210 --- /dev/null +++ b/libsecurity_cdsa_client/lib/cspclient.h @@ -0,0 +1,268 @@ +/* + * Copyright (c) 2000-2002 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. + */ + + +// +// cspclient - client interface to CSSM CSPs and their operations +// +#ifndef _H_CDSA_CLIENT_CSPCLIENT +#define _H_CDSA_CLIENT_CSPCLIENT 1 + +#include +#include +#include + +namespace Security { +namespace CssmClient { + + +// +// A CSP attachment +// +class CSPImpl : public AttachmentImpl +{ +public: + CSPImpl(const Guid &guid); + CSPImpl(const Module &module); + virtual ~CSPImpl(); + + // the least inappropriate place for this one + void freeKey(CssmKey &key, const AccessCredentials *cred = NULL, bool permanent = false); +}; + +class CSP : public Attachment +{ +public: + typedef CSPImpl Impl; + + explicit CSP(Impl *impl) : Attachment(impl) {} + CSP(const Guid &guid) : Attachment(new Impl(guid)) {} + CSP(const Module &module) : Attachment(new Impl(module)) {} + + Impl *operator ->() const { return &impl(); } + Impl &operator *() const { return impl(); } +}; + +// +// A cryptographic context. +// Contexts always belong to CSPs (CSP attachments). +// +class Context : public ObjectImpl +{ +public: + Context(const CSP &csp, CSSM_ALGORITHMS alg = CSSM_ALGID_NONE); + ~Context(); + + CSP attachment() const { return parent(); } + Module module() const { return attachment()->module(); } + + CSSM_ALGORITHMS algorithm() const { return mAlgorithm; } + void algorithm(CSSM_ALGORITHMS alg); + + const AccessCredentials *cred() const { return mCred; } + void cred(const CSSM_ACCESS_CREDENTIALS *cred); + void cred(const CSSM_ACCESS_CREDENTIALS &cred) { this->cred(&cred); } + +public: + CSSM_CC_HANDLE handle() { activate(); return mHandle; } + + uint32 getOutputSize(uint32 inputSize, bool encrypt = true); + void getOutputSize(CSSM_QUERY_SIZE_DATA &sizes, uint32 count, bool encrypt = true); + +public: + // don't use this section unless you know what you're doing! + void override(const ::Context &ctx); + + template + void set(CSSM_ATTRIBUTE_TYPE type, const T &value) + { + if (isActive()) { + ::Context::Attr attr(type, value); + check(CSSM_UpdateContextAttributes(mHandle, 1, &attr)); + } + } + + void set(CSSM_ATTRIBUTE_TYPE type, uint32 value) + { + if (isActive()) { + ::Context::Attr attr(type, value); + check(CSSM_UpdateContextAttributes(mHandle, 1, &attr)); + } + } + + template + void add(CSSM_ATTRIBUTE_TYPE type, const T &value) + { activate(); set(type, value); } + + void add(CSSM_ATTRIBUTE_TYPE type, uint32 value) + { activate(); set(type, value); } + +protected: + void deactivate(); + + virtual void init(); // Subclasses must implement if they support staged operations. + + void unstaged() + { activate(); if (mStaged) CssmError::throwMe(CSSMERR_CSP_STAGED_OPERATION_IN_PROGRESS); } + + void staged() + { if (!mStaged) init(); } + + const AccessCredentials *neededCred() + { return AccessCredentials::needed(mCred); } + +protected: + CSSM_ALGORITHMS mAlgorithm; // intended algorithm + CSSM_CC_HANDLE mHandle; // CSSM CC handle + bool mStaged; // staged in progress + const AccessCredentials *mCred; // if explicitly set +}; + + +// +// An RccBearer holds a ResourceControlContext. Note that this is a composite +// of an AccessCredentials and an AclEntryInput. We allow setting the whole +// thing, or its two components separately. A complete rcc set (via ::rcc) +// overrides any components. +// @@@ Perhaps we should merge components into a specified rcc? Iffy, though... +// Note: We call the credential components "opCred" to distinguish it from +// the "cred" of a CredBearer; some classes are both. As a rule, the "cred" goes +// into the context, while the "opCred" gets passed as an argument. +// +class RccBearer { +public: + RccBearer() : mOpCred(NULL), mOwner(NULL), mRcc(NULL) { } + + const AccessCredentials *opCred() const { return mOpCred; } + void opCred(const CSSM_ACCESS_CREDENTIALS *cred) { mOpCred = AccessCredentials::overlay(cred); } + void opCred(const CSSM_ACCESS_CREDENTIALS &cred) { this->opCred(&cred); } + const AclEntryInput *owner() const { return mOwner; } + void owner(const CSSM_ACL_ENTRY_INPUT *owner) { mOwner = AclEntryInput::overlay(owner); } + void owner(const CSSM_ACL_ENTRY_INPUT &owner) { this->owner(&owner); } + void owner(const CSSM_ACL_ENTRY_PROTOTYPE *owner); + void owner(const CSSM_ACL_ENTRY_PROTOTYPE &owner) { this->owner(&owner); } + const ResourceControlContext *rcc() const { return mRcc; } + void rcc(const CSSM_RESOURCE_CONTROL_CONTEXT *rcc) + { mRcc = ResourceControlContext::overlay(rcc); } + void rcc(const CSSM_RESOURCE_CONTROL_CONTEXT &rcc) { this->rcc(&rcc); } + +protected: + const ResourceControlContext &compositeRcc() const; + +private: + // an RCC contains both a cred and entryInput + // mCred/mAcl are only considered if mRcc is not set (NULL) + const AccessCredentials *mOpCred; + const AclEntryInput *mOwner; + const ResourceControlContext *mRcc; + + mutable ResourceControlContext mWorkRcc; // work area + mutable AclEntryInput mWorkInput; // work area +}; + + +// +// A PassThough context +// +class PassThrough : public Context +{ +public: + PassThrough(const CSP &csp) : Context(csp) { } + +public: + void operator () (uint32 passThroughId, const void *inData, void **outData); + + template + void operator () (uint32 passThroughId, const TIn *inData, TOut **outData) + { operator () (passThroughId, (const void *)inData, (void **)outData); } + + template + void operator () (uint32 passThroughId, const TIn *inData) + { operator () (passThroughId, (const void *)inData, NULL); } + + const CSSM_KEY *key() const { return mKey; } + void key(const CSSM_KEY *k) { mKey = k; set(CSSM_ATTRIBUTE_KEY, k); } + +protected: + void activate(); + +protected: + const CSSM_KEY *mKey; +}; + + +// +// A Digest context +// +class Digest : public Context +{ +public: + Digest(const CSP &csp, CSSM_ALGORITHMS alg) : Context(csp, alg) { } + +public: + // integrated + void digest(const CssmData &data, CssmData &digest) { this->digest(&data, 1, digest); } + void digest(const CssmData *data, uint32 count, CssmData &digest); + + // staged + void digest(const CssmData &data) { digest(&data, 1); } + void digest(const CssmData *data, uint32 count); + void operator () (CssmData &digest); + CssmData operator () () { CssmData digest; (*this)(digest); return digest; } + +protected: + void activate(); +}; + + +// +// A [P]RNG context +// +class Random : public Context +{ +public: + Random(const CSP &csp, CSSM_ALGORITHMS alg) : Context(csp, alg), mSeed(NULL), mSize(1) { } + Random(const CSP &csp, CSSM_ALGORITHMS alg, const CssmCryptoData &seed) + : Context(csp, alg), mSeed(&seed), mSize(1) { } + Random(const CSP &csp, CSSM_ALGORITHMS alg, uint32 size) + : Context(csp, alg), mSeed(NULL), mSize(size) { } + Random(const CSP &csp, CSSM_ALGORITHMS alg, const CssmCryptoData &seed, uint32 size) + : Context(csp, alg), mSeed(&seed), mSize(size) { } + + void seed(const CssmCryptoData &data); + void size(uint32 size); + +public: + void generate(CssmData &data, uint32 size = 0); + + // alternate function-call form + CssmData operator () (uint32 size = 0) + { CssmData output; generate(output, size); return output; } + +protected: + void activate(); + +private: + const CssmCryptoData *mSeed; + uint32 mSize; +}; + + +} // end namespace CssmClient +} // end namespace Security + +#endif // _H_CDSA_CLIENT_CSPCLIENT diff --git a/libsecurity_cdsa_client/lib/cssmclient.cpp b/libsecurity_cdsa_client/lib/cssmclient.cpp new file mode 100644 index 00000000..ec3fb44d --- /dev/null +++ b/libsecurity_cdsa_client/lib/cssmclient.cpp @@ -0,0 +1,515 @@ +/* + * 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. + */ + + +// +// cssmclient - common client interface to CSSM and MDS. +// +// Locking Strategy (preliminary): +// XXX This is obsolete update this --mb +// A CssmObject is a CountingMutex. Its count represents the number of children that have registered +// themselves (using addChild/removeChild). The lock controls the internal management fields of the +// various subclasses to protect them against corruption. It does NOT control attribute and argument +// fields and operations, not does it control object-constant fields. +// This means that if you use an object from multiple threads, you (the caller) must lock the object +// during set/get calls of attributes. Note that the CSSM operations themselves are safely multithreaded +// and thus don't need to be interlocked explicitly. +// +#include + + +using namespace CssmClient; + +// +// Exception model +// +const char * +Error::what () const throw() +{ + return "CSSM client library error"; +} + + +// +// General utilities +// +void +ObjectImpl::check(CSSM_RETURN status) +{ + if (status != CSSM_OK) + { + CssmError::throwMe(status); + } +} + + +// +// Common features of Objects +// +ObjectImpl::ObjectImpl() : mParent(), mChildCount(0) +{ + mActive = false; // not activated + mAllocator = NULL; // allocator to be determined +} + +ObjectImpl::ObjectImpl(const Object &mommy) : mParent(mommy.mImpl), mChildCount(0) +{ + mActive = false; // not activated + mAllocator = NULL; // allocator to be determined + if (mParent) + mParent->addChild(); +} + +ObjectImpl::~ObjectImpl() +try +{ + assert(!mActive); // subclass must have deactivated us + assert(isIdle()); + + // release parent from her obligations (if we still have one) + if (mParent) + mParent->removeChild(); +} +catch(...) +{ + return; +} + +void +ObjectImpl::addChild() +{ + mChildCount++; // atomic +} + +void +ObjectImpl::removeChild() +{ + mChildCount--; // atomic +} + + +// +// Manage allocators in the Object tree +// +Allocator & +ObjectImpl::allocator() const +{ + if (mAllocator == NULL) + { + // fix allocator now + if (mParent) + mAllocator = &mParent->allocator(); + else + mAllocator = &Allocator::standard(); + } + + return *mAllocator; +} + +void +ObjectImpl::allocator(Allocator &alloc) +{ + assert(mAllocator == NULL); // cannot redefine allocator once set + mAllocator = &alloc; +} + +// Comparison operators use pointer comparison by default. Subclasses may override. +bool +ObjectImpl::operator <(const ObjectImpl &other) const +{ + return this < &other; +} + +bool +ObjectImpl::operator ==(const ObjectImpl &other) const +{ + return this == &other; +} + + +// +// CSSMSession objects. +// parent ::= NULL (none) +// active ::= CSSM initialized +// +ModuleNexus CssmImpl::mStandard; + +CssmImpl::CssmImpl() : ObjectImpl() +{ + setup(); + mStandard().setCssm(this); +} + +CssmImpl::CssmImpl(bool) : ObjectImpl() +{ + setup(); + // implicitly constructed - caller responsible for standard session management +} + +CssmImpl::~CssmImpl() +{ + try + { + deactivate(); + } + catch(...) {} + + // this may be the standard session... + mStandard().unsetCssm(this); +} + + +void +CssmImpl::setup() +{ + // set default configuration + mVersion.Major = 2; + mVersion.Minor = 0; + mScope = CSSM_PRIVILEGE_SCOPE_PROCESS; +} + + +Cssm +CssmImpl::standard() +{ + return Cssm(mStandard().get()); +} + + +void +CssmImpl::activate() +{ + if (!mActive) + { + // currently, no choices on PVC mode and key hierarchy + CSSM_PVC_MODE pvc = CSSM_PVC_NONE; + switch (CSSM_RETURN rc = CSSM_Init(&mVersion, + mScope, &mCallerGuid, + CSSM_KEY_HIERARCHY_NONE, &pvc, NULL)) { + case CSSMERR_CSSM_PVC_ALREADY_CONFIGURED: + case CSSM_OK: + break; + default: + check(rc); + } + mActive = true; + } +} + +void +CssmImpl::deactivate() +{ + if (mActive) + { + mActive = false; + + // clear module map (all gone now) + moduleMap.erase(moduleMap.begin(), moduleMap.end()); + + // now terminate CSSM + check(CSSM_Terminate()); + } +} + +void +CssmImpl::atExitHandler() +{ + try { + mStandard.reset(); + } catch (...) { + } +} + +void +CssmImpl::catchExit() +{ + // @@@ Even though this is the "right thing" to do. This only causes + // exceptions during exit and doesn't really help cleanup correctly. +#if 0 + if (::atexit(atExitHandler)) + UnixError::throwMe(); +#endif +} + + +// +// Manage the automatic Cssm object. +// This is a program global. +// +void CssmImpl::StandardCssm::setCssm(CssmImpl *cssm) +{ + StLock _(*this); + if (mCssm == NULL) + mCssm = cssm; +} + +void CssmImpl::StandardCssm::unsetCssm(CssmImpl *cssm) +{ + StLock _(*this); + if (mCssm == cssm) + mCssm = NULL; +} + +CssmImpl *CssmImpl::StandardCssm::get() +{ + StLock _(*this); + if (mCssm == NULL) { // make the default instance + mCssm = new CssmImpl(true); + } + return mCssm; +} + +CssmImpl::StandardCssm::~StandardCssm() +{ + if (mCssm) { + mCssm->deactivate(); + delete mCssm; + } +} + + +// +// Auto-module management +// +Module +CssmImpl::autoModule(const Guid &guid) +{ + StLock _(mapLock); + ModuleMap::iterator it = moduleMap.find(guid); + if (it == moduleMap.end()) + { + // no automodule for this guid yet, create one + Module module(guid, Cssm(this)); + moduleMap.insert(ModuleMap::value_type(guid, module)); + return module; + } + else + { + // existing automodule - use it + return it->second; + } +} + + +// +// Module objects. +// parent ::= the session object (usually Cssm::standard) +// active ::= module is loaded. +// +ModuleImpl::ModuleImpl(const Guid &guid) : ObjectImpl(Cssm::standard()), + mAppNotifyCallback(NULL), + mAppNotifyCallbackCtx(NULL) +{ + setGuid(guid); +} + +ModuleImpl::ModuleImpl(const Guid &guid, const Cssm &session) : ObjectImpl(session), + mAppNotifyCallback(NULL), + mAppNotifyCallbackCtx(NULL) +{ + setGuid(guid); +} + +ModuleImpl::~ModuleImpl() +{ + unload(); +} + + +// +// RawModuleEvent objects encapsulate CSSM module callbacks +// +RawModuleEvents::~RawModuleEvents() +{ } + +CSSM_RETURN RawModuleEvents::sendNotify(const CSSM_GUID *, void *context, + uint32 subService, CSSM_SERVICE_TYPE type, CSSM_MODULE_EVENT event) +{ + try { + reinterpret_cast(context)->notify(subService, type, event); + return CSSM_OK; + } catch (const CommonError &error) { + return CssmError::cssmError(error, CSSM_CSSM_BASE_ERROR); + } catch (...) { + return CSSMERR_CSSM_INTERNAL_ERROR; // whatever... + } +} + + +// +// ModuleEvents enhance RawModuleEvents by splitting the callback up by type +// +void ModuleEvents::notify(uint32 subService, + CSSM_SERVICE_TYPE type, CSSM_MODULE_EVENT event) +{ + switch (event) { + case CSSM_NOTIFY_INSERT: + insertion(subService, type); + break; + case CSSM_NOTIFY_REMOVE: + removal(subService, type); + break; + case CSSM_NOTIFY_FAULT: + fault(subService, type); + break; + } +} + +// default callbacks do nothing +void ModuleEvents::insertion(uint32 subService, CSSM_SERVICE_TYPE type) { } +void ModuleEvents::removal(uint32 subService, CSSM_SERVICE_TYPE type) { } +void ModuleEvents::fault(uint32 subService, CSSM_SERVICE_TYPE type) { } + + +void +ModuleImpl::appNotifyCallback(CSSM_API_ModuleEventHandler appNotifyCallback, void *appNotifyCallbackCtx) +{ + secdebug("callback","In ModuleImpl::appNotifyCallback, appNotifyCallback=%p, appNotifyCallbackCtx=%p", + appNotifyCallback, appNotifyCallbackCtx); + if (mActive) + Error::throwMe(Error::objectBusy); + + mAppNotifyCallback = appNotifyCallback; + mAppNotifyCallbackCtx = appNotifyCallbackCtx; +} + +void +ModuleImpl::appNotifyCallback(RawModuleEvents *handler) +{ + appNotifyCallback(RawModuleEvents::sendNotify, handler); +} + +void +ModuleImpl::activate() +{ + if (!mActive) + { + session()->init(); + // @@@ install handler here (use central dispatch with override) + secdebug("callback","In ModuleImpl::activate, mAppNotifyCallback=%p, mAppNotifyCallbackCtx=%p", + mAppNotifyCallback, mAppNotifyCallbackCtx); + check(CSSM_ModuleLoad(&guid(), CSSM_KEY_HIERARCHY_NONE, mAppNotifyCallback, mAppNotifyCallbackCtx)); + mActive = true; + session()->catchExit(); + } +} + +void +ModuleImpl::deactivate() +{ + if (!isIdle()) + Error::throwMe(Error::objectBusy); + if (mActive) + { + mActive = false; + check(CSSM_ModuleUnload(&guid(), mAppNotifyCallback, mAppNotifyCallbackCtx)); + } +} + +Cssm +ModuleImpl::session() const +{ + return parent(); +} + + +// +// CssmAttachment objects. +// parent ::= the loaded module object. +// active ::= attached. +// +AttachmentImpl::AttachmentImpl(const Guid &guid, CSSM_SERVICE_TYPE subserviceType) +: ObjectImpl(CssmImpl::standard()->autoModule(guid)) +{ + make(subserviceType); +} + +AttachmentImpl::AttachmentImpl(const Module &module, CSSM_SERVICE_TYPE subserviceType) +: ObjectImpl(module) +{ + make(subserviceType); +} + +AttachmentImpl::~AttachmentImpl() +{ + detach(); +} + +void +AttachmentImpl::make(CSSM_SERVICE_TYPE subserviceType) +{ + // default configuration + mVersion.Major = 2; + mVersion.Minor = 0; + mSubserviceType = subserviceType; + mSubserviceId = 0; + mAttachFlags = 0; +} + +void +AttachmentImpl::activate() +{ + if (!mActive) + { + module()->load(); + mMemoryFunctions = CssmAllocatorMemoryFunctions(allocator()); + check(CSSM_ModuleAttach(&guid(), &mVersion, + &mMemoryFunctions, + mSubserviceId, + mSubserviceType, + mAttachFlags, + CSSM_KEY_HIERARCHY_NONE, + NULL, 0, // no function pointer table return + NULL, // reserved + &mHandle)); + mActive = true; + } +} + +void +AttachmentImpl::deactivate() +{ + if (mActive) + { + mActive = false; + check(CSSM_ModuleDetach(mHandle)); + } +} + +CSSM_SERVICE_MASK +AttachmentImpl::subserviceMask() const +{ + return mSubserviceType; +} + +void +AttachmentImpl::subserviceId(uint32 id) +{ + mSubserviceId = id; +} + +CssmSubserviceUid +AttachmentImpl::subserviceUid() const +{ + return CssmSubserviceUid(guid(), &mVersion, mSubserviceId, subserviceMask()); +} + +Module +AttachmentImpl::module() const +{ + return parent(); +} diff --git a/libsecurity_cdsa_client/lib/cssmclient.h b/libsecurity_cdsa_client/lib/cssmclient.h new file mode 100644 index 00000000..b6b2f321 --- /dev/null +++ b/libsecurity_cdsa_client/lib/cssmclient.h @@ -0,0 +1,375 @@ +/* + * 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. + */ + + +// +// cssmclient - common client interface to CSSM and MDS +// +#ifndef _H_CDSA_CLIENT_CSSMCLIENT +#define _H_CDSA_CLIENT_CSSMCLIENT 1 + +#include +#include +#include +#include +#include +#include + +namespace Security { +namespace CssmClient { + + +// +// Forward declarations +// +class Cssm; +class Module; +class Attachment; + + +// +// An mixin for objects that have (store) GUIDs. +// The GUID value is meant to be set-once constant, and can be lock-handled accordingly. +// +class HasGuid { +public: + HasGuid(const Guid &guid) { mGuid = guid; } + HasGuid() { } + + const Guid &guid() const { return mGuid; } + +protected: + void setGuid(const Guid &guid) { mGuid = guid; } + +private: + Guid mGuid; +}; + + +// +// Exceptions are based on the CssmError utility class. We add our own class of client-side exceptions. +// +class Error : public CssmError { +public: + Error(CSSM_RETURN err) : CssmError(err) { } + virtual const char *what () const throw(); + + enum { + objectBusy = -1, + }; +}; + + +// +// The CssmObject abstract class models features common to different Cssm objects. +// It handles a tree hierarchy of objects (parent/children) safely. +// +class Object; + +class ObjectImpl : virtual public RefCount +{ +public: + explicit ObjectImpl(); // Constructor for Impl objects without a parent. + explicit ObjectImpl(const Object &parent); + virtual ~ObjectImpl(); + + bool isActive() const { return mActive; } + + virtual Allocator &allocator() const; + virtual void allocator(Allocator &alloc); + + // Pointer comparison by default. Subclasses may override. + virtual bool operator <(const ObjectImpl &other) const; + virtual bool operator ==(const ObjectImpl &other) const; + + static void check(CSSM_RETURN status); + +protected: + bool mActive; // loaded, attached, etc. + mutable Allocator *mAllocator; // allocator hierarchy (NULL => TBD) + + template Obj parent() const + { assert(mParent); return Obj(static_cast(&(*mParent))); } + + void addChild(); + void removeChild(); + bool isIdle() const { return mChildCount == 0; } + + // {de,}activate() assume you have locked *this + virtual void activate() = 0; + virtual void deactivate() = 0; + +private: + RefPointer mParent; // parent object + AtomicCounter mChildCount; +}; + + +class Object +{ + friend class ObjectImpl; +public: + typedef ObjectImpl Impl; + explicit Object(Impl *impl) : mImpl(impl) {} + +protected: + // @@@ CSPDL subclass breaks if the is a static_cast + template _Impl &impl() const + { return dynamic_cast<_Impl &>(*mImpl); } + +public: + Impl *operator ->() const { return &(*mImpl); } + Impl &operator *() const { return *mImpl; } + + // @@@ Why is this needed. DbCursor which inheirits from Object wants to call this. + template _Impl &checkedImpl() const + { return dynamic_cast<_Impl &>(*mImpl); } + + bool operator !() const { return !mImpl; } + operator bool() const { return mImpl; } + + bool isActive() const { return mImpl && mImpl->isActive(); } + Allocator &allocator() const { return mImpl->allocator(); } + void release() { mImpl = NULL; } + + bool operator <(const Object &other) const + { return mImpl && other.mImpl ? *mImpl < *other.mImpl : mImpl < other.mImpl; } + bool operator ==(const Object &other) const + { return mImpl && other.mImpl ? *mImpl == *other.mImpl : mImpl == other.mImpl; } + +private: + RefPointer mImpl; +}; + + +// +// Event callback mix-in class +// +class ModuleImpl; + +class RawModuleEvents { + friend class ModuleImpl; +public: + virtual ~RawModuleEvents(); + + virtual void notify(uint32 subService, + CSSM_SERVICE_TYPE type, CSSM_MODULE_EVENT event) = 0; + +private: + static CSSM_RETURN sendNotify(const CSSM_GUID *, void *context, uint32 subService, + CSSM_SERVICE_TYPE type, CSSM_MODULE_EVENT event); +}; + +class ModuleEvents : public RawModuleEvents { +public: + virtual void insertion(uint32 subService, CSSM_SERVICE_TYPE type); + virtual void removal(uint32 subService, CSSM_SERVICE_TYPE type); + virtual void fault(uint32 subService, CSSM_SERVICE_TYPE type); + +protected: + void notify(uint32 subService, CSSM_SERVICE_TYPE type, CSSM_MODULE_EVENT event); +}; + + +// +// A CSSM loadable module. +// You rarely directly interact with these objects, but if you need to, +// here they are. +// +class ModuleImpl : public ObjectImpl, public HasGuid +{ +public: + ModuleImpl(const Guid &guid); + ModuleImpl(const Guid &guid, const Cssm &session); + virtual ~ModuleImpl(); + + void load() { activate(); } + void unload() { deactivate(); } + bool isLoaded() const { return isActive(); } + + Cssm session() const; + + void appNotifyCallback(CSSM_API_ModuleEventHandler appNotifyCallback, void *appNotifyCallbackCtx); + void appNotifyCallback(RawModuleEvents *handler); + +protected: + void activate(); + void deactivate(); + + CSSM_API_ModuleEventHandler mAppNotifyCallback; + void *mAppNotifyCallbackCtx; +}; + +class Module : public Object +{ +public: + typedef ModuleImpl Impl; + explicit Module(Impl *impl) : Object(impl) {} + Module() : Object(NULL) {} // XXX This might break operator < + Module(const Guid &guid) : Object(new Impl(guid)) {} + Module(const Guid &guid, const Cssm &session) : Object(new Impl(guid, session)) {} + + Impl *operator ->() const { return &impl(); } + Impl &operator *() const { return impl(); } +}; + + +// +// An Attachment object. This is the base class of all typed attachment classes. +// +class AttachmentImpl : public ObjectImpl +{ +public: + AttachmentImpl(const Guid &guid, CSSM_SERVICE_TYPE subserviceType); + AttachmentImpl(const Module &module, CSSM_SERVICE_TYPE subserviceType); + //AttachmentImpl(... mds reference ...); + virtual ~AttachmentImpl(); + + // Virtual so that subclasses can return there true mask. + virtual CSSM_SERVICE_MASK subserviceMask() const; + + CSSM_SERVICE_TYPE subserviceType() const { return mSubserviceType; } + CSSM_VERSION version() const { return mVersion; } + void version(const CSSM_VERSION &v) { mVersion = v; } + uint32 subserviceId() const { return mSubserviceId; } + virtual void subserviceId(uint32 id); + CSSM_ATTACH_FLAGS flags() const { return mAttachFlags; } + void flags(CSSM_ATTACH_FLAGS f) { mAttachFlags = f; } + + void attach() { activate(); } + void detach() { deactivate(); } + bool attached() const { return isActive(); } + + Module module() const; + const Guid &guid() const { return module()->guid(); } + CSSM_MODULE_HANDLE handle() { attach(); return mHandle; } + + CssmSubserviceUid subserviceUid() const; + +protected: + void activate(); + void deactivate(); + +private: + void make(CSSM_SERVICE_TYPE subserviceType); // common constructor + + CSSM_MODULE_HANDLE mHandle; + + CSSM_SERVICE_TYPE mSubserviceType; // set by constructor + CSSM_VERSION mVersion; + uint32 mSubserviceId; + CSSM_ATTACH_FLAGS mAttachFlags; + + CssmAllocatorMemoryFunctions mMemoryFunctions; // set on attach() +}; + +class Attachment : public Object +{ +public: + typedef AttachmentImpl Impl; + explicit Attachment(Impl *impl) : Object(impl) {} + Attachment(const Guid &guid, CSSM_SERVICE_TYPE subserviceType) + : Object(new Impl(guid, subserviceType)) {} + Attachment(const Module &module, CSSM_SERVICE_TYPE subserviceType) + : Object(new Impl(module, subserviceType)) {} + //Attachment(... mds reference ...); + + Impl *operator ->() const { return &impl(); } + Impl &operator *() const { return impl(); } +}; + + +// +// A CSSM session object. +// You usually only have one per program, or library, or what-not. +// +class Cssm; + +class CssmImpl : public ObjectImpl { + class StandardCssm; friend class StandardCssm; +public: + CssmImpl(); + virtual ~CssmImpl(); + + void init() { activate(); } + void terminate() { deactivate(); } + + CSSM_PRIVILEGE_SCOPE scope() const { return mScope; } + void scope(CSSM_PRIVILEGE_SCOPE sc) { mScope = sc; } + const Guid &callerGuid() const { return mCallerGuid; } + void callerGuid(const CSSM_GUID &guid) { mCallerGuid = Guid::overlay(guid); } + + Module autoModule(const Guid &guid); + +protected: + explicit CssmImpl(bool); // internal constructor + + void setup(); // constructor setup + + void activate(); + void deactivate(); + +private: + // CSSM global configuration -- picked up on each Init + CSSM_VERSION mVersion; + CSSM_PRIVILEGE_SCOPE mScope; + Guid mCallerGuid; + + // module repository: modules by guid (protected by self) + typedef map ModuleMap; + ModuleMap moduleMap; + Mutex mapLock; + +public: + static Cssm standard(); + static void catchExit(); + +private: + static void atExitHandler(); + + class StandardCssm : public Mutex { + public: + StandardCssm() : mCssm(NULL) { } + ~StandardCssm(); + void setCssm(CssmImpl *cssm); + void unsetCssm(CssmImpl *cssm); + CssmImpl *get(); + + private: + CssmImpl *mCssm; + }; + static ModuleNexus mStandard; +}; + +class Cssm : public Object +{ +public: + typedef CssmImpl Impl; + explicit Cssm(Impl *impl) : Object(impl) {} + explicit Cssm() : Object(new Impl()) {} + + Impl *operator ->() const { return &impl(); } + Impl &operator *() const { return impl(); } + + static Cssm standard() { return CssmImpl::standard(); } +}; + +} // end namespace CssmClient + +} // end namespace Security + +#endif // _H_CDSA_CLIENT_CSSMCLIENT diff --git a/libsecurity_cdsa_client/lib/dl_standard.cpp b/libsecurity_cdsa_client/lib/dl_standard.cpp new file mode 100644 index 00000000..961105a8 --- /dev/null +++ b/libsecurity_cdsa_client/lib/dl_standard.cpp @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2000-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. + */ + + +// +// mds_standard - standard-defined MDS record types +// +#include +#include + + +namespace Security { +namespace CssmClient { + + +// +// CDSA Common relation (one record per module) +// +static const char * const commonAttributes[] = { + "PrintName", + "Alias", + NULL +}; +DLCommonFields::DLCommonFields(const char * const * names) + : Record(commonAttributes) +{ + addAttributes(names); +} + +string DLCommonFields::printName() const { return mAttributes[0]; } +string DLCommonFields::alias() const + { return mAttributes[1].size() ? string(mAttributes[1]) : "(no value)"; } + + +// +// The all-record-types pseudo-record +// +AllDLRecords::AllDLRecords() + : DLCommonFields(NULL) +{ } + + +// +// CDSA Generic record attributes +// +static const char * const genericAttributes[] = { + NULL +}; +GenericRecord::GenericRecord() + : DLCommonFields(genericAttributes) +{ +} + + +// +// Apple "Generic Password" records +// +static const char * const genericPasswordAttributes[] = { + // if you find yourself here, you should add the attributes and their functions + NULL +}; +GenericPasswordRecord::GenericPasswordRecord() + : DLCommonFields(genericPasswordAttributes) +{ +} + + +// +// Common key attributes +// +static const char * const keyAttributes[] = { + "KeyClass", + "KeyType", + "KeySizeInBits", + "EffectiveKeySize", + "Label", + "ApplicationTag", + "Permanent", + "Private", + "Modifiable", + "Sensitive", + "AlwaysSensitive", + "Extractable", + "NeverExtractable", + "Encrypt", + "Decrypt", + "Derive", + "Sign", + "Verify", + "Wrap", + "Unwrap", + NULL +}; + +KeyRecord::KeyRecord() + : DLCommonFields(keyAttributes) +{ +} + +uint32 KeyRecord::keyClass() const { return mAttributes[2]; } +uint32 KeyRecord::type() const { return mAttributes[3]; } +uint32 KeyRecord::size() const { return mAttributes[4]; } +uint32 KeyRecord::effectiveSize() const { return mAttributes[5]; } +const CssmData &KeyRecord::label() const { return mAttributes[6]; } +const CssmData &KeyRecord::applicationTag() const { return mAttributes[7]; } +bool KeyRecord::isPermanent() const { return mAttributes[8]; } +bool KeyRecord::isPrivate() const { return mAttributes[9]; } +bool KeyRecord::isModifiable() const { return mAttributes[10]; } +bool KeyRecord::isSensitive() const { return mAttributes[11]; } +bool KeyRecord::wasAlwaysSensitive() const { return mAttributes[12]; } +bool KeyRecord::isExtractable() const { return mAttributes[13]; } +bool KeyRecord::wasNeverExtractable() const { return mAttributes[14]; } +bool KeyRecord::canEncrypt() const { return mAttributes[15]; } +bool KeyRecord::canDecrypt() const { return mAttributes[16]; } +bool KeyRecord::canDerive() const { return mAttributes[17]; } +bool KeyRecord::canSign() const { return mAttributes[18]; } +bool KeyRecord::canVerify() const { return mAttributes[19]; } +bool KeyRecord::canWrap() const { return mAttributes[20]; } +bool KeyRecord::canUnwrap() const { return mAttributes[21]; } + + +// +// Certificate attributes +// +static const char * const certAttributes[] = { + "CertType", + "CertEncoding", + "Subject", + "Issuer", + "SerialNumber", + "SubjectKeyIdentifier", + "PublicKeyHash", + NULL +}; + +X509CertRecord::X509CertRecord() + : DLCommonFields(certAttributes) +{ +} + +CSSM_CERT_TYPE X509CertRecord::type() const { return mAttributes[2]; } +CSSM_CERT_ENCODING X509CertRecord::encoding() const { return mAttributes[3]; } +const CssmData &X509CertRecord::subject() const { return mAttributes[4]; } +const CssmData &X509CertRecord::issuer() const { return mAttributes[5]; } +const CssmData &X509CertRecord::serial() const { return mAttributes[6]; } +const CssmData &X509CertRecord::subjectKeyIdentifier() const { return mAttributes[7]; } +const CssmData &X509CertRecord::publicKeyHash() const { return mAttributes[8]; } + + +// +// UnlockReferral attributes +// +static const char * const unlockReferralAttributes[] = { + "Type", + "DbName", + "DbNetname", + "DbGuid", + "DbSSID", + "DbSSType", + "KeyLabel", + "KeyAppTag", + NULL +}; + +UnlockReferralRecord::UnlockReferralRecord() + : DLCommonFields(unlockReferralAttributes) +{ +} + +uint32 UnlockReferralRecord::type() const { return mAttributes[2]; } +string UnlockReferralRecord::dbName() const { return mAttributes[3]; } +const CssmData &UnlockReferralRecord::dbNetname() const { return mAttributes[4]; } +const Guid &UnlockReferralRecord::dbGuid() const { return mAttributes[5]; } +uint32 UnlockReferralRecord::dbSSID() const { return mAttributes[6]; } +uint32 UnlockReferralRecord::dbSSType() const { return mAttributes[7]; } +const CssmData &UnlockReferralRecord::keyLabel() const { return mAttributes[8]; } +const CssmData &UnlockReferralRecord::keyApplicationTag() const { return mAttributes[9]; } + + +} // end namespace CssmClient +} // end namespace Security diff --git a/libsecurity_cdsa_client/lib/dl_standard.h b/libsecurity_cdsa_client/lib/dl_standard.h new file mode 100644 index 00000000..130fcfaf --- /dev/null +++ b/libsecurity_cdsa_client/lib/dl_standard.h @@ -0,0 +1,167 @@ +/* + * 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. + */ + + +// +// dl_standard - standard-defined DL record types. +// +// These are the C++ record types corresponding to standard and Apple-defined +// DL relations. Note that not all standard fields are included; only those +// of particular interest to the implementation. Feel free to add field functions +// as needed. +// + +#ifndef _H_CDSA_CLIENT_DL_STANDARD +#define _H_CDSA_CLIENT_DL_STANDARD + +#include + + +namespace Security { +namespace CssmClient { + + +// +// All CDSA standard DL schemas contain these fields +// +class DLCommonFields : public Record { +public: + DLCommonFields(const char * const * names); + + string printName() const; + string alias() const; +}; + + +// +// A record type for all records in a DL, with PrintName (only) +// +class AllDLRecords : public DLCommonFields { +public: + AllDLRecords(); +}; + + +// +// The CDSA-standard "generic record" table +// +class GenericRecord : public DLCommonFields { +public: + GenericRecord(); + static const CSSM_DB_RECORDTYPE recordType = CSSM_DL_DB_RECORD_GENERIC; +}; + + +// +// Generic password records (Apple specific) +// +class GenericPasswordRecord : public DLCommonFields { +public: + GenericPasswordRecord(); + static const CSSM_DB_RECORDTYPE recordType = CSSM_DL_DB_RECORD_GENERIC_PASSWORD; +}; + + +// +// Key records +// +class KeyRecord : public DLCommonFields { +public: + KeyRecord(); + static const CSSM_DB_RECORDTYPE recordType = CSSM_DL_DB_RECORD_ALL_KEYS; + + uint32 keyClass() const; + uint32 type() const; + uint32 size() const; + uint32 effectiveSize() const; + const CssmData &label() const; + const CssmData &applicationTag() const; + + // boolean attributes for classification + bool isPermanent() const; + bool isPrivate() const; + bool isModifiable() const; + bool isSensitive() const; + bool wasAlwaysSensitive() const; + bool isExtractable() const; + bool wasNeverExtractable() const; + bool canEncrypt() const; + bool canDecrypt() const; + bool canDerive() const; + bool canSign() const; + bool canVerify() const; + bool canWrap() const; + bool canUnwrap() const; +}; + +class PrivateKeyRecord : public KeyRecord { +public: + static const CSSM_DB_RECORDTYPE recordType = CSSM_DL_DB_RECORD_PRIVATE_KEY; +}; + +class PublicKeyRecord : public KeyRecord { +public: + static const CSSM_DB_RECORDTYPE recordType = CSSM_DL_DB_RECORD_PUBLIC_KEY; +}; + +class SymmetricKeyRecord : public KeyRecord { +public: + static const CSSM_DB_RECORDTYPE recordType = CSSM_DL_DB_RECORD_SYMMETRIC_KEY; +}; + + +// +// X509 Certificate records +// +class X509CertRecord : public DLCommonFields { +public: + X509CertRecord(); + static const CSSM_DB_RECORDTYPE recordType = CSSM_DL_DB_RECORD_X509_CERTIFICATE; + + CSSM_CERT_TYPE type() const; + CSSM_CERT_ENCODING encoding() const; + const CssmData &subject() const; + const CssmData &issuer() const; + const CssmData &serial() const; + const CssmData &subjectKeyIdentifier() const; + const CssmData &publicKeyHash() const; +}; + + +// +// Unlock referral records +// +class UnlockReferralRecord : public DLCommonFields { +public: + UnlockReferralRecord(); + static const CSSM_DB_RECORDTYPE recordType = CSSM_DL_DB_RECORD_UNLOCK_REFERRAL; + + uint32 type() const; + string dbName() const; + const CssmData &dbNetname() const; + const Guid &dbGuid() const; + uint32 dbSSID() const; + uint32 dbSSType() const; + const CssmData &keyLabel() const; + const CssmData &keyApplicationTag() const; +}; + + +} // end namespace CssmClient +} // end namespace Security + +#endif // _H_CDSA_CLIENT_DL_STANDARD diff --git a/libsecurity_cdsa_client/lib/dlclient.cpp b/libsecurity_cdsa_client/lib/dlclient.cpp new file mode 100644 index 00000000..3f1d466c --- /dev/null +++ b/libsecurity_cdsa_client/lib/dlclient.cpp @@ -0,0 +1,878 @@ +/* + * 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. + */ + + +// +// dlclient - client interface to CSSM DLs and their operations +// +#include +#include +#include +#include + +using namespace CssmClient; + + +// blob type for blobs created by these classes -- done so that we can change the formats later +const uint32 kBlobType = 0x1; + + +// +// Abstract classes +// +DbMaker::~DbMaker() +{ /* virtual */ } + +DbCursorMaker::~DbCursorMaker() +{ /* virtual */ } + +DbUniqueRecordMaker::~DbUniqueRecordMaker() +{ /* virtual */ } + + +// +// Manage DL attachments +// +DLImpl::DLImpl(const Guid &guid) : AttachmentImpl(guid, CSSM_SERVICE_DL) +{ +} + +DLImpl::DLImpl(const Module &module) : AttachmentImpl(module, CSSM_SERVICE_DL) +{ +} + +DLImpl::~DLImpl() +{ +} + +void +DLImpl::getDbNames(char **) +{ + CssmError::throwMe(CSSMERR_DL_FUNCTION_NOT_IMPLEMENTED); +} + +void +DLImpl::freeNameList(char **) +{ + CssmError::throwMe(CSSMERR_DL_FUNCTION_NOT_IMPLEMENTED); +} + +DbImpl * +DLImpl::newDb(const char *inDbName, const CSSM_NET_ADDRESS *inDbLocation) +{ + return new DbImpl(DL(this), inDbName, inDbLocation); +} + + +// +// Db (database) +// +DbImpl::DbImpl(const DL &dl, const char *inDbName, const CSSM_NET_ADDRESS *inDbLocation) + : ObjectImpl(dl), mDbName(inDbName, inDbLocation), + mUseNameFromHandle(!inDbName), mNameFromHandle(NULL), + mAccessRequest(CSSM_DB_ACCESS_READ), mAccessCredentials(NULL), + mDefaultCredentials(NULL), mOpenParameters(NULL), mDbInfo(NULL), + mResourceControlContext(NULL) +{ +} + +DbImpl::~DbImpl() +{ + try + { + if (mNameFromHandle) + allocator().free(mNameFromHandle); + deactivate(); + } + catch(...) {} +} + +void +DbImpl::open() +{ + if (!mActive) + { + assert(mDbInfo == nil); + mHandle.DLHandle = dl()->handle(); + check(CSSM_DL_DbOpen(mHandle.DLHandle, mDbName.canonicalName(), dbLocation(), + mAccessRequest, mAccessCredentials, + mOpenParameters, &mHandle.DBHandle)); + mActive = true; + + if (!mAccessCredentials && mDefaultCredentials) + if (const AccessCredentials *creds = mDefaultCredentials->makeCredentials()) + CSSM_DL_Authenticate(handle(), mAccessRequest, creds); // ignore error + } +} + +void +DbImpl::createWithBlob(CssmData &blob) +{ + if (mActive) + CssmError::throwMe(CSSMERR_DL_DATASTORE_ALREADY_EXISTS); + + if (mDbInfo == nil) { + // handle a missing (null) mDbInfo as an all-zero one + static const CSSM_DBINFO nullDbInfo = { }; + mDbInfo = &nullDbInfo; + } + + mHandle.DLHandle = dl()->handle(); + + // create a parameter block for our call to the passthrough + CSSM_APPLE_CSPDL_DB_CREATE_WITH_BLOB_PARAMETERS params; + + params.dbName = mDbName.canonicalName (); + params.dbLocation = dbLocation (); + params.dbInfo = mDbInfo; + params.accessRequest = mAccessRequest; + params.credAndAclEntry = NULL; + params.openParameters = mOpenParameters; + params.blob = &blob; + + check(CSSM_DL_PassThrough (mHandle, CSSM_APPLECSPDL_DB_CREATE_WITH_BLOB, ¶ms, (void**) &mHandle.DBHandle)); +} + +void +DbImpl::create() +{ + if (mActive) + CssmError::throwMe(CSSMERR_DL_DATASTORE_ALREADY_EXISTS); + + if (mDbInfo == nil) { + // handle a missing (null) mDbInfo as an all-zero one + static const CSSM_DBINFO nullDbInfo = { }; + mDbInfo = &nullDbInfo; + } + mHandle.DLHandle = dl()->handle(); + + if (!mResourceControlContext && mAccessCredentials) { + AclFactory::AnyResourceContext ctx(mAccessCredentials); + check(CSSM_DL_DbCreate(mHandle.DLHandle, mDbName.canonicalName(), dbLocation(), + mDbInfo, mAccessRequest, &ctx, + mOpenParameters, &mHandle.DBHandle)); + } else { + check(CSSM_DL_DbCreate(mHandle.DLHandle, mDbName.canonicalName(), dbLocation(), + mDbInfo, mAccessRequest, mResourceControlContext, + mOpenParameters, &mHandle.DBHandle)); + } + mActive = true; +} + +void +DbImpl::close() +{ + if (mActive) + { + check(CSSM_DL_DbClose (mHandle)); + mActive = false; + } +} + +void +DbImpl::activate() +{ + if (!mActive) + { + if (mDbInfo) + create(); + else + open(); + } +} + +void +DbImpl::deactivate() +{ + if (mActive) + { + mActive = false; + close(); + } +} + +void +DbImpl::deleteDb() +{ + // Deactivate so the db gets closed if it was open. + deactivate(); + // This call does not require the receiver to be active. + check(CSSM_DL_DbDelete(dl()->handle(), mDbName.canonicalName(), dbLocation(), + mAccessCredentials)); +} + +void +DbImpl::rename(const char *newName) +{ + // Deactivate so the db gets closed if it was open. + deactivate(); + if (::rename(mDbName.canonicalName(), newName)) + UnixError::throwMe(errno); + + // Change our DbName to reflect this rename. + mDbName = DbName(newName, dbLocation()); +} + +void +DbImpl::authenticate(CSSM_DB_ACCESS_TYPE inAccessRequest, + const CSSM_ACCESS_CREDENTIALS *inAccessCredentials) +{ + if (!mActive) + { + // XXX Could do the same for create but this would require sticking + // inAccessCredentials into mResourceControlContext. + if (!mDbInfo) + { + // We were not yet active. Just do an open. + accessRequest(inAccessRequest); + accessCredentials(inAccessCredentials); + activate(); + return; + } + } + + check(CSSM_DL_Authenticate(handle(), inAccessRequest, inAccessCredentials)); +} + +void +DbImpl::name(char *&outDbName) +{ + check(CSSM_DL_GetDbNameFromHandle(handle(), &outDbName)); +} + +const char * +DbImpl::name() +{ + if (mUseNameFromHandle) + { + if (mNameFromHandle + || !CSSM_DL_GetDbNameFromHandle(handle(), &mNameFromHandle)) + { + return mNameFromHandle; + } + + // We failed to get the name from the handle so use the passed + // in name instead + mUseNameFromHandle = false; + } + + return mDbName.canonicalName(); +} + +void +DbImpl::createRelation(CSSM_DB_RECORDTYPE inRelationID, + const char *inRelationName, + uint32 inNumberOfAttributes, + const CSSM_DB_SCHEMA_ATTRIBUTE_INFO *pAttributeInfo, + uint32 inNumberOfIndexes, + const CSSM_DB_SCHEMA_INDEX_INFO *pIndexInfo) +{ + check(CSSM_DL_CreateRelation(handle(), inRelationID, inRelationName, + inNumberOfAttributes, pAttributeInfo, + inNumberOfIndexes, pIndexInfo)); +} + +void +DbImpl::destroyRelation(CSSM_DB_RECORDTYPE inRelationID) +{ + check(CSSM_DL_DestroyRelation(handle(), inRelationID)); +} + +DbUniqueRecord +DbImpl::insert(CSSM_DB_RECORDTYPE recordType, const CSSM_DB_RECORD_ATTRIBUTE_DATA *attributes, + const CSSM_DATA *data) +{ + DbUniqueRecord uniqueId(Db(this)); + check(CSSM_DL_DataInsert(handle(), recordType, + attributes, + data, uniqueId)); + // Activate uniqueId so CSSM_DL_FreeUniqueRecord() gets called when it goes out of scope. + uniqueId->activate(); + return uniqueId; +} + + +DbUniqueRecord +DbImpl::insertWithoutEncryption(CSSM_DB_RECORDTYPE recordType, const CSSM_DB_RECORD_ATTRIBUTE_DATA *attributes, + CSSM_DATA *data) +{ + DbUniqueRecord uniqueId(Db(this)); + + // fill out the parameters + CSSM_APPLECSPDL_DB_INSERT_WITHOUT_ENCRYPTION_PARAMETERS params; + params.recordType = recordType; + params.attributes = const_cast(attributes); + params.data = *data; + + // for clarity, call the overloaded operator to produce a unique record pointer + CSSM_DB_UNIQUE_RECORD_PTR *uniquePtr = uniqueId; + + // make the call + passThrough (CSSM_APPLECSPDL_DB_INSERT_WITHOUT_ENCRYPTION, ¶ms, (void**) uniquePtr); + + // Activate uniqueId so CSSM_DL_FreeUniqueRecord() gets called when it goes out of scope. + uniqueId->activate(); + return uniqueId; +} + + +// +// Generic Passthrough interface +// +void DbImpl::passThrough(uint32 passThroughId, const void *in, void **out) +{ + check(CSSM_DL_PassThrough(handle(), passThroughId, in, out)); +} + + +// +// Passthrough functions (only implemented by AppleCSPDL). +// +void +DbImpl::lock() +{ + check(CSSM_DL_PassThrough(handle(), CSSM_APPLECSPDL_DB_LOCK, NULL, NULL)); +} + +void +DbImpl::unlock() +{ + check(CSSM_DL_PassThrough(handle(), CSSM_APPLECSPDL_DB_UNLOCK, NULL, NULL)); +} + +void +DbImpl::unlock(const CSSM_DATA &password) +{ + check(CSSM_DL_PassThrough(handle(), CSSM_APPLECSPDL_DB_UNLOCK, &password, NULL)); +} + +void +DbImpl::getSettings(uint32 &outIdleTimeout, bool &outLockOnSleep) +{ + CSSM_APPLECSPDL_DB_SETTINGS_PARAMETERS_PTR settings; + check(CSSM_DL_PassThrough(handle(), CSSM_APPLECSPDL_DB_GET_SETTINGS, + NULL, reinterpret_cast(&settings))); + outIdleTimeout = settings->idleTimeout; + outLockOnSleep = settings->lockOnSleep; + allocator().free(settings); +} + +void +DbImpl::setSettings(uint32 inIdleTimeout, bool inLockOnSleep) +{ + CSSM_APPLECSPDL_DB_SETTINGS_PARAMETERS settings; + settings.idleTimeout = inIdleTimeout; + settings.lockOnSleep = inLockOnSleep; + check(CSSM_DL_PassThrough(handle(), CSSM_APPLECSPDL_DB_SET_SETTINGS, &settings, NULL)); +} + +bool +DbImpl::isLocked() +{ + CSSM_APPLECSPDL_DB_IS_LOCKED_PARAMETERS_PTR params; + check(CSSM_DL_PassThrough(handle(), CSSM_APPLECSPDL_DB_IS_LOCKED, + NULL, reinterpret_cast(¶ms))); + bool isLocked = params->isLocked; + allocator().free(params); + return isLocked; +} + +void +DbImpl::changePassphrase(const CSSM_ACCESS_CREDENTIALS *cred) +{ + CSSM_APPLECSPDL_DB_CHANGE_PASSWORD_PARAMETERS params; + params.accessCredentials = const_cast(cred); + check(CSSM_DL_PassThrough(handle(), CSSM_APPLECSPDL_DB_CHANGE_PASSWORD, ¶ms, NULL)); +} + +void DbImpl::recode(const CSSM_DATA &data, const CSSM_DATA &extraData) +{ + // setup parameters for the recode call + CSSM_APPLECSPDL_RECODE_PARAMETERS params; + params.dbBlob = data; + params.extraData = extraData; + + // do the call + check(CSSM_DL_PassThrough(handle(), CSSM_APPLECSPDL_CSP_RECODE, ¶ms, NULL)); +} + +void DbImpl::copyBlob (CssmData &data) +{ + // do the call + check(CSSM_DL_PassThrough(handle(), CSSM_APPLECSPDL_DB_COPY_BLOB, NULL, (void**) (CSSM_DATA*) &data)); +} + +void DbImpl::setBatchMode(Boolean mode, Boolean rollback) +{ + // + // We need the DL_DB_Handle of the underyling DL in order to use CSSM_APPLEFILEDL_TOGGLE_AUTOCOMMIT + // + CSSM_RETURN result; + CSSM_DL_DB_HANDLE dldbHandleOfUnderlyingDL; + result = CSSM_DL_PassThrough(handle(), + CSSM_APPLECSPDL_DB_GET_HANDLE, + NULL, + (void **)&dldbHandleOfUnderlyingDL); + // + // Now, toggle the autocommit... + // + if ( result == noErr ) + { + CSSM_BOOL modeToUse = !mode; + if (rollback) + { + result = (OSStatus)CSSM_DL_PassThrough(dldbHandleOfUnderlyingDL, + CSSM_APPLEFILEDL_ROLLBACK, NULL, NULL); + } + + result = CSSM_DL_PassThrough(dldbHandleOfUnderlyingDL, + CSSM_APPLEFILEDL_TOGGLE_AUTOCOMMIT, + (void *)(modeToUse), + NULL); + if (!rollback && modeToUse) + result = CSSM_DL_PassThrough(dldbHandleOfUnderlyingDL, + CSSM_APPLEFILEDL_COMMIT, + NULL, + NULL); + } +} + +// +// DbCursorMaker +// +DbCursorImpl * +DbImpl::newDbCursor(const CSSM_QUERY &query, Allocator &allocator) +{ + return new DbDbCursorImpl(Db(this), query, allocator); +} + +DbCursorImpl * +DbImpl::newDbCursor(uint32 capacity, Allocator &allocator) +{ + return new DbDbCursorImpl(Db(this), capacity, allocator); +} + + +// +// Db adapters for AclBearer +// +void DbImpl::getAcl(AutoAclEntryInfoList &aclInfos, const char *selectionTag) const +{ + aclInfos.allocator(allocator()); + check(CSSM_DL_GetDbAcl(const_cast(this)->handle(), + reinterpret_cast(selectionTag), aclInfos, aclInfos)); +} + +void DbImpl::changeAcl(const CSSM_ACL_EDIT &aclEdit, + const CSSM_ACCESS_CREDENTIALS *accessCred) +{ + check(CSSM_DL_ChangeDbAcl(handle(), AccessCredentials::needed(accessCred), &aclEdit)); +} + +void DbImpl::getOwner(AutoAclOwnerPrototype &owner) const +{ + owner.allocator(allocator()); + check(CSSM_DL_GetDbOwner(const_cast(this)->handle(), owner)); +} + +void DbImpl::changeOwner(const CSSM_ACL_OWNER_PROTOTYPE &newOwner, + const CSSM_ACCESS_CREDENTIALS *accessCred) +{ + check(CSSM_DL_ChangeDbOwner(handle(), + AccessCredentials::needed(accessCred), &newOwner)); +} + +void DbImpl::defaultCredentials(DefaultCredentialsMaker *maker) +{ + mDefaultCredentials = maker; +} + + +// +// Abstract DefaultCredentialsMakers +// +DbImpl::DefaultCredentialsMaker::~DefaultCredentialsMaker() +{ /* virtual */ } + + +// +// Db adapters for DLAccess +// +CSSM_HANDLE Db::dlGetFirst(const CSSM_QUERY &query, CSSM_DB_RECORD_ATTRIBUTE_DATA &attributes, + CSSM_DATA *data, CSSM_DB_UNIQUE_RECORD *&id) +{ + CSSM_HANDLE result; + switch (CSSM_RETURN rc = CSSM_DL_DataGetFirst(handle(), &query, &result, &attributes, data, &id)) { + case CSSM_OK: + return result; + case CSSMERR_DL_ENDOFDATA: + return CSSM_INVALID_HANDLE; + default: + CssmError::throwMe(rc); + return CSSM_INVALID_HANDLE; // placebo + } +} + +bool Db::dlGetNext(CSSM_HANDLE query, CSSM_DB_RECORD_ATTRIBUTE_DATA &attributes, + CSSM_DATA *data, CSSM_DB_UNIQUE_RECORD *&id) +{ + CSSM_RETURN rc = CSSM_DL_DataGetNext(handle(), query, &attributes, data, &id); + switch (rc) { + case CSSM_OK: + return true; + case CSSMERR_DL_ENDOFDATA: + return false; + default: + CssmError::throwMe(rc); + return false; // placebo + } +} + +void Db::dlAbortQuery(CSSM_HANDLE query) +{ + CssmError::check(CSSM_DL_DataAbortQuery(handle(), query)); +} + +void Db::dlFreeUniqueId(CSSM_DB_UNIQUE_RECORD *id) +{ + CssmError::check(CSSM_DL_FreeUniqueRecord(handle(), id)); +} + +void Db::dlDeleteRecord(CSSM_DB_UNIQUE_RECORD *id) +{ + CssmError::check(CSSM_DL_DataDelete(handle(), id)); +} + +Allocator &Db::allocator() +{ + return Object::allocator(); +} + + +// +// DbUniqueRecordMaker +// +DbUniqueRecordImpl * +DbImpl::newDbUniqueRecord() +{ + return new DbUniqueRecordImpl(Db(this)); +} + + +// +// Utility methods +// +DLDbIdentifier +DbImpl::dlDbIdentifier() +{ + // Always use the same dbName and dbLocation that were passed in during + // construction + return DLDbIdentifier(dl()->subserviceUid(), mDbName.canonicalName(), dbLocation()); +} + + +// +// DbDbCursorImpl +// +DbDbCursorImpl::DbDbCursorImpl(const Db &db, const CSSM_QUERY &query, Allocator &allocator) +: DbCursorImpl(db, query, allocator), mResultsHandle(CSSM_INVALID_HANDLE) +{ +} + +DbDbCursorImpl::DbDbCursorImpl(const Db &db, uint32 capacity, Allocator &allocator) +: DbCursorImpl(db, capacity, allocator), mResultsHandle(CSSM_INVALID_HANDLE) +{ +} + +DbDbCursorImpl::~DbDbCursorImpl() +{ + try + { + deactivate(); + } + catch(...) {} +} + +bool +DbDbCursorImpl::next(DbAttributes *attributes, ::CssmDataContainer *data, DbUniqueRecord &uniqueId) +{ + if (attributes) + attributes->deleteValues(); + + if (data) + data->clear(); + + CSSM_RETURN result; + Db db(database()); + DbUniqueRecord unique(db); + if (!mActive) + { + // ask the CSP/DL if the requested record type exists + CSSM_BOOL boolResult; + CSSM_DL_PassThrough(db->handle(), CSSM_APPLECSPDL_DB_RELATION_EXISTS, &RecordType, (void**) &boolResult); + if (!boolResult) + { + if (data != NULL) + { + data->invalidate(); + } + + return false; + } + + result = CSSM_DL_DataGetFirst(db->handle(), + this, + &mResultsHandle, + attributes, + data, + unique); + if (result == CSSM_OK) + mActive = true; + else if (data != NULL) + data->invalidate (); + } + else + { + result = CSSM_DL_DataGetNext(db->handle(), + mResultsHandle, + attributes, + data, + unique); + + if (result != CSSM_OK && data != NULL) + { + data->invalidate (); + } + } + + if (result != CSSM_OK && attributes != NULL) + { + attributes->invalidate(); + } + + if (result == CSSMERR_DL_ENDOFDATA) + { + mActive = false; + return false; + } + + check(result); + + // Activate uniqueId so CSSM_DL_FreeUniqueRecord() gets called when it goes out of scope. + unique->activate(); + uniqueId = unique; + return true; +} + +void +DbDbCursorImpl::activate() +{ +} + +void +DbDbCursorImpl::deactivate() +{ + if (mActive) + { + mActive = false; + check(CSSM_DL_DataAbortQuery(database()->handle(), mResultsHandle)); + } +} + + +// +// DbCursorImpl +// +DbCursorImpl::DbCursorImpl(const Object &parent, const CSSM_QUERY &query, Allocator &allocator) : +ObjectImpl(parent), CssmAutoQuery(query, allocator) +{ +} + +DbCursorImpl::DbCursorImpl(const Object &parent, uint32 capacity, Allocator &allocator) : +ObjectImpl(parent), CssmAutoQuery(capacity, allocator) +{ +} + +Allocator & +DbCursorImpl::allocator() const +{ + return ObjectImpl::allocator(); +} + +void +DbCursorImpl::allocator(Allocator &alloc) +{ + ObjectImpl::allocator(alloc); +} + + +// +// DbUniqueRecord +// +DbUniqueRecordImpl::DbUniqueRecordImpl(const Db &db) : ObjectImpl(db), mDestroyID (false) +{ +} + +DbUniqueRecordImpl::~DbUniqueRecordImpl() +{ + try + { + if (mDestroyID) + { + allocator ().free (mUniqueId); + } + + deactivate(); + } + catch(...) {} +} + +void +DbUniqueRecordImpl::deleteRecord() +{ + check(CSSM_DL_DataDelete(database()->handle(), mUniqueId)); +} + +void +DbUniqueRecordImpl::modify(CSSM_DB_RECORDTYPE recordType, + const CSSM_DB_RECORD_ATTRIBUTE_DATA *attributes, + const CSSM_DATA *data, + CSSM_DB_MODIFY_MODE modifyMode) +{ + check(CSSM_DL_DataModify(database()->handle(), recordType, mUniqueId, + attributes, + data, modifyMode)); +} + +void +DbUniqueRecordImpl::modifyWithoutEncryption(CSSM_DB_RECORDTYPE recordType, + const CSSM_DB_RECORD_ATTRIBUTE_DATA *attributes, + const CSSM_DATA *data, + CSSM_DB_MODIFY_MODE modifyMode) +{ + // fill out the parameters + CSSM_APPLECSPDL_DB_MODIFY_WITHOUT_ENCRYPTION_PARAMETERS params; + params.recordType = recordType; + params.uniqueID = mUniqueId; + params.attributes = const_cast(attributes); + params.data = (CSSM_DATA*) data; + params.modifyMode = modifyMode; + + // modify the data + check(CSSM_DL_PassThrough(database()->handle(), + CSSM_APPLECSPDL_DB_MODIFY_WITHOUT_ENCRYPTION, + ¶ms, + NULL)); +} + +void +DbUniqueRecordImpl::get(DbAttributes *attributes, + ::CssmDataContainer *data) +{ + if (attributes) + attributes->deleteValues(); + + if (data) + data->clear(); + + // @@@ Fix the allocators for attributes and data. + CSSM_RETURN result; + result = CSSM_DL_DataGetFromUniqueRecordId(database()->handle(), mUniqueId, + attributes, + data); + + if (result != CSSM_OK) + { + if (attributes) + attributes->invalidate(); + if (data != NULL) // the data returned is no longer valid + { + data->invalidate (); + } + } + + check(result); +} + +void +DbUniqueRecordImpl::getWithoutEncryption(DbAttributes *attributes, + ::CssmDataContainer *data) +{ + if (attributes) + attributes->deleteValues(); + + if (data) + data->clear(); + + // @@@ Fix the allocators for attributes and data. + CSSM_RETURN result; + + // make the parameter block + CSSM_APPLECSPDL_DB_GET_WITHOUT_ENCRYPTION_PARAMETERS params; + params.uniqueID = mUniqueId; + params.attributes = attributes; + + // get the data + ::CssmDataContainer recordData; + result = CSSM_DL_PassThrough(database()->handle(), CSSM_APPLECSPDL_DB_GET_WITHOUT_ENCRYPTION, ¶ms, + (void**) data); + check (result); +} + +void +DbUniqueRecordImpl::activate() +{ + mActive = true; +} + +void +DbUniqueRecordImpl::deactivate() +{ + if (mActive) + { + mActive = false; + check(CSSM_DL_FreeUniqueRecord(database()->handle(), mUniqueId)); + } +} + +void +DbUniqueRecordImpl::getRecordIdentifier(CSSM_DATA &data) +{ + check(CSSM_DL_PassThrough(database()->handle(), CSSM_APPLECSPDL_DB_GET_RECORD_IDENTIFIER, + mUniqueId, (void**) &data)); +} + +void DbUniqueRecordImpl::setUniqueRecordPtr(CSSM_DB_UNIQUE_RECORD_PTR uniquePtr) +{ + // clone the record + mUniqueId = (CSSM_DB_UNIQUE_RECORD_PTR) allocator ().malloc (sizeof (CSSM_DB_UNIQUE_RECORD)); + *mUniqueId = *uniquePtr; + mDestroyID = true; +} + +// +// DbAttributes +// +DbAttributes::DbAttributes() +: CssmAutoDbRecordAttributeData(0, Allocator::standard(), Allocator::standard()) +{ +} + +DbAttributes::DbAttributes(const Db &db, uint32 capacity, Allocator &allocator) +: CssmAutoDbRecordAttributeData(capacity, db->allocator(), allocator) +{ +} diff --git a/libsecurity_cdsa_client/lib/dlclient.h b/libsecurity_cdsa_client/lib/dlclient.h new file mode 100644 index 00000000..ae8e0787 --- /dev/null +++ b/libsecurity_cdsa_client/lib/dlclient.h @@ -0,0 +1,556 @@ +/* + * 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. + */ + + +// +// dlclient - client interface to CSSM DLs and their operations +// + +#ifndef _H_CDSA_CLIENT_DLCLIENT +#define _H_CDSA_CLIENT_DLCLIENT 1 + +#include +#include +#include +#include +#include +#include +#include + + +namespace Security +{ + +namespace CssmClient +{ + +#define CSSM_DB_ATTR(ATTR) ATTR +#define CSSM_DB_ATTR_SCHEMA(ATTR) ATTR ## Schema + +#define CSSM_DB_INDEX(ATTR) ATTR ## Index +#define CSSM_DB_UNIQUE(ATTR) ATTR ## Unique + +// +// Helper macro for declaring and defining a Db index unique and non-unique attributes +// +#define CSSM_DB_INDEX_DECL(ATTR) static const CSSM_DB_INDEX_INFO CSSM_DB_INDEX(ATTR) +#define CSSM_DB_UNIQUE_DECL(ATTR) static const CSSM_DB_INDEX_INFO CSSM_DB_UNIQUE(ATTR) + + +// +// Use this macro for defining a non-unique attribute +// +#define CSSM_DB_INDEX_DEF(ATTR) \ +const CSSM_DB_INDEX_INFO CSSM_DB_INDEX(ATTR) = \ +{ \ + CSSM_DB_INDEX_NONUNIQUE, \ + CSSM_DB_INDEX_ON_ATTRIBUTE, \ + CSSM_DB_ATTR(ATTR) \ +} + +// +// Use this macro for defining a unique attribute + +// +#define CSSM_DB_UNIQUE_DEF(ATTR) \ +const CSSM_DB_INDEX_INFO CSSM_DB_UNIQUE(ATTR) = \ +{ \ + CSSM_DB_INDEX_UNIQUE, \ + CSSM_DB_INDEX_ON_ATTRIBUTE, \ + CSSM_DB_ATTR(ATTR) \ +} + + + +// +// Helper macro for declaring and defining a Db schema attributes +// Use this macro in your header to declare each attribute you require. +// +#define CSSM_DB_ATTR_DECL(ATTR) \ +static const CSSM_DB_ATTRIBUTE_INFO CSSM_DB_ATTR(ATTR); \ +static const CSSM_DB_SCHEMA_ATTRIBUTE_INFO CSSM_DB_ATTR_SCHEMA(ATTR) + +// +// Don't directly use this macro use one of the below instead. +// +#define CSSM_DB_ATTR_DEFINE_SCHEMA(ATTR, INTEGER, NAME, OID_LEN, OID_DATA, VALUETYPE) \ +const CSSM_DB_SCHEMA_ATTRIBUTE_INFO CSSM_DB_ATTR_SCHEMA(ATTR) = \ +{ \ + INTEGER, \ + NAME, \ + { OID_LEN, OID_DATA }, \ + CSSM_DB_ATTRIBUTE_FORMAT_ ## VALUETYPE \ +} + + +// +// Use one of the following macros to defined each declared attribute required by your application. +// +// +// Use this macro to define attributes which are looked up by integer AttributeID. +// +#define CSSM_DB_INTEGER_ATTR(ATTR, INTEGER, NAME, OID_LEN, OID_DATA, VALUETYPE) \ +const CSSM_DB_ATTRIBUTE_INFO ATTR = \ +{ \ + CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER, \ + {(char *)INTEGER}, \ + CSSM_DB_ATTRIBUTE_FORMAT_ ## VALUETYPE \ +};\ +\ +CSSM_DB_ATTR_DEFINE_SCHEMA(ATTR, INTEGER, NAME, OID_LEN, OID_DATA, VALUETYPE) + +// +// Use this macro to define attributes which are looked up by string AttributeName. +// +#define CSSM_DB_NAME_ATTR(ATTR, INTEGER, NAME, OID_LEN, OID_DATA, VALUETYPE) \ +const CSSM_DB_ATTRIBUTE_INFO ATTR = \ +{ \ + CSSM_DB_ATTRIBUTE_NAME_AS_STRING, \ + {NAME}, \ + CSSM_DB_ATTRIBUTE_FORMAT_ ## VALUETYPE \ +};\ +\ +CSSM_DB_ATTR_DEFINE_SCHEMA(ATTR, INTEGER, NAME, OID_LEN, OID_DATA, VALUETYPE) + +// +// Use this macro to define attributes which are looked up by OID AttributeNameID. +// XXX This does not work yet. +// +#define CSSM_DB_OID_ATTR(ATTR, INTEGER, NAME, OID_LEN, OID_DATA, VALUETYPE) \ +const CSSM_DB_ATTRIBUTE_INFO ATTR = \ +{ \ + CSSM_DB_ATTRIBUTE_NAME_AS_OID, \ + {{OID_LEN, OID_DATA}}, \ + CSSM_DB_ATTRIBUTE_FORMAT_ ## VALUETYPE \ +};\ +\ +CSSM_DB_ATTR_DEFINE_SCHEMA(ATTR, INTEGER, NAME, OID_LEN, OID_DATA, VALUETYPE) + + +// +// Use this macro to define attributes which are part of the primary key. +// +#define CSSM_DB_PRIMARKEY_ATTR(ATTR, NAME) \ +const CSSM_DB_ATTRIBUTE_INFO ATTR = \ +{ \ + CSSM_DB_INDEX_UNIQUE, \ + CSSM_DB_INDEX_ON_ATTRIBUTE, \ + CSSM_DB_ATTRIBUTE_FORMAT_ ## VALUETYPE \ +};\ +\ +CSSM_DB_ATTR_DEFINE_SCHEMA(ATTR, INTEGER, NAME, OID_LEN, OID_DATA, VALUETYPE) + + + +// +// Maker interfaces used by various Impl objects +// + +// DbMaker -- someone who can create a new DbImpl. +class DbImpl; +class DbMaker +{ +public: + virtual ~DbMaker(); + virtual DbImpl *newDb(const char *inDbName, const CSSM_NET_ADDRESS *inDbLocation) = 0; +}; + +// DbCursorMaker -- someone who can create a new DbCursorImpl. +class DbCursorImpl; +class DbCursorMaker +{ +public: + virtual ~DbCursorMaker(); + virtual DbCursorImpl *newDbCursor(const CSSM_QUERY &query, Allocator &allocator) = 0; + virtual DbCursorImpl *newDbCursor(uint32 capacity, Allocator &allocator) = 0; +}; + +// DbUniqueRecordMaker -- someone who can create a new DbUniqueRecordImpl. +class DbUniqueRecordImpl; +class DbUniqueRecordMaker +{ +public: + virtual ~DbUniqueRecordMaker(); + virtual DbUniqueRecordImpl *newDbUniqueRecord() = 0; +}; + + +// +// A DL attachment +// +class DLImpl : public AttachmentImpl, public DbMaker +{ +public: + DLImpl(const Guid &guid); + DLImpl(const Module &module); + virtual ~DLImpl(); + + virtual void getDbNames(char **); + virtual void freeNameList(char **); + + // DbMaker + virtual DbImpl *newDb(const char *inDbName, const CSSM_NET_ADDRESS *inDbLocation); +private: +}; + +class DL : public Attachment +{ +public: + typedef DLImpl Impl; + + explicit DL(Impl *impl) : Attachment(impl) {} + DL() : Attachment(NULL) {} + DL(const Guid &guid) : Attachment(new Impl(guid)) {} + DL(const Module &module) : Attachment(new Impl(module)) {} + + Impl *operator ->() const { return &impl(); } + Impl &operator *() const { return impl(); } + + // Conversion to DbMaker. + operator DbMaker &() const { return impl(); } +}; + + +class DbAttributes; +class DbUniqueRecord; +class Db; + + +// +// A CSSM_DLDB handle. +// Dbs always belong to DLs (DL attachments) +// +class DbImpl : public ObjectImpl, public AclBearer, + public DbCursorMaker, public DbUniqueRecordMaker +{ +public: + DbImpl(const DL &dl, const char *inDbName = NULL, const CSSM_NET_ADDRESS *inDbLocation = NULL); + virtual ~DbImpl(); + + DL dl() const { return parent

    (); } + Module module() const { return dl()->module(); } + + virtual void open(); + virtual void create(); + virtual void createWithBlob (CssmData &blob); + virtual void close(); + virtual void deleteDb(); + virtual void rename(const char *newName); + virtual void authenticate(CSSM_DB_ACCESS_TYPE inAccessRequest, + const CSSM_ACCESS_CREDENTIALS *inAccessCredentials); + virtual void name(char *&outName); // CSSM_DL_GetDbNameFromHandle() + + virtual void createRelation(CSSM_DB_RECORDTYPE inRelationID, + const char *inRelationName, + uint32 inNumberOfAttributes, + const CSSM_DB_SCHEMA_ATTRIBUTE_INFO *pAttributeInfo, + uint32 inNumberOfIndexes, + const CSSM_DB_SCHEMA_INDEX_INFO *pIndexInfo); + virtual void destroyRelation(CSSM_DB_RECORDTYPE inRelationID); + + virtual DbUniqueRecord insert(CSSM_DB_RECORDTYPE recordType, + const CSSM_DB_RECORD_ATTRIBUTE_DATA *attributes, + const CSSM_DATA *data); + + virtual DbUniqueRecord insertWithoutEncryption(CSSM_DB_RECORDTYPE recordType, + const CSSM_DB_RECORD_ATTRIBUTE_DATA *attributes, + CSSM_DATA *data); + + const CSSM_DL_DB_HANDLE &handle() { activate(); return mHandle; } + + const DbName &dbName() { return mDbName; } + void dbName(const DbName &dbName) { mDbName = dbName; } + + // Attempt to get a (cached) name from CSSM_DL_GetDbNameFromHandle(), falls + // back to the name passed in to the constructor if this fails. + const char *name(); + + const CSSM_NET_ADDRESS *dbLocation() const { return mDbName.dbLocation(); } + + CSSM_DB_ACCESS_TYPE accessRequest() const { return mAccessRequest; } + void accessRequest(CSSM_DB_ACCESS_TYPE inAccessRequest) + { mAccessRequest = inAccessRequest; } + + const CSSM_ACCESS_CREDENTIALS *accessCredentials() const + { return mAccessCredentials; } + void accessCredentials(const CSSM_ACCESS_CREDENTIALS *inAccessCredentials) + { mAccessCredentials = inAccessCredentials; } + + const void *openParameters() const { return mOpenParameters; } + void openParameters(const void *inOpenParameters) + { mOpenParameters = inOpenParameters; } + + const CSSM_DBINFO *dbInfo() const { return mDbInfo; } + void dbInfo(const CSSM_DBINFO *inDbInfo) { mDbInfo = inDbInfo; } + + const ResourceControlContext *resourceControlContext() const + { return mResourceControlContext; } + void resourceControlContext(const CSSM_RESOURCE_CONTROL_CONTEXT *inResourceControlContext) + { mResourceControlContext = ResourceControlContext::overlay(inResourceControlContext); } + + void passThrough(uint32 passThroughId, const void *in, void **out = NULL); + + template + void passThrough(uint32 passThroughId, const TIn *in, TOut *out = NULL) + { passThrough(passThroughId, (const void *)in, (void **)out); } + + // Passthrough functions (only implemented by AppleCSPDL). + virtual void lock(); + virtual void unlock(); + virtual void unlock(const CSSM_DATA &password); + virtual void getSettings(uint32 &outIdleTimeout, bool &outLockOnSleep); + virtual void setSettings(uint32 inIdleTimeout, bool inLockOnSleep); + virtual bool isLocked(); + virtual void changePassphrase(const CSSM_ACCESS_CREDENTIALS *cred); + virtual void recode(const CSSM_DATA &data, const CSSM_DATA &extraData); + virtual void copyBlob(CssmData &data); + virtual void setBatchMode(Boolean mode, Boolean rollback); + + // Utility methods + + // Always use the dbName and dbLocation that were passed in during + // construction. + virtual DLDbIdentifier dlDbIdentifier(); + + // DbCursorMaker + virtual DbCursorImpl *newDbCursor(const CSSM_QUERY &query, Allocator &allocator); + virtual DbCursorImpl *newDbCursor(uint32 capacity, Allocator &allocator); + + // DbUniqueRecordMaker + virtual DbUniqueRecordImpl *newDbUniqueRecord(); + + // Acl manipulation + void getAcl(AutoAclEntryInfoList &aclInfos, const char *selectionTag = NULL) const; + void changeAcl(const CSSM_ACL_EDIT &aclEdit, + const CSSM_ACCESS_CREDENTIALS *accessCred); + + // Acl owner manipulation + void getOwner(AutoAclOwnerPrototype &owner) const; + void changeOwner(const CSSM_ACL_OWNER_PROTOTYPE &newOwner, + const CSSM_ACCESS_CREDENTIALS *accessCred = NULL); + + // default-credential hook + class DefaultCredentialsMaker { + public: + virtual ~DefaultCredentialsMaker(); + virtual const AccessCredentials *makeCredentials() = 0; + }; + + void defaultCredentials(DefaultCredentialsMaker *maker); // NULL to turn off + + void activate(); + +protected: + void deactivate(); + +private: + CSSM_DL_DB_HANDLE mHandle; // CSSM DLDB handle + + DbName mDbName; + bool mUseNameFromHandle; // false if CSSM_DL_GetDbNameFromHandle failed + char *mNameFromHandle; // Cached CSSM_DL_GetDbNameFromHandle result. + CSSM_DB_ACCESS_TYPE mAccessRequest; + const CSSM_ACCESS_CREDENTIALS *mAccessCredentials; + DefaultCredentialsMaker *mDefaultCredentials; + const void *mOpenParameters; + + // Arguments to create + const CSSM_DBINFO *mDbInfo; + const ResourceControlContext *mResourceControlContext; +}; + + +class Db : public Object, public DLAccess +{ +public: + typedef DbImpl Impl; + typedef Impl::DefaultCredentialsMaker DefaultCredentialsMaker; + + explicit Db(Impl *impl) : Object(impl) {} + Db() : Object(NULL) {} + Db(DbMaker &maker, const char *inDbName, const CSSM_NET_ADDRESS *inDbLocation = NULL) + : Object(maker.newDb(inDbName, inDbLocation)) {} + + Impl *operator ->() const { return &impl(); } + Impl &operator *() const { return impl(); } + + // Conversion to DbCursorMaker. + operator DbCursorMaker &() const { return impl(); } + // Conversion to DbUniqueRecordMaker. + operator DbUniqueRecordMaker &() const { return impl(); } + + const CSSM_DL_DB_HANDLE &handle() { return impl().handle(); } + +protected: + // DLAccess adapters + CSSM_HANDLE dlGetFirst(const CSSM_QUERY &query, + CSSM_DB_RECORD_ATTRIBUTE_DATA &attributes, CSSM_DATA *data, + CSSM_DB_UNIQUE_RECORD *&id); + bool dlGetNext(CSSM_HANDLE handle, + CSSM_DB_RECORD_ATTRIBUTE_DATA &attributes, CSSM_DATA *data, + CSSM_DB_UNIQUE_RECORD *&id); + void dlAbortQuery(CSSM_HANDLE handle); + void dlFreeUniqueId(CSSM_DB_UNIQUE_RECORD *id); + void dlDeleteRecord(CSSM_DB_UNIQUE_RECORD *id); + Allocator &allocator(); +}; + +// +// DbCursor +// + +// This class is still abstract. You must subclass it in order to be able to instantiate an instance. +class DbCursorImpl : public ObjectImpl, public CssmAutoQuery +{ +public: + DbCursorImpl(const Object &parent, const CSSM_QUERY &query, Allocator &allocator); + DbCursorImpl(const Object &parent, uint32 capacity, Allocator &allocator); + + virtual Allocator &allocator() const; + virtual void allocator(Allocator &alloc); + + virtual bool next(DbAttributes *attributes, ::CssmDataContainer *data, DbUniqueRecord &uniqueId) = 0; + void abort() { deactivate(); } +}; + +class DbCursor : public Object +{ +public: + typedef DbCursorImpl Impl; + + explicit DbCursor(Impl *impl) : Object(impl) {} + DbCursor() : Object(NULL) {} + DbCursor(DbCursorMaker &maker, const CSSM_QUERY &query, + Allocator &allocator = Allocator::standard()) + : Object(maker.newDbCursor(query, allocator)) {} + DbCursor(DbCursorMaker &maker, uint32 capacity = 0, + Allocator &allocator = Allocator::standard()) + : Object(maker.newDbCursor(capacity, allocator)) {} + + Impl *operator ->() const { return &impl(); } + Impl &operator *() const { return impl(); } +}; + + +// +// DbUniqueRecord +// +class DbUniqueRecordImpl : public ObjectImpl +{ +public: + DbUniqueRecordImpl(const Db &db); + virtual ~DbUniqueRecordImpl(); + + virtual void deleteRecord(); + virtual void modify(CSSM_DB_RECORDTYPE recordType, + const CSSM_DB_RECORD_ATTRIBUTE_DATA *attributes, + const CSSM_DATA *data, + CSSM_DB_MODIFY_MODE modifyMode); + + virtual void modifyWithoutEncryption (CSSM_DB_RECORDTYPE recordType, + const CSSM_DB_RECORD_ATTRIBUTE_DATA *attributes, + const CSSM_DATA *data, + CSSM_DB_MODIFY_MODE modifyMode); + + virtual void get(DbAttributes *attributes, ::CssmDataContainer *data); + + virtual void getWithoutEncryption(DbAttributes *attributes, ::CssmDataContainer *data); + + Db database() const { return parent(); } + + void free() { deactivate(); } + + // Client must call activate() after calling this function if mUniqueId is successfully set. + operator CSSM_DB_UNIQUE_RECORD_PTR *() { if (mActive) free(); return &mUniqueId; } + + operator CSSM_DB_UNIQUE_RECORD *() { return mUniqueId; } + operator const CSSM_DB_UNIQUE_RECORD *() const { return mUniqueId; } + + void activate(); + + void getRecordIdentifier(CSSM_DATA &data); + + void setUniqueRecordPtr (CSSM_DB_UNIQUE_RECORD_PTR uniquePtr); // because cast overloading is evil! + +protected: + void deactivate(); + + CSSM_DB_UNIQUE_RECORD_PTR mUniqueId; + bool mDestroyID; +}; + +class DbUniqueRecord : public Object +{ +public: + typedef DbUniqueRecordImpl Impl; + + explicit DbUniqueRecord(Impl *impl) : Object(impl) {} + DbUniqueRecord() : Object(NULL) {} + DbUniqueRecord(DbUniqueRecordMaker &maker) : Object(maker.newDbUniqueRecord()) {} + + Impl *operator ->() { return &impl(); } + Impl &operator *() { return impl(); } + const Impl &operator *() const { return impl(); } + + // Conversion operators must be here. + + // Client must activate after calling this function if mUniqueId is successfully set. + operator CSSM_DB_UNIQUE_RECORD_PTR *() { return **this; } + + operator CSSM_DB_UNIQUE_RECORD *() { return **this; } + operator const CSSM_DB_UNIQUE_RECORD *() const { return **this; } +}; + + +// +// DbAttributes +// +class DbAttributes : public CssmAutoDbRecordAttributeData +{ +public: + DbAttributes(); + DbAttributes(const Db &db, uint32 capacity = 0, Allocator &allocator = Allocator::standard()); +}; + + +// +// DbDbCursor -- concrete subclass of DbCursorImpl for querying Db's +// +class DbDbCursorImpl : public DbCursorImpl +{ +public: + DbDbCursorImpl(const Db &db, const CSSM_QUERY &query, Allocator &allocator); + DbDbCursorImpl(const Db &db, uint32 capacity, Allocator &allocator); + virtual ~DbDbCursorImpl(); + + bool next(DbAttributes *attributes, ::CssmDataContainer *data, DbUniqueRecord &uniqueId); + +protected: + Db database() { return parent(); } + + void activate(); + void deactivate(); + +private: + CSSM_HANDLE mResultsHandle; +}; + +} // end namespace CssmClient + +} // end namespace Security + +#endif // _H_CDSA_CLIENT_DLCLIENT diff --git a/libsecurity_cdsa_client/lib/dlclientpriv.cpp b/libsecurity_cdsa_client/lib/dlclientpriv.cpp new file mode 100644 index 00000000..560c9db0 --- /dev/null +++ b/libsecurity_cdsa_client/lib/dlclientpriv.cpp @@ -0,0 +1,35 @@ +/* + * 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. + */ + + +// +// dlclientpriv - private client interface to CSSM DLs +// +// This file implements those (non-virtual) methods of Db/DbImpl that +// require additional libraries to function. The OS X linker is too inept +// to eliminate unused functions peacefully (as of OS X 10.3/XCode 1.5 anyway). +// +#include +#include +#include + +using namespace CssmClient; + + +// +// Currently empty. +// diff --git a/libsecurity_cdsa_client/lib/dliterators.cpp b/libsecurity_cdsa_client/lib/dliterators.cpp new file mode 100644 index 00000000..18617f83 --- /dev/null +++ b/libsecurity_cdsa_client/lib/dliterators.cpp @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2000-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. + */ + + +// +// mdsclient - friendly interface to CDSA MDS API +// +#include + + +namespace Security { +namespace CssmClient { + + +// +// DLAccess gets a virtual destructor just in case +// +DLAccess::~DLAccess() +{ } + + +// +// Basic Record objects (abstract) +// +Record::Record(const char * const * names) + : CssmAutoData(Allocator::standard(Allocator::sensitive)) +{ + addAttributes(names); +} + +void Record::addAttributes(const char * const * name) +{ + if (name) + while (*name) + mAttributes.add(CssmDbAttributeInfo(*name++)); +} + +Record::~Record() +{ } + + +// +// Tables and their components (non-template common features) +// +TableBase::TableBase(DLAccess &source, CSSM_DB_RECORDTYPE type, bool getData /* = true */) + : database(source), mRecordType(type), mGetData(getData) +{ +} + +TableBase::Handle::~Handle() +{ + if (query) + mAccess->dlAbortQuery(query); +} + +TableBase::Uid::~Uid() +{ + if (uid) + mAccess->dlFreeUniqueId(uid); +} + +TableBase::Iterator::Iterator(DLAccess *ac, CSSM_HANDLE query, + CSSM_DB_UNIQUE_RECORD *id, Record *record, bool getData) + : mAccess(ac), mQuery(new Handle(ac, query)), + mUid(new Uid(ac, id)), mRecord(record), mGetData(getData) +{ } + + +void TableBase::Iterator::advance(Record *fill) +{ + RefPointer newRecord = fill; // hold it safely + CSSM_DB_UNIQUE_RECORD *id; + CssmAutoData data(mAccess->allocator()); + if (mAccess->dlGetNext(mQuery->query, newRecord->attributes(), + mGetData ? &data.get() : NULL, id)) { + if (mGetData) + newRecord->recordData() = data; + mUid = new Uid(mAccess, id); + mRecord = newRecord; + } else { + mQuery->query = CSSM_INVALID_HANDLE; // was automatically aborted + // release all iterator resources and make me == end() + mQuery = NULL; + mUid = NULL; + mRecord = NULL; + } +} + + +uint32 TableBase::erase(const CSSM_QUERY &query) +{ + CSSM_DB_UNIQUE_RECORD *id; + CssmDbRecordAttributeData noAttributes; + CSSM_HANDLE handle = database.dlGetFirst(query, noAttributes, NULL, id); + if (handle == CSSM_INVALID_HANDLE) + return 0; // no match, nothing erased + uint32 count = 0; + do { + database.dlDeleteRecord(id); + count++; + database.dlFreeUniqueId(id); + } while (database.dlGetNext(handle, noAttributes, NULL, id)); + return count; +} + +uint32 TableBase::erase(const Query &query) +{ + return erase(query.cssmQuery()); +} + + +} // end namespace CssmClient +} // end namespace Security diff --git a/libsecurity_cdsa_client/lib/dliterators.h b/libsecurity_cdsa_client/lib/dliterators.h new file mode 100644 index 00000000..e93b6c13 --- /dev/null +++ b/libsecurity_cdsa_client/lib/dliterators.h @@ -0,0 +1,272 @@ +/* + * Copyright (c) 2000-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. + */ + + +// +// dliterators - DL/MDS table access as C++ iterators +// +// This is currently an almost read-only implementation. +// (You can erase but you can't create or modify.) +// +#ifndef _H_CDSA_CLIENT_DLITERATORS +#define _H_CDSA_CLIENT_DLITERATORS + +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace Security { +namespace CssmClient { + + +// +// An abstract interface to a (partial) DLDb-style object. +// This is a particular (open) database that you can perform CSSM database +// operations on. +// +class DLAccess { +public: + virtual ~DLAccess(); + + virtual CSSM_HANDLE dlGetFirst(const CSSM_QUERY &query, + CSSM_DB_RECORD_ATTRIBUTE_DATA &attributes, CSSM_DATA *data, + CSSM_DB_UNIQUE_RECORD *&id) = 0; + virtual bool dlGetNext(CSSM_HANDLE handle, + CSSM_DB_RECORD_ATTRIBUTE_DATA &attributes, CSSM_DATA *data, + CSSM_DB_UNIQUE_RECORD *&id) = 0; + virtual void dlAbortQuery(CSSM_HANDLE handle) = 0; + virtual void dlFreeUniqueId(CSSM_DB_UNIQUE_RECORD *id) = 0; + virtual void dlDeleteRecord(CSSM_DB_UNIQUE_RECORD *id) = 0; + virtual Allocator &allocator() = 0; +}; + + +// +// Abstract Database Records. +// Each database record type has a subclass of this. +// These are RefCounted; you can hang on to them as long as you like, +// stick (RefPointers to) them into maps, and so on. Just go for it. +// +class Record : public RefCount, public CssmAutoData { +public: + Record() : CssmAutoData(Allocator::standard(Allocator::sensitive)) { } + Record(const char * const * attributeNames); // sets mAttributes + virtual ~Record(); + static const CSSM_DB_RECORDTYPE recordType = CSSM_DL_DB_RECORD_ANY; + + void addAttributes(const char * const * attributeNames); // add more + + // raw attribute access + CssmDbRecordAttributeData &attributes() { return mAttributes; } + const CssmDbRecordAttributeData &attributes() const { return mAttributes; } + CSSM_DB_RECORDTYPE actualRecordType() const { return mAttributes.recordType(); } + + CssmAutoData &recordData() { return *this; } // my data nature + +protected: + CssmAutoDbRecordAttributeData mAttributes; +}; + + +// +// TableBase is an implementation class for template Table below. +// Do not use it directly (you'll be sorry). +// Continue reading at template Table below. +// +class TableBase { +public: + DLAccess &database; + + CSSM_DB_RECORDTYPE recordType() const { return mRecordType; } + void recordType(CSSM_DB_RECORDTYPE t) { mRecordType = t; } // override + + // erase all elements matching a query + uint32 erase(const CSSM_QUERY &query); + uint32 erase(const Query &query); + +protected: + TableBase(DLAccess &source, CSSM_DB_RECORDTYPE type, bool getData = true); + + class AccessRef : public RefCount { + protected: + AccessRef() : mAccess(NULL) { } + AccessRef(DLAccess *ac) : mAccess(ac) { } + DLAccess *mAccess; + }; + + struct Handle : public AccessRef { + CSSM_HANDLE query; + Handle(DLAccess *ac, CSSM_HANDLE q) : AccessRef(ac), query(q) { } + ~Handle(); + }; + + struct Uid : public AccessRef { + CSSM_DB_UNIQUE_RECORD *uid; + Uid(DLAccess *ac, CSSM_DB_UNIQUE_RECORD *id) : AccessRef(ac), uid(id) { } + ~Uid(); + }; + + class Iterator { + public: + const CSSM_DB_UNIQUE_RECORD *recordHandle() const + { assert(mUid); return mUid->uid; } + + protected: + Iterator() { } + Iterator(DLAccess *ac, CSSM_HANDLE query, CSSM_DB_UNIQUE_RECORD *id, + Record *record, bool getData); + void advance(Record *newRecord); // generic operator ++ helper + + DLAccess *mAccess; // data source + RefPointer mQuery; // DL/MDS query handle + RefPointer mUid; // record unique identifier + RefPointer mRecord; // current record value + bool mGetData; // ask for data on iteration + }; + +protected: + CSSM_DB_RECORDTYPE mRecordType; // CSSM/MDS record type + bool mGetData; // ask for record data on primary iteration +}; + + +// +// A Table represents a single relation in a database (of some kind) +// +template +class Table : private TableBase { + typedef RefPointer RecPtr; +public: + Table(DLAccess &source) : TableBase(source, RecordType::recordType) { } + Table(DLAccess &source, CSSM_DB_RECORDTYPE type) : TableBase(source, type) { } + Table(DLAccess &source, bool getData) : TableBase(source, RecordType::recordType, getData) { } + +public: + class iterator : public Iterator, + public std::iterator > { + friend class Table; + public: + iterator() { } + + bool operator == (const iterator &other) const + { return mUid.get() == other.mUid.get(); } + bool operator != (const iterator &other) const + { return mUid.get() != other.mUid.get(); } + + RecPtr operator * () const { return static_cast(mRecord.get()); } + RecordType *operator -> () const { return static_cast(mRecord.get()); } + iterator operator ++ () { advance(new RecordType); return *this; } + iterator operator ++ (int) { iterator old = *this; operator ++ (); return old; } + + void erase(); + + private: + iterator(DLAccess *ac, CSSM_HANDLE query, CSSM_DB_UNIQUE_RECORD *id, + RecordType *record, bool getData) + : Iterator(ac, query, id, record, getData) { } + }; + +public: + iterator begin(); + iterator find(const CSSM_QUERY &query); + iterator find(const Query &query); + iterator end() { return iterator(); } + RecPtr fetch(const Query &query, CSSM_RETURN err = CSSM_OK) // one-stop shopping + { return fetchFirst(find(query), err); } + RecPtr fetch(CSSM_RETURN err = CSSM_OK) // fetch first of type + { return fetchFirst(begin(), err); } + + // erase all records matching a query + void erase(const CSSM_QUERY &query); + void erase(const Query &query); + + void erase(iterator it) { it.erase(); } + +private: + iterator startQuery(const CssmQuery &query, bool getData); + RecPtr fetchFirst(iterator it, CSSM_RETURN err); +}; + + +// +// Template out-of-line functions +// +template +typename Table::iterator Table::begin() +{ + return startQuery(CssmQuery(mRecordType), mGetData); +} + +template +typename Table::iterator Table::find(const CSSM_QUERY &query) +{ + return startQuery(CssmQuery(CssmQuery::overlay(query), mRecordType), mGetData); +} + +template +typename Table::iterator Table::find(const Query &query) +{ + return startQuery(CssmQuery(query.cssmQuery(), mRecordType), mGetData); +} + +template +RefPointer Table::fetchFirst(iterator it, CSSM_RETURN err) +{ + if (it == end()) + if (err) + CssmError::throwMe(err); + else + return NULL; + else + return *it; +} + + +template +typename Table::iterator Table::startQuery(const CssmQuery &query, bool getData) +{ + RefPointer record = new RecordType; + CSSM_DB_UNIQUE_RECORD *id; + CssmAutoData data(database.allocator()); + CSSM_HANDLE queryHandle = database.dlGetFirst(query, record->attributes(), + getData ? &data.get() : NULL, id); + if (queryHandle == CSSM_INVALID_HANDLE) + return end(); // not found + if (getData) + record->recordData() = data; + return iterator(&database, queryHandle, id, record, getData); +} + + +template +void Table::iterator::erase() +{ + mAccess->dlDeleteRecord(mUid->uid); + mUid->uid = NULL; +} + + +} // end namespace CssmClient +} // end namespace Security + +#endif // _H_CDSA_CLIENT_DLITERATORS diff --git a/libsecurity_cdsa_client/lib/dlquery.cpp b/libsecurity_cdsa_client/lib/dlquery.cpp new file mode 100644 index 00000000..1a897685 --- /dev/null +++ b/libsecurity_cdsa_client/lib/dlquery.cpp @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2000-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. + */ + + +// +// dlquery - search query sublanguage for DL and MDS queries +// +#include + + +namespace Security { +namespace CssmClient { + + +// +// Constructing Relations +// +Comparison::Comparison(const Comparison &r) + : mName(r.mName), mOperator(r.mOperator), mFormat(r.mFormat), + mValue(Allocator::standard()) +{ + mValue.copy(r.mValue); +} + +Comparison &Comparison::operator = (const Comparison &r) +{ + mName = r.mName; + mOperator = r.mOperator; + mFormat = r.mFormat; + mValue.copy(r.mValue); + return *this; +} + + +Comparison::Comparison(const Attribute &attr, CSSM_DB_OPERATOR op, const char *s) + : mName(attr.name()), mOperator(op), mFormat(CSSM_DB_ATTRIBUTE_FORMAT_STRING), + mValue(Allocator::standard(), StringData(s)) +{ } + +Comparison::Comparison(const Attribute &attr, CSSM_DB_OPERATOR op, const std::string &s) + : mName(attr.name()), mOperator(op), mFormat(CSSM_DB_ATTRIBUTE_FORMAT_STRING), + mValue(Allocator::standard(), StringData(s)) +{ } + +Comparison::Comparison(const Attribute &attr, CSSM_DB_OPERATOR op, uint32 value) + : mName(attr.name()), mOperator(op), mFormat(CSSM_DB_ATTRIBUTE_FORMAT_UINT32), + mValue(Allocator::standard(), CssmData::wrap(value)) +{ } + +Comparison::Comparison(const Attribute &attr, CSSM_DB_OPERATOR op, bool value) + : mName(attr.name()), mOperator(op), mFormat(CSSM_DB_ATTRIBUTE_FORMAT_UINT32), + mValue(Allocator::standard(), CssmData::wrap(uint32(value ? 1 : 0))) +{ } + +Comparison::Comparison(const Attribute &attr, CSSM_DB_OPERATOR op, const CssmData &data) + : mName(attr.name()), mOperator(op), mFormat(CSSM_DB_ATTRIBUTE_FORMAT_BLOB), + mValue(Allocator::standard(), data) +{ } + +Comparison::Comparison(const Attribute &attr, CSSM_DB_OPERATOR op, const CSSM_GUID &guid) + : mName(attr.name()), mOperator(op), mFormat(CSSM_DB_ATTRIBUTE_FORMAT_STRING), + mValue(Allocator::standard(), StringData(Guid::overlay(guid).toString())) +{ +} + + +Comparison::Comparison(const Attribute &attr) + : mName(attr.name()), mOperator(CSSM_DB_NOT_EQUAL), mFormat(CSSM_DB_ATTRIBUTE_FORMAT_UINT32), + mValue(Allocator::standard(), CssmData::wrap(uint32(CSSM_FALSE))) +{ +} + +Comparison operator ! (const Attribute &attr) +{ + return Comparison(attr, CSSM_DB_EQUAL, uint32(CSSM_FALSE)); +} + + +// +// Query methods +// +Query &Query::operator = (const Query &q) +{ + mRelations = q.mRelations; + mQueryValid = false; + return *this; +} + + +// +// Form the CssmQuery from a Query object. +// We cache this in mQuery, which we have made sure isn't copied along. +// +const CssmQuery &Query::cssmQuery() const +{ + if (!mQueryValid) { + // record type remains at ANY + mQuery.conjunctive(CSSM_DB_AND); + for (vector::const_iterator it = mRelations.begin(); it != mRelations.end(); it++) { + CssmSelectionPredicate pred; + pred.dbOperator(it->mOperator); + pred.attribute().info() = CssmDbAttributeInfo(it->mName.c_str(), it->mFormat); + pred.attribute().set(it->mValue.get()); + mPredicates.push_back(pred); + } + mQuery.set(mPredicates.size(), &mPredicates[0]); + mQueryValid = true; + } + return mQuery; +} + + +} // end namespace CssmClient +} // end namespace Security diff --git a/libsecurity_cdsa_client/lib/dlquery.h b/libsecurity_cdsa_client/lib/dlquery.h new file mode 100644 index 00000000..a7d79384 --- /dev/null +++ b/libsecurity_cdsa_client/lib/dlquery.h @@ -0,0 +1,131 @@ +/* + * 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. + */ + + +// +// dlquery - search query sublanguage for DL and MDS queries +// + +#ifndef _H_CDSA_CLIENT_DLQUERY +#define _H_CDSA_CLIENT_DLQUERY + +#include +#include +#include + + +namespace Security { +namespace CssmClient { + + +// +// A DL record attribute +// +class Attribute { +public: + Attribute(const std::string &name) : mName(name) { } + Attribute(const char *name) : mName(name) { } + + const std::string &name() const { return mName; } + +private: + std::string mName; +}; + + +// +// A comparison (attribute ~rel~ constant-value) +// +class Comparison { + friend class Query; +public: + Comparison(const Attribute &attr, CSSM_DB_OPERATOR op, const char *s); + Comparison(const Attribute &attr, CSSM_DB_OPERATOR op, const std::string &s); + Comparison(const Attribute &attr, CSSM_DB_OPERATOR op, uint32 v); + Comparison(const Attribute &attr, CSSM_DB_OPERATOR op, bool v); + Comparison(const Attribute &attr, CSSM_DB_OPERATOR op, const CSSM_GUID &guid); + Comparison(const Attribute &attr, CSSM_DB_OPERATOR op, const CssmData &data); + + Comparison(const Attribute &attr); + friend Comparison operator ! (const Attribute &attr); + + Comparison(const Comparison &r); + Comparison &operator = (const Comparison &r); + +private: + std::string mName; + CSSM_DB_OPERATOR mOperator; + CSSM_DB_ATTRIBUTE_FORMAT mFormat; + CssmAutoData mValue; +}; + +template +Comparison operator == (const Attribute &attr, const Value &value) +{ return Comparison(attr, CSSM_DB_EQUAL, value); } + +template +Comparison operator != (const Attribute &attr, const Value &value) +{ return Comparison(attr, CSSM_DB_NOT_EQUAL, value); } + +template +Comparison operator < (const Attribute &attr, const Value &value) +{ return Comparison(attr, CSSM_DB_LESS_THAN, value); } + +template +Comparison operator > (const Attribute &attr, const Value &value) +{ return Comparison(attr, CSSM_DB_GREATER_THAN, value); } + +template +Comparison operator % (const Attribute &attr, const Value &value) +{ return Comparison(attr, CSSM_DB_CONTAINS, value); } + + +// +// A Query +// +class Query { +public: + Query() : mQueryValid(false) { } + Query(const Comparison r) : mQueryValid(false) { mRelations.push_back(r); } + Query(const Attribute &attr) : mQueryValid(false) { mRelations.push_back(attr); } + + Query(const Query &q) : mRelations(q.mRelations), mQueryValid(false) { } + + Query &operator = (const Query &q); + + Query &add(const Comparison &r) + { mRelations.push_back(r); return *this; } + + const CssmQuery &cssmQuery() const; + +private: + std::vector mRelations; + + // cached CssmQuery equivalent of this object + mutable bool mQueryValid; // mQuery has been constructed + mutable vector mPredicates; // holds lifetimes for mQuery + mutable CssmQuery mQuery; +}; + +inline Query operator && (Query c, const Comparison &r) +{ return c.add(r); } + + +} // end namespace CssmClient +} // end namespace Security + +#endif // _H_CDSA_CLIENT_DLQUERY diff --git a/libsecurity_cdsa_client/lib/genkey.cpp b/libsecurity_cdsa_client/lib/genkey.cpp new file mode 100644 index 00000000..3e5d52d9 --- /dev/null +++ b/libsecurity_cdsa_client/lib/genkey.cpp @@ -0,0 +1,93 @@ +/* + * 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. + */ + + +// +// genkey - client interface to CSSM sign/verify contexts +// +#include + +using namespace CssmClient; + + +GenerateKey::GenerateKey(const CSP &csp, CSSM_ALGORITHMS alg, uint32 size) +: Context(csp, alg), mKeySize(size), mSeed(NULL), mSalt(NULL), mParams(NULL) +{ +} + +void +GenerateKey::database(const Db &inDb) +{ + mDb = inDb; + if (mDb && isActive()) + set(CSSM_ATTRIBUTE_DL_DB_HANDLE, mDb->handle()); +} + +void GenerateKey::activate() +{ + if (!mActive) + { + check(CSSM_CSP_CreateKeyGenContext(attachment()->handle(), mAlgorithm, + mKeySize, mSeed, mSalt, NULL, NULL, mParams, &mHandle)); + // Must be done before calling set() since is does nothing unless we are active. + // Also we are technically active even if set() throws since we already created a context. + mActive = true; + if (mDb) + set(CSSM_ATTRIBUTE_DL_DB_HANDLE, mDb->handle()); + } +} + +Key GenerateKey::operator () (const KeySpec &spec) +{ + Key key; + + check(CSSM_GenerateKey(handle(), spec.usage, spec.attributes, spec.label, + &compositeRcc(), key.makeNewKey(attachment()))); + + key->activate(); + + return key; +} + +void GenerateKey::operator () (CssmKey &key, const KeySpec &spec) +{ + check(CSSM_GenerateKey(handle(), spec.usage, spec.attributes, spec.label, &compositeRcc(), &key)); + +} + +void GenerateKey::operator () (Key &publicKey, const KeySpec &pubSpec, + Key &privateKey, const KeySpec &privSpec) +{ + check(CSSM_GenerateKeyPair(handle(), + pubSpec.usage, pubSpec.attributes, + pubSpec.label, publicKey.makeNewKey(attachment()), + privSpec.usage, privSpec.attributes, + privSpec.label, &compositeRcc(), privateKey.makeNewKey(attachment()))); + + publicKey->activate(); + privateKey->activate(); + +} + +void GenerateKey::operator () (CssmKey &publicKey, const KeySpec &pubSpec, + CssmKey &privateKey, const KeySpec &privSpec) +{ + check(CSSM_GenerateKeyPair(handle(), + pubSpec.usage, pubSpec.attributes, pubSpec.label, &publicKey, + privSpec.usage, privSpec.attributes, privSpec.label, &compositeRcc(), &privateKey)); +} + diff --git a/libsecurity_cdsa_client/lib/genkey.h b/libsecurity_cdsa_client/lib/genkey.h new file mode 100644 index 00000000..4d1381b2 --- /dev/null +++ b/libsecurity_cdsa_client/lib/genkey.h @@ -0,0 +1,79 @@ +/* + * 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. + */ + + +// +// genkey - client interface to CSSM sign/verify contexts +// +#ifndef _H_CDSA_CLIENT_GENKEY +#define _H_CDSA_CLIENT_GENKEY 1 + +#include +#include +#include +#include + + +namespace Security +{ + +namespace CssmClient +{ + +class GenerateKey : public Context, public RccBearer { +public: + GenerateKey(const CSP &csp, CSSM_ALGORITHMS alg, uint32 size = 0); + +public: + // context parameters + void size(uint32 s) { mKeySize = s; set(CSSM_ATTRIBUTE_KEY_LENGTH, s); } + void seed(const CssmCryptoData &s) { mSeed = &s; set(CSSM_ATTRIBUTE_SEED, s); } + void salt(const CssmData &s) { mSalt = &s;set(CSSM_ATTRIBUTE_SALT, s); } + void params(const CssmData &p) { mParams = &p; set(CSSM_ATTRIBUTE_ALG_PARAMS, p); } + void database(const Db &inDb); + + // symmetric key generation + Key operator () (const KeySpec &spec); + void operator () (CssmKey &key, const KeySpec &spec); + + // asymmetric key generation + void operator () (Key &publicKey, const KeySpec &publicSpec, + Key &privateKey, const KeySpec &privateSpec); + void operator () (CssmKey &publicKey, const KeySpec &publicSpec, + CssmKey &privateKey, const KeySpec &privateSpec); + + +protected: + void activate(); + +private: + // context parameters + uint32 mKeySize; + const CssmCryptoData *mSeed; + const CssmData *mSalt; + const CssmData *mParams; + Db mDb; + + // generation parameters(?) + const ResourceControlContext *mInitialAcl; +}; + +} // end namespace CssmClient + +} // end namespace Security + +#endif // _H_CDSA_CLIENT_GENKEY diff --git a/libsecurity_cdsa_client/lib/keychainacl.cpp b/libsecurity_cdsa_client/lib/keychainacl.cpp new file mode 100644 index 00000000..58ddbb8a --- /dev/null +++ b/libsecurity_cdsa_client/lib/keychainacl.cpp @@ -0,0 +1,133 @@ +/* + * 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. + */ + + +// +// keychainacl - Keychain-related ACL and credential forms +// +#ifdef __MWERKS__ +#define _CPP_KEYCHAINACL +#endif + +#include "keychainacl.h" +#include + +using namespace CssmClient; + + +// +// Construct the factory. +// @@@ Leaks. +// +KeychainAclFactory::KeychainAclFactory(Allocator &alloc) +: allocator(alloc), nullCred(alloc, 1), kcCred(alloc, 2), kcUnlockCred(alloc, 1) +{ + // the credential objects self-initialize to empty + nullCred.sample(0) = TypedList(alloc, CSSM_SAMPLE_TYPE_THRESHOLD); + + kcCred.sample(0) = TypedList(alloc, CSSM_SAMPLE_TYPE_KEYCHAIN_PROMPT); + kcCred.sample(1) = TypedList(alloc, CSSM_SAMPLE_TYPE_THRESHOLD, + new(alloc) ListElement(TypedList(alloc, CSSM_SAMPLE_TYPE_KEYCHAIN_PROMPT))); + + // @@@ This leaks a ListElement(CSSM_SAMPLE_TYPE_KEYCHAIN_PROMPT) + kcUnlockCred.sample(0) = TypedList(alloc, CSSM_SAMPLE_TYPE_KEYCHAIN_LOCK, + new(alloc) ListElement(CSSM_SAMPLE_TYPE_KEYCHAIN_PROMPT)); +} + +KeychainAclFactory::~KeychainAclFactory() +{ +} + + +// +// Produce credentials. +// These are constants that don't need to be allocated per use. +// +const AccessCredentials *KeychainAclFactory::nullCredentials() +{ + return &nullCred; +} + +const AccessCredentials *KeychainAclFactory::keychainPromptCredentials() +{ + return &kcCred; +} + +const AccessCredentials *KeychainAclFactory::keychainPromptUnlockCredentials() +{ + return &kcUnlockCred; +} + +const AutoCredentials *KeychainAclFactory::passwordChangeCredentials(const CssmData &password) +{ + AutoCredentials *cred = new AutoCredentials(allocator, 1); + // @@@ This leaks a ListElement(CSSM_SAMPLE_TYPE_KEYCHAIN_PROMPT) and ListElement(password) + cred->sample(0) = TypedList(allocator, CSSM_SAMPLE_TYPE_KEYCHAIN_CHANGE_LOCK, + new(allocator) ListElement(CSSM_SAMPLE_TYPE_PASSWORD), + new(allocator) ListElement(password)); + return cred; +} + +const AutoCredentials *KeychainAclFactory::passwordUnlockCredentials(const CssmData &password) +{ + AutoCredentials *cred = new AutoCredentials(allocator, 1); + // @@@ This leaks a ListElement(CSSM_SAMPLE_TYPE_KEYCHAIN_PROMPT) and ListElement(password) + cred->sample(0) = TypedList(allocator, CSSM_SAMPLE_TYPE_KEYCHAIN_LOCK, + new(allocator) ListElement(CSSM_SAMPLE_TYPE_PASSWORD), + new(allocator) ListElement(password)); + return cred; +} + + +// +// +AclEntryInput *KeychainAclFactory::keychainPromptOwner(const CssmData &description) +{ + // @@@ Make sure this works for a NULL description + AclEntryPrototype proto(TypedList(allocator, CSSM_ACL_SUBJECT_TYPE_KEYCHAIN_PROMPT, + new(allocator) ListElement(allocator, description))); + return new(allocator) AclEntryInput(proto); +} + +AclEntryInput *KeychainAclFactory::anyOwner() +{ + AclEntryPrototype proto(TypedList(allocator, CSSM_ACL_SUBJECT_TYPE_ANY)); + return new(allocator) AclEntryInput(proto); +} + +void KeychainAclFactory::release(AclEntryInput *input) +{ + DataWalkers::chunkFree(input, allocator); +} + + +// +// ACL editing +// +void KeychainAclFactory::comment(TypedList &subject) +{ + subject.insert(new(allocator) ListElement(CSSM_ACL_SUBJECT_TYPE_COMMENT), + subject.first()); +} + +void KeychainAclFactory::uncomment(TypedList &subject) +{ + ListElement *first = subject.first(); + assert(*first == CSSM_ACL_SUBJECT_TYPE_COMMENT); + subject -= first; + destroy(first, allocator); +} diff --git a/libsecurity_cdsa_client/lib/keychainacl.h b/libsecurity_cdsa_client/lib/keychainacl.h new file mode 100644 index 00000000..9e7748d8 --- /dev/null +++ b/libsecurity_cdsa_client/lib/keychainacl.h @@ -0,0 +1,89 @@ +/* + * 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. + */ + + +// +// keychainacl - Keychain-related ACL and credential forms +// +#ifndef _KEYCHAINACL +#define _KEYCHAINACL + +#include +#include +#include +#include + +#ifdef _CPP_KEYCHAINACL +# pragma export on +#endif + + +namespace Security +{ + +namespace CssmClient +{ + +class KeychainAclFactory +{ +public: + KeychainAclFactory(Allocator &alloc); + ~KeychainAclFactory(); + + Allocator &allocator; + +public: + // + // Create credentials. These functions return AccessCredentials pointers. + // + const AccessCredentials *nullCredentials(); + const AccessCredentials *keychainPromptCredentials(); + const AccessCredentials *keychainPromptUnlockCredentials(); + const AutoCredentials *passwordChangeCredentials(const CssmData &password); + const AutoCredentials *passwordUnlockCredentials(const CssmData &password); + +public: + // + // Create initial ACLs. Pass those to resource creation functions. + // + AclEntryInput *keychainPromptOwner(const CssmData &description); + AclEntryInput *anyOwner(); + void release(AclEntryInput *input); + +public: + // + // Edit ACLs (in external form, as TypedLists) + // + void comment(TypedList &subject); + void uncomment(TypedList &subject); + +private: + AutoCredentials nullCred; + AutoCredentials kcCred; + AutoCredentials kcUnlockCred; +}; + + +} // end namespace CssmClient + +} // end namespace Security + +#ifdef _CPP_KEYCHAINACL +# pragma export off +#endif + +#endif //_KEYCHAINACL diff --git a/libsecurity_cdsa_client/lib/keyclient.cpp b/libsecurity_cdsa_client/lib/keyclient.cpp new file mode 100644 index 00000000..00c738e0 --- /dev/null +++ b/libsecurity_cdsa_client/lib/keyclient.cpp @@ -0,0 +1,117 @@ +/* + * 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. + */ + + +// +// keyclient +// +#include +#include + + +using namespace CssmClient; + + +KeyImpl::KeyImpl(const CSP &csp) : ObjectImpl(csp), CssmKey() +{ + mActive=false; +} + +KeyImpl::KeyImpl(const CSP &csp, const CSSM_KEY &key, bool copy) : ObjectImpl(csp), CssmKey(key) +{ + if (copy) + keyData() = CssmAutoData(csp.allocator(), keyData()).release(); + mActive=true; +} + +KeyImpl::KeyImpl(const CSP &csp, const CSSM_DATA &keyData) : ObjectImpl(csp), +CssmKey(keyData.Length, csp->allocator().alloc(keyData.Length)) +{ + memcpy(KeyData.Data, keyData.Data, keyData.Length); + mActive=true; +} + +KeyImpl::~KeyImpl() +{ + try + { + deactivate(); + } + catch(...) {} +} + +void +KeyImpl::deleteKey(const CSSM_ACCESS_CREDENTIALS *cred) +{ + if (mActive) + { + mActive=false; + check(CSSM_FreeKey(csp()->handle(), cred, this, CSSM_TRUE)); + } +} + +CssmKeySize +KeyImpl::sizeInBits() const +{ + CssmKeySize size; + check(CSSM_QueryKeySizeInBits(csp()->handle(), CSSM_INVALID_HANDLE, this, &size)); + return size; +} + +void +KeyImpl::getAcl(AutoAclEntryInfoList &aclInfos, const char *selectionTag) const +{ + aclInfos.allocator(allocator()); + check(CSSM_GetKeyAcl(csp()->handle(), this, reinterpret_cast(selectionTag), aclInfos, aclInfos)); +} + +void +KeyImpl::changeAcl(const CSSM_ACL_EDIT &aclEdit, + const CSSM_ACCESS_CREDENTIALS *accessCred) +{ + check(CSSM_ChangeKeyAcl(csp()->handle(), + AccessCredentials::needed(accessCred), &aclEdit, this)); +} + +void +KeyImpl::getOwner(AutoAclOwnerPrototype &owner) const +{ + owner.allocator(allocator()); + check(CSSM_GetKeyOwner(csp()->handle(), this, owner)); +} + +void +KeyImpl::changeOwner(const CSSM_ACL_OWNER_PROTOTYPE &newOwner, + const CSSM_ACCESS_CREDENTIALS *accessCred) +{ + check(CSSM_ChangeKeyOwner(csp()->handle(), + AccessCredentials::needed(accessCred), this, &newOwner)); +} + +void KeyImpl::activate() +{ + mActive=true; +} + +void KeyImpl::deactivate() +{ + if (mActive) + { + mActive=false; + check(CSSM_FreeKey(csp()->handle(), NULL, this, CSSM_FALSE)); + } +} diff --git a/libsecurity_cdsa_client/lib/keyclient.h b/libsecurity_cdsa_client/lib/keyclient.h new file mode 100644 index 00000000..0f2e6040 --- /dev/null +++ b/libsecurity_cdsa_client/lib/keyclient.h @@ -0,0 +1,113 @@ +/* + * 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. + */ + + +// +// keyclient +// +#ifndef _H_CDSA_CLIENT_KEYCLIENT +#define _H_CDSA_CLIENT_KEYCLIENT 1 + +#include +#include + +namespace Security +{ + +namespace CssmClient +{ + +// +// Key +// +class KeyImpl : public ObjectImpl, public AclBearer, public CssmKey +{ +public: + KeyImpl(const CSP &csp); + KeyImpl(const CSP &csp, const CSSM_KEY &key, bool copy = false); + KeyImpl(const CSP &csp, const CSSM_DATA &keyData); + virtual ~KeyImpl(); + + CSP csp() const { return parent(); } + void deleteKey(const CSSM_ACCESS_CREDENTIALS *cred); + + CssmKeySize sizeInBits() const; + + // Acl manipulation + void getAcl(AutoAclEntryInfoList &aclInfos, const char *selectionTag = NULL) const; + void changeAcl(const CSSM_ACL_EDIT &aclEdit, + const CSSM_ACCESS_CREDENTIALS *accessCred); + + // Acl owner manipulation + void getOwner(AutoAclOwnerPrototype &owner) const; + void changeOwner(const CSSM_ACL_OWNER_PROTOTYPE &newOwner, + const CSSM_ACCESS_CREDENTIALS *accessCred = NULL); + + // Call this after completing the CSSM API call after having called Key::makeNewKey() + void activate(); + +protected: + void deactivate(); +}; + +class Key : public Object +{ +public: + typedef KeyImpl Impl; + explicit Key(Impl *impl) : Object(impl) {} + + Key() : Object(NULL) {} + Key(const CSP &csp, const CSSM_KEY &key, bool copy = false) : Object(new Impl(csp, key, copy)) {} + Key(const CSP &csp, const CSSM_DATA &keyData) : Object(new Impl(csp, keyData)) {} + + // Creates an inactive key, client must call activate() after this. + Key(const CSP &csp) : Object(new Impl(csp)) {} + + Impl *operator ->() const { return (*this) ? &impl() : NULL; } + Impl &operator *() const { return impl(); } + + // Conversion operators to CssmKey baseclass. + operator const CssmKey * () const { return (*this) ? &(**this) : NULL; } + operator const CssmKey & () const { return **this; } + + // a few shortcuts to make life easier + CssmKey::Header &header() const { return (*this)->header(); } + + // Creates an inactive key, client must call activate() after this. + CssmKey *makeNewKey(const CSP &csp) { (*this) = Key(csp); return &(**this); } + + // inquiries + CssmKeySize sizeInBits() const { return (*this)->sizeInBits(); } +}; + + +struct KeySpec { + CSSM_KEYUSE usage; + CSSM_KEYATTR_FLAGS attributes; + const CssmData *label; + //add rc context + + KeySpec(CSSM_KEYUSE u, CSSM_KEYATTR_FLAGS a) : usage(u), attributes(a), label(NULL) { } + KeySpec(CSSM_KEYUSE u, CSSM_KEYATTR_FLAGS a, const CssmData &l) : usage(u), attributes(a), label(&l) { } +}; + +} // end namespace CssmClient + +} // end namespace Security + + +#endif // _H_CDSA_CLIENT_KEYCLIENT diff --git a/libsecurity_cdsa_client/lib/macclient.cpp b/libsecurity_cdsa_client/lib/macclient.cpp new file mode 100644 index 00000000..38c8b6a7 --- /dev/null +++ b/libsecurity_cdsa_client/lib/macclient.cpp @@ -0,0 +1,98 @@ +/* + * 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. + */ + + +// +// macclient - client interface to CSSM sign/verify mac contexts +// +#include + +using namespace CssmClient; + + +// +// Common features of signing and verify mac contexts +// +void MacContext::activate() +{ + if (!mActive) + { + check(CSSM_CSP_CreateMacContext(attachment()->handle(), mAlgorithm, + mKey, &mHandle)); + mActive = true; + if (cred()) + cred(cred()); // install explicitly + } +} + + +// +// Signing +// +void GenerateMac::sign(const CssmData *data, uint32 count, CssmData &mac) +{ + unstaged(); + check(CSSM_GenerateMac(handle(), data, count, &mac)); +} + +void GenerateMac::init() +{ + check(CSSM_GenerateMacInit(handle())); + mStaged = true; +} + +void GenerateMac::sign(const CssmData *data, uint32 count) +{ + staged(); + check(CSSM_GenerateMacUpdate(handle(), data, count)); +} + +void GenerateMac::operator () (CssmData &mac) +{ + staged(); + check(CSSM_GenerateMacFinal(handle(), &mac)); + mStaged = false; +} + + +// +// Verifying +// +void VerifyMac::verify(const CssmData *data, uint32 count, const CssmData &mac) +{ + unstaged(); + check(CSSM_VerifyMac(handle(), data, count, &mac)); +} + +void VerifyMac::init() +{ + check(CSSM_VerifyMacInit(handle())); + mStaged = true; +} + +void VerifyMac::verify(const CssmData *data, uint32 count) +{ + staged(); + check(CSSM_VerifyMacUpdate(handle(), data, count)); +} + +void VerifyMac::operator () (const CssmData &mac) +{ + staged(); + check(CSSM_VerifyMacFinal(handle(), &mac)); + mStaged = false; +} diff --git a/libsecurity_cdsa_client/lib/macclient.h b/libsecurity_cdsa_client/lib/macclient.h new file mode 100644 index 00000000..4621d5f2 --- /dev/null +++ b/libsecurity_cdsa_client/lib/macclient.h @@ -0,0 +1,90 @@ +/* + * 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. + */ + + +// +// macclient - client interface to CSSM sign/verify mac contexts +// +#ifndef _H_CDSA_CLIENT_MACCLIENT +#define _H_CDSA_CLIENT_MACCLIENT 1 + +#include +#include + +namespace Security +{ + +namespace CssmClient +{ + +// +// A signing/verifying mac context +// +class MacContext : public Context +{ +public: + MacContext(const CSP &csp, CSSM_ALGORITHMS alg) + : Context(csp, alg) { } + + // preliminary interface + Key key() const { assert(mKey); return mKey; } + void key(const Key &k) { mKey = k; set(CSSM_ATTRIBUTE_KEY, mKey); } + +protected: + void activate(); + Key mKey; +}; + + +class GenerateMac : public MacContext +{ +public: + GenerateMac(const CSP &csp, CSSM_ALGORITHMS alg) : MacContext(csp, alg) { } + + // integrated + void sign(const CssmData &data, CssmData &mac) { sign(&data, 1, mac); } + void sign(const CssmData *data, uint32 count, CssmData &mac); + + // staged + void init(); // Optional + void sign(const CssmData &data) { sign(&data, 1); } + void sign(const CssmData *data, uint32 count); + void operator () (CssmData &mac); + CssmData operator () () { CssmData mac; (*this)(mac); return mac; } +}; + +class VerifyMac : public MacContext +{ +public: + VerifyMac(const CSP &csp, CSSM_ALGORITHMS alg) : MacContext(csp, alg) { } + + // integrated + void verify(const CssmData &data, const CssmData &mac) { verify(&data, 1, mac); } + void verify(const CssmData *data, uint32 count, const CssmData &mac); + + // staged + void init(); // Optional + void verify(const CssmData &data) { verify(&data, 1); } + void verify(const CssmData *data, uint32 count); + void operator () (const CssmData &mac); +}; + +} // end namespace CssmClient + +} // end namespace Security + +#endif // _H_CDSA_CLIENT_MACCLIENT diff --git a/libsecurity_cdsa_client/lib/mds_standard.cpp b/libsecurity_cdsa_client/lib/mds_standard.cpp new file mode 100644 index 00000000..5c2eb46a --- /dev/null +++ b/libsecurity_cdsa_client/lib/mds_standard.cpp @@ -0,0 +1,228 @@ +/* + * Copyright (c) 2000-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. + */ + + +// +// mds_standard - standard-defined MDS record types +// +#include +#include + + +namespace Security { +namespace MDSClient { + + +// +// CDSA Common relation (one record per module) +// +static const char * const commonAttributes[] = { + "ModuleID", + "ModuleName", + "Path", + "Desc", + "DynamicFlag", + "MultiThreadFlag", + "ServiceMask", + NULL +}; +Common::Common() : Record(commonAttributes) { } + +string Common::moduleID() const { return mAttributes[0]; } +string Common::moduleName() const { return mAttributes[1]; } +string Common::path() const { return mAttributes[2]; } +string Common::description() const { return mAttributes[3]; } +bool Common::dynamic() const { return mAttributes[4]; } +bool Common::singleThreaded() const { return !mAttributes[5]; } +CSSM_SERVICE_MASK Common::serviceMask() const { return mAttributes[6]; } + + +// +// Common::Carrier draws in the Common fields for anything with +// a ModuleID attribute (which must be the first attribute listed) +// +Common::Carrier::~Carrier() { } + +Common &Common::Carrier::common() const +{ + if (!mCommon) { + const CssmDbRecordAttributeData &attrs + = dynamic_cast(this)->attributes(); + RefPointer rpc; + rpc = Table(mds()).fetch( + Attribute("ModuleID") == string(attrs[0]), + CSSMERR_DL_ENDOFDATA); + mCommon = rpc; + } + return *mCommon; +} + + +// +// Attributes that are common to all primary relations +// +static const char * const primaryAttributes[] = { + "ModuleID", + "SSID", + "ModuleName", + "ProductVersion", + "Vendor", + NULL +}; +PrimaryRecord::PrimaryRecord(const char * const * names) + : Record(primaryAttributes) +{ + addAttributes(names); +} + +string PrimaryRecord::moduleID() const { return mAttributes[0]; } +uint32 PrimaryRecord::subserviceID() const { return mAttributes[1]; } +string PrimaryRecord::moduleName() const { return mAttributes[2]; } +string PrimaryRecord::productVersion() const { return mAttributes[3]; } +string PrimaryRecord::vendor() const { return mAttributes[4]; } + + +// +// CSP Primary relation (one record per CSP SSID) +// +static const char * const cspAttributes[] = { + // up to Vendor is handled by PrimaryRecord + "CspType", + "CspFlags", + NULL +}; +CSP::CSP() : PrimaryRecord(cspAttributes) { } + +uint32 CSP::cspType() const { return mAttributes[5]; } +CSSM_CSP_FLAGS CSP::cspFlags() const { return mAttributes[6]; } + + +// +// CSP capabilities relation +// +static const char * const capAttributes[] = { + "ModuleID", + "SSID", + "ContextType", + "AlgType", + "GroupId", + "AttributeType", + "Description", + NULL +}; +CSPCapabilities::CSPCapabilities() : Record(capAttributes) { } + +string CSPCapabilities::moduleID() const { return mAttributes[0]; } +uint32 CSPCapabilities::subserviceID() const { return mAttributes[1]; } +uint32 CSPCapabilities::contextType() const { return mAttributes[2]; } +uint32 CSPCapabilities::algorithm() const { return mAttributes[3]; } +uint32 CSPCapabilities::group() const { return mAttributes[4]; } +uint32 CSPCapabilities::attribute() const { return mAttributes[5]; } +string CSPCapabilities::description() const { return mAttributes[6]; } + + +// +// CSP SmartcardInfo relation (one record per smartcard token present) +// +static const char * const scAttributes[] = { + "ModuleID", + "SSID", + "ScDesc", + "ScVendor", + "ScVersion", + "ScFirmwareVersion", + "ScFlags", + "ScCustomFlags", + "ScSerialNumber", + NULL +}; +SmartcardInfo::SmartcardInfo() : Record(scAttributes) { } + +string SmartcardInfo::moduleID() const { return mAttributes[0]; } +uint32 SmartcardInfo::subserviceID() const { return mAttributes[1]; } +string SmartcardInfo::description() const { return mAttributes[2]; } +string SmartcardInfo::vendor() const { return mAttributes[3]; } +string SmartcardInfo::version() const { return mAttributes[4]; } +string SmartcardInfo::firmware() const { return mAttributes[5]; } +CSSM_SC_FLAGS SmartcardInfo::flags() const { return mAttributes[6]; } +CSSM_SC_FLAGS SmartcardInfo::customFlags() const { return mAttributes[7]; } +string SmartcardInfo::serial() const { return mAttributes[8]; } + + +// +// DL Primary relation (one record per DL SSID) +// +static const char * const dlAttributes[] = { + // up to Vendor is handled by PrimaryRecord + "DLType", + "QueryLimitsFlag", + NULL +}; +DL::DL() : PrimaryRecord(dlAttributes) { } + +uint32 DL::dlType() const { return mAttributes[5]; } +uint32 DL::queryLimits() const { return mAttributes[6]; } + + +// +// CL Primary relation (one record per CL SSID) +// +static const char * const clAttributes[] = { + // up to Vendor is handled by PrimaryRecord + "CertTypeFormat", + "CrlTypeFormat", + NULL +}; +CL::CL() : PrimaryRecord(clAttributes) { } + +uint32 CL::certTypeFormat() const { return mAttributes[5]; } +uint32 CL::crlTypeFormat() const { return mAttributes[6]; } + + +// +// TP Primary relation (one record per TP SSID) +// +static const char * const tpAttributes[] = { + // up to Vendor is handled by PrimaryRecord + "CertTypeFormat", + NULL +}; +TP::TP() : PrimaryRecord(tpAttributes) { } + +uint32 TP::certTypeFormat() const { return mAttributes[5]; } + + +// +// TP Policy-OIDS relation (one record per supported policy and TP) +// +static const char * const policyAttributes[] = { + "ModuleID", + "SSID", + "OID", + "Value", + NULL +}; +PolicyOids::PolicyOids() : Record(policyAttributes) { } + +string PolicyOids::moduleID() const { return mAttributes[0]; } +uint32 PolicyOids::subserviceID() const { return mAttributes[1]; } +CssmData PolicyOids::oid() const { return mAttributes[2]; } +CssmData PolicyOids::value() const { return mAttributes[3]; } + + +} // end namespace MDSClient +} // end namespace Security diff --git a/libsecurity_cdsa_client/lib/mds_standard.h b/libsecurity_cdsa_client/lib/mds_standard.h new file mode 100644 index 00000000..6dc30900 --- /dev/null +++ b/libsecurity_cdsa_client/lib/mds_standard.h @@ -0,0 +1,205 @@ +/* + * Copyright (c) 2000-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. + */ + + +// +// mds_standard - standard-defined MDS record types. +// +// These are the C++ record types corresponding to standard and Apple-defined +// MDS relations. Note that not all standard fields are included; only those +// of particular interest to the implementation. Feel free to add field functions +// as needed. +// + +#ifndef _H_CDSA_CLIENT_MDS_STANDARD +#define _H_CDSA_CLIENT_MDS_STANDARD + +#include + + +namespace Security { +namespace MDSClient { + + +// +// The CDSA Common table (one record per module) +// +class Common : public Record { +public: + Common(); + static const CSSM_DB_RECORDTYPE recordType = MDS_CDSADIR_COMMON_RECORDTYPE; + + string moduleID() const; + string moduleName() const; + string path() const; + string description() const; + bool dynamic() const; + bool singleThreaded() const; + CSSM_SERVICE_MASK serviceMask() const; + +public: + // + // "Link in" a Common into another record, whose attributes()[0] is the ModuleID + // + class Carrier { + public: + virtual ~Carrier(); + + string moduleName() const { return common().moduleName(); } + string path() const { return common().path(); } + string description() const { return common().description(); } + bool dynamic() const { return common().dynamic(); } + bool singleThreaded() const { return common().singleThreaded(); } + CSSM_SERVICE_MASK serviceMask() const { return common().serviceMask(); } + + private: + mutable RefPointer mCommon; + + Common &common() const; + }; +}; + + +// +// PrimaryRecord shapes the "common head" of all MDS primary relations +// +class PrimaryRecord : public Record, public Common::Carrier { +public: + PrimaryRecord(const char * const * names); + + string moduleID() const; + uint32 subserviceID() const; + string moduleName() const; + string productVersion() const; + string vendor() const; +}; + + +// +// The CSP Primary relation +// +class CSP : public PrimaryRecord { +public: + CSP(); + static const CSSM_DB_RECORDTYPE recordType = MDS_CDSADIR_CSP_PRIMARY_RECORDTYPE; + + uint32 cspType() const; + CSSM_CSP_FLAGS cspFlags() const; +}; + + +// +// The CSP Capabilities relation +// +class CSPCapabilities : public Record, public Common::Carrier { +public: + CSPCapabilities(); + static const CSSM_DB_RECORDTYPE recordType = MDS_CDSADIR_CSP_CAPABILITY_RECORDTYPE; + + string moduleID() const; + uint32 subserviceID() const; + uint32 contextType() const; + uint32 algorithm() const; + uint32 group() const; + uint32 attribute() const; + string description() const; +}; + + +// +// The CSP "smartcard token" relation +// +class SmartcardInfo : public Record, public Common::Carrier { +public: + SmartcardInfo(); + static const CSSM_DB_RECORDTYPE recordType = MDS_CDSADIR_CSP_SC_INFO_RECORDTYPE; + + string moduleID() const; + uint32 subserviceID() const; + string description() const; + string vendor() const; + string version() const; + string firmware() const; + CSSM_SC_FLAGS flags() const; + CSSM_SC_FLAGS customFlags() const; + string serial() const; +}; + + +// +// The DL Primary relation +// +class DL : public PrimaryRecord { +public: + DL(); + static const CSSM_DB_RECORDTYPE recordType = MDS_CDSADIR_DL_PRIMARY_RECORDTYPE; + + uint32 dlType() const; + uint32 queryLimits() const; +}; + + +// +// The CL Primary relation +// +class CL : public PrimaryRecord { +public: + CL(); + static const CSSM_DB_RECORDTYPE recordType = MDS_CDSADIR_CL_PRIMARY_RECORDTYPE; + + uint32 certTypeFormat() const; + uint32 certType() const { return certTypeFormat() >> 16; } + uint32 certEncoding() const { return certTypeFormat() & 0xFFFF; } + uint32 crlTypeFormat() const; + uint32 crlType() const { return crlTypeFormat() >> 16; } + uint32 crlEncoding() const { return crlTypeFormat() & 0xFFFF; } +}; + + +// +// The TP Primary relation +// +class TP : public PrimaryRecord { +public: + TP(); + static const CSSM_DB_RECORDTYPE recordType = MDS_CDSADIR_TP_PRIMARY_RECORDTYPE; + + uint32 certTypeFormat() const; + uint32 certType() const { return certTypeFormat() >> 16; } + uint32 certEncoding() const { return certTypeFormat() & 0xFFFF; } +}; + + +// +// The TP Policy-OIDS relation +// +class PolicyOids : public Record { +public: + PolicyOids(); + static const CSSM_DB_RECORDTYPE recordType = MDS_CDSADIR_TP_OIDS_RECORDTYPE; + + string moduleID() const; + uint32 subserviceID() const; + CssmData oid() const; + CssmData value() const; +}; + + +} // end namespace MDSClient +} // end namespace Security + +#endif // _H_CDSA_CLIENT_MDS_STANDARD diff --git a/libsecurity_cdsa_client/lib/mdsclient.cpp b/libsecurity_cdsa_client/lib/mdsclient.cpp new file mode 100644 index 00000000..16eade72 --- /dev/null +++ b/libsecurity_cdsa_client/lib/mdsclient.cpp @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2000-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. + */ + + +// +// mdsclient - friendly interface to CDSA MDS API +// +#include +#include + + +namespace Security { +namespace MDSClient { + + +// +// The MDS access object singleton +// +ModuleNexus mds; + + +// +// Directory construction initializes MDS and opens the "CDSA" database +// +Directory::Directory() + : mMemoryFunctions(Allocator::standard()) +{ + StLock _(mInitLock); + CssmError::check(MDS_Initialize(&mCallerGuid, &mMemoryFunctions, + this, &mCDSA.DLHandle)); + mCDSA.DBHandle = CSSM_INVALID_HANDLE; +} + + +// +// Cleanup (only called if the ModuleNexus is explicitly reset) +// +Directory::~Directory() +{ + if (mCDSA.DBHandle) + CssmError::check(DbClose(mCDSA)); + CssmError::check(MDS_Terminate(mds())); +} + + +// +// Open MDS database if needed +// +const MDS_DB_HANDLE &Directory::cdsa() const +{ + if (mCDSA.DBHandle == CSSM_INVALID_HANDLE) { + StLock _(mInitLock); + if (mCDSA.DBHandle == CSSM_INVALID_HANDLE) + CssmError::check(DbOpen(mCDSA.DLHandle, MDS_CDSA_DIRECTORY_NAME, NULL, + CSSM_DB_ACCESS_READ, // access mode + NULL, // credentials + NULL, // OpenParameters + &mCDSA.DBHandle)); + } + return mCDSA; +} + + +// +// The DLAccess implementation for MDS. +// We don't ever return record data, of course; we just zero it out. +// +CSSM_HANDLE Directory::dlGetFirst(const CSSM_QUERY &query, CSSM_DB_RECORD_ATTRIBUTE_DATA &attributes, + CSSM_DATA *data, CSSM_DB_UNIQUE_RECORD *&id) +{ + CSSM_HANDLE result; + switch (CSSM_RETURN rc = DataGetFirst(cdsa(), &query, &result, &attributes, NULL, &id)) { + case CSSM_OK: + if (data) + *data = CssmData(); + return result; + case CSSMERR_DL_ENDOFDATA: + return CSSM_INVALID_HANDLE; + default: + CssmError::throwMe(rc); + return CSSM_INVALID_HANDLE; // placebo + } +} + +bool Directory::dlGetNext(CSSM_HANDLE handle, CSSM_DB_RECORD_ATTRIBUTE_DATA &attributes, + CSSM_DATA *data, CSSM_DB_UNIQUE_RECORD *&id) +{ + CSSM_RETURN rc = DataGetNext(cdsa(), handle, &attributes, NULL, &id); + switch (rc) { + case CSSM_OK: + if (data) + *data = CssmData(); + return true; + case CSSMERR_DL_ENDOFDATA: + return false; + default: + CssmError::throwMe(rc); + return false; // placebo + } +} + +void Directory::dlAbortQuery(CSSM_HANDLE handle) +{ + CssmError::check(DataAbortQuery(cdsa(), handle)); +} + +void Directory::dlFreeUniqueId(CSSM_DB_UNIQUE_RECORD *id) +{ + CssmError::check(FreeUniqueRecord(cdsa(), id)); +} + +void Directory::dlDeleteRecord(CSSM_DB_UNIQUE_RECORD *id) +{ + CssmError::check(DataDelete(cdsa(), id)); +} + +Allocator &Directory::allocator() +{ + return Allocator::standard(); +} + + +// +// Public MDS operations +// +void Directory::install() +{ + CssmError::check(MDS_Install(this->mds())); +} + +void Directory::install(const MDS_InstallDefaults *defaults, + const char *path, const char *subdir, const char *file) +{ + CssmError::check(MDS_InstallFile(this->mds(), defaults, path, subdir, file)); +} + +void Directory::uninstall(const char *guid, uint32 ssid) +{ + CssmError::check(MDS_RemoveSubservice(this->mds(), guid, ssid)); +} + + +} // end namespace MDSClient +} // end namespace Security diff --git a/libsecurity_cdsa_client/lib/mdsclient.h b/libsecurity_cdsa_client/lib/mdsclient.h new file mode 100644 index 00000000..fcc0aa4e --- /dev/null +++ b/libsecurity_cdsa_client/lib/mdsclient.h @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2000-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. + */ + + +// +// mdsclient - friendly interface to CDSA MDS API +// +// It is useful to think of the mdsclient interface as "slightly below" the +// rest of the cdsa_client layer. It does not actually call into CSSM (we +// consider MDS as a separate facility, "slightly lower" than CSSM as well). +// This means that you can use mdsclient without creating a binary dependency +// on CSSM, and thus Security.framework. +// + +#ifndef _H_CDSA_CLIENT_MDSCLIENT +#define _H_CDSA_CLIENT_MDSCLIENT + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace Security { +namespace MDSClient { + +// import query sublanguage classes into MDSClient namespace +using CssmClient::Attribute; +using CssmClient::Query; +using CssmClient::Record; +using CssmClient::Table; + + +// +// A singleton for the MDS itself. +// This is automatically created as a ModuleNexus when needed. +// You can reset() it to release resources. +// Don't make your own. +// +class Directory : public MDS_FUNCS, public CssmClient::DLAccess { +public: + Directory(); + virtual ~Directory(); + + MDS_HANDLE mds() const { return mCDSA.DLHandle; } + const MDS_DB_HANDLE &cdsa() const; + +public: + CSSM_HANDLE dlGetFirst(const CSSM_QUERY &query, + CSSM_DB_RECORD_ATTRIBUTE_DATA &attributes, CSSM_DATA *data, + CSSM_DB_UNIQUE_RECORD *&id); + bool dlGetNext(CSSM_HANDLE handle, + CSSM_DB_RECORD_ATTRIBUTE_DATA &attributes, CSSM_DATA *data, + CSSM_DB_UNIQUE_RECORD *&id); + void dlAbortQuery(CSSM_HANDLE handle); + void dlFreeUniqueId(CSSM_DB_UNIQUE_RECORD *id); + void dlDeleteRecord(CSSM_DB_UNIQUE_RECORD *id); + Allocator &allocator(); + +public: + // not for ordinary use - system administration only + void install(); // system default install/regenerate + void install(const MDS_InstallDefaults *defaults, // defaults + const char *path, // path to bundle (NULL -> main) + const char *subdir = NULL, // subdirectory in Resources (NULL -> all) + const char *file = NULL); // individual file (NULL -> all) + void uninstall(const char *guid, uint32 ssid); + +private: + mutable MDS_DB_HANDLE mCDSA; // CDSA database handle + mutable Mutex mInitLock; // interlock for lazy DB open + CssmAllocatorMemoryFunctions mMemoryFunctions; + Guid mCallerGuid; //@@@ fake/unused +}; + +extern ModuleNexus mds; + + +} // end namespace MDSClient +} // end namespace Security + +#endif // _H_CDSA_CLIENT_MDSCLIENT diff --git a/libsecurity_cdsa_client/lib/multidldb.cpp b/libsecurity_cdsa_client/lib/multidldb.cpp new file mode 100644 index 00000000..71332079 --- /dev/null +++ b/libsecurity_cdsa_client/lib/multidldb.cpp @@ -0,0 +1,233 @@ +/* + * 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. + */ + + +// +// MultiDLDb implementation. +// + +#include +#include + + + +namespace Security +{ + +using namespace CssmClient; + +namespace CssmClient +{ + +// +// MultiDLDbDbCursorImpl declaration +// +class MultiDLDbDbCursorImpl : public DbCursorImpl +{ +public: + MultiDLDbDbCursorImpl(const MultiDLDb &parent, const CSSM_QUERY &query, Allocator &allocator); + MultiDLDbDbCursorImpl(const MultiDLDb &parent, uint32 capacity, Allocator &allocator); + virtual ~MultiDLDbDbCursorImpl(); + + bool next(DbAttributes *attributes, ::CssmDataContainer *data, DbUniqueRecord &uniqueId); +private: + MultiDLDb multiDLDb() { return parent(); } + void activate(); + void deactivate(); + + MultiDLDbImpl::ListRef mListRef; + MultiDLDbImpl::List::const_iterator mNext; + MultiDLDbImpl::List::const_iterator mEnd; + DbCursor mCursor; +}; + +} // end namespace CssmClient + +} // end namespace Security + +// +// MultiDLDbImpl +// +MultiDLDbImpl::MultiDLDbImpl(const vector &list, bool useSecureStorage, const Cssm &cssm) +: ObjectImpl(cssm), mListRef(list), mUseSecureStorage(useSecureStorage) +{ +} + +MultiDLDbImpl::MultiDLDbImpl(const vector &list, bool useSecureStorage) +: ObjectImpl(Cssm::standard()), mListRef(list), mUseSecureStorage(useSecureStorage) +{ +} + +MultiDLDbImpl::~MultiDLDbImpl() +{ + deactivate(); +} + +Db +MultiDLDbImpl::database(const DLDbIdentifier &dlDbIdentifier) +{ + StLock _(mLock); + DbMap::const_iterator it = mDbMap.find(dlDbIdentifier); + if (it != mDbMap.end()) + return it->second; + + Module module(dlDbIdentifier.ssuid().guid(), cssm()); + DL dl; + if (dlDbIdentifier.ssuid().subserviceType() & CSSM_SERVICE_CSP) + { + if (mUseSecureStorage) + dl = SSCSPDL(module); + else + dl = CSPDL(module); + } + else + dl = DL(module); + + dl->subserviceId(dlDbIdentifier.ssuid().subserviceId()); + dl->version(dlDbIdentifier.ssuid().version()); + Db db(dl, dlDbIdentifier.dbName()); + if (find(mListRef->begin(), mListRef->end(), dlDbIdentifier) != mListRef->end()) + mDbMap.insert(DbMap::value_type(dlDbIdentifier, db)); + + return db; +} + +void +MultiDLDbImpl::list(const vector &list) +{ + StLock _(mLock); + set oldList(mListRef->begin(), mListRef->end()); + mListRef = ListRef(list); + set newList(mListRef->begin(), mListRef->end()); + vector obsolete; + back_insert_iterator > ii(obsolete); + // Remove all db's from the map that were in oldList but are not in mListRef. + set_difference(oldList.begin(), oldList.end(), newList.begin(), newList.end(), ii); + for (vector::const_iterator it = obsolete.begin(); it != obsolete.end(); ++it) + mDbMap.erase(*it); +} + +DbCursorImpl * +MultiDLDbImpl::newDbCursor(const CSSM_QUERY &query, Allocator &allocator) +{ + return new MultiDLDbDbCursorImpl(MultiDLDb(this), query, allocator); +} + +DbCursorImpl * +MultiDLDbImpl::newDbCursor(uint32 capacity, Allocator &allocator) +{ + return new MultiDLDbDbCursorImpl(MultiDLDb(this), capacity, allocator); +} + +void +MultiDLDbImpl::activate() +{ +} + +void +MultiDLDbImpl::deactivate() +{ + StLock _(mLock); + mDbMap.erase(mDbMap.begin(), mDbMap.end()); +} + + +// +// MultiDLDbDbCursorImpl +// +MultiDLDbDbCursorImpl::MultiDLDbDbCursorImpl(const MultiDLDb &parent, + const CSSM_QUERY &query, Allocator &allocator) +: DbCursorImpl(parent, query, allocator) +{ +} + +MultiDLDbDbCursorImpl::MultiDLDbDbCursorImpl(const MultiDLDb &parent, + uint32 capacity, Allocator &allocator) +: DbCursorImpl(parent, capacity, allocator) +{ +} + +MultiDLDbDbCursorImpl::~MultiDLDbDbCursorImpl() +{ + try + { + deactivate(); + } + catch(...) {} +} + +bool +MultiDLDbDbCursorImpl::next(DbAttributes *attributes, ::CssmDataContainer *data, DbUniqueRecord &uniqueId) +{ + activate(); + for (;;) + { + if (!mCursor) + { + if (mNext == mEnd) + { + // This is how it ends. + deactivate(); + return false; + } + + mCursor = DbCursor(multiDLDb()->database(*mNext++), *this); + } + + try + { + if (mCursor->next(attributes, data, uniqueId)) + return true; + } + + catch(const CommonError &err) + { + OSStatus status = err.osStatus(); + if(status != CSSMERR_DL_DATASTORE_DOESNOT_EXIST) + throw; + } + + + + mCursor = DbCursor(); + } +} + +void +MultiDLDbDbCursorImpl::activate() +{ + if (!mActive) + { + mListRef = multiDLDb()->listRef(); + mNext = mListRef->begin(); + mEnd = mListRef->end(); + mActive = true; + } +} + +void +MultiDLDbDbCursorImpl::deactivate() +{ + if (mActive) + { + mActive = false; + mListRef = MultiDLDbImpl::ListRef(); + mNext = mEnd; + mCursor = DbCursor(); + } +} + diff --git a/libsecurity_cdsa_client/lib/multidldb.h b/libsecurity_cdsa_client/lib/multidldb.h new file mode 100644 index 00000000..efb33649 --- /dev/null +++ b/libsecurity_cdsa_client/lib/multidldb.h @@ -0,0 +1,101 @@ +/* + * 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. + */ + + +// +// multidldb interfaces for searching multiple dls or db with a single cursor. +// +#ifndef _H_CDSA_CLIENT_MULTIDLDB +#define _H_CDSA_CLIENT_MULTIDLDB 1 + +#include +#include + +namespace Security +{ + +namespace CssmClient +{ + +// +// The MultiDLDb class. +// +class MultiDLDbImpl : public ObjectImpl, public DbCursorMaker +{ +public: + struct List : public vector, public RefCount + { + List(const vector &list) : vector(list) {} + }; + + struct ListRef : public RefPointer + { + ListRef() {} + ListRef(const vector &list) : RefPointer(new List(list)) {} + }; + + MultiDLDbImpl(const vector &list, bool useSecureStorage, const Cssm &cssm); + MultiDLDbImpl(const vector &list, bool useSecureStorage); + virtual ~MultiDLDbImpl(); + + Cssm cssm() const { return parent(); } + Db database(const DLDbIdentifier &dlDbIdentifier); + ListRef listRef() { return mListRef; } + void list(const vector &list); + const vector &list() { return *mListRef; } + + // DbCursorMaker + virtual DbCursorImpl *newDbCursor(const CSSM_QUERY &query, Allocator &allocator); + virtual DbCursorImpl *newDbCursor(uint32 capacity, Allocator &allocator); + +protected: + void activate(); + void deactivate(); + +private: + typedef map DbMap; + + // Lock protecting this object during changes. + Mutex mLock; + ListRef mListRef; + DbMap mDbMap; + bool mUseSecureStorage; +}; + +class MultiDLDb : public Object +{ +public: + typedef MultiDLDbImpl Impl; + + explicit MultiDLDb(Impl *impl) : Object(impl) {} + MultiDLDb(const vector &list, bool useSecureStorage, const Cssm &cssm) + : Object(new Impl(list, useSecureStorage, cssm)) {} + MultiDLDb(const vector &list, bool useSecureStorage) + : Object(new Impl(list, useSecureStorage)) {} + + Impl *operator ->() const { return &impl(); } + Impl &operator *() const { return impl(); } + + // Conversion to DbCursorMaker + operator DbCursorMaker &() { return impl(); } +}; + +}; // end namespace CssmClient + +} // end namespace Security + +#endif // _H_CDSA_CLIENT_MULTIDLDB diff --git a/libsecurity_cdsa_client/lib/securestorage.cpp b/libsecurity_cdsa_client/lib/securestorage.cpp new file mode 100644 index 00000000..cc12b833 --- /dev/null +++ b/libsecurity_cdsa_client/lib/securestorage.cpp @@ -0,0 +1,646 @@ +/* + * 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 "securestorage.h" +#include +//#include //@@@CONV +#include +#include + +using namespace CssmClient; +//using namespace KeychainCore; + +// +// Manage CSPDL attachments +// +CSPDLImpl::CSPDLImpl(const Guid &guid) +: CSPImpl(Cssm::standard()->autoModule(guid)), +DLImpl(CSPImpl::module()) +{ +} + +CSPDLImpl::CSPDLImpl(const Module &module) +: CSPImpl(module), +DLImpl(module) +{ +} + +CSPDLImpl::~CSPDLImpl() +{ +} + +Allocator &CSPDLImpl::allocator() const +{ + DLImpl::allocator(); return CSPImpl::allocator(); +} + +void CSPDLImpl::allocator(Allocator &alloc) +{ + CSPImpl::allocator(alloc); DLImpl::allocator(alloc); +} + +bool CSPDLImpl::operator <(const CSPDLImpl &other) const +{ + return (static_cast(*this) < static_cast(other) || + (!(static_cast(other) < static_cast(*this)) + && static_cast(*this) < static_cast(other))); +} + +bool CSPDLImpl::operator ==(const CSPDLImpl &other) const +{ + return (static_cast(*this) == static_cast(other) + && static_cast(*this) == static_cast(other)); +} + +CSSM_SERVICE_MASK CSPDLImpl::subserviceMask() const +{ + return CSPImpl::subserviceType() | DLImpl::subserviceType(); +} + +void CSPDLImpl::subserviceId(uint32 id) +{ + CSPImpl::subserviceId(id); DLImpl::subserviceId(id); +} + + +// +// Secure storage +// +SSCSPDLImpl::SSCSPDLImpl(const Guid &guid) : CSPDLImpl::CSPDLImpl(guid) +{ +} + +SSCSPDLImpl::SSCSPDLImpl(const Module &module) : CSPDLImpl::CSPDLImpl(module) +{ +} + +SSCSPDLImpl::~SSCSPDLImpl() +{ +} + +DbImpl * +SSCSPDLImpl::newDb(const char *inDbName, const CSSM_NET_ADDRESS *inDbLocation) +{ + return new SSDbImpl(SSCSPDL(this), inDbName, inDbLocation); +} + + +// +// SSDbImpl -- Secure Storage Database Implementation +// +SSDbImpl::SSDbImpl(const SSCSPDL &cspdl, const char *inDbName, + const CSSM_NET_ADDRESS *inDbLocation) +: DbImpl(cspdl, inDbName, inDbLocation) +{ +} + +SSDbImpl::~SSDbImpl() +{ +} + +void +SSDbImpl::create() +{ + DbImpl::create(); +} + +void +SSDbImpl::open() +{ + DbImpl::open(); +} + +SSDbUniqueRecord +SSDbImpl::insert(CSSM_DB_RECORDTYPE recordType, + const CSSM_DB_RECORD_ATTRIBUTE_DATA *attributes, + const CSSM_DATA *data, + const CSSM_RESOURCE_CONTROL_CONTEXT *rc) +{ + // Get the handle of the DL underlying this CSPDL. + CSSM_DL_DB_HANDLE dldbh; + passThrough(CSSM_APPLECSPDL_DB_GET_HANDLE, NULL, + reinterpret_cast(&dldbh)); + + // Turn off autocommit on the underlying DL and remember the old state. + CSSM_BOOL autoCommit = CSSM_TRUE; + check(CSSM_DL_PassThrough(dldbh, CSSM_APPLEFILEDL_TOGGLE_AUTOCOMMIT, + 0, reinterpret_cast(&autoCommit))); + SSGroup group(SSDb(this), rc); + const CSSM_ACCESS_CREDENTIALS *cred = rc ? rc->AccessCred : NULL; + try + { + return insert(recordType, attributes, data, group, cred); + if (autoCommit) + { + // autoCommit was on so commit now that we are done and turn + // it back on. + check(CSSM_DL_PassThrough(dldbh, CSSM_APPLEFILEDL_COMMIT, NULL, NULL)); + CSSM_DL_PassThrough(dldbh, CSSM_APPLEFILEDL_TOGGLE_AUTOCOMMIT, + reinterpret_cast(autoCommit), NULL); + } + } + catch(...) + { + try { group->deleteKey(cred); } catch (...) {} + if (autoCommit) + { + // autoCommit was off so rollback since we failed and turn + // autoCommit back on. + CSSM_DL_PassThrough(dldbh, CSSM_APPLEFILEDL_ROLLBACK, NULL, NULL); + CSSM_DL_PassThrough(dldbh, CSSM_APPLEFILEDL_TOGGLE_AUTOCOMMIT, + reinterpret_cast(autoCommit), NULL); + } + throw; + } + + // keep the compiler happy -- this path is NEVER taken + CssmError::throwMe(0); +} + +SSDbUniqueRecord +SSDbImpl::insert(CSSM_DB_RECORDTYPE recordType, + const CSSM_DB_RECORD_ATTRIBUTE_DATA *attributes, + const CSSM_DATA *data, const SSGroup &group, + const CSSM_ACCESS_CREDENTIALS *cred) +{ + // Create an encoded dataBlob for this item. + CssmDataContainer dataBlob(allocator()); + group->encodeDataBlob(data, cred, dataBlob); + + // Insert the record with the new juicy dataBlob. + return SSDbUniqueRecord(safe_cast + (&(*DbImpl::insert(recordType, attributes, &dataBlob)))); +} + + +// DbCursorMaker +DbCursorImpl * +SSDbImpl::newDbCursor(const CSSM_QUERY &query, Allocator &allocator) +{ + return new SSDbCursorImpl(Db(this), query, allocator); +} + +DbCursorImpl * +SSDbImpl::newDbCursor(uint32 capacity, Allocator &allocator) +{ + return new SSDbCursorImpl(Db(this), capacity, allocator); +} + + +// SSDbUniqueRecordMaker +DbUniqueRecordImpl * +SSDbImpl::newDbUniqueRecord() +{ + return new SSDbUniqueRecordImpl(Db(this)); +} + + +// +// SSGroup -- Group key with acl, used to protect a group of items. +// +// @@@ Get this from a shared spot. +CSSM_DB_NAME_ATTR(SSGroupImpl::kLabel, 6, (char*) "Label", 0, NULL, BLOB); + +// Create a new group. +SSGroupImpl::SSGroupImpl(const SSDb &ssDb, + const CSSM_RESOURCE_CONTROL_CONTEXT *credAndAclEntry) +: KeyImpl(ssDb->csp()), mLabel(ssDb->allocator()) +{ + mLabel.Length = kLabelSize; + mLabel.Data = reinterpret_cast + (mLabel.mAllocator.malloc(mLabel.Length)); + + // Get our csp and set up a random number generation context. + CSP csp(this->csp()); + Random random(csp, CSSM_ALGID_APPLE_YARROW); + + // Generate a kLabelSize byte random number that will be the label of + // the key which we store in the dataBlob. + random.generate(mLabel, mLabel.Length); + + // Overwrite the first 4 bytes with the magic cookie for a group. + reinterpret_cast(mLabel.Data)[0] = h2n(uint32(kGroupMagic)); + + // @@@ Ensure that the label is unique (Chance of collision is 2^80 -- + // birthday paradox). + + // Generate a permanent 3DES key that we will use to encrypt the data. + GenerateKey genKey(csp, CSSM_ALGID_3DES_3KEY, 192); + genKey.database(ssDb); + + // Set the acl of the key correctly here + genKey.rcc(credAndAclEntry); + + // Generate the key + genKey(*this, KeySpec(CSSM_KEYUSE_ENCRYPT|CSSM_KEYUSE_DECRYPT, + CSSM_KEYATTR_PERMANENT|CSSM_KEYATTR_SENSITIVE, + mLabel)); + + // Activate ourself so CSSM_FreeKey will get called when we go out of + // scope. + activate(); +} + +// Lookup an existing group based on a dataBlob. +SSGroupImpl::SSGroupImpl(const SSDb &ssDb, const CSSM_DATA &dataBlob) +: KeyImpl(ssDb->csp()), mLabel(ssDb->allocator()) +{ + if (dataBlob.Length < kLabelSize + kIVSize) + CssmError::throwMe(CSSMERR_DL_RECORD_NOT_FOUND); // Not a SS record + + mLabel = CssmData(dataBlob.Data, kLabelSize); + if (*reinterpret_cast(mLabel.Data) != h2n (uint32(kGroupMagic))) + CssmError::throwMe(CSSMERR_DL_RECORD_NOT_FOUND); // Not a SS record + + // Look up the symmetric key with that label. + DbCursor cursor(new DbDbCursorImpl(ssDb, 0, Allocator::standard())); + cursor->recordType(CSSM_DL_DB_RECORD_SYMMETRIC_KEY); + cursor->add(CSSM_DB_EQUAL, kLabel, mLabel); + + DbUniqueRecord keyId; + CssmDataContainer keyData(ssDb->allocator()); + if (!cursor->next(NULL, &keyData, keyId)) + CssmError::throwMe(CSSMERR_DL_RECORD_NOT_FOUND); // The key can't be found + + // Set the key part of ourself. + static_cast(*this) = + *reinterpret_cast(keyData.Data); + + // Activate ourself so CSSM_FreeKey will get called when we go out of + // scope. + activate(); +} + +bool +SSGroupImpl::isGroup(const CSSM_DATA &dataBlob) +{ + return dataBlob.Length >= kLabelSize + kIVSize + && *reinterpret_cast(dataBlob.Data) == h2n(uint32(kGroupMagic)); +} + +const CssmData +SSGroupImpl::label() const +{ + return mLabel; +} + +void +SSGroupImpl::decodeDataBlob(const CSSM_DATA &dataBlob, + const CSSM_ACCESS_CREDENTIALS *cred, + Allocator &allocator, CSSM_DATA &data) +{ + // First get the IV and the cipherText from the blob. + CssmData iv(&dataBlob.Data[kLabelSize], kIVSize); + CssmData cipherText(&dataBlob.Data[kLabelSize + kIVSize], + dataBlob.Length - (kLabelSize + kIVSize)); + + CssmDataContainer plainText1(allocator); + CssmDataContainer plainText2(allocator); + // Decrypt the data + // @@@ Don't use staged decrypt once the AppleCSPDL can do combo + // encryption. + // Setup decryption context + Decrypt decrypt(csp(), algorithm()); + decrypt.mode(CSSM_ALGMODE_CBCPadIV8); + decrypt.padding(CSSM_PADDING_PKCS1); + decrypt.initVector(iv); + decrypt.key(Key(this)); + decrypt.cred(AccessCredentials::overlay(cred)); + decrypt.decrypt(&cipherText, 1, &plainText1, 1); + decrypt.final(plainText2); + + // Use DL allocator for allocating memory for data. + uint32 length = plainText1.Length + plainText2.Length; + data.Data = allocator.alloc(length); + data.Length = length; + memcpy(data.Data, plainText1.Data, plainText1.Length); + memcpy(&data.Data[plainText1.Length], plainText2.Data, plainText2.Length); +} + +void +SSGroupImpl::encodeDataBlob(const CSSM_DATA *data, + const CSSM_ACCESS_CREDENTIALS *cred, + CssmDataContainer &dataBlob) +{ + // Get our csp and set up a random number generation context. + CSP csp(this->csp()); + Random random(csp, CSSM_ALGID_APPLE_YARROW); + + // Encrypt data using key and encode it in a dataBlob. + + // First calculate a random IV. + uint8 ivBuf[kIVSize]; + CssmData iv(ivBuf, kIVSize); + random.generate(iv, kIVSize); + + // Setup encryption context + Encrypt encrypt(csp, algorithm()); + encrypt.mode(CSSM_ALGMODE_CBCPadIV8); + encrypt.padding(CSSM_PADDING_PKCS1); + encrypt.initVector(iv); + encrypt.key(Key(this)); + encrypt.cred(AccessCredentials::overlay(cred)); + + // Encrypt the data + const CssmData nothing; + const CssmData *plainText = data ? CssmData::overlay(data) : ¬hing; + // @@@ Don't use staged encrypt once the AppleCSPDL can do combo + // encryption. + CssmDataContainer cipherText1, cipherText2; + encrypt.encrypt(plainText, 1, &cipherText1, 1); + encrypt.final(cipherText2); + + // Create a dataBlob containing the label followed by the IV followed + // by the cipherText. + uint32 length = (kLabelSize + kIVSize + + cipherText1.Length + cipherText2.Length); + dataBlob.Data = dataBlob.mAllocator.alloc(length); + dataBlob.Length = length; + memcpy(dataBlob.Data, mLabel.Data, kLabelSize); + memcpy(&dataBlob.Data[kLabelSize], iv.Data, kIVSize); + memcpy(&dataBlob.Data[kLabelSize + kIVSize], + cipherText1.Data, cipherText1.Length); + memcpy(&dataBlob.Data[kLabelSize + kIVSize + cipherText1.Length], + cipherText2.Data, cipherText2.Length); +} + + +// +// SSDbCursorImpl -- Secure Storage Database Cursor Implementation. +// +SSDbCursorImpl::SSDbCursorImpl(const Db &db, const CSSM_QUERY &query, + Allocator &allocator) +: DbDbCursorImpl(db, query, allocator) +{ +} + +SSDbCursorImpl::SSDbCursorImpl(const Db &db, uint32 capacity, + Allocator &allocator) +: DbDbCursorImpl(db, capacity, allocator) +{ +} + +bool +SSDbCursorImpl::next(DbAttributes *attributes, ::CssmDataContainer *data, + DbUniqueRecord &uniqueId) +{ + return next(attributes, data, uniqueId, NULL); +} + +bool +SSDbCursorImpl::next(DbAttributes *attributes, ::CssmDataContainer *data, + DbUniqueRecord &uniqueId, + const CSSM_ACCESS_CREDENTIALS *cred) +{ + if (!data) + return DbDbCursorImpl::next(attributes, data, uniqueId); + + DbAttributes noAttrs, *attrs; + attrs = attributes ? attributes : &noAttrs; + + // Get the datablob for this record + CssmDataContainer dataBlob(allocator()); + for (;;) + { + if (!DbDbCursorImpl::next(attrs, &dataBlob, uniqueId)) + return false; + + // Keep going until we find a non key type record. + CSSM_DB_RECORDTYPE rt = attrs->recordType(); + if (rt != CSSM_DL_DB_RECORD_SYMMETRIC_KEY + && rt != CSSM_DL_DB_RECORD_PRIVATE_KEY + && rt != CSSM_DL_DB_RECORD_PUBLIC_KEY) + { + // @@@ Check the label and if it doesn't start with the magic for a SSKey return the key. + break; + } + else + { + // Free the key we just retrieved + database()->csp()->freeKey(*reinterpret_cast(dataBlob.Data)); + } + } + + if (!SSGroupImpl::isGroup(dataBlob)) + { + data->Data = dataBlob.Data; + data->Length = dataBlob.Length; + dataBlob.Data = NULL; + dataBlob.Length = 0; + return true; + } + + // Get the group for dataBlob + SSGroup group(database(), dataBlob); + + // Decode the dataBlob, pass in the DL allocator. + group->decodeDataBlob(dataBlob, cred, database()->allocator(), *data); + return true; +} + +bool +SSDbCursorImpl::nextKey(DbAttributes *attributes, Key &key, + DbUniqueRecord &uniqueId) +{ + DbAttributes noAttrs, *attrs; + attrs = attributes ? attributes : &noAttrs; + CssmDataContainer keyData(database()->allocator()); + for (;;) + { + if (!DbDbCursorImpl::next(attrs, &keyData, uniqueId)) + return false; + // Keep going until we find a key type record. + CSSM_DB_RECORDTYPE rt = attrs->recordType(); + if (rt == CSSM_DL_DB_RECORD_SYMMETRIC_KEY + || rt == CSSM_DL_DB_RECORD_PRIVATE_KEY + || rt == CSSM_DL_DB_RECORD_PUBLIC_KEY) + break; + } + + key = Key(database()->csp(), *reinterpret_cast(keyData.Data)); + return true; +} + +void +SSDbCursorImpl::activate() +{ + return DbDbCursorImpl::activate(); +} + +void +SSDbCursorImpl::deactivate() +{ + return DbDbCursorImpl::deactivate(); +} + + +// +// SSDbUniqueRecordImpl -- Secure Storage UniqueRecord Implementation. +// +SSDbUniqueRecordImpl::SSDbUniqueRecordImpl(const Db &db) +: DbUniqueRecordImpl(db) +{ +} + +SSDbUniqueRecordImpl::~SSDbUniqueRecordImpl() +{ +} + +void +SSDbUniqueRecordImpl::deleteRecord() +{ + deleteRecord(NULL); +} + +void +SSDbUniqueRecordImpl::deleteRecord(const CSSM_ACCESS_CREDENTIALS *cred) +{ + // Get the datablob for this record + // @@@ Fixme so we don't need to call DbUniqueRecordImpl::get + CssmDataContainer dataBlob(allocator()); + DbAttributes attributes; + + DbUniqueRecordImpl::get(&attributes, &dataBlob); + CSSM_KEY_PTR keyPtr = (CSSM_KEY_PTR) dataBlob.data(); + + // delete data part first: + // (1) don't leave data without keys around + // (2) delete orphaned data anyway + DbUniqueRecordImpl::deleteRecord(); + + // @@@ Use transactions? + if (SSGroupImpl::isGroup(dataBlob)) + try { + // Get the group for dataBlob + SSGroup group(database(), dataBlob); + // Delete the group (key) + group->deleteKey(cred); + } catch (const CssmError &err) { + switch (err.error) { + case CSSMERR_DL_RECORD_NOT_FOUND: + // Zombie item (no group key). Finally at peace! No error + break; + default: + + if (attributes.recordType() == CSSM_DL_DB_RECORD_PUBLIC_KEY || + attributes.recordType() == CSSM_DL_DB_RECORD_PRIVATE_KEY || + attributes.recordType() == CSSM_DL_DB_RECORD_SYMMETRIC_KEY) + { + allocator().free(keyPtr->KeyData.Data); + } + + throw; + } + } + + if (attributes.recordType() == CSSM_DL_DB_RECORD_PUBLIC_KEY || + attributes.recordType() == CSSM_DL_DB_RECORD_PRIVATE_KEY || + attributes.recordType() == CSSM_DL_DB_RECORD_SYMMETRIC_KEY) + { + allocator().free(keyPtr->KeyData.Data); + } +} + +void +SSDbUniqueRecordImpl::modify(CSSM_DB_RECORDTYPE recordType, + const CSSM_DB_RECORD_ATTRIBUTE_DATA *attributes, + const CSSM_DATA *data, + CSSM_DB_MODIFY_MODE modifyMode) +{ + modify(recordType, attributes, data, modifyMode, NULL); +} + +void +SSDbUniqueRecordImpl::modify(CSSM_DB_RECORDTYPE recordType, + const CSSM_DB_RECORD_ATTRIBUTE_DATA *attributes, + const CSSM_DATA *data, + CSSM_DB_MODIFY_MODE modifyMode, + const CSSM_ACCESS_CREDENTIALS *cred) +{ + if (!data) + { + DbUniqueRecordImpl::modify(recordType, attributes, NULL, modifyMode); + return; + } + + // Get the datablob for this record + // @@@ Fixme so we don't need to call DbUniqueRecordImpl::get + CssmDataContainer oldDataBlob(allocator()); + DbUniqueRecordImpl::get(NULL, &oldDataBlob); + + if (!SSGroupImpl::isGroup(oldDataBlob)) + { + DbUniqueRecordImpl::modify(recordType, attributes, data, modifyMode); + return; + } + + // Get the group for oldDataBlob + SSGroup group(database(), oldDataBlob); + + // Create a new dataBlob. + CssmDataContainer dataBlob(allocator()); + group->encodeDataBlob(data, cred, dataBlob); + DbUniqueRecordImpl::modify(recordType, attributes, &dataBlob, modifyMode); +} + +void +SSDbUniqueRecordImpl::get(DbAttributes *attributes, ::CssmDataContainer *data) +{ + get(attributes, data, NULL); +} + +void +SSDbUniqueRecordImpl::get(DbAttributes *attributes, ::CssmDataContainer *data, + const CSSM_ACCESS_CREDENTIALS *cred) +{ + if (!data) + { + DbUniqueRecordImpl::get(attributes, NULL); + return; + } + + // Get the datablob for this record + // @@@ Fixme so we don't need to call DbUniqueRecordImpl::get + CssmDataContainer dataBlob(allocator()); + DbUniqueRecordImpl::get(attributes, &dataBlob); + + if (!SSGroupImpl::isGroup(dataBlob)) + { + data->Data = dataBlob.Data; + data->Length = dataBlob.Length; + dataBlob.Data = NULL; + dataBlob.Length = 0; + return; + } + + // Get the group for dataBlob + SSGroup group(database(), dataBlob); + + // Decode the dataBlob, pass in the DL allocator. + group->decodeDataBlob(dataBlob, cred, allocator(), *data); +} + +SSGroup +SSDbUniqueRecordImpl::group() +{ + // Get the datablob for this record + // @@@ Fixme so we don't need to call DbUniqueRecordImpl::get + CssmDataContainer dataBlob(allocator()); + DbUniqueRecordImpl::get(NULL, &dataBlob); + return SSGroup(database(), dataBlob); +} diff --git a/libsecurity_cdsa_client/lib/securestorage.h b/libsecurity_cdsa_client/lib/securestorage.h new file mode 100644 index 00000000..2771f4bb --- /dev/null +++ b/libsecurity_cdsa_client/lib/securestorage.h @@ -0,0 +1,343 @@ +/* + * 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. + */ + + +// +// securestorage - client interface to CSP DLs and their operations +// +#ifndef _H_CDSA_CLIENT_SECURESTORAGE +#define _H_CDSA_CLIENT_SECURESTORAGE 1 + +#include +#include +#include + +namespace Security +{ + +namespace CssmClient +{ + +// +// A CSP and a DL attachment of the same subservice +// +// This gives us 2 Object instances, but we make sure that have the same +// mImpl. Currently this class has no behaviour, but it will get some in +// the future. +// +class CSPDLImpl : public CSPImpl, public DLImpl +{ +public: + CSPDLImpl(const Guid &guid); + CSPDLImpl(const Module &module); + virtual ~CSPDLImpl(); + + // Object methods. + bool isActive() const { return CSPImpl::isActive() || DLImpl::isActive(); } + + virtual Allocator &allocator() const; + virtual void allocator(Allocator &alloc); + + virtual bool operator <(const CSPDLImpl &other) const; + virtual bool operator ==(const CSPDLImpl &other) const; + + // Attachment methods. + virtual CSSM_SERVICE_MASK subserviceMask() const; + virtual void subserviceId(uint32 id); + + uint32 subserviceId() const { return CSPImpl::subserviceId(); } + CSSM_ATTACH_FLAGS cspFlags() const { return CSPImpl::flags(); } + void cspFlags(CSSM_ATTACH_FLAGS f) { CSPImpl::flags(f); } + CSSM_ATTACH_FLAGS dlFlags() const { return DLImpl::flags(); } + void dlFlags(CSSM_ATTACH_FLAGS f) { DLImpl::flags(f); } + + void attach() { CSPImpl::attach(); DLImpl::attach(); } + void detach() { CSPImpl::detach(); DLImpl::detach(); } + bool attached() const { return CSPImpl::attached() || DLImpl::attached(); } + + Module module() const { return CSPImpl::module(); } + const Guid &guid() const { return CSPImpl::guid(); } + CSSM_MODULE_HANDLE cspHandle() { return CSPImpl::handle(); } + CSSM_MODULE_HANDLE dlHandle() { return DLImpl::handle(); } + + CssmSubserviceUid subserviceUid() const + { return CSPImpl::subserviceUid(); } + +private: +}; + + +class CSPDL : public CSP, public DL +{ +public: + typedef CSPDLImpl Impl; + + explicit CSPDL(Impl *impl) : CSP(impl), DL(impl) {} + CSPDL(const Guid &guid) : CSP(new Impl(guid)), DL(&CSP::impl()) {} + CSPDL(const Module &module) + : CSP(new Impl(module)), DL(&CSP::impl()) {} + + //template _Impl &impl() const + //{ return CSP::impl<_Impl>(); } + + Impl *get() const { return &CSP::impl(); } + Impl *operator ->() const { return &CSP::impl(); } + Impl &operator *() const { return CSP::impl(); } + + // Conversion operators must be here + bool operator !() const { return !get(); } + operator bool() const { return get(); } + + bool operator <(const CSPDL &other) const + { return *this && other ? **this < *other : get() < other.get(); } + bool operator ==(const CSPDL &other) const + { return *this && other ? **this == *other : get() == other.get(); } +}; + + +// +// SSCSPDL -- Secure storage class +// +class SSCSPDLImpl : public CSPDLImpl +{ +public: + SSCSPDLImpl(const Guid &guid); + SSCSPDLImpl(const Module &module); + virtual ~SSCSPDLImpl(); + + // DbMaker + DbImpl *newDb(const char *inDbName, const CSSM_NET_ADDRESS *inDbLocation); +private: +}; + +class SSCSPDL : public CSPDL +{ +public: + typedef SSCSPDLImpl Impl; + + explicit SSCSPDL(Impl *impl) : CSPDL(impl) {} + SSCSPDL(const Guid &guid) : CSPDL(new Impl(guid)) {} + SSCSPDL(const Module &module) : CSPDL(new Impl(module)) {} + + Impl *operator ->() const { return &CSP::impl(); } + Impl &operator *() const { return CSP::impl(); } +}; + + +// +// SSDbImpl -- A Security Storage Db object. +// +class SSGroup; +class SSDbUniqueRecord; + +class SSDbImpl : public DbImpl +{ +public: + SSDbImpl(const SSCSPDL &cspdl, + const char *inDbName, const CSSM_NET_ADDRESS *inDbLocation); + virtual ~SSDbImpl(); + + void create(); + void open(); + + SSDbUniqueRecord insert(CSSM_DB_RECORDTYPE recordType, + const CSSM_DB_RECORD_ATTRIBUTE_DATA *attributes, + const CSSM_DATA *data, + const CSSM_RESOURCE_CONTROL_CONTEXT *rc = NULL); + + SSDbUniqueRecord insert(CSSM_DB_RECORDTYPE recordType, + const CSSM_DB_RECORD_ATTRIBUTE_DATA *attributes, + const CSSM_DATA *data, const SSGroup &group, + const CSSM_ACCESS_CREDENTIALS *cred); + + // DbCursorMaker + DbCursorImpl *newDbCursor(const CSSM_QUERY &query, + Allocator &allocator); + DbCursorImpl *newDbCursor(uint32 capacity, Allocator &allocator); + + // SSDbUniqueRecordMaker + DbUniqueRecordImpl *newDbUniqueRecord(); + + CSP csp() { return parent(); } +}; + +class SSDb : public Db +{ +public: + typedef SSDbImpl Impl; + + explicit SSDb(Impl *impl) : Db(impl) {} + SSDb(const SSCSPDL &cspdl, const char *inDbName, + const CSSM_NET_ADDRESS *inDbLocation = NULL) + : Db(cspdl->newDb(inDbName, inDbLocation)) {} + + Impl *operator ->() const { return &impl(); } + Impl &operator *() const { return impl(); } +}; + + +// +// SSGroup -- Group key with acl, used to protect a group of items. +// +class SSGroupImpl : public KeyImpl +{ +public: + SSGroupImpl(const SSDb &ssDb, const CSSM_DATA &dataBlob); + SSGroupImpl(const SSDb &ssDb, + const CSSM_RESOURCE_CONTROL_CONTEXT *credAndAclEntry); + + static bool isGroup(const CSSM_DATA &dataBlob); + + const CssmData label() const; + void decodeDataBlob(const CSSM_DATA &dataBlob, + const CSSM_ACCESS_CREDENTIALS *cred, + Allocator &allocator, CSSM_DATA &data); + void encodeDataBlob(const CSSM_DATA *data, + const CSSM_ACCESS_CREDENTIALS *cred, + CssmDataContainer &dataBlob); + +private: + // Constants + enum + { + // Label prefix for a secure storage group + kGroupMagic = FOUR_CHAR_CODE('ssgp'), + + // Size of label (including prefix) + kLabelSize = 20, + + // Size of IV + kIVSize = 8 + }; + + CSSM_DB_ATTR_DECL(kLabel); + + CssmDataContainer mLabel; +}; + +class SSGroup : public Key +{ +public: + typedef SSGroupImpl Impl; + explicit SSGroup(Impl *impl) : Key(impl) {} + + SSGroup() : Key(NULL) {} + + // Create a new group. + SSGroup(const SSDb &ssDb, + const CSSM_RESOURCE_CONTROL_CONTEXT *credAndAclEntry) + : Key(new Impl(ssDb, credAndAclEntry)) {} + + // Lookup an existing group based on a dataBlob. + SSGroup(const SSDb &ssDb, const CSSM_DATA &dataBlob) + : Key(new Impl(ssDb, dataBlob)) {} + + Impl *operator ->() const { return &impl(); } + Impl &operator *() const { return impl(); } +}; + + +// +// SSDbCursor -- Cursor for iterating over Securely Stored records (or keys) +// +class SSDbCursorImpl : public DbDbCursorImpl +{ +public: + SSDbCursorImpl(const Db &db, const CSSM_QUERY &query, + Allocator &allocator); + SSDbCursorImpl(const Db &db, uint32 capacity, + Allocator &allocator); + + bool next(DbAttributes *attributes, ::CssmDataContainer *data, + DbUniqueRecord &uniqueId); + bool next(DbAttributes *attributes, ::CssmDataContainer *data, + DbUniqueRecord &uniqueId, const CSSM_ACCESS_CREDENTIALS *cred); + bool nextKey(DbAttributes *attributes, Key &key, DbUniqueRecord &uniqueId); + //bool nextGroup(DbAttributes *attributes, SSGroup &group, DbUniqueRecord &uniqueId); + + SSDb database() { return parent(); } +protected: + void activate(); + void deactivate(); +}; + +class SSDbCursor : public DbCursor +{ +public: + typedef SSDbCursorImpl Impl; + + explicit SSDbCursor(Impl *impl) : DbCursor(impl) {} + SSDbCursor(const SSDb &ssDb, const CSSM_QUERY &query, + Allocator &allocator = Allocator::standard()) + : DbCursor(ssDb->newDbCursor(query, allocator)) {} + SSDbCursor(const SSDb &ssDb, const uint32 capacity = 0, + Allocator &allocator = Allocator::standard()) + : DbCursor(ssDb->newDbCursor(capacity, allocator)) {} + + Impl *operator ->() const { return &impl(); } + Impl &operator *() const { return impl(); } +}; + + +// +// SSDbUniqueRecord +// +class SSDbUniqueRecordImpl : public DbUniqueRecordImpl +{ +public: + SSDbUniqueRecordImpl(const Db &db); + virtual ~SSDbUniqueRecordImpl(); + + void deleteRecord(); + void deleteRecord(const CSSM_ACCESS_CREDENTIALS *cred); + void modify(CSSM_DB_RECORDTYPE recordType, + const CSSM_DB_RECORD_ATTRIBUTE_DATA *attributes, + const CSSM_DATA *data, + CSSM_DB_MODIFY_MODE modifyMode); + void modify(CSSM_DB_RECORDTYPE recordType, + const CSSM_DB_RECORD_ATTRIBUTE_DATA *attributes, + const CSSM_DATA *data, + CSSM_DB_MODIFY_MODE modifyMode, + const CSSM_ACCESS_CREDENTIALS *cred); + void get(DbAttributes *attributes, ::CssmDataContainer *data); + void get(DbAttributes *attributes, ::CssmDataContainer *data, + const CSSM_ACCESS_CREDENTIALS *cred); + + SSDb database() { return parent(); } + + // Return the group that this record is in. + SSGroup group(); +}; + +class SSDbUniqueRecord : public DbUniqueRecord +{ +public: + typedef SSDbUniqueRecordImpl Impl; + + explicit SSDbUniqueRecord(Impl *impl) : DbUniqueRecord(impl) {} + SSDbUniqueRecord(const SSDb &ssDb) + : DbUniqueRecord(ssDb->newDbUniqueRecord()) {} + + Impl *operator ->() const { return &impl(); } + Impl &operator *() const { return impl(); } +}; + +}; // end namespace CssmClient + +} // end namespace Security + +#endif //_H_CDSA_CLIENT_SECURESTORAGE diff --git a/libsecurity_cdsa_client/lib/signclient.cpp b/libsecurity_cdsa_client/lib/signclient.cpp new file mode 100644 index 00000000..6b5e0377 --- /dev/null +++ b/libsecurity_cdsa_client/lib/signclient.cpp @@ -0,0 +1,96 @@ +/* + * 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. + */ + + +// +// signclient - client interface to CSSM sign/verify contexts +// +#include + +using namespace CssmClient; + + +// +// Common features of signing and verify contexts +// +void SigningContext::activate() +{ + if (!mActive) + { + check(CSSM_CSP_CreateSignatureContext(attachment()->handle(), mAlgorithm, + cred(), mKey, &mHandle)); + mActive = true; + } +} + + +// +// Signing +// +void Sign::sign(const CssmData *data, uint32 count, CssmData &signature) +{ + unstaged(); + check(CSSM_SignData(handle(), data, count, mSignOnly, &signature)); +} + +void Sign::init() +{ + check(CSSM_SignDataInit(handle())); + mStaged = true; +} + +void Sign::sign(const CssmData *data, uint32 count) +{ + staged(); + check(CSSM_SignDataUpdate(handle(), data, count)); +} + +void Sign::operator () (CssmData &signature) +{ + staged(); + check(CSSM_SignDataFinal(handle(), &signature)); + mStaged = false; +} + + +// +// Verifying +// +void Verify::verify(const CssmData *data, uint32 count, const CssmData &signature) +{ + unstaged(); + check(CSSM_VerifyData(handle(), data, count, mSignOnly, &signature)); +} + +void Verify::init() +{ + check(CSSM_VerifyDataInit(handle())); + mStaged = true; +} + +void Verify::verify(const CssmData *data, uint32 count) +{ + staged(); + check(CSSM_VerifyDataUpdate(handle(), data, count)); +} + +void Verify::operator () (const CssmData &signature) +{ + staged(); + check(CSSM_VerifyDataFinal(handle(), &signature)); + mStaged = false; +} diff --git a/libsecurity_cdsa_client/lib/signclient.h b/libsecurity_cdsa_client/lib/signclient.h new file mode 100644 index 00000000..a0e2fe0b --- /dev/null +++ b/libsecurity_cdsa_client/lib/signclient.h @@ -0,0 +1,93 @@ +/* + * 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. + */ + + +// +// signclient - client interface to CSSM sign/verify contexts +// +#ifndef _H_CDSA_CLIENT_SIGNCLIENT +#define _H_CDSA_CLIENT_SIGNCLIENT 1 + +#include +#include + +namespace Security { +namespace CssmClient { + + +// +// A signing/verifying context +// +class SigningContext : public Context +{ +public: + SigningContext(const CSP &csp, CSSM_ALGORITHMS alg, CSSM_ALGORITHMS signOnly = CSSM_ALGID_NONE) + : Context(csp, alg), mSignOnly(signOnly) { } + + Key key() const { assert(mKey); return mKey; } + void key(const Key &k) { mKey = k; set(CSSM_ATTRIBUTE_KEY, mKey); } + + CSSM_ALGORITHMS signOnlyAlgorithm() const { return mSignOnly; } + void signOnlyAlgorithm(CSSM_ALGORITHMS alg) { mSignOnly = alg; } + +protected: + void activate(); + CSSM_ALGORITHMS mSignOnly; + Key mKey; +}; + + +class Sign : public SigningContext +{ +public: + Sign(const CSP &csp, CSSM_ALGORITHMS alg, CSSM_ALGORITHMS signOnly = CSSM_ALGID_NONE) + : SigningContext(csp, alg, signOnly) { } + + // integrated + void sign(const CssmData &data, CssmData &signature) { sign(&data, 1, signature); } + void sign(const CssmData *data, uint32 count, CssmData &signature); + + // staged + void init(); // Optional + void sign(const CssmData &data) { sign(&data, 1); } + void sign(const CssmData *data, uint32 count); + void operator () (CssmData &signature); + CssmData operator () () { CssmData signature; (*this)(signature); return signature; } +}; + +class Verify : public SigningContext +{ +public: + Verify(const CSP &csp, CSSM_ALGORITHMS alg, CSSM_ALGORITHMS verifyOnly = CSSM_ALGID_NONE) + : SigningContext(csp, alg, verifyOnly) { } + + // integrated + void verify(const CssmData &data, const CssmData &signature) { verify(&data, 1, signature); } + void verify(const CssmData *data, uint32 count, const CssmData &signature); + + // staged + void init(); // Optional + void verify(const CssmData &data) { verify(&data, 1); } + void verify(const CssmData *data, uint32 count); + void operator () (const CssmData &signature); +}; + +} // end namespace CssmClient + +} // end namespace Security + +#endif // _H_CDSA_CLIENT_SIGNCLIENT diff --git a/libsecurity_cdsa_client/lib/tpclient.cpp b/libsecurity_cdsa_client/lib/tpclient.cpp new file mode 100644 index 00000000..4e2f779b --- /dev/null +++ b/libsecurity_cdsa_client/lib/tpclient.cpp @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2000-2002 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. + */ + + +// +// tpclient - client interface to CSSM TPs and their operations +// +#include + +namespace Security { +namespace CssmClient { + + +// +// Manage TP attachments +// +TPImpl::TPImpl(const Guid &guid) + : AttachmentImpl(guid, CSSM_SERVICE_TP), mUseCL(NULL), mUseCSP(NULL), + mOwnCL(false), mOwnCSP(false) +{ +} + +TPImpl::TPImpl(const Module &module) + : AttachmentImpl(module, CSSM_SERVICE_TP), mUseCL(NULL), mUseCSP(NULL), + mOwnCL(false), mOwnCSP(false) +{ +} + +TPImpl::~TPImpl() +{ + if (mOwnCL) + delete mUseCL; + if (mOwnCSP) + delete mUseCSP; +} + + +// +// Verify a CertGroup +// +void TPImpl::certGroupVerify(const CertGroup &certGroup, + const TPVerifyContext &context, + TPVerifyResult *result) +{ + setupCL(); + setupCSP(); + check(CSSM_TP_CertGroupVerify(handle(), (*mUseCL)->handle(), (*mUseCSP)->handle(), + &certGroup, &context, result)); +} + + +// +// Initialize auxiliary modules for operation +// +void TPImpl::setupCL() +{ + if (mUseCL == NULL) { + secdebug("tpclient", "TP is auto-attaching supporting CL"); + mUseCL = new CL(gGuidAppleX509CL); + mOwnCL = true; + } +} + +void TPImpl::setupCSP() +{ + if (mUseCSP == NULL) { + secdebug("tpclient", "TP is auto-attaching supporting CSP"); + mUseCSP = new CSP(gGuidAppleCSP); + mOwnCSP = true; + } +} + +void TPImpl::use(CL &cl) +{ + if (mOwnCL) + delete mUseCL; + mUseCL = &cl; + mOwnCL = false; +} + +void TPImpl::use(CSP &csp) +{ + if (mOwnCSP) + delete mUseCSP; + mUseCSP = &csp; + mOwnCSP = false; +} + +CL &TPImpl::usedCL() +{ + setupCL(); + return *mUseCL; +} + +CSP &TPImpl::usedCSP() +{ + setupCSP(); + return *mUseCSP; +} + + +// +// A TPBuildVerifyContext +// +TPBuildVerifyContext::TPBuildVerifyContext(CSSM_TP_ACTION action, Allocator &alloc) + : allocator(alloc) +{ + // clear out the PODs + clearPod(); + mCallerAuth.clearPod(); + mDlDbList.clearPod(); + + // set initial elements + Action = action; + callerAuthPtr(&mCallerAuth); + mCallerAuth.dlDbList() = &mDlDbList; +} + + +} // end namespace CssmClient +} // end namespace Security + diff --git a/libsecurity_cdsa_client/lib/tpclient.h b/libsecurity_cdsa_client/lib/tpclient.h new file mode 100644 index 00000000..f655d3a9 --- /dev/null +++ b/libsecurity_cdsa_client/lib/tpclient.h @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2000-2002 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. + */ + + +// +// tpclient - client interface to CSSM TPs and their operations +// +#ifndef _H_CDSA_CLIENT_TPCLIENT +#define _H_CDSA_CLIENT_TPCLIENT 1 + +#include +#include +#include +#include +#include +#include + + +namespace Security { +namespace CssmClient { + + +// +// A TP attachment +// +class TPImpl : public AttachmentImpl +{ +public: + TPImpl(const Guid &guid); + TPImpl(const Module &module); + virtual ~TPImpl(); + +public: + // the CL and CSP used with many TP operations is usually + // pretty stable. The system may even figure them out + // automatically in the future. + void use(CL &cl); + void use(CSP &csp); + CL &usedCL(); + CSP &usedCSP(); + +public: + void certGroupVerify(const CertGroup &certGroup, const TPVerifyContext &context, + TPVerifyResult *result); + +private: + void setupCL(); // setup mUseCL + void setupCSP(); // setup mUseCSP + +private: + CL *mUseCL; // use this CL for TP operation + CSP *mUseCSP; // use this CSP for TP operation + bool mOwnCL, mOwnCSP; // whether we've made our own +}; + + +class TP : public Attachment +{ +public: + typedef TPImpl Impl; + + explicit TP(Impl *impl) : Attachment(impl) {} + TP(const Guid &guid) : Attachment(new Impl(guid)) {} + TP(const Module &module) : Attachment(new Impl(module)) {} + + Impl *operator ->() const { return &impl(); } + Impl &operator *() const { return impl(); } +}; + + +// +// A self-building TPVerifyContext. +// This is a TPVerifyContext, but it's NOT A PODWRAPPER (it's larger). +// +// NOTE: This is not a client-side object. +// +class TPBuildVerifyContext : public TPVerifyContext { +public: + TPBuildVerifyContext(CSSM_TP_ACTION action = CSSM_TP_ACTION_DEFAULT, + Allocator &alloc = Allocator::standard()); + + Allocator &allocator; + +private: + TPCallerAuth mCallerAuth; + PolicyInfo mPolicyInfo; + CssmDlDbList mDlDbList; +}; + + +} // end namespace CssmClient +} // end namespace Security + +#endif // _H_CDSA_CLIENT_CLCLIENT diff --git a/libsecurity_cdsa_client/lib/wrapkey.cpp b/libsecurity_cdsa_client/lib/wrapkey.cpp new file mode 100644 index 00000000..674fc8d8 --- /dev/null +++ b/libsecurity_cdsa_client/lib/wrapkey.cpp @@ -0,0 +1,193 @@ +/* + * 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. + */ + + +// +// wrapkey - client interface for wrapping and unwrapping keys +// +#include + +namespace Security { +namespace CssmClient { + + +Key +WrapKey::operator () (Key &keyToBeWrapped, const CssmData *descriptiveData) +{ + Key wrappedKey; + + check(CSSM_WrapKey(handle(), neededCred(), keyToBeWrapped, descriptiveData, + wrappedKey.makeNewKey(attachment()))); + wrappedKey->activate(); + + return wrappedKey; +} + +void +WrapKey::operator () (const CssmKey &keyToBeWrapped, CssmKey &wrappedKey, + const CssmData *descriptiveData) +{ + check(CSSM_WrapKey(handle(), neededCred(), &keyToBeWrapped, + descriptiveData, &wrappedKey)); +} + +void +WrapKey::activate() +{ + if (!mActive) + { + Crypt::activate(); + if (mWrappedKeyFormat != CSSM_KEYBLOB_WRAPPED_FORMAT_NONE); + set(CSSM_ATTRIBUTE_WRAPPED_KEY_FORMAT, mWrappedKeyFormat); + } +} + +Key +UnwrapKey::operator () (const CssmKey &keyToBeUnwrapped, const KeySpec &spec) +{ + CssmData data(reinterpret_cast(1), 0); + Key unwrappedKey; + check(CSSM_UnwrapKey(handle(), NULL, + &keyToBeUnwrapped, spec.usage, spec.attributes, + spec.label, &compositeRcc(), + unwrappedKey.makeNewKey(attachment()), &data)); + unwrappedKey->activate(); + + return unwrappedKey; +} + +void +UnwrapKey::operator () (const CssmKey &keyToBeUnwrapped, const KeySpec &spec, + CssmKey &unwrappedKey) +{ + CssmData data(reinterpret_cast(1), 0); + check(CSSM_UnwrapKey(handle(), NULL, &keyToBeUnwrapped, spec.usage, + spec.attributes, spec.label, &compositeRcc(), + &unwrappedKey, &data)); +} + +Key +UnwrapKey::operator () (const CssmKey &keyToBeUnwrapped, const KeySpec &spec, + Key &optionalPublicKey) +{ + CssmData data(reinterpret_cast(1), 0); + Key unwrappedKey; + check(CSSM_UnwrapKey(handle(), optionalPublicKey, + &keyToBeUnwrapped, spec.usage, spec.attributes, + spec.label, &compositeRcc(), + unwrappedKey.makeNewKey(attachment()), &data)); + + unwrappedKey->activate(); + + return unwrappedKey; +} + +void +UnwrapKey::operator () (const CssmKey &keyToBeUnwrapped, const KeySpec &spec, + CssmKey &unwrappedKey, + const CssmKey *optionalPublicKey) +{ + CssmData data(reinterpret_cast(1), 0); + check(CSSM_UnwrapKey(handle(), optionalPublicKey, &keyToBeUnwrapped, + spec.usage, spec.attributes, spec.label, + &compositeRcc(), &unwrappedKey, &data)); +} + + +Key +UnwrapKey::operator () (const CssmKey &keyToBeUnwrapped, const KeySpec &spec, + CssmData *descriptiveData) +{ + Key unwrappedKey; + check(CSSM_UnwrapKey(handle(), NULL, &keyToBeUnwrapped, spec.usage, + spec.attributes, spec.label, &compositeRcc(), + unwrappedKey.makeNewKey(attachment()), + descriptiveData)); + unwrappedKey->activate(); + + return unwrappedKey; +} + +void +UnwrapKey::operator () (const CssmKey &keyToBeUnwrapped, const KeySpec &spec, + CssmKey &unwrappedKey, CssmData *descriptiveData) +{ + check(CSSM_UnwrapKey(handle(), NULL, &keyToBeUnwrapped, spec.usage, + spec.attributes, spec.label, &compositeRcc(), + &unwrappedKey, descriptiveData)); +} + +Key +UnwrapKey::operator () (const CssmKey &keyToBeUnwrapped, const KeySpec &spec, + const Key &optionalPublicKey, CssmData *descriptiveData) +{ + Key unwrappedKey; + check(CSSM_UnwrapKey(handle(), optionalPublicKey, &keyToBeUnwrapped, + spec.usage, spec.attributes, spec.label, + &compositeRcc(), + unwrappedKey.makeNewKey(attachment()), + descriptiveData)); + unwrappedKey->activate(); + + return unwrappedKey; +} + +void +UnwrapKey::operator () (const CssmKey &keyToBeUnwrapped, const KeySpec &spec, + CssmKey &unwrappedKey, CssmData *descriptiveData, + const CssmKey *optionalPublicKey) +{ + check(CSSM_UnwrapKey(handle(), optionalPublicKey, &keyToBeUnwrapped, + spec.usage, spec.attributes, spec.label, + &compositeRcc(), &unwrappedKey, + descriptiveData)); +} + + +void DeriveKey::activate() +{ + if (!mActive) + { + check(CSSM_CSP_CreateDeriveKeyContext(attachment()->handle(), mAlgorithm, + mTargetType, mKeySize, mCred, mKey, mIterationCount, mSalt, mSeed, &mHandle)); + mActive = true; + } +} + + +Key +DeriveKey::operator () (CssmData *param, const KeySpec &spec) +{ + Key derivedKey; + check(CSSM_DeriveKey(handle(), param, spec.usage, spec.attributes, + spec.label, &compositeRcc(), + derivedKey.makeNewKey(attachment()))); + derivedKey->activate(); + + return derivedKey; +} + +void +DeriveKey::operator () (CssmData *param, const KeySpec &spec, + CssmKey &derivedKey) +{ + check(CSSM_DeriveKey(handle(), param, spec.usage, spec.attributes, + spec.label, &compositeRcc(), &derivedKey)); +} + +} // end namespace CssmClient +} // end namespace Security diff --git a/libsecurity_cdsa_client/lib/wrapkey.h b/libsecurity_cdsa_client/lib/wrapkey.h new file mode 100644 index 00000000..9b75870f --- /dev/null +++ b/libsecurity_cdsa_client/lib/wrapkey.h @@ -0,0 +1,127 @@ +/* + * 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. + */ + + +// +// wrapkey - client interface for wrapping and unwrapping keys +// +#ifndef _H_CDSA_CLIENT_WRAPKEY +#define _H_CDSA_CLIENT_WRAPKEY 1 + +#include +#include +#include + + +namespace Security { +namespace CssmClient { + + +// +// Wrap a key +// +class WrapKey : public Crypt { +public: + WrapKey(const CSP &csp, CSSM_ALGORITHMS alg) : + Crypt(csp, alg), mWrappedKeyFormat(CSSM_KEYBLOB_WRAPPED_FORMAT_NONE) {} + +public: + CSSM_KEYBLOB_FORMAT wrappedKeyFormat() const { return mWrappedKeyFormat; } + void wrappedKeyFormat(CSSM_KEYBLOB_FORMAT wrappedKeyFormat) + { mWrappedKeyFormat = wrappedKeyFormat; set(CSSM_ATTRIBUTE_WRAPPED_KEY_FORMAT, wrappedKeyFormat); } + + // wrap the key + Key operator () (Key &keyToBeWrapped, const CssmData *descriptiveData = NULL); + void operator () (const CssmKey &keyToBeWrapped, CssmKey &wrappedKey, + const CssmData *descriptiveData = NULL); + +protected: + void activate(); + +private: + CSSM_KEYBLOB_FORMAT mWrappedKeyFormat; +}; + + +// +// Unwrap a key. This creates a new key object +// +class UnwrapKey : public Crypt, public RccBearer { +public: + UnwrapKey(const CSP &csp, CSSM_ALGORITHMS alg) : Crypt(csp, alg) {} + +public: + // wrap the key + Key operator () (const CssmKey &keyToBeUnwrapped, const KeySpec &spec); + void operator () (const CssmKey &keyToBeUnwrapped, const KeySpec &spec, + CssmKey &unwrappedKey); + + Key operator () (const CssmKey &keyToBeUnwrapped, const KeySpec &spec, + Key &optionalPublicKey); + void operator () (const CssmKey &keyToBeUnwrapped, const KeySpec &spec, + CssmKey &unwrappedKey, const CssmKey *optionalPublicKey); + + Key operator () (const CssmKey &keyToBeUnwrapped, const KeySpec &spec, + CssmData *descriptiveData); + void operator () (const CssmKey &keyToBeUnwrapped, const KeySpec &spec, + CssmKey &unwrappedKey, CssmData *descriptiveData); + + Key operator () (const CssmKey &keyToBeUnwrapped, const KeySpec &spec, + const Key &optionalPublicKey, CssmData *descriptiveData); + void operator () (const CssmKey &keyToBeUnwrapped, const KeySpec &spec, + CssmKey &unwrappedKey, CssmData *descriptiveData, + const CssmKey *optionalPublicKey); +}; + + +// +// Derive a key in various and wonderous ways. Creates a new key object. +// +class DeriveKey : public Crypt, public RccBearer { +public: + DeriveKey(const CSP &csp, CSSM_ALGORITHMS alg, CSSM_ALGORITHMS target, uint32 size = 0) + : Crypt(csp, alg), mKeySize(size), mTargetType(target), mIterationCount(0), + mSeed(NULL), mSalt(NULL) { } + +public: + CSSM_ALGORITHMS targetType() const { return mTargetType; } + void targetType(CSSM_ALGORITHMS alg) { mTargetType = alg; } + uint32 iterationCount() const { return mIterationCount; } + void iterationCount(uint32 c) { mIterationCount = c; } + const CssmCryptoData seed() const { return *mSeed; } + void seed(const CssmCryptoData &data) { mSeed = &data; } + const CssmData salt() const { return *mSalt; } + void salt(const CssmData &data) { mSalt = &data; } + + Key operator () (CssmData *param, const KeySpec &spec); + void operator () (CssmData *param, const KeySpec &spec, + CssmKey &derivedKey); + + void activate(); + +private: + uint32 mKeySize; + CSSM_ALGORITHMS mTargetType; + uint32 mIterationCount; + const CssmCryptoData *mSeed; + const CssmData *mSalt; +}; + +} // end namespace CssmClient +} // end namespace Security + +#endif // _H_CDSA_CLIENT_WRAPKEY diff --git a/libsecurity_cdsa_client/libsecurity_cdsa_client.xcodeproj/project.pbxproj b/libsecurity_cdsa_client/libsecurity_cdsa_client.xcodeproj/project.pbxproj new file mode 100644 index 00000000..c8ba138e --- /dev/null +++ b/libsecurity_cdsa_client/libsecurity_cdsa_client.xcodeproj/project.pbxproj @@ -0,0 +1,382 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 1865FBDA14723C7600FD79DF /* aclclient.h in Headers */ = {isa = PBXBuildFile; fileRef = C25F9884052C9E3100EDA739 /* aclclient.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1865FBDB14723C7600FD79DF /* clclient.h in Headers */ = {isa = PBXBuildFile; fileRef = C25F9886052C9E3100EDA739 /* clclient.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1865FBDC14723C7600FD79DF /* cryptoclient.h in Headers */ = {isa = PBXBuildFile; fileRef = C25F9888052C9E3100EDA739 /* cryptoclient.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1865FBDD14723C7600FD79DF /* cspclient.h in Headers */ = {isa = PBXBuildFile; fileRef = C25F988A052C9E3100EDA739 /* cspclient.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1865FBDE14723C7600FD79DF /* cssmclient.h in Headers */ = {isa = PBXBuildFile; fileRef = C25F988C052C9E3100EDA739 /* cssmclient.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1865FBDF14723C7600FD79DF /* dlclient.h in Headers */ = {isa = PBXBuildFile; fileRef = C25F988E052C9E3100EDA739 /* dlclient.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1865FBE014723C7600FD79DF /* dliterators.h in Headers */ = {isa = PBXBuildFile; fileRef = C2828D7E0678EF2E00AF941B /* dliterators.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1865FBE114723C7600FD79DF /* dlquery.h in Headers */ = {isa = PBXBuildFile; fileRef = C2EF2AB6066CFFC000F205D4 /* dlquery.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1865FBE214723C7600FD79DF /* dl_standard.h in Headers */ = {isa = PBXBuildFile; fileRef = C2CFE2C106BB009800D98609 /* dl_standard.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1865FBE314723C7600FD79DF /* DLDBList.h in Headers */ = {isa = PBXBuildFile; fileRef = C25F9890052C9E3100EDA739 /* DLDBList.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1865FBE414723C7600FD79DF /* genkey.h in Headers */ = {isa = PBXBuildFile; fileRef = C25F9892052C9E3100EDA739 /* genkey.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1865FBE514723C7600FD79DF /* keychainacl.h in Headers */ = {isa = PBXBuildFile; fileRef = C25F9894052C9E3200EDA739 /* keychainacl.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1865FBE614723C7600FD79DF /* keyclient.h in Headers */ = {isa = PBXBuildFile; fileRef = C25F9896052C9E3200EDA739 /* keyclient.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1865FBE714723C7600FD79DF /* macclient.h in Headers */ = {isa = PBXBuildFile; fileRef = C25F9898052C9E3200EDA739 /* macclient.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1865FBE814723C7600FD79DF /* mdsclient.h in Headers */ = {isa = PBXBuildFile; fileRef = C2B3F4990666992F0010FCA5 /* mdsclient.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1865FBE914723C7600FD79DF /* mds_standard.h in Headers */ = {isa = PBXBuildFile; fileRef = C2B3F6C60667FFFB0010FCA5 /* mds_standard.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1865FBEA14723C7600FD79DF /* multidldb.h in Headers */ = {isa = PBXBuildFile; fileRef = C25F989A052C9E3200EDA739 /* multidldb.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1865FBEB14723C7600FD79DF /* securestorage.h in Headers */ = {isa = PBXBuildFile; fileRef = C25F98A0052C9E3200EDA739 /* securestorage.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1865FBEC14723C7600FD79DF /* signclient.h in Headers */ = {isa = PBXBuildFile; fileRef = C25F98A2052C9E3200EDA739 /* signclient.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1865FBED14723C7600FD79DF /* tpclient.h in Headers */ = {isa = PBXBuildFile; fileRef = C25F98A4052C9E3200EDA739 /* tpclient.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1865FBEE14723C7600FD79DF /* wrapkey.h in Headers */ = {isa = PBXBuildFile; fileRef = C25F98A6052C9E3200EDA739 /* wrapkey.h */; settings = {ATTRIBUTES = (Public, ); }; }; + C25F98A7052C9E3200EDA739 /* aclclient.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C25F9883052C9E3100EDA739 /* aclclient.cpp */; }; + C25F98A9052C9E3200EDA739 /* clclient.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C25F9885052C9E3100EDA739 /* clclient.cpp */; }; + C25F98AB052C9E3200EDA739 /* cryptoclient.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C25F9887052C9E3100EDA739 /* cryptoclient.cpp */; }; + C25F98AD052C9E3200EDA739 /* cspclient.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C25F9889052C9E3100EDA739 /* cspclient.cpp */; }; + C25F98AF052C9E3200EDA739 /* cssmclient.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C25F988B052C9E3100EDA739 /* cssmclient.cpp */; }; + C25F98B1052C9E3200EDA739 /* dlclient.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C25F988D052C9E3100EDA739 /* dlclient.cpp */; }; + C25F98B3052C9E3200EDA739 /* DLDBList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C25F988F052C9E3100EDA739 /* DLDBList.cpp */; }; + C25F98B5052C9E3200EDA739 /* genkey.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C25F9891052C9E3100EDA739 /* genkey.cpp */; }; + C25F98B7052C9E3200EDA739 /* keychainacl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C25F9893052C9E3200EDA739 /* keychainacl.cpp */; }; + C25F98B9052C9E3200EDA739 /* keyclient.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C25F9895052C9E3200EDA739 /* keyclient.cpp */; }; + C25F98BB052C9E3200EDA739 /* macclient.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C25F9897052C9E3200EDA739 /* macclient.cpp */; }; + C25F98BD052C9E3200EDA739 /* multidldb.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C25F9899052C9E3200EDA739 /* multidldb.cpp */; }; + C25F98C3052C9E3200EDA739 /* securestorage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C25F989F052C9E3200EDA739 /* securestorage.cpp */; }; + C25F98C5052C9E3200EDA739 /* signclient.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C25F98A1052C9E3200EDA739 /* signclient.cpp */; }; + C25F98C7052C9E3200EDA739 /* tpclient.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C25F98A3052C9E3200EDA739 /* tpclient.cpp */; }; + C25F98C9052C9E3200EDA739 /* wrapkey.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C25F98A5052C9E3200EDA739 /* wrapkey.cpp */; }; + C261C8BA0675444A0031FA9C /* dlclientpriv.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C261C8B90675444A0031FA9C /* dlclientpriv.cpp */; }; + C2828D7F0678EF2E00AF941B /* dliterators.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2828D7D0678EF2E00AF941B /* dliterators.cpp */; }; + C2B3F49A0666992F0010FCA5 /* mdsclient.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2B3F4980666992F0010FCA5 /* mdsclient.cpp */; }; + C2B3F6C70667FFFB0010FCA5 /* mds_standard.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2B3F6C50667FFFB0010FCA5 /* mds_standard.cpp */; }; + C2CFE2C206BB009800D98609 /* dl_standard.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2CFE2C006BB009800D98609 /* dl_standard.cpp */; }; + C2EF2AB7066CFFC000F205D4 /* dlquery.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2EF2AB5066CFFC000F205D4 /* dlquery.cpp */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 18446163146E94DE00B12992 /* base.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = base.xcconfig; sourceTree = ""; }; + 18446164146E94DE00B12992 /* debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = debug.xcconfig; sourceTree = ""; }; + 18446165146E94DE00B12992 /* lib.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = lib.xcconfig; sourceTree = ""; }; + 18446166146E94DE00B12992 /* release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = release.xcconfig; sourceTree = ""; }; + 4CA1FEBE052A3C8100F22E42 /* libsecurity_cdsa_client.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libsecurity_cdsa_client.a; sourceTree = BUILT_PRODUCTS_DIR; }; + C25F9883052C9E3100EDA739 /* aclclient.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = aclclient.cpp; sourceTree = ""; }; + C25F9884052C9E3100EDA739 /* aclclient.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = aclclient.h; sourceTree = ""; }; + C25F9885052C9E3100EDA739 /* clclient.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = clclient.cpp; sourceTree = ""; }; + C25F9886052C9E3100EDA739 /* clclient.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = clclient.h; sourceTree = ""; }; + C25F9887052C9E3100EDA739 /* cryptoclient.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = cryptoclient.cpp; sourceTree = ""; }; + C25F9888052C9E3100EDA739 /* cryptoclient.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cryptoclient.h; sourceTree = ""; }; + C25F9889052C9E3100EDA739 /* cspclient.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = cspclient.cpp; sourceTree = ""; }; + C25F988A052C9E3100EDA739 /* cspclient.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cspclient.h; sourceTree = ""; }; + C25F988B052C9E3100EDA739 /* cssmclient.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = cssmclient.cpp; sourceTree = ""; }; + C25F988C052C9E3100EDA739 /* cssmclient.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cssmclient.h; sourceTree = ""; }; + C25F988D052C9E3100EDA739 /* dlclient.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = dlclient.cpp; sourceTree = ""; }; + C25F988E052C9E3100EDA739 /* dlclient.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = dlclient.h; sourceTree = ""; }; + C25F988F052C9E3100EDA739 /* DLDBList.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = DLDBList.cpp; sourceTree = ""; }; + C25F9890052C9E3100EDA739 /* DLDBList.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DLDBList.h; sourceTree = ""; }; + C25F9891052C9E3100EDA739 /* genkey.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = genkey.cpp; sourceTree = ""; }; + C25F9892052C9E3100EDA739 /* genkey.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = genkey.h; sourceTree = ""; }; + C25F9893052C9E3200EDA739 /* keychainacl.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = keychainacl.cpp; sourceTree = ""; }; + C25F9894052C9E3200EDA739 /* keychainacl.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = keychainacl.h; sourceTree = ""; }; + C25F9895052C9E3200EDA739 /* keyclient.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = keyclient.cpp; sourceTree = ""; }; + C25F9896052C9E3200EDA739 /* keyclient.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = keyclient.h; sourceTree = ""; }; + C25F9897052C9E3200EDA739 /* macclient.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = macclient.cpp; sourceTree = ""; }; + C25F9898052C9E3200EDA739 /* macclient.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = macclient.h; sourceTree = ""; }; + C25F9899052C9E3200EDA739 /* multidldb.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = multidldb.cpp; sourceTree = ""; }; + C25F989A052C9E3200EDA739 /* multidldb.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = multidldb.h; sourceTree = ""; }; + C25F989F052C9E3200EDA739 /* securestorage.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = securestorage.cpp; sourceTree = ""; }; + C25F98A0052C9E3200EDA739 /* securestorage.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = securestorage.h; sourceTree = ""; }; + C25F98A1052C9E3200EDA739 /* signclient.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = signclient.cpp; sourceTree = ""; }; + C25F98A2052C9E3200EDA739 /* signclient.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = signclient.h; sourceTree = ""; }; + C25F98A3052C9E3200EDA739 /* tpclient.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = tpclient.cpp; sourceTree = ""; }; + C25F98A4052C9E3200EDA739 /* tpclient.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = tpclient.h; sourceTree = ""; }; + C25F98A5052C9E3200EDA739 /* wrapkey.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = wrapkey.cpp; sourceTree = ""; }; + C25F98A6052C9E3200EDA739 /* wrapkey.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = wrapkey.h; sourceTree = ""; }; + C261C8B90675444A0031FA9C /* dlclientpriv.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = dlclientpriv.cpp; sourceTree = ""; }; + C2828D7D0678EF2E00AF941B /* dliterators.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = dliterators.cpp; sourceTree = ""; }; + C2828D7E0678EF2E00AF941B /* dliterators.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = dliterators.h; sourceTree = ""; }; + C2B3F4980666992F0010FCA5 /* mdsclient.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = mdsclient.cpp; sourceTree = ""; }; + C2B3F4990666992F0010FCA5 /* mdsclient.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = mdsclient.h; sourceTree = ""; }; + C2B3F6C50667FFFB0010FCA5 /* mds_standard.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = mds_standard.cpp; sourceTree = ""; }; + C2B3F6C60667FFFB0010FCA5 /* mds_standard.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = mds_standard.h; sourceTree = ""; }; + C2CFE2C006BB009800D98609 /* dl_standard.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = dl_standard.cpp; sourceTree = ""; }; + C2CFE2C106BB009800D98609 /* dl_standard.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = dl_standard.h; sourceTree = ""; }; + C2EF2AB5066CFFC000F205D4 /* dlquery.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = dlquery.cpp; sourceTree = ""; }; + C2EF2AB6066CFFC000F205D4 /* dlquery.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = dlquery.h; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 4CA1FEBB052A3C8100F22E42 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 18446162146E94DE00B12992 /* config */ = { + isa = PBXGroup; + children = ( + 18446163146E94DE00B12992 /* base.xcconfig */, + 18446164146E94DE00B12992 /* debug.xcconfig */, + 18446165146E94DE00B12992 /* lib.xcconfig */, + 18446166146E94DE00B12992 /* release.xcconfig */, + ); + name = config; + path = ../config; + sourceTree = ""; + }; + 4CA1FEA7052A3C3800F22E42 = { + isa = PBXGroup; + children = ( + C25F9882052C9E3100EDA739 /* lib */, + 18446162146E94DE00B12992 /* config */, + 4CA1FEBF052A3C8100F22E42 /* Products */, + ); + sourceTree = ""; + }; + 4CA1FEBF052A3C8100F22E42 /* Products */ = { + isa = PBXGroup; + children = ( + 4CA1FEBE052A3C8100F22E42 /* libsecurity_cdsa_client.a */, + ); + name = Products; + sourceTree = ""; + }; + C25F9882052C9E3100EDA739 /* lib */ = { + isa = PBXGroup; + children = ( + C25F9883052C9E3100EDA739 /* aclclient.cpp */, + C25F9884052C9E3100EDA739 /* aclclient.h */, + C25F9885052C9E3100EDA739 /* clclient.cpp */, + C25F9886052C9E3100EDA739 /* clclient.h */, + C25F9887052C9E3100EDA739 /* cryptoclient.cpp */, + C25F9888052C9E3100EDA739 /* cryptoclient.h */, + C25F9889052C9E3100EDA739 /* cspclient.cpp */, + C25F988A052C9E3100EDA739 /* cspclient.h */, + C25F988B052C9E3100EDA739 /* cssmclient.cpp */, + C25F988C052C9E3100EDA739 /* cssmclient.h */, + C25F988D052C9E3100EDA739 /* dlclient.cpp */, + C261C8B90675444A0031FA9C /* dlclientpriv.cpp */, + C25F988E052C9E3100EDA739 /* dlclient.h */, + C2828D7D0678EF2E00AF941B /* dliterators.cpp */, + C2828D7E0678EF2E00AF941B /* dliterators.h */, + C2EF2AB5066CFFC000F205D4 /* dlquery.cpp */, + C2EF2AB6066CFFC000F205D4 /* dlquery.h */, + C2CFE2C006BB009800D98609 /* dl_standard.cpp */, + C2CFE2C106BB009800D98609 /* dl_standard.h */, + C25F988F052C9E3100EDA739 /* DLDBList.cpp */, + C25F9890052C9E3100EDA739 /* DLDBList.h */, + C25F9891052C9E3100EDA739 /* genkey.cpp */, + C25F9892052C9E3100EDA739 /* genkey.h */, + C25F9893052C9E3200EDA739 /* keychainacl.cpp */, + C25F9894052C9E3200EDA739 /* keychainacl.h */, + C25F9895052C9E3200EDA739 /* keyclient.cpp */, + C25F9896052C9E3200EDA739 /* keyclient.h */, + C25F9897052C9E3200EDA739 /* macclient.cpp */, + C25F9898052C9E3200EDA739 /* macclient.h */, + C2B3F4980666992F0010FCA5 /* mdsclient.cpp */, + C2B3F4990666992F0010FCA5 /* mdsclient.h */, + C2B3F6C50667FFFB0010FCA5 /* mds_standard.cpp */, + C2B3F6C60667FFFB0010FCA5 /* mds_standard.h */, + C25F9899052C9E3200EDA739 /* multidldb.cpp */, + C25F989A052C9E3200EDA739 /* multidldb.h */, + C25F989F052C9E3200EDA739 /* securestorage.cpp */, + C25F98A0052C9E3200EDA739 /* securestorage.h */, + C25F98A1052C9E3200EDA739 /* signclient.cpp */, + C25F98A2052C9E3200EDA739 /* signclient.h */, + C25F98A3052C9E3200EDA739 /* tpclient.cpp */, + C25F98A4052C9E3200EDA739 /* tpclient.h */, + C25F98A5052C9E3200EDA739 /* wrapkey.cpp */, + C25F98A6052C9E3200EDA739 /* wrapkey.h */, + ); + path = lib; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + C2EDE99A0545D8AD00E31CF9 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 1865FBDE14723C7600FD79DF /* cssmclient.h in Headers */, + 1865FBDA14723C7600FD79DF /* aclclient.h in Headers */, + 1865FBDB14723C7600FD79DF /* clclient.h in Headers */, + 1865FBDC14723C7600FD79DF /* cryptoclient.h in Headers */, + 1865FBDD14723C7600FD79DF /* cspclient.h in Headers */, + 1865FBDF14723C7600FD79DF /* dlclient.h in Headers */, + 1865FBE014723C7600FD79DF /* dliterators.h in Headers */, + 1865FBE114723C7600FD79DF /* dlquery.h in Headers */, + 1865FBE214723C7600FD79DF /* dl_standard.h in Headers */, + 1865FBE314723C7600FD79DF /* DLDBList.h in Headers */, + 1865FBE414723C7600FD79DF /* genkey.h in Headers */, + 1865FBE514723C7600FD79DF /* keychainacl.h in Headers */, + 1865FBE614723C7600FD79DF /* keyclient.h in Headers */, + 1865FBE714723C7600FD79DF /* macclient.h in Headers */, + 1865FBE814723C7600FD79DF /* mdsclient.h in Headers */, + 1865FBE914723C7600FD79DF /* mds_standard.h in Headers */, + 1865FBEA14723C7600FD79DF /* multidldb.h in Headers */, + 1865FBEB14723C7600FD79DF /* securestorage.h in Headers */, + 1865FBEC14723C7600FD79DF /* signclient.h in Headers */, + 1865FBED14723C7600FD79DF /* tpclient.h in Headers */, + 1865FBEE14723C7600FD79DF /* wrapkey.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 4CA1FEBD052A3C8100F22E42 /* libsecurity_cdsa_client */ = { + isa = PBXNativeTarget; + buildConfigurationList = C27AD2D20987FCDD001272E0 /* Build configuration list for PBXNativeTarget "libsecurity_cdsa_client" */; + buildPhases = ( + C2EDE99A0545D8AD00E31CF9 /* Headers */, + 4CA1FEBA052A3C8100F22E42 /* Sources */, + 4CA1FEBB052A3C8100F22E42 /* Frameworks */, + 18B96AFA14743E02005A4D2E /* ShellScript */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = libsecurity_cdsa_client; + productInstallPath = /usr/local/lib; + productName = libsecurity_cdsa_client; + productReference = 4CA1FEBE052A3C8100F22E42 /* libsecurity_cdsa_client.a */; + productType = "com.apple.product-type.library.static"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 4CA1FEAB052A3C3800F22E42 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0420; + }; + buildConfigurationList = C27AD2D60987FCDD001272E0 /* Build configuration list for PBXProject "libsecurity_cdsa_client" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 1; + knownRegions = ( + English, + Japanese, + French, + German, + ); + mainGroup = 4CA1FEA7052A3C3800F22E42; + productRefGroup = 4CA1FEBF052A3C8100F22E42 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 4CA1FEBD052A3C8100F22E42 /* libsecurity_cdsa_client */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXShellScriptBuildPhase section */ + 18B96AFA14743E02005A4D2E /* 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 = ( + C25F98A7052C9E3200EDA739 /* aclclient.cpp in Sources */, + C25F98A9052C9E3200EDA739 /* clclient.cpp in Sources */, + C25F98AB052C9E3200EDA739 /* cryptoclient.cpp in Sources */, + C25F98AD052C9E3200EDA739 /* cspclient.cpp in Sources */, + C25F98AF052C9E3200EDA739 /* cssmclient.cpp in Sources */, + C25F98B1052C9E3200EDA739 /* dlclient.cpp in Sources */, + C25F98B3052C9E3200EDA739 /* DLDBList.cpp in Sources */, + C25F98B5052C9E3200EDA739 /* genkey.cpp in Sources */, + C25F98B7052C9E3200EDA739 /* keychainacl.cpp in Sources */, + C25F98B9052C9E3200EDA739 /* keyclient.cpp in Sources */, + C25F98BB052C9E3200EDA739 /* macclient.cpp in Sources */, + C25F98BD052C9E3200EDA739 /* multidldb.cpp in Sources */, + C25F98C3052C9E3200EDA739 /* securestorage.cpp in Sources */, + C25F98C5052C9E3200EDA739 /* signclient.cpp in Sources */, + C25F98C7052C9E3200EDA739 /* tpclient.cpp in Sources */, + C25F98C9052C9E3200EDA739 /* wrapkey.cpp in Sources */, + C2B3F49A0666992F0010FCA5 /* mdsclient.cpp in Sources */, + C2B3F6C70667FFFB0010FCA5 /* mds_standard.cpp in Sources */, + C2EF2AB7066CFFC000F205D4 /* dlquery.cpp in Sources */, + C261C8BA0675444A0031FA9C /* dlclientpriv.cpp in Sources */, + C2828D7F0678EF2E00AF941B /* dliterators.cpp in Sources */, + C2CFE2C206BB009800D98609 /* dl_standard.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + C27AD2D30987FCDD001272E0 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 18446164146E94DE00B12992 /* debug.xcconfig */; + buildSettings = { + PUBLIC_HEADERS_FOLDER_PATH = /usr/local/include/security_cdsa_client; + SKIP_INSTALL = NO; + }; + name = Debug; + }; + C27AD2D50987FCDD001272E0 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 18446166146E94DE00B12992 /* release.xcconfig */; + buildSettings = { + PUBLIC_HEADERS_FOLDER_PATH = /usr/local/include/security_cdsa_client; + SKIP_INSTALL = NO; + }; + name = Release; + }; + C27AD2D70987FCDD001272E0 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 18446165146E94DE00B12992 /* lib.xcconfig */; + buildSettings = { + }; + name = Debug; + }; + C27AD2D90987FCDD001272E0 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 18446165146E94DE00B12992 /* lib.xcconfig */; + buildSettings = { + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + C27AD2D20987FCDD001272E0 /* Build configuration list for PBXNativeTarget "libsecurity_cdsa_client" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C27AD2D30987FCDD001272E0 /* Debug */, + C27AD2D50987FCDD001272E0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C27AD2D60987FCDD001272E0 /* Build configuration list for PBXProject "libsecurity_cdsa_client" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C27AD2D70987FCDD001272E0 /* Debug */, + C27AD2D90987FCDD001272E0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 4CA1FEAB052A3C3800F22E42 /* Project object */; +} diff --git a/libsecurity_cdsa_plugin/Info-security_cdsa_plugin.plist b/libsecurity_cdsa_plugin/Info-security_cdsa_plugin.plist new file mode 100644 index 00000000..0c67376e --- /dev/null +++ b/libsecurity_cdsa_plugin/Info-security_cdsa_plugin.plist @@ -0,0 +1,5 @@ + + + + + diff --git a/libsecurity_cdsa_plugin/lib/ACsession.h b/libsecurity_cdsa_plugin/lib/ACsession.h new file mode 100644 index 00000000..67ad37f6 --- /dev/null +++ b/libsecurity_cdsa_plugin/lib/ACsession.h @@ -0,0 +1,52 @@ +/* + * 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. + */ + + +// +// ACsession.h - Framework for AC plugin modules +// +#ifndef _H_ACSESSION +#define _H_ACSESSION + +#include + +namespace Security +{ + +// +// The abstract ACPluginSession class is the common ancestor of your implementation +// object for an AC type plugin attachment session. Inherit from this and implement +// the abstract methods to define a plugin session. +// +class ACPluginSession : public PluginSession, public ACAbstractPluginSession { +public: + ACPluginSession(CSSM_MODULE_HANDLE theHandle, + CssmPlugin &plug, + const CSSM_VERSION &version, + uint32 subserviceId, + CSSM_SERVICE_TYPE subserviceType, + CSSM_ATTACH_FLAGS attachFlags, + const CSSM_UPCALLS &upcalls) + : PluginSession(theHandle, plug, version, subserviceId, subserviceType, attachFlags, upcalls) { } + +protected: + CSSM_MODULE_FUNCS_PTR construct(); +}; + +} // end namespace Security + +#endif //_H_ACSESSION diff --git a/libsecurity_cdsa_plugin/lib/CLsession.h b/libsecurity_cdsa_plugin/lib/CLsession.h new file mode 100644 index 00000000..8d9ff050 --- /dev/null +++ b/libsecurity_cdsa_plugin/lib/CLsession.h @@ -0,0 +1,51 @@ +/* + * 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. + */ + + +// +// CLsession.h - Framework for CL plugin modules +// +#ifndef _H_CLSESSION +#define _H_CLSESSION + +#include + +namespace Security { + +// +// The abstract CLPluginSession class is the common ancestor of your implementation +// object for an CL type plugin attachment session. Inherit from this and implement +// the abstract methods to define a plugin session. +// +class CLPluginSession : public PluginSession, public CLAbstractPluginSession { +public: + CLPluginSession(CSSM_MODULE_HANDLE theHandle, + CssmPlugin &plug, + const CSSM_VERSION &version, + uint32 subserviceId, + CSSM_SERVICE_TYPE subserviceType, + CSSM_ATTACH_FLAGS attachFlags, + const CSSM_UPCALLS &upcalls) + : PluginSession(theHandle, plug, version, subserviceId, subserviceType, attachFlags, upcalls) { } + +protected: + CSSM_MODULE_FUNCS_PTR construct(); +}; + +} // end namespace Security + +#endif //_H_CLSESSION diff --git a/libsecurity_cdsa_plugin/lib/CSPsession.cpp b/libsecurity_cdsa_plugin/lib/CSPsession.cpp new file mode 100644 index 00000000..862df167 --- /dev/null +++ b/libsecurity_cdsa_plugin/lib/CSPsession.cpp @@ -0,0 +1,1156 @@ +/* + * 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. + */ + + +// +// CSPsession - Plugin framework for CSP plugin modules +// +#include +#include +#include + + +typedef CSPFullPluginSession::CSPContext CSPContext; + + +// +// PluginContext construction +// +CSPPluginSession::PluginContext::~PluginContext() +{ /* virtual */ } + +CSPFullPluginSession::AlgorithmFactory::~AlgorithmFactory() +{ /* virtual */ } + + +// +// Internal utilities +// +CssmData CSPFullPluginSession::makeBuffer(size_t size, Allocator &alloc) +{ + return CssmData(alloc.malloc(size), size); +} + +inline size_t CSPFullPluginSession::totalBufferSize(const CssmData *data, uint32 count) +{ + size_t size = 0; + for (uint32 n = 0; n < count; n++) + size += data[n].length(); + return size; +} + + +// +// Notify a context that its underlying CSSM context has (well, may have) changed. +// The default reaction is to ask the frame to delete the context and start over. +// +bool CSPPluginSession::PluginContext::changed(const Context &context) +{ + return false; // delete me, please +} + + +// +// The Session's init() function calls your setupContext() method to prepare +// it for action, then calls the context's init() method. +// +CSPContext *CSPFullPluginSession::init(CSSM_CC_HANDLE ccHandle, + CSSM_CONTEXT_TYPE type, + const Context &context, bool encoding) +{ + CSPContext *ctx = getContext(ccHandle); + checkOperation(context.type(), type); + + // ask the implementation to set up an internal context + setupContext(ctx, context, encoding); + assert(ctx != NULL); // must have context now (@@@ throw INTERNAL_ERROR instead?) + ctx->mType = context.type(); + ctx->mDirection = encoding; + setContext(ccHandle, ctx); + + // initialize the context and return it + ctx->init(context, encoding); + return ctx; +} + + +// +// Retrieve a context for a staged operation in progress. +// +CSPContext *CSPFullPluginSession::getStagedContext(CSSM_CC_HANDLE ccHandle, + CSSM_CONTEXT_TYPE type, bool encoding) +{ + CSPContext *ctx = getContext(ccHandle); + if (ctx == NULL) + CssmError::throwMe(CSSMERR_CSP_INVALID_CONTEXT); //@@@ better diagnostic? + checkOperation(ctx->type(), type); + if (ctx->encoding() != encoding) + CssmError::throwMe(CSSMERR_CSP_INVALID_CONTEXT); + return ctx; +} + + +// +// The Session's checkState() function is called for subsequent staged operations +// (update/final) to verify that the user didn't screw up the sequencing. +// +void CSPFullPluginSession::checkOperation(CSSM_CONTEXT_TYPE ctxType, CSSM_CONTEXT_TYPE opType) +{ + switch (opType) { + case CSSM_ALGCLASS_NONE: // no check + return; + case CSSM_ALGCLASS_CRYPT: // symmetric or asymmetric encryption + if (ctxType == CSSM_ALGCLASS_SYMMETRIC || + ctxType == CSSM_ALGCLASS_ASYMMETRIC) + return; + default: // plain match + if (ctxType == opType) + return; + } + CssmError::throwMe(CSSMERR_CSP_INVALID_CONTEXT); +} + + +// +// The default implementations of the primary context operations throw internal +// errors. You must implement any of these that are actually called by the +// operations involved. The others, of course, can be left alone. +// +void CSPContext::init(const Context &context, bool encoding) +{ CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR); } + +void CSPContext::update(const CssmData &data) +{ CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR); } + +void CSPContext::update(void *inp, size_t &inSize, void *outp, size_t &outSize) +{ CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR); } + +void CSPContext::final(CssmData &out) +{ CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR); } + +void CSPContext::final(const CssmData &in) +{ CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR); } + +void CSPContext::generate(const Context &, CssmKey &pubKey, CssmKey &privKey) +{ CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR); } + +void CSPContext::generate(const Context &, uint32, CssmData ¶ms, + uint32 &attrCount, Context::Attr * &attrs) +{ CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR); } + +size_t CSPContext::inputSize(size_t outSize) +{ CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR); } + +size_t CSPContext::outputSize(bool final, size_t inSize) +{ CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR); } + +void CSPContext::minimumProgress(size_t &in, size_t &out) +{ CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR); } + +CSPFullPluginSession::CSPContext *CSPContext::clone(Allocator &) +{ CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); } + +void CSPContext::setDigestAlgorithm(CSSM_ALGORITHMS digestAlg) +{ CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM); } + +void CSPContext::update(const CssmData *in, + uint32 inCount, Writer &writer) +{ + const CssmData *lastIn = in + inCount; + CssmData current; + for (;;) { + if (current.length() == 0) { + if (in == lastIn) + return; // all done + current = *in++; + continue; // Just in case next block is zero length too. + } + // match up current input and output buffers + void *outP; size_t outSize; + writer.nextBlock(outP, outSize); + size_t inSize = inputSize(outSize); + if (inSize > current.length()) + inSize = current.length(); // cap to remaining input buffer + if (inSize > 0) { + // we can stuff into the current output buffer - do it + update(current.data(), inSize, outP, outSize); + current.use(inSize); + writer.use(outSize); + } else { + // We have remaining output buffer space, but not enough + // for the algorithm to make progress with it. We must proceed with + // a bounce buffer and split it manually into this and the next buffer(s). + size_t minOutput; + minimumProgress(inSize, minOutput); + assert(minOutput > outSize); // PluginContext consistency (not fatal) + char splitBuffer[128]; + assert(minOutput <= sizeof(splitBuffer)); // @@@ static buffer for now + outSize = sizeof(splitBuffer); + if (current.length() < inSize) + inSize = current.length(); // cap to data remaining in input buffer + update(current.data(), inSize, splitBuffer, outSize); + assert(inSize > 0); // progress made + writer.put(splitBuffer, outSize); // stuff into buffer, the hard way + current.use(inSize); + } + } +} + +void CSPContext::final(CssmData &out, Allocator &alloc) +{ + size_t needed = outputSize(true, 0); + if (out) { + if (out.length() < needed) + CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR); + } else { + out = makeBuffer(needed, alloc); + } + final(out); +} + +void CSPContext::final(Writer &writer, Allocator &alloc) +{ + if (size_t needed = outputSize(true, 0)) { + // need to generate additional output + writer.allocate(needed, alloc); // belt + suspender + + void *addr; size_t size; + writer.nextBlock(addr, size); // next single block available + if (needed <= size) { // rest fits into one block + CssmData chunk(addr, size); + final(chunk); + writer.use(chunk.length()); + } else { // need to split it up + char splitBuffer[128]; + assert(needed <= sizeof(splitBuffer)); + CssmData chunk(splitBuffer, sizeof(splitBuffer)); + final(chunk); + writer.put(chunk.data(), chunk.length()); + } + } +} + + +// +// Default context response functions +// +CSPPluginSession::PluginContext * +CSPPluginSession::contextCreate(CSSM_CC_HANDLE, const Context &) +{ + return NULL; // request no local context +} + +void CSPPluginSession::contextUpdate(CSSM_CC_HANDLE ccHandle, + const Context &context, PluginContext * &ctx) +{ + // call update notifier in context object + if (ctx && !ctx->changed(context)) { + // context requested that it be removed + delete ctx; + ctx = NULL; + } +} + +void CSPPluginSession::contextDelete(CSSM_CC_HANDLE, const Context &, PluginContext *) +{ + // do nothing (you can't prohibit deletion here) +} + + +// +// Default event notification handler. +// This default handler calls the virtual context* methods to dispose of context actions. +// +void CSPPluginSession::EventNotify(CSSM_CONTEXT_EVENT event, + CSSM_CC_HANDLE ccHandle, const Context &context) +{ + switch (event) { + case CSSM_CONTEXT_EVENT_CREATE: + if (PluginContext *ctx = contextCreate(ccHandle, context)) { + StLock _(contextMapLock); + assert(contextMap[ccHandle] == NULL); // check context re-creation + contextMap[ccHandle] = ctx; + } + break; + case CSSM_CONTEXT_EVENT_UPDATE: + // note that the handler can change the map entry (even to NULL, if desired) + { + StLock _(contextMapLock); + contextUpdate(ccHandle, context, contextMap[ccHandle]); + } + break; + case CSSM_CONTEXT_EVENT_DELETE: + { + StLock _(contextMapLock); + if (PluginContext *ctx = contextMap[ccHandle]) { + contextDelete(ccHandle, context, ctx); + delete ctx; + } + contextMap.erase(ccHandle); + } + break; + default: + CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR); // unexpected event code + } +} + + +// +// Defaults for methods you *should* implement. +// If you don't, they'll throw UNIMPLEMENTED. +// +void CSPFullPluginSession::getKeySize(const CssmKey &key, CSSM_KEY_SIZE &size) +{ unimplemented(); } + + +// +// Encryption and decryption +// +void CSPFullPluginSession::EncryptData(CSSM_CC_HANDLE ccHandle, + const Context &context, + const CssmData clearBufs[], + uint32 clearBufCount, + CssmData cipherBufs[], + uint32 cipherBufCount, + CSSM_SIZE &bytesEncrypted, + CssmData &remData, + CSSM_PRIVILEGE privilege) +{ + Writer writer(cipherBufs, cipherBufCount, &remData); + CSPContext *ctx = init(ccHandle, CSSM_ALGCLASS_CRYPT, context, true); + size_t outNeeded = ctx->outputSize(true, totalBufferSize(clearBufs, clearBufCount)); + writer.allocate(outNeeded, *this); + ctx->update(clearBufs, clearBufCount, writer); + ctx->final(writer, *this); + bytesEncrypted = writer.close(); +} + +void CSPFullPluginSession::EncryptDataInit(CSSM_CC_HANDLE ccHandle, + const Context &context, + CSSM_PRIVILEGE Privilege) +{ + init(ccHandle, CSSM_ALGCLASS_CRYPT, context, true); +} + +void CSPFullPluginSession::EncryptDataUpdate(CSSM_CC_HANDLE ccHandle, + const CssmData clearBufs[], + uint32 clearBufCount, + CssmData cipherBufs[], + uint32 cipherBufCount, + CSSM_SIZE &bytesEncrypted) +{ + CSPContext *alg = getStagedContext(ccHandle, CSSM_ALGCLASS_CRYPT, true); + Writer writer(cipherBufs, cipherBufCount); + size_t outNeeded = alg->outputSize(false, totalBufferSize(clearBufs, clearBufCount)); + writer.allocate(outNeeded, *this); + alg->update(clearBufs, clearBufCount, writer); + bytesEncrypted = writer.close(); +} + +void CSPFullPluginSession::EncryptDataFinal(CSSM_CC_HANDLE ccHandle, + CssmData &remData) +{ + getStagedContext(ccHandle, CSSM_ALGCLASS_CRYPT, true)->final(remData, *this); +} + + +void CSPFullPluginSession::DecryptData(CSSM_CC_HANDLE ccHandle, + const Context &context, + const CssmData cipherBufs[], + uint32 cipherBufCount, + CssmData clearBufs[], + uint32 clearBufCount, + CSSM_SIZE &bytesDecrypted, + CssmData &remData, + CSSM_PRIVILEGE privilege) +{ + Writer writer(clearBufs, clearBufCount, &remData); + CSPContext *ctx = init(ccHandle, CSSM_ALGCLASS_CRYPT, context, false); + size_t outNeeded = ctx->outputSize(true, totalBufferSize(cipherBufs, cipherBufCount)); + writer.allocate(outNeeded, *this); + ctx->update(cipherBufs, cipherBufCount, writer); + ctx->final(writer, *this); + bytesDecrypted = writer.close(); +} + +void CSPFullPluginSession::DecryptDataInit(CSSM_CC_HANDLE ccHandle, + const Context &context, + CSSM_PRIVILEGE Privilege) +{ + init(ccHandle, CSSM_ALGCLASS_CRYPT, context, false); +} + +void CSPFullPluginSession::DecryptDataUpdate(CSSM_CC_HANDLE ccHandle, + const CssmData cipherBufs[], + uint32 cipherBufCount, + CssmData clearBufs[], + uint32 clearBufCount, + CSSM_SIZE &bytesDecrypted) +{ + CSPContext *ctx = getStagedContext(ccHandle, CSSM_ALGCLASS_CRYPT, false); + Writer writer(clearBufs, clearBufCount); + size_t outNeeded = ctx->outputSize(false, totalBufferSize(cipherBufs, cipherBufCount)); + writer.allocate(outNeeded, *this); + ctx->update(cipherBufs, cipherBufCount, writer); + bytesDecrypted = writer.close(); +} + +void CSPFullPluginSession::DecryptDataFinal(CSSM_CC_HANDLE ccHandle, + CssmData &remData) +{ + getStagedContext(ccHandle, CSSM_ALGCLASS_CRYPT, false)->final(remData, *this); +} + +void CSPFullPluginSession::QuerySize(CSSM_CC_HANDLE ccHandle, + const Context &context, + CSSM_BOOL encrypt, + uint32 querySizeCount, + QuerySizeData *dataBlock) +{ + if (querySizeCount == 0) + return; // nothing ventured, nothing gained + CSPContext *ctx = getContext(ccHandle); // existing context? + if (ctx == NULL) // force internal context creation (as best we can) + ctx = init(ccHandle, context.type(), context, encrypt); + // If QuerySizeCount > 1, we assume this inquires about a staged + // operation, and the LAST item gets the 'final' treatment. + //@@@ Intel revised algspec says "use the staged flag" -- TBD + for (uint32 n = 0; n < querySizeCount; n++) { + // the outputSize() call might throw CSSMERR_CSP_QUERY_SIZE_UNKNOWN + dataBlock[n].SizeOutputBlock = + ctx->outputSize(n == querySizeCount-1, dataBlock[n].inputSize()); + } + //@@@ if we forced a context creation, should we discard it now? +} + + +// +// Key wrapping and unwrapping. +// +void CSPFullPluginSession::WrapKey(CSSM_CC_HANDLE CCHandle, + const Context &Context, + const AccessCredentials &AccessCred, + const CssmKey &Key, + const CssmData *DescriptiveData, + CssmKey &WrappedKey, + CSSM_PRIVILEGE Privilege) +{ + unimplemented(); +} + +void CSPFullPluginSession::UnwrapKey(CSSM_CC_HANDLE CCHandle, + const Context &Context, + const CssmKey *PublicKey, + const CssmKey &WrappedKey, + uint32 KeyUsage, + uint32 KeyAttr, + const CssmData *KeyLabel, + const CSSM_RESOURCE_CONTROL_CONTEXT *CredAndAclEntry, + CssmKey &UnwrappedKey, + CssmData &DescriptiveData, + CSSM_PRIVILEGE Privilege) +{ + unimplemented(); +} + +void CSPFullPluginSession::DeriveKey(CSSM_CC_HANDLE CCHandle, + const Context &Context, + CssmData &Param, + uint32 KeyUsage, + uint32 KeyAttr, + const CssmData *KeyLabel, + const CSSM_RESOURCE_CONTROL_CONTEXT *CredAndAclEntry, + CssmKey &DerivedKey) +{ + unimplemented(); +} + + +// +// Message Authentication Codes. +// Almost like signatures (signatures with symmetric keys), though the +// underlying implementation may be somewhat different. +// +void CSPFullPluginSession::GenerateMac(CSSM_CC_HANDLE ccHandle, + const Context &context, + const CssmData dataBufs[], + uint32 dataBufCount, + CssmData &mac) +{ + GenerateMacInit(ccHandle, context); + GenerateMacUpdate(ccHandle, dataBufs, dataBufCount); + GenerateMacFinal(ccHandle, mac); +} + +void CSPFullPluginSession::GenerateMacInit(CSSM_CC_HANDLE ccHandle, + const Context &context) +{ + init(ccHandle, CSSM_ALGCLASS_MAC, context, true); +} + +void CSPFullPluginSession::GenerateMacUpdate(CSSM_CC_HANDLE ccHandle, + const CssmData dataBufs[], + uint32 dataBufCount) +{ + getStagedContext(ccHandle, CSSM_ALGCLASS_MAC, true)->update(dataBufs, dataBufCount); +} + +void CSPFullPluginSession::GenerateMacFinal(CSSM_CC_HANDLE ccHandle, + CssmData &mac) +{ + getStagedContext(ccHandle, CSSM_ALGCLASS_MAC, true)->final(mac, *this); +} + +void CSPFullPluginSession::VerifyMac(CSSM_CC_HANDLE ccHandle, + const Context &context, + const CssmData dataBufs[], + uint32 dataBufCount, + const CssmData &mac) +{ + VerifyMacInit(ccHandle, context); + VerifyMacUpdate(ccHandle, dataBufs, dataBufCount); + VerifyMacFinal(ccHandle, mac); +} + +void CSPFullPluginSession::VerifyMacInit(CSSM_CC_HANDLE ccHandle, + const Context &context) +{ + init(ccHandle, CSSM_ALGCLASS_MAC, context, false); +} + +void CSPFullPluginSession::VerifyMacUpdate(CSSM_CC_HANDLE ccHandle, + const CssmData dataBufs[], + uint32 dataBufCount) +{ + getStagedContext(ccHandle, CSSM_ALGCLASS_MAC, false)->update(dataBufs, dataBufCount); +} + +void CSPFullPluginSession::VerifyMacFinal(CSSM_CC_HANDLE ccHandle, + const CssmData &mac) +{ + getStagedContext(ccHandle, CSSM_ALGCLASS_MAC, false)->final(mac); +} + + +// +// Signatures +// +void CSPFullPluginSession::SignData(CSSM_CC_HANDLE ccHandle, + const Context &context, + const CssmData dataBufs[], + uint32 dataBufCount, + CSSM_ALGORITHMS digestAlgorithm, + CssmData &Signature) +{ + SignDataInit(ccHandle, context); + if(digestAlgorithm != CSSM_ALGID_NONE) { + getStagedContext(ccHandle, CSSM_ALGCLASS_SIGNATURE, + true)->setDigestAlgorithm(digestAlgorithm); + } + SignDataUpdate(ccHandle, dataBufs, dataBufCount); + SignDataFinal(ccHandle, Signature); +} + +void CSPFullPluginSession::SignDataInit(CSSM_CC_HANDLE ccHandle, + const Context &context) +{ + init(ccHandle, CSSM_ALGCLASS_SIGNATURE, context, true); +} + +void CSPFullPluginSession::SignDataUpdate(CSSM_CC_HANDLE ccHandle, + const CssmData dataBufs[], + uint32 dataBufCount) +{ + getStagedContext(ccHandle, CSSM_ALGCLASS_SIGNATURE, true)->update(dataBufs, dataBufCount); +} + +void CSPFullPluginSession::SignDataFinal(CSSM_CC_HANDLE ccHandle, + CssmData &signature) +{ + getStagedContext(ccHandle, CSSM_ALGCLASS_SIGNATURE, true)->final(signature, *this); +} + + +void CSPFullPluginSession::VerifyData(CSSM_CC_HANDLE ccHandle, + const Context &context, + const CssmData dataBufs[], + uint32 dataBufCount, + CSSM_ALGORITHMS digestAlgorithm, + const CssmData &Signature) +{ + VerifyDataInit(ccHandle, context); + if(digestAlgorithm != CSSM_ALGID_NONE) { + getStagedContext(ccHandle, CSSM_ALGCLASS_SIGNATURE, + false)->setDigestAlgorithm(digestAlgorithm); + } + VerifyDataUpdate(ccHandle, dataBufs, dataBufCount); + VerifyDataFinal(ccHandle, Signature); +} + +void CSPFullPluginSession::VerifyDataInit(CSSM_CC_HANDLE ccHandle, const Context &context) +{ + init(ccHandle, CSSM_ALGCLASS_SIGNATURE, context, false); +} + +void CSPFullPluginSession::VerifyDataUpdate(CSSM_CC_HANDLE ccHandle, + const CssmData dataBufs[], + uint32 dataBufCount) +{ + getStagedContext(ccHandle, CSSM_ALGCLASS_SIGNATURE, false)->update(dataBufs, dataBufCount); +} + +void CSPFullPluginSession::VerifyDataFinal(CSSM_CC_HANDLE ccHandle, + const CssmData &signature) +{ + getStagedContext(ccHandle, CSSM_ALGCLASS_SIGNATURE, false)->final(signature); +} + + +// +// Digesting +// +void CSPFullPluginSession::DigestData(CSSM_CC_HANDLE ccHandle, + const Context &context, + const CssmData dataBufs[], + uint32 DataBufCount, + CssmData &Digest) +{ + DigestDataInit(ccHandle, context); + DigestDataUpdate(ccHandle, dataBufs, DataBufCount); + DigestDataFinal(ccHandle, Digest); +} + +void CSPFullPluginSession::DigestDataInit(CSSM_CC_HANDLE ccHandle, const Context &context) +{ + init(ccHandle, CSSM_ALGCLASS_DIGEST, context); +} + +void CSPFullPluginSession::DigestDataUpdate(CSSM_CC_HANDLE ccHandle, + const CssmData dataBufs[], + uint32 dataBufCount) +{ + getStagedContext(ccHandle, CSSM_ALGCLASS_DIGEST)->update(dataBufs, dataBufCount); +} + +void CSPFullPluginSession::DigestDataFinal(CSSM_CC_HANDLE ccHandle, + CssmData &digest) +{ + getStagedContext(ccHandle, CSSM_ALGCLASS_DIGEST)->final(digest, *this); +} + +void CSPFullPluginSession::DigestDataClone(CSSM_CC_HANDLE ccHandle, + CSSM_CC_HANDLE clonedCCHandle) +{ + CSPContext *cloned = getStagedContext(ccHandle, CSSM_ALGCLASS_DIGEST)->clone(*this); + cloned->mDirection = true; + cloned->mType = CSSM_ALGCLASS_DIGEST; + setContext(clonedCCHandle, cloned); +} + + +// +// Key generation, Derivation, and inquiry +// +void CSPFullPluginSession::GenerateKey(CSSM_CC_HANDLE ccHandle, + const Context &context, + uint32 keyUsage, + uint32 keyAttr, + const CssmData *keyLabel, + const CSSM_RESOURCE_CONTROL_CONTEXT *credAndAclEntry, + CssmKey &key, + CSSM_PRIVILEGE privilege) +{ + CSPContext *alg = init(ccHandle, CSSM_ALGCLASS_KEYGEN, context); + setKey(key, context, CSSM_KEYCLASS_SESSION_KEY, keyAttr, keyUsage); + CssmKey blank; // dummy 2nd key (not used) + alg->generate(context, key, blank); +} + +class ContextMinder +{ +private: + CSSM_CC_HANDLE mHandle; + +public: + ContextMinder(CSSM_CC_HANDLE ccHandle) : mHandle(ccHandle) {} + ~ContextMinder() {CSSM_DeleteContext(mHandle);} +}; + + + +void CSPFullPluginSession::GenerateKeyPair(CSSM_CC_HANDLE ccHandle, + const Context &context, + uint32 publicKeyUsage, + uint32 publicKeyAttr, + const CssmData *publicKeyLabel, + CssmKey &publicKey, + uint32 privateKeyUsage, + uint32 privateKeyAttr, + const CssmData *privateKeyLabel, + const CSSM_RESOURCE_CONTROL_CONTEXT *credAndAclEntry, + CssmKey &privateKey, + CSSM_PRIVILEGE privilege) +{ + CSPContext *alg = init(ccHandle, CSSM_ALGCLASS_KEYGEN, context); + + setKey(publicKey, context, CSSM_KEYCLASS_PUBLIC_KEY, publicKeyAttr, publicKeyUsage); + setKey(privateKey, context, CSSM_KEYCLASS_PRIVATE_KEY, privateKeyAttr, privateKeyUsage); + alg->generate(context, publicKey, privateKey); + + //@@@ handle labels + //@@@ handle reference keys + + bool encryptPublic = publicKeyUsage & CSSM_KEYUSE_ENCRYPT; + bool encryptPrivate = privateKeyUsage & CSSM_KEYUSE_ENCRYPT; + + if (!(encryptPublic || encryptPrivate)) + { + return ; + } + + // time to do the FIPS required test! + CSSM_CSP_HANDLE moduleHandle = handle(); + CSSM_CC_HANDLE encryptHandle; + CSSM_ACCESS_CREDENTIALS nullCreds; + memset(&nullCreds, 0, sizeof(nullCreds)); + + CSSM_KEY_PTR encryptingKey, decryptingKey; + if (encryptPublic) + { + encryptingKey = &publicKey; + decryptingKey = &privateKey; + } + else + { + encryptingKey = &privateKey; + decryptingKey = &publicKey; + } + + // make data to be encrypted + unsigned bytesInKey = encryptingKey->KeyHeader.LogicalKeySizeInBits / 8; + u_int8_t buffer[bytesInKey]; + unsigned i; + + for (i = 0; i < bytesInKey; ++i) + { + buffer[i] = i; + } + + CSSM_DATA clearBuf = {bytesInKey, buffer}; + CSSM_DATA cipherBuf; // have the CSP allocate the resulting memory + CSSM_SIZE bytesEncrypted; + CSSM_DATA remData = {0, NULL}; + CSSM_DATA decryptedBuf = {bytesInKey, buffer}; + + CSSM_RETURN result = CSSM_CSP_CreateAsymmetricContext(moduleHandle, encryptingKey->KeyHeader.AlgorithmId, &nullCreds, encryptingKey, CSSM_PADDING_NONE, &encryptHandle); + if (result != CSSM_OK) + { + CssmError::throwMe(result); + } + + ContextMinder encryptMinder(encryptHandle); // auto throw away if we error out + + CSSM_QUERY_SIZE_DATA qsData; + qsData.SizeInputBlock = bytesInKey; + result = CSSM_QuerySize(encryptHandle, CSSM_TRUE, 1, &qsData); + if (result == CSSMERR_CSP_INVALID_ALGORITHM) + { + return; + } + + uint8 cipherBuffer[qsData.SizeOutputBlock]; + cipherBuf.Length = qsData.SizeOutputBlock; + cipherBuf.Data = cipherBuffer; + + // do the encryption + result = CSSM_EncryptData(encryptHandle, &clearBuf, 1, &cipherBuf, 1, &bytesEncrypted, &remData); + if (result != CSSM_OK) + { + CssmError::throwMe(result); + } + + // check the result + if (memcmp(cipherBuf.Data, clearBuf.Data, clearBuf.Length) == 0) + { + // we have a match, that's not good news... + abort(); + } + + // clean up + if (remData.Data != NULL) + { + free(remData.Data); + } + + // make a context to perform the decryption + CSSM_CC_HANDLE decryptHandle; + result = CSSM_CSP_CreateAsymmetricContext(moduleHandle, encryptingKey->KeyHeader.AlgorithmId, &nullCreds, decryptingKey, CSSM_PADDING_NONE, &decryptHandle); + ContextMinder decryptMinder(decryptHandle); + + if (result != CSSM_OK) + { + CssmError::throwMe(result); + } + + result = CSSM_DecryptData(decryptHandle, &cipherBuf, 1, &decryptedBuf, 1, &bytesEncrypted, &remData); + if (result != CSSM_OK) + { + CssmError::throwMe(result); + } + + // check the results + for (i = 0; i < bytesInKey; ++i) + { + if (decryptedBuf.Data[i] != (i & 0xFF)) + { + // bad news + abort(); + } + } + + if (remData.Data != NULL) + { + free(remData.Data); + } +} + +void CSPFullPluginSession::ObtainPrivateKeyFromPublicKey(const CssmKey &PublicKey, + CssmKey &PrivateKey) +{ + unimplemented(); +} + +void CSPFullPluginSession::QueryKeySizeInBits(CSSM_CC_HANDLE ccHandle, + const Context *context, + const CssmKey *key, + CSSM_KEY_SIZE &keySize) +{ + if (context) { + getKeySize(context->get(CSSM_ATTRIBUTE_KEY, CSSMERR_CSP_MISSING_ATTR_KEY), + keySize); + } else { + getKeySize(CssmKey::required(key), keySize); + } +} + + +// +// Free a key object. +// +void CSPFullPluginSession::FreeKey(const AccessCredentials *AccessCred, + CssmKey &key, + CSSM_BOOL Delete) +{ + free(key.data()); +} + + +// +// Random number and parameter generation +// +void CSPFullPluginSession::GenerateRandom(CSSM_CC_HANDLE ccHandle, + const Context &context, + CssmData &randomNumber) +{ + init(ccHandle, CSSM_ALGCLASS_RANDOMGEN, context)->final(randomNumber, *this); +} + +void CSPFullPluginSession::GenerateAlgorithmParams(CSSM_CC_HANDLE ccHandle, + const Context &context, + uint32 paramBits, + CssmData ¶m, + uint32 &attrCount, + CSSM_CONTEXT_ATTRIBUTE_PTR &attrs) +{ + Context::Attr *attrList; + init(ccHandle, CSSM_ALGCLASS_NONE, context)->generate(context, paramBits, + param, attrCount, attrList); + attrs = attrList; +} + + +// +// Login/Logout and token operational maintainance. +// These mean little without support by the actual implementation, but we can help... +// @@@ Should this be in CSP[non-Full]PluginSession? +// +void CSPFullPluginSession::Login(const AccessCredentials &AccessCred, + const CssmData *LoginName, + const void *Reserved) +{ + if (Reserved != NULL) + CssmError::throwMe(CSSM_ERRCODE_INVALID_POINTER); + + // default implementation refuses to log in + //@@@ should hand it to implementation virtual defaulting to this + CssmError::throwMe(CSSMERR_CSP_INVALID_LOGIN_NAME); +} + +void CSPFullPluginSession::Logout() +{ + if (!loggedIn(false)) + CssmError::throwMe(CSSMERR_CSP_NOT_LOGGED_IN); +} + +void CSPFullPluginSession::VerifyDevice(const CssmData &DeviceCert) +{ + CssmError::throwMe(CSSMERR_CSP_DEVICE_VERIFY_FAILED); +} + +void CSPFullPluginSession::GetOperationalStatistics(CSPOperationalStatistics &statistics) +{ + memset(&statistics, 0, sizeof(statistics)); + statistics.UserAuthenticated = loggedIn(); + //@@@ collect device flags - capability matrix setup? + //@@@ collect token limitation parameters (static) - capability matrix setup? + //@@@ collect token statistics (dynamic) - dynamic accounting call-downs? +} + + +// +// Utterly miscellaneous, rarely used, strange functions +// +void CSPFullPluginSession::RetrieveCounter(CssmData &Counter) +{ + unimplemented(); +} + +void CSPFullPluginSession::RetrieveUniqueId(CssmData &UniqueID) +{ + unimplemented(); +} + +void CSPFullPluginSession::GetTimeValue(CSSM_ALGORITHMS TimeAlgorithm, CssmData &TimeData) +{ + unimplemented(); +} + + +// +// ACL retrieval and change operations +// +void CSPFullPluginSession::GetKeyOwner(const CssmKey &Key, + CSSM_ACL_OWNER_PROTOTYPE &Owner) +{ + unimplemented(); +} + +void CSPFullPluginSession::ChangeKeyOwner(const AccessCredentials &AccessCred, + const CssmKey &Key, + const CSSM_ACL_OWNER_PROTOTYPE &NewOwner) +{ + unimplemented(); +} + +void CSPFullPluginSession::GetKeyAcl(const CssmKey &Key, + const CSSM_STRING *SelectionTag, + uint32 &NumberOfAclInfos, + CSSM_ACL_ENTRY_INFO_PTR &AclInfos) +{ + unimplemented(); +} + +void CSPFullPluginSession::ChangeKeyAcl(const AccessCredentials &AccessCred, + const CSSM_ACL_EDIT &AclEdit, + const CssmKey &Key) +{ + unimplemented(); +} + +void CSPFullPluginSession::GetLoginOwner(CSSM_ACL_OWNER_PROTOTYPE &Owner) +{ + unimplemented(); +} + +void CSPFullPluginSession::ChangeLoginOwner(const AccessCredentials &AccessCred, + const CSSM_ACL_OWNER_PROTOTYPE &NewOwner) +{ + unimplemented(); +} + +void CSPFullPluginSession::GetLoginAcl(const CSSM_STRING *SelectionTag, + uint32 &NumberOfAclInfos, + CSSM_ACL_ENTRY_INFO_PTR &AclInfos) +{ + unimplemented(); +} + +void CSPFullPluginSession::ChangeLoginAcl(const AccessCredentials &AccessCred, + const CSSM_ACL_EDIT &AclEdit) +{ + unimplemented(); +} + + + +// +// Passthroughs (by default, unimplemented) +// +void CSPFullPluginSession::PassThrough(CSSM_CC_HANDLE CCHandle, + const Context &Context, + uint32 PassThroughId, + const void *InData, + void **OutData) +{ + unimplemented(); +} + + +// +// KeyPool -- ReferencedKey management functionality +// +KeyPool::KeyPool() +{ +} + +KeyPool::~KeyPool() +{ + StLock _(mKeyMapLock); + // Delete every ReferencedKey in the pool, but be careful to deactivate them first + // to keep them from calling erase (which would cause deadlock since we already hold mKeyMapLock). + KeyMap::iterator end = mKeyMap.end(); + for (KeyMap::iterator it = mKeyMap.begin(); it != end; ++it) + { + try + { + it->second->deactivate(); + } + catch(...) {} + delete it->second; + } + mKeyMap.clear(); +} + +void +KeyPool::add(ReferencedKey &referencedKey) +{ + StLock _(mKeyMapLock); + IFDEBUG(bool inserted =) + mKeyMap.insert(KeyMap::value_type(referencedKey.keyReference(), &referencedKey)).second; + // Since add is only called from the constructor of ReferencedKey we should + // never add a key that is already in mKeyMap + assert(inserted); +} + +ReferencedKey & +KeyPool::findKey(const CSSM_KEY &key) const +{ + return findKeyReference(ReferencedKey::keyReference(key)); +} + +ReferencedKey & +KeyPool::findKeyReference(ReferencedKey::KeyReference keyReference) const +{ + StLock _(mKeyMapLock); + KeyMap::const_iterator it = mKeyMap.find(keyReference); + if (it == mKeyMap.end()) + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_REFERENCE); + + return *it->second; +} + +void +KeyPool::erase(ReferencedKey &referencedKey) +{ + erase(referencedKey.keyReference()); +} + +ReferencedKey & +KeyPool::erase(ReferencedKey::KeyReference keyReference) +{ + StLock _(mKeyMapLock); + KeyMap::iterator it = mKeyMap.find(keyReference); + if (it == mKeyMap.end()) + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_REFERENCE); + + ReferencedKey &referencedKey = *it->second; + mKeyMap.erase(it); + return referencedKey; +} + +// Erase keyReference from mKeyMap, free the ioKey, and delete the ReferencedKey +void +KeyPool::freeKey(Allocator &allocator, CSSM_KEY &ioKey) +{ + delete &erase(ReferencedKey::freeReferenceKey(allocator, ioKey)); +} + +// +// ReferencedKey class +// +ReferencedKey::ReferencedKey(KeyPool &keyPool) : mKeyPool(&keyPool) +{ + mKeyPool->add(*this); +} + +ReferencedKey::~ReferencedKey() +{ + if (isActive()) + mKeyPool->erase(*this); +} + +ReferencedKey::KeyReference +ReferencedKey::keyReference() +{ + // @@@ Possibly check isActive() and return an invalid reference if it is not set. + return reinterpret_cast(this); +} + +// +// Making, retrieving and freeing Key references of CssmKeys +// +void +ReferencedKey::makeReferenceKey(Allocator &allocator, KeyReference keyReference, CSSM_KEY &key) +{ + key.KeyHeader.BlobType = CSSM_KEYBLOB_REFERENCE; + key.KeyHeader.Format = CSSM_KEYBLOB_REF_FORMAT_INTEGER; + key.KeyData.Length = sizeof(KeyReference); + key.KeyData.Data = allocator.alloc(sizeof(KeyReference)); + uint8 *cp = key.KeyData.Data; + for (int i = sizeof(KeyReference); --i >= 0;) + { + cp[i] = keyReference & 0xff; + keyReference = keyReference >> 8; + } +} + +ReferencedKey::KeyReference +ReferencedKey::keyReference(const CSSM_KEY &key) +{ + if (key.KeyHeader.BlobType != CSSM_KEYBLOB_REFERENCE + || key.KeyHeader.Format != CSSM_KEYBLOB_REF_FORMAT_INTEGER + || key.KeyData.Length != sizeof(KeyReference) + || key.KeyData.Data == NULL) + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_REFERENCE); + + const uint8 *cp = key.KeyData.Data; + KeyReference keyReference = 0; + for (uint32 i = 0; i < sizeof(KeyReference); ++i) + keyReference = (keyReference << 8) + cp[i]; + + return keyReference; +} + +ReferencedKey::KeyReference +ReferencedKey::freeReferenceKey(Allocator &allocator, CSSM_KEY &key) +{ + KeyReference aKeyReference = keyReference(key); + allocator.free(key.KeyData.Data); + key.KeyData.Data = NULL; + key.KeyData.Length = 0; + return aKeyReference; +} diff --git a/libsecurity_cdsa_plugin/lib/CSPsession.h b/libsecurity_cdsa_plugin/lib/CSPsession.h new file mode 100644 index 00000000..1d2ae9b1 --- /dev/null +++ b/libsecurity_cdsa_plugin/lib/CSPsession.h @@ -0,0 +1,545 @@ +/* + * 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. + */ + + +// +// CSPsession.h - Framework for CSP plugin modules +// +#ifndef _H_CSPSESSION +#define _H_CSPSESSION + +#include +#include + + +namespace Security { + +// +// The CSPPluginSession provides a general bed for CSP plugin session objects. +// Derive from this if you want to write your CSP, effectively, from scratch. +// We still provide a framework for managing local cryptographic contexts and +// (module) logins. +// +class CSPPluginSession : public PluginSession, public CSPAbstractPluginSession { +public: + CSPPluginSession(CSSM_MODULE_HANDLE theHandle, + CssmPlugin &plug, + const CSSM_VERSION &version, + uint32 subserviceId, + CSSM_SERVICE_TYPE subserviceType, + CSSM_ATTACH_FLAGS attachFlags, + const CSSM_UPCALLS &upcalls) + : PluginSession(theHandle, plug, version, subserviceId, subserviceType, attachFlags, upcalls) { } + + // methods implemented here that you should not override in a subclass + void EventNotify(CSSM_CONTEXT_EVENT e, + CSSM_CC_HANDLE ccHandle, const Context &context); + CSSM_MODULE_FUNCS_PTR construct(); + +public: + class PluginContext { + public: + virtual bool changed(const Context &context); + virtual ~PluginContext(); + }; + +public: + bool loggedIn() const { return mLoggedIn; } + bool loggedIn(bool li) { bool old = mLoggedIn; mLoggedIn = li; return old; } + + template Ctx *getContext(CSSM_CC_HANDLE handle) + { StLock _(contextMapLock); return safe_cast(contextMap[handle]); } + + void setContext(CSSM_CC_HANDLE handle, PluginContext *ctx) + { StLock _(contextMapLock); contextMap[handle] = ctx; } + +public: + // context management methods - override as needed + virtual PluginContext *contextCreate(CSSM_CC_HANDLE handle, const Context &context); + virtual void contextUpdate(CSSM_CC_HANDLE handle, + const Context &context, PluginContext * &ctx); + virtual void contextDelete(CSSM_CC_HANDLE handle, const Context &context, PluginContext *ctx); + +private: + bool mLoggedIn; + + map contextMap; + Mutex contextMapLock; +}; + + +// +// On the other hand, for most CSP modules, this subclass of CSPPluginSession provides +// much more convenient embedding facilities. The theory of operation is too complicated +// to explain here; refer to the accompanying documentation. +// +class CSPFullPluginSession : public CSPPluginSession { +public: + class CSPContext; + class AlgorithmFactory; + + CSPFullPluginSession(CSSM_MODULE_HANDLE theHandle, + CssmPlugin &plug, + const CSSM_VERSION &version, + uint32 subserviceId, + CSSM_SERVICE_TYPE subserviceType, + CSSM_ATTACH_FLAGS attachFlags, + const CSSM_UPCALLS &upcalls) + : CSPPluginSession(theHandle, plug, version, + subserviceId, subserviceType, attachFlags, upcalls) { } + + // final context preparation (called by secondary transition layer) + CSPContext *init(CSSM_CC_HANDLE ccHandle, CSSM_CONTEXT_TYPE type, + const Context &context, bool encoding = true); + + // verify proper state on continuation (update/final) calls + CSPContext *getStagedContext(CSSM_CC_HANDLE ccHandle, + CSSM_CONTEXT_TYPE type, bool encoding = true); + + static const uint32 CSSM_ALGCLASS_CRYPT = 1001; // internally added to CONTEXT_TYPE + +protected: + // validate operation type against context class + void checkOperation(CSSM_CONTEXT_TYPE ctxType, CSSM_CONTEXT_TYPE opType); + +protected: + // + // The Writer class encapsulates staged-output destinations with optional overflow + // + class Writer { + public: + Writer(CssmData *v, uint32 n, CssmData *rem = NULL); + + // can this buffer be extended? + bool isExtensible() const + { return !*vec || remData && !*remData; } + + // increase size if necessary (and possible) + void allocate(size_t needed, Allocator &alloc); + + // straight-forward buffer writing + void put(void *addr, size_t size); + + // locate-mode output (deliver buffer mode) + void nextBlock(void * &p, size_t &sz); + void use(size_t sz); + + // wrap up and return total number of bytes written + size_t close(); + + private: + CssmData *vec; // current buffer descriptor (the one in use) + CssmData *firstVec; // first buffer descriptor + CssmData *lastVec; // last buffer descriptor (NOT one past it) + CssmData *remData; // overflow buffer, if any + + void *currentBuffer; // next free byte in vec + size_t currentSize; // free bytes in vec + + size_t written; // bytes written + + void useData(CssmData *data) + { currentBuffer = data->data(); currentSize = data->length(); } + }; + +public: + // internal utilities (used by our own subclasses) + static CssmData makeBuffer(size_t size, Allocator &alloc); + static size_t totalBufferSize(const CssmData *data, uint32 count); + void setKey(CssmKey &key, + const Context &context, CSSM_KEYCLASS keyClass, + CSSM_KEYATTR_FLAGS attrs, CSSM_KEYUSE use); + +public: + // + // All contexts from CSPFullPluginSession's subclasses must derive from CSPContext. + // CSPFullPluginSession reformulates CSSM operations in terms of virtual methods of + // the context class. + // + class CSPContext : public PluginContext { + friend class CSPFullPluginSession; + public: + CSSM_CONTEXT_TYPE type() const { return mType; } + bool encoding() const { return mDirection; } + + // init() is called for all algorithms + virtual void init(const Context &context, bool encoding = true); + + // the following methods will be called for some but not all algorithms + virtual void update(const CssmData &data); // all block-input algorithms + virtual void update(void *inp, size_t &inSize, void *outp, size_t &outSize); // cryption algs + virtual void final(CssmData &out); // output-data producing algorithms + virtual void final(const CssmData &in); // verifying algorithms + virtual void generate(const Context &context, CssmKey &pubKey, CssmKey &privKey); + virtual void generate(const Context &context, uint32, + CssmData ¶ms, uint32 &attrCount, Context::Attr * &attrs); + virtual CSPContext *clone(Allocator &); // clone internal state + virtual void setDigestAlgorithm(CSSM_ALGORITHMS digestAlg); + + virtual size_t inputSize(size_t outSize); // input for given output size + virtual size_t outputSize(bool final = false, size_t inSize = 0); // output for given input size + virtual void minimumProgress(size_t &in, size_t &out); // minimum progress chunks + + protected: + // convenience forms of the above + void update(const CssmData *in, uint32 inCount, Writer &writer); + void final(CssmData &out, Allocator &alloc); + void final(Writer &writer, Allocator &alloc); + + void update(const CssmData *in, uint32 inCount) + { for (uint32 n = 0; n < inCount; n++) update(in[n]); } + + void checkOperation(CSSM_CONTEXT_TYPE type); + void checkOperation(CSSM_CONTEXT_TYPE type, bool encode); + + CSSM_CONTEXT_TYPE mType; // CSSM context type + bool mDirection; // operation direction (true if irrelevant) + }; + +protected: + virtual void setupContext(CSPContext * &ctx, const Context &context, bool encoding) = 0; + + virtual void getKeySize(const CssmKey &key, CSSM_KEY_SIZE &size); + +public: + // an algorithm factory. This is an optional feature + class AlgorithmFactory { + public: + virtual ~AlgorithmFactory(); + + // set ctx and return true if you can handle this + virtual bool setup(CSPContext * &ctx, const Context &context) = 0; + }; + +public: + void EncryptData(CSSM_CC_HANDLE CCHandle, + const Context &Context, + const CssmData ClearBufs[], + uint32 ClearBufCount, + CssmData CipherBufs[], + uint32 CipherBufCount, + CSSM_SIZE &bytesEncrypted, + CssmData &RemData, + CSSM_PRIVILEGE Privilege); + void EncryptDataInit(CSSM_CC_HANDLE CCHandle, + const Context &Context, + CSSM_PRIVILEGE Privilege); + void EncryptDataUpdate(CSSM_CC_HANDLE CCHandle, + const CssmData ClearBufs[], + uint32 ClearBufCount, + CssmData CipherBufs[], + uint32 CipherBufCount, + CSSM_SIZE &bytesEncrypted); + void EncryptDataFinal(CSSM_CC_HANDLE CCHandle, + CssmData &RemData); + + void DecryptData(CSSM_CC_HANDLE CCHandle, + const Context &Context, + const CssmData CipherBufs[], + uint32 CipherBufCount, + CssmData ClearBufs[], + uint32 ClearBufCount, + CSSM_SIZE &bytesDecrypted, + CssmData &RemData, + CSSM_PRIVILEGE Privilege); + void DecryptDataInit(CSSM_CC_HANDLE CCHandle, + const Context &Context, + CSSM_PRIVILEGE Privilege); + void DecryptDataUpdate(CSSM_CC_HANDLE CCHandle, + const CssmData CipherBufs[], + uint32 CipherBufCount, + CssmData ClearBufs[], + uint32 ClearBufCount, + CSSM_SIZE &bytesDecrypted); + void DecryptDataFinal(CSSM_CC_HANDLE CCHandle, + CssmData &RemData); + + void QuerySize(CSSM_CC_HANDLE CCHandle, + const Context &Context, + CSSM_BOOL Encrypt, + uint32 QuerySizeCount, + QuerySizeData *DataBlock); + + void WrapKey(CSSM_CC_HANDLE CCHandle, + const Context &Context, + const AccessCredentials &AccessCred, + const CssmKey &Key, + const CssmData *DescriptiveData, + CssmKey &WrappedKey, + CSSM_PRIVILEGE Privilege); + void UnwrapKey(CSSM_CC_HANDLE CCHandle, + const Context &Context, + const CssmKey *PublicKey, + const CssmKey &WrappedKey, + uint32 KeyUsage, + uint32 KeyAttr, + const CssmData *KeyLabel, + const CSSM_RESOURCE_CONTROL_CONTEXT *CredAndAclEntry, + CssmKey &UnwrappedKey, + CssmData &DescriptiveData, + CSSM_PRIVILEGE Privilege); + void DeriveKey(CSSM_CC_HANDLE CCHandle, + const Context &Context, + CssmData &Param, + uint32 KeyUsage, + uint32 KeyAttr, + const CssmData *KeyLabel, + const CSSM_RESOURCE_CONTROL_CONTEXT *CredAndAclEntry, + CssmKey &DerivedKey); + + void GenerateMac(CSSM_CC_HANDLE CCHandle, + const Context &Context, + const CssmData DataBufs[], + uint32 DataBufCount, + CssmData &Mac); + void GenerateMacInit(CSSM_CC_HANDLE CCHandle, + const Context &Context); + void GenerateMacUpdate(CSSM_CC_HANDLE CCHandle, + const CssmData DataBufs[], + uint32 DataBufCount); + void GenerateMacFinal(CSSM_CC_HANDLE CCHandle, + CssmData &Mac); + + void VerifyMac(CSSM_CC_HANDLE CCHandle, + const Context &Context, + const CssmData DataBufs[], + uint32 DataBufCount, + const CssmData &Mac); + virtual void VerifyMacInit(CSSM_CC_HANDLE CCHandle, + const Context &Context); + virtual void VerifyMacUpdate(CSSM_CC_HANDLE CCHandle, + const CssmData DataBufs[], + uint32 DataBufCount); + virtual void VerifyMacFinal(CSSM_CC_HANDLE CCHandle, + const CssmData &Mac); + + void SignData(CSSM_CC_HANDLE CCHandle, + const Context &Context, + const CssmData DataBufs[], + uint32 DataBufCount, + CSSM_ALGORITHMS DigestAlgorithm, + CssmData &Signature); + void SignDataInit(CSSM_CC_HANDLE CCHandle, + const Context &Context); + void SignDataUpdate(CSSM_CC_HANDLE CCHandle, + const CssmData DataBufs[], + uint32 DataBufCount); + void SignDataFinal(CSSM_CC_HANDLE CCHandle, + CssmData &Signature); + + void VerifyData(CSSM_CC_HANDLE CCHandle, + const Context &Context, + const CssmData DataBufs[], + uint32 DataBufCount, + CSSM_ALGORITHMS DigestAlgorithm, + const CssmData &Signature); + virtual void VerifyDataInit(CSSM_CC_HANDLE CCHandle, + const Context &Context); + virtual void VerifyDataUpdate(CSSM_CC_HANDLE CCHandle, + const CssmData DataBufs[], + uint32 DataBufCount); + virtual void VerifyDataFinal(CSSM_CC_HANDLE CCHandle, + const CssmData &Signature); + + void DigestData(CSSM_CC_HANDLE CCHandle, + const Context &Context, + const CssmData DataBufs[], + uint32 DataBufCount, + CssmData &Digest); + void DigestDataInit(CSSM_CC_HANDLE CCHandle, + const Context &Context); + void DigestDataUpdate(CSSM_CC_HANDLE CCHandle, + const CssmData DataBufs[], + uint32 DataBufCount); + void DigestDataFinal(CSSM_CC_HANDLE CCHandle, + CssmData &Digest); + void DigestDataClone(CSSM_CC_HANDLE CCHandle, + CSSM_CC_HANDLE ClonedCCHandle); + + void GenerateKey(CSSM_CC_HANDLE CCHandle, + const Context &Context, + uint32 KeyUsage, + uint32 KeyAttr, + const CssmData *KeyLabel, + const CSSM_RESOURCE_CONTROL_CONTEXT *CredAndAclEntry, + CssmKey &Key, + CSSM_PRIVILEGE Privilege); + void GenerateKeyPair(CSSM_CC_HANDLE CCHandle, + const Context &Context, + uint32 PublicKeyUsage, + uint32 PublicKeyAttr, + const CssmData *PublicKeyLabel, + CssmKey &PublicKey, + uint32 PrivateKeyUsage, + uint32 PrivateKeyAttr, + const CssmData *PrivateKeyLabel, + const CSSM_RESOURCE_CONTROL_CONTEXT *CredAndAclEntry, + CssmKey &PrivateKey, + CSSM_PRIVILEGE Privilege); + + void ObtainPrivateKeyFromPublicKey(const CssmKey &PublicKey, + CssmKey &PrivateKey); + void QueryKeySizeInBits(CSSM_CC_HANDLE CCHandle, + const Context *Context, + const CssmKey *Key, + CSSM_KEY_SIZE &KeySize); + + void FreeKey(const AccessCredentials *AccessCred, + CssmKey &KeyPtr, + CSSM_BOOL Delete); + + void GenerateRandom(CSSM_CC_HANDLE CCHandle, + const Context &Context, + CssmData &RandomNumber); + void GenerateAlgorithmParams(CSSM_CC_HANDLE CCHandle, + const Context &Context, + uint32 ParamBits, + CssmData &Param, + uint32 &NumberOfUpdatedAttibutes, + CSSM_CONTEXT_ATTRIBUTE_PTR &UpdatedAttributes); + + void Login(const AccessCredentials &AccessCred, + const CssmData *LoginName, + const void *Reserved); + void Logout(); + void VerifyDevice(const CssmData &DeviceCert); + void GetOperationalStatistics(CSPOperationalStatistics &Statistics); + + void RetrieveCounter(CssmData &Counter); + void RetrieveUniqueId(CssmData &UniqueID); + void GetTimeValue(CSSM_ALGORITHMS TimeAlgorithm, CssmData &TimeData); + + void GetKeyOwner(const CssmKey &Key, + CSSM_ACL_OWNER_PROTOTYPE &Owner); + void ChangeKeyOwner(const AccessCredentials &AccessCred, + const CssmKey &Key, + const CSSM_ACL_OWNER_PROTOTYPE &NewOwner); + void GetKeyAcl(const CssmKey &Key, + const CSSM_STRING *SelectionTag, + uint32 &NumberOfAclInfos, + CSSM_ACL_ENTRY_INFO_PTR &AclInfos); + void ChangeKeyAcl(const AccessCredentials &AccessCred, + const CSSM_ACL_EDIT &AclEdit, + const CssmKey &Key); + + void GetLoginOwner(CSSM_ACL_OWNER_PROTOTYPE &Owner); + void ChangeLoginOwner(const AccessCredentials &AccessCred, + const CSSM_ACL_OWNER_PROTOTYPE &NewOwner); + void GetLoginAcl(const CSSM_STRING *SelectionTag, + uint32 &NumberOfAclInfos, + CSSM_ACL_ENTRY_INFO_PTR &AclInfos); + void ChangeLoginAcl(const AccessCredentials &AccessCred, + const CSSM_ACL_EDIT &AclEdit); + + void PassThrough(CSSM_CC_HANDLE CCHandle, + const Context &Context, + uint32 PassThroughId, + const void *InData, + void **OutData); +}; + + +// +// Classes for dealing with reference keys. +// + +// Forward declaration. +class KeyPool; + +// +// A ReferencedKey -- The private (to the CSP) part of a Reference Key. +// +class ReferencedKey +{ + friend class KeyPool; // So it can call deactivate() +public: + // What we use to reference a ReferencedKey. + typedef CSSM_INTPTR KeyReference; + ReferencedKey(KeyPool &session); // Calls KeyPool::add() + virtual ~ReferencedKey(); // Calls KeyPool::erase() + + KeyReference keyReference(); + bool isActive() { return mKeyPool != NULL; } + + template + SubPool &keyPool() { assert(mKeyPool); return safer_cast(*mKeyPool); } +public: + // Making, retrieving and freeing CSSM_KEYBLOB_REF_FORMAT_INTEGER CSSM_KEY type reference keys + // NOTE: that none of these functions affect mKeyMap. + static void makeReferenceKey(Allocator &allocator, KeyReference keyReference, CSSM_KEY &ioKey); + static KeyReference keyReference(const CSSM_KEY &key); + static KeyReference freeReferenceKey(Allocator &allocator, CSSM_KEY &ioKey); + +private: + void deactivate() { mKeyPool = NULL; } + + // Will be NULL iff this key is not active + KeyPool *mKeyPool; +}; + + +// +// KeyPool -- a mixin class to manage a pool of ReferencedKeys +// +class KeyPool +{ +public: + friend class ReferencedKey; // So it can call add() and erase() +public: + KeyPool(); + virtual ~KeyPool(); + + // Type safe ReferencedKey subclass lookup + template + Subclass &find(const CSSM_KEY &key) const; + + // Free the ioKey, erase keyReference from mKeyMap, and delete the ReferencedKey + void freeKey(Allocator &allocator, CSSM_KEY &key); + +protected: + // Called by the constructor of ReferencedKey -- add referencedKey to mKeyMap + void add(ReferencedKey &referencedKey); + + ReferencedKey &findKey(const CSSM_KEY &key) const; + ReferencedKey &findKeyReference(ReferencedKey::KeyReference keyReference) const; + + // Called by the destructor of ReferencedKey -- erase keyReference from mKeyMap + void erase(ReferencedKey &referencedKey); + + // Erase keyReference from mKeyMap, and return it (for deletion) + ReferencedKey &erase(ReferencedKey::KeyReference keyReference); + +protected: + typedef map KeyMap; + KeyMap mKeyMap; + mutable Mutex mKeyMapLock; +}; + +// Implementation of type safe ReferencedKey subclass lookup. +template +Subclass & +KeyPool::find(const CSSM_KEY &key) const +{ + Subclass *sub; + if (!(sub = dynamic_cast(&findKey(key)))) + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_REFERENCE); + return *sub; +} + +} // end namespace Security + +#endif //_H_CSPSESSION diff --git a/libsecurity_cdsa_plugin/lib/DLsession.cpp b/libsecurity_cdsa_plugin/lib/DLsession.cpp new file mode 100644 index 00000000..508d4712 --- /dev/null +++ b/libsecurity_cdsa_plugin/lib/DLsession.cpp @@ -0,0 +1,57 @@ +/* + * 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. + */ + + +// +// DLsession - Plugin framework for CSP plugin modules +// +#ifdef __MWERKS__ +#define _CPP_DLSESSION +#endif + +#include +#include + + +// +// Construct a DLPluginSession +// +DLPluginSession::DLPluginSession(CSSM_MODULE_HANDLE theHandle, + CssmPlugin &plug, + const CSSM_VERSION &version, + uint32 subserviceId, + CSSM_SERVICE_TYPE subserviceType, + CSSM_ATTACH_FLAGS attachFlags, + const CSSM_UPCALLS &upcalls, + DatabaseManager &databaseManager) + : PluginSession(theHandle, plug, version, subserviceId, subserviceType, attachFlags, upcalls), + DatabaseSession (databaseManager) +{ +} + + +// +// Implement Allocator methods from the PluginSession side +// +void *DLPluginSession::malloc(size_t size) throw(std::bad_alloc) +{ return PluginSession::malloc(size); } + +void DLPluginSession::free(void *addr) throw() +{ return PluginSession::free(addr); } + +void *DLPluginSession::realloc(void *addr, size_t size) throw(std::bad_alloc) +{ return PluginSession::realloc(addr, size); } diff --git a/libsecurity_cdsa_plugin/lib/DLsession.h b/libsecurity_cdsa_plugin/lib/DLsession.h new file mode 100644 index 00000000..bd1b221c --- /dev/null +++ b/libsecurity_cdsa_plugin/lib/DLsession.h @@ -0,0 +1,57 @@ +/* + * 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. + */ + + +// +// DLsession.h - Framework for DL plugin modules +// +#ifndef _H_DLSESSION +#define _H_DLSESSION + +#include +#include + +namespace Security { + +// +// The abstract DLPluginSession class is the common ancestor of your implementation +// object for an DL type plugin attachment session. Inherit from this and implement +// the abstract methods to define a plugin session. +// +class DLPluginSession : public PluginSession, public DatabaseSession { + NOCOPY(DLPluginSession) +public: + DLPluginSession(CSSM_MODULE_HANDLE theHandle, + CssmPlugin &plug, + const CSSM_VERSION &version, + uint32 subserviceId, + CSSM_SERVICE_TYPE subserviceType, + CSSM_ATTACH_FLAGS attachFlags, + const CSSM_UPCALLS &upcalls, + DatabaseManager &databaseManager); + + void *malloc(size_t size) throw(std::bad_alloc); + void free(void *addr) throw(); + void *realloc(void *addr, size_t size) throw(std::bad_alloc); + +protected: + CSSM_MODULE_FUNCS_PTR construct(); +}; + +} // end namespace Security + +#endif //_H_DLSESSION diff --git a/libsecurity_cdsa_plugin/lib/Database.cpp b/libsecurity_cdsa_plugin/lib/Database.cpp new file mode 100644 index 00000000..2343108b --- /dev/null +++ b/libsecurity_cdsa_plugin/lib/Database.cpp @@ -0,0 +1,232 @@ +/* + * 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. + */ + + +#ifdef __MWERKS__ +#define _CPP_DATABASE +#endif +#include +#include +#include +#include + +DatabaseManager::DatabaseManager () +{ +} + +DatabaseManager::~DatabaseManager () +{ +} + +Database * +DatabaseManager::get (const DbName &inDbName) +{ + StLock _(mDatabaseMapLock); + DatabaseMap::iterator anIterator = mDatabaseMap.find (inDbName); + if (anIterator == mDatabaseMap.end()) + { + auto_ptr aDatabase(make(inDbName)); + mDatabaseMap.insert(DatabaseMap::value_type(aDatabase->mDbName, aDatabase.get())); + return aDatabase.release(); + } + + return anIterator->second; +} + +void +DatabaseManager::removeIfUnused(Database &inDatabase) +{ + StLock _(mDatabaseMapLock); + if (!inDatabase.hasDbContexts()) { + mDatabaseMap.erase(inDatabase.mDbName); + delete &inDatabase; + } +} + +DbContext & +DatabaseManager::dbOpen(DatabaseSession &inDatabaseSession, + const DbName &inDbName, + CSSM_DB_ACCESS_TYPE inAccessRequest, + const AccessCredentials *inAccessCred, + const void *inOpenParameters) +{ + Database &aDatabase = *get(inDbName); + try + { + return aDatabase._dbOpen(inDatabaseSession, inAccessRequest, inAccessCred, inOpenParameters); + } + catch (...) + { + removeIfUnused(aDatabase); + throw; + } +} + +DbContext & +DatabaseManager::dbCreate(DatabaseSession &inDatabaseSession, + const DbName &inDbName, + const CSSM_DBINFO &inDBInfo, + CSSM_DB_ACCESS_TYPE inAccessRequest, + const CSSM_RESOURCE_CONTROL_CONTEXT *inCredAndAclEntry, + const void *inOpenParameters) +{ + Database &aDatabase = *get(inDbName); + try + { + return aDatabase._dbCreate(inDatabaseSession, inDBInfo, inAccessRequest, + inCredAndAclEntry, inOpenParameters); + } + catch (...) + { + removeIfUnused(aDatabase); + throw; + } +} + +// Delete a DbContext instance created by calling dbOpen or dbCreate. +void +DatabaseManager::dbClose(DbContext &inDbContext) +{ + Database &aDatabase = inDbContext.mDatabase; + aDatabase._dbClose(inDbContext); + removeIfUnused(aDatabase); +} + +// Delete a database. +void +DatabaseManager::dbDelete(DatabaseSession &inDatabaseSession, + const DbName &inDbName, + const AccessCredentials *inAccessCred) +{ + Database &aDatabase = *get(inDbName); + try + { + aDatabase.dbDelete(inDatabaseSession, inAccessCred); + } + catch (...) + { + removeIfUnused(aDatabase); + throw; + } + + removeIfUnused(aDatabase); +} + +// List all available databases. +CSSM_NAME_LIST_PTR +DatabaseManager::getDbNames(DatabaseSession &inDatabaseSession) +{ + CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); +} + +void +DatabaseManager::freeNameList(DatabaseSession &inDatabaseSession, + CSSM_NAME_LIST &inNameList) +{ + CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); +} + +// Start of Database implementation. + +Database::Database (const DbName &inDbName) +: mDbName(inDbName) +{ +} + +Database::~Database () +{ +} + +bool +Database::hasDbContexts() +{ + StLock _(mDbContextSetLock); + return !mDbContextSet.empty(); +} + +DbContext & +Database::_dbOpen(DatabaseSession &inDatabaseSession, + CSSM_DB_ACCESS_TYPE inAccessRequest, + const AccessCredentials *inAccessCred, + const void *inOpenParameters) +{ + auto_ptraDbContext(makeDbContext(inDatabaseSession, + inAccessRequest, + inAccessCred, + inOpenParameters)); + { + StLock _(mDbContextSetLock); + mDbContextSet.insert(aDbContext.get()); + // Release the mDbContextSetLock + } + + try + { + dbOpen(*aDbContext); + } + catch (...) + { + StLock _(mDbContextSetLock); + mDbContextSet.erase(aDbContext.get()); + throw; + } + + return *aDbContext.release(); +} + +DbContext & +Database::_dbCreate(DatabaseSession &inDatabaseSession, + const CSSM_DBINFO &inDBInfo, + CSSM_DB_ACCESS_TYPE inAccessRequest, + const CSSM_RESOURCE_CONTROL_CONTEXT *inCredAndAclEntry, + const void *inOpenParameters) +{ + auto_ptraDbContext(makeDbContext(inDatabaseSession, + inAccessRequest, + (inCredAndAclEntry + ? AccessCredentials::optional(inCredAndAclEntry->AccessCred) + : NULL), + inOpenParameters)); + { + StLock _(mDbContextSetLock); + mDbContextSet.insert(aDbContext.get()); + // Release the mDbContextSetLock + } + + try + { + dbCreate(*aDbContext, inDBInfo, + inCredAndAclEntry ? &inCredAndAclEntry->InitialAclEntry : NULL); + } + catch (...) + { + StLock _(mDbContextSetLock); + mDbContextSet.erase(aDbContext.get()); + throw; + } + + return *aDbContext.release(); +} + +void +Database::_dbClose(DbContext &dbContext) +{ + StLock _(mDbContextSetLock); + mDbContextSet.erase(&dbContext); + if (mDbContextSet.empty()) + dbClose(); +} diff --git a/libsecurity_cdsa_plugin/lib/Database.h b/libsecurity_cdsa_plugin/lib/Database.h new file mode 100644 index 00000000..52753ae3 --- /dev/null +++ b/libsecurity_cdsa_plugin/lib/Database.h @@ -0,0 +1,248 @@ +/* + * Copyright (c) 2000-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 _DATABASE_H_ +#define _DATABASE_H_ 1 + +#include +#include +#include +#include +#include +#include + + +// @@@ Should not use using in headers. +using namespace std; + +namespace Security +{ + +class Database; +class DatabaseFactory; +class DatabaseSession; +class DbContext; + +/* DatabaseManager class. */ +class DatabaseManager +{ + NOCOPY(DatabaseManager) +public: + DatabaseManager (); + virtual ~DatabaseManager (); + + // Create and return a new DbContext instance which is owned by us and must be discared by calling dbClose. + virtual DbContext &dbOpen(DatabaseSession &inDatabaseSession, + const DbName &inDbName, + CSSM_DB_ACCESS_TYPE inAccessRequest, + const AccessCredentials *inAccessCred, + const void *inOpenParameters); + virtual DbContext &dbCreate(DatabaseSession &inDatabaseSession, + const DbName &inDbName, + const CSSM_DBINFO &inDBInfo, + CSSM_DB_ACCESS_TYPE inAccessRequest, + const CSSM_RESOURCE_CONTROL_CONTEXT *inCredAndAclEntry, + const void *inOpenParameters); + + // Delete a DbContext instance created by calling dbOpen or dbCreate. + virtual void dbClose(DbContext &inDbContext); + + // Delete a database. + virtual void dbDelete(DatabaseSession &inDatabaseSession, + const DbName &inDbName, + const AccessCredentials *inAccessCred); + + // List all available databases. + virtual CSSM_NAME_LIST_PTR getDbNames(DatabaseSession &inDatabaseSession); + virtual void freeNameList(DatabaseSession &inDatabaseSession, + CSSM_NAME_LIST &inNameList); +protected: + virtual void removeIfUnused(Database &inDatabase); + virtual Database *get (const DbName &inDbName); // Get existing instance or make a new one. + virtual Database *make (const DbName &inDbName) = 0; // Create a new database instance subclass must implement. +private: + typedef map DatabaseMap; + DatabaseMap mDatabaseMap; + Mutex mDatabaseMapLock; +}; + + +/* Database is an abstract class. Each Database subclass should implement all the + pure virtual methods listed below. The constructor for a particular Database + subclass should create the Database object. A subsequent call to dBOpen or + dBCreate should be is made. This returns a DbContext. All other methods take + a DbContext as an argument. + */ +class Database +{ +public: + virtual void + dbCreate (DbContext &inDbContext, const CSSM_DBINFO &inDBInfo, + const CSSM_ACL_ENTRY_INPUT *inInitialAclEntry) = 0; + + // Don't override this method in subclasses. + virtual DbContext & + _dbCreate(DatabaseSession &inDatabaseSession, + const CSSM_DBINFO &inDBInfo, + CSSM_DB_ACCESS_TYPE inAccessRequest, + const CSSM_RESOURCE_CONTROL_CONTEXT *inCredAndAclEntry, + const void *inOpenParameters); + + virtual void + dbOpen (DbContext &inDbContext) = 0; + + // Don't override this method in subclasses. + virtual DbContext & + _dbOpen (DatabaseSession &inDatabaseSession, + CSSM_DB_ACCESS_TYPE inAccessRequest, + const AccessCredentials *inAccessCred, + const void *inOpenParameters); + + virtual void + dbClose () = 0; + + // Don't override this method in subclasses. + virtual void + _dbClose (DbContext &dbContext); + + virtual void + dbDelete(DatabaseSession &inDatabaseSession, + const AccessCredentials *inAccessCred) = 0; + + virtual void + createRelation (DbContext &dbContext, + CSSM_DB_RECORDTYPE inRelationID, + const char *inRelationName, + uint32 inNumberOfAttributes, + const CSSM_DB_SCHEMA_ATTRIBUTE_INFO *inAttributeInfo, + uint32 inNumberOfIndexes, + const CSSM_DB_SCHEMA_INDEX_INFO &inIndexInfo) = 0; + + virtual void + destroyRelation (DbContext &dbContext, + CSSM_DB_RECORDTYPE inRelationID) = 0; + + virtual void + authenticate(DbContext &dbContext, + CSSM_DB_ACCESS_TYPE inAccessRequest, + const AccessCredentials &inAccessCred) = 0; + + virtual void + getDbAcl(DbContext &dbContext, + const CSSM_STRING *inSelectionTag, + uint32 &outNumberOfAclInfos, + CSSM_ACL_ENTRY_INFO_PTR &outAclInfos) = 0; + + virtual void + changeDbAcl(DbContext &dbContext, + const AccessCredentials &inAccessCred, + const CSSM_ACL_EDIT &inAclEdit) = 0; + + virtual void + getDbOwner(DbContext &dbContext, CSSM_ACL_OWNER_PROTOTYPE &outOwner) = 0; + + virtual void + changeDbOwner(DbContext &dbContext, + const AccessCredentials &inAccessCred, + const CSSM_ACL_OWNER_PROTOTYPE &inNewOwner) = 0; + + virtual char * + getDbNameFromHandle (const DbContext &dbContext) const = 0; + + virtual CSSM_DB_UNIQUE_RECORD_PTR + dataInsert (DbContext &dbContext, + CSSM_DB_RECORDTYPE RecordType, + const CSSM_DB_RECORD_ATTRIBUTE_DATA *inAttributes, + const CssmData *inData) = 0; + + virtual void + dataDelete (DbContext &dbContext, + const CSSM_DB_UNIQUE_RECORD &inUniqueRecordIdentifier) = 0; + + virtual void + dataModify (DbContext &dbContext, + CSSM_DB_RECORDTYPE RecordType, + CSSM_DB_UNIQUE_RECORD &inoutUniqueRecordIdentifier, + const CSSM_DB_RECORD_ATTRIBUTE_DATA *inAttributesToBeModified, + const CssmData *inDataToBeModified, + CSSM_DB_MODIFY_MODE ModifyMode) = 0; + + virtual CSSM_HANDLE + dataGetFirst (DbContext &dbContext, + const CssmQuery *inQuery, + CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR inoutAttributes, + CssmData *inoutData, + CSSM_DB_UNIQUE_RECORD_PTR &outUniqueRecord) = 0; + + virtual bool + dataGetNext (DbContext &dbContext, + CSSM_HANDLE inResultsHandle, + CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR inoutAttributes, + CssmData *inoutData, + CSSM_DB_UNIQUE_RECORD_PTR &outUniqueRecord) = 0; + + virtual void + dataAbortQuery (DbContext &dbContext, + CSSM_HANDLE inResultsHandle) = 0; + + virtual void + dataGetFromUniqueRecordId (DbContext &dbContext, + const CSSM_DB_UNIQUE_RECORD &inUniqueRecord, + CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR inoutAttributes, + CssmData *inoutData) = 0; + + virtual void + freeUniqueRecord (DbContext &dbContext, + CSSM_DB_UNIQUE_RECORD &inUniqueRecord) = 0; + + virtual void + passThrough(DbContext &dbContext, + uint32 passThroughId, + const void *inputParams, + void **outputParams) = 0; + + Database (const DbName &inDbName); + virtual ~Database (); + + virtual bool hasDbContexts(); + + // XXX @@@ Think about consequences of race conditions between DbOpen/DbCreate/DbDelete/DbClose + // on databases with the same name at the same time. + //virtual DbContext &insertDbContext(); + //virtual void removeDbContext(DbContext &inDbContext); + + const DbName mDbName; +protected: + // Subclasses must implement this method. + virtual DbContext *makeDbContext(DatabaseSession &inDatabaseSession, + CSSM_DB_ACCESS_TYPE inAccessRequest, + const AccessCredentials *inAccessCred, + const void *inOpenParameters) = 0; +private: + typedef set DbContextSet; + DbContextSet mDbContextSet; + Mutex mDbContextSetLock; +}; + +} // end namespace Security + +#ifdef _CPP_DATABASE +# pragma export off +#endif + +#endif //_DATABASE_H_ diff --git a/libsecurity_cdsa_plugin/lib/DatabaseSession.cpp b/libsecurity_cdsa_plugin/lib/DatabaseSession.cpp new file mode 100644 index 00000000..1f554afd --- /dev/null +++ b/libsecurity_cdsa_plugin/lib/DatabaseSession.cpp @@ -0,0 +1,687 @@ +/* + * 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. + */ + + +// +// DatabaseSession.cpp - DL Session. +// +#include + +#include +#include +#include +#include +#include + +/* log open/close events */ +#define DOCDebug(args...) secdebug("DBOpen", ## args) + + +using namespace std; + +extern "C" char* cssmErrorString(CSSM_RETURN errCode); + +// +// Session constructor +// +DatabaseSession::DatabaseSession(DatabaseManager &inDatabaseManager) +: mDatabaseManager(inDatabaseManager) +{ +} + +DatabaseSession::~DatabaseSession() +{ +} + + +// Utility functions +void +DatabaseSession::GetDbNames(CSSM_NAME_LIST_PTR &outNameList) +{ + secdebug("dbsession", "GetDbNames"); + outNameList = mDatabaseManager.getDbNames (*this); + +#ifndef NDEBUG + // dump the returned names + uint32 n; + secdebug("dbsession", "GetDbNames returned %d names", outNameList->NumStrings); + for (n = 0; n < outNameList->NumStrings; ++n) + { + secdebug("dbsession", "%d: %s", n, outNameList->String[n]); + } +#endif + + secdebug("dbsession", "********************"); +} + + +void +DatabaseSession::FreeNameList(CSSM_NAME_LIST &inNameList) +{ + secdebug("dbsession", "FreeNameList"); + mDatabaseManager.freeNameList (*this, inNameList); + secdebug("dbsession", "********************"); +} + + +void +DatabaseSession::DbDelete(const char *inDbName, + const CSSM_NET_ADDRESS *inDbLocation, + const AccessCredentials *inAccessCred) +{ + // The databaseManager will notify all its DbContext instances + // that the database is question is being deleted. + secdebug("dbsession", "DbDelete of %s", inDbName); + mDatabaseManager.dbDelete(*this, DbName(inDbName, CssmNetAddress::optional(inDbLocation)), inAccessCred); + secdebug("dbsession", "********************"); +} + +// DbContext creation and destruction. +void +DatabaseSession::DbCreate(const char *inDbName, + const CSSM_NET_ADDRESS *inDbLocation, + const CSSM_DBINFO &inDBInfo, + CSSM_DB_ACCESS_TYPE inAccessRequest, + const CSSM_RESOURCE_CONTROL_CONTEXT *inCredAndAclEntry, + const void *inOpenParameters, + CSSM_DB_HANDLE &outDbHandle) +{ + outDbHandle = CSSM_INVALID_HANDLE; // CDSA 2.0 says to set this if we fail + secdebug("dbsession", "DbCreate of %s", inDbName); + + outDbHandle = insertDbContext(mDatabaseManager.dbCreate(*this, + DbName(inDbName, CssmNetAddress::optional(inDbLocation)), + inDBInfo, + inAccessRequest, + inCredAndAclEntry, + inOpenParameters)); + secdebug("dbsession", "DbCreate returned handle %#lx", outDbHandle); + + secdebug("dbsession", "********************"); +} + +void +DatabaseSession::DbOpen(const char *inDbName, + const CSSM_NET_ADDRESS *inDbLocation, + CSSM_DB_ACCESS_TYPE inAccessRequest, + const AccessCredentials *inAccessCred, + const void *inOpenParameters, + CSSM_DB_HANDLE &outDbHandle) +{ + DOCDebug("DatabaseSession::DbOpen: dbName %s", inDbName); + secdebug("dbsession", "DbOpen of %s", inDbName); + outDbHandle = CSSM_INVALID_HANDLE; // CDSA 2.0 says to set this if we fail + outDbHandle = insertDbContext(mDatabaseManager.dbOpen(*this, + DbName(inDbName, CssmNetAddress::optional(inDbLocation)), + inAccessRequest, + inAccessCred, + inOpenParameters)); + secdebug("dbsession", "DbOpen returned handle %#lx", outDbHandle); + secdebug("dbsession", "********************"); +} + +CSSM_DB_HANDLE +DatabaseSession::insertDbContext(DbContext &inDbContext) +{ + CSSM_DB_HANDLE aDbHandle; + try + { + aDbHandle = inDbContext.handle (); + StLock _(mDbContextMapLock); + mDbContextMap.insert(DbContextMap::value_type(aDbHandle, &inDbContext)); + } + catch (...) + { + // Close the context + mDatabaseManager.dbClose(inDbContext); + throw; + } + + return aDbHandle; +} + +DbContext & +DatabaseSession::findDbContext(CSSM_DB_HANDLE inDbHandle) +{ + StLock _(mDbContextMapLock); + DbContextMap::iterator it = mDbContextMap.find(inDbHandle); + if (it == mDbContextMap.end()) + CssmError::throwMe(CSSM_ERRCODE_INVALID_DB_HANDLE); + return *it->second; +} + +void +DatabaseSession::closeAll() +{ + StLock _(mDbContextMapLock); + for (DbContextMap::iterator it = mDbContextMap.begin(); + it != mDbContextMap.end(); + it++) + { + DbContext *aDbContext = it->second; + try + { + mDatabaseManager.dbClose(*aDbContext); + // This is done by the database itself which owns the context. + //delete aDbContext; + } + catch (...) + { + // Ignore exceptions since we want to close as many DBs as possible. + // XXX @@@ log an error or something. + } + } + + mDbContextMap.clear(); + secdebug("dbsession", "********************"); +} + +// Operations using DbContext instances. +void +DatabaseSession::DbClose(CSSM_DB_HANDLE inDbHandle) +{ + StLock _(mDbContextMapLock); + DOCDebug("DatabaseSession::Close"); + secdebug("dbsession", "DbClose of handle %ld", inDbHandle); + DbContextMap::iterator it = mDbContextMap.find(inDbHandle); + if (it == mDbContextMap.end()) + CssmError::throwMe(CSSM_ERRCODE_INVALID_DB_HANDLE); + auto_ptr aDbContext(it->second); + mDbContextMap.erase(it); + mDatabaseManager.dbClose(*aDbContext); + secdebug("dbsession", "********************"); +} + +void +DatabaseSession::CreateRelation(CSSM_DB_HANDLE inDbHandle, + CSSM_DB_RECORDTYPE inRelationID, + const char *inRelationName, + uint32 inNumberOfAttributes, + const CSSM_DB_SCHEMA_ATTRIBUTE_INFO *inAttributeInfo, + uint32 inNumberOfIndexes, + const CSSM_DB_SCHEMA_INDEX_INFO &inIndexInfo) +{ + secdebug("dbsession", "CreateRelation from handle %ld of record type %X with relation name %s", inDbHandle, inRelationID, inRelationName); + secdebug("dbsession", "number of attributes = %d", inNumberOfAttributes); +#ifndef NDEBUG + unsigned n; + for (n = 0; n < inNumberOfAttributes; ++n) + { + secdebug("dbsession", "%d: id %d name %s, data type %d", n, inAttributeInfo[n].AttributeId, + inAttributeInfo[n].AttributeName, + inAttributeInfo[n].DataType); + } +#endif + + secdebug("dbsession", "number of indexes: %d", inNumberOfIndexes); +#ifndef NDEBUG + for (n = 0; n < inNumberOfIndexes; ++n) + { + secdebug("dbsession", "%d: id %d indexid %d indextype %d location %d", n, inIndexInfo.AttributeId, + inIndexInfo.IndexedDataLocation, + inIndexInfo.IndexId, + inIndexInfo.IndexType); + } +#endif + + DbContext &aDbContext = findDbContext(inDbHandle); + return aDbContext.mDatabase.createRelation(aDbContext, inRelationID, inRelationName, + inNumberOfAttributes, inAttributeInfo, + inNumberOfIndexes, inIndexInfo); + secdebug("dbsession", "********************"); +} + +void +DatabaseSession::DestroyRelation(CSSM_DB_HANDLE inDbHandle, + CSSM_DB_RECORDTYPE inRelationID) +{ + secdebug("dbsession", "DestroyRelation (handle %ld) %d", inDbHandle, inRelationID); + DbContext &aDbContext = findDbContext(inDbHandle); + aDbContext.mDatabase.destroyRelation(aDbContext, inRelationID); + secdebug("dbsession", "********************"); +} + +void +DatabaseSession::Authenticate(CSSM_DB_HANDLE inDbHandle, + CSSM_DB_ACCESS_TYPE inAccessRequest, + const AccessCredentials &inAccessCred) +{ + secdebug("dbsession", "Authenticate (handle %ld) inAccessRequest %d", inDbHandle, inAccessRequest); + DbContext &aDbContext = findDbContext(inDbHandle); + aDbContext.mDatabase.authenticate(aDbContext, inAccessRequest, inAccessCred); + secdebug("dbsession", "********************"); +} + + +void +DatabaseSession::GetDbAcl(CSSM_DB_HANDLE inDbHandle, + const CSSM_STRING *inSelectionTag, + uint32 &outNumberOfAclInfos, + CSSM_ACL_ENTRY_INFO_PTR &outAclInfos) +{ + secdebug("dbsession", "GetDbAcl (handle %ld)", inDbHandle); + DbContext &aDbContext = findDbContext(inDbHandle); + aDbContext.mDatabase.getDbAcl(aDbContext, inSelectionTag, outNumberOfAclInfos, outAclInfos); + secdebug("dbsession", "********************"); +} + +void +DatabaseSession::ChangeDbAcl(CSSM_DB_HANDLE inDbHandle, + const AccessCredentials &inAccessCred, + const CSSM_ACL_EDIT &inAclEdit) +{ + secdebug("dbsession", "ChangeDbAcl (handle %ld)", inDbHandle); + DbContext &aDbContext = findDbContext(inDbHandle); + aDbContext.mDatabase.changeDbAcl(aDbContext, inAccessCred, inAclEdit); + secdebug("dbsession", "********************"); +} + +void +DatabaseSession::GetDbOwner(CSSM_DB_HANDLE inDbHandle, + CSSM_ACL_OWNER_PROTOTYPE &outOwner) +{ + secdebug("dbsession", "GetDbOwner (handle %ld)", inDbHandle); + DbContext &aDbContext = findDbContext(inDbHandle); + aDbContext.mDatabase.getDbOwner(aDbContext, outOwner); + secdebug("dbsession", "********************"); +} + +void +DatabaseSession::ChangeDbOwner(CSSM_DB_HANDLE inDbHandle, + const AccessCredentials &inAccessCred, + const CSSM_ACL_OWNER_PROTOTYPE &inNewOwner) +{ + secdebug("dbsession", "ChangeDbOwner (handle %ld)", inDbHandle); + DbContext &aDbContext = findDbContext(inDbHandle); + aDbContext.mDatabase.changeDbOwner(aDbContext, inAccessCred, inNewOwner); + secdebug("dbsession", "********************"); +} + +void +DatabaseSession::GetDbNameFromHandle(CSSM_DB_HANDLE inDbHandle, + char **outDbName) +{ + secdebug("dbsession", "GetDbNameFromHandle (handle %ld)", inDbHandle); + DbContext &aDbContext = findDbContext(inDbHandle); + Required(outDbName) = aDbContext.mDatabase.getDbNameFromHandle(aDbContext); + secdebug("dbsession", "name: %s", *outDbName); + secdebug("dbsession", "********************"); +} + +#ifndef NDEBUG +void DumpAttributeInfo(const CSSM_DB_ATTRIBUTE_INFO &info) +{ + const char* attrNameType; + switch (info.AttributeFormat) + { + case CSSM_DB_ATTRIBUTE_NAME_AS_STRING: + attrNameType = "CSSM_DB_ATTRIBUTE_NAME_AS_STRING"; + break; + + case CSSM_DB_ATTRIBUTE_NAME_AS_OID: + attrNameType = "CSSM_DB_ATTRIBUTE_NAME_AS_OID"; + break; + + case CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER: + attrNameType = "CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER"; + break; + } + + secdebug("dbsession", " Attribute name type: %s", attrNameType); + switch (info.AttributeFormat) + { + case CSSM_DB_ATTRIBUTE_NAME_AS_STRING: + secdebug("dbsession", " name: %s", info.Label.AttributeName); + break; + + case CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER: + secdebug("dbsession", " name: %d", info.Label.AttributeID); + break; + + case CSSM_DB_ATTRIBUTE_NAME_AS_OID: + secdebug("dbsession", " name is oid"); + break; + } + + const char* s; + switch (info.AttributeFormat) + { + case CSSM_DB_ATTRIBUTE_FORMAT_STRING: + s = "CSSM_DB_ATTRIBUTE_FORMAT_STRING"; + break; + case CSSM_DB_ATTRIBUTE_FORMAT_SINT32: + s = "CSSM_DB_ATTRIBUTE_FORMAT_SINT32"; + break; + case CSSM_DB_ATTRIBUTE_FORMAT_UINT32: + s = "CSSM_DB_ATTRIBUTE_FORMAT_UINT32"; + break; + case CSSM_DB_ATTRIBUTE_FORMAT_BIG_NUM: + s = "CSSM_DB_ATTRIBUTE_FORMAT_BIG_NUM"; + break; + case CSSM_DB_ATTRIBUTE_FORMAT_REAL: + s = "CSSM_DB_ATTRIBUTE_FORMAT_REAL"; + break; + case CSSM_DB_ATTRIBUTE_FORMAT_TIME_DATE: + s = "CSSM_DB_ATTRIBUTE_FORMAT_TIME_DATE"; + break; + case CSSM_DB_ATTRIBUTE_FORMAT_BLOB: + s = "CSSM_DB_ATTRIBUTE_FORMAT_BLOB"; + break; + case CSSM_DB_ATTRIBUTE_FORMAT_MULTI_UINT32: + s = "CSSM_DB_ATTRIBUTE_FORMAT_MULTI_UINT32"; + break; + case CSSM_DB_ATTRIBUTE_FORMAT_COMPLEX: + s = "CSSM_DB_ATTRIBUTE_FORMAT_COMPLEX"; + break; + } + + secdebug("dbsession", " attribute format: %s", s); +} + + + +void DumpAttributes(const CSSM_DB_RECORD_ATTRIBUTE_DATA *inAttributes) +{ + if (!inAttributes) + { + secdebug("dbsession", "No attributes defined."); + return; + } + + secdebug("dbsession", "insert into %d", inAttributes->DataRecordType); + secdebug("dbsession", "Semantic information %d", inAttributes->SemanticInformation); + secdebug("dbsession", "Number of attributes: %d", inAttributes->NumberOfAttributes); + + unsigned n; + for (n = 0; n < inAttributes->NumberOfAttributes; ++n) + { + DumpAttributeInfo(inAttributes->AttributeData[n].Info); + secdebug("dbsession", "Attribute %d\n", n); + secdebug("dbsession", " number of values: %d", inAttributes->AttributeData[n].NumberOfValues); + unsigned i; + for (i = 0; i < inAttributes->AttributeData[n].NumberOfValues; ++i) + { + switch (inAttributes->AttributeData[n].Info.AttributeFormat) + { + case CSSM_DB_ATTRIBUTE_FORMAT_STRING: + { + std::string ss((char*) inAttributes->AttributeData[n].Value[i].Data, inAttributes->AttributeData[n].Value[i].Length); + secdebug("dbsession", " Value %d: %s", i, ss.c_str()); + break; + } + case CSSM_DB_ATTRIBUTE_FORMAT_SINT32: + secdebug("dbsession", " Value %d: %d", i, *(sint32*)inAttributes->AttributeData[n].Value[i].Data); + break; + case CSSM_DB_ATTRIBUTE_FORMAT_UINT32: + secdebug("dbsession", " Value %d: %u", i, *(uint32*)inAttributes->AttributeData[n].Value[i].Data); + break; + case CSSM_DB_ATTRIBUTE_FORMAT_BIG_NUM: + secdebug("dbsession", " Value %d: (bignum)", i); + break; + case CSSM_DB_ATTRIBUTE_FORMAT_REAL: + secdebug("dbsession", " Value %d: %f", i, *(double*)inAttributes->AttributeData[n].Value[i].Data); + break; + case CSSM_DB_ATTRIBUTE_FORMAT_TIME_DATE: + secdebug("dbsession", " Value %d: %s", i, (char*)inAttributes->AttributeData[n].Value[i].Data); + break; + case CSSM_DB_ATTRIBUTE_FORMAT_BLOB: + secdebug("dbsession", " Value %d: (blob)", i); + break; + case CSSM_DB_ATTRIBUTE_FORMAT_MULTI_UINT32: + { + unsigned j; + unsigned numInts = inAttributes->AttributeData[n].Value[i].Length / sizeof(UInt32); + for (j = 0; j < numInts; ++j) + { + uint32* nums = (uint32*) inAttributes->AttributeData[n].Value[i].Data; + secdebug("dbsession", " %d", nums[j]); + } + + break; + } + + case CSSM_DB_ATTRIBUTE_FORMAT_COMPLEX: + secdebug("dbsession", " Value %d: (complex)", i); + break; + } + } + } +} + + + +void +DumpUniqueRecord(const CSSM_DB_UNIQUE_RECORD &record) +{ + const char* s; + +/* + switch (record.RecordLocator.IndexType) + { + case CSSM_DB_INDEX_UNIQUE: + { + s = "CSSM_DB_INDEX_UNIQUE"; + break; + } + + case CSSM_DB_INDEX_NONUNIQUE: + { + s = "CSSM_DB_INDEX_NONUNIQUE"; + break; + } + } + + secdebug("dbsession", "RecordLocator.IndexType: %s", s); + + switch (record.RecordLocator.IndexedDataLocation) + { + case CSSM_DB_INDEX_ON_UNKNOWN: + { + s = "CSSM_DB_INDEX_ON_UNKNOWN"; + break; + } + + case CSSM_DB_INDEX_ON_ATTRIBUTE: + { + s = "CSSM_DB_INDEX_ON_ATTRIBUTE"; + break; + } + + case CSSM_DB_INDEX_ON_RECORD: + { + s = "CSSM_DB_INDEX_ON_RECORD"; + break; + } + } + + secdebug("dbsession", "RecordLocator.IndexedDataLocation: %s", s); + + secdebug("dbsession", "Attribute info:"); + + DumpAttributeInfo(record.RecordLocator.Info); +*/ + + // put the record ID into hex + std::string output; + char hexBuffer[4]; + unsigned i; + for (i = 0; i < record.RecordIdentifier.Length; ++i) + { + sprintf(hexBuffer, "%02X", record.RecordIdentifier.Data[i]); + output += hexBuffer; + } + + secdebug("dbsession", " RecordIdentifier.Data: %s", output.c_str()); +} +#endif + +void +DatabaseSession::DataInsert(CSSM_DB_HANDLE inDbHandle, + CSSM_DB_RECORDTYPE inRecordType, + const CSSM_DB_RECORD_ATTRIBUTE_DATA *inAttributes, + const CssmData *inData, + CSSM_DB_UNIQUE_RECORD_PTR &outUniqueId) +{ + secdebug("dbsession", "%p DataInsert(%lx,%x)", this, inDbHandle, inRecordType); + DbContext &aDbContext = findDbContext(inDbHandle); + outUniqueId = aDbContext.mDatabase.dataInsert(aDbContext, inRecordType, inAttributes, inData); + +#ifndef NDEBUG + secdebug("dbsession", "Returned unique id:"); + DumpUniqueRecord(*outUniqueId); +#endif + + secdebug("dbsession", "********************"); +} + + +void +DatabaseSession::DataDelete(CSSM_DB_HANDLE inDbHandle, + const CSSM_DB_UNIQUE_RECORD &inUniqueRecordIdentifier) +{ + secdebug("dbsession", "%p DataDelete(%lx)", this, inDbHandle); + DbContext &aDbContext = findDbContext(inDbHandle); + aDbContext.mDatabase.dataDelete(aDbContext, inUniqueRecordIdentifier); + +#ifndef NDEBUG + secdebug("dbsession", "Record identifier:"); + DumpUniqueRecord(inUniqueRecordIdentifier); +#endif + secdebug("dbsession", "********************"); +} + + +void +DatabaseSession::DataModify(CSSM_DB_HANDLE inDbHandle, + CSSM_DB_RECORDTYPE inRecordType, + CSSM_DB_UNIQUE_RECORD &inoutUniqueRecordIdentifier, + const CSSM_DB_RECORD_ATTRIBUTE_DATA *inAttributesToBeModified, + const CssmData *inDataToBeModified, + CSSM_DB_MODIFY_MODE inModifyMode) +{ + secdebug("dbsession", "%p DataModify(%lx,%x)", this, inDbHandle, inRecordType); + DbContext &aDbContext = findDbContext(inDbHandle); + aDbContext.mDatabase.dataModify(aDbContext, inRecordType, inoutUniqueRecordIdentifier, + inAttributesToBeModified, inDataToBeModified, inModifyMode); +#ifndef NDEBUG + secdebug("dbsession", "Out record identifier:"); + DumpUniqueRecord(inoutUniqueRecordIdentifier); +#endif + secdebug("dbsession", "********************"); +} + +CSSM_HANDLE +DatabaseSession::DataGetFirst(CSSM_DB_HANDLE inDbHandle, + const CssmQuery *inQuery, + CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR inoutAttributes, + CssmData *inoutData, + CSSM_DB_UNIQUE_RECORD_PTR &outUniqueId) +{ + secdebug("dbsession", "%p DataGetFirst(%lx)", this, inDbHandle); + DbContext &aDbContext = findDbContext(inDbHandle); + + CSSM_HANDLE result = aDbContext.mDatabase.dataGetFirst(aDbContext, inQuery, + inoutAttributes, inoutData, outUniqueId); +#ifndef NDEBUG + secdebug("dbsession", "result handle: %lx", result); + if (result != 0) + { + secdebug("dbsession", "Returned ID:"); + DumpUniqueRecord(*outUniqueId); + } +#endif + + secdebug("dbsession", "********************"); + return result; +} + +bool +DatabaseSession::DataGetNext(CSSM_DB_HANDLE inDbHandle, + CSSM_HANDLE inResultsHandle, + CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR inoutAttributes, + CssmData *inoutData, + CSSM_DB_UNIQUE_RECORD_PTR &outUniqueRecord) +{ + secdebug("dbsession", "DataGetNext(%lx)", inDbHandle); + DbContext &aDbContext = findDbContext(inDbHandle); + + bool result = aDbContext.mDatabase.dataGetNext(aDbContext, inResultsHandle, inoutAttributes, + inoutData, outUniqueRecord); + +#ifndef NDEBUG + if (result) + { + secdebug("dbsession", "Returned ID:"); + DumpUniqueRecord(*outUniqueRecord); + } +#endif + + secdebug("dbsession", "********************"); + return result; +} + +void +DatabaseSession::DataAbortQuery(CSSM_DB_HANDLE inDbHandle, + CSSM_HANDLE inResultsHandle) +{ + secdebug("dbsession", "%p DataAbortQuery(%lx)", this, inDbHandle); + DbContext &aDbContext = findDbContext(inDbHandle); + aDbContext.mDatabase.dataAbortQuery(aDbContext, inResultsHandle); + secdebug("dbsession", "********************"); +} + +void +DatabaseSession::DataGetFromUniqueRecordId(CSSM_DB_HANDLE inDbHandle, + const CSSM_DB_UNIQUE_RECORD &inUniqueRecord, + CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR inoutAttributes, + CssmData *inoutData) +{ + secdebug("dbsession", "%p DataGetFromUniqueId(%lx)", this, inDbHandle); +#ifndef NDEBUG + secdebug("dbsession", "inUniqueRecord:"); + DumpUniqueRecord(inUniqueRecord); +#endif + + DbContext &aDbContext = findDbContext(inDbHandle); + aDbContext.mDatabase.dataGetFromUniqueRecordId(aDbContext, inUniqueRecord, + inoutAttributes, inoutData); + secdebug("dbsession", "********************"); +} + +void +DatabaseSession::FreeUniqueRecord(CSSM_DB_HANDLE inDbHandle, + CSSM_DB_UNIQUE_RECORD &inUniqueRecordIdentifier) +{ + secdebug("dbsession", "FreeUniqueRecord: %lx", inDbHandle); +#ifndef NDEBUG + secdebug("dbsession", "inUniqueRecordIdentifier follows:"); + DumpUniqueRecord(inUniqueRecordIdentifier); +#endif + DbContext &aDbContext = findDbContext(inDbHandle); + aDbContext.mDatabase.freeUniqueRecord(aDbContext, inUniqueRecordIdentifier); + secdebug("dbsession", "********************"); +} + +void +DatabaseSession::PassThrough(CSSM_DB_HANDLE inDbHandle, + uint32 passThroughId, + const void *inputParams, + void **outputParams) +{ + DbContext &aDbContext = findDbContext(inDbHandle); + aDbContext.mDatabase.passThrough(aDbContext, passThroughId, inputParams, outputParams); +} diff --git a/libsecurity_cdsa_plugin/lib/DatabaseSession.h b/libsecurity_cdsa_plugin/lib/DatabaseSession.h new file mode 100644 index 00000000..9e65d8b4 --- /dev/null +++ b/libsecurity_cdsa_plugin/lib/DatabaseSession.h @@ -0,0 +1,140 @@ +/* + * 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. + */ + + +// +// DatabaseSession.h - Framework for DL plugin modules +// +#ifndef _H_DATABASESESSION +#define _H_DATABASESESSION + +#include + +#include +#include +#include +#include + +namespace Security { + +class DatabaseManager; +class DbContext; + +// A class providing some of the base Database (DL and MDS) functionality. +class DatabaseSession: public DLAbstractPluginSession, public Allocator +{ +public: + DatabaseSession(DatabaseManager &inDatabaseManager); + virtual ~DatabaseSession(); + + virtual void GetDbNames(CSSM_NAME_LIST_PTR &NameList); + virtual void FreeNameList(CSSM_NAME_LIST &NameList); + void DbDelete(const char *DbName, + const CSSM_NET_ADDRESS *DbLocation, + const AccessCredentials *AccessCred); + void DbCreate(const char *DbName, + const CSSM_NET_ADDRESS *DbLocation, + const CSSM_DBINFO &DBInfo, + CSSM_DB_ACCESS_TYPE AccessRequest, + const CSSM_RESOURCE_CONTROL_CONTEXT *CredAndAclEntry, + const void *OpenParameters, + CSSM_DB_HANDLE &DbHandle); + virtual void DbOpen(const char *DbName, + const CSSM_NET_ADDRESS *DbLocation, + CSSM_DB_ACCESS_TYPE AccessRequest, + const AccessCredentials *AccessCred, + const void *OpenParameters, + CSSM_DB_HANDLE &DbHandle); + void DbClose(CSSM_DB_HANDLE DBHandle); + void CreateRelation(CSSM_DB_HANDLE DBHandle, + CSSM_DB_RECORDTYPE RelationID, + const char *RelationName, + uint32 NumberOfAttributes, + const CSSM_DB_SCHEMA_ATTRIBUTE_INFO *pAttributeInfo, + uint32 NumberOfIndexes, + const CSSM_DB_SCHEMA_INDEX_INFO &pIndexInfo); + void DestroyRelation(CSSM_DB_HANDLE DBHandle, + CSSM_DB_RECORDTYPE RelationID); + + void Authenticate(CSSM_DB_HANDLE DBHandle, + CSSM_DB_ACCESS_TYPE AccessRequest, + const AccessCredentials &AccessCred); + void GetDbAcl(CSSM_DB_HANDLE DBHandle, + const CSSM_STRING *SelectionTag, + uint32 &NumberOfAclInfos, + CSSM_ACL_ENTRY_INFO_PTR &AclInfos); + void ChangeDbAcl(CSSM_DB_HANDLE DBHandle, + const AccessCredentials &AccessCred, + const CSSM_ACL_EDIT &AclEdit); + void GetDbOwner(CSSM_DB_HANDLE DBHandle, + CSSM_ACL_OWNER_PROTOTYPE &Owner); + void ChangeDbOwner(CSSM_DB_HANDLE DBHandle, + const AccessCredentials &AccessCred, + const CSSM_ACL_OWNER_PROTOTYPE &NewOwner); + void GetDbNameFromHandle(CSSM_DB_HANDLE DBHandle, + char **DbName); + void DataInsert(CSSM_DB_HANDLE DBHandle, + CSSM_DB_RECORDTYPE RecordType, + const CSSM_DB_RECORD_ATTRIBUTE_DATA *Attributes, + const CssmData *Data, + CSSM_DB_UNIQUE_RECORD_PTR &UniqueId); + void DataDelete(CSSM_DB_HANDLE DBHandle, + const CSSM_DB_UNIQUE_RECORD &UniqueRecordIdentifier); + void DataModify(CSSM_DB_HANDLE DBHandle, + CSSM_DB_RECORDTYPE RecordType, + CSSM_DB_UNIQUE_RECORD &UniqueRecordIdentifier, + const CSSM_DB_RECORD_ATTRIBUTE_DATA *AttributesToBeModified, + const CssmData *DataToBeModified, + CSSM_DB_MODIFY_MODE ModifyMode); + CSSM_HANDLE DataGetFirst(CSSM_DB_HANDLE DBHandle, + const CssmQuery *Query, + CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR Attributes, + CssmData *Data, + CSSM_DB_UNIQUE_RECORD_PTR &UniqueId); + bool DataGetNext(CSSM_DB_HANDLE DBHandle, + CSSM_HANDLE ResultsHandle, + CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR Attributes, + CssmData *Data, + CSSM_DB_UNIQUE_RECORD_PTR &UniqueId); + void DataAbortQuery(CSSM_DB_HANDLE DBHandle, + CSSM_HANDLE ResultsHandle); + void DataGetFromUniqueRecordId(CSSM_DB_HANDLE DBHandle, + const CSSM_DB_UNIQUE_RECORD &UniqueRecord, + CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR Attributes, + CssmData *Data); + void FreeUniqueRecord(CSSM_DB_HANDLE DBHandle, + CSSM_DB_UNIQUE_RECORD &UniqueRecord); + void PassThrough(CSSM_DB_HANDLE DBHandle, + uint32 PassThroughId, + const void *InputParams, + void **OutputParams); + + DatabaseManager &mDatabaseManager; +protected: + void closeAll(); +private: + CSSM_DB_HANDLE insertDbContext(DbContext &dbContext); + DbContext &findDbContext(CSSM_DB_HANDLE inDbHandle); + + typedef std::map DbContextMap; + DbContextMap mDbContextMap; + Mutex mDbContextMapLock; +}; + +} // end namespace Security + +#endif //_H_DATABASESESSION diff --git a/libsecurity_cdsa_plugin/lib/DbContext.cpp b/libsecurity_cdsa_plugin/lib/DbContext.cpp new file mode 100644 index 00000000..43461b9e --- /dev/null +++ b/libsecurity_cdsa_plugin/lib/DbContext.cpp @@ -0,0 +1,44 @@ +/* + * 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. + */ + + +#ifdef __MWERKS__ +#define _CPP_DBCONTEXT +#endif +#include + +#include + +#include + +DbContext::DbContext (Database &inDatabase, + DatabaseSession &inDatabaseSession, + CSSM_DB_ACCESS_TYPE inAccessRequest, + const CSSM_ACCESS_CREDENTIALS *inAccessCred) : + mDatabase (inDatabase), + mDatabaseSession (inDatabaseSession), + mAccessRequest (inAccessRequest) +{ + // XXX Copy the ACL. + //mAccessCred = inAccessCred; +} + +DbContext::~DbContext () +{ + //delete mAccessCred; + // XXX How do we delete these? +} diff --git a/libsecurity_cdsa_plugin/lib/DbContext.h b/libsecurity_cdsa_plugin/lib/DbContext.h new file mode 100644 index 00000000..d5877195 --- /dev/null +++ b/libsecurity_cdsa_plugin/lib/DbContext.h @@ -0,0 +1,76 @@ +/* + * 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 _DBCONTEXT_H_ +#define _DBCONTEXT_H_ 1 + +#include +#include + +#ifdef _CPP_DBCONTEXT +# pragma export on +#endif + +namespace Security +{ + +class DatabaseSession; + +class DbContext : public HandleObject +{ + NOCOPY(DbContext) +public: + Database &mDatabase; + DatabaseSession &mDatabaseSession; + + DbContext(Database &inDatabase, + DatabaseSession &inDatabaseSession, + CSSM_DB_ACCESS_TYPE inAccessRequest, + const CSSM_ACCESS_CREDENTIALS *inAccessCred); + + virtual ~DbContext(); + + CSSM_HANDLE + dataGetFirst(const CssmQuery *inQuery, + CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR inoutAttributes, + CssmData *inoutData, + CSSM_DB_UNIQUE_RECORD_PTR &outUniqueRecord); + + void + dataGetNext(CSSM_HANDLE inResultsHandle, + CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR inoutAttributes, + CssmData *inoutData, + CSSM_DB_UNIQUE_RECORD_PTR &outUniqueRecord); + + void + dataAbortQuery(CSSM_HANDLE inResultsHandle); +private: + CSSM_DB_ACCESS_TYPE mAccessRequest; + CSSM_ACCESS_CREDENTIALS *mAccessCred; + //typedef set DbQuerySet; + //DbQuerySet mDbQuerySet; + //Mutex mDbQuerySetLock; +}; + +} // end namespace Security + +#ifdef _CPP_DBCONTEXT +# pragma export off +#endif + +#endif //_DBCONTEXT_H_ diff --git a/libsecurity_cdsa_plugin/lib/TPsession.h b/libsecurity_cdsa_plugin/lib/TPsession.h new file mode 100644 index 00000000..1aa72a7d --- /dev/null +++ b/libsecurity_cdsa_plugin/lib/TPsession.h @@ -0,0 +1,56 @@ +/* + * 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. + */ + + +// +// TPsession.h - Framework for TP plugin modules +// +#ifndef _H_TPSESSION +#define _H_TPSESSION + +#include + +#if defined(_CPP_TPSESSION) +# pragma export on +#endif + +namespace Security { + +// +// The abstract TPPluginSession class is the common ancestor of your implementation +// object for an TP type plugin attachment session. Inherit from this and implement +// the abstract methods to define a plugin session. +// +class TPPluginSession : public PluginSession, public TPAbstractPluginSession { +public: + TPPluginSession(CSSM_MODULE_HANDLE theHandle, + CssmPlugin &plug, + const CSSM_VERSION &version, + uint32 subserviceId, + CSSM_SERVICE_TYPE subserviceType, + CSSM_ATTACH_FLAGS attachFlags, + const CSSM_UPCALLS &upcalls) + : PluginSession(theHandle, plug, version, subserviceId, subserviceType, attachFlags, upcalls) { } + +protected: + CSSM_MODULE_FUNCS_PTR construct(); +}; + +} // end namespace Security + + +#endif //_H_TPSESSION diff --git a/libsecurity_cdsa_plugin/lib/c++plugin.h b/libsecurity_cdsa_plugin/lib/c++plugin.h new file mode 100644 index 00000000..d272895c --- /dev/null +++ b/libsecurity_cdsa_plugin/lib/c++plugin.h @@ -0,0 +1,42 @@ +/* + * 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. + */ + + +// +// spilayer - "roof" interface layer for CDSA SPI plugins +// +#ifndef _H_SPILAYER +#define _H_SPILAYER + +#include +#include +#include +#include + + +namespace Security +{ + +// +// Forward/common - separate file (which?) @@@ +// +class CssmPlugin; +class PluginSession; + +} // end namespace Security + +#endif //_H_SPILAYER diff --git a/libsecurity_cdsa_plugin/lib/csputilities.cpp b/libsecurity_cdsa_plugin/lib/csputilities.cpp new file mode 100644 index 00000000..467cdd5f --- /dev/null +++ b/libsecurity_cdsa_plugin/lib/csputilities.cpp @@ -0,0 +1,152 @@ +/* + * 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. + */ + + +// +// csputilities - utility classes for CSP implementation +// +#include +#include +#include +#include + +using LowLevelMemoryUtilities::increment; + + +// +// Writer objects +// +CSPFullPluginSession::Writer::Writer(CssmData *v, uint32 n, CssmData *rem) +: vec(v), firstVec(v), lastVec(v + n - 1), remData(rem) +{ + if (vec == NULL || n == 0) + CssmError::throwMe(CSSMERR_CSP_INVALID_OUTPUT_VECTOR); // CDSA p.253, amended + useData(vec); + written = 0; +} + +void CSPFullPluginSession::Writer::allocate(size_t needed, Allocator &alloc) +{ + if (!needed) + return; // No output buffer space needed so we're done. + else if (vec == firstVec && !*vec) { // initial null vector element, wants allocation there + *vec = makeBuffer(needed, alloc); + lastVec = vec; // ignore all subsequent buffers in vector + useData(vec); + } else { + // how much output space do we have left? + size_t size = currentSize; + for (CssmData *v = vec + 1; v <= lastVec; v++) + size += v->length(); + if (size >= needed) + return; // we're fine + if (remData) { + if (!*remData) { // have overflow, can allocate + *remData = makeBuffer(needed - size, alloc); + return; // got it + } + if (size + remData->length() >= needed) + return; // will fit into overflow + } + // not enough buffer space, and can't allocate + CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR); + } +} + +void CSPFullPluginSession::Writer::nextBlock(void * &ptr, size_t &size) +{ + ptr = currentBuffer; + size = currentSize; +} + +void CSPFullPluginSession::Writer::use(size_t used) +{ + assert(used <= currentSize); + written += used; + if (used < currentSize) { + currentBuffer = increment(currentBuffer, used); + currentSize -= used; + } else { + if (vec < lastVec) { + useData(vec++); // use next vector buffer + } else if (vec == lastVec && remData) { + useData(remData); // use remainder buffer + vec++; // mark used +#if !defined(NDEBUG) && 0 + } else if (vec == lastVec) { + vec++; + } else if (vec > lastVec) { + assert(false); // 2nd try to overflow end +#endif /* !NDEBUG */ + } else { + currentBuffer = NULL; // no more output buffer + currentSize = 0; + } + } +} + +void CSPFullPluginSession::Writer::put(void *addr, size_t size) +{ + while (size > 0) { + void *p; size_t sz; + nextBlock(p, sz); + if (size < sz) + sz = size; // cap transfer + memcpy(p, addr, sz); + use(sz); + addr = increment(addr, sz); + size -= sz; + } +} + +size_t CSPFullPluginSession::Writer::close() +{ + return written; +} + + +// +// Common algorithm utilities +// +void CSPFullPluginSession::setKey(CssmKey &key, + const Context &context, CSSM_KEYCLASS keyClass, + CSSM_KEYATTR_FLAGS attrs, CSSM_KEYUSE use) +{ + // general setup + memset(&key.KeyHeader, 0, sizeof(key.KeyHeader)); + key.KeyHeader.HeaderVersion = CSSM_KEYHEADER_VERSION; + key.KeyHeader.CspId = plugin.myGuid(); + key.KeyHeader.AlgorithmId = context.algorithm(); + key.KeyHeader.KeyClass = keyClass; + key.KeyHeader.KeyUsage = use; + key.KeyHeader.KeyAttr = attrs; + + CssmDate *theDate = context.get(CSSM_ATTRIBUTE_START_DATE); + if(theDate) { + key.KeyHeader.StartDate = *theDate; + } + theDate = context.get(CSSM_ATTRIBUTE_END_DATE); + if(theDate) { + key.KeyHeader.EndDate = *theDate; + } + + // defaults (change as needed) + key.KeyHeader.WrapAlgorithmId = CSSM_ALGID_NONE; + + // clear key data (standard says, "Always allocate this, ignore prior contents.") + key = CssmData(); +} diff --git a/libsecurity_cdsa_plugin/lib/cssmplugin.cpp b/libsecurity_cdsa_plugin/lib/cssmplugin.cpp new file mode 100644 index 00000000..36597e7e --- /dev/null +++ b/libsecurity_cdsa_plugin/lib/cssmplugin.cpp @@ -0,0 +1,184 @@ +/* + * 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. + */ + + +// +// cssmplugin - adapter framework for C++-based CDSA plugin modules +// +// A note on locking: Attachments are effectively reference counted in CSSM. +// CSSM will not let a client detach an attachment that has a(nother) thread +// active in its code. Thus, our locks merely protect global maps; they do not +// need (or try) to close the classic use-and-delete window. +// +#include +#include +#include + + +ModuleNexus CssmPlugin::sessionMap; + + +CssmPlugin::CssmPlugin() + : mLoaded(false) +{ +} + +CssmPlugin::~CssmPlugin() +{ + // Note: if mLoaded, we're being unloaded forcibly. + // (CSSM wouldn't do this to us in normal operation.) +} + + +// +// Load processing. +// CSSM only calls this once for a module, and multiplexes any additional +// CSSM_ModuleLoad calls internally. So this is only called when we have just +// been loaded (and not yet attached). +// +void CssmPlugin::moduleLoad(const Guid &cssmGuid, + const Guid &moduleGuid, + const ModuleCallback &newCallback) +{ + if (mLoaded) + CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR); + + mMyGuid = moduleGuid; + + // let the implementation know that we're loading + this->load(); + + // commit + mCallback = newCallback; + mLoaded = true; +} + + +// +// Unload processing. +// The callback passed here will be the same passed to load. +// CSSM only calls this on a "final" CSSM_ModuleUnload, after all attachments +// are destroyed and (just) before we are physically unloaded. +// +void CssmPlugin::moduleUnload(const Guid &cssmGuid, + const Guid &moduleGuid, + const ModuleCallback &oldCallback) +{ + // check the callback vector + if (!mLoaded || oldCallback != mCallback) + CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR); + + // tell our subclass that we're closing down + this->unload(); + + // commit closure + mLoaded = false; +} + + +// +// Create one attachment session. This is what CSSM calls to process +// a CSSM_ModuleAttach call. moduleLoad() has already been called and has +// returned successfully. +// +void CssmPlugin::moduleAttach(CSSM_MODULE_HANDLE theHandle, + const Guid &newCssmGuid, + const Guid &moduleGuid, + const Guid &moduleManagerGuid, + const Guid &callerGuid, + const CSSM_VERSION &version, + uint32 subserviceId, + CSSM_SERVICE_TYPE subserviceType, + CSSM_ATTACH_FLAGS attachFlags, + CSSM_KEY_HIERARCHY keyHierarchy, + const CSSM_UPCALLS &upcalls, + CSSM_MODULE_FUNCS_PTR &funcTbl) +{ + // basic (in)sanity checks + if (moduleGuid != mMyGuid) + CssmError::throwMe(CSSM_ERRCODE_INVALID_GUID); + + // make the new session object, hanging in thin air + auto_ptr session(this->makeSession(theHandle, + version, + subserviceId, subserviceType, + attachFlags, + upcalls)); + + // haggle with the implementor + funcTbl = session->construct(); + + // commit this session creation + StLock _(sessionMap()); + sessionMap()[theHandle] = session.release(); +} + + +// +// Undo a (single) module attachment. This calls the detach() method on +// the Session object representing the attachment. This is only called +// if session->construct() has succeeded previously. +// If session->detach() fails, we do not destroy the session and it continues +// to live, though its handle may have (briefly) been invalid. This is for +// desperate "mustn't go right now" situations and should not be abused. +// CSSM always has the ability to ditch you without your consent if you are +// obstreporous. +// +void CssmPlugin::moduleDetach(CSSM_MODULE_HANDLE handle) +{ + // locate the plugin and hold the sessionMapLock + PluginSession *session; + { + StLock _(sessionMap()); + SessionMap::iterator it = sessionMap().find(handle); + if (it == sessionMap().end()) + CssmError::throwMe(CSSMERR_CSSM_INVALID_ADDIN_HANDLE); + session = it->second; + sessionMap().erase(it); + } + + // let the session know it is going away + try { + session->detach(); + delete session; + } catch (...) { + // session detach failed - put the plugin back and fail + StLock _(sessionMap()); + sessionMap()[handle] = session; + throw; + } +} + + +// +// Send an official CSSM module callback message upstream +// +void CssmPlugin::sendCallback(CSSM_MODULE_EVENT event, uint32 ssid, + CSSM_SERVICE_TYPE serviceType) const +{ + assert(mLoaded); + mCallback(event, mMyGuid, ssid, serviceType); +} + + +// +// Default subclass hooks. +// The default implementations succeed without doing anything. +// +void CssmPlugin::load() { } + +void CssmPlugin::unload() { } diff --git a/libsecurity_cdsa_plugin/lib/cssmplugin.h b/libsecurity_cdsa_plugin/lib/cssmplugin.h new file mode 100644 index 00000000..294a3a8a --- /dev/null +++ b/libsecurity_cdsa_plugin/lib/cssmplugin.h @@ -0,0 +1,132 @@ +/* + * 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. + */ + + +// +// cssmplugin - common header for CSSM plugin modules +// +#ifndef _H_CSSMPLUGIN +#define _H_CSSMPLUGIN + +#include +#include +#include +#include + +#include +using __gnu_cxx::hash_map; + + +namespace Security { + + +// +// Inherit from this (abstract) class to implement your plugin +// +class CssmPlugin { + NOCOPY(CssmPlugin) +public: + CssmPlugin(); + virtual ~CssmPlugin(); + + void moduleLoad(const Guid &cssmGuid, + const Guid &moduleGuid, + const ModuleCallback &callback); + void moduleUnload(const Guid &cssmGuid, + const Guid &moduleGuid, + const ModuleCallback &callback); + + void moduleAttach(CSSM_MODULE_HANDLE theHandle, + const Guid &cssmGuid, + const Guid &moduleGuid, + const Guid &moduleManagerGuid, + const Guid &callerGuid, + const CSSM_VERSION &Version, + uint32 SubserviceID, + CSSM_SERVICE_TYPE SubServiceType, + CSSM_ATTACH_FLAGS AttachFlags, + CSSM_KEY_HIERARCHY KeyHierarchy, + const CSSM_UPCALLS &Upcalls, + CSSM_MODULE_FUNCS_PTR &FuncTbl); + void moduleDetach(CSSM_MODULE_HANDLE handle); + + const Guid &myGuid() const { return mMyGuid; } + + void sendCallback(CSSM_MODULE_EVENT event, + uint32 ssid, + CSSM_SERVICE_TYPE serviceType) const; + + void sendInsertion(uint32 subId, CSSM_SERVICE_TYPE serviceType) const + { sendCallback(CSSM_NOTIFY_INSERT, subId, serviceType); } + + void sendRemoval(uint32 subId, CSSM_SERVICE_TYPE serviceType) const + { sendCallback(CSSM_NOTIFY_REMOVE, subId, serviceType); } + + void sendFault(uint32 subId, CSSM_SERVICE_TYPE serviceType) const + { sendCallback(CSSM_NOTIFY_FAULT, subId, serviceType); } + +protected: + // subclass-defined methods + virtual void load(); + virtual void unload(); + + // make a session object for your plugin + virtual PluginSession *makeSession(CSSM_MODULE_HANDLE handle, + const CSSM_VERSION &version, + uint32 subserviceId, + CSSM_SERVICE_TYPE subserviceType, + CSSM_ATTACH_FLAGS attachFlags, + const CSSM_UPCALLS &upcalls) = 0; + +private: + // map of (CSSM) handles to attachment objects + struct SessionMap : + public hash_map, + public Mutex { }; + + static ModuleNexus sessionMap; + + Guid mMyGuid; + + // the registered callback. Set during load processing, unset during unload + ModuleCallback mCallback; + bool mLoaded; + +public: + static PluginSession *find(CSSM_MODULE_HANDLE h) + { + StLock _(sessionMap()); + SessionMap::iterator it = sessionMap().find(h); + if (it == sessionMap().end()) + CssmError::throwMe(CSSMERR_CSSM_INVALID_ADDIN_HANDLE); + return it->second; + } +}; + +template +inline SessionClass &findSession(CSSM_MODULE_HANDLE h) +{ + SessionClass *session = dynamic_cast(CssmPlugin::find(h)); + if (session == NULL) + CssmError::throwMe(CSSMERR_CSSM_INVALID_ADDIN_HANDLE); + assert(session->handle() == h); + return *session; +} + +} // end namespace Security + +#endif //_H_CSSMPLUGIN diff --git a/libsecurity_cdsa_plugin/lib/generator.cfg b/libsecurity_cdsa_plugin/lib/generator.cfg new file mode 100644 index 00000000..6a585002 --- /dev/null +++ b/libsecurity_cdsa_plugin/lib/generator.cfg @@ -0,0 +1,59 @@ +# +# transition.cfg +# +# Configuration file for generating the CSSM plugin framework transition layer. +# + + +# +# Specify optional arguments +# + +# CSP +optional CSP:Login LoginName +optional CSP:GetLoginAcl SelectionTag +optional CSP:GetKeyAcl SelectionTag +optional DL:GetDbAcl SelectionTag +optional CSP:GenerateKey KeyLabel CredAndAclEntry +optional CSP:GenerateKeyPair PrivateKeyLabel PublicKeyLabel CredAndAclEntry +optional CSP:WrapKey DescriptiveData +optional CSP:UnwrapKey PublicKey KeyLabel CredAndAclEntry +optional CSP:DeriveKey KeyLabel CredAndAclEntry +optional CSP:FreeKey AccessCred +optional CSP:QuerySize DataBlock +optional CSP:QueryKeySizeInBits Context Key + +# CL/TP +optional TP:SubmitCredRequest PreferredAuthority CallerAuthContext +optional TP:RetrieveCredResult CallerAuthCredentials +optional TP:ConfirmCredResult CallerAuthCredentials PreferredAuthority +optional TP:CertReclaimKey CredAndAclEntry +optional TP:FormRequest PreferredAuthority +optional TP:FormSubmit ClearanceAuthority RepresentedAuthority Credentials +optional TP:CertGroupVerify VerifyContext VerifyContextResult +optional TP:CertSign SignerVerifyContext SignerVerifyResult +optional TP:CrlVerify VerifyContext RevokerVerifyResult +optional TP:CertRevoke OldCrlTemplate +optional TP:CertRemoveFromCrlTemplate OldCrlTemplate +optional TP:CrlSign SignerVerifyContext SignerVerifyResult +optional TP:ApplyCrlToDb ApplyCrlVerifyContext +optional TP:PassThrough DBList +optional AC:AuthCompute Credentials RequestedAuthorizationPeriod +optional CL:CertSign SignScope +optional CL:CertVerify SignerCert VerifyScope +optional CL:CertGroupToSignedBundle SignerCert BundleInfo +optional CL:CertGroupFromVerifiedBundle SignerCert +optional CL:CrlSign SignScope +optional CL:CrlVerify SignerCert VerifyScope +optional CL:CrlGetFirstCachedFieldValue CrlRecordIndex + +# DL +optional DL:DbOpen DbLocation AccessCred +optional DL:DbCreate DbLocation CredAndAclEntry +optional DL:DbDelete DbLocation AccessCred +optional DL:DataInsert Attributes Data +optional DL:DataModify AttributesToBeModified DataToBeModified +optional DL:DataGetFirst Query Attributes Data +optional DL:DataGetNext Query Attributes Data +optional DL:DataGetFromUniqueRecordId Attributes Data +optional DL:CreateRelation pAttributeInfo diff --git a/libsecurity_cdsa_plugin/lib/generator.mk b/libsecurity_cdsa_plugin/lib/generator.mk new file mode 100644 index 00000000..0451e8c4 --- /dev/null +++ b/libsecurity_cdsa_plugin/lib/generator.mk @@ -0,0 +1,29 @@ +# Makefile for generated files. + +SOURCES = $(BUILT_PRODUCTS_DIR)/derived_src/security_cdsa_plugin +HEADERS = $(SOURCES) + +HFILES = $(HEADERS)/ACabstractsession.h +CPPFILES = $(SOURCES)/ACabstractsession.cpp + +build: $(HFILES) $(CPPFILES) + +install: build + +installhdrs: $(HFILES) + +installsrc: + +clean: + rm -f $(SPIGLUE_GEN) + +debug: build + +profile: build + +.PHONY: build clean debug profile + +# partial dependencies only +$(HFILES) $(CPPFILES) : $(PROJECT_DIR)/lib/generator.pl $(PROJECT_DIR)/lib/generator.cfg + mkdir -p $(SOURCES) + perl $(PROJECT_DIR)/lib/generator.pl $(CSSM_HEADERS) $(PROJECT_DIR)/lib/generator.cfg $(HEADERS) $(SOURCES) diff --git a/libsecurity_cdsa_plugin/lib/generator.pl b/libsecurity_cdsa_plugin/lib/generator.pl new file mode 100644 index 00000000..585186b0 --- /dev/null +++ b/libsecurity_cdsa_plugin/lib/generator.pl @@ -0,0 +1,247 @@ +#!/usr/bin/perl +# +# generator.pl - auto-generate code for the CSSM plugin interfaces +# +# Usage: +# perl generator.pl input-directory h-output-dir c-output-dir +# +# Perry The Cynic, Fall 1999. +# +@API_H=("cssmapi.h"); +%SPI_H=("AC" => "cssmaci.h", "CSP" => "cssmcspi.h", "DL" => "cssmdli.h", + "CL" => "cssmcli.h", "TP" => "cssmtpi.h"); + +$SOURCEPATH=$ARGV[0]; # where all the input files are +$APICFG=$ARGV[1]; # configuration file +$HTARGETDIR=$ARGV[2]; # where the generated headers go +$CTARGETDIR=$ARGV[3]; # where the generated sources go + + +$tabs = "\t\t\t"; # argument indentation (noncritical) +$warning = "This file was automatically generated. Do not edit on penalty of futility!"; + + +# +# Open and read the configuration file +# +$/=undef; # gulp file +open(APICFG, $APICFG) or die "Cannot open $APICFG: $^E"; +$_=; +close(APICFG); +%optionals = /^\s*optional\s+(\w+:\w+)\s+(.*)$/gm; + + +# +# Pre-arranged arrays for processing below +# +%noDataReturnError = ( CL => "CSSMERR_CL_NO_FIELD_VALUES", + DL => "CSSMERR_DL_ENDOFDATA" ); + + +# +# process one SPI at a time +# +while (($type, $header) = each %SPI_H) { + my(%functions, %methods, %actuals); + ($typelower = $type) =~ tr/A-Z/a-z/; # lowercase version of type + + # start in on the $type header file + for my $sourcedir (split (/:/, $SOURCEPATH)) { + open(SPI, "$sourcedir/$header") and last; + } + SPI or die "cannot find $header in $SOURCEPATH: $^E"; + $/=undef; # big gulp mode + $_ = ; # aaaaah... + close(SPI); # done + # throw away leading and trailing crud (only interested in SPI structure) + s/^.*struct cssm_spi.*{(.*)} CSSM_SPI.*$/$1/s + or die "bad format in $SPI_H{$name}"; + + # break up into functions (you'd do that HOW in YOUR language? :-) + @functions = /CSSM_RETURN \(CSSM${type}I \*([A-Za-z_]+)\)\s+\(([^)]+)\);/g; + %functions = @functions; + + $MOREHEADERS=""; + $MOREHEADERS .= "#include \n" if /CSSM_CONTEXT/; + $MOREHEADERS .= "#include \n" if /CSSM_(ACL|ACCESS)/; + $MOREHEADERS .= "#include \n" if /CSSM_QUERY/; + + # break function arguments into many forms: + # functions => formal SPI arguments + # methods => formal C++ method arguments + # actuals => actual expression forms for transition layer use + # and (by the way) massage them into a more palatable form... + $nFunctions = 0; + while (($function, $_) = each %functions) { + # + # Turn CSSM SPI formal into method formal + # + $returntype{$function} = "void"; + $prefix{$function} = ""; + $postfix{$function} = ";"; + # reshape initial argument (the module handle, more or less) + s/^CSSM_${type}_HANDLE ${type}Handle(,\s*\n\s*|$)//s; # remove own handle (-> this) + s/^CSSM_DL_DB_HANDLE DLDBHandle/CSSM_DB_HANDLE DBHandle/s; # DL_DB handle -> DB handle + s/CSSM_HANDLE_PTR ResultsHandle(,?)\n//m # turn ptr-to-resultshandle into fn result + and do { + $returntype{$function} = "CSSM_HANDLE"; + $prefix{$function} = "if ((Required(ResultsHandle) = "; + $postfix{$function} = ") == CSSM_INVALID_HANDLE)\n return $noDataReturnError{$type};"; + }; + if ($function =~ /GetNext/) { # *GetNext* returns a bool + $returntype{$function} = "bool"; + $prefix{$function} = "if (!"; + $postfix{$function} = ")\n return $noDataReturnError{$type};"; + } + # reshape subsequent arguments + s/([su]int32) \*(\w+,?)/$1 \&$2/gm; # int * -> int & (output integer) + s/(CSSM_\w+_PTR) \*(\w+,?)/$1 \&$2/gm; # _PTR * -> _PTR & + s/(CSSM_\w+)_PTR (\w+)/$1 \*$2/gm; # XYZ_PTR -> XYZ * (explicit) + s/(const )?CSSM_DATA \*(\w+)Bufs/$1CssmData $2Bufs\[\]/gm; # c DATA *Bufs (plural) + s/(const )?CSSM_(DATA|OID) \*/$1CssmData \&/gm; # c DATA * -> c Data & + s/(const )?CSSM_FIELD \*(\w+)Fields/$1CSSM_FIELD $2Fields\[\]/gm; # c FIELD *Fields (plural) + s/(const )?CSSM_FIELD \*CrlTemplate/$1CSSM_FIELD CrlTemplate\[\]/gm; # c FIELD *CrlTemplate + s/const CSSM_CONTEXT \*/const Context \&/gm; # c CSSM_CONTEXT * -> c Context & + s/(const )?CSSM_ACCESS_CREDENTIALS \*/$1AccessCredentials \&/gm; # ditto + s/(const )?CSSM_QUERY_SIZE_DATA \*/$1QuerySizeData \&/gm; # ditto + s/(const )?CSSM_CSP_OPERATIONAL_STATISTICS \*/$1CSPOperationalStatistics \&/gm; # ditto + s/(const )?CSSM_(WRAP_)?KEY \*/$1CssmKey \&/gm; # CSSM[WRAP]KEY * -> CssmKey & + s/const CSSM_QUERY \*/const CssmQuery \&/gm; # c QUERY * -> c Query & + s/(const )?(CSSM_[A-Z_]+) \*/$1$2 \&/gm; # c CSSM_ANY * -> c CSSM_ANY & + $methods{$function} = $_; + + # + # Now turn the method formal into the transition invocation actuals + # + s/^CSSM_DB_HANDLE \w+(,?)/DLDBHandle.DBHandle$1/s; # matching change to DL_DB handles + s/(const )?([A-Z][a-z]\w+) &(\w+)(,?)/$2::required($3)$4/gm; # BIG_ * -> Small_ & + s/(const )?CssmData (\w+)Bufs\[\](,?)/\&\&CssmData::required($2Bufs)$3/gm; # c DATA *DataBufs + s/(const )?CSSM_FIELD (\w+)Fields\[\](,?)/$2Fields$3/gm; # c CSSM_FIELD *Fields + s/(const )?CSSM_FIELD CrlTemplate\[\](,?)/CrlTemplate$2/gm; # c CSSM_FIELD *CrlTemplate + # now remove formal arguments and clean up + s/^.* \&\&(\w+,?)/$tabs\&$1/gm; # && escape (to keep real &) + s/^.* \&(\w+)(,?)/${tabs}Required($1)$2/gm; # dereference for ref transition + s/^.* \**(\w+,?)/$tabs$1/gm; # otherwise, plain actual argument + s/^$tabs//; + $actuals{$function} = $_; + + # + # Fix optional arguments + # + foreach $opt (split " ", $optionals{"$type:$function"}) { + $methods{$function} =~ s/\&$opt\b/\*$opt/; # turn refs back into pointers + $actuals{$function} =~ s/::required\($opt\)/::optional($opt)/; # optional specific + $actuals{$function} =~ s/Required\($opt\)/$opt/; # optional generic + }; + $nFunctions++; + }; + + # + # Prepare to write header and source files + # + open(H, ">$HTARGETDIR/${type}abstractsession.h") or die "cannot write ${type}abstractsession.h: $^E"; + open(C, ">$CTARGETDIR/${type}abstractsession.cpp") or die "cannot write ${type}abstractsession.cpp: $^E"; + + # + # Create header file + # + print H < +#include +$MOREHEADERS + +namespace Security { + + +// +// A pure abstract class to define the ${type} module interface +// +class ${type}AbstractPluginSession { +public: + virtual ~${type}AbstractPluginSession(); +HDRHEAD + + $functionCount = 0; + while (($function, $arglist) = each %methods) { + # generate method declaration + print H " virtual $returntype{$function} $function($arglist) = 0;\n"; + $functionCount++; + }; + print H < +#include +#include +#include + + +${type}AbstractPluginSession::~${type}AbstractPluginSession() +{ /* virtual */ } + +BODY + + # write transition layer functions + while (($function, $arglist) = each %functions) { + $lookupHandle = "${type}Handle"; + $lookupHandle = "DLDBHandle.DLHandle" if $arglist =~ /DL_DB_HANDLE/; + print C <($lookupHandle).$function($actuals{$function})${postfix{$function}} + END_API($type) +} + +SHIM + }; + + # generate dispatch table - in the right order, please + print C "\nstatic const CSSM_SPI_${type}_FUNCS ${type}FunctionStruct = {\n"; + while ($function = shift @functions) { + print C " cssm_$function,\n"; + shift @functions; # skip over arglist part + }; + print C "};\n\n"; + + print C < +#include +#include + + +// +// Construct a PluginSession +// +PluginSession::PluginSession(CSSM_MODULE_HANDLE theHandle, + CssmPlugin &myPlugin, + const CSSM_VERSION &version, + uint32 subserviceId, + CSSM_SERVICE_TYPE subserviceType, + CSSM_ATTACH_FLAGS attachFlags, + const CSSM_UPCALLS &inUpcalls) + : HandledObject(theHandle), plugin(myPlugin), + mVersion(version), mSubserviceId(subserviceId), + mSubserviceType(subserviceType), mAttachFlags(attachFlags), + upcalls(inUpcalls) +{ +} + + +// +// Destruction +// +PluginSession::~PluginSession() +{ +} + + +// +// The default implementation of detach() does nothing +// +void PluginSession::detach() +{ +} + + +// +// Allocation management +// +void *PluginSession::malloc(size_t size) throw(std::bad_alloc) +{ + if (void *addr = upcalls.malloc_func(handle(), size)) + return addr; + throw std::bad_alloc(); +} + +void *PluginSession::realloc(void *oldAddr, size_t size) throw(std::bad_alloc) +{ + if (void *addr = upcalls.realloc_func(handle(), oldAddr, size)) + return addr; + throw std::bad_alloc(); +} + + +// +// Dispatch callback events through the plugin object. +// Subsystem ID and subservice type default to our own. +// + +void PluginSession::sendCallback(CSSM_MODULE_EVENT event, + uint32 ssid, + CSSM_SERVICE_TYPE serviceType) const +{ + plugin.sendCallback(event, + (ssid == uint32(-1)) ? mSubserviceId : ssid, + serviceType ? serviceType : mSubserviceType); +} diff --git a/libsecurity_cdsa_plugin/lib/pluginsession.h b/libsecurity_cdsa_plugin/lib/pluginsession.h new file mode 100644 index 00000000..c747fe23 --- /dev/null +++ b/libsecurity_cdsa_plugin/lib/pluginsession.h @@ -0,0 +1,92 @@ +/* + * 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. + */ + + +// +// pluginsession - an attachment session for a CSSM plugin +// +#ifndef _H_PLUGINSESSION +#define _H_PLUGINSESSION + +#include +#include +#include + + +namespace Security { + + +// +// A PluginSession object describes an ongoing connection between a particular +// CSSM client and our plugin. Every time CSSM_SPI_ModuleAttach is called +// (due to the client calling CSSM_ModuleAttach), a new PluginSession object +// is created as a result. Sessions and CSSM_MODULE_HANDLES correspond one-to-one. +// Note that CSSM makes up our module handle; we just record it. +// +// A PluginSession *is* an Allocator, whose implementation is to call the +// "application allocator" functions provided by CSSM's caller for the attachment. +// Use the session object as the Allocator for anything you return to your caller. +// +class PluginSession : public Allocator, public HandledObject { + NOCOPY(PluginSession) + friend class CssmPlugin; +public: + PluginSession(CSSM_MODULE_HANDLE theHandle, + CssmPlugin &myPlugin, + const CSSM_VERSION &Version, + uint32 SubserviceID, + CSSM_SERVICE_TYPE SubServiceType, + CSSM_ATTACH_FLAGS AttachFlags, + const CSSM_UPCALLS &upcalls); + virtual ~PluginSession(); + virtual void detach(); + + CssmPlugin &plugin; + + void sendCallback(CSSM_MODULE_EVENT event, + uint32 ssid = uint32(-1), + CSSM_SERVICE_TYPE serviceType = 0) const; + + static void unimplemented() { CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); } + +protected: + virtual CSSM_MODULE_FUNCS_PTR construct() = 0; + +public: + // implement Allocator + void *malloc(size_t size) throw(std::bad_alloc); + void *realloc(void *addr, size_t size) throw(std::bad_alloc); + void free(void *addr) throw() { upcalls.free_func(handle(), addr); } + + // about ourselves + const CSSM_VERSION &version() const { return mVersion; } + uint32 subserviceId() const { return mSubserviceId; } + CSSM_SERVICE_TYPE subserviceType() const { return mSubserviceType; } + CSSM_ATTACH_FLAGS attachFlags() const { return mAttachFlags; } + +private: + CSSM_VERSION mVersion; + uint32 mSubserviceId; + CSSM_SERVICE_TYPE mSubserviceType; + CSSM_ATTACH_FLAGS mAttachFlags; + const CSSM_UPCALLS &upcalls; +}; + +} // end namespace Security + + +#endif //_H_PLUGINSESSION diff --git a/libsecurity_cdsa_plugin/lib/pluginspi.h b/libsecurity_cdsa_plugin/lib/pluginspi.h new file mode 100644 index 00000000..b9845e71 --- /dev/null +++ b/libsecurity_cdsa_plugin/lib/pluginspi.h @@ -0,0 +1,99 @@ +/* + * 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. + */ + + +// +// pluginspi - "roof" level entry points into a CSSM plugin. +// +// This file is meant to be included into the top-level source file +// for a CSSM plugin written to the C++ alternate interface. +// It contains actual code that defines the four required entry points. +// +#include + + +// +// Provide some flexibility for the includer +// +#if !defined(SPIPREFIX) +# define SPIPREFIX extern "C" CSSMSPI +#endif + +#if !defined(SPINAME) +# define SPINAME(s) s +#endif + + +SPIPREFIX CSSM_RETURN SPINAME(CSSM_SPI_ModuleLoad) (const CSSM_GUID *CssmGuid, + const CSSM_GUID *ModuleGuid, + CSSM_SPI_ModuleEventHandler CssmNotifyCallback, + void *CssmNotifyCallbackCtx) +{ + BEGIN_API + plugin().moduleLoad(Guid::required(CssmGuid), + Guid::required(ModuleGuid), + ModuleCallback(CssmNotifyCallback, CssmNotifyCallbackCtx)); + END_API(CSSM) +} + +SPIPREFIX CSSM_RETURN SPINAME(CSSM_SPI_ModuleUnload) (const CSSM_GUID *CssmGuid, + const CSSM_GUID *ModuleGuid, + CSSM_SPI_ModuleEventHandler CssmNotifyCallback, + void *CssmNotifyCallbackCtx) +{ + BEGIN_API + plugin().moduleUnload(Guid::required(CssmGuid), + Guid::required(ModuleGuid), + ModuleCallback(CssmNotifyCallback, CssmNotifyCallbackCtx)); + END_API(CSSM) +} + +SPIPREFIX CSSM_RETURN SPINAME(CSSM_SPI_ModuleAttach) (const CSSM_GUID *ModuleGuid, + const CSSM_VERSION *Version, + uint32 SubserviceID, + CSSM_SERVICE_TYPE SubServiceType, + CSSM_ATTACH_FLAGS AttachFlags, + CSSM_MODULE_HANDLE ModuleHandle, + CSSM_KEY_HIERARCHY KeyHierarchy, + const CSSM_GUID *CssmGuid, + const CSSM_GUID *ModuleManagerGuid, + const CSSM_GUID *CallerGuid, + const CSSM_UPCALLS *Upcalls, + CSSM_MODULE_FUNCS_PTR *FuncTbl) +{ + BEGIN_API + plugin().moduleAttach(ModuleHandle, + Guid::required(CssmGuid), + Guid::required(ModuleGuid), + Guid::required(ModuleManagerGuid), + Guid::required(CallerGuid), + *Version, + SubserviceID, + SubServiceType, + AttachFlags, + KeyHierarchy, + Required(Upcalls), + Required(FuncTbl)); + END_API(CSSM) +} + +SPIPREFIX CSSM_RETURN SPINAME(CSSM_SPI_ModuleDetach) (CSSM_MODULE_HANDLE ModuleHandle) +{ + BEGIN_API + plugin().moduleDetach(ModuleHandle); + END_API(CSSM) +} diff --git a/libsecurity_cdsa_plugin/libsecurity_cdsa_plugin.xcodeproj/project.pbxproj b/libsecurity_cdsa_plugin/libsecurity_cdsa_plugin.xcodeproj/project.pbxproj new file mode 100644 index 00000000..77f74464 --- /dev/null +++ b/libsecurity_cdsa_plugin/libsecurity_cdsa_plugin.xcodeproj/project.pbxproj @@ -0,0 +1,450 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 182BB5DB1470664C000BF1F3 /* CSPabstractsession.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2196BDD053B6036005808D4 /* CSPabstractsession.cpp */; }; + 1865FC2C1472485800FD79DF /* ACsession.h in Headers */ = {isa = PBXBuildFile; fileRef = C2F8455E052CA23100F4D742 /* ACsession.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1865FC2D1472485800FD79DF /* c++plugin.h in Headers */ = {isa = PBXBuildFile; fileRef = C2F8455F052CA23100F4D742 /* c++plugin.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1865FC2E1472485800FD79DF /* CLsession.h in Headers */ = {isa = PBXBuildFile; fileRef = C2F84560052CA23100F4D742 /* CLsession.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1865FC2F1472485800FD79DF /* CSPsession.h in Headers */ = {isa = PBXBuildFile; fileRef = C2F84562052CA23100F4D742 /* CSPsession.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1865FC301472485800FD79DF /* cssmplugin.h in Headers */ = {isa = PBXBuildFile; fileRef = C2F84565052CA23100F4D742 /* cssmplugin.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1865FC311472485800FD79DF /* Database.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C34408C0534CC81005148B6 /* Database.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1865FC321472485800FD79DF /* DatabaseSession.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C34408E0534CC81005148B6 /* DatabaseSession.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1865FC331472485800FD79DF /* DbContext.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C3440900534CC82005148B6 /* DbContext.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1865FC341472485800FD79DF /* DLsession.h in Headers */ = {isa = PBXBuildFile; fileRef = C2F84567052CA23100F4D742 /* DLsession.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1865FC351472485800FD79DF /* pluginsession.h in Headers */ = {isa = PBXBuildFile; fileRef = C2F8456C052CA23100F4D742 /* pluginsession.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1865FC361472485800FD79DF /* pluginspi.h in Headers */ = {isa = PBXBuildFile; fileRef = C2F8456D052CA23100F4D742 /* pluginspi.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1865FC371472485800FD79DF /* TPsession.h in Headers */ = {isa = PBXBuildFile; fileRef = C2F8456E052CA23100F4D742 /* TPsession.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1865FC381472485800FD79DF /* ACabstractsession.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C52AC740540B25100536F78 /* ACabstractsession.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1865FC391472485800FD79DF /* CLabstractsession.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C52AC750540B25100536F78 /* CLabstractsession.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1865FC3A1472485800FD79DF /* CSPabstractsession.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C52AC760540B25100536F78 /* CSPabstractsession.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1865FC3B1472485800FD79DF /* DLabstractsession.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C52AC770540B25100536F78 /* DLabstractsession.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1865FC3C1472485800FD79DF /* TPabstractsession.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C52AC780540B25100536F78 /* TPabstractsession.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 4C3440910534CC82005148B6 /* Database.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C34408B0534CC81005148B6 /* Database.cpp */; }; + 4C3440930534CC82005148B6 /* DatabaseSession.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C34408D0534CC81005148B6 /* DatabaseSession.cpp */; }; + 4C3440950534CC82005148B6 /* DbContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C34408F0534CC82005148B6 /* DbContext.cpp */; }; + C2196BE0053B6036005808D4 /* ACabstractsession.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2196BDB053B6036005808D4 /* ACabstractsession.cpp */; }; + C2196BE1053B6036005808D4 /* CLabstractsession.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2196BDC053B6036005808D4 /* CLabstractsession.cpp */; }; + C2196BE3053B6036005808D4 /* DLabstractsession.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2196BDE053B6036005808D4 /* DLabstractsession.cpp */; }; + C2196BE4053B6036005808D4 /* TPabstractsession.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2196BDF053B6036005808D4 /* TPabstractsession.cpp */; }; + C2F84572052CA23100F4D742 /* CSPsession.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2F84561052CA23100F4D742 /* CSPsession.cpp */; }; + C2F84574052CA23100F4D742 /* csputilities.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2F84563052CA23100F4D742 /* csputilities.cpp */; }; + C2F84575052CA23100F4D742 /* cssmplugin.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2F84564052CA23100F4D742 /* cssmplugin.cpp */; }; + C2F84577052CA23100F4D742 /* DLsession.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2F84566052CA23100F4D742 /* DLsession.cpp */; }; + C2F84579052CA23100F4D742 /* pluginsession.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2F8456B052CA23100F4D742 /* pluginsession.cpp */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 182BB36B146F126A000BF1F3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 18446077146DF45600B12992 /* libsecurity_utilities.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = C2C9C69D0CECBE8400B3FE07; + remoteInfo = libsecurity_utilitiesDTrace; + }; + 18446071146DEEE300B12992 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4CA1FEAB052A3C3800F22E42 /* Project object */; + proxyType = 1; + remoteGlobalIDString = C2C38A530535EDE600D7421F; + remoteInfo = generate; + }; + 1844607C146DF45600B12992 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 18446077146DF45600B12992 /* libsecurity_utilities.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 4CA2A53A0523D32800978A7B; + remoteInfo = libsecurity_utilities; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 1844606D146DEE4400B12992 /* base.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = base.xcconfig; sourceTree = ""; }; + 1844606E146DEE4400B12992 /* debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = debug.xcconfig; sourceTree = ""; }; + 1844606F146DEE4400B12992 /* lib.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = lib.xcconfig; sourceTree = ""; }; + 18446070146DEE4400B12992 /* release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = release.xcconfig; sourceTree = ""; }; + 18446077146DF45600B12992 /* libsecurity_utilities.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libsecurity_utilities.xcodeproj; path = ../libsecurity_utilities/libsecurity_utilities.xcodeproj; sourceTree = ""; }; + 4C34408B0534CC81005148B6 /* Database.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = Database.cpp; sourceTree = ""; }; + 4C34408C0534CC81005148B6 /* Database.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Database.h; sourceTree = ""; }; + 4C34408D0534CC81005148B6 /* DatabaseSession.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = DatabaseSession.cpp; sourceTree = ""; }; + 4C34408E0534CC81005148B6 /* DatabaseSession.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DatabaseSession.h; sourceTree = ""; }; + 4C34408F0534CC82005148B6 /* DbContext.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = DbContext.cpp; sourceTree = ""; }; + 4C3440900534CC82005148B6 /* DbContext.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DbContext.h; sourceTree = ""; }; + 4C52AC740540B25100536F78 /* ACabstractsession.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = ACabstractsession.h; path = derived_src/security_cdsa_plugin/ACabstractsession.h; sourceTree = BUILT_PRODUCTS_DIR; }; + 4C52AC750540B25100536F78 /* CLabstractsession.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = CLabstractsession.h; path = derived_src/security_cdsa_plugin/CLabstractsession.h; sourceTree = BUILT_PRODUCTS_DIR; }; + 4C52AC760540B25100536F78 /* CSPabstractsession.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = CSPabstractsession.h; path = derived_src/security_cdsa_plugin/CSPabstractsession.h; sourceTree = BUILT_PRODUCTS_DIR; }; + 4C52AC770540B25100536F78 /* DLabstractsession.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = DLabstractsession.h; path = derived_src/security_cdsa_plugin/DLabstractsession.h; sourceTree = BUILT_PRODUCTS_DIR; }; + 4C52AC780540B25100536F78 /* TPabstractsession.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = TPabstractsession.h; path = derived_src/security_cdsa_plugin/TPabstractsession.h; sourceTree = BUILT_PRODUCTS_DIR; }; + 4CA1FEBE052A3C8100F22E42 /* libsecurity_cdsa_plugin.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libsecurity_cdsa_plugin.a; sourceTree = BUILT_PRODUCTS_DIR; }; + C2196BDB053B6036005808D4 /* ACabstractsession.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = ACabstractsession.cpp; path = derived_src/security_cdsa_plugin/ACabstractsession.cpp; sourceTree = BUILT_PRODUCTS_DIR; }; + C2196BDC053B6036005808D4 /* CLabstractsession.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = CLabstractsession.cpp; path = derived_src/security_cdsa_plugin/CLabstractsession.cpp; sourceTree = BUILT_PRODUCTS_DIR; }; + C2196BDD053B6036005808D4 /* CSPabstractsession.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = CSPabstractsession.cpp; path = derived_src/security_cdsa_plugin/CSPabstractsession.cpp; sourceTree = BUILT_PRODUCTS_DIR; }; + C2196BDE053B6036005808D4 /* DLabstractsession.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = DLabstractsession.cpp; path = derived_src/security_cdsa_plugin/DLabstractsession.cpp; sourceTree = BUILT_PRODUCTS_DIR; }; + C2196BDF053B6036005808D4 /* TPabstractsession.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = TPabstractsession.cpp; path = derived_src/security_cdsa_plugin/TPabstractsession.cpp; sourceTree = BUILT_PRODUCTS_DIR; }; + C2F8455E052CA23100F4D742 /* ACsession.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ACsession.h; sourceTree = ""; }; + C2F8455F052CA23100F4D742 /* c++plugin.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = "c++plugin.h"; sourceTree = ""; }; + C2F84560052CA23100F4D742 /* CLsession.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = CLsession.h; sourceTree = ""; }; + C2F84561052CA23100F4D742 /* CSPsession.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = CSPsession.cpp; sourceTree = ""; }; + C2F84562052CA23100F4D742 /* CSPsession.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = CSPsession.h; sourceTree = ""; }; + C2F84563052CA23100F4D742 /* csputilities.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = csputilities.cpp; sourceTree = ""; }; + C2F84564052CA23100F4D742 /* cssmplugin.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = cssmplugin.cpp; sourceTree = ""; }; + C2F84565052CA23100F4D742 /* cssmplugin.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cssmplugin.h; sourceTree = ""; }; + C2F84566052CA23100F4D742 /* DLsession.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = DLsession.cpp; sourceTree = ""; }; + C2F84567052CA23100F4D742 /* DLsession.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DLsession.h; sourceTree = ""; }; + C2F84568052CA23100F4D742 /* generator.cfg */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = generator.cfg; sourceTree = ""; }; + C2F84569052CA23100F4D742 /* generator.mk */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = generator.mk; sourceTree = ""; }; + C2F8456A052CA23100F4D742 /* generator.pl */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.script.perl; path = generator.pl; sourceTree = ""; }; + C2F8456B052CA23100F4D742 /* pluginsession.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = pluginsession.cpp; sourceTree = ""; }; + C2F8456C052CA23100F4D742 /* pluginsession.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = pluginsession.h; sourceTree = ""; }; + C2F8456D052CA23100F4D742 /* pluginspi.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = pluginspi.h; sourceTree = ""; }; + C2F8456E052CA23100F4D742 /* TPsession.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = TPsession.h; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 4CA1FEBB052A3C8100F22E42 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 1844606C146DEE4400B12992 /* config */ = { + isa = PBXGroup; + children = ( + 1844606D146DEE4400B12992 /* base.xcconfig */, + 1844606E146DEE4400B12992 /* debug.xcconfig */, + 1844606F146DEE4400B12992 /* lib.xcconfig */, + 18446070146DEE4400B12992 /* release.xcconfig */, + ); + name = config; + path = ../config; + sourceTree = ""; + }; + 18446078146DF45600B12992 /* Products */ = { + isa = PBXGroup; + children = ( + 1844607D146DF45600B12992 /* libsecurity_utilities.a */, + ); + name = Products; + sourceTree = ""; + }; + 4CA1FEA7052A3C3800F22E42 = { + isa = PBXGroup; + children = ( + 18446077146DF45600B12992 /* libsecurity_utilities.xcodeproj */, + C2F8455D052CA23100F4D742 /* lib */, + 1844606C146DEE4400B12992 /* config */, + C2196BD8053B5FFE005808D4 /* derived_src */, + 4CA1FEBF052A3C8100F22E42 /* Products */, + ); + sourceTree = ""; + }; + 4CA1FEBF052A3C8100F22E42 /* Products */ = { + isa = PBXGroup; + children = ( + 4CA1FEBE052A3C8100F22E42 /* libsecurity_cdsa_plugin.a */, + ); + name = Products; + sourceTree = ""; + }; + C2196BD8053B5FFE005808D4 /* derived_src */ = { + isa = PBXGroup; + children = ( + C2196BDB053B6036005808D4 /* ACabstractsession.cpp */, + C2196BDC053B6036005808D4 /* CLabstractsession.cpp */, + C2196BDD053B6036005808D4 /* CSPabstractsession.cpp */, + C2196BDE053B6036005808D4 /* DLabstractsession.cpp */, + C2196BDF053B6036005808D4 /* TPabstractsession.cpp */, + 4C52AC740540B25100536F78 /* ACabstractsession.h */, + 4C52AC750540B25100536F78 /* CLabstractsession.h */, + 4C52AC760540B25100536F78 /* CSPabstractsession.h */, + 4C52AC770540B25100536F78 /* DLabstractsession.h */, + 4C52AC780540B25100536F78 /* TPabstractsession.h */, + ); + path = derived_src; + sourceTree = BUILT_PRODUCTS_DIR; + }; + C2F8455D052CA23100F4D742 /* lib */ = { + isa = PBXGroup; + children = ( + C2F8455E052CA23100F4D742 /* ACsession.h */, + C2F8455F052CA23100F4D742 /* c++plugin.h */, + C2F84560052CA23100F4D742 /* CLsession.h */, + C2F84561052CA23100F4D742 /* CSPsession.cpp */, + C2F84562052CA23100F4D742 /* CSPsession.h */, + C2F84563052CA23100F4D742 /* csputilities.cpp */, + C2F84564052CA23100F4D742 /* cssmplugin.cpp */, + C2F84565052CA23100F4D742 /* cssmplugin.h */, + 4C34408B0534CC81005148B6 /* Database.cpp */, + 4C34408C0534CC81005148B6 /* Database.h */, + 4C34408D0534CC81005148B6 /* DatabaseSession.cpp */, + 4C34408E0534CC81005148B6 /* DatabaseSession.h */, + 4C34408F0534CC82005148B6 /* DbContext.cpp */, + 4C3440900534CC82005148B6 /* DbContext.h */, + C2F84566052CA23100F4D742 /* DLsession.cpp */, + C2F84567052CA23100F4D742 /* DLsession.h */, + C2F84568052CA23100F4D742 /* generator.cfg */, + C2F84569052CA23100F4D742 /* generator.mk */, + C2F8456A052CA23100F4D742 /* generator.pl */, + C2F8456B052CA23100F4D742 /* pluginsession.cpp */, + C2F8456C052CA23100F4D742 /* pluginsession.h */, + C2F8456D052CA23100F4D742 /* pluginspi.h */, + C2F8456E052CA23100F4D742 /* TPsession.h */, + ); + path = lib; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 4C22DE5A055340D40032D046 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 1865FC2C1472485800FD79DF /* ACsession.h in Headers */, + 1865FC2D1472485800FD79DF /* c++plugin.h in Headers */, + 1865FC2E1472485800FD79DF /* CLsession.h in Headers */, + 1865FC2F1472485800FD79DF /* CSPsession.h in Headers */, + 1865FC301472485800FD79DF /* cssmplugin.h in Headers */, + 1865FC311472485800FD79DF /* Database.h in Headers */, + 1865FC321472485800FD79DF /* DatabaseSession.h in Headers */, + 1865FC331472485800FD79DF /* DbContext.h in Headers */, + 1865FC341472485800FD79DF /* DLsession.h in Headers */, + 1865FC351472485800FD79DF /* pluginsession.h in Headers */, + 1865FC361472485800FD79DF /* pluginspi.h in Headers */, + 1865FC371472485800FD79DF /* TPsession.h in Headers */, + 1865FC381472485800FD79DF /* ACabstractsession.h in Headers */, + 1865FC391472485800FD79DF /* CLabstractsession.h in Headers */, + 1865FC3A1472485800FD79DF /* CSPabstractsession.h in Headers */, + 1865FC3B1472485800FD79DF /* DLabstractsession.h in Headers */, + 1865FC3C1472485800FD79DF /* TPabstractsession.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXLegacyTarget section */ + C2C38A530535EDE600D7421F /* libsecurity_cdsa_plugin_generate */ = { + isa = PBXLegacyTarget; + buildArgumentsString = "-f $(PROJECT_DIR)/lib/generator.mk $ACTION"; + buildConfigurationList = C27AD2DC0987FCDD001272E0 /* Build configuration list for PBXLegacyTarget "libsecurity_cdsa_plugin_generate" */; + buildPhases = ( + ); + buildToolPath = /usr/bin/gnumake; + buildWorkingDirectory = ""; + dependencies = ( + 182BB36C146F126A000BF1F3 /* PBXTargetDependency */, + ); + name = libsecurity_cdsa_plugin_generate; + passBuildSettingsInEnvironment = 1; + productName = Generate; + }; +/* End PBXLegacyTarget section */ + +/* Begin PBXNativeTarget section */ + 4CA1FEBD052A3C8100F22E42 /* libsecurity_cdsa_plugin */ = { + isa = PBXNativeTarget; + buildConfigurationList = C27AD2E40987FCDD001272E0 /* Build configuration list for PBXNativeTarget "libsecurity_cdsa_plugin" */; + buildPhases = ( + 4C22DE5A055340D40032D046 /* Headers */, + 4CA1FEBA052A3C8100F22E42 /* Sources */, + 4CA1FEBB052A3C8100F22E42 /* Frameworks */, + 18B96AFC14743E18005A4D2E /* ShellScript */, + ); + buildRules = ( + ); + dependencies = ( + 18446072146DEEE300B12992 /* PBXTargetDependency */, + ); + name = libsecurity_cdsa_plugin; + productName = libsecurity_cdsa_plugin; + productReference = 4CA1FEBE052A3C8100F22E42 /* libsecurity_cdsa_plugin.a */; + productType = "com.apple.product-type.library.static"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 4CA1FEAB052A3C3800F22E42 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0420; + }; + buildConfigurationList = C27AD2E80987FCDD001272E0 /* Build configuration list for PBXProject "libsecurity_cdsa_plugin" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 1; + knownRegions = ( + en, + ); + mainGroup = 4CA1FEA7052A3C3800F22E42; + productRefGroup = 4CA1FEBF052A3C8100F22E42 /* Products */; + projectDirPath = ""; + projectReferences = ( + { + ProductGroup = 18446078146DF45600B12992 /* Products */; + ProjectRef = 18446077146DF45600B12992 /* libsecurity_utilities.xcodeproj */; + }, + ); + projectRoot = ""; + targets = ( + 4CA1FEBD052A3C8100F22E42 /* libsecurity_cdsa_plugin */, + C2C38A530535EDE600D7421F /* libsecurity_cdsa_plugin_generate */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXReferenceProxy section */ + 1844607D146DF45600B12992 /* libsecurity_utilities.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libsecurity_utilities.a; + remoteRef = 1844607C146DF45600B12992 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; +/* End PBXReferenceProxy section */ + +/* Begin PBXShellScriptBuildPhase section */ + 18B96AFC14743E18005A4D2E /* 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 = ( + C2F84572052CA23100F4D742 /* CSPsession.cpp in Sources */, + C2F84574052CA23100F4D742 /* csputilities.cpp in Sources */, + C2F84575052CA23100F4D742 /* cssmplugin.cpp in Sources */, + 4C3440910534CC82005148B6 /* Database.cpp in Sources */, + 4C3440930534CC82005148B6 /* DatabaseSession.cpp in Sources */, + 4C3440950534CC82005148B6 /* DbContext.cpp in Sources */, + C2F84577052CA23100F4D742 /* DLsession.cpp in Sources */, + C2F84579052CA23100F4D742 /* pluginsession.cpp in Sources */, + C2196BE0053B6036005808D4 /* ACabstractsession.cpp in Sources */, + C2196BE1053B6036005808D4 /* CLabstractsession.cpp in Sources */, + 182BB5DB1470664C000BF1F3 /* CSPabstractsession.cpp in Sources */, + C2196BE3053B6036005808D4 /* DLabstractsession.cpp in Sources */, + C2196BE4053B6036005808D4 /* TPabstractsession.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 182BB36C146F126A000BF1F3 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = libsecurity_utilitiesDTrace; + targetProxy = 182BB36B146F126A000BF1F3 /* PBXContainerItemProxy */; + }; + 18446072146DEEE300B12992 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = C2C38A530535EDE600D7421F /* libsecurity_cdsa_plugin_generate */; + targetProxy = 18446071146DEEE300B12992 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + C27AD2DD0987FCDD001272E0 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CSSM_HEADERS = "$(PROJECT_DIR)/../libsecurity_cssm/lib"; + INSTALLHDRS_SCRIPT_PHASE = YES; + }; + name = Debug; + }; + C27AD2DF0987FCDD001272E0 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CSSM_HEADERS = "$(PROJECT_DIR)/../libsecurity_cssm/lib"; + INSTALLHDRS_SCRIPT_PHASE = YES; + }; + name = Release; + }; + C27AD2E50987FCDD001272E0 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1844606E146DEE4400B12992 /* debug.xcconfig */; + buildSettings = { + OTHER_CFLAGS = ""; + PUBLIC_HEADERS_FOLDER_PATH = /usr/local/include/security_cdsa_plugin; + SKIP_INSTALL = NO; + }; + name = Debug; + }; + C27AD2E70987FCDD001272E0 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 18446070146DEE4400B12992 /* release.xcconfig */; + buildSettings = { + OTHER_CFLAGS = ""; + PUBLIC_HEADERS_FOLDER_PATH = /usr/local/include/security_cdsa_plugin; + SKIP_INSTALL = NO; + }; + name = Release; + }; + C27AD2E90987FCDD001272E0 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1844606F146DEE4400B12992 /* lib.xcconfig */; + buildSettings = { + }; + name = Debug; + }; + C27AD2EB0987FCDD001272E0 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1844606F146DEE4400B12992 /* lib.xcconfig */; + buildSettings = { + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + C27AD2DC0987FCDD001272E0 /* Build configuration list for PBXLegacyTarget "libsecurity_cdsa_plugin_generate" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C27AD2DD0987FCDD001272E0 /* Debug */, + C27AD2DF0987FCDD001272E0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C27AD2E40987FCDD001272E0 /* Build configuration list for PBXNativeTarget "libsecurity_cdsa_plugin" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C27AD2E50987FCDD001272E0 /* Debug */, + C27AD2E70987FCDD001272E0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C27AD2E80987FCDD001272E0 /* Build configuration list for PBXProject "libsecurity_cdsa_plugin" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C27AD2E90987FCDD001272E0 /* Debug */, + C27AD2EB0987FCDD001272E0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 4CA1FEAB052A3C3800F22E42 /* Project object */; +} diff --git a/libsecurity_cdsa_utilities/APPLE_LICENSE b/libsecurity_cdsa_utilities/APPLE_LICENSE new file mode 100644 index 00000000..71fe6fd7 --- /dev/null +++ b/libsecurity_cdsa_utilities/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/libsecurity_cdsa_utilities/Info-security_cdsa_utilities.plist b/libsecurity_cdsa_utilities/Info-security_cdsa_utilities.plist new file mode 100644 index 00000000..0c67376e --- /dev/null +++ b/libsecurity_cdsa_utilities/Info-security_cdsa_utilities.plist @@ -0,0 +1,5 @@ + + + + + diff --git a/libsecurity_cdsa_utilities/lib/AuthorizationData.cpp b/libsecurity_cdsa_utilities/lib/AuthorizationData.cpp new file mode 100644 index 00000000..dc007fd6 --- /dev/null +++ b/libsecurity_cdsa_utilities/lib/AuthorizationData.cpp @@ -0,0 +1,362 @@ +/* + * Copyright (c) 2000-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 +#include +#include +#include +#include +#include + + +// checkpw() that uses provided struct passwd +extern "C" +{ +int checkpw_internal( const struct passwd *pw, const char* password ); +} + + +namespace Authorization { + + +AuthValueRef::AuthValueRef(const AuthValue &value) : + RefPointer(new AuthValue(value)) {} + +AuthValueRef::AuthValueRef(const AuthorizationValue &value) : + RefPointer(new AuthValue(value)) {} + +AuthValue::AuthValue(const AuthorizationValue &value) : + mOwnsValue(false) +{ + mValue.length = value.length; + mValue.data = value.data; +} + +AuthValueRef::AuthValueRef(UInt32 length, void *data) : + RefPointer(new AuthValue(length, data)) {} + +AuthValue::AuthValue(UInt32 length, void *data) : + mOwnsValue(true) +{ + mValue.length = length; + mValue.data = new uint8_t[length]; + if (length) + memcpy(mValue.data, data, length); +} + +AuthValue::~AuthValue() +{ + if (mOwnsValue) + { + memset(mValue.data, 0, mValue.length); + delete[] reinterpret_cast(mValue.data); + } +} + +AuthValue & +AuthValue::operator = (const AuthValue &other) +{ + if (mOwnsValue) + { + memset(mValue.data, 0 , mValue.length); + delete[] reinterpret_cast(mValue.data); + } + + mValue = other.mValue; + mOwnsValue = other.mOwnsValue; + other.mOwnsValue = false; + return *this; +} + +void +AuthValue::fillInAuthorizationValue(AuthorizationValue &value) +{ + value.length = mValue.length; + value.data = mValue.data; +} + +AuthValueVector & +AuthValueVector::operator = (const AuthorizationValueVector& valueVector) +{ + clear(); + for (unsigned int i=0; i < valueVector.count; i++) + push_back(AuthValueRef(valueVector.values[i])); + return *this; +} + +void +AuthValueVector::copy(AuthorizationValueVector **data, size_t *length) const +{ + AuthorizationValueVector valueVector; + valueVector.count = size(); + valueVector.values = new AuthorizationValue[valueVector.count]; + int i = 0; + for (const_iterator it = begin(); it != end(); ++it, ++i) + { + (*it)->fillInAuthorizationValue(valueVector.values[i]); + } + + DataWalkers::Copier flatValueVector(&valueVector); + *length = flatValueVector.length(); + *data = flatValueVector.keep(); + + delete[] valueVector.values; +} + +AuthItem::AuthItem(const AuthorizationItem &item) : + mFlags(item.flags), + mOwnsName(true), + mOwnsValue(true) +{ + if (!item.name) + MacOSError::throwMe(errAuthorizationInternal); + size_t nameLen = strlen(item.name) + 1; + mName = new char[nameLen]; + memcpy(const_cast(mName), item.name, nameLen); + + mValue.length = item.valueLength; + mValue.data = new uint8_t[item.valueLength]; + if (mValue.length) + memcpy(mValue.data, item.value, item.valueLength); +} + + +AuthItem::AuthItem(AuthorizationString name) : + mName(name), + mFlags(0), + mOwnsName(false), + mOwnsValue(false) +{ + mValue.length = 0; + mValue.data = NULL; +} + +AuthItem::AuthItem(AuthorizationString name, AuthorizationValue value, AuthorizationFlags flags) : + mFlags(flags), + mOwnsName(true), + mOwnsValue(true) +{ + if (!name) + MacOSError::throwMe(errAuthorizationInternal); + size_t nameLen = strlen(name) + 1; + mName = new char[nameLen]; + memcpy(const_cast(mName), name, nameLen); + + mValue.length = value.length; + mValue.data = new uint8_t[value.length]; + if (mValue.length) + memcpy(mValue.data, value.data, value.length); +} + +AuthItem::~AuthItem() +{ + if (mOwnsName) + delete[] mName; + if (mOwnsValue) + { + memset(mValue.data, 0, mValue.length); + delete[] reinterpret_cast(mValue.data); + } +} + +bool +AuthItem::operator < (const AuthItem &other) const +{ + return strcmp(mName, other.mName) < 0; +} + +AuthItem & +AuthItem::operator = (const AuthItem &other) +{ + if (mOwnsName) + delete[] mName; + if (mOwnsValue) + { + memset(mValue.data, 0, mValue.length); + delete[] reinterpret_cast(mValue.data); + } + + mName = other.mName; + mValue = other.mValue; + mFlags = other.mFlags; + mOwnsName = other.mOwnsName; + other.mOwnsName = false; + mOwnsValue = other.mOwnsValue; + other.mOwnsValue = false; + return *this; +} + +void +AuthItem::fillInAuthorizationItem(AuthorizationItem &item) +{ + item.name = mName; + item.valueLength = mValue.length; + item.value = mValue.data; + item.flags = mFlags; +} + +bool +AuthItem::getBool(bool &value) +{ + if (mValue.length == sizeof(bool)) + { + bool *tmpValue = (bool *)mValue.data; + + if (tmpValue) + { + value = *tmpValue; + return true; + } + } + + return false; +} + +bool +AuthItem::getString(string &value) +{ + value = string(static_cast(mValue.data), mValue.length); + return true; +} + +bool +AuthItem::getCssmData(CssmAutoData &value) +{ + value = CssmData(static_cast(mValue.data), mValue.length); + return true; +} + + +AuthItemRef::AuthItemRef(const AuthorizationItem &item) : RefPointer(new AuthItem(item)) {} + +AuthItemRef::AuthItemRef(AuthorizationString name) : RefPointer(new AuthItem(name)) {} + +AuthItemRef::AuthItemRef(AuthorizationString name, AuthorizationValue value, AuthorizationFlags flags) : RefPointer(new AuthItem(name, value, flags)) {} + + +// +// AuthItemSet +// +AuthItemSet::AuthItemSet() +: firstItemName(NULL) +{ +} + +AuthItemSet::~AuthItemSet() +{ + if (NULL != firstItemName) + free(firstItemName); +} + +AuthItemSet & +AuthItemSet::operator = (const AuthorizationItemSet& itemSet) +{ + clear(); + + for (unsigned int i=0; i < itemSet.count; i++) + insert(AuthItemRef(itemSet.items[i])); + + return *this; +} + +AuthItemSet& +AuthItemSet::operator=(const AuthItemSet& itemSet) +{ + std::set::operator=(itemSet); + + if (this != &itemSet) { + duplicate(itemSet); + } + + return *this; +} + +AuthItemSet::AuthItemSet(const AuthorizationItemSet *itemSet) +: firstItemName(NULL) +{ + if (NULL != itemSet && NULL != itemSet->items) + { + if (0 < itemSet->count && NULL != itemSet->items[0].name) + firstItemName = strdup(itemSet->items[0].name); + + for (unsigned int i=0; i < itemSet->count; i++) + insert(AuthItemRef(itemSet->items[i])); + } +} + +AuthItemSet::AuthItemSet(const AuthItemSet& itemSet) +: std::set(itemSet) +{ + duplicate(itemSet); +} + +void +AuthItemSet::duplicate(const AuthItemSet& itemSet) +{ + if (itemSet.firstItemName != NULL) + firstItemName = strdup(itemSet.firstItemName); + else + firstItemName = NULL; +} + +void +AuthItemSet::copy(AuthorizationItemSet *&data, size_t &length, Allocator &alloc) const +{ + AuthorizationItemSet itemSet; + itemSet.count = size(); + itemSet.items = new AuthorizationItem[itemSet.count]; + int i = 0; + for (const_iterator it = begin(); it != end(); ++it, ++i) + { + (*it)->fillInAuthorizationItem(itemSet.items[i]); + } + + DataWalkers::Copier flatItemSet(&itemSet, alloc); + length = flatItemSet.length(); + + data = flatItemSet.keep(); + // else flatItemSet disappears again + + delete[] itemSet.items; +} + +AuthorizationItemSet * +AuthItemSet::copy() const +{ + AuthorizationItemSet *aCopy; + size_t aLength; + copy(aCopy, aLength); + return aCopy; +} + +AuthItem * +AuthItemSet::find(const char *name) +{ + AuthItemSet::const_iterator found = find_if(this->begin(), this->end(), FindAuthItemByRightName(name) ); + if (found != this->end()) + return *found; + + return NULL; +} + +} // end namespace Authorization diff --git a/libsecurity_cdsa_utilities/lib/AuthorizationData.h b/libsecurity_cdsa_utilities/lib/AuthorizationData.h new file mode 100644 index 00000000..d841db28 --- /dev/null +++ b/libsecurity_cdsa_utilities/lib/AuthorizationData.h @@ -0,0 +1,201 @@ +/* + * Copyright (c) 2000,2002-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@ + */ + + +/* + * AuthorizationData.h + * Authorization + */ + +#ifndef _H_AUTHORIZATIONDATA +#define _H_AUTHORIZATIONDATA 1 + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +// ptrdiff_t needed, so including STL type closest +#include + +// @@@ Should consider making the various types better citizens by taking an Allocator, for now values are wiped. + +namespace Authorization +{ + +class AuthValueOverlay : public AuthorizationValue +{ +public: + AuthValueOverlay(const string& stringValue) { length = stringValue.length(); data = const_cast(stringValue.c_str()); } + AuthValueOverlay(UInt32 inLength, void *inData) { length = inLength; data = inData; } +}; + +class AuthValueRef; + +class AuthValue : public RefCount +{ + friend class AuthValueRef; +private: + AuthValue(const AuthValue& value) {} +protected: + AuthValue(const AuthorizationValue &value); + AuthValue(UInt32 length, void *data); +public: + AuthValue &operator = (const AuthValue &other); + ~AuthValue(); + void fillInAuthorizationValue(AuthorizationValue &value); + const AuthorizationValue& value() const { return mValue; } +private: + AuthorizationValue mValue; + mutable bool mOwnsValue; +}; + +// AuthValueRef impl +class AuthValueRef : public RefPointer +{ +public: + AuthValueRef(const AuthValue &value); + AuthValueRef(const AuthorizationValue &value); + AuthValueRef(UInt32 length, void *data); +}; + + +// vector should become a member with accessors +class AuthValueVector : public vector +{ +public: + AuthValueVector() {} + ~AuthValueVector() {} + + AuthValueVector &operator = (const AuthorizationValueVector& valueVector); + + void copy(AuthorizationValueVector **data, size_t *length) const; +}; + + + +class AuthItemRef; + +class AuthItem : public RefCount +{ + friend class AuthItemRef; +private: + AuthItem(const AuthItem& item); +protected: + AuthItem(const AuthorizationItem &item); + AuthItem(AuthorizationString name); + AuthItem(AuthorizationString name, AuthorizationValue value); + AuthItem(AuthorizationString name, AuthorizationValue value, AuthorizationFlags flags); + + bool operator < (const AuthItem &other) const; + +public: + AuthItem &operator = (const AuthItem &other); + ~AuthItem(); + + void fillInAuthorizationItem(AuthorizationItem &item); + + AuthorizationString name() const { return mName; } + const AuthorizationValue& value() const { return mValue; } + string stringValue() const { return string(static_cast(mValue.data), mValue.length); } + AuthorizationFlags flags() const { return mFlags; } + void setFlags(AuthorizationFlags inFlags) { mFlags = inFlags; }; + +private: + AuthorizationString mName; + AuthorizationValue mValue; + AuthorizationFlags mFlags; + mutable bool mOwnsName; + mutable bool mOwnsValue; + +public: + bool getBool(bool &value); + bool getString(string &value); + bool getCssmData(CssmAutoData &value); +}; + +class AuthItemRef : public RefPointer +{ +public: + AuthItemRef(const AuthorizationItem &item); + AuthItemRef(AuthorizationString name); + AuthItemRef(AuthorizationString name, AuthorizationValue value, AuthorizationFlags flags = 0); + + bool operator < (const AuthItemRef &other) const + { + return **this < *other; + } +}; + +// set should become a member with accessors +class AuthItemSet : public set +{ +public: + AuthItemSet(); + ~AuthItemSet(); + AuthItemSet(const AuthorizationItemSet *item); + AuthItemSet(const AuthItemSet& itemSet); + + AuthItemSet &operator = (const AuthorizationItemSet& itemSet); + AuthItemSet &operator = (const AuthItemSet& itemSet); + + void copy(AuthorizationItemSet *&data, size_t &length, Allocator &alloc = Allocator::standard()) const; + AuthorizationItemSet *copy() const; + + char *firstItemName; + +public: + AuthItem *find(const char *name); + +private: + void duplicate(const AuthItemSet& itemSet); +}; + +class FindAuthItemByRightName +{ +public: + FindAuthItemByRightName(const char *find_name) : name(find_name) { } + + bool operator()( const AuthItemRef& authitem ) + { + return (!strcmp(name, authitem->name())); + } + bool operator()( const AuthorizationItem* authitem ) + { + return (!strcmp(name, authitem->name)); + } + +private: + const char *name; +}; + +}; // namespace Authorization + +#endif /* ! _H_AUTHORIZATIONDATA */ diff --git a/libsecurity_cdsa_utilities/lib/AuthorizationWalkers.h b/libsecurity_cdsa_utilities/lib/AuthorizationWalkers.h new file mode 100644 index 00000000..94631a58 --- /dev/null +++ b/libsecurity_cdsa_utilities/lib/AuthorizationWalkers.h @@ -0,0 +1,82 @@ +/* + * 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@ + */ + + +/* + * AuthorizationWalkers.h + * SecurityCore + */ + +#if !defined(__AuthorizationWalkers__) +#define __AuthorizationWalkers__ 1 + +#include +#include +#include +#include // char * walker + +namespace Security { +namespace DataWalkers { + + +template +void walk(Action &operate, AuthorizationItem &item) +{ + operate(item); + walk(operate, const_cast(item.name)); + operate.blob(item.value, item.valueLength); + // Ignore reserved +} + +template +AuthorizationItemSet *walk(Action &operate, AuthorizationItemSet * &itemSet) +{ + operate(itemSet); + operate.blob(itemSet->items, itemSet->count * sizeof(itemSet->items[0])); + for (uint32 n = 0; n < itemSet->count; n++) + walk(operate, itemSet->items[n]); + return itemSet; +} + +template +void walk(Action &operate, AuthorizationValue &authvalue) +{ + operate.blob(authvalue.data, authvalue.length); +} + +template +AuthorizationValueVector *walk(Action &operate, AuthorizationValueVector * &valueVector) +{ + operate(valueVector); + operate.blob(valueVector->values, valueVector->count * sizeof(valueVector->values[0])); + for (uint32 n = 0; n < valueVector->count; n++) + walk(operate, valueVector->values[n]); + return valueVector; +} + + + +} // end namespace DataWalkers +} // end namespace Security + +#endif /* ! __AuthorizationWalkers__ */ diff --git a/libsecurity_cdsa_utilities/lib/KeySchema.h b/libsecurity_cdsa_utilities/lib/KeySchema.h new file mode 100644 index 00000000..6eed5196 --- /dev/null +++ b/libsecurity_cdsa_utilities/lib/KeySchema.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2000-2001,2003-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@ + */ + + +// +// KeySchema.h +// +#ifndef _H_KEYSCHEMA +#define _H_KEYSCHEMA + +#include + +namespace KeySchema +{ + extern const CSSM_DB_ATTRIBUTE_INFO KeyClass; + extern const CSSM_DB_ATTRIBUTE_INFO PrintName; + extern const CSSM_DB_ATTRIBUTE_INFO Alias; + extern const CSSM_DB_ATTRIBUTE_INFO Permanent; + extern const CSSM_DB_ATTRIBUTE_INFO Private; + extern const CSSM_DB_ATTRIBUTE_INFO Modifiable; + extern const CSSM_DB_ATTRIBUTE_INFO Label; + extern const CSSM_DB_ATTRIBUTE_INFO ApplicationTag; + extern const CSSM_DB_ATTRIBUTE_INFO KeyCreator; + extern const CSSM_DB_ATTRIBUTE_INFO KeyType; + extern const CSSM_DB_ATTRIBUTE_INFO KeySizeInBits; + extern const CSSM_DB_ATTRIBUTE_INFO EffectiveKeySize; + extern const CSSM_DB_ATTRIBUTE_INFO StartDate; + extern const CSSM_DB_ATTRIBUTE_INFO EndDate; + extern const CSSM_DB_ATTRIBUTE_INFO Sensitive; + extern const CSSM_DB_ATTRIBUTE_INFO AlwaysSensitive; + extern const CSSM_DB_ATTRIBUTE_INFO Extractable; + extern const CSSM_DB_ATTRIBUTE_INFO NeverExtractable; + extern const CSSM_DB_ATTRIBUTE_INFO Encrypt; + extern const CSSM_DB_ATTRIBUTE_INFO Decrypt; + extern const CSSM_DB_ATTRIBUTE_INFO Derive; + extern const CSSM_DB_ATTRIBUTE_INFO Sign; + extern const CSSM_DB_ATTRIBUTE_INFO Verify; + extern const CSSM_DB_ATTRIBUTE_INFO SignRecover; + extern const CSSM_DB_ATTRIBUTE_INFO VerifyRecover; + extern const CSSM_DB_ATTRIBUTE_INFO Wrap; + extern const CSSM_DB_ATTRIBUTE_INFO Unwrap; + + extern const CSSM_DB_SCHEMA_ATTRIBUTE_INFO KeySchemaAttributeList[]; + extern const CSSM_DB_SCHEMA_INDEX_INFO KeySchemaIndexList[]; + extern const uint32 KeySchemaAttributeCount; + extern const uint32 KeySchemaIndexCount; +}; + + +#endif // _H_KEYSCHEMA diff --git a/libsecurity_cdsa_utilities/lib/KeySchema.m4 b/libsecurity_cdsa_utilities/lib/KeySchema.m4 new file mode 100644 index 00000000..38996b5a --- /dev/null +++ b/libsecurity_cdsa_utilities/lib/KeySchema.m4 @@ -0,0 +1,129 @@ +divert(-1) +changecom(/*, */) +/* + * Copyright (c) 2000-2002 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. + */ + +define(`startClass', +`define(`indexIndex', 0)dnl +define(`class', $1)dnl +divert(2)dnl +// $1 attributes +const CSSM_DB_SCHEMA_ATTRIBUTE_INFO $1SchemaAttributeList[] = +{ +divert(3)dnl +// $1 indices +const CSSM_DB_SCHEMA_INDEX_INFO $1SchemaIndexList[] = +{') + +define(`endClass', +`divert(2)dnl +}; + +const uint32 class()SchemaAttributeCount = sizeof(class()SchemaAttributeList) / sizeof(CSSM_DB_SCHEMA_ATTRIBUTE_INFO); + +divert(3)dnl +` // Unique (primary) index' +undivert(5) +` // Secondary indices' +undivert(6)dnl +}; + +const uint32 class()SchemaIndexCount = sizeof(class()SchemaIndexList) / sizeof(CSSM_DB_SCHEMA_INDEX_INFO); + +undivert(4)dnl +divert(0)dnl +undivert(1)dnl +undivert(2)dnl +undivert(3)dnl') + +define(`attributeBody', +`{ +ifelse(index(`$1',`s'),-1, +` CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER, + {(char *)((uint64_t)$3<<32|$3)},', +` CSSM_DB_ATTRIBUTE_NAME_AS_STRING, + {$4},') + CSSM_DB_ATTRIBUTE_FORMAT_$7 +}') + +define(`simpleAttribute', +`const CSSM_DB_ATTRIBUTE_INFO $2 = +attributeBody($*); +') + +define(`attribute', +`divert(2)dnl + { $3, (char*) $4, { $5, $6 }, CSSM_DB_ATTRIBUTE_FORMAT_$7 }, +divert(-1) +ifelse(index(`$1',`S'),-1,`', +`divert(4)dnl +simpleAttribute($*) +divert(-1)')dnl + +ifelse(index(`$1',`U'),-1,`', +`divert(5)dnl + { $3, 0, CSSM_DB_INDEX_UNIQUE, CSSM_DB_INDEX_ON_ATTRIBUTE }, +divert(-1)')dnl +ifelse(index(`$1',`I'),-1,`', +`define(`indexIndex', incr(indexIndex))dnl +divert(6)dnl + { $3, indexIndex(), CSSM_DB_INDEX_NONUNIQUE, CSSM_DB_INDEX_ON_ATTRIBUTE }, +divert(-1)')') + +/* Start of actual output */ +divert(0)dnl +/* + * Generated by m4 from KeySchema.m4 please do not edit this file. + */ + +`#include ' +#include + +namespace KeySchema { + +divert(-1) +startClass(Key) +attribute(` Ss', KeyClass, kSecKeyKeyClass, (char*) "KeyClass", 0, NULL, UINT32) +attribute(` Ss', PrintName, kSecKeyPrintName, (char*) "PrintName", 0, NULL, BLOB) +attribute(` Ss', Alias, kSecKeyAlias, (char*) "Alias", 0, NULL, BLOB) +attribute(` Ss', Permanent, kSecKeyPermanent, (char*) "Permanent", 0, NULL, UINT32) +attribute(` Ss', Private, kSecKeyPrivate, (char*) "Private", 0, NULL, UINT32) +attribute(` Ss', Modifiable, kSecKeyModifiable, (char*) "Modifiable", 0, NULL, UINT32) +attribute(`UISs', Label, kSecKeyLabel, (char*) "Label", 0, NULL, BLOB) +attribute(`U Ss', ApplicationTag, kSecKeyApplicationTag, (char*) "ApplicationTag", 0, NULL, BLOB) +attribute(`U Ss', KeyCreator, kSecKeyKeyCreator, (char*) "KeyCreator", 0, NULL, BLOB) +attribute(`U Ss', KeyType, kSecKeyKeyType, (char*) "KeyType", 0, NULL, UINT32) +attribute(`U Ss', KeySizeInBits, kSecKeyKeySizeInBits, (char*) "KeySizeInBits", 0, NULL, UINT32) +attribute(`U Ss', EffectiveKeySize, kSecKeyEffectiveKeySize, (char*) "EffectiveKeySize", 0, NULL, UINT32) +attribute(`U Ss', StartDate, kSecKeyStartDate, (char*) "StartDate", 0, NULL, BLOB) +attribute(`U Ss', EndDate, kSecKeyEndDate, (char*) "EndDate", 0, NULL, BLOB) +attribute(` Ss', Sensitive, kSecKeySensitive, (char*) "Sensitive", 0, NULL, UINT32) +attribute(` Ss', AlwaysSensitive, kSecKeyAlwaysSensitive, (char*) "AlwaysSensitive", 0, NULL, UINT32) +attribute(` Ss', Extractable, kSecKeyExtractable, (char*) "Extractable", 0, NULL, UINT32) +attribute(` Ss', NeverExtractable, kSecKeyNeverExtractable, (char*) "NeverExtractable", 0, NULL, UINT32) +attribute(` ISs', Encrypt, kSecKeyEncrypt, (char*) "Encrypt", 0, NULL, UINT32) +attribute(` ISs', Decrypt, kSecKeyDecrypt, (char*) "Decrypt", 0, NULL, UINT32) +attribute(` ISs', Derive, kSecKeyDerive, (char*) "Derive", 0, NULL, UINT32) +attribute(` ISs', Sign, kSecKeySign, (char*) "Sign", 0, NULL, UINT32) +attribute(` ISs', Verify, kSecKeyVerify, (char*) "Verify", 0, NULL, UINT32) +attribute(` ISs', SignRecover, kSecKeySignRecover, (char*) "SignRecover", 0, NULL, UINT32) +attribute(` ISs', VerifyRecover, kSecKeyVerifyRecover, (char*) "VerifyRecover", 0, NULL, UINT32) +attribute(` ISs', Wrap, kSecKeyWrap, (char*) "Wrap", 0, NULL, UINT32) +attribute(` ISs', Unwrap, kSecKeyUnwrap, (char*) "Unwrap", 0, NULL, UINT32) +endClass() + +} // end namespace KeySchema diff --git a/libsecurity_cdsa_utilities/lib/Schema.h b/libsecurity_cdsa_utilities/lib/Schema.h new file mode 100644 index 00000000..49735347 --- /dev/null +++ b/libsecurity_cdsa_utilities/lib/Schema.h @@ -0,0 +1,129 @@ +/* + * 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@ + */ + + +// +// Schema.h +// +#ifndef _SECURITY_SCHEMA_H_ +#define _SECURITY_SCHEMA_H_ + +#include + +namespace Security { + +namespace KeychainCore { + +namespace Schema { + +CSSM_DB_RECORDTYPE recordTypeFor(SecItemClass itemClass); +SecItemClass itemClassFor(CSSM_DB_RECORDTYPE recordType); +const CSSM_DB_ATTRIBUTE_INFO &attributeInfo(SecKeychainAttrType attrType); + +extern const CSSM_DB_ATTRIBUTE_INFO RelationID; +extern const CSSM_DB_ATTRIBUTE_INFO RelationName; +extern const CSSM_DB_ATTRIBUTE_INFO AttributeID; +extern const CSSM_DB_ATTRIBUTE_INFO AttributeNameFormat; +extern const CSSM_DB_ATTRIBUTE_INFO AttributeName; +extern const CSSM_DB_ATTRIBUTE_INFO AttributeNameID; +extern const CSSM_DB_ATTRIBUTE_INFO AttributeFormat; +extern const CSSM_DB_ATTRIBUTE_INFO IndexType; + +extern const CSSM_DBINFO DBInfo; + +// Certificate attributes and schema +extern const CSSM_DB_ATTRIBUTE_INFO kX509CertificateCertType; +extern const CSSM_DB_ATTRIBUTE_INFO kX509CertificateCertEncoding; +extern const CSSM_DB_ATTRIBUTE_INFO kX509CertificatePrintName; +extern const CSSM_DB_ATTRIBUTE_INFO kX509CertificateAlias; +extern const CSSM_DB_ATTRIBUTE_INFO kX509CertificateSubject; +extern const CSSM_DB_ATTRIBUTE_INFO kX509CertificateIssuer; +extern const CSSM_DB_ATTRIBUTE_INFO kX509CertificateSerialNumber; +extern const CSSM_DB_ATTRIBUTE_INFO kX509CertificateSubjectKeyIdentifier; +extern const CSSM_DB_ATTRIBUTE_INFO kX509CertificatePublicKeyHash; + +extern const CSSM_DB_SCHEMA_ATTRIBUTE_INFO X509CertificateSchemaAttributeList[]; +extern const CSSM_DB_SCHEMA_INDEX_INFO X509CertificateSchemaIndexList[]; +extern const uint32 X509CertificateSchemaAttributeCount; +extern const uint32 X509CertificateSchemaIndexCount; + +// CRL attributes and schema +extern const CSSM_DB_ATTRIBUTE_INFO kX509CrlCrlType; +extern const CSSM_DB_ATTRIBUTE_INFO kX509CrlCrlEncoding; +extern const CSSM_DB_ATTRIBUTE_INFO kX509CrlPrintName; +extern const CSSM_DB_ATTRIBUTE_INFO kX509CrlAlias; +extern const CSSM_DB_ATTRIBUTE_INFO kX509CrlIssuer; +extern const CSSM_DB_ATTRIBUTE_INFO kX509CrlSerialNumber; +extern const CSSM_DB_ATTRIBUTE_INFO kX509CrlThisUpdate; +extern const CSSM_DB_ATTRIBUTE_INFO kX509CrlNextUpdate; + +extern const CSSM_DB_SCHEMA_ATTRIBUTE_INFO X509CrlSchemaAttributeList[]; +extern const CSSM_DB_SCHEMA_INDEX_INFO X509CrlSchemaIndexList[]; +extern const uint32 X509CrlSchemaAttributeCount; +extern const uint32 X509CrlSchemaIndexCount; + +// UserTrust records attributes and schema +extern const CSSM_DB_ATTRIBUTE_INFO kUserTrustTrustedCertificate; +extern const CSSM_DB_ATTRIBUTE_INFO kUserTrustTrustedPolicy; + +extern const CSSM_DB_SCHEMA_ATTRIBUTE_INFO UserTrustSchemaAttributeList[]; +extern const CSSM_DB_SCHEMA_INDEX_INFO UserTrustSchemaIndexList[]; +extern const uint32 UserTrustSchemaAttributeCount; +extern const uint32 UserTrustSchemaIndexCount; + +// UnlockReferral records attributes and schema +extern const CSSM_DB_ATTRIBUTE_INFO kUnlockReferralType; +extern const CSSM_DB_ATTRIBUTE_INFO kUnlockReferralDbName; +extern const CSSM_DB_ATTRIBUTE_INFO kUnlockReferralDbGuid; +extern const CSSM_DB_ATTRIBUTE_INFO kUnlockReferralDbSSID; +extern const CSSM_DB_ATTRIBUTE_INFO kUnlockReferralDbSSType; +extern const CSSM_DB_ATTRIBUTE_INFO kUnlockReferralDbNetname; +extern const CSSM_DB_ATTRIBUTE_INFO kUnlockReferralKeyLabel; +extern const CSSM_DB_ATTRIBUTE_INFO kUnlockReferralKeyAppTag; +extern const CSSM_DB_ATTRIBUTE_INFO kUnlockReferralPrintName; +extern const CSSM_DB_ATTRIBUTE_INFO kUnlockReferralAlias; + +extern const CSSM_DB_SCHEMA_ATTRIBUTE_INFO UnlockReferralSchemaAttributeList[]; +extern const CSSM_DB_SCHEMA_INDEX_INFO UnlockReferralSchemaIndexList[]; +extern const uint32 UnlockReferralSchemaAttributeCount; +extern const uint32 UnlockReferralSchemaIndexCount; + +// Extended Attribute record attributes and schema +extern const CSSM_DB_ATTRIBUTE_INFO kExtendedAttributeRecordType; +extern const CSSM_DB_ATTRIBUTE_INFO kExtendedAttributeItemID; +extern const CSSM_DB_ATTRIBUTE_INFO kExtendedAttributeAttributeName; +extern const CSSM_DB_ATTRIBUTE_INFO kExtendedAttributeModDate; +extern const CSSM_DB_ATTRIBUTE_INFO kExtendedAttributeAttributeValue; + +extern const CSSM_DB_SCHEMA_ATTRIBUTE_INFO ExtendedAttributeSchemaAttributeList[]; +extern const CSSM_DB_SCHEMA_INDEX_INFO ExtendedAttributeSchemaIndexList[]; +extern const uint32 ExtendedAttributeSchemaAttributeCount; +extern const uint32 ExtendedAttributeSchemaIndexCount; + +} // end namespace Schema + +} // end namespace KeychainCore + +} // end namespace Security + +#endif // !_SECURITY_SCHEMA_H_ diff --git a/libsecurity_cdsa_utilities/lib/Schema.m4 b/libsecurity_cdsa_utilities/lib/Schema.m4 new file mode 100644 index 00000000..b611e62d --- /dev/null +++ b/libsecurity_cdsa_utilities/lib/Schema.m4 @@ -0,0 +1,466 @@ +divert(-1) +changecom(/*, */) +/* + * Copyright (c) 2000-2002 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. + */ + +define(`startClass', +`define(`arrayIndex', 0)dnl +define(`class', $1)dnl +divert(0)dnl +// $1 password attributes +static const CSSM_DB_ATTRIBUTE_INFO $1Attributes[] = +{ +divert(1)dnl +// $1 password indices +static const CSSM_DB_INDEX_INFO $1Indices[] = +{') + +define(`endClass', +`divert(0)dnl +}; + +divert(1)dnl +` // Unique (primary) index' +undivert(3) +` // Secondary indices' +undivert(4)dnl +}; + +divert(-1)') + +define(`attributeBody', +` { +ifelse(index(`$1',`s'),-1, +` CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER, + {(char *)((uint64_t)$3<<32|$3)},', +` CSSM_DB_ATTRIBUTE_NAME_AS_STRING, + {$4},') + CSSM_DB_ATTRIBUTE_FORMAT_$7 + }') + +define(`simpleAttribute', +`const CSSM_DB_ATTRIBUTE_INFO $2 = +attributeBody($*); +') + +define(`attribute', +`ifelse(index(`$1',`U'),-1,`', +`divert(3)dnl + { + CSSM_DB_INDEX_UNIQUE, + CSSM_DB_INDEX_ON_ATTRIBUTE, +attributeBody($*) + }, +')dnl +ifelse(index(`$1',`I'),-1,`', +`divert(4)dnl + { + CSSM_DB_INDEX_NONUNIQUE, + CSSM_DB_INDEX_ON_ATTRIBUTE, +attributeBody($*) + }, +')dnl +divert(2)dnl +dnl const CSSM_DB_ATTRIBUTE_INFO &`k'class()$2 = class()Attributes[arrayIndex()]; +`#define k'class()$2 class()Attributes[arrayIndex()]; +divert(0)dnl +attributeBody($*),dnl +define(`arrayIndex', incr(arrayIndex))dnl +') + +define(`attrInfo', +`{ + $1, + sizeof($2Attributes) / sizeof(CSSM_DB_ATTRIBUTE_INFO), + const_cast($2Attributes) + }') + +define(`indexInfo', +`{ + $1, + sizeof($2Indices) / sizeof(CSSM_DB_INDEX_INFO), + const_cast($2Indices) + }') + +define(`parseInfo', +`{ + CSSM_DB_RECORDTYPE_APP_DEFINED_START, + { + {0,0,0,{0}}, + {0,0}, + 0, + 0 + } + }') + +define(`startNewClass', +`define(`indexIndex', 0)dnl +define(`class', $1)dnl +divert(2)dnl +// $1 attributes +const CSSM_DB_SCHEMA_ATTRIBUTE_INFO $1SchemaAttributeList[] = +{ +divert(3)dnl +// $1 indices +const CSSM_DB_SCHEMA_INDEX_INFO $1SchemaIndexList[] = +{') + +define(`endNewClass', +`divert(2)dnl +}; + +const uint32 class()SchemaAttributeCount = sizeof(class()SchemaAttributeList) / sizeof(CSSM_DB_SCHEMA_ATTRIBUTE_INFO); + +divert(3)dnl +` // Unique (primary) index' +undivert(5) +` // Secondary indices' +undivert(6)dnl +}; + +const uint32 class()SchemaIndexCount = sizeof(class()SchemaIndexList) / sizeof(CSSM_DB_SCHEMA_INDEX_INFO); + +undivert(4)dnl +divert(0)dnl +undivert(2)dnl +undivert(3)dnl') + +define(`newAttributeBody', +`{ +ifelse(index(`$1',`s'),-1, +` CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER, + {(char *)((uint64_t)$3<<32|$3)},', +` CSSM_DB_ATTRIBUTE_NAME_AS_STRING, + {$4},') + CSSM_DB_ATTRIBUTE_FORMAT_$7 +}') + +define(`simpleNewAttribute', +`const CSSM_DB_ATTRIBUTE_INFO `k'class()$2 = +newAttributeBody($*); +') + +define(`newAttribute', +`divert(2)dnl + { $3, $4, { $5, $6 }, CSSM_DB_ATTRIBUTE_FORMAT_$7 }, +divert(-1) +ifelse(index(`$1',`S'),-1,`', +`divert(4)dnl +simpleNewAttribute($*) +divert(-1)')dnl + +ifelse(index(`$1',`U'),-1,`', +`divert(5)dnl + { $3, 0, CSSM_DB_INDEX_UNIQUE, CSSM_DB_INDEX_ON_ATTRIBUTE }, +divert(-1)')dnl +ifelse(index(`$1',`I'),-1,`', +`define(`indexIndex', incr(indexIndex))dnl +divert(6)dnl + { $3, indexIndex(), CSSM_DB_INDEX_NONUNIQUE, CSSM_DB_INDEX_ON_ATTRIBUTE }, +divert(-1)')') + +/* Start of actual output */ +divert(0)dnl +/* + * Generated by m4 from Schema.m4 please do not edit this file. + */ + +`#include ' + +`#include ' +`#include ' +`#include ' +`#include ' +`#include ' + +namespace Security { + +namespace KeychainCore { + +namespace Schema { + +// Meta attributes +simpleAttribute(` s', RelationID, 0, (char*) "RelationID", 0, NULL, UINT32) +simpleAttribute(` s', RelationName, 1, (char*) "RelationName", 0, NULL, STRING) +simpleAttribute(` s', AttributeID, 1, (char*) "AttributeID", 0, NULL, UINT32) +simpleAttribute(` s', AttributeNameFormat, 2, (char*) "AttributeNameFormat", 0, NULL, UINT32) +simpleAttribute(` s', AttributeName, 3, (char*) "AttributeName", 0, NULL, STRING) +simpleAttribute(` s', AttributeNameID, 4, (char*) "AttributeNameID", 0, NULL, BLOB) +simpleAttribute(` s', AttributeFormat, 5, (char*) "AttributeFormat", 0, NULL, UINT32) +simpleAttribute(` s', IndexType, 3, (char*) "IndexType", 0, NULL, UINT32) + +divert(-1) +startClass(Generic) +attribute(` i', CreationDate, kSecCreationDateItemAttr, (char*) "CreationDate", 0, NULL, TIME_DATE) +attribute(` i', ModDate, kSecModDateItemAttr, (char*) "ModDate", 0, NULL, TIME_DATE) +attribute(` i', Description, kSecDescriptionItemAttr, (char*) "Description", 0, NULL, BLOB) +attribute(` i', Comment, kSecCommentItemAttr, (char*) "Comment", 0, NULL, BLOB) +attribute(` i', Creator, kSecCreatorItemAttr, (char*) "Creator", 0, NULL, UINT32) +attribute(` i', Type, kSecTypeItemAttr, (char*) "Type", 0, NULL, UINT32) +attribute(` i', ScriptCode, kSecScriptCodeItemAttr, (char*) "ScriptCode", 0, NULL, SINT32) +attribute(` s', PrintName, kSecLabelItemAttr, (char*) "PrintName", 0, NULL, BLOB) +attribute(` s', Alias, kSecAlias, (char*) "Alias", 0, NULL, BLOB) +attribute(` i', Invisible, kSecInvisibleItemAttr, (char*) "Invisible", 0, NULL, SINT32) +attribute(` i', Negative, kSecNegativeItemAttr, (char*) "Negative", 0, NULL, SINT32) +attribute(` i', CustomIcon, kSecCustomIconItemAttr, (char*) "CustomIcon", 0, NULL, SINT32) +attribute(` i', Protected, kSecProtectedDataItemAttr, (char*) "Protected", 0, NULL, BLOB) +attribute(`UIi', Account, kSecAccountItemAttr, (char*) "Account", 0, NULL, BLOB) +attribute(`UIi', Service, kSecServiceItemAttr, (char*) "Service", 0, NULL, BLOB) +attribute(` i', Generic, kSecGenericItemAttr, (char*) "Generic", 0, NULL, BLOB) +endClass() + +startClass(Appleshare) +attribute(` i', CreationDate, kSecCreationDateItemAttr, (char*) "CreationDate", 0, NULL, TIME_DATE) +attribute(` i', ModDate, kSecModDateItemAttr, (char*) "ModDate", 0, NULL, TIME_DATE) +attribute(` i', Description, kSecDescriptionItemAttr, (char*) "Description", 0, NULL, BLOB) +attribute(` i', Comment, kSecCommentItemAttr, (char*) "Comment", 0, NULL, BLOB) +attribute(` i', Creator, kSecCreatorItemAttr, (char*) "Creator", 0, NULL, UINT32) +attribute(` i', Type, kSecTypeItemAttr, (char*) "Type", 0, NULL, UINT32) +attribute(` i', ScriptCode, kSecScriptCodeItemAttr, (char*) "ScriptCode", 0, NULL, SINT32) +attribute(` s', PrintName, kSecLabelItemAttr, (char*) "PrintName", 0, NULL, BLOB) +attribute(` s', Alias, kSecAlias, (char*) "Alias", 0, NULL, BLOB) +attribute(` i', Invisible, kSecInvisibleItemAttr, (char*) "Invisible", 0, NULL, SINT32) +attribute(` i', Negative, kSecNegativeItemAttr, (char*) "Negative", 0, NULL, SINT32) +attribute(` i', CustomIcon, kSecCustomIconItemAttr, (char*) "CustomIcon", 0, NULL, SINT32) +attribute(` i', Protected, kSecProtectedDataItemAttr, (char*) "Protected", 0, NULL, BLOB) +attribute(`UIi', Account, kSecAccountItemAttr, (char*) "Account", 0, NULL, BLOB) +attribute(`UIi', Volume, kSecVolumeItemAttr, (char*) "Volume", 0, NULL, BLOB) +attribute(` i', Server, kSecServerItemAttr, (char*) "Server", 0, NULL, BLOB) +attribute(` i', Protocol, kSecProtocolItemAttr, (char*) "Protocol", 0, NULL, UINT32) +attribute(`UIi', Address, kSecAddressItemAttr, (char*) "Address", 0, NULL, BLOB) +attribute(`UIi', Signature, kSecSignatureItemAttr, (char*) "Signature", 0, NULL, BLOB) +endClass() + +startClass(Internet) +attribute(` i', CreationDate, kSecCreationDateItemAttr, (char*) "CreationDate", 0, NULL, TIME_DATE) +attribute(` i', ModDate, kSecModDateItemAttr, (char*) "ModDate", 0, NULL, TIME_DATE) +attribute(` i', Description, kSecDescriptionItemAttr, (char*) "Description", 0, NULL, BLOB) +attribute(` i', Comment, kSecCommentItemAttr, (char*) "Comment", 0, NULL, BLOB) +attribute(` i', Creator, kSecCreatorItemAttr, (char*) "Creator", 0, NULL, UINT32) +attribute(` i', Type, kSecTypeItemAttr, (char*) "Type", 0, NULL, UINT32) +attribute(` i', ScriptCode, kSecScriptCodeItemAttr, (char*) "ScriptCode", 0, NULL, SINT32) +attribute(` s', PrintName, kSecLabelItemAttr, (char*) "PrintName", 0, NULL, BLOB) +attribute(` s', Alias, kSecAlias, (char*) "Alias", 0, NULL, BLOB) +attribute(` i', Invisible, kSecInvisibleItemAttr, (char*) "Invisible", 0, NULL, SINT32) +attribute(` i', Negative, kSecNegativeItemAttr, (char*) "Negative", 0, NULL, SINT32) +attribute(` i', CustomIcon, kSecCustomIconItemAttr, (char*) "CustomIcon", 0, NULL, SINT32) +attribute(` i', Protected, kSecProtectedDataItemAttr, (char*) "Protected", 0, NULL, BLOB) +attribute(`UIi', Account, kSecAccountItemAttr, (char*) "Account", 0, NULL, BLOB) +attribute(`UIi', SecurityDomain, kSecSecurityDomainItemAttr, (char*) "SecurityDomain", 0, NULL, BLOB) +attribute(`UIi', Server, kSecServerItemAttr, (char*) "Server", 0, NULL, BLOB) +attribute(`UIi', Protocol, kSecProtocolItemAttr, (char*) "Protocol", 0, NULL, UINT32) +attribute(`UIi', AuthType, kSecAuthenticationTypeItemAttr, (char*) "AuthType", 0, NULL, BLOB) +attribute(`UIi', Port, kSecPortItemAttr, (char*) "Port", 0, NULL, UINT32) +attribute(`UIi', Path, kSecPathItemAttr, (char*) "Path", 0, NULL, BLOB) +endClass() + +startNewClass(X509Certificate) +newAttribute(`UISs', CertType, kSecCertTypeItemAttr, (char*) "CertType", 0, NULL, UINT32) +newAttribute(` Ss', CertEncoding, kSecCertEncodingItemAttr, (char*) "CertEncoding", 0, NULL, UINT32) +newAttribute(` Ss', PrintName, kSecLabelItemAttr, (char*) "PrintName", 0, NULL, BLOB) +newAttribute(` ISs', Alias, kSecAlias, (char*) "Alias", 0, NULL, BLOB) +newAttribute(` ISs', Subject, kSecSubjectItemAttr, (char*) "Subject", 0, NULL, BLOB) +newAttribute(`UISs', Issuer, kSecIssuerItemAttr, (char*) "Issuer", 0, NULL, BLOB) +newAttribute(`UISs', SerialNumber, kSecSerialNumberItemAttr, (char*) "SerialNumber", 0, NULL, BLOB) +newAttribute(` ISs', SubjectKeyIdentifier, kSecSubjectKeyIdentifierItemAttr, (char*) "SubjectKeyIdentifier", 0, NULL, BLOB) +newAttribute(` ISs', PublicKeyHash, kSecPublicKeyHashItemAttr, (char*) "PublicKeyHash", 0, NULL, BLOB) +endNewClass() + +startNewClass(X509Crl) +newAttribute(`UISs', CrlType, kSecCrlType, (char*) "CrlType", 0, NULL, UINT32) +newAttribute(` Ss', CrlEncoding, kSecCrlEncodingItemAttr, (char*) "CrlEncoding", 0, NULL, UINT32) +newAttribute(` Ss', PrintName, kSecLabelItemAttr, (char*) "PrintName", 0, NULL, BLOB) +newAttribute(` Ss', Alias, kSecAlias, (char*) "Alias", 0, NULL, BLOB) +newAttribute(`UISs', Issuer, kSecIssuerItemAttr, (char*) "Issuer", 0, NULL, BLOB) +newAttribute(`UISs', ThisUpdate, kSecThisUpdateItemAttr, (char*) "ThisUpdate", 0, NULL, BLOB) +newAttribute(`UISs', NextUpdate, kSecNextUpdateItemAttr, (char*) "NextUpdate", 0, NULL, BLOB) +newAttribute(` Ss', URI, kSecUriItemAttr, (char*) "URI", 0, NULL, BLOB) +newAttribute(` ISs', CrlNumber, kSecCrlNumberItemAttr, (char*) "CrlNumber", 0, NULL, UINT32) +newAttribute(` ISs', DeltaCrlNumber, kSecDeltaCrlNumberItemAttr, (char*) "DeltaCrlNumber", 0, NULL, UINT32) +endNewClass() + +startNewClass(UserTrust) +newAttribute(`UISs', TrustedCertificate, kSecTrustCertAttr, (char*) "TrustedCertificate", 0, NULL, BLOB) +newAttribute(`UISs', TrustedPolicy, kSecTrustPolicyAttr, (char*) "TrustedPolicy", 0, NULL, BLOB) +newAttribute(` Ss', PrintName, kSecLabelItemAttr, (char*) "PrintName", 0, NULL, BLOB) +endNewClass() + +startNewClass(UnlockReferral) +newAttribute(`UISs', Type, kSecReferralTypeAttr, (char*) "Type", 0, NULL, UINT32) +newAttribute(`UISs', DbName, kSecReferralDbNameAttr, (char*) "DbName", 0, NULL, STRING) +newAttribute(`UISs', DbNetname, kSecReferralDbNetnameAttr, (char*) "DbNetname", 0, NULL, BLOB) +newAttribute(`UISs', DbGuid, kSecReferralDbGuidAttr, (char*) "DbGuid", 0, NULL, BLOB) +newAttribute(`UISs', DbSSID, kSecReferralDbSSIDAttr, (char*) "DbSSID", 0, NULL, UINT32) +newAttribute(`UISs', DbSSType, kSecReferralDbSSTypeAttr, (char*) "DbSSType", 0, NULL, UINT32) +newAttribute(` ISs', KeyLabel, kSecReferralKeyLabelAttr, (char*) "KeyLabel", 0, NULL, BLOB) +newAttribute(` ISs', KeyAppTag, kSecReferralKeyAppTagAttr, (char*) "KeyAppTag", 0, NULL, BLOB) +newAttribute(` Ss', PrintName, kSecLabelItemAttr, (char*) "PrintName", 0, NULL, BLOB) +newAttribute(` Ss', Alias, kSecAlias, (char*) "Alias", 0, NULL, BLOB) +endNewClass() + +// Extended Attribute +startNewClass(ExtendedAttribute) +newAttribute(`UISs', RecordType, kExtendedAttrRecordTypeAttr, (char*) "RecordType", 0, NULL, UINT32) +newAttribute(`UISs', ItemID, kExtendedAttrItemIDAttr, (char*) "ItemID", 0, NULL, BLOB) +newAttribute(`UISs', AttributeName, kExtendedAttrAttributeNameAttr, (char*) "AttributeName", 0, NULL, BLOB) +newAttribute(` Ss', ModDate, kSecModDateItemAttr, (char*) "ModDate", 0, NULL, TIME_DATE) +newAttribute(` Ss', AttributeValue, kExtendedAttrAttributeValueAttr, (char*) "AttributeValue", 0, NULL, BLOB) +endNewClass() + +divert(3) +static const CSSM_DB_RECORD_ATTRIBUTE_INFO Attributes[] = +{ + attrInfo(CSSM_DL_DB_RECORD_GENERIC_PASSWORD, Generic), + attrInfo(CSSM_DL_DB_RECORD_APPLESHARE_PASSWORD, Appleshare), + attrInfo(CSSM_DL_DB_RECORD_INTERNET_PASSWORD, Internet) +}; + +static const CSSM_DB_RECORD_INDEX_INFO Indices[] = +{ + indexInfo(CSSM_DL_DB_RECORD_GENERIC_PASSWORD, Generic), + indexInfo(CSSM_DL_DB_RECORD_APPLESHARE_PASSWORD, Appleshare), + indexInfo(CSSM_DL_DB_RECORD_INTERNET_PASSWORD, Internet) +}; + +static const CSSM_DB_PARSING_MODULE_INFO ParseInfos[] = +{ + parseInfo(), + parseInfo(), + parseInfo() +}; + +// +// Public stuff +// +const CSSM_DBINFO DBInfo = +{ + sizeof(Attributes) / sizeof(CSSM_DB_RECORD_ATTRIBUTE_INFO), + const_cast(ParseInfos), + const_cast(Attributes), + const_cast(Indices), + CSSM_TRUE, + NULL, + NULL +}; + +// +// Schema methods +// +CSSM_DB_RECORDTYPE +recordTypeFor(SecItemClass itemClass) +{ + switch (itemClass) + { + case kSecGenericPasswordItemClass: return CSSM_DL_DB_RECORD_GENERIC_PASSWORD; + case kSecInternetPasswordItemClass: return CSSM_DL_DB_RECORD_INTERNET_PASSWORD; + case kSecAppleSharePasswordItemClass: return CSSM_DL_DB_RECORD_APPLESHARE_PASSWORD; + default: return CSSM_DB_RECORDTYPE(itemClass); + } +} + +SecItemClass +itemClassFor(CSSM_DB_RECORDTYPE recordType) +{ + switch (recordType) + { + case CSSM_DL_DB_RECORD_GENERIC_PASSWORD: return kSecGenericPasswordItemClass; + case CSSM_DL_DB_RECORD_INTERNET_PASSWORD: return kSecInternetPasswordItemClass; + case CSSM_DL_DB_RECORD_APPLESHARE_PASSWORD: return kSecAppleSharePasswordItemClass; + default: return SecItemClass(recordType); + } +} + +const CSSM_DB_ATTRIBUTE_INFO & +attributeInfo(SecKeychainAttrType attrType) +{ + switch (attrType) + { + case kSecCreationDateItemAttr: return kGenericCreationDate; + case kSecModDateItemAttr: return kGenericModDate; + case kSecDescriptionItemAttr: return kGenericDescription; + case kSecCommentItemAttr: return kGenericComment; + case kSecCreatorItemAttr: return kGenericCreator; + case kSecTypeItemAttr: return kGenericType; + case kSecScriptCodeItemAttr: return kGenericScriptCode; + case kSecLabelItemAttr: return kGenericPrintName; + case kSecAlias: return kGenericAlias; + case kSecInvisibleItemAttr: return kGenericInvisible; + case kSecNegativeItemAttr: return kGenericNegative; + case kSecCustomIconItemAttr: return kGenericCustomIcon; + /* Unique Generic password attributes */ + case kSecAccountItemAttr: return kGenericAccount; + case kSecServiceItemAttr: return kGenericService; + case kSecGenericItemAttr: return kGenericGeneric; + /* Unique Appleshare password attributes */ + case kSecVolumeItemAttr: return kAppleshareVolume; + case kSecAddressItemAttr: return kAppleshareAddress; + case kSecSignatureItemAttr: return kAppleshareSignature; + /* Unique AppleShare and Internet attributes */ + case kSecServerItemAttr: return kAppleshareServer; + case kSecProtocolItemAttr: return kAppleshareProtocol; + /* Unique Internet password attributes */ + case kSecSecurityDomainItemAttr: return kInternetSecurityDomain; + case kSecAuthenticationTypeItemAttr: return kInternetAuthType; + case kSecPortItemAttr: return kInternetPort; + case kSecPathItemAttr: return kInternetPath; + /* Unique Certificate attributes */ + case kSecCertTypeItemAttr: return kX509CertificateCertType; + case kSecCertEncodingItemAttr: return kX509CertificateCertEncoding; + case kSecSubjectItemAttr: return kX509CertificateSubject; + case kSecIssuerItemAttr: return kX509CertificateIssuer; + case kSecSerialNumberItemAttr: return kX509CertificateSerialNumber; + case kSecSubjectKeyIdentifierItemAttr: return kX509CertificateSubjectKeyIdentifier; + case kSecPublicKeyHashItemAttr: return kX509CertificatePublicKeyHash; + /* Unique UserTrust attributes */ + case kSecTrustCertAttr: return kUserTrustTrustedCertificate; + case kSecTrustPolicyAttr: return kUserTrustTrustedPolicy; + /* Unique UnlockReferral attributes */ + case kSecReferralTypeAttr: return kUnlockReferralType; + case kSecReferralDbNameAttr: return kUnlockReferralDbName; + case kSecReferralDbGuidAttr: return kUnlockReferralDbGuid; + case kSecReferralDbSSIDAttr: return kUnlockReferralDbSSID; + case kSecReferralDbSSTypeAttr: return kUnlockReferralDbSSType; + case kSecReferralDbNetnameAttr: return kUnlockReferralDbNetname; + case kSecReferralKeyLabelAttr: return kUnlockReferralKeyLabel; + case kSecReferralKeyAppTagAttr: return kUnlockReferralKeyAppTag; + /* Unique ExtendedAttribute attributes */ + case kExtendedAttrRecordTypeAttr: return kExtendedAttributeRecordType; + case kExtendedAttrItemIDAttr: return kExtendedAttributeItemID; + case kExtendedAttrAttributeNameAttr: return kExtendedAttributeAttributeName; + case kExtendedAttrAttributeValueAttr: return kExtendedAttributeAttributeValue; + /* ??? */ + case kSecProtectedDataItemAttr: return kGenericProtected; + default: + { + if (attrType == 7) + { + return kGenericPrintName; + } + else if (attrType == 8) + { + return kGenericAlias; + } + MacOSError::throwMe(errSecNoSuchAttr); + } + } +} + +} // end namespace Schema + +} // end namespace KeychainCore + +} // end namespace Security diff --git a/libsecurity_cdsa_utilities/lib/acl_any.cpp b/libsecurity_cdsa_utilities/lib/acl_any.cpp new file mode 100644 index 00000000..50e4aea8 --- /dev/null +++ b/libsecurity_cdsa_utilities/lib/acl_any.cpp @@ -0,0 +1,63 @@ +/* + * 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@ + */ + + +// +// acl_any - "anyone" ACL subject type. +// +#include +#include + + +// +// The ANY subject matches all credentials, including none at all. +// +bool AnyAclSubject::validate(const AclValidationContext &) const +{ + return true; +} + + +// +// The CSSM_LIST version is trivial. It has no private part to omit. +// +CssmList AnyAclSubject::toList(Allocator &alloc) const +{ + return TypedList(alloc, CSSM_ACL_SUBJECT_TYPE_ANY); +} + + +// +// The subject form takes no arguments. +// +AnyAclSubject *AnyAclSubject::Maker::make(const TypedList &list) const +{ + crack(list, 0); // no arguments in input list + return new AnyAclSubject(); +} + +AnyAclSubject *AnyAclSubject::Maker::make(Version, Reader &, Reader &) const +{ + return new AnyAclSubject(); +} + diff --git a/libsecurity_cdsa_utilities/lib/acl_any.h b/libsecurity_cdsa_utilities/lib/acl_any.h new file mode 100644 index 00000000..d7dc25a8 --- /dev/null +++ b/libsecurity_cdsa_utilities/lib/acl_any.h @@ -0,0 +1,60 @@ +/* + * 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@ + */ + + +// +// acl_any - "anyone" ACL subject type. +// +// This subject will categorically match everything and anything, even no +// credentials at all (a NULL AccessCredentials pointer). +// +#ifndef _ACL_ANY +#define _ACL_ANY + +#include +#include + +namespace Security { + + +// +// The ANY subject simply matches everything. No sweat. +// +class AnyAclSubject : public AclSubject { +public: + AnyAclSubject() : AclSubject(CSSM_ACL_SUBJECT_TYPE_ANY) { } + bool validate(const AclValidationContext &ctx) const; + CssmList toList(Allocator &alloc) const; + + class Maker : public AclSubject::Maker { + public: + Maker() : AclSubject::Maker(CSSM_ACL_SUBJECT_TYPE_ANY) { } + AnyAclSubject *make(const TypedList &list) const; + AnyAclSubject *make(Version, Reader &pub, Reader &priv) const; + }; +}; + +} // end namespace Security + + +#endif //_ACL_ANY diff --git a/libsecurity_cdsa_utilities/lib/acl_codesigning.cpp b/libsecurity_cdsa_utilities/lib/acl_codesigning.cpp new file mode 100644 index 00000000..9869ec64 --- /dev/null +++ b/libsecurity_cdsa_utilities/lib/acl_codesigning.cpp @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2000-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@ + */ + + +// +// acl_codesigning - ACL subject for signature of calling application +// +#include +#include +#include +#include + + +// +// Code signature credentials are validated globally - they are entirely +// a feature of "the" process (defined by the environment), and take no +// samples whatsoever. +// +bool CodeSignatureAclSubject::validate(const AclValidationContext &context) const +{ + // a suitable environment is required for a match + if (Environment *env = context.environment()) + return env->verifyCodeSignature(*this, context); + else + return false; +} + + +// +// Make a copy of this subject in CSSM_LIST form. +// The format is (head), (type code: Wordid), (signature data: datum), (comment: datum) +// +CssmList CodeSignatureAclSubject::toList(Allocator &alloc) const +{ + assert(path().find('\0') == string::npos); // no embedded nulls in path + uint32_t type = CSSM_ACL_CODE_SIGNATURE_OSX; + TypedList list(alloc, CSSM_ACL_SUBJECT_TYPE_CODE_SIGNATURE, + new(alloc) ListElement(type), + new(alloc) ListElement(alloc, CssmData::wrap(legacyHash(), SHA1::digestLength)), + new(alloc) ListElement(alloc, CssmData::wrap(path().c_str(), path().size() + 1))); + if (requirement()) { + CFRef reqData; + MacOSError::check(SecRequirementCopyData(requirement(), kSecCSDefaultFlags, &reqData.aref())); + list += new(alloc) ListElement(alloc, + CssmData::wrap(CFDataGetBytePtr(reqData), CFDataGetLength(reqData))); + } + for (AuxMap::const_iterator it = beginAux(); it != endAux(); it++) + list += new(alloc) ListElement(alloc, CssmData(*it->second)); + return list; +} + + +// +// Create a CodeSignatureAclSubject +// +CodeSignatureAclSubject *CodeSignatureAclSubject::Maker::make(const TypedList &list) const +{ + // there once was a format with only a hash (length 2+1). It is no longer supported + unsigned total = list.length(); // includes subject type header + if (total >= 3 + 1 + && list[1].is(CSSM_LIST_ELEMENT_WORDID) // [1] == signature type + && list[1] == CSSM_ACL_CODE_SIGNATURE_OSX + && list[2].is(CSSM_LIST_ELEMENT_DATUM) // [2] == legacy hash + && list[2].data().length() == SHA1::digestLength + && list[3].is(CSSM_LIST_ELEMENT_DATUM)) { + // structurally okay + CodeSignatureAclSubject *subj = + new CodeSignatureAclSubject(list[2].data().interpretedAs(), + list[3].data().interpretedAs()); + for (unsigned n = 3 + 1; n < total; n++) { + if (list[n].is(CSSM_LIST_ELEMENT_DATUM)) { + const BlobCore *blob = list[n].data().interpretedAs(); + if (blob->length() < sizeof(BlobCore)) { + secdebug("csblob", "runt blob (0x%x/%zd) slot %d in CSSM_LIST", + blob->magic(), blob->length(), n); + CssmError::throwMe(CSSM_ERRCODE_INVALID_ACL_SUBJECT_VALUE); + } else if (blob->length() != list[n].data().length()) { + secdebug("csblob", "badly sized blob (0x%x/%zd) slot %d in CSSM_LIST", + blob->magic(), blob->length(), n); + CssmError::throwMe(CSSM_ERRCODE_INVALID_ACL_SUBJECT_VALUE); + } + subj->add(blob); + } else + CssmError::throwMe(CSSM_ERRCODE_INVALID_ACL_SUBJECT_VALUE); + } + return subj; + } else + CssmError::throwMe(CSSM_ERRCODE_INVALID_ACL_SUBJECT_VALUE); +} + +CodeSignatureAclSubject *CodeSignatureAclSubject::Maker::make(Version version, + Reader &pub, Reader &priv) const +{ + assert(version == 0); + Endian sigType; pub(sigType); + const void *data; size_t length; pub.countedData(data, length); + const void *commentData; size_t commentLength; pub.countedData(commentData, commentLength); + if (sigType == CSSM_ACL_CODE_SIGNATURE_OSX + && length == SHA1::digestLength) { + return make((const SHA1::Byte *)data, CssmData::wrap(commentData, commentLength)); + } + CssmError::throwMe(CSSM_ERRCODE_INVALID_ACL_SUBJECT_VALUE); +} + +CodeSignatureAclSubject *CodeSignatureAclSubject::Maker::make(const SHA1::Byte *hash, + const CssmData &commentBag) const +{ + using namespace LowLevelMemoryUtilities; + const char *path = commentBag.interpretedAs(); + CodeSignatureAclSubject *subj = new CodeSignatureAclSubject(hash, path); + for (const BlobCore *blob = increment(commentBag.data(), alignUp(strlen(path) + 1, commentBagAlignment)); + blob < commentBag.end(); + blob = increment(blob, alignUp(blob->length(), commentBagAlignment))) { + size_t leftInBag = difference(commentBag.end(), blob); + if (leftInBag < sizeof(BlobCore) || blob->length() < sizeof(BlobCore) || blob->length() > leftInBag) { + secdebug("csblob", "invalid blob (0x%x/%zd) [%zd in bag] in code signing ACL for %s - stopping scan", + blob->magic(), blob->length(), leftInBag, subj->path().c_str()); + break; // can't trust anything beyond this blob + } + subj->add(blob); + } + return subj; +} + + +// +// Export the subject to a memory blob +// +void CodeSignatureAclSubject::exportBlob(Writer::Counter &pub, Writer::Counter &priv) +{ + using LowLevelMemoryUtilities::alignUp; + assert(path().find('\0') == string::npos); // no embedded nulls in path + Endian sigType = CSSM_ACL_CODE_SIGNATURE_OSX; pub(sigType); + pub.countedData(legacyHash(), SHA1::digestLength); + size_t size = path().size() + 1; + if (requirement()) { + CFRef reqData; + MacOSError::check(SecRequirementCopyData(requirement(), kSecCSDefaultFlags, &reqData.aref())); + size = alignUp(size, commentBagAlignment) + CFDataGetLength(reqData); + } + for (AuxMap::const_iterator it = beginAux(); it != endAux(); it++) { + size = alignUp(size, commentBagAlignment) + it->second->length(); + } + pub.countedData(NULL, size); +} + +void CodeSignatureAclSubject::exportBlob(Writer &pub, Writer &priv) +{ + using LowLevelMemoryUtilities::alignUp; + Endian sigType = CSSM_ACL_CODE_SIGNATURE_OSX; pub(sigType); + pub.countedData(legacyHash(), SHA1::digestLength); + CssmAutoData commentBag(Allocator::standard(), path().c_str(), path().size() + 1); + static const uint32_t zero = 0; + if (requirement()) { + CFRef reqData; + MacOSError::check(SecRequirementCopyData(requirement(), kSecCSDefaultFlags, &reqData.aref())); + commentBag.append(&zero, + alignUp(commentBag.length(), commentBagAlignment) - commentBag.length()); + commentBag.append(CFDataGetBytePtr(reqData), CFDataGetLength(reqData)); + } + for (AuxMap::const_iterator it = beginAux(); it != endAux(); it++) { + commentBag.append(&zero, + alignUp(commentBag.length(), commentBagAlignment) - commentBag.length()); + commentBag.append(CssmData(*it->second)); + } + pub.countedData(commentBag); +} + + +#ifdef DEBUGDUMP + +void CodeSignatureAclSubject::debugDump() const +{ + Debug::dump("CodeSigning "); + OSXVerifier::dump(); +} + +#endif //DEBUGDUMP diff --git a/libsecurity_cdsa_utilities/lib/acl_codesigning.h b/libsecurity_cdsa_utilities/lib/acl_codesigning.h new file mode 100644 index 00000000..552f5f54 --- /dev/null +++ b/libsecurity_cdsa_utilities/lib/acl_codesigning.h @@ -0,0 +1,95 @@ +/* + * 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@ + */ + + +// +// acl_codesigning - ACL subject for signature of calling application +// +// Note: +// Once upon a time, a code signature was a single binary blob, a "signature". +// Then we added an optional second blob, a "comment". The comment was only +// ancilliary (non-security) data first, but then we added more security data +// to it later. Now, the security-relevant data is kept in a (signature, comment) +// pair, all of which is relevant for the security of such subjects. +// Don't read any particular semantics into this separation. It is historical only +// (having to do with backward binary compatibility of ACL blobs). +// +#ifndef _H_ACL_CODESIGNING +#define _H_ACL_CODESIGNING + +#include +#include +#include + +namespace Security { + + +// +// The CodeSignature subject type matches a code signature applied to the +// disk image that originated the client process. +// +class CodeSignatureAclSubject : public AclSubject, public OSXVerifier { +public: + class Maker; friend class Maker; + + static const size_t commentBagAlignment = 4; + + CodeSignatureAclSubject(const SHA1::Byte *hash, const std::string &path) + : AclSubject(CSSM_ACL_SUBJECT_TYPE_CODE_SIGNATURE), OSXVerifier(hash, path) { } + + CodeSignatureAclSubject(const OSXVerifier &verifier) + : AclSubject(CSSM_ACL_SUBJECT_TYPE_CODE_SIGNATURE), OSXVerifier(verifier) { } + + bool validate(const AclValidationContext &baseCtx) const; + CssmList toList(Allocator &alloc) const; + + void exportBlob(Writer::Counter &pub, Writer::Counter &priv); + void exportBlob(Writer &pub, Writer &priv); + + IFDUMP(void debugDump() const); + +public: + class Environment : public virtual AclValidationEnvironment { + public: + virtual bool verifyCodeSignature(const OSXVerifier &verifier, + const AclValidationContext &context) = 0; + }; + +public: + class Maker : public AclSubject::Maker { + public: + Maker() + : AclSubject::Maker(CSSM_ACL_SUBJECT_TYPE_CODE_SIGNATURE) { } + CodeSignatureAclSubject *make(const TypedList &list) const; + CodeSignatureAclSubject *make(Version version, Reader &pub, Reader &priv) const; + + private: + CodeSignatureAclSubject *make(const SHA1::Byte *hash, const CssmData &commentBag) const; + }; +}; + +} // end namespace Security + + + +#endif //_H_ACL_CODESIGNING diff --git a/libsecurity_cdsa_utilities/lib/acl_comment.cpp b/libsecurity_cdsa_utilities/lib/acl_comment.cpp new file mode 100644 index 00000000..6a5ab718 --- /dev/null +++ b/libsecurity_cdsa_utilities/lib/acl_comment.cpp @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2000-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@ + */ + + +// +// acl_comment - "ignore" ACL subject type. +// +// CommentAclSubjects were a bad idea, badly implemented. The code below +// exists solely to keep existing (external) ACL forms from blowing up the +// ACL reader machinery and crashing the evaluation host. +// The original serialization code was not architecture independent - for either +// pointer sizes(!) or byte ordering. Yes, that was a stupid mistake. +// The following code is intentionally, wilfully violating the layer separation +// of the ACL reader/writer machine to deduce enough information about the +// originating architecture to cleanly consume (just) the bytes making up this +// ACL's external representation. We make no use of the bytes read; thankfully, +// the semantics of a CommentAclSubject have always been "never matches." +// We do not preserve them on write-out; a newly-written ACL will contain no data +// (and will read cleanly). +// If you use this code as a template for anything (other than a how-not-to-write-code +// seminar), your backups shall rot right after your main harddrive crashes, and +// you have only yourself to blame. +// +#include +#include +#include +#include + +using namespace DataWalkers; + + +// +// The COMMENT subject matches nothing, no matter how pretty. +// +bool CommentAclSubject::validate(const AclValidationContext &) const +{ + return false; +} + + +// +// The list form has no values. +// +CssmList CommentAclSubject::toList(Allocator &alloc) const +{ + return TypedList(Allocator::standard(), CSSM_ACL_SUBJECT_TYPE_COMMENT); +} + + +// +// We completely disregard any data contained in CSSM form COMMENT ACLs. +// +CommentAclSubject *CommentAclSubject::Maker::make(const TypedList &list) const +{ + return new CommentAclSubject(); +} + + +// +// This is the nasty code. We don't really care what data was originally baked +// into this ACL's external (stream) form, but since there's no external framing +// to delimit it, we need to figure out how many bytes to consume to keep the +// reader from going out of sync. And that's not pretty, since the external form +// contains (stupidly!) a pointer, so we have all permutations of byte order and +// pointer size to worry about. +// +CommentAclSubject *CommentAclSubject::Maker::make(Version, Reader &pub, Reader &) const +{ + // + // At this point, the Reader is positioned at data that was once written using + // this code: + // pub(ptr); // yes, that's a pointer + // pub.countedData(ptr, size); + // We know ptr was a non-NULL pointer (4 or 8 bytes, alas). + // CountedData writes a 4-byte NBO length followed by that many bytes. + // The data written starts with a CSSM_LIST structure in native architecture. + // That in turn begins with a CSSM_LIST_TYPE (4 bytes, native, 0<=type<=2). + // So to summarize (h=host byte order, n=network byte order), we might be looking at: + // 32 bits: | P4h | L4n | T4h | (L-4 bytes) | + // 64 bits: | P8h | L4n | (L bytes) | + // It's the T4h-or-L4n bytes that save our day, since we know that + // 0 <= T <= 2 (definition of CSSM_LIST_TYPE) + // 16M > L >= sizeof(CSSM_LIST) >= 12 + // Phew. I'd rather be lucky than good... + // + // So let's get started: + static const size_t minCssmList = 12; // min(sizeof(CSSM_LIST)) of all architectures + pub.get(4); // skip first 4 bytes + uint32_t lop; pub(lop); // read L4n-or-(bottom of)P8h + uint32_t tol; pub(tol); // read T4h-or-L4n + if (tol <= 2 || flip(tol) <= 2) { // 32 bits + // the latter can't be a very big (flipped) L because we know 12 < L < 16M, + // and you'd have to be a multiple of 2^24 to pass that test + size_t length = n2h(lop); + assert(length >= minCssmList); + pub.get(length - sizeof(tol)); // skip L-4 bytes + } else { // 64 bits + size_t length = n2h(tol); + assert(length >= minCssmList); + pub.get(length); // skip L bytes + } + + // we've successfully thrown out the garbage. What's left is a data-less subject + return new CommentAclSubject(); // no data +} + + +// +// Export to blob form. +// This simply writes the smallest form consistent with the heuristic above. +// +void CommentAclSubject::exportBlob(Writer::Counter &pub, Writer::Counter &) +{ + uint32_t zero = 0; + Endian length = 12; + pub(zero); pub(length); pub(zero); pub(zero); pub(zero); +} + +void CommentAclSubject::exportBlob(Writer &pub, Writer &) +{ + uint32_t zero = 0; + Endian length = 12; + pub(zero); pub(length); pub(zero); pub(zero); pub(zero); +} + + +#ifdef DEBUGDUMP + +void CommentAclSubject::debugDump() const +{ + Debug::dump("Comment[never]"); +} + +#endif //DEBUGDUMP diff --git a/libsecurity_cdsa_utilities/lib/acl_comment.h b/libsecurity_cdsa_utilities/lib/acl_comment.h new file mode 100644 index 00000000..3a3c6344 --- /dev/null +++ b/libsecurity_cdsa_utilities/lib/acl_comment.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2000-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@ + */ + + +// +// acl_comment - "ignore" ACL subject type +// +// This ACL subject is a historical mistake. It has no use in present applications, +// and remains only to support existing keychains with their already-baked item ACLs. +// Do not use this for new applications of ANY kind. +// +// A CommentAclSubject always fails to verify. +// See further (mis-)usage comments in the .cpp. +// +#ifndef _ACL_COMMENT +#define _ACL_COMMENT + +#include + + +namespace Security +{ + +// +// The ANY subject simply matches everything. No sweat. +// +class CommentAclSubject : public AclSubject { +public: + CommentAclSubject() + : AclSubject(CSSM_ACL_SUBJECT_TYPE_COMMENT) { } + + bool validate(const AclValidationContext &ctx) const; + CssmList toList(Allocator &alloc) const; + + void exportBlob(Writer::Counter &pub, Writer::Counter &priv); + void exportBlob(Writer &pub, Writer &priv); + + class Maker : public AclSubject::Maker { + public: + Maker() : AclSubject::Maker(CSSM_ACL_SUBJECT_TYPE_COMMENT) { } + CommentAclSubject *make(const TypedList &list) const; + CommentAclSubject *make(Version, Reader &pub, Reader &priv) const; + }; + + IFDUMP(void debugDump() const); +}; + +} // end namespace Security + + +#endif //_ACL_COMMENT diff --git a/libsecurity_cdsa_utilities/lib/acl_password.cpp b/libsecurity_cdsa_utilities/lib/acl_password.cpp new file mode 100644 index 00000000..8e6d3fda --- /dev/null +++ b/libsecurity_cdsa_utilities/lib/acl_password.cpp @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2000-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@ + */ + + +// +// acl_password - password-based ACL subject types +// +#include +#include +#include +#include + + +// +// PasswordAclSubject always pre-loads its secret, and thus never has to +// "get" its secret. If we ever try, it's a bug. +// +bool PasswordAclSubject::getSecret(const AclValidationContext &context, + const TypedList &sample, CssmOwnedData &secret) const +{ + switch (sample.length()) { + case 1: + return false; // no password in sample + case 2: + secret = sample[1]; + return true; + default: + CssmError::throwMe(CSSM_ERRCODE_INVALID_SAMPLE_VALUE); + } +} + + +// +// Make a copy of this subject in CSSM_LIST form +// +CssmList PasswordAclSubject::toList(Allocator &alloc) const +{ + // the password itself is private and not exported to CSSM + return TypedList(alloc, CSSM_ACL_SUBJECT_TYPE_PASSWORD); +} + + +// +// Create a PasswordAclSubject +// +PasswordAclSubject *PasswordAclSubject::Maker::make(const TypedList &list) const +{ + Allocator &alloc = Allocator::standard(Allocator::sensitive); + switch (list.length()) { + case 1: + return new PasswordAclSubject(alloc, true); + case 2: + { + ListElement *password; + crack(list, 1, &password, CSSM_LIST_ELEMENT_DATUM); + return new PasswordAclSubject(alloc, password->data()); + } + default: + CssmError::throwMe(CSSM_ERRCODE_INVALID_ACL_SUBJECT_VALUE); + } +} + +PasswordAclSubject *PasswordAclSubject::Maker::make(Version, Reader &pub, Reader &priv) const +{ + Allocator &alloc = Allocator::standard(Allocator::sensitive); + const void *data; size_t length; priv.countedData(data, length); + CssmAutoData passwordData(alloc, data, length); + return new PasswordAclSubject(alloc, passwordData); +} + + +// +// Export the subject to a memory blob +// +void PasswordAclSubject::exportBlob(Writer::Counter &pub, Writer::Counter &priv) +{ + priv.countedData(secret()); +} + +void PasswordAclSubject::exportBlob(Writer &pub, Writer &priv) +{ + priv.countedData(secret()); +} + + +#ifdef DEBUGDUMP + +void PasswordAclSubject::debugDump() const +{ + Debug::dump("Password"); + SecretAclSubject::debugDump(); +} + +#endif //DEBUGDUMP diff --git a/libsecurity_cdsa_utilities/lib/acl_password.h b/libsecurity_cdsa_utilities/lib/acl_password.h new file mode 100644 index 00000000..83444866 --- /dev/null +++ b/libsecurity_cdsa_utilities/lib/acl_password.h @@ -0,0 +1,75 @@ +/* + * 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@ + */ + + +// +// acl_password - password-based ACL subject types. +// +// This implements simple password-based subject types as per CSSM standard. +// +#ifndef _ACL_PASSWORD +#define _ACL_PASSWORD + +#include + + +namespace Security { + + +// +// A PasswordAclSubject simply contains its secret. +// The environment is never consulted; we just compare against our known secret. +// +class PasswordAclSubject : public SecretAclSubject { +public: + CssmList toList(Allocator &alloc) const; + + PasswordAclSubject(Allocator &alloc, const CssmData &password) + : SecretAclSubject(alloc, CSSM_ACL_SUBJECT_TYPE_PASSWORD, password) { } + PasswordAclSubject(Allocator &alloc, CssmManagedData &password) + : SecretAclSubject(alloc, CSSM_ACL_SUBJECT_TYPE_PASSWORD, password) { } + PasswordAclSubject(Allocator &alloc, bool cache) + : SecretAclSubject(alloc, CSSM_ACL_SUBJECT_TYPE_PASSWORD, cache) { } + + void exportBlob(Writer::Counter &pub, Writer::Counter &priv); + void exportBlob(Writer &pub, Writer &priv); + + IFDUMP(void debugDump() const); + +public: + class Maker : public SecretAclSubject::Maker { + public: + Maker() : SecretAclSubject::Maker(CSSM_ACL_SUBJECT_TYPE_PASSWORD) { } + PasswordAclSubject *make(const TypedList &list) const; + PasswordAclSubject *make(Version, Reader &pub, Reader &priv) const; + }; + +protected: + bool getSecret(const AclValidationContext &context, + const TypedList &subject, CssmOwnedData &secret) const; +}; + +} // end namespace Security + + +#endif //_ACL_PASSWORD diff --git a/libsecurity_cdsa_utilities/lib/acl_preauth.cpp b/libsecurity_cdsa_utilities/lib/acl_preauth.cpp new file mode 100644 index 00000000..86ad36e2 --- /dev/null +++ b/libsecurity_cdsa_utilities/lib/acl_preauth.cpp @@ -0,0 +1,238 @@ +/* + * 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@ + */ + + +// +// acl_preauth - a subject type for modeling PINs and similar slot-specific +// pre-authentication schemes. +// +#include "acl_preauth.h" +#include + + +namespace Security { +namespace PreAuthorizationAcls { + + +// +// Origin forms +// +AclSubject *OriginMaker::make(const TypedList &list) const +{ + ListElement *args[1]; + crack(list, 1, args, CSSM_LIST_ELEMENT_WORDID); + return new OriginAclSubject(*args[0]); +} + +AclSubject *OriginMaker::make(AclSubject::Version version, Reader &pub, Reader &) const +{ + // just an integer containing the auth tag + Endian auth; + pub(auth); + return new OriginAclSubject(AclAuthorization(auth)); +} + + +// +// Validate the origin form. +// This tries to find the source AclObject and hands the question off to it. +// If anything isn't right, fail the validation. +// +bool OriginAclSubject::validate(const AclValidationContext &ctx) const +{ + if (Environment *env = ctx.environment()) + if (ObjectAcl *source = env->preAuthSource()) + if (source->validates(mAuthTag, ctx.cred(), ctx.environment())) + return true; + + // no joy (the sad default) + return false; +} + + +CssmList OriginAclSubject::toList(Allocator &alloc) const +{ + return TypedList(alloc, CSSM_ACL_SUBJECT_TYPE_PREAUTH, + new(alloc) ListElement(mAuthTag)); +} + +OriginAclSubject::OriginAclSubject(AclAuthorization auth) + : AclSubject(CSSM_ACL_SUBJECT_TYPE_PREAUTH), mAuthTag(auth) +{ + if (auth < CSSM_ACL_AUTHORIZATION_PREAUTH_BASE || auth >= CSSM_ACL_AUTHORIZATION_PREAUTH_END) + CssmError::throwMe(CSSM_ERRCODE_INVALID_ACL_SUBJECT_VALUE); +} + + +// +// Origin exported form is just a four-byte integer (preauth authorization tag) +// +void OriginAclSubject::exportBlob(Writer::Counter &pub, Writer::Counter &priv) +{ + Endian auth = mAuthTag; + pub(auth); +} + +void OriginAclSubject::exportBlob(Writer &pub, Writer &priv) +{ + Endian auth = mAuthTag; + pub(auth); +} + + +// +// Now for the other side of the coin. +// SourceAclSubjects describe the unusual side (for ACL management) of this game. +// The AclSubject of a preauth source MUST be of PREAUTH_SOURCE type. This subject +// contains the actual validation conditions as a sub-subject, and may provide +// additional information to represent known state of the preauth system. +// +// Think of the extra data in a PreAuthSource ACL as "current state informational" +// that only exists internally, and in the CssmList view. It does not get put into +// persistent (externalized) ACL storage at all. (After all, there's nothing persistent +// about it.) +// +AclSubject *SourceMaker::make(const TypedList &list) const +{ + // minimum requirement: item[1] = sub-subject (sublist) + if (list.length() < 2) + CssmError::throwMe(CSSM_ERRCODE_INVALID_ACL_SUBJECT_VALUE); + ListElement &sub = list[1]; + RefPointer subSubject = ObjectAcl::make(sub); + + // anything else is interpreted as tracking state (defaulted if missing) + switch (list.length()) { + case 2: // no tracking state + return new SourceAclSubject(subSubject); + case 3: + if (list[2].type() == CSSM_LIST_ELEMENT_WORDID) + return new SourceAclSubject(subSubject, list[2]); + // fall through + default: + CssmError::throwMe(CSSM_ERRCODE_INVALID_ACL_SUBJECT_VALUE); + } +} + +AclSubject *SourceMaker::make(AclSubject::Version version, Reader &pub, Reader &priv) const +{ + // external form does not contain tracking state - defaults to unknown + RefPointer subSubject = ObjectAcl::importSubject(pub, priv); + return new SourceAclSubject(subSubject); +} + + +// +// Source validation uses its own home-cooked validation context. +// +class SourceValidationContext : public AclValidationContext { +public: + SourceValidationContext(const AclValidationContext &base) + : AclValidationContext(base), mCredTag(base.entryTag()) { } + + uint32 count() const { return cred() ? cred()->samples().length() : 0; } + uint32 size() const { return count(); } + const TypedList &sample(uint32 n) const + { assert(n < count()); return cred()->samples()[n]; } + + const char *credTag() const { return mCredTag; } // override + + void matched(const TypedList *) const { } //@@@ prelim + +private: + const char *mCredTag; +}; + +bool SourceAclSubject::SourceAclSubject::validate(const AclValidationContext &baseCtx) const +{ + // try to authenticate our sub-subject + if (Environment *env = baseCtx.environment()) { + AclAuthorization auth = baseCtx.authorization(); + if (!CSSM_ACL_AUTHORIZATION_IS_PREAUTH(auth)) // all muddled up; bail + CssmError::throwMe(CSSM_ERRCODE_INVALID_ACL_SUBJECT_VALUE); + uint32 slot = CSSM_ACL_AUTHORIZATION_PREAUTH_SLOT(auth); + secdebug("preauth", "using state %d@%p", slot, &env->store(this)); + bool &accepted = env->store(this).attachment((void *)slot).accepted; + if (!accepted) { + secdebug("preauth", "%p needs to authenticate its subject", this); + SourceValidationContext ctx(baseCtx); + if (mSourceSubject->validate(ctx)) { + secdebug("preauth", "%p pre-authenticated", this); + accepted = true; + } + } + return accepted; + } + return false; +} + + +CssmList SourceAclSubject::toList(Allocator &alloc) const +{ + return TypedList(alloc, CSSM_ACL_SUBJECT_TYPE_PREAUTH_SOURCE, + new(alloc) ListElement(mSourceSubject->toList(alloc))); +} + + +SourceAclSubject::SourceAclSubject(AclSubject *subSubject, CSSM_ACL_PREAUTH_TRACKING_STATE state) + : AclSubject(CSSM_ACL_SUBJECT_TYPE_PREAUTH), + mSourceSubject(subSubject) +{ +} + + +// +// Export the subject to a memory blob +// +void SourceAclSubject::exportBlob(Writer::Counter &pub, Writer::Counter &priv) +{ + mSourceSubject->exportBlob(pub, priv); +} + +void SourceAclSubject::exportBlob(Writer &pub, Writer &priv) +{ + mSourceSubject->exportBlob(pub, priv); + // tracking state is not exported +} + + +#ifdef DEBUGDUMP + +void OriginAclSubject::debugDump() const +{ + Debug::dump("Preauth(to slot %d)", mAuthTag - CSSM_ACL_AUTHORIZATION_PREAUTH_BASE); +} + +void SourceAclSubject::debugDump() const +{ + Debug::dump("Preauth source: "); + if (mSourceSubject) + mSourceSubject->debugDump(); + else + Debug::dump("NULL?"); +} + +#endif //DEBUGDUMP + + +} // namespace PreAuthorizationAcls +} // namespace Security diff --git a/libsecurity_cdsa_utilities/lib/acl_preauth.h b/libsecurity_cdsa_utilities/lib/acl_preauth.h new file mode 100644 index 00000000..4f84bc6f --- /dev/null +++ b/libsecurity_cdsa_utilities/lib/acl_preauth.h @@ -0,0 +1,132 @@ +/* + * Copyright (c) 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@ + */ + + +// +// acl_preauth - a subject type for modeling PINs and similar slot-specific +// pre-authentication schemes. +// +#ifndef _ACL_PREAUTH +#define _ACL_PREAUTH + +#include +#include + + +namespace Security { +namespace PreAuthorizationAcls { + + +class OriginMaker : public AclSubject::Maker { +protected: + typedef LowLevelMemoryUtilities::Reader Reader; + typedef LowLevelMemoryUtilities::Writer Writer; +public: + OriginMaker() : AclSubject::Maker(CSSM_ACL_SUBJECT_TYPE_PREAUTH) { } + AclSubject *make(const TypedList &list) const; + AclSubject *make(AclSubject::Version version, Reader &pub, Reader &priv) const; +}; + +class SourceMaker : public AclSubject::Maker { +protected: + typedef LowLevelMemoryUtilities::Reader Reader; + typedef LowLevelMemoryUtilities::Writer Writer; +public: + SourceMaker() : AclSubject::Maker(CSSM_ACL_SUBJECT_TYPE_PREAUTH_SOURCE) { } + AclSubject *make(const TypedList &list) const; + AclSubject *make(AclSubject::Version version, Reader &pub, Reader &priv) const; +}; + + +// +// The actual designation of the PreAuth source AclBearer is provide by the environment. +// +class Environment : public virtual AclValidationEnvironment { +public: + virtual ObjectAcl *preAuthSource() = 0; +}; + + +// +// This is the object that is being "attached" (as an Adornment) to hold +// the pre-authorization state of a SourceAclSubject. +// The Adornable used for storage is determined by the Environment's store() method. +// +struct AclState { + AclState() : accepted(false) { } + bool accepted; // was previously accepted by upstream +}; + + +// +// This is the "origin" subject class that gets created the usual way. +// It models a pre-auth "origin" - i.e. it points at a preauth slot and accepts +// its verdict on validation. Think of it as the "come from" part of the link. +// +class OriginAclSubject : public AclSubject { +public: + bool validate(const AclValidationContext &ctx) const; + CssmList toList(Allocator &alloc) const; + + OriginAclSubject(AclAuthorization auth); + + void exportBlob(Writer::Counter &pub, Writer::Counter &priv); + void exportBlob(Writer &pub, Writer &priv); + + IFDUMP(void debugDump() const); + +private: + AclAuthorization mAuthTag; // authorization tag referred to (origin only) +}; + + +// +// The "source" subject class describes the other end of the link; the "go to" part +// if you will. Its sourceSubject is consulted for actual validation; and prior validation +// state is remembered (through the environment store facility) so that future validation +// attempts will automaticaly succeed (that's the "pre" in PreAuth). +// +class SourceAclSubject : public AclSubject { +public: + bool validate(const AclValidationContext &ctx) const; + CssmList toList(Allocator &alloc) const; + + SourceAclSubject(AclSubject *subSubject, + CSSM_ACL_PREAUTH_TRACKING_STATE state = CSSM_ACL_PREAUTH_TRACKING_UNKNOWN); + + void exportBlob(Writer::Counter &pub, Writer::Counter &priv); + void exportBlob(Writer &pub, Writer &priv); + + IFDUMP(void debugDump() const); + +private: + RefPointer mSourceSubject; // subject determining outcome (source only) +}; + + + +} // namespace PreAuthorizationAcls +} // namespace Security + + +#endif //_ACL_PREAUTH diff --git a/libsecurity_cdsa_utilities/lib/acl_process.cpp b/libsecurity_cdsa_utilities/lib/acl_process.cpp new file mode 100644 index 00000000..37a48674 --- /dev/null +++ b/libsecurity_cdsa_utilities/lib/acl_process.cpp @@ -0,0 +1,157 @@ +/* + * 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@ + */ + + +// +// acl_process - Process-attribute ACL subject type. +// +#include +#include +#include + + +// +// Validate a credential set against this subject. +// No credential is required for this match. +// +bool ProcessAclSubject::validate(const AclValidationContext &context) const +{ + // reality check (internal structure was validated when created) + assert(select.uses(CSSM_ACL_MATCH_BITS)); + + // access the environment + Environment *env = context.environment(); + if (env == NULL) { + static Environment localEnvironment; + env = &localEnvironment; + } + + // match uid + if (select.uses(CSSM_ACL_MATCH_UID)) { + uid_t uid = env->getuid(); + if (!(uid == select.uid || (select.uses(CSSM_ACL_MATCH_HONOR_ROOT) && uid == 0))) + return false; + } + + // match gid + if (select.uses(CSSM_ACL_MATCH_GID) && select.gid != env->getgid()) + return false; + + return true; +} + + +// +// Make a copy of this subject in CSSM_LIST form +// +CssmList ProcessAclSubject::toList(Allocator &alloc) const +{ + // all associated data is public (no secrets) + //@@@ ownership of selector data is murky; revisit after leak-plugging pass + CssmData sData(memcpy(alloc.alloc(), + &select, sizeof(select)), sizeof(select)); + return TypedList(alloc, CSSM_ACL_SUBJECT_TYPE_PROCESS, + new(alloc) ListElement(sData)); +} + + +// +// Create a ProcessAclSubject +// +ProcessAclSubject *ProcessAclSubject::Maker::make(const TypedList &list) const +{ + // crack input apart + ListElement *selectorData; + crack(list, 1, &selectorData, CSSM_LIST_ELEMENT_DATUM); + AclProcessSubjectSelector selector; + selectorData->extract(selector); + + // validate input + if (selector.version != CSSM_ACL_PROCESS_SELECTOR_CURRENT_VERSION) + CssmError::throwMe(CSSM_ERRCODE_INVALID_ACL_SUBJECT_VALUE); + if (!selector.uses(CSSM_ACL_MATCH_BITS)) + CssmError::throwMe(CSSM_ERRCODE_INVALID_ACL_SUBJECT_VALUE); + + // okay + return new ProcessAclSubject(selector); +} + +ProcessAclSubject *ProcessAclSubject::Maker::make(Version, Reader &pub, Reader &priv) const +{ + AclProcessSubjectSelector selector; pub(selector); + n2hi(selector.version); + n2hi(selector.mask); + n2hi(selector.uid); + n2hi(selector.gid); + return new ProcessAclSubject(selector); +} + + +// +// Export the subject to a memory blob +// +void ProcessAclSubject::exportBlob(Writer::Counter &pub, Writer::Counter &priv) +{ + pub(select); +} + +void ProcessAclSubject::exportBlob(Writer &pub, Writer &priv) +{ + AclProcessSubjectSelector temp; + temp.version = h2n (select.version); + temp.mask = h2n (select.mask); + temp.uid = h2n (select.uid); + temp.gid = h2n (select.gid); + pub(temp); +} + + +// +// Implement the default methods of a ProcessEnvironment +// +uid_t ProcessAclSubject::Environment::getuid() const +{ + return ::getuid(); +} + +gid_t ProcessAclSubject::Environment::getgid() const +{ + return ::getgid(); +} + + +#ifdef DEBUGDUMP + +void ProcessAclSubject::debugDump() const +{ + Debug::dump("Process "); + if (select.uses(CSSM_ACL_MATCH_UID)) { + Debug::dump("uid=%d", int(select.uid)); + if (select.uses(CSSM_ACL_MATCH_HONOR_ROOT)) + Debug::dump("+root"); + } + if (select.uses(CSSM_ACL_MATCH_GID)) + Debug::dump("gid=%d", int(select.gid)); +} + +#endif //DEBUGDUMP diff --git a/libsecurity_cdsa_utilities/lib/acl_process.h b/libsecurity_cdsa_utilities/lib/acl_process.h new file mode 100644 index 00000000..f34c67ca --- /dev/null +++ b/libsecurity_cdsa_utilities/lib/acl_process.h @@ -0,0 +1,93 @@ +/* + * 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@ + */ + + +// +// acl_process - Process-attribute ACL subject type. +// +// NOTE: +// The default Environment provides data about the current process (the one that +// validate() is run in). If this isn't right for you (e.g. because you want to +// validate against a process on the other side of some IPC connection), you must +// make your own version of Environment and pass it to validate(). +// +#ifndef _ACL_PROCESS +#define _ACL_PROCESS + +#include +#include + +namespace Security +{ + +class AclProcessSubjectSelector + : public PodWrapper { +public: + AclProcessSubjectSelector() + { version = CSSM_ACL_PROCESS_SELECTOR_CURRENT_VERSION; mask = 0; } + + bool uses(uint32 m) const { return mask & m; } +}; + + +// +// The ProcessAclSubject matches process attributes securely identified +// by the system across IPC channels. +// +class ProcessAclSubject : public AclSubject { +public: + bool validate(const AclValidationContext &baseCtx) const; + CssmList toList(Allocator &alloc) const; + + ProcessAclSubject(const AclProcessSubjectSelector &selector) + : AclSubject(CSSM_ACL_SUBJECT_TYPE_PROCESS), + select(selector) { } + + void exportBlob(Writer::Counter &pub, Writer::Counter &priv); + void exportBlob(Writer &pub, Writer &priv); + + IFDUMP(void debugDump() const); + +public: + class Environment : public virtual AclValidationEnvironment { + public: + virtual uid_t getuid() const; // retrieve effective userid to match + virtual gid_t getgid() const; // retrieve effective groupid to match + }; + +public: + class Maker : public AclSubject::Maker { + public: + Maker() : AclSubject::Maker(CSSM_ACL_SUBJECT_TYPE_PROCESS) { } + ProcessAclSubject *make(const TypedList &list) const; + ProcessAclSubject *make(Version, Reader &pub, Reader &priv) const; + }; + +private: + AclProcessSubjectSelector select; +}; + +} // end namespace Security + + +#endif //_ACL_PROCESS diff --git a/libsecurity_cdsa_utilities/lib/acl_prompted.cpp b/libsecurity_cdsa_utilities/lib/acl_prompted.cpp new file mode 100644 index 00000000..15496a3c --- /dev/null +++ b/libsecurity_cdsa_utilities/lib/acl_prompted.cpp @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2000-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@ + */ + + +// +// acl_prompted - password-based validation with out-of-band prompting. +// +#include +#include +#include +#include + + +// +// Construct PromptedAclSubjects from prompts and optional data +// +PromptedAclSubject::PromptedAclSubject(Allocator &alloc, + const CssmData &prompt, const CssmData &password) + : SecretAclSubject(alloc, CSSM_ACL_SUBJECT_TYPE_PROMPTED_PASSWORD, password), + mPrompt(alloc, prompt) { } +PromptedAclSubject::PromptedAclSubject(Allocator &alloc, + CssmManagedData &prompt, CssmManagedData &password) + : SecretAclSubject(alloc, CSSM_ACL_SUBJECT_TYPE_PROMPTED_PASSWORD, password), + mPrompt(alloc, prompt) { } +PromptedAclSubject::PromptedAclSubject(Allocator &alloc, + const CssmData &prompt, bool cache) + : SecretAclSubject(alloc, CSSM_ACL_SUBJECT_TYPE_PROMPTED_PASSWORD, cache), + mPrompt(alloc, prompt) { } + + +// +// PromptedAclSubject will prompt for the secret +// +bool PromptedAclSubject::getSecret(const AclValidationContext &context, + const TypedList &subject, CssmOwnedData &secret) const +{ + if (Environment *env = context.environment()) { + return env->getSecret(secret, mPrompt); + } else { + return false; + } +} + + +// +// Make a copy of this subject in CSSM_LIST form +// +CssmList PromptedAclSubject::toList(Allocator &alloc) const +{ + // the password itself is private and not exported to CSSM + return TypedList(alloc, CSSM_ACL_SUBJECT_TYPE_PROMPTED_PASSWORD, + new(alloc) ListElement(alloc, mPrompt)); +} + + +// +// Create a PromptedAclSubject +// +PromptedAclSubject *PromptedAclSubject::Maker::make(const TypedList &list) const +{ + Allocator &alloc = Allocator::standard(Allocator::sensitive); + switch (list.length()) { + case 2: + { + ListElement *elem[1]; + crack(list, 1, elem, CSSM_LIST_ELEMENT_DATUM); + return new PromptedAclSubject(alloc, elem[0]->data(), true); + } + case 3: + { + ListElement *elem[2]; + crack(list, 2, elem, CSSM_LIST_ELEMENT_DATUM, CSSM_LIST_ELEMENT_DATUM); + return new PromptedAclSubject(alloc, elem[0]->data(), elem[1]->data()); + } + default: + CssmError::throwMe(CSSM_ERRCODE_INVALID_ACL_SUBJECT_VALUE); + } +} + +PromptedAclSubject *PromptedAclSubject::Maker::make(Version, Reader &pub, Reader &priv) const +{ + Allocator &alloc = Allocator::standard(Allocator::sensitive); + const void *data; size_t length; priv.countedData(data, length); + return new PromptedAclSubject(alloc, CssmAutoData(alloc, data, length), true); +} + + +// +// Export the subject to a memory blob +// +void PromptedAclSubject::exportBlob(Writer::Counter &pub, Writer::Counter &priv) +{ + pub.countedData(mPrompt); +} + +void PromptedAclSubject::exportBlob(Writer &pub, Writer &priv) +{ + pub.countedData(mPrompt); +} + + +#ifdef DEBUGDUMP + +void PromptedAclSubject::debugDump() const +{ + Debug::dump("Prompted-Password"); + SecretAclSubject::debugDump(); +} + +#endif //DEBUGDUMP diff --git a/libsecurity_cdsa_utilities/lib/acl_prompted.h b/libsecurity_cdsa_utilities/lib/acl_prompted.h new file mode 100644 index 00000000..26b47f96 --- /dev/null +++ b/libsecurity_cdsa_utilities/lib/acl_prompted.h @@ -0,0 +1,85 @@ +/* + * 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@ + */ + + +// +// acl_prompted - password-based validation with out-of-band prompting. +// +// This implements simple password-based subject types with out-of-band +// prompting (via SecurityAgent), somewhat as per the CSSM standard. +// +#ifndef _ACL_PROMPTED +#define _ACL_PROMPTED + +#include + + +namespace Security { + + +// +// A PromptedAclSubject obtains its sample by prompting the user interactively +// through some prompting mechanism defined in the environment. +// +class PromptedAclSubject : public SecretAclSubject { +public: + CssmList toList(Allocator &alloc) const; + + PromptedAclSubject(Allocator &alloc, + const CssmData &prompt, const CssmData &password); + PromptedAclSubject(Allocator &alloc, + CssmManagedData &prompt, CssmManagedData &password); + PromptedAclSubject(Allocator &alloc, const CssmData &prompt, bool cache = false); + + void exportBlob(Writer::Counter &pub, Writer::Counter &priv); + void exportBlob(Writer &pub, Writer &priv); + + IFDUMP(void debugDump() const); + +public: + class Environment : virtual public AclValidationEnvironment { + public: + virtual bool getSecret(CssmOwnedData &secret, + const CssmData &prompt) const = 0; + }; + +public: + class Maker : public SecretAclSubject::Maker { + public: + Maker() : SecretAclSubject::Maker(CSSM_ACL_SUBJECT_TYPE_PROMPTED_PASSWORD) { } + PromptedAclSubject *make(const TypedList &list) const; + PromptedAclSubject *make(Version, Reader &pub, Reader &priv) const; + }; + +protected: + bool getSecret(const AclValidationContext &context, + const TypedList &subject, CssmOwnedData &secret) const; + +private: + CssmAutoData mPrompt; // transparently handled prompt data +}; + +} // end namespace Security + + +#endif //_ACL_PROMPTED diff --git a/libsecurity_cdsa_utilities/lib/acl_protectedpw.cpp b/libsecurity_cdsa_utilities/lib/acl_protectedpw.cpp new file mode 100644 index 00000000..7ebff0eb --- /dev/null +++ b/libsecurity_cdsa_utilities/lib/acl_protectedpw.cpp @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2000-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@ + */ + + +// +// acl_protectedpw - protected-path password-based ACL subject types. +// +#include +#include +#include + + +// +// Construct a password ACL subject +// +ProtectedPasswordAclSubject::ProtectedPasswordAclSubject(Allocator &alloc, const CssmData &password) + : SimpleAclSubject(CSSM_ACL_SUBJECT_TYPE_PROTECTED_PASSWORD), + allocator(alloc), mPassword(alloc, password) +{ } + +ProtectedPasswordAclSubject::ProtectedPasswordAclSubject(Allocator &alloc, CssmManagedData &password) + : SimpleAclSubject(CSSM_ACL_SUBJECT_TYPE_PROTECTED_PASSWORD), + allocator(alloc), mPassword(alloc, password) +{ } + + +// +// Validate a credential set against this subject +// +bool ProtectedPasswordAclSubject::validate(const AclValidationContext &context, + const TypedList &sample) const +{ + if (sample.length() == 1) { + return true; //@@@ validate against PP + } else if (sample.length() == 2 && sample[1].type() == CSSM_LIST_ELEMENT_DATUM) { + const CssmData &password = sample[1]; + return password == mPassword; + } else + CssmError::throwMe(CSSM_ERRCODE_INVALID_SAMPLE_VALUE); +} + + +// +// Make a copy of this subject in CSSM_LIST form +// +CssmList ProtectedPasswordAclSubject::toList(Allocator &alloc) const +{ + // the password itself is private and not exported to CSSM + return TypedList(alloc, CSSM_ACL_SUBJECT_TYPE_PROTECTED_PASSWORD); +} + + +// +// Create a ProtectedPasswordAclSubject +// +ProtectedPasswordAclSubject *ProtectedPasswordAclSubject::Maker::make(const TypedList &list) const +{ + CssmAutoData password(Allocator::standard(Allocator::sensitive)); + if (list.length() == 1) { + char pass[] = "secret"; + CssmData password = CssmData::wrap(pass, 6); //@@@ get password from PP + return new ProtectedPasswordAclSubject(Allocator::standard(Allocator::sensitive), password); + } else { + ListElement *password; + crack(list, 1, &password, CSSM_LIST_ELEMENT_DATUM); + return new ProtectedPasswordAclSubject(Allocator::standard(Allocator::sensitive), *password); + } +} + +ProtectedPasswordAclSubject *ProtectedPasswordAclSubject::Maker::make(Version, + Reader &pub, Reader &priv) const +{ + Allocator &alloc = Allocator::standard(Allocator::sensitive); + const void *data; size_t length; priv.countedData(data, length); + return new ProtectedPasswordAclSubject(alloc, CssmAutoData(alloc, data, length)); +} + + +// +// Export the subject to a memory blob +// +void ProtectedPasswordAclSubject::exportBlob(Writer::Counter &pub, Writer::Counter &priv) +{ + priv.countedData(mPassword); +} + +void ProtectedPasswordAclSubject::exportBlob(Writer &pub, Writer &priv) +{ + priv.countedData(mPassword); +} + + +#ifdef DEBUGDUMP + +void ProtectedPasswordAclSubject::debugDump() const +{ + Debug::dump("Protected Password "); + Debug::dumpData(mPassword.data(), mPassword.length()); +} + +#endif //DEBUGDUMP diff --git a/libsecurity_cdsa_utilities/lib/acl_protectedpw.h b/libsecurity_cdsa_utilities/lib/acl_protectedpw.h new file mode 100644 index 00000000..8acf952e --- /dev/null +++ b/libsecurity_cdsa_utilities/lib/acl_protectedpw.h @@ -0,0 +1,75 @@ +/* + * 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@ + */ + + +// +// acl_protectedpw - protected-path password-based ACL subject types. +// +// This implements "protected path" password-based subject types as per CSSM standard. +// A "protected path" is something that is outside the scope of the computer proper, +// like e.g. a PINpad directly attached to a smartcard token. +// Note: A password prompted through securityd/SecurityAgent is a "prompted password", +// not a "protected password". See acl_prompted.h. +// +// @@@ Warning: This is not quite implemented. +// +#ifndef _ACL_PROTECTED_PASSWORD +#define _ACL_PROTECTED_PASSWORD + +#include +#include +#include + + +namespace Security { + +class ProtectedPasswordAclSubject : public SimpleAclSubject { +public: + bool validate(const AclValidationContext &baseCtx, const TypedList &sample) const; + CssmList toList(Allocator &alloc) const; + + ProtectedPasswordAclSubject(Allocator &alloc, const CssmData &password); + ProtectedPasswordAclSubject(Allocator &alloc, CssmManagedData &password); + + Allocator &allocator; + + void exportBlob(Writer::Counter &pub, Writer::Counter &priv); + void exportBlob(Writer &pub, Writer &priv); + + IFDUMP(void debugDump() const); + + class Maker : public AclSubject::Maker { + public: + Maker() : AclSubject::Maker(CSSM_ACL_SUBJECT_TYPE_PROTECTED_PASSWORD) { } + ProtectedPasswordAclSubject *make(const TypedList &list) const; + ProtectedPasswordAclSubject *make(Version, Reader &pub, Reader &priv) const; + }; + +private: + CssmAutoData mPassword; +}; + +} // end namespace Security + + +#endif //_ACL_PROTECTED_PASSWORD diff --git a/libsecurity_cdsa_utilities/lib/acl_secret.cpp b/libsecurity_cdsa_utilities/lib/acl_secret.cpp new file mode 100644 index 00000000..825ce5fe --- /dev/null +++ b/libsecurity_cdsa_utilities/lib/acl_secret.cpp @@ -0,0 +1,127 @@ +/* + * 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@ + */ + + +// +// acl_secret - secret-validation password ACLs framework. +// +#include +#include +#include +#include +#include + + +// +// Construct a secret-bearing ACL subject +// +SecretAclSubject::SecretAclSubject(Allocator &alloc, + CSSM_ACL_SUBJECT_TYPE type, const CssmData &password) + : SimpleAclSubject(type), allocator(alloc), + mSecret(alloc, password), mSecretValid(true), mCacheSecret(false) +{ } + +SecretAclSubject::SecretAclSubject(Allocator &alloc, + CSSM_ACL_SUBJECT_TYPE type, CssmManagedData &password) + : SimpleAclSubject(type), allocator(alloc), + mSecret(alloc, password), mSecretValid(true), mCacheSecret(false) +{ } + +SecretAclSubject::SecretAclSubject(Allocator &alloc, + CSSM_ACL_SUBJECT_TYPE type, bool doCache) + : SimpleAclSubject(type), allocator(alloc), + mSecret(alloc), mSecretValid(false), mCacheSecret(doCache) +{ } + + +// +// Set the secret after creation. +// +// These are const methods by design, even though they obvious (may) set +// a field in the SecretAclSubject. The fields are mutable, following the +// general convention that transient state in AclSubjects is mutable. +// +void SecretAclSubject::secret(const CssmData &s) const +{ + assert(!mSecretValid); // can't re-set it + if (mCacheSecret) { + mSecret = s; + mSecretValid = true; + secdebug("aclsecret", "%p secret stored", this); + } else + secdebug("aclsecret", "%p refused to store secret", this); +} + +void SecretAclSubject::secret(CssmManagedData &s) const +{ + assert(!mSecretValid); // can't re-set it + if (mCacheSecret) { + mSecret = s; + mSecretValid = true; + secdebug("aclsecret", "%p secret stored", this); + } else + secdebug("aclsecret", "%p refused to store secret", this); +} + + +// +// Validate a secret. +// The subclass has to come up with the secret somehow. We just validate it. +// +bool SecretAclSubject::validate(const AclValidationContext &context, + const TypedList &sample) const +{ + CssmAutoData secret(allocator); + + // try to get the secret; fail if we can't + if (!getSecret(context, sample, secret)) + return false; + + // now validate the secret + if (mSecretValid) { + return mSecret == secret; + } else if (Environment *env = context.environment()) { + TrackingAllocator alloc(Allocator::standard()); + TypedList data(alloc, type(), new(alloc) ListElement(secret.get())); + CssmSample sample(data); + AccessCredentials cred((SampleGroup(sample)), context.credTag()); + return env->validateSecret(this, &cred); + } else { + return false; + } +} + + +#ifdef DEBUGDUMP + +void SecretAclSubject::debugDump() const +{ + if (mSecretValid) { + Debug::dump(" "); + Debug::dumpData(mSecret.data(), mSecret.length()); + } + if (mCacheSecret) + Debug::dump("; CACHING"); +} + +#endif //DEBUGDUMP diff --git a/libsecurity_cdsa_utilities/lib/acl_secret.h b/libsecurity_cdsa_utilities/lib/acl_secret.h new file mode 100644 index 00000000..f321a66f --- /dev/null +++ b/libsecurity_cdsa_utilities/lib/acl_secret.h @@ -0,0 +1,99 @@ +/* + * 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@ + */ + + +// +// acl_secret - secret-validation password ACLs framework. +// +#ifndef _ACL_SECRET +#define _ACL_SECRET + +#include +#include +#include + + +namespace Security { + + +// +// SecretAclSubject implements AclSubjects that perform their validation by +// passing their secret through some deterministic validation mechanism. +// As a limiting case, the subject can contain the secret itself and validate +// by comparing for equality. +// +// This is not a fully functional ACL subject. You must subclass it. +// +// There are three elements to consider here: +// (1) How to OBTAIN the secret. This is the job of your subclass; SecretAclSubject +// is agnostic (and abstract) in this respect. +// (2) How to VALIDATE the secret. This is delegated to an environment method, +// which gets this very subject passed as an argument for maximum flexibility. +// (3) Whether to use a locally stored copy of the secret for validation (by equality) +// or hand it off to the environment validator. This is fully implemented here. +// This implementation assumes that the secret, whatever it may be, can be stored +// as a (flat) data blob and can be compared for bit-wise equality. No other +// interpretation is required at this level. +// +class SecretAclSubject : public SimpleAclSubject { +public: + bool validate(const AclValidationContext &ctx, const TypedList &sample) const; + + SecretAclSubject(Allocator &alloc, CSSM_ACL_SUBJECT_TYPE type, const CssmData &secret); + SecretAclSubject(Allocator &alloc, CSSM_ACL_SUBJECT_TYPE type, CssmManagedData &secret); + SecretAclSubject(Allocator &alloc, CSSM_ACL_SUBJECT_TYPE type, bool doCache); + + bool haveSecret() const { return mSecretValid; } + bool cacheSecret() const { return mCacheSecret; } + + void secret(const CssmData &secret) const; + void secret(CssmManagedData &secret) const; + + Allocator &allocator; + + IFDUMP(void debugDump() const); + +public: + class Environment : virtual public AclValidationEnvironment { + public: + virtual bool validateSecret(const SecretAclSubject *me, + const AccessCredentials *secret) = 0; + }; + +protected: + // implement this to get your secret (somehow) + virtual bool getSecret(const AclValidationContext &context, + const TypedList &sample, CssmOwnedData &secret) const = 0; + + const CssmData &secret() const { assert(mSecretValid); return mSecret; } + +private: + mutable CssmAutoData mSecret; // locally known secret + mutable bool mSecretValid; // mSecret is valid + bool mCacheSecret; // cache secret locally and validate from cache +}; + +} // end namespace Security + + +#endif //_ACL_SECRET diff --git a/libsecurity_cdsa_utilities/lib/acl_threshold.cpp b/libsecurity_cdsa_utilities/lib/acl_threshold.cpp new file mode 100644 index 00000000..aea04434 --- /dev/null +++ b/libsecurity_cdsa_utilities/lib/acl_threshold.cpp @@ -0,0 +1,180 @@ +/* + * 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@ + */ + + +// +// acl_threshold - Threshold-based group ACL subjects +// +#include +#include +#include + + +// +// Validate a credential set against this subject. +// +// With STRICTCOUNTING set, we assume that every match in the threshold ACL +// "consumes" one sample in the corresponding threshold sample. This will not +// work as expected for subject types that may succeed without a sample (e.g. ANY) +// or subject types that may multiply match against a single sample. You have been +// warned. +// +class SublistValidationContext : public AclValidationContext { +public: + SublistValidationContext(const AclValidationContext &ctx, const TypedList &list) + : AclValidationContext(ctx), sampleList(list) { } + + uint32 count() const { return sampleList.length() - 1; } + const TypedList &sample(uint32 n) const + { return TypedList::overlay(sampleList[n+1].list()); } + + void matched(const TypedList *) const { } //@@@ ignore sub-matches for now + + const TypedList &sampleList; +}; + +bool ThresholdAclSubject::validate(const AclValidationContext &baseCtx, + const TypedList &sample) const +{ +#ifdef STRICTCOUNTING + // Pre-screen for reasonable number of subsamples. + // We could more strictly require subSampleCount == elements.length(); + // this is more flexible in that it allows the caller to abbreviate. + uint32 subSampleCount = sample.length() - 1; // (drop type header) + if (subSampleCount < minimumNeeded) // can't possibly satisfy + CssmError::throwMe(CSSM_ERRCODE_INVALID_SAMPLE_VALUE); + if (subSampleCount > totalSubjects) // reject attempt at sample stuffing + CssmError::throwMe(CSSM_ERRCODE_INVALID_SAMPLE_VALUE); +#endif //STRICTCOUNTING + + // evaluate + SublistValidationContext ctx(baseCtx, sample); + uint32 matched = 0; + for (uint32 n = 0; n < totalSubjects; n++) { + if ((matched += elements[n]->validate(ctx)) >= minimumNeeded) + return true; +#ifdef STRICTCOUNTING + else if (matched + subSampleCount - n <= minimumNeeded) + return false; // can't get there anymore +#endif //STRICTCOUNTING + } + return false; +} + + +// +// Make a copy of this subject in CSSM_LIST form +// +CssmList ThresholdAclSubject::toList(Allocator &alloc) const +{ + TypedList result(alloc, CSSM_ACL_SUBJECT_TYPE_THRESHOLD, + new(alloc) ListElement(minimumNeeded), + new(alloc) ListElement(totalSubjects)); + for (uint32 n = 0; n < totalSubjects; n++) + result += new(alloc) ListElement(elements[n]->toList(alloc)); + return result; +} + + +// +// Create a ThresholdAclSubject +// +ThresholdAclSubject *ThresholdAclSubject::Maker::make(const TypedList &list) const +{ + // pick apart the input list + if (list.length() < 4) // head + "n" + "k" + at least one subSubject + CssmError::throwMe(CSSM_ERRCODE_INVALID_ACL_SUBJECT_VALUE); + uint32 minimumNeeded = getWord(list[1], 1); + uint32 totalSubjects = getWord(list[2], minimumNeeded); + if (list.length() != 3 + totalSubjects) + CssmError::throwMe(CSSM_ERRCODE_INVALID_ACL_SUBJECT_VALUE); + + // now compile the subSubjects + AclSubjectVector elements(totalSubjects); + const ListElement *subSubject = &list[3]; + for (uint32 n = 0; n < totalSubjects; n++, subSubject = subSubject->next()) + elements[n] = ObjectAcl::make(subSubject->typedList()); + return new ThresholdAclSubject(totalSubjects, minimumNeeded, elements); +} + +ThresholdAclSubject *ThresholdAclSubject::Maker::make(Version, Reader &pub, Reader &priv) const +{ + Endian totalSubjects; pub(totalSubjects); + Endian minimumNeeded; pub(minimumNeeded); + AclSubjectVector subSubjects(totalSubjects); + for (uint32 n = 0; n < totalSubjects; n++) + subSubjects[n] = ObjectAcl::importSubject(pub, priv); + return new ThresholdAclSubject(totalSubjects, minimumNeeded, subSubjects); +} + +ThresholdAclSubject::ThresholdAclSubject(uint32 n, uint32 k, + const AclSubjectVector &subSubjects) +: SimpleAclSubject(CSSM_ACL_SUBJECT_TYPE_THRESHOLD), + minimumNeeded(k), totalSubjects(n), elements(subSubjects) +{ +} + + +// +// Export the subject to a memory blob +// +template +void ThresholdAclSubject::exportBlobForm(Action &pub, Action &priv) +{ + pub(h2n(totalSubjects)); + pub(h2n(minimumNeeded)); + for (uint32 n = 0; n < totalSubjects; n++) + ObjectAcl::exportSubject(elements[n], pub, priv); +} + +void ThresholdAclSubject::exportBlob(Writer::Counter &pub, Writer::Counter &priv) +{ exportBlobForm(pub, priv); } + +void ThresholdAclSubject::exportBlob(Writer &pub, Writer &priv) +{ exportBlobForm(pub, priv); } + + +void ThresholdAclSubject::add(AclSubject *subject, unsigned beforePosition) +{ + secdebug("threshacl", "adding subject %p before position %u", + subject, beforePosition); + elements.insert(elements.begin() + beforePosition, subject); + totalSubjects++; +} + + +#ifdef DEBUGDUMP + +void ThresholdAclSubject::debugDump() const +{ + Debug::dump("Threshold(%u of %u)", minimumNeeded, totalSubjects); + for (unsigned int n = 0; n < elements.size(); n++) { + Debug::dump(" ["); + if (Version v = elements[n]->version()) + Debug::dump("V=%d ", v); + elements[n]->debugDump(); + Debug::dump("]"); + } +} + +#endif //DEBUGDUMP diff --git a/libsecurity_cdsa_utilities/lib/acl_threshold.h b/libsecurity_cdsa_utilities/lib/acl_threshold.h new file mode 100644 index 00000000..71ff0b8b --- /dev/null +++ b/libsecurity_cdsa_utilities/lib/acl_threshold.h @@ -0,0 +1,86 @@ +/* + * 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@ + */ + + +// +// acl_threshold - Threshold-based group ACL subjects. +// +// This subject type implements threshold (k of n) subjects as per CSSM standard. +// Subsubjects are stored and evaluated in the order received. Any subsubject +// is presented with all subsamples of the corresponding threshold sample, but +// not any other samples possibly present in the credentials. Subsubject evaluation +// stops as soon as the threshold is satisfied, or as soon as it becomes numerically +// impossible to satisfy the threshold with future matches. +// Note that this subject will reject out of hand any threshold sample that +// contains more than subsamples. This defeats "sample stuffing" attacks +// where the attacker provides thousands of samples in the hope that some may +// match by accident. It will however accept threshold samples with fewer than +// subsamples, as long as there are at least subsamples. +// +#ifndef _ACL_THRESHOLD +#define _ACL_THRESHOLD + +#include +#include + + +namespace Security { + +class ThresholdAclSubject : public SimpleAclSubject { + typedef ObjectAcl::AclSubjectPointer AclSubjectPointer; + typedef vector AclSubjectVector; +public: + bool validate(const AclValidationContext &baseCtx, const TypedList &sample) const; + CssmList toList(Allocator &alloc) const; + + ThresholdAclSubject(uint32 n, uint32 k, const AclSubjectVector &subSubjects); + + void exportBlob(Writer::Counter &pub, Writer::Counter &priv); + void exportBlob(Writer &pub, Writer &priv); + + unsigned count() const { return totalSubjects; } + AclSubject *subject(unsigned n) const { return elements[n]; } + void add(AclSubject *subject, unsigned beforePosition); + + IFDUMP(void debugDump() const); + + class Maker : public AclSubject::Maker { + public: + Maker() : AclSubject::Maker(CSSM_ACL_SUBJECT_TYPE_THRESHOLD) { } + ThresholdAclSubject *make(const TypedList &list) const; + ThresholdAclSubject *make(Version, Reader &pub, Reader &priv) const; + }; + +private: + uint32 minimumNeeded; // number of matches needed + uint32 totalSubjects; // number of subSubjects + AclSubjectVector elements; // sub-subject vector + + template + void exportBlobForm(Action &pub, Action &priv); +}; + +} // namespace Security + + +#endif //_ACL_THRESHOLD diff --git a/libsecurity_cdsa_utilities/lib/aclsubject.cpp b/libsecurity_cdsa_utilities/lib/aclsubject.cpp new file mode 100644 index 00000000..e1e6e214 --- /dev/null +++ b/libsecurity_cdsa_utilities/lib/aclsubject.cpp @@ -0,0 +1,160 @@ +/* + * 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@ + */ + + +// +// aclsubject - abstract ACL subject implementation +// +#include +#include +#include +#include +#include +#include + + +// +// Validation contexts +// +AclValidationContext::~AclValidationContext() +{ /* virtual */ } + + +void AclValidationContext::init(ObjectAcl *acl, AclSubject *subject) +{ + mAcl = acl; + mSubject = subject; +} + + +const char *AclValidationContext::credTag() const +{ + return mCred ? mCred->tag() : NULL; +} + +std::string AclValidationContext::s_credTag() const +{ + const char *s = this->credTag(); + return s ? s : ""; +} + +const char *AclValidationContext::entryTag() const +{ + return mEntryTag; +} + +void AclValidationContext::entryTag(const char *tag) +{ + mEntryTag = (tag && tag[0]) ? tag : NULL; +} + +void AclValidationContext::entryTag(const std::string &tag) +{ + mEntryTag = tag.empty() ? NULL : tag.c_str(); +} + + +// +// Common (basic) features of AclSubjects +// +AclSubject::AclSubject(uint32 type, Version v /* = 0 */) + : mType(type), mVersion(v) +{ + assert(!(type & versionMask)); +} + +AclSubject::~AclSubject() +{ } + +AclValidationEnvironment::~AclValidationEnvironment() +{ } + +Adornable &AclValidationEnvironment::store(const AclSubject *subject) +{ + CssmError::throwMe(CSSM_ERRCODE_ACL_SUBJECT_TYPE_NOT_SUPPORTED); +} + +void AclSubject::exportBlob(Writer::Counter &, Writer::Counter &) +{ } + +void AclSubject::exportBlob(Writer &, Writer &) +{ } + +void AclSubject::importBlob(Reader &, Reader &) +{ } + +void AclSubject::reset() +{ } + +AclSubject::Maker::~Maker() +{ +} + + +// +// A SimpleAclSubject accepts only a single type of sample, validates +// samples independently, and makes no use of certificates. +// +bool SimpleAclSubject::validate(const AclValidationContext &ctx) const +{ + for (uint32 n = 0; n < ctx.count(); n++) { + const TypedList &sample = ctx[n]; + if (!sample.isProper()) + CssmError::throwMe(CSSM_ERRCODE_INVALID_SAMPLE_VALUE); + if (sample.type() == type() && validate(ctx, sample)) { + ctx.matched(ctx[n]); + return true; // matched this sample; validation successful + } + } + return false; +} + + +// +// AclSubjects always have a (virtual) dump method. +// It's empty unless DEBUGDUMP is enabled. +// +void AclSubject::debugDump() const +{ +#if defined(DEBUGDUMP) + switch (type()) { + case CSSM_ACL_SUBJECT_TYPE_ANY: + Debug::dump("ANY"); + break; + default: + Debug::dump("subject type=%d", type()); + break; + } +#endif //DEBUGDUMP +} + +#if defined(DEBUGDUMP) + +void AclSubject::dump(const char *title) const +{ + Debug::dump(" ** %s ", title); + this->debugDump(); + Debug::dump("\n"); +} + +#endif //DEBUGDUMP diff --git a/libsecurity_cdsa_utilities/lib/aclsubject.h b/libsecurity_cdsa_utilities/lib/aclsubject.h new file mode 100644 index 00000000..b62e3325 --- /dev/null +++ b/libsecurity_cdsa_utilities/lib/aclsubject.h @@ -0,0 +1,223 @@ +/* + * 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@ + */ + + +// +// aclsubject - abstract ACL subject implementation +// +#ifndef _ACLSUBJECT +#define _ACLSUBJECT + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace Security { + +class ObjectAcl; +class AclValidationContext; +class AclSubject; + + +// +// An AclValidationEnvironment can be subclassed to add context access to ACL subject +// validation. If you use ACL subject classes that need context beyond the credential +// structure itself, add that context to (a virtual subclass of) AclValidationContext, pass that +// to ObjectAcl::validate() along with the credentials, and have the Subject implementation +// access validationContext.environment(). +// +class AclValidationEnvironment { + friend class AclValidationContext; +public: + virtual ~AclValidationEnvironment(); // ensure virtual methods (need dynamic_cast) + + // provide an Adornable for a given subject to store data in, or throw if none available (default) + virtual Adornable &store(const AclSubject *subject); +}; + + +// +// An AclValidationContext holds all context for an ACL evaluation in one +// package. It's designed to provide a uniform representation of credentials, plus +// any (trusted path and/or implicit) context information useful for ACL validation. +// +// Contexts are immutable (constant) for validators; they do not change at all +// during a validation exercise. Anything that should be mutable must go into +// the environment (which is indirect and modifyable). +// +class AclValidationContext { + friend class ObjectAcl; +public: + AclValidationContext(const AccessCredentials *cred, + AclAuthorization auth, AclValidationEnvironment *env = NULL) + : mCred(cred), mAuth(auth), mEnv(env), mEntryTag(NULL) { } + AclValidationContext(const AclValidationContext &ctx) + : mAcl(ctx.mAcl), mSubject(ctx.mSubject), mCred(ctx.mCred), + mAuth(ctx.mAuth), mEnv(ctx.mEnv), mEntryTag(NULL) { } + virtual ~AclValidationContext(); + + // access to (suitably focused) sample set + virtual uint32 count() const = 0; // number of samples + uint32 size() const { return count(); } // alias + virtual const TypedList &sample(uint32 n) const = 0; // retrieve one sample + const TypedList &operator [] (uint32 n) const { return sample(n); } + + // context access + AclAuthorization authorization() const { return mAuth; } + const AccessCredentials *cred() const { return mCred; } + AclValidationEnvironment *environment() const { return mEnv; } + template Env *environment() const { return dynamic_cast(mEnv); } + AclSubject *subject() const { return mSubject; } + ObjectAcl *acl() const { return mAcl; } + + // tag manipulation + virtual const char *credTag() const; + virtual const char *entryTag() const; + std::string s_credTag() const; + void entryTag(const char *tag); + void entryTag(const std::string &tag); + + // selective match support - not currently implemented + virtual void matched(const TypedList *match) const = 0; + void matched(const TypedList &match) const { return matched(&match); } + +private: + void init(ObjectAcl *acl, AclSubject *subject); + +private: + ObjectAcl *mAcl; // underlying ObjectAcl + AclSubject *mSubject; // subject being validated + const AccessCredentials *mCred; // original credentials + AclAuthorization mAuth; // action requested + AclValidationEnvironment *mEnv; // environmental context (if any) + const char *mEntryTag; // entry tag +}; + + +// +// The AclSubject class models an ACL "subject" object. If you have a new ACL +// subject type or variant, you make a subclass of this (plus a suitable Maker). +// +// Note that AclSubjects can contain both configuration and state information. +// Configuration is set during AclSubject creation (passwords to check against, +// evaluation options, etc.) and are typically passed on in the externalized form; +// it is persistent. +// On the other hand, state is volatile and is lost when the AclSubject dies. +// This is stuff that accumulates during a particular lifetime, such as results +// of previous evaluations (for caching or more nefarious purposes). +// Be clear what each of your subclass members are, and document accordingly. +// +class AclSubject : public RefCount { +public: + typedef LowLevelMemoryUtilities::Writer Writer; + typedef LowLevelMemoryUtilities::Reader Reader; + + typedef uint8 Version; // binary version marker + static const int versionShift = 24; // highest-order byte of type is version + static const uint32 versionMask = 0xff000000; + +public: + explicit AclSubject(uint32 type, Version v = 0); + virtual ~AclSubject(); + CSSM_ACL_SUBJECT_TYPE type() const { return mType; } + + // validation (evaluation) primitive + virtual bool validate(const AclValidationContext &ctx) const = 0; + + // export to CSSM interface + virtual CssmList toList(Allocator &alloc) const = 0; + + // export/import for save/restore interface + virtual void exportBlob(Writer::Counter &pub, Writer::Counter &priv); + virtual void exportBlob(Writer &pub, Writer &priv); + virtual void importBlob(Reader &pub, Reader &priv); + + // binary compatibility version management. The version defaults to zero + Version version() const { return mVersion; } + + // forget any validation-related state you have acquired + virtual void reset(); + + // debug suupport (dummied out but present for -UDEBUGDUMP) + virtual void debugDump() const; + IFDUMP(void dump(const char *title) const); + +protected: + void version(Version v) { mVersion = v; } + +private: + CSSM_ACL_SUBJECT_TYPE mType; + Version mVersion; + +public: + class Maker { + public: + Maker(CSSM_ACL_SUBJECT_TYPE type); + virtual ~Maker(); + + uint32 type() const { return mType; } + virtual AclSubject *make(const TypedList &list) const = 0; + virtual AclSubject *make(Version version, Reader &pub, Reader &priv) const = 0; + + protected: + // list parsing helpers + static void crack(const CssmList &list, uint32 count, + ListElement **array = NULL, ...); + static CSSM_WORDID_TYPE getWord(const ListElement &list, + int min = 0, int max = INT_MAX); + + private: + CSSM_ACL_SUBJECT_TYPE mType; + }; +}; + + +// +// A SimpleAclSubject validates a credential by scanning its samples +// one at a time, without any interactions between them. Thus its validate() +// can be a lot simpler. +// Note that this layer assumes that subject and sample types have the same +// value, as is typical when both are derived from a WORDID. +// +class SimpleAclSubject : public AclSubject { +public: + SimpleAclSubject(CSSM_ACL_SUBJECT_TYPE type) : AclSubject(type) { } + + bool validate(const AclValidationContext &ctx) const; + virtual bool validate(const AclValidationContext &baseCtx, + const TypedList &sample) const = 0; +}; + + +} // end namespace Security + + +#endif //_ACLSUBJECT diff --git a/libsecurity_cdsa_utilities/lib/callback.cpp b/libsecurity_cdsa_utilities/lib/callback.cpp new file mode 100644 index 00000000..023fff0f --- /dev/null +++ b/libsecurity_cdsa_utilities/lib/callback.cpp @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2000-2001,2003-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@ + */ + + +// +// Encapsulate the callback mechanism of CSSM. +// +#include + + +// +// Invoke a callback +// +void ModuleCallback::operator () (CSSM_MODULE_EVENT event, + const Guid &guid, uint32 subId, + CSSM_SERVICE_TYPE serviceType) const +{ + try + { + if (mCallback) + if (CSSM_RETURN err = mCallback(&guid, mContext, subId, serviceType, event)) + CssmError::throwMe(err); + } + catch (...) + { + } +} + + +// +// Manage Callback sets. +// THREADS: Caller is ensuring single-thread access on these calls. +// +void ModuleCallbackSet::insert(const ModuleCallback &newCallback) +{ + callbacks.insert(CallbackMap::value_type(newCallback, new CountingMutex)); +} + +void ModuleCallbackSet::erase(const ModuleCallback &oldCallback) +{ + CallbackMap::iterator it = callbacks.find(oldCallback); + if (it == callbacks.end()) // not registered; fail + CssmError::throwMe(CSSMERR_CSSM_INVALID_ADDIN_HANDLE); + CountingMutex *counter = it->second; + { + StLock _(*counter); + if (!counter->isIdle()) // callbacks are scheduled against this + CssmError::throwMe(CSSM_ERRCODE_FUNCTION_FAILED); // @#module is busy + } + // counter is zero (idle), and we hold the entry lock (via our caller) + delete counter; + callbacks.erase(it); +} + + +// +// Invoke an entire callback set. +// THREADS: Caller is ensuring single-thread access on these calls. +// +void ModuleCallbackSet::operator () (CSSM_MODULE_EVENT event, + const Guid &guid, uint32 subId, + CSSM_SERVICE_TYPE serviceType) const +{ + if (callbacks.empty()) // nothing to do; quick exit + return; + +#if _USE_THREADS == _USE_NO_THREADS || defined(SYNCHRONOUS_CALLBACKS) + // no threading model supported - we HAVE to do this right here + // note that the user better not re-enter CSSM too much, + // or we might deadlock... + for (CallbackMap::const_iterator it = callbacks.begin(); + it != callbacks.end(); it++) { + it->first(event, guid, subId, serviceType); + } +#else // real threads available + // lock down all callback elements - still protected by global lock (via caller) + for (CallbackMap::iterator it = callbacks.begin(); + it != callbacks.end(); it++) + it->second->enter(); + + // get out of this thread - now! + (new Runner(callbacks, event, guid, subId, serviceType))->run(); +#endif +} + +void ModuleCallbackSet::Runner::action() +{ + // + // NOTE WELL: Our callbacks map shares (pointed-to) values with the ModuleCallbackSet + // we were created from. Some of these values may be dangling pointers since they have + // been destroyed by other threads, but only *after* we are done with them, since + // we must call exit() on them before they become eligible for destruction. + // In all cases, it is the responsibility of other threads to destroy those mutexi. + // + // @@@ Could also fan out to multiple callback threads in parallel. + for (CallbackMap::iterator it = callbacks.begin(); + it != callbacks.end(); it++) { + //@@@ safety vs. convenience - recheck + it->first(event, guid, subserviceId, serviceType); + it->second->exit(); + } +} diff --git a/libsecurity_cdsa_utilities/lib/callback.h b/libsecurity_cdsa_utilities/lib/callback.h new file mode 100644 index 00000000..7bb5191d --- /dev/null +++ b/libsecurity_cdsa_utilities/lib/callback.h @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2000-2001,2003-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@ + */ + + +// +// Encapsulate the callback mechanism of CSSM. +// +#ifndef _H_CALLBACK +#define _H_CALLBACK + +#include +#include +#include +#include + +namespace Security +{ + +// +// A single module-specific callback as requested by the user. +// +class ModuleCallback { +public: + ModuleCallback() : mCallback(0), mContext(0) { } + ModuleCallback(CSSM_API_ModuleEventHandler callback, void *context) + : mCallback(callback), mContext(context) { } + + void operator () (CSSM_MODULE_EVENT event, + const Guid &guid, uint32 subId, + CSSM_SERVICE_TYPE serviceType) const; + + operator bool () const { return mCallback || mContext; } + bool operator ! () const { return !bool(*this); } + + bool operator == (const ModuleCallback &cb) const + { return mCallback == cb.mCallback && mContext == cb.mContext; } + bool operator < (const ModuleCallback &cb) const + { return mCallback < cb.mCallback + || mCallback == cb.mCallback && mContext < cb.mContext; } + +private: + CSSM_API_ModuleEventHandler mCallback; + void *mContext; +}; + + +// +// A set of callbacks that can be invoked automatically in a thread-safe manner. +// THREADS: The set itself is not interlocked by the ModuleCallbackSet class; you +// are responsible for ensuring single access to the set object. The class ensures +// that any threads it spawns to execute the callbacks will not step on each other +// or on you, and that you will not be able to erase() a callback while it has +// activity scheduled against it. This also applies to the invocation method +// (operator ()) - you must lock against multiple accesses to it until it returns. +// +class ModuleCallbackSet { +public: + unsigned int size() const { return callbacks.size(); } + void insert(const ModuleCallback &newCallback); + void erase(const ModuleCallback &oldCallback); + + void operator () (CSSM_MODULE_EVENT event, + const Guid &guid, uint32 subId, + CSSM_SERVICE_TYPE serviceType) const; + +private: + // note mutex *: we don't want to rely on copy-ability of Mutex objects + typedef multimap CallbackMap; + mutable CallbackMap callbacks; + + struct Runner : public Thread { + Runner(CallbackMap &inCallbacks, + CSSM_MODULE_EVENT inEvent, + const Guid &inGuid, + uint32 inSSId, + CSSM_SERVICE_TYPE inServiceType) + : callbacks(inCallbacks), event(inEvent), guid(inGuid), + subserviceId(inSSId), serviceType(inServiceType) { } + + CallbackMap callbacks; // note that we share the CountingMutex * values! + const CSSM_MODULE_EVENT event; + const Guid guid; + const uint32 subserviceId; + const CSSM_SERVICE_TYPE serviceType; + + void action(); + }; +}; + +} // end namespace Security + + +#endif //_H_CALLBACK diff --git a/libsecurity_cdsa_utilities/lib/constdata.cpp b/libsecurity_cdsa_utilities/lib/constdata.cpp new file mode 100644 index 00000000..40ba116e --- /dev/null +++ b/libsecurity_cdsa_utilities/lib/constdata.cpp @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2000-2001,2003-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@ + */ + + +// +// constdata - shared constant binary data objects +// +#include "constdata.h" +#include + + +namespace Security { + + +// +// Construct a Blob from a source +// +ConstData::Blob::Blob(const void *base, size_t size, bool takeOwnership) : mSize(size) +{ + mData = takeOwnership ? base : memcpy(new char[size], base, size); +} + + +} // end namespace Security diff --git a/libsecurity_cdsa_utilities/lib/constdata.h b/libsecurity_cdsa_utilities/lib/constdata.h new file mode 100644 index 00000000..0dbee228 --- /dev/null +++ b/libsecurity_cdsa_utilities/lib/constdata.h @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2000-2001,2003-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@ + */ + + +// +// constdata - shared constant binary data objects +// +#ifndef _H_CONSTDATA +#define _H_CONSTDATA + +#include +#include + + +namespace Security { + + +// +// ConstData represents a contiguous, binary blob of constant data. +// Assignment is by sharing (thus cheap). +// ConstData is a (constant) Dataoid type. +// +class ConstData { +private: + class Blob : public RefCount { + public: + Blob() : mData(NULL), mSize(0) { } + Blob(const void *base, size_t size, bool takeOwnership = false); + ~Blob() { delete[] reinterpret_cast(mData); } + + const void *data() const { return mData; } + size_t length() const { return mSize; } + + private: + const void *mData; + size_t mSize; + }; + +public: + ConstData() { } //@@@ use a nullBlob? + ConstData(const void *base, size_t size, bool takeOwnership = false) + : mBlob(new Blob(base, size, takeOwnership)) { } + + template + static ConstData wrap(const T &obj, bool takeOwnership) + { return ConstData(&obj, sizeof(obj), takeOwnership); } + +public: + const void *data() const { return mBlob ? mBlob->data() : NULL; } + size_t length() const { return mBlob ? mBlob->length() : 0; } + + operator bool() const { return mBlob; } + bool operator !() const { return !mBlob; } + + template operator const T *() const + { return reinterpret_cast(data()); } + + template const T &as() const + { return *static_cast(reinterpret_cast(data())); } + +private: + RefPointer mBlob; +}; + + +} // end namespace Security + + +#endif //_H_CONSTDATA diff --git a/libsecurity_cdsa_utilities/lib/context.cpp b/libsecurity_cdsa_utilities/lib/context.cpp new file mode 100644 index 00000000..3a3a3a26 --- /dev/null +++ b/libsecurity_cdsa_utilities/lib/context.cpp @@ -0,0 +1,189 @@ +/* + * Copyright (c) 2000-2001,2003-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@ + */ + + +// +// context - manage CSSM (cryptographic) contexts every which way. +// +// A note on memory management: +// Context attributes are allocated from application memory in big chunks comprising +// many attributes as well as the attribute array itself. The CSSM_CONTEXT fields +// NumberOfAttributes and ContextAttributes are handled as a group. Context::Builder +// and Context::copyFrom assume these fields are undefined and fill them. Context::clear +// assumes they are valid and invalides them, freeing memory. +// +// You may also want to look at cssmcontext.h in CSSM proper, where CSSM's internal Context +// objects are built on top of our Context class. +// +#include + + +// +// Construct Context objects +// +Context::Context(CSSM_CONTEXT_TYPE type, CSSM_ALGORITHMS algorithmId) +{ + clearPod(); + ContextType = type; + AlgorithmType = algorithmId; +} + + +// +// Delete a single attribute from a Context by type. +// We implement this by simply nulling out the slot - the memory is not released, +// and will not be reclaimed until the Context is deleted or reconstructed for some reason. +// +void Context::deleteAttribute(CSSM_ATTRIBUTE_TYPE type) +{ + for (uint32 n = 0; n < attributesInUse(); n++) + if (ContextAttributes[n].AttributeType == type) { + ContextAttributes[n].AttributeType = CSSM_ATTRIBUTE_NONE; + ContextAttributes[n].AttributeLength = 0; + return; + } + // not found + CssmError::throwMe(CSSMERR_CSSM_ATTRIBUTE_NOT_IN_CONTEXT); +} + + +// +// This swiss-army-knife function performs a deep copy of all of a Context's attributes, +// bundling them up into a single memory node and storing them into a pointer/count pair. +// It also returns the size of the memory block allocated, in case you care (IPC does). +// +size_t Context::copyAttributes(CSSM_CONTEXT_ATTRIBUTE * &attrs, uint32 &count, + Allocator &alloc) const +{ + Context::Builder builder(alloc); + for (unsigned n = 0; n < attributesInUse(); n++) + builder.setup(ContextAttributes[n]); + size_t size = builder.make(); + for (unsigned n = 0; n < attributesInUse(); n++) + builder.put(ContextAttributes[n]); + builder.done(attrs, count); + return size; +} + + +// +// Locate attribute values by type. +// This function deals in attribute vectors, not contexts; hence the explicit count argument. +// Returns NULL for attribute not found. +// +Context::Attr *Context::find(CSSM_ATTRIBUTE_TYPE theType, + const CSSM_CONTEXT_ATTRIBUTE *attrs, unsigned int count) +{ + for (unsigned n = 0; n < count; n++) + if (attrs[n].AttributeType == theType) + return (Attr *)&attrs[n]; + return NULL; +} + + +// +// Post-IPC context fixup. +// A Context is transmitted via IPC as a two-element blob. The first is the Context +// structure itself, which is taken as flat. The second is the flattened attribute +// vector blob as produced by the Context::Builder class. Since IPC will relocate +// each blob, we need to offset all internal pointers to compensate. +// +void Context::postIPC(void *base, CSSM_CONTEXT_ATTRIBUTE *ipcAttributes) +{ + ReconstituteWalker relocator(LowLevelMemoryUtilities::difference(ipcAttributes, base)); + ContextAttributes = ipcAttributes; // fix context->attr vector link + for (uint32 n = 0; n < attributesInUse(); n++) + walk(relocator, (*this)[n]); +} + + +// +// Context Builders +// +size_t Context::Builder::make() +{ + size_t vectorSize = + LowLevelMemoryUtilities::alignUp(slotCount * sizeof(CSSM_CONTEXT_ATTRIBUTE)); + size_t totalSize = vectorSize + sizer; + attributes = reinterpret_cast(allocator.malloc(totalSize)); + copier = LowLevelMemoryUtilities::increment(attributes, vectorSize); + slot = 0; + return totalSize; +} + +void Context::Builder::done(CSSM_CONTEXT_ATTRIBUTE * &attributes, uint32 &count) +{ + assert(slot == slotCount); // match pass profiles + attributes = this->attributes; + count = slotCount; + this->attributes = NULL; // delivered the goods, no longer our responsibility +} + + +// +// Debugging support +// +#if defined(DEBUGDUMP) + +static void dumpData(CSSM_DATA *data) +{ + if (data == NULL) + Debug::dump("[NULL]"); + else + Debug::dump("[%p,%ld]@%p", data->Data, data->Length, data); +} + +void Context::Attr::dump() const +{ + Debug::dump(" Attr{type=%x, size=%d, value=", int(AttributeType), int(AttributeLength)); + switch (AttributeType & CSSM_ATTRIBUTE_TYPE_MASK) { + case CSSM_ATTRIBUTE_DATA_UINT32: + Debug::dump("%ld", long(Attribute.Uint32)); break; + case CSSM_ATTRIBUTE_DATA_STRING: + Debug::dump("%s@%p", Attribute.String, Attribute.String); break; + case CSSM_ATTRIBUTE_DATA_CSSM_DATA: + dumpData(Attribute.Data); + break; + case CSSM_ATTRIBUTE_DATA_CRYPTO_DATA: + dumpData(&Attribute.CryptoData->Param); + break; + default: + Debug::dump("%p", Attribute.String); break; // (slightly unclean) + }; + Debug::dump("}\n"); +} + +void Context::dump(const char *title, const CSSM_CONTEXT_ATTRIBUTE *attrs) const +{ + if (attrs == NULL) + attrs = ContextAttributes; + Debug::dump("Context %s{type=%d, alg=%d, CSP=%u, %d attributes@%p:\n", + title ? title : "", + int(ContextType), int(AlgorithmType), (unsigned int)CSPHandle, + int(NumberOfAttributes), attrs); + for (unsigned int n = 0; n < NumberOfAttributes; n++) + Attr::overlay(attrs[n]).dump(); + Debug::dump("} // end Context\n"); +} + +#endif //DEBUGDUMP diff --git a/libsecurity_cdsa_utilities/lib/context.h b/libsecurity_cdsa_utilities/lib/context.h new file mode 100644 index 00000000..5fdd9725 --- /dev/null +++ b/libsecurity_cdsa_utilities/lib/context.h @@ -0,0 +1,379 @@ +/* + * Copyright (c) 2000-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@ + */ + + +// +// context - CSSM cryptographic context objects +// +#ifndef _H_CONTEXT +#define _H_CONTEXT + +#include +#include +#include +#include +#include // to serialize/copy access credentials +#include + +namespace Security { + + +// +// Context is a POD overlay for the CSSM_CONTEXT type. It does +// add allocation functions and lots of good stuff. +// Note that if you're outside CSSM proper, you are not supposed to +// memory-manage Context structures on your own. Be a good boy and +// call the CSSM API functions. +// We also provide a POD overlay for CSSM_CONTEXT_ATTRIBUTE, with +// the obvious semantics. +// +class Context : public PodWrapper { +public: + Context(CSSM_CONTEXT_TYPE type, CSSM_ALGORITHMS algorithmId); + + uint32 attributesInUse() const { return NumberOfAttributes; } + CSSM_CONTEXT_TYPE type() const { return ContextType; } + CSSM_ALGORITHMS algorithm() const { return AlgorithmType; } + CSSM_CSP_HANDLE cspHandle() const { return CSPHandle; } + + void deleteAttribute(CSSM_ATTRIBUTE_TYPE type); + size_t copyAttributes(CSSM_CONTEXT_ATTRIBUTE * &attrs, uint32 &count, Allocator &alloc) const; + + void copyFrom(const Context &source, Allocator &alloc) + { source.copyAttributes(ContextAttributes, NumberOfAttributes, alloc); } + +public: + class Attr : public PodWrapper { + public: + Attr() { } + Attr(const CSSM_CONTEXT_ATTRIBUTE &attr) { (CSSM_CONTEXT_ATTRIBUTE &)*this = attr; } + + template + Attr(CSSM_ATTRIBUTE_TYPE typ, T &value, size_t size = 0) + { + AttributeType = typ; + // attribute component pointers are stupidly non-const; allow const input + Attribute.String = const_cast(reinterpret_cast(&value)); + AttributeLength = size ? size : sizeof(T); + } + + Attr(CSSM_ATTRIBUTE_TYPE typ, uint32 value) + { + AttributeType = typ; + Attribute.Uint32 = value; + AttributeLength = 0; + } + + CSSM_ATTRIBUTE_TYPE type() const { return AttributeType; } + uint32 baseType() const { return AttributeType & CSSM_ATTRIBUTE_TYPE_MASK; } + + operator char * () const + { assert(baseType() == CSSM_ATTRIBUTE_DATA_STRING); return Attribute.String; } + operator CssmData & () const + { assert(baseType() == CSSM_ATTRIBUTE_DATA_CSSM_DATA); + return CssmData::overlay(*Attribute.Data); } + operator CssmCryptoData & () const + { assert(baseType() == CSSM_ATTRIBUTE_DATA_CRYPTO_DATA); + return CssmCryptoData::overlay(*Attribute.CryptoData); } + operator CssmKey & () const + { assert(baseType() == CSSM_ATTRIBUTE_DATA_KEY); return CssmKey::overlay(*Attribute.Key); } + operator AccessCredentials & () const + { assert(baseType() == CSSM_ATTRIBUTE_DATA_ACCESS_CREDENTIALS); + return AccessCredentials::overlay(*Attribute.AccessCredentials); } + operator uint32 () const + { assert(baseType() == CSSM_ATTRIBUTE_DATA_UINT32); return Attribute.Uint32; } + operator CSSM_DL_DB_HANDLE &() const + { + assert(baseType() == CSSM_ATTRIBUTE_DATA_DL_DB_HANDLE); + if (Attribute.DLDBHandle == NULL) + CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_DL_DB_HANDLE); + return *Attribute.DLDBHandle; + } + operator CssmDate & () const + { assert(baseType() == CSSM_ATTRIBUTE_DATA_DATE); + return CssmDate::overlay(*Attribute.Date); } + // @@@ etc. etc. - add yours today! + + void operator = (uint32 value) { Attribute.Uint32 = value; } + template + void operator = (T *ptr) { Attribute.String = reinterpret_cast(ptr); } + + IFDUMP(void dump() const;) // debug dump this Attr to stdout (one line) + }; + + // Attributes by position + Attr *attributes() const { return Attr::overlay(ContextAttributes); } + Attr &operator [] (unsigned int ix) + { assert(ix < NumberOfAttributes); return static_cast(ContextAttributes[ix]); } + const Attr &operator [] (unsigned int ix) const + { assert(ix < NumberOfAttributes); return static_cast(ContextAttributes[ix]); } + + // general attribute retrieval by type + Attr *find(CSSM_ATTRIBUTE_TYPE theType) const + { return find(theType, ContextAttributes, NumberOfAttributes); } + + template + Elem &get(CSSM_ATTRIBUTE_TYPE type, CSSM_RETURN err) const + { + if (Attr *attr = find(type)) + return static_cast(*attr); + else + CssmError::throwMe(err); + } + + template + Elem *get(CSSM_ATTRIBUTE_TYPE type) const + { + if (Attr *attr = find(type)) + // @@@ Invoking conversion operator to Elem & on *attr and taking address of result. + return &static_cast(*attr); + else + return NULL; + } + + uint32 getInt(CSSM_ATTRIBUTE_TYPE type, CSSM_RETURN err) const + { + if (Attr *attr = find(type)) + return static_cast(*attr); + else + CssmError::throwMe(err); + } + + uint32 getInt(CSSM_ATTRIBUTE_TYPE type) const + { + if (Attr *attr = find(type)) + return static_cast(*attr); + else + return 0; + } + + bool getInt(CSSM_ATTRIBUTE_TYPE type, uint32 &value) const + { + if (Attr *attr = find(type)) { + value = static_cast(*attr); + return true; + } else + return false; + } + +public: + template + void replace(CSSM_ATTRIBUTE_TYPE type, const T &newValue) const + { + if (Attr *attr = find(type)) + *attr = Attr(type, newValue); + else + CssmError::throwMe(CSSMERR_CSSM_ATTRIBUTE_NOT_IN_CONTEXT); + } + +public: + void *operator new (size_t size, Allocator &alloc) throw(std::bad_alloc) + { return alloc.malloc(size); } + void operator delete (void *addr, size_t, Allocator &alloc) throw() + { return alloc.free(addr); } + static void destroy(Context *context, Allocator &alloc) throw() + { alloc.free(context->ContextAttributes); alloc.free(context); } + +public: + // Post-IPC context fixup. + // This can only be called on a Built Context after IPC transmission. + void postIPC(void *base, CSSM_CONTEXT_ATTRIBUTE *ipcAttributes); + +public: + class Builder; + + // dump to stdout, multiline format + IFDUMP(void dump(const char *title = NULL, + const CSSM_CONTEXT_ATTRIBUTE *attrs = NULL) const;) + +protected: + // find an attribute in a plain array of attribute structures (no context) + static Attr *find(CSSM_ATTRIBUTE_TYPE theType, + const CSSM_CONTEXT_ATTRIBUTE *attrs, unsigned int count); +}; + + +namespace DataWalkers { + + +template +void walk(Action &operate, CSSM_CONTEXT_ATTRIBUTE &attr) +{ + operate(attr); + if (attr.Attribute.String) // non-NULL pointer (imprecise but harmless) + switch (attr.AttributeType & CSSM_ATTRIBUTE_TYPE_MASK) { + case CSSM_ATTRIBUTE_DATA_CSSM_DATA: + walk(operate, attr.Attribute.Data); break; + case CSSM_ATTRIBUTE_DATA_CRYPTO_DATA: + walk(operate, attr.Attribute.CryptoData); break; + case CSSM_ATTRIBUTE_DATA_KEY: + walk(operate, attr.Attribute.Key); break; + case CSSM_ATTRIBUTE_DATA_STRING: + walk(operate, attr.Attribute.String); break; + case CSSM_ATTRIBUTE_DATA_DATE: + walk(operate, attr.Attribute.Date); break; + case CSSM_ATTRIBUTE_DATA_RANGE: + walk(operate, attr.Attribute.Range); break; + case CSSM_ATTRIBUTE_DATA_ACCESS_CREDENTIALS: + walk(operate, attr.Attribute.AccessCredentials); break; + case CSSM_ATTRIBUTE_DATA_VERSION: + walk(operate, attr.Attribute.Version); break; + case CSSM_ATTRIBUTE_DATA_DL_DB_HANDLE: + walk(operate, attr.Attribute.DLDBHandle); break; + case CSSM_ATTRIBUTE_NONE: + case CSSM_ATTRIBUTE_DATA_UINT32: + break; + default: + secdebug("walkers", "invalid attribute (%ux) in context", (unsigned)attr.AttributeType); + break; + } +} + +template +void walk(Action &operate, Context::Attr &attr) +{ + walk(operate, static_cast(attr)); +} + +} // end namespace DataWalkers + + +// +// Context::Builder - make context attributes the fun way. +// +// A Context (aka CSSM_CONTEXT) has a pointer to an array of context attributes, +// most of which contain pointers to other stuff with pointers to God Knows Where. +// Instead of allocating this all over the heap, a Context::Builder performs +// a two-pass algorithm that places all that stuff into a single heap node. +// Specifically, the builder will allocate and create a vector of CSSM_CONTEXT_ATTRIBUTE +// structures and all their subordinate heap storage. +// A Builder does not deal in Context objects and does not care what you do with your +// CSSM_CONTEXT_ATTRIBUTE array once it's delivered. Since it's a single heap node, +// you can just free() it using the appropriate allocator when you're done with it. +// +// Theory of operation: +// Builder works in two phases, called scan and build. During scan, you call setup() +// with the desired data to be placed into the attribute vector. When done, call make() +// to switch to build phase. Then call put() with the SAME sequence of values as in phase 1. +// Finally, call done() to receive the pointer-and-count values. +// @@@ Add comment about IPC use. +// +using namespace DataWalkers; + +class Context::Builder { +protected: +public: + Builder(Allocator &alloc) : allocator(alloc) + { slotCount = 0; attributes = NULL; } + ~Builder() { allocator.free(attributes); } + + Allocator &allocator; + + // switch to build phase + size_t make(); + // deliver result + void done(CSSM_CONTEXT_ATTRIBUTE * &attributes, uint32 &count); + +public: + // + // Phase 1 (scan) dispatch. Call once for each attribute needed. + // + template + void setup(T p, CSSM_RETURN invalidError = CSSM_OK) + { + if (p) { + slotCount++; + walk(sizer, unconst_ref_cast(p)); + } else if (invalidError) + CssmError::throwMe(invalidError); + } + + void setup(uint32 n, CSSM_RETURN invalidError = CSSM_OK) + { + if (n) + slotCount++; + else if (invalidError) + CssmError::throwMe(invalidError); + } + + void setup(CSSM_SIZE n, CSSM_RETURN invalidError = CSSM_OK) + { + if (n) + slotCount++; + else if (invalidError) + CssmError::throwMe(invalidError); + } + + // dynamic attribute type + void setup(const CSSM_CONTEXT_ATTRIBUTE &attr) + { slotCount++; walk(sizer, const_cast(attr)); } + void setup(const Context::Attr &attr) { setup(static_cast(attr)); } + + // + // Phase 2 (copy) dispatch. Call once for each attribute, in same order as setup(). + // + template + void put(CSSM_ATTRIBUTE_TYPE type, const T *p) + { + if (p) { + assert(slot < slotCount); // check overflow + Attr &attribute = attributes[slot++]; + attribute.AttributeType = type; + attribute.AttributeLength = size(p); //@@@ needed? how/when/what for? + T *tmp = const_cast(p); + attribute = walk(copier, tmp); + } + } + void put(CSSM_ATTRIBUTE_TYPE type, uint32 value) + { + if (value) { + assert(slot < slotCount); // check overflow + Attr &attribute = attributes[slot++]; + attribute.AttributeType = type; + attribute.AttributeLength = 0; //@@@ unclear what that should be + attribute = value; // no heap data (immediate value) + } + } + void put(const CSSM_CONTEXT_ATTRIBUTE &attr) + { + assert(slot < slotCount); + Attr &attribute = attributes[slot++]; + attribute = attr; // shallow copy + walk(copier, attribute); // deep copy + } + void put(const Context::Attr &attr) { put(static_cast(attr)); } + +private: + // pass 1 state: collect sizes and counts + unsigned slotCount; // count of attribute slots in use + SizeWalker sizer; // memory size calculator + + // pass 2 state: build the data set + Context::Attr *attributes; // attribute vector and start of block + CopyWalker copier; // data copy engine + uint32 slot; // writer slot position +}; + +} // end namespace Security + +#endif //_H_CONTEXT diff --git a/libsecurity_cdsa_utilities/lib/cssmacl.cpp b/libsecurity_cdsa_utilities/lib/cssmacl.cpp new file mode 100644 index 00000000..62baccc3 --- /dev/null +++ b/libsecurity_cdsa_utilities/lib/cssmacl.cpp @@ -0,0 +1,28 @@ +/* + * 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@ + */ + + +// +// cssmacl - core ACL management interface +// +#include diff --git a/libsecurity_cdsa_utilities/lib/cssmacl.h b/libsecurity_cdsa_utilities/lib/cssmacl.h new file mode 100644 index 00000000..9c891741 --- /dev/null +++ b/libsecurity_cdsa_utilities/lib/cssmacl.h @@ -0,0 +1,63 @@ +/* + * 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@ + */ + + +// +// cssmacl - core ACL management interface. +// +// This header once contain the entire canonical ACL machinery. It's been split up +// since, into objectacl.h and aclsubject.h. What remains is the PodWrapper for +// ResourceControlContext, because nobody else wants it. +// +#ifndef _CSSMACL +#define _CSSMACL + +#include +#include + + +namespace Security { + + +// +// This bastard child of two different data structure sets has no natural home. +// We'll take pity on it here. +// +class ResourceControlContext : public PodWrapper { +public: + ResourceControlContext() { clearPod(); } + ResourceControlContext(const AclEntryInput &initial, + const AccessCredentials *cred = NULL) + { InitialAclEntry = initial; AccessCred = const_cast(cred); } + + AclEntryInput &input() { return AclEntryInput::overlay(InitialAclEntry); } + operator AclEntryInput &() { return input(); } + AccessCredentials *credentials() const { return AccessCredentials::overlay(AccessCred); } + void credentials(const CSSM_ACCESS_CREDENTIALS *creds) + { AccessCred = const_cast(creds); } +}; + +} // end namespace Security + + +#endif //_CSSMACL diff --git a/libsecurity_cdsa_utilities/lib/cssmaclpod.cpp b/libsecurity_cdsa_utilities/lib/cssmaclpod.cpp new file mode 100644 index 00000000..def26ab1 --- /dev/null +++ b/libsecurity_cdsa_utilities/lib/cssmaclpod.cpp @@ -0,0 +1,222 @@ +/* + * 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@ + */ + + +// +// cssmaclpod - enhanced PodWrappers for ACL-related CSSM data structures +// +#include +#include +#include + + +namespace Security { + + +// +// AclAuthorizationSets +// +AclAuthorizationSet::AclAuthorizationSet(AclAuthorization auth0, AclAuthorization auth, ...) +{ + insert(auth0); + + va_list args; + va_start(args, auth); + while (auth) { + insert(auth); + auth = va_arg(args, AclAuthorization); + } + va_end(args); +} + + +// +// AclAuthorizationGroups +// +AuthorizationGroup::AuthorizationGroup(const AclAuthorizationSet &auths, Allocator &alloc) +{ + NumberOfAuthTags = auths.size(); + AuthTags = alloc.alloc(NumberOfAuthTags); + copy(auths.begin(), auths.end(), AuthTags); // happens to be sorted +} + +AuthorizationGroup::AuthorizationGroup(CSSM_ACL_AUTHORIZATION_TAG tag, Allocator &alloc) +{ + AuthTags = alloc.alloc(1); + AuthTags[0] = tag; + NumberOfAuthTags = 1; +} + +void AuthorizationGroup::destroy(Allocator &alloc) +{ + alloc.free(AuthTags); +} + +bool AuthorizationGroup::contains(CSSM_ACL_AUTHORIZATION_TAG tag) const +{ + return find(AuthTags, &AuthTags[NumberOfAuthTags], tag) != &AuthTags[NumberOfAuthTags]; +} + + +AuthorizationGroup::operator AclAuthorizationSet() const +{ + return AclAuthorizationSet(AuthTags, &AuthTags[NumberOfAuthTags]); +} + +AclEntryPrototype::AclEntryPrototype(const AclOwnerPrototype &proto) +{ + memset(this, 0, sizeof(*this)); + TypedSubject = proto.subject(); Delegate = proto.delegate(); + //@@@ set authorization to "is owner" pseudo-auth? See cssmacl.h +} + +void AclEntryPrototype::tag(const char *tagString) +{ + if (tagString == NULL) + EntryTag[0] = '\0'; + else if (strlen(tagString) > CSSM_MODULE_STRING_SIZE) + CssmError::throwMe(CSSM_ERRCODE_INVALID_ACL_ENTRY_TAG); + else + strcpy(EntryTag, tagString); +} + +void AclEntryPrototype::tag(const string &tagString) +{ + if (tagString.length() > CSSM_MODULE_STRING_SIZE) + CssmError::throwMe(CSSM_ERRCODE_INVALID_ACL_ENTRY_TAG); + else + memcpy(EntryTag, tagString.c_str(), tagString.length() + 1); +} + + +AclOwnerPrototype *AutoAclOwnerPrototype::make() +{ + if (!mAclOwnerPrototype) { + mAclOwnerPrototype = new AclOwnerPrototype; + mAclOwnerPrototype->clearPod(); + } + return mAclOwnerPrototype; +} + +AutoAclOwnerPrototype::~AutoAclOwnerPrototype() +{ + if (mAllocator) + DataWalkers::chunkFree(mAclOwnerPrototype, *mAllocator); +} + +void +AutoAclOwnerPrototype::allocator(Allocator &allocator) +{ + mAllocator = &allocator; +} + + +void AutoAclEntryInfoList::size(uint32 newSize) +{ + assert(mAllocator); + mEntries = mAllocator->alloc(mEntries, newSize); + for (uint32 n = mCount; n < newSize; n++) + mEntries[n].clearPod(); + mCount = newSize; +} + + +AclEntryInfo &AutoAclEntryInfoList::at(uint32 ix) +{ + if (ix >= mCount) + size(ix + 1); // expand vector + return mEntries[ix]; +} + + +void AutoAclEntryInfoList::clear() +{ + if (mAllocator) + { + DataWalkers::ChunkFreeWalker w(*mAllocator); + for (uint32 ix = 0; ix < mCount; ix++) + walk(w, mEntries[ix]); + mAllocator->free(mEntries); + mEntries = NULL; + mCount = 0; + } +} + +void AutoAclEntryInfoList::allocator(Allocator &allocator) +{ + mAllocator = &allocator; +} + + +void AutoAclEntryInfoList::add(const TypedList &subj, const AclAuthorizationSet &auths, const char *tag /* = NULL */) +{ + AclEntryInfo &info = at(size()); + info.proto() = AclEntryPrototype(subj); + info.proto().authorization() = AuthorizationGroup(auths, allocator()); + info.proto().tag(tag); + info.handle(size()); +} + +void AutoAclEntryInfoList::addPin(const TypedList &subj, uint32 slot) +{ + char tag[20]; + snprintf(tag, sizeof(tag), "PIN%d", slot); + add(subj, CSSM_ACL_AUTHORIZATION_PREAUTH(slot), tag); +} + +void AutoAclEntryInfoList::addPinState(uint32 slot, uint32 status) +{ + char tag[20]; + snprintf(tag, sizeof(tag), "PIN%d?", slot); + TypedList subj(allocator(), CSSM_WORDID_PIN, + new(allocator()) ListElement(slot), + new(allocator()) ListElement(status)); + add(subj, CSSM_WORDID_PIN, tag); +} + +void AutoAclEntryInfoList::addPinState(uint32 slot, uint32 status, uint32 count) +{ + char tag[20]; + snprintf(tag, sizeof(tag), "PIN%d?", slot); + TypedList subj(allocator(), CSSM_WORDID_PIN, + new(allocator()) ListElement(slot), + new(allocator()) ListElement(status), + new(allocator()) ListElement(count)); + add(subj, CSSM_WORDID_PIN, tag); +} + +uint32 pinFromAclTag(const char *tag, const char *suffix /* = NULL */) +{ + if (tag) { + char format[20]; + snprintf(format, sizeof(format), "PIN%%d%s%%n", suffix ? suffix : ""); + uint32 pin; + unsigned consumed; + sscanf(tag, format, &pin, &consumed); + if (consumed == strlen(tag)) // complete and sufficient + return pin; + } + return 0; +} + +} // namespace Security diff --git a/libsecurity_cdsa_utilities/lib/cssmaclpod.h b/libsecurity_cdsa_utilities/lib/cssmaclpod.h new file mode 100644 index 00000000..7e4acc0e --- /dev/null +++ b/libsecurity_cdsa_utilities/lib/cssmaclpod.h @@ -0,0 +1,356 @@ +/* + * Copyright (c) 2000-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@ + */ + + +// +// cssmaclpod - enhanced PodWrappers for ACL-related CSSM data structures +// +#ifndef _CSSMACLPOD +#define _CSSMACLPOD + +#include +#include +#include + +namespace Security { + +// a nicer name for an authorization tag +typedef CSSM_ACL_AUTHORIZATION_TAG AclAuthorization; + + +// +// An STL set of authorization tags, with some convenience features +// +class AclAuthorizationSet : public std::set { +public: + AclAuthorizationSet() { } + AclAuthorizationSet(AclAuthorization auth) { insert(auth); } + AclAuthorizationSet(AclAuthorization *authBegin, AclAuthorization *authEnd) + : set(authBegin, authEnd) { } + AclAuthorizationSet(AclAuthorization a1, AclAuthorization a2, ...); // list of auths, end with zero +}; + + +// +// Enhanced POD Wrappers for the public ACL-related CSSM structures +// +class AuthorizationGroup : public PodWrapper { +public: + AuthorizationGroup() { NumberOfAuthTags = 0; } + AuthorizationGroup(const AclAuthorizationSet &, Allocator &alloc); + AuthorizationGroup(AclAuthorization tag, Allocator &alloc); + void destroy(Allocator &alloc); + + bool empty() const { return NumberOfAuthTags == 0; } + unsigned int size() const { return NumberOfAuthTags; } + unsigned int count() const { return NumberOfAuthTags; } + CSSM_ACL_AUTHORIZATION_TAG operator [] (unsigned ix) const + { assert(ix < size()); return AuthTags[ix]; } + + bool contains(CSSM_ACL_AUTHORIZATION_TAG tag) const; + operator AclAuthorizationSet () const; +}; + +class AclOwnerPrototype; + +class AclEntryPrototype : public PodWrapper { +public: + AclEntryPrototype() { clearPod(); } + explicit AclEntryPrototype(const AclOwnerPrototype &proto); + AclEntryPrototype(const CSSM_LIST &subj, bool delegate = false) + { clearPod(); TypedSubject = subj; Delegate = delegate; } + + TypedList &subject() { return TypedList::overlay(TypedSubject); } + const TypedList &subject() const { return TypedList::overlay(TypedSubject); } + + bool delegate() const { return Delegate; } + void delegate(bool d) { Delegate = d; } + + char *tag() { return EntryTag[0] ? EntryTag : NULL; } + void tag(const char *tagString); + void tag(const std::string &tagString); + const char *tag() const { return EntryTag[0] ? EntryTag : NULL; } + std::string s_tag() const { return EntryTag; } + + AuthorizationGroup &authorization() { return AuthorizationGroup::overlay(Authorization); } + const AuthorizationGroup &authorization() const + { return AuthorizationGroup::overlay(Authorization); } +}; + +class AclOwnerPrototype : public PodWrapper { +public: + AclOwnerPrototype() { clearPod(); } + explicit AclOwnerPrototype(const AclEntryPrototype &proto) + { TypedSubject = proto.subject(); delegate(proto.delegate()); } + AclOwnerPrototype(const CSSM_LIST &subj, bool del = false) + { TypedSubject = subj; delegate(del); } + + TypedList &subject() { return TypedList::overlay(TypedSubject); } + const TypedList &subject() const { return TypedList::overlay(TypedSubject); } + bool delegate() const { return Delegate; } + void delegate(bool d) { Delegate = d; } +}; + +class AclEntryInfo : public PodWrapper { +public: + AclEntryInfo() { clearPod(); } + AclEntryInfo(const AclEntryPrototype &prot, CSSM_ACL_HANDLE h = 0) + { proto() = prot; handle() = h; } + + AclEntryPrototype &proto() { return AclEntryPrototype::overlay(EntryPublicInfo); } + const AclEntryPrototype &proto() const + { return AclEntryPrototype::overlay(EntryPublicInfo); } + + operator AclEntryPrototype &() { return proto(); } + operator const AclEntryPrototype &() const { return proto(); } + + CSSM_ACL_HANDLE &handle() { return EntryHandle; } + const CSSM_ACL_HANDLE &handle() const { return EntryHandle; } + void handle(CSSM_ACL_HANDLE h) { EntryHandle = h; } +}; + +class AclEntryInput : public PodWrapper { +public: + AclEntryInput() { clearPod(); } + AclEntryInput(const CSSM_ACL_ENTRY_PROTOTYPE &prot) + { Prototype = prot; Callback = NULL; CallerContext = NULL; } + + AclEntryInput &operator = (const CSSM_ACL_ENTRY_PROTOTYPE &prot) + { Prototype = prot; Callback = NULL; CallerContext = NULL; return *this; } + + AclEntryPrototype &proto() { return AclEntryPrototype::overlay(Prototype); } + const AclEntryPrototype &proto() const { return AclEntryPrototype::overlay(Prototype); } + //@@@ not supporting callback features (yet) +}; + +class AclEdit : public PodWrapper { +public: + AclEdit(CSSM_ACL_EDIT_MODE m, CSSM_ACL_HANDLE h, const AclEntryInput *data) + { EditMode = m; OldEntryHandle = h; NewEntry = data; } + AclEdit(const AclEntryInput &add) + { EditMode = CSSM_ACL_EDIT_MODE_ADD; OldEntryHandle = CSSM_INVALID_HANDLE; NewEntry = &add; } + AclEdit(CSSM_ACL_HANDLE h, const AclEntryInput &modify) + { EditMode = CSSM_ACL_EDIT_MODE_REPLACE; OldEntryHandle = h; NewEntry = &modify; } + AclEdit(CSSM_ACL_HANDLE h) + { EditMode = CSSM_ACL_EDIT_MODE_DELETE; OldEntryHandle = h; NewEntry = NULL; } + + CSSM_ACL_EDIT_MODE mode() const { return EditMode; } + CSSM_ACL_HANDLE handle() const { return OldEntryHandle; } + const AclEntryInput *newEntry() const { return AclEntryInput::overlay(NewEntry); } +}; + + +// +// Allocating versions of Acl structures +// +class AutoAclOwnerPrototype { + NOCOPY(AutoAclOwnerPrototype) +public: + // allocator can be set after construction + AutoAclOwnerPrototype(Allocator *allocator = NULL) + : mAclOwnerPrototype(NULL), mAllocator(allocator) { } + ~AutoAclOwnerPrototype(); + + operator bool () const { return mAllocator; } + bool operator ! () const { return !mAllocator; } + + operator AclOwnerPrototype * () { return make(); } + operator AclOwnerPrototype & () { return *make(); } + AclOwnerPrototype &operator * () { return *make(); } + + TypedList &subject() { return make()->subject(); } + TypedList &subject() const + { assert(mAclOwnerPrototype); return mAclOwnerPrototype->subject(); } + bool delegate() const + { assert(mAclOwnerPrototype); return mAclOwnerPrototype->delegate(); } + void delegate(bool d) { make()->delegate(d); } + + void allocator(Allocator &allocator); + Allocator &allocator() const { assert(mAllocator); return *mAllocator; } + + AclOwnerPrototype &operator = (const TypedList &subj) + { make()->subject() = subj; make()->delegate(false); return *mAclOwnerPrototype; } + + const AclOwnerPrototype *release() + { AclOwnerPrototype *r = mAclOwnerPrototype; mAclOwnerPrototype = NULL; return r; } + +private: + AclOwnerPrototype *mAclOwnerPrototype; + Allocator *mAllocator; + + AclOwnerPrototype *make(); +}; + + +class AutoAclEntryInfoList { + NOCOPY(AutoAclEntryInfoList) +public: + // allocator can be set after construction + AutoAclEntryInfoList(Allocator *allocator = NULL) + : mEntries(NULL), mCount(0), mAllocator(allocator) { } + ~AutoAclEntryInfoList() { clear(); } + + operator bool () const { return mAllocator; } + bool operator ! () const { return !mAllocator; } + operator uint32 *() { return &mCount; } + operator CSSM_ACL_ENTRY_INFO ** () { return reinterpret_cast(&mEntries); } + + void allocator(Allocator &allocator); + Allocator &allocator() const { assert(mAllocator); return *mAllocator; } + + const AclEntryInfo &at(uint32 ix) const + { assert(ix < mCount); return mEntries[ix]; } + const AclEntryInfo &operator [] (uint32 ix) const { return at(ix); } + AclEntryInfo &at(uint32 ix); + AclEntryInfo &operator[] (uint32 ix) { return at(ix); } + + uint32 size() const { return mCount; } + uint32 count() const { return mCount; } + AclEntryInfo *entries() const { return mEntries; } + + void clear(); + void size(uint32 newSize); + + // structured adders. Inputs must be chunk-allocated with our Allocator + void add(const TypedList &subj, const AclAuthorizationSet &auths, const char *tag = NULL); + void addPin(const TypedList &subj, uint32 slot); + void addPinState(uint32 slot, uint32 state); + void addPinState(uint32 slot, uint32 state, uint32 count); + + void release() { mAllocator = NULL; } + +private: + AclEntryInfo *mEntries; + uint32 mCount; + Allocator *mAllocator; +}; + +// +// Extract the pin number from a "PIN%d?" tag. +// Returns 0 if the tag isn't of that form. +// +uint32 pinFromAclTag(const char *tag, const char *suffix = NULL); + + +class AutoAuthorizationGroup : public AuthorizationGroup { +public: + AutoAuthorizationGroup(Allocator &alloc) : allocator(alloc) { } + explicit AutoAuthorizationGroup(const AclAuthorizationSet &set, + Allocator &alloc) : AuthorizationGroup(set, alloc), allocator(alloc) { } + ~AutoAuthorizationGroup() { destroy(allocator); } + + Allocator &allocator; +}; + + +// +// Walkers for the CSSM API structure types +// +namespace DataWalkers { + +// AclEntryInput +template +AclEntryInput *walk(Action &operate, AclEntryInput * &input) +{ + operate(input); + walk(operate, input->proto()); + return input; +} + +template +void walk(Action &operate, AclEntryInput &input) +{ + operate(input); + walk(operate, input.proto()); +} + +// AclEntryInfo +template +void walk(Action &operate, AclEntryInfo &info) +{ + operate(info); + walk(operate, info.proto()); +} + +// AuthorizationGroup +template +void walk(Action &operate, AuthorizationGroup &auth) +{ + operate(auth); + uint32 count = auth.count(); + operate.blob(auth.AuthTags, count * sizeof(auth.AuthTags[0])); + for (uint32 n = 0; n < count; n++) + operate(auth.AuthTags[n]); +} + +template +void walk(Action &operate, CSSM_AUTHORIZATIONGROUP &auth) +{ walk(operate, static_cast(auth)); } + +// AclEntryPrototype +template +void enumerate(Action &operate, AclEntryPrototype &proto) +{ + walk(operate, proto.subject()); + walk(operate, proto.authorization()); + //@@@ ignoring validity period +} + +template +void walk(Action &operate, AclEntryPrototype &proto) +{ + operate(proto); + enumerate(operate, proto); +} + +template +AclEntryPrototype *walk(Action &operate, AclEntryPrototype * &proto) +{ + operate(proto); + enumerate(operate, *proto); + return proto; +} + +// AclOwnerPrototype +template +void walk(Action &operate, AclOwnerPrototype &proto) +{ + operate(proto); + walk(operate, proto.subject()); +} + +template +AclOwnerPrototype *walk(Action &operate, AclOwnerPrototype * &proto) +{ + operate(proto); + walk(operate, proto->subject()); + return proto; +} + + +} // end namespace DataWalkers + +} // end namespace Security + + +#endif //_CSSMACLPOD diff --git a/libsecurity_cdsa_utilities/lib/cssmalloc.cpp b/libsecurity_cdsa_utilities/lib/cssmalloc.cpp new file mode 100644 index 00000000..1df102b7 --- /dev/null +++ b/libsecurity_cdsa_utilities/lib/cssmalloc.cpp @@ -0,0 +1,87 @@ +/* + * 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@ + */ + + +// +// cssmalloc - memory allocation in the CDSA world. +// +// Don't eat heavily before inspecting this code. +// +#include +#include +#include + + + +namespace Security { + + +// +// CssmMemoryFunctionsAllocators +// +void *CssmMemoryFunctionsAllocator::malloc(size_t size) throw(std::bad_alloc) +{ return functions.malloc(size); } + +void CssmMemoryFunctionsAllocator::free(void *addr) throw() +{ return functions.free(addr); } + +void *CssmMemoryFunctionsAllocator::realloc(void *addr, size_t size) throw(std::bad_alloc) +{ return functions.realloc(addr, size); } + + +// +// CssmAllocatorMemoryFunctions +// +CssmAllocatorMemoryFunctions::CssmAllocatorMemoryFunctions(Allocator &alloc) +{ + AllocRef = &alloc; + malloc_func = relayMalloc; + free_func = relayFree; + realloc_func = relayRealloc; + calloc_func = relayCalloc; +} + +void *CssmAllocatorMemoryFunctions::relayMalloc(size_t size, void *ref) throw(std::bad_alloc) +{ return allocator(ref).malloc(size); } + +void CssmAllocatorMemoryFunctions::relayFree(void *mem, void *ref) throw() +{ allocator(ref).free(mem); } + +void *CssmAllocatorMemoryFunctions::relayRealloc(void *mem, size_t size, void *ref) throw(std::bad_alloc) +{ return allocator(ref).realloc(mem, size); } + +void *CssmAllocatorMemoryFunctions::relayCalloc(uint32 count, size_t size, void *ref) throw(std::bad_alloc) +{ + // Allocator doesn't have a calloc() method + void *mem = allocator(ref).malloc(size * count); + memset(mem, 0, size * count); + return mem; +} + + +// +// CssmVector +// + + +} // namespace Security diff --git a/libsecurity_cdsa_utilities/lib/cssmalloc.h b/libsecurity_cdsa_utilities/lib/cssmalloc.h new file mode 100644 index 00000000..e1a39cb1 --- /dev/null +++ b/libsecurity_cdsa_utilities/lib/cssmalloc.h @@ -0,0 +1,155 @@ +/* + * 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@ + */ + + +// +// cssmalloc - memory allocation in the CDSA world +// +#ifndef _H_CSSMALLOC +#define _H_CSSMALLOC + +#include +#include +#include + + +namespace Security +{ + + +// +// A POD wrapper for the memory functions structure passed around in CSSM. +// +class CssmMemoryFunctions : public PodWrapper { +public: + CssmMemoryFunctions(const CSSM_MEMORY_FUNCS &funcs) + { *(CSSM_MEMORY_FUNCS *)this = funcs; } + CssmMemoryFunctions() { } + + void *malloc(size_t size) const throw(std::bad_alloc); + void free(void *mem) const throw() { free_func(mem, AllocRef); } + void *realloc(void *mem, size_t size) const throw(std::bad_alloc); + void *calloc(uint32 count, size_t size) const throw(std::bad_alloc); + + bool operator == (const CSSM_MEMORY_FUNCS &other) const throw() + { return !memcmp(this, &other, sizeof(*this)); } +}; + +inline void *CssmMemoryFunctions::malloc(size_t size) const throw(std::bad_alloc) +{ + if (void *addr = malloc_func(size, AllocRef)) + return addr; + throw std::bad_alloc(); +} + +inline void *CssmMemoryFunctions::calloc(uint32 count, size_t size) const throw(std::bad_alloc) +{ + if (void *addr = calloc_func(count, size, AllocRef)) + return addr; + throw std::bad_alloc(); +} + +inline void *CssmMemoryFunctions::realloc(void *mem, size_t size) const throw(std::bad_alloc) +{ + if (void *addr = realloc_func(mem, size, AllocRef)) + return addr; + throw std::bad_alloc(); +} + + +// +// A Allocator based on CssmMemoryFunctions +// +class CssmMemoryFunctionsAllocator : public Allocator { +public: + CssmMemoryFunctionsAllocator(const CssmMemoryFunctions &memFuncs) : functions(memFuncs) { } + + void *malloc(size_t size) throw(std::bad_alloc); + void free(void *addr) throw(); + void *realloc(void *addr, size_t size) throw(std::bad_alloc); + + operator const CssmMemoryFunctions & () const throw() { return functions; } + +private: + const CssmMemoryFunctions functions; +}; + + +// +// A MemoryFunctions object based on a Allocator. +// Note that we don't copy the Allocator object. It needs to live (at least) +// as long as any CssmAllocatorMemoryFunctions object based on it. +// +class CssmAllocatorMemoryFunctions : public CssmMemoryFunctions { +public: + CssmAllocatorMemoryFunctions(Allocator &alloc); + CssmAllocatorMemoryFunctions() { /*IFDEBUG(*/ AllocRef = NULL /*)*/ ; } // later assignment req'd + +private: + static void *relayMalloc(size_t size, void *ref) throw(std::bad_alloc); + static void relayFree(void *mem, void *ref) throw(); + static void *relayRealloc(void *mem, size_t size, void *ref) throw(std::bad_alloc); + static void *relayCalloc(uint32 count, size_t size, void *ref) throw(std::bad_alloc); + + static Allocator &allocator(void *ref) throw() + { return *reinterpret_cast(ref); } +}; + + +// +// A generic helper for the unhappily ubiquitous CSSM-style +// (count, pointer-to-array) style of arrays. +// +template +class CssmVector { +public: + CssmVector(uint32 &cnt, Base * &vec, Allocator &alloc = Allocator::standard()) + : count(cnt), vector(reinterpret_cast(vec)), + allocator(alloc) + { + count = 0; + vector = NULL; + } + + ~CssmVector() { allocator.free(vector); } + + uint32 &count; + Wrapper * &vector; + Allocator &allocator; + +public: + Wrapper &operator [] (uint32 ix) + { assert(ix < count); return vector[ix]; } + + void operator += (const Wrapper &add) + { + vector = reinterpret_cast(allocator.realloc(vector, (count + 1) * sizeof(Wrapper))); + //@@@???compiler bug??? vector = allocator.alloc(vector, count + 1); + vector[count++] = add; + } +}; + + +} // end namespace Security + +#endif //_H_CSSMALLOC diff --git a/libsecurity_cdsa_utilities/lib/cssmbridge.h b/libsecurity_cdsa_utilities/lib/cssmbridge.h new file mode 100644 index 00000000..dd1e2e99 --- /dev/null +++ b/libsecurity_cdsa_utilities/lib/cssmbridge.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2000-2001,2003-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@ + */ + + +// +// CSSM-style C/C++ bridge facilities +// +#ifndef _H_CSSMBRIDGE +#define _H_CSSMBRIDGE + +#include +#include +#include + + +namespace Security { + + +// +// API boilerplate macros. These provide a frame for C++ code that is impermeable to exceptions. +// Usage: +// BEGIN_API +// ... your C++ code here ... +// END_API(base) // returns CSSM_RETURN on exception; complete it to 'base' (DL, etc.) class; +// // returns CSSM_OK on fall-through +// END_API0 // completely ignores exceptions; falls through in all cases +// END_API1(bad) // return (bad) on exception; fall through on success +// +#define BEGIN_API try { +#define END_API(base) } \ +catch (const CommonError &err) { return CssmError::cssmError(err, CSSM_ ## base ## _BASE_ERROR); } \ +catch (const std::bad_alloc &) { return CssmError::cssmError(CSSM_ERRCODE_MEMORY_ERROR, CSSM_ ## base ## _BASE_ERROR); } \ +catch (...) { return CssmError::cssmError(CSSM_ERRCODE_INTERNAL_ERROR, CSSM_ ## base ## _BASE_ERROR); } \ + return CSSM_OK; +#define END_API0 } catch (...) { return; } +#define END_API1(bad) } catch (...) { return bad; } + + +} // end namespace Security + + +#endif //_H_CSSMBRIDGE diff --git a/libsecurity_cdsa_utilities/lib/cssmcert.cpp b/libsecurity_cdsa_utilities/lib/cssmcert.cpp new file mode 100644 index 00000000..37eded60 --- /dev/null +++ b/libsecurity_cdsa_utilities/lib/cssmcert.cpp @@ -0,0 +1,88 @@ +/* + * 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@ + */ + + +// +// cssmcert - CSSM layer certificate (CL) related objects. +// +#include +#include + + +namespace Security { + + +// +// Construct an EncodedCertificate +// +EncodedCertificate::EncodedCertificate(CSSM_CERT_TYPE type, CSSM_CERT_ENCODING enc, + const CSSM_DATA *data) +{ + clearPod(); + CertType = type; + CertEncoding = enc; + if (data) + CertBlob = *data; +} + + +// +// Construct an empty CertGroup. +// +CertGroup::CertGroup(CSSM_CERT_TYPE ctype, + CSSM_CERT_ENCODING encoding, CSSM_CERTGROUP_TYPE type) +{ + clearPod(); + CertType = ctype; + CertEncoding = encoding; + CertGroupType = type; +} + + +// +// Free all memory in a CertGroup +// +void CertGroup::destroy(Allocator &allocator) +{ + switch (type()) { + case CSSM_CERTGROUP_DATA: + // array of CSSM_DATA elements + for (uint32 n = 0; n < count(); n++) + allocator.free(blobCerts()[n].data()); + allocator.free (blobCerts ()); + break; + case CSSM_CERTGROUP_ENCODED_CERT: + for (uint32 n = 0; n < count(); n++) + allocator.free(encodedCerts()[n].data()); + allocator.free (blobCerts ()); + break; + case CSSM_CERTGROUP_PARSED_CERT: + // CSSM_PARSED_CERTS array -- unimplemented + case CSSM_CERTGROUP_CERT_PAIR: + // CSSM_CERT_PAIR array -- unimplemented + break; + } +} + + +} // end namespace Security diff --git a/libsecurity_cdsa_utilities/lib/cssmcert.h b/libsecurity_cdsa_utilities/lib/cssmcert.h new file mode 100644 index 00000000..2090685e --- /dev/null +++ b/libsecurity_cdsa_utilities/lib/cssmcert.h @@ -0,0 +1,125 @@ +/* + * 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@ + */ + + +// +// cssmcert - CSSM layer certificate (CL) related objects. +// +#ifndef _H_CSSMCERT +#define _H_CSSMCERT + +#include +#include + + +namespace Security { + + +// +// A CSSM_FIELD, essentially an OID/Data pair. +// +class CssmField : public PodWrapper { +public: + CssmField() { } + CssmField(const CSSM_OID &oid, const CSSM_DATA &value) + { FieldOid = oid; FieldValue = value; } + + CssmField(const CSSM_OID &oid) + { FieldOid = oid; FieldValue = CssmData(); } + +public: + CssmOid &oid() { return CssmOid::overlay(FieldOid); } + CssmOid &value() { return CssmOid::overlay(FieldValue); } + const CssmOid &oid() const { return CssmOid::overlay(FieldOid); } + const CssmOid &value() const { return CssmOid::overlay(FieldValue); } + + bool isComplex() const + { return value().length() == CSSM_FIELDVALUE_COMPLEX_DATA_TYPE; } +}; + + +// +// An encoded certificate +// +class EncodedCertificate : public PodWrapper { +public: + EncodedCertificate(CSSM_CERT_TYPE type = CSSM_CERT_UNKNOWN, + CSSM_CERT_ENCODING enc = CSSM_CERT_ENCODING_UNKNOWN, + const CSSM_DATA *data = NULL); + + CSSM_CERT_TYPE type() const { return CertType; } + CSSM_CERT_ENCODING encoding() const { return CertEncoding; } + const CssmData &blob() const { return CssmData::overlay(CertBlob); } + + // CssmDataoid features + void *data() const { return blob().data(); } + size_t length() const { return blob().length(); } +}; + + +// +// CertGroups - groups of certificates in a bewildering variety of forms +// +class CertGroup : public PodWrapper { +public: + CertGroup() { } + CertGroup(CSSM_CERT_TYPE ctype, CSSM_CERT_ENCODING encoding, CSSM_CERTGROUP_TYPE type); + +public: + CSSM_CERT_TYPE certType() const { return CertType; } + CSSM_CERT_ENCODING encoding() const { return CertEncoding; } + CSSM_CERTGROUP_TYPE type() const { return CertGroupType; } + uint32 count() const { return NumCerts; } + uint32 &count() { return NumCerts; } + +public: + // CSSM_CERTGROUP_DATA version + CssmData * &blobCerts() + { assert(type() == CSSM_CERTGROUP_DATA); return CssmData::overlayVar(GroupList.CertList); } + CssmData *blobCerts() const + { assert(type() == CSSM_CERTGROUP_DATA); return CssmData::overlay(GroupList.CertList); } + + // CSSM_CERTGROUP_ENCODED_CERT version + EncodedCertificate * &encodedCerts() + { return EncodedCertificate::overlayVar(GroupList.EncodedCertList); } + EncodedCertificate *encodedCerts() const + { return EncodedCertificate::overlay(GroupList.EncodedCertList); } + +public: + // free all memory in this group with the given allocator + void destroy(Allocator &allocator); +}; + + +// +// Walkers +// +namespace DataWalkers { + + + + +} // end namespace DataWalkers +} // end namespace Security + +#endif //_H_CSSMCERT diff --git a/libsecurity_cdsa_utilities/lib/cssmcred.cpp b/libsecurity_cdsa_utilities/lib/cssmcred.cpp new file mode 100644 index 00000000..72cf2645 --- /dev/null +++ b/libsecurity_cdsa_utilities/lib/cssmcred.cpp @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2000-2001,2003-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@ + */ + + +// +// cssmcred - enhanced PodWrappers and construction aids for ACL credentials +// +#include + + +namespace Security { + + +// +// The null credential constant. +// +static const CSSM_ACCESS_CREDENTIALS null_credentials = { "" }; // and more nulls +#if BUG_GCC +const AccessCredentials &AccessCredentials::null = + *static_cast(&null_credentials); +#else +const AccessCredentials &AccessCredentials::null = + static_cast(null_credentials); +#endif + + +// +// Scan a SampleGroup for samples with a given CSSM_SAMPLE_TYPE. +// Collect all matching samples into a list (which is cleared to begin with). +// Return true if any were found, false if none. +// Throw if any of the samples are obviously malformed. +// +bool SampleGroup::collect(CSSM_SAMPLE_TYPE sampleType, list &matches) const +{ + for (uint32 n = 0; n < length(); n++) { + TypedList sample = (*this)[n]; + sample.checkProper(); + if (sample.type() == sampleType) { + sample.snip(); // skip sample type + matches.push_back(sample); + } + } + return !matches.empty(); +} + + +// +// AccessCredentials +// +void AccessCredentials::tag(const char *tagString) +{ + if (tagString == NULL) + EntryTag[0] = '\0'; + else if (strlen(tagString) > CSSM_MODULE_STRING_SIZE) + CssmError::throwMe(CSSM_ERRCODE_INVALID_ACL_ENTRY_TAG); + else + strcpy(EntryTag, tagString); +} + + +// +// AutoCredentials self-constructing credentials structure +// +AutoCredentials::AutoCredentials(Allocator &alloc) : allocator(alloc) +{ + init(); +} + +AutoCredentials::AutoCredentials(Allocator &alloc, uint32 nSamples) : allocator(alloc) +{ + init(); + getSample(nSamples - 1); // extend array to nSamples elements +} + +void AutoCredentials::init() +{ + sampleArray = NULL; + nSamples = 0; +} + + +CssmSample &AutoCredentials::getSample(uint32 n) +{ + if (n >= nSamples) { + sampleArray = allocator.alloc(sampleArray, nSamples = n + 1); + Samples.Samples = sampleArray; + Samples.NumberOfSamples = nSamples; + } + return sampleArray[n]; +} + +} // end namespace Security diff --git a/libsecurity_cdsa_utilities/lib/cssmcred.h b/libsecurity_cdsa_utilities/lib/cssmcred.h new file mode 100644 index 00000000..045ff7ed --- /dev/null +++ b/libsecurity_cdsa_utilities/lib/cssmcred.h @@ -0,0 +1,191 @@ +/* + * 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@ + */ + + +// +// cssmcred - enhanced PodWrappers and construction aids for ACL credentials +// +#ifndef _CSSMCRED +#define _CSSMCRED + +#include +#include +#include +#include + +namespace Security { + + +// +// PodWrappers for samples and sample groups +// +class CssmSample : public PodWrapper { +public: + CssmSample(const TypedList &list) + { TypedSample = list; Verifier = NULL; } + CssmSample(const TypedList &list, const CssmSubserviceUid &ver) + { TypedSample = list; Verifier = &ver; } + + TypedList &value() { return TypedList::overlay(TypedSample); } + const TypedList &value() const { return TypedList::overlay(TypedSample); } + operator TypedList & () { return value(); } + + const CssmSubserviceUid *verifier() const { return CssmSubserviceUid::overlay(Verifier); } + CssmSubserviceUid * &verifier() + { return const_cast(CssmSubserviceUid::overlayVar(Verifier)); } +}; + +class SampleGroup : public PodWrapper { +public: + SampleGroup() { clearPod(); } + SampleGroup(CssmSample &single) { NumberOfSamples = 1; Samples = &single; } + + uint32 size() const { return NumberOfSamples; } + uint32 length() const { return size(); } // legacy; prefer size() + CssmSample *&samples() { return CssmSample::overlayVar(const_cast(Samples)); } + CssmSample *samples() const { return CssmSample::overlay(const_cast(Samples)); } + + CssmSample &operator [] (uint32 ix) const + { assert(ix < size()); return samples()[ix]; } + +public: + // extract all samples of a given sample type. return true if any found + // note that you get a shallow copy of the sample structures for temporary use ONLY + bool collect(CSSM_SAMPLE_TYPE sampleType, list &samples) const; +}; + + +// +// The PodWrapper for the top-level CSSM credentials structure +// +class AccessCredentials : public PodWrapper { +public: + AccessCredentials() { clearPod(); } + explicit AccessCredentials(const SampleGroup &samples, const char *tag = NULL) + { this->samples() = samples; this->tag(tag); } + explicit AccessCredentials(const SampleGroup &samples, const std::string &tag) + { this->samples() = samples; this->tag(tag); } + + const char *tag() const { return EntryTag[0] ? EntryTag : NULL; } + std::string s_tag() const { return EntryTag; } + void tag(const char *tagString); + void tag(const std::string &tagString) { return tag(tagString.c_str()); } + + SampleGroup &samples() { return SampleGroup::overlay(Samples); } + const SampleGroup &samples() const { return SampleGroup::overlay(Samples); } + + // pass-throughs to our SampleGroup + uint32 size() const { return samples().size(); } + CssmSample &operator [] (uint32 ix) const { return samples()[ix]; } + +public: + static const AccessCredentials &null; // all null credential + + // turn NULL into a null credential if needed + static const AccessCredentials *needed(const CSSM_ACCESS_CREDENTIALS *cred) + { return cred ? overlay(cred) : &null; } +}; + + +// +// An AccessCredentials object with some construction help. +// Note that this is NOT a PodWrapper. +// +class AutoCredentials : public AccessCredentials { +public: + AutoCredentials(Allocator &alloc); + AutoCredentials(Allocator &alloc, uint32 nSamples); + + Allocator &allocator; + + CssmSample &sample(uint32 n) { return getSample(n); } + + CssmSample &append(const CssmSample &sample) + { return getSample(samples().length()) = sample; } + TypedList &append(const TypedList &exhibit) + { return (getSample(samples().length()) = exhibit).value(); } + + CssmSample &operator += (const CssmSample &sample) { return append(sample); } + TypedList &operator += (const TypedList &exhibit) { return append(exhibit); } + +private: + void init(); + CssmSample &getSample(uint32 n); + + CssmSample *sampleArray; + uint32 nSamples; +}; + + +// +// Walkers for the CSSM API structure types. +// Note that there are irrational "const"s strewn about the credential sub-structures. +// They make it essentially impossible to incrementally construction them without +// violating them. Since we know what we're doing, we do. +// +namespace DataWalkers +{ + +// CssmSample (with const override) +template +void walk(Action &operate, CssmSample &sample) +{ + operate(sample); + walk(operate, sample.value()); + if (sample.verifier()) + walk(operate, sample.verifier()); +} + +// SampleGroup +template +void walk(Action &operate, SampleGroup &samples) +{ + operate(samples); + enumerateArray(operate, samples, &SampleGroup::samples); +} + +// AccessCredentials +template +AccessCredentials *walk(Action &operate, AccessCredentials * &cred) +{ + operate(cred); + //@@@ ignoring BaseCerts + walk(operate, cred->samples()); + //@@@ ignoring challenge callback + return cred; +} + +template +CSSM_ACCESS_CREDENTIALS *walk(Action &operate, CSSM_ACCESS_CREDENTIALS * &cred) +{ return walk(operate, AccessCredentials::overlayVar(cred)); } + +template +AutoCredentials *walk(Action &operate, AutoCredentials * &cred) +{ return (AutoCredentials *)walk(operate, (AccessCredentials * &)cred); } + + +} // end namespace DataWalkers +} // end namespace Security + + +#endif //_CSSMCRED diff --git a/libsecurity_cdsa_utilities/lib/cssmdata.cpp b/libsecurity_cdsa_utilities/lib/cssmdata.cpp new file mode 100644 index 00000000..661d29b7 --- /dev/null +++ b/libsecurity_cdsa_utilities/lib/cssmdata.cpp @@ -0,0 +1,248 @@ +/* + * 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@ + */ + + +// +// cssmdata.cpp -- Manager different CssmData types +// +#include +#include +#include +#include + + +namespace Security { + + +// +// Comparing raw CSSM_DATA things +// +bool operator == (const CSSM_DATA &d1, const CSSM_DATA &d2) +{ + if (&d1 == &d2) + return true; // identical + if (d1.Length != d2.Length) + return false; // can't be + if (d1.Data == d2.Data) + return true; // points to same data + return !memcmp(d1.Data, d2.Data, d1.Length); +} + + +// +// CssmData out of line members +// +string CssmData::toString() const +{ + return data() ? + string(reinterpret_cast(data()), length()) + : + string(); +} + + +// +// Conversion from/to hex digits. +// This could be separate functions, or Rep templates, but we just hang +// it onto generic CssmData. +// +string CssmData::toHex() const +{ + static const char digits[] = "0123456789abcdef"; + string result; + unsigned char *p = Data; + for (uint32 n = 0; n < length(); n++) { + result.push_back(digits[p[n] >> 4]); + result.push_back(digits[p[n] & 0xf]); + } + return result; +} + +static unsigned char hexValue(char c) +{ + static const char digits[] = "0123456789abcdef"; + if (const char *p = strchr(digits, tolower(c))) + return p - digits; + else + return 0; +} + +void CssmData::fromHex(const char *hexDigits) +{ + size_t bytes = strlen(hexDigits) / 2; // (discards malformed odd end) + length(bytes); // (will assert if we try to grow it) + for (size_t n = 0; n < bytes; n++) { + Data[n] = hexValue(hexDigits[2*n]) << 4 | hexValue(hexDigits[2*n+1]); + } +} + + +// +// Conversion from/to OID strings. +// These are not strict; invalid inputs are not necessarily flagged as errors. +// +static unsigned long getOid(const CssmData &data, unsigned int &pos) +{ + unsigned long q = 0; + do { + q = q * 128 + (data.byte(pos) & ~0x80); + } while (pos < data.length() && data.byte(pos++) & 0x80); + return q; +} + +string CssmData::toOid() const +{ + if (length() == 0) + return ""; + + unsigned int pos = 0; + + // first byte is composite (q1,q2) + char buffer[10]; + unsigned long oid1 = getOid(*this, pos); + unsigned int q1 = min(oid1 / 40, 2ul); + snprintf(buffer, sizeof(buffer), "%u.%lu", q1, oid1 - q1 * 40); + string s = buffer; + + // now for the rest + while (pos < length()) { + char buffer[20]; + snprintf(buffer, sizeof(buffer), ".%lu", getOid(*this, pos)); + s += buffer; + } + return s; +} + +static void putOid(CssmOwnedData &data, unsigned long id) +{ + unsigned char buffer[sizeof(unsigned long) * 2]; // * (8/7) + 1, conservative + unsigned char *p = buffer + sizeof(buffer); + do { + *--p = 0x80 | (id & 0x7F); // last 7 bits, high bit set + } while ((id >>= 7) > 0); + buffer[sizeof(buffer) - 1] &= ~0x80; // clear last high bit (end of number) + data.append(p, buffer + sizeof(buffer) - p); // append generated byte string +} + +// +// Convert OID string (1.2.3...) into CssmOid form. +// Allocates the data, replacing current contents. +// Will not process oid elements out of unsigned long range. +// +void CssmOwnedData::fromOid(const char *oid) +{ + this->length(0); // make empty + + // first two elements get combined in weird&wacky ways + unsigned long q1 = strtoul(oid, (char **)&oid, 10); + if (*oid++ != '.') + return; + unsigned long q2 = strtoul(oid, (char **)&oid, 10); + putOid(*this, 40 * q1 + q2); + while (oid[0] == '.') { + oid++; + putOid(*this, strtoul(oid, (char **)&oid, 10)); + } +} + + +// +// Managed data objects +// +CssmManagedData::~CssmManagedData() +{ } + + +// +// CssmOwnedData +// +void CssmOwnedData::set(CssmManagedData &source) +{ + if (source.length() == 0) { // source is empty + reset(); // so just clear old data + } else if (allocator == source.allocator) { // compatible allocators + if (referent.data() == source.data()) { // same data *and* we own it?! + assert(this == &source); // this better *be* me! + } else { // different data + reset(); // give up our old data + referent = source.release(); // take over source's data + } + } else { // different allocators + copy(source); // make a copy with our allocator + source.reset(); // release source's data + } +} + + +// +// CssmAutoData +// +CssmData CssmAutoData::release() +{ + CssmData result = mData; + mData.clear(); + return result; +} + +void CssmAutoData::reset() +{ + allocator.free(mData); + mData.clear(); +} + + +// +// CssmRemoteData +// +CssmData CssmRemoteData::release() +{ + iOwnTheData = false; + return referent; +} + +void CssmRemoteData::reset() +{ + if (iOwnTheData) + allocator.free(referent); + referent.clear(); +} + + +// +// Date stuff +// +CssmDateData::CssmDateData(const CSSM_DATE &date) +: CssmData(buffer, sizeof(buffer)) +{ + memcpy(buffer, date.Year, 4); + memcpy(buffer + 4, date.Month, 2); + memcpy(buffer + 6, date.Day, 2); +} + + +CssmData& CssmOwnedData::get() const throw() +{ + return referent; +} + +} // end namespace Security diff --git a/libsecurity_cdsa_utilities/lib/cssmdata.h b/libsecurity_cdsa_utilities/lib/cssmdata.h new file mode 100644 index 00000000..a55d0f37 --- /dev/null +++ b/libsecurity_cdsa_utilities/lib/cssmdata.h @@ -0,0 +1,561 @@ +/* + * Copyright (c) 2000-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@ + */ + + +// +// cssmdata.h -- Manager different CssmData types +// +#ifndef _H_CDSA_UTILITIES_CSSMDATA +#define _H_CDSA_UTILITIES_CSSMDATA + +#include +#include +#include +#include +#include + +namespace Security { + + +// +// User-friendlier CSSM_DATA thingies. +// CssmData is a PODWrapper for CSSM_DATA, but is also used throughout +// the security code as a "byte blob" representation. +// +class CssmData : public PodWrapper { +public: + CssmData() { Data = 0; Length = 0; } + + size_t length() const { return Length; } + void *data() const { return Data; } + void *end() const { return Data + Length; } + + // + // Create a CssmData from any pointer-to-byte-sized-object and length. + // + CssmData(void *data, size_t length) + { Data = reinterpret_cast(data); Length = length; } + CssmData(char *data, size_t length) + { Data = reinterpret_cast(data); Length = length; } + CssmData(unsigned char *data, size_t length) + { Data = reinterpret_cast(data); Length = length; } + CssmData(signed char *data, size_t length) + { Data = reinterpret_cast(data); Length = length; } + + CssmData(CFDataRef cf) + { Data = const_cast(CFDataGetBytePtr(cf)); Length = CFDataGetLength(cf); } + + // the void * form accepts too much; explicitly deny all other types + private: template CssmData(T *, size_t); public: + + // explicitly construct from a data-oid source + template + explicit CssmData(const T &obj) + { Data = (UInt8 *)obj.data(); Length = obj.length(); } + + // + // Do allow generic "wrapping" of any data structure, but make it conspicuous + // since it's not necessarily the Right Thing (alignment and byte order wise). + // Also note that the T & form removes const-ness, since there is no ConstCssmData. + // + template + static CssmData wrap(const T &it) + { return CssmData(const_cast(reinterpret_cast(&it)), sizeof(it)); } + + template + static CssmData wrap(T *data, size_t length) + { return CssmData(const_cast(static_cast(data)), length); } + + // + // Automatically convert a CssmData to any pointer-to-byte-sized-type. + // + operator signed char * () const { return reinterpret_cast(Data); } + operator unsigned char * () const { return reinterpret_cast(Data); } + operator char * () const { return reinterpret_cast(Data); } + operator void * () const { return reinterpret_cast(Data); } + + // + // If you want to interpret the contents of a CssmData blob as a particular + // type, you have to be more explicit to show that you know what you're doing. + // See wrap() above. + // + template + T *interpretedAs() const { return reinterpret_cast(Data); } + + template + T *interpretedAs(CSSM_RETURN error) const + { return interpretedAs(sizeof(T), error); } + + template + T *interpretedAs(size_t len, CSSM_RETURN error) const + { + if (data() == NULL || length() != len) CssmError::throwMe(error); + return interpretedAs(); + } + +public: + void length(size_t newLength) // shorten only + { assert(newLength <= Length); Length = newLength; } + + void *at(off_t offset) const + { assert(offset >= 0 && (CSSM_SIZE)offset <= Length); return Data + offset; } + void *at(off_t offset, size_t size) const // length-checking version + { assert(offset >= 0 && (CSSM_SIZE)offset + size <= Length); return Data + offset; } + + template T *at(off_t offset) const { return reinterpret_cast(at(offset)); } + template T *at(off_t offset, size_t size) const + { return reinterpret_cast(at(offset, size)); } + + unsigned char byte(off_t offset) const { return *at(offset); } + unsigned char &byte(off_t offset) { return *at(offset); } + + void *use(size_t taken) // logically remove some bytes + { assert(taken <= Length); void *r = Data; Length -= taken; Data += taken; return r; } + + void clear() + { Data = NULL; Length = 0; } + + string toString () const; // convert to string type (no trailing null) + string toHex() const; // hex string of binary blob + string toOid() const; // standard OID string encoding (1.2.3...) + void fromHex(const char *digits); // fill myself with hex data (no allocation) + + operator bool () const { return Data != NULL; } + bool operator ! () const { return Data == NULL; } + bool operator < (const CssmData &other) const; + bool operator == (const CssmData &other) const + { return length() == other.length() && !memcmp(data(), other.data(), length()); } + bool operator != (const CssmData &other) const + { return !(*this == other); } + + // Extract fixed-format data from a CssmData. Fixes any alignment trouble for you. + template + void extract(T &destination, CSSM_RETURN error = CSSM_ERRCODE_INVALID_DATA) const + { + if (length() != sizeof(destination) || data() == NULL) + CssmError::throwMe(error); + memcpy(&destination, data(), sizeof(destination)); + } +}; + + +inline bool CssmData::operator < (const CssmData &other) const +{ + if (Length != other.Length) // If lengths are not equal the shorter data is smaller. + return Length < other.Length; + if (Length == 0) // If lengths are both zero ignore the Data. + return false; + if (Data == NULL || other.Data == NULL) // arbitrary (but consistent) ordering + return Data < other.Data; + return memcmp(Data, other.Data, Length) < 0; // Do a lexicographic compare on equal sized Data. +} + + +// +// CSSM_OIDs are CSSM_DATAs but will probably have different wrapping characteristics. +// +typedef CssmData CssmOid; + + +// +// A convenient way to make a CssmData from a (const) string. +// Note that the underlying string is not memory-managed, so it +// should either be static or of sufficient (immutable) lifetime. +// +class StringData : public CssmData { +public: + StringData(const char *s) : CssmData(const_cast(s), strlen(s)) { } + StringData(const std::string &s) : CssmData(const_cast(s.c_str()), s.size()) { } +}; + + +// +// A CssmData bundled up with a data buffer it refers to +// +template +struct DataBuffer : public CssmData { + unsigned char buffer[size]; + DataBuffer() : CssmData(buffer, size) { } +}; + + +// +// Comparing CssmDatas for equality. +// Note: No ordering is established here. +// Both CSSM_DATAs have to exist. +// +bool operator == (const CSSM_DATA &d1, const CSSM_DATA &d2); +inline bool operator != (const CSSM_DATA &d1, const CSSM_DATA &d2) +{ return !(d1 == d2); } + + +// +// The following pseudo-code describes what (at minimum) is required for a class +// to be a "PseudoData". PseudoData arguments ("DataOids") are used in templates. +// +// class PseudoData { +// void *data() const ... +// size_t length() const ... +// operator const CssmData &() const ... +// } +// +// All this can be satisfied, of course, by inheriting from CssmData. +// + + +// +// A common virtual parent for CssmData-like objects that actively manage the +// allocation status of their data blob. Note that this is about allocating +// the data(), not the CssmData structure itself. +// The ManagedData layer provides for little active memory management, since +// the underlying strategies are potentially very disparate. It does however +// have a well defined interface for *yielding up* its data for copying or transfer. +// +class CssmManagedData { +public: + CssmManagedData(Allocator &alloc) : allocator(alloc) { } + virtual ~CssmManagedData(); + + Allocator &allocator; + + virtual operator const CssmData & () const { return get(); } + template T *data() const { return reinterpret_cast(data()); } + void *data() const { return get().data(); } + size_t length() const { return get().length(); } + + virtual CssmData &get() const throw() = 0; // get shared copy, no ownership change + virtual CssmData release() = 0; // give up copy, ownership is transferred + virtual void reset() = 0; // give up copy, data is discarded +}; + + +inline bool operator == (const CssmManagedData &d1, const CssmData &d2) +{ return d1.get() == d2; } + +inline bool operator == (const CssmData &d1, const CssmManagedData &d2) +{ return d1 == d2.get(); } + +inline bool operator == (const CssmManagedData &d1, const CssmManagedData &d2) +{ return d1.get() == d2.get(); } + +inline bool operator != (const CssmManagedData &d1, const CssmData &d2) +{ return d1.get() != d2; } + +inline bool operator != (const CssmData &d1, const CssmManagedData &d2) +{ return d1 != d2.get(); } + +inline bool operator != (const CssmManagedData &d1, const CssmManagedData &d2) +{ return d1.get() != d2.get(); } + + +// +// A CssmOwnedData is a CssmManagedData that unilaterally owns its data storage. +// It has its CssmData object provided during construction. +// +class CssmOwnedData : public CssmManagedData { +public: + CssmOwnedData(Allocator &alloc, CssmData &mine) : CssmManagedData(alloc), referent(mine) { } + + CssmOwnedData(Allocator &alloc, CSSM_DATA &mine) + : CssmManagedData(alloc), referent(CssmData::overlay(mine)) { referent.clear(); } + + // + // Basic retrievals (this echoes features of CssmData) + // + operator void * () const { return referent; } + operator char * () const { return referent; } + operator signed char * () const { return referent; } + operator unsigned char * () const { return referent; } + + operator bool () const { return referent; } + bool operator ! () const { return !referent; } + + size_t length() const { return referent.length(); } + + + // + // Basic allocators + // + void *malloc(size_t len) + { + // pseudo-atomic reallocation semantics + CssmAutoPtr alloc(allocator, allocator.malloc(len)); + reset(); + return referent = CssmData(alloc.release(), len); + } + + void *realloc(size_t newLen) + { + // Allocator::realloc() should be pseudo-atomic (i.e. throw on error) + return referent = CssmData(allocator.realloc(referent.data(), newLen), newLen); + } + + void length(size_t len) { realloc(len); } + + + // + // Manipulate existing data + // + void *append(const void *addData, size_t addLength) + { + size_t oldLength = length(); + realloc(oldLength + addLength); + return memcpy(referent.at(oldLength), addData, addLength); + } + + void *append(const CssmData &data) + { return append(data.data(), data.length()); } + + + // + // set() replaces current data with new, taking over ownership to the extent possible. + // + template + void set(T *data, size_t length) + { + // assume that data was allocated by our allocator -- we can't be sure + reset(); + referent = CssmData(data, length); + } + + void set(CssmManagedData &source); + void set(const CSSM_DATA &source) { set(source.Data, source.Length); } + // NOTE: General template set() cannot be used because all subclasses of CssmManagedData + // need to receive the special handling above. Use set(*.data(), *.length()) instead. + + + // + // copy() replaces current data with new, making a copy and leaving + // the source intact. + // + 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); + } + + void copy(const CssmData &source) + { if (&source != &referent) copy(source.data(), source.length()); } + void copy(const CSSM_DATA &source) + { if (&source != &referent) copy(source.Data, source.Length); } + void copy(CssmManagedData &source) { copy(source.get()); } + template + void copy(const Data &source) { copy(source.data(), source.length()); } + + + // + // Assignment conservatively uses copy if allocator unknown, set if known + // + void operator = (CssmManagedData &source) { set(source); } + void operator = (CssmOwnedData &source) { set(source); } + void operator = (const CSSM_DATA &source) { copy(source); } + + CssmData &get() const throw(); + +public: + void fromOid(const char *oid); // fill from text OID form (1.2.3...) + +protected: + CssmData &referent; +}; + + +// +// A CssmAutoData is a CssmOwnedData that includes its CssmData object. +// This is the very simple case: The object includes ownership, data object, +// and data storage. +// +class CssmAutoData : public CssmOwnedData { +public: + CssmAutoData(Allocator &alloc) : CssmOwnedData(alloc, mData) { } + + template + CssmAutoData(Allocator &alloc, const Data &source) : CssmOwnedData(alloc, mData) + { *this = source; } + + CssmAutoData(CssmAutoData &source) : CssmOwnedData(source.allocator, mData) + { set(source); } + + explicit CssmAutoData(CssmManagedData &source) : CssmOwnedData(source.allocator, mData) + { set(source); } + + CssmAutoData(Allocator &alloc, const void *data, size_t length) + : CssmOwnedData(alloc, mData) { copy(data, length); } + + ~CssmAutoData() { allocator.free(mData); } + + CssmData release(); + void reset(); + + // assignment (not usefully inherited) + void operator = (CssmManagedData &source) { set(source); } + void operator = (CssmOwnedData &source) { set(source); } + void operator = (CssmAutoData &source) { set(source); } + template + void operator = (const Data &source) { copy(source); } + +private: + CssmData mData; +}; + + +// +// A CssmRemoteData is a CssmOwnedData that uses an external CssmData object. +// Its release operation clears an internal ownership flag but does not clear +// the CssmData values so they can be used to return values to an outside scope. +// +class CssmRemoteData : public CssmOwnedData { +public: + CssmRemoteData(Allocator &alloc, CssmData &mine) + : CssmOwnedData(alloc, mine), iOwnTheData(true) { } + + CssmRemoteData(Allocator &alloc, CSSM_DATA &mine) + : CssmOwnedData(alloc, mine), iOwnTheData(true) { } + + ~CssmRemoteData() + { if (iOwnTheData) allocator.free(referent); } + + CssmData release(); + void reset(); + + // assignment (not usefully inherited) + void operator = (CssmManagedData &source) { set(source); } + void operator = (CssmOwnedData &source) { set(source); } + void operator = (CssmAutoData &source) { set(source); } + template + void operator = (const Data &source) { copy(source); } + +private: + bool iOwnTheData; +}; + + +// +// CssmPolyData +// +// Used by functions that take a CssmData and would like to allow it to be +// initialized with a static string, int or other basic type. The function *must* +// copy the Data of the CssmPolyData when doing so if it is to be used +// after the function returns. (For example by creating a CssmDataContainer from it). +class CssmPolyData : public CssmData { + template + uint8 *set(const T &it) + { return const_cast(reinterpret_cast(&it)); } +public: + template + CssmPolyData(const char_T *s) : CssmData(const_cast(s), strlen(s)) {} + CssmPolyData(const string &s) : CssmData(const_cast(s.c_str()), s.size()) {} + CssmPolyData(const CSSM_DATA &data) : CssmData(data.Data, data.Length) {} + + // Don't use a template constructor (for T &) here - it would eat way too much + CssmPolyData(const bool &t) : CssmData(set(t), sizeof(t)) { } + CssmPolyData(const uint32 &t) : CssmData(set(t), sizeof(t)) { } + CssmPolyData(const sint32 &t) : CssmData(set(t), sizeof(t)) { } + CssmPolyData(const sint64 &t) : CssmData(set(t), sizeof(t)) { } + CssmPolyData(const double &t) : CssmData(set(t), sizeof(t)) { } + CssmPolyData(const unsigned long &t) : CssmData(set(t), sizeof(t)) { } + CssmPolyData(const CSSM_GUID &t) : CssmData(set(t), sizeof(t)) { } + CssmPolyData(const StringPtr s) : CssmData (reinterpret_cast(s + 1), uint32 (s[0])) {} +}; + +class CssmDateData : public CssmData +{ +public: + CssmDateData(const CSSM_DATE &date); +private: + uint8 buffer[8]; +}; + + +// +// Non POD refcounted CssmData wrapper that own the data it refers to. +// +class CssmDataContainer : public CssmData, public RefCount +{ +public: + CssmDataContainer(Allocator &inAllocator = Allocator::standard()) : + CssmData(), mAllocator(inAllocator) {} + template + CssmDataContainer(const T *data, size_t length, Allocator &inAllocator = Allocator::standard()) : + CssmData(inAllocator.malloc(length), length), mAllocator(inAllocator) + { if (length) ::memcpy(Data, data, length); } + void clear() { if (Data) { mAllocator.free(Data); Data = NULL; Length = 0; } } + void invalidate () {Data = NULL; Length = 0;} + ~CssmDataContainer() { if (Data) mAllocator.free(Data); } + void append(const CssmPolyData &data) + { + uint32 newLength = Length + data.Length; + Data = reinterpret_cast(mAllocator.realloc(Data, newLength)); + memcpy(Data + Length, data.Data, data.Length); + Length = newLength; + } + CssmDataContainer(const CssmDataContainer &other) + : mAllocator(other.mAllocator) + { + Data = reinterpret_cast(mAllocator.malloc(other.Length)); + memcpy(Data, other.Data, other.Length); + Length = other.Length; + } + CssmDataContainer & operator = (const CSSM_DATA &other) + { + clear(); + Data = reinterpret_cast(mAllocator.malloc(other.Length)); + memcpy(Data, other.Data, other.Length); + Length = other.Length; + return *this; + } + +public: + Allocator &mAllocator; + +private: + operator CssmDataContainer * () const; // prohibit conversion-to-my-pointer +}; + +// +// CSSM_OIDs are CSSM_DATAs but will probably have different wrapping characteristics. +// +typedef CssmDataContainer CssmOidContainer; + +template +class CssmBuffer : public RefPointer +{ +public: + CssmBuffer() : RefPointer(new Container()) {} // XXX This should may just set ptr to NULL. + template + CssmBuffer(const T *data, size_t length, Allocator &inAllocator = Allocator::standard()) : + RefPointer(new Container(data, length, inAllocator)) {} + CssmBuffer(const CSSM_DATA &data, Allocator &inAllocator = Allocator::standard()) : + RefPointer(new Container(data.Data, data.Length, inAllocator)) {} + CssmBuffer(const CssmBuffer& other) : RefPointer(other) {} + CssmBuffer(Container *p) : RefPointer(p) {} + bool operator < (const CssmBuffer &other) const { return (**this) < (*other); } +}; + + +} // end namespace Security + +#endif // _H_CDSA_UTILITIES_CSSMDATA diff --git a/libsecurity_cdsa_utilities/lib/cssmdates.cpp b/libsecurity_cdsa_utilities/lib/cssmdates.cpp new file mode 100644 index 00000000..0c938a7f --- /dev/null +++ b/libsecurity_cdsa_utilities/lib/cssmdates.cpp @@ -0,0 +1,195 @@ +/* + * 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@ + */ + + +// +// Manage the Tower of Babel of CSSM dates and times +// +#include +#include +#include +#include + + +// +// A (private) PODwrapper for CFGregorianDate +// +struct Gregorian : public PodWrapper { + Gregorian() { } + + Gregorian(int y, int m, int d, int h = 0, int min = 0, double sec = 0) + { + year = y; month = m; day = d; + hour = h; minute = min; second = sec; + } + + Gregorian(CFAbsoluteTime ref) + { static_cast(*this) = CFAbsoluteTimeGetGregorianDate(ref, NULL); } + + operator CFAbsoluteTime () const + { return CFGregorianDateGetAbsoluteTime(*this, NULL); } +}; + + +// +// The CssmDate PODwrapper +// +CssmDate::CssmDate(const char *y, const char *m, const char *d) +{ + assign(years(), 4, y); + assign(months(), 2, m); + assign(days(), 2, d); +} + +CssmDate::CssmDate(int y, int m, int d) +{ + // internal format is "yyyymmdd" (no null termination) + char str[9]; + if (8 != snprintf(str, 9, "%4.4d%2.2d%2.2d", y, m, d)) + CssmError::throwMe(CSSM_ERRCODE_UNKNOWN_FORMAT); + memcpy(this, str, 8); +} + +int CssmDate::year() const +{ return atoi(string(years(), 4).c_str()); } + +int CssmDate::month() const +{ return atoi(string(months(), 2).c_str()); } + +int CssmDate::day() const +{ return atoi(string(days(), 2).c_str()); } + +// right-adjust fill +void CssmDate::assign(char *dest, int width, const char *src) +{ + // pick last width characters of src at most + int len = strlen(src); + if (len > width) + CssmError::throwMe(CSSM_ERRCODE_UNKNOWN_FORMAT); + memset(dest, '0', width - len); + memcpy(dest + width - len, src, len); +} + + +// +// CssmUniformDate core functions +// + + +// +// Uniform conversions with CFDateRef +// +CssmUniformDate::CssmUniformDate(CFDateRef ref) +{ + mTime = CFDateGetAbsoluteTime(ref); +} + +CssmUniformDate::operator CFDateRef() const +{ + return CFDateCreate(NULL, mTime); +} + + +// +// Uniform conversions with CssmDates +// +CssmUniformDate::CssmUniformDate(const CssmDate &date) +{ + mTime = CFGregorianDateGetAbsoluteTime(Gregorian(date.year(), date.month(), date.day()), + NULL); +} + +CssmUniformDate::operator CssmDate () const +{ + Gregorian greg(mTime); + return CssmDate(greg.year, greg.month, greg.day); +} + + +// +// Uniform conversions with CssmData (1999-06-30_15:05:39 form) +// +CssmUniformDate::CssmUniformDate(const CSSM_DATA &inData) +{ + const CssmData &data = CssmData::overlay(inData); + if (data.length() != 19) + CssmError::throwMe(CSSM_ERRCODE_UNKNOWN_FORMAT); + setFromString(reinterpret_cast(inData.Data), "%ld-%d-%d_%d:%d:%lf", 19); +} + +void CssmUniformDate::convertTo(CssmOwnedData &data) const +{ + Gregorian greg(mTime); + char str[20]; + if (19 != snprintf(str, 20, "%4.4d-%2.2d-%2.2d_%2.2d:%2.2d:%2.2d", + int(greg.year), greg.month, greg.day, greg.hour, greg.minute, int(greg.second))) + CssmError::throwMe(CSSM_ERRCODE_UNKNOWN_FORMAT); + data = CssmData(str, 19); +} + + +// +// Uniform conversions with CSSM_TIMESTRING (19990630150539 form) +// +CssmUniformDate::CssmUniformDate(const char *src) +{ + setFromString(src, "%4ld%2d%2d%2d%2d%2lf", 14); +} + +void CssmUniformDate::convertTo(char *dst, size_t length) const +{ + if (length < 14) + CssmError::throwMe(CSSMERR_CSSM_BUFFER_TOO_SMALL); + Gregorian greg(mTime); + char str[15]; + if (14 != snprintf(str, 15, "%4.4d%2.2d%2.2d%2.2d%2.2d%2.2d", + int(greg.year), greg.month, greg.day, greg.hour, greg.minute, int(greg.second))) + CssmError::throwMe(CSSM_ERRCODE_UNKNOWN_FORMAT); + memcpy(dst, str, length == 14 ? 14 : 15); // null terminate if there's room +} + + +// +// Generalized parse-from-string setup +// +void CssmUniformDate::setFromString(const char *src, const char *format, size_t fieldWidth) +{ + // use a stack buffer + char str[20]; + assert(fieldWidth < sizeof(str)); + + // make a copy with proper null terminator + memcpy(str, src, fieldWidth); + str[fieldWidth] = '\0'; + + // parse (with limited checks for bad field formats) + long year; + int month, day, hour, minute; + double second; + if (6 != sscanf(str, format, + &year, &month, &day, &hour, &minute, &second)) + CssmError::throwMe(CSSM_ERRCODE_UNKNOWN_FORMAT); + + // success + mTime = Gregorian(year, month, day, hour, minute, second); +} diff --git a/libsecurity_cdsa_utilities/lib/cssmdates.h b/libsecurity_cdsa_utilities/lib/cssmdates.h new file mode 100644 index 00000000..afbe3d5a --- /dev/null +++ b/libsecurity_cdsa_utilities/lib/cssmdates.h @@ -0,0 +1,127 @@ +/* + * 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@ + */ + + +// +// Manage the Tower of Babel of CSSM dates and times. +// +#ifndef _H_CSSMDATES +#define _H_CSSMDATES + +#include +#include +#include + + +namespace Security { + + +// +// A PodWrapper for CSSM_DATE +// +class CssmDate : public PodWrapper { +public: + CssmDate() { } + CssmDate(const char *y, const char *m, const char *d); + CssmDate(int y, int m, int d); + + const char *years() const { return reinterpret_cast(Year); } + const char *months() const { return reinterpret_cast(Month); } + const char *days() const { return reinterpret_cast(Day); } + char *years() { return reinterpret_cast(Year); } + char *months() { return reinterpret_cast(Month); } + char *days() { return reinterpret_cast(Day); } + + int year() const; + int month() const; + int day() const; + +private: + static void assign(char *dest, int width, const char *src); +}; + +inline bool operator == (const CSSM_DATE &d1, const CSSM_DATE &d2) +{ return !memcmp(&d1, &d2, sizeof(d1)); } + +inline bool operator != (const CSSM_DATE &d1, const CSSM_DATE &d2) +{ return !memcmp(&d1, &d2, sizeof(d1)); } + + +// +// Yet another CSSM date/time format is CSSM_TIMESTRING. This is +// defined as "char *", just so you can't use the type system +// to keep things sane, so we can't really PodWrap it the usual way. +// What *were* they thinking? +// The format is allegedly "yyyymmddhhmmss", and the standard says +// nothing about trailing null characters. +// + + +// +// A unified date-and-time object. +// This is based on CFDate objects and converts to various CSSM +// inspired formats. +// +class CssmUniformDate { +public: + CssmUniformDate() { } + + // convert to/from CFDateRef + CssmUniformDate(CFDateRef ref); + operator CFDateRef() const; + + // convert to/from CFAbsoluteTime + CssmUniformDate(CFAbsoluteTime ct) : mTime(ct) { } + operator CFAbsoluteTime() const { return mTime; } + + // convert to/from CSSM_DATE + CssmUniformDate(const CssmDate &src); + operator CssmDate () const; + + // convert to/from DATA format (1999-06-30_15:05:39 form) + CssmUniformDate(const CSSM_DATA &src); + void convertTo(CssmOwnedData &data) const; + + // convert to/from CSSM_TIMESTRING format (19990630150539) + CssmUniformDate(const char *src); + void convertTo(char *dest, size_t length) const; + + // native comparisons + bool operator < (const CssmUniformDate &other) const { return mTime < other.mTime; } + bool operator == (const CssmUniformDate &other) const { return mTime == other.mTime; } + bool operator > (const CssmUniformDate &other) const { return mTime > other.mTime; } + bool operator <= (const CssmUniformDate &other) const { return mTime <= other.mTime; } + bool operator >= (const CssmUniformDate &other) const { return mTime >= other.mTime; } + bool operator != (const CssmUniformDate &other) const { return mTime != other.mTime; } + +private: + void setFromString(const char *src, const char *format, size_t fieldLength); + +private: + CFAbsoluteTime mTime; +}; + + +} // end namespace Security + +#endif //_H_CSSMDATES diff --git a/libsecurity_cdsa_utilities/lib/cssmdb.cpp b/libsecurity_cdsa_utilities/lib/cssmdb.cpp new file mode 100644 index 00000000..5765e86d --- /dev/null +++ b/libsecurity_cdsa_utilities/lib/cssmdb.cpp @@ -0,0 +1,590 @@ +/* + * 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@ + */ + + +// cssmdb.cpp +// +// +#include + +bool DLDbIdentifier::Impl::operator < (const DLDbIdentifier::Impl &other) const +{ + if (mCssmSubserviceUid < other.mCssmSubserviceUid) + return true; + if (mCssmSubserviceUid != other.mCssmSubserviceUid) // i.e. greater than + return false; + + // Murf correctly points out that 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. + // + // if (mDbName.canonicalName() == NULL || other.mDbName.canonicalName() == NULL) + // { + // return false; + // } + + // this is the correct way + const char* a = mDbName.canonicalName(); + const char* b = other.mDbName.canonicalName(); + + if (a == NULL && b != NULL) + { + return true; // NULL is always < something + } + + if (a != NULL && b == NULL) + { + return false; // something is always >= NULL + } + + if (a == NULL && b == NULL) + { + return false; // since == is not < + } + + // if we get to this point, both are not null. No crash and the lexical value is correct. + return strcmp(a, b) < 0; +} + +bool DLDbIdentifier::Impl::operator == (const Impl &other) const +{ + bool subserviceIdEqual = mCssmSubserviceUid == other.mCssmSubserviceUid; + if (!subserviceIdEqual) + { + return false; + } + + const char* a = mDbName.canonicalName(); + const char* b = other.mDbName.canonicalName(); + + if (a == NULL && b != NULL) + { + return false; + } + + if (a != NULL && b == NULL) + { + return false; + } + + if (a == NULL && b == NULL) + { + return true; + } + + bool namesEqual = strcmp(a, b) == 0; + return namesEqual; +} + +// +// CssmDLPolyData +// +CssmDLPolyData::operator CSSM_DATE () const +{ + assert(mFormat == CSSM_DB_ATTRIBUTE_FORMAT_BLOB); + if (mData.Length != 8) + CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT); + + CSSM_DATE date; + memcpy(date.Year, mData.Data, 4); + memcpy(date.Month, mData.Data + 4, 2); + memcpy(date.Day, mData.Data + 6, 2); + return date; +} + +CssmDLPolyData::operator Guid () const +{ + assert(mFormat == CSSM_DB_ATTRIBUTE_FORMAT_BLOB); + if (mData.Length != Guid::stringRepLength + 1) + CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT); + + return Guid(reinterpret_cast(mData.Data)); +} + + +// +// CssmDbAttributeInfo +// +CssmDbAttributeInfo::CssmDbAttributeInfo(const char *name, CSSM_DB_ATTRIBUTE_FORMAT vFormat) +{ + clearPod(); + AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING; + Label.AttributeName = const_cast(name); // silly CDSA + AttributeFormat = vFormat; +} + +CssmDbAttributeInfo::CssmDbAttributeInfo(const CSSM_OID &oid, CSSM_DB_ATTRIBUTE_FORMAT vFormat) +{ + clearPod(); + AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_OID; + Label.AttributeOID = oid; + AttributeFormat = vFormat; +} + +CssmDbAttributeInfo::CssmDbAttributeInfo(uint32 id, CSSM_DB_ATTRIBUTE_FORMAT vFormat) +{ + clearPod(); + AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER; + Label.AttributeID = id; + AttributeFormat = vFormat; +} + + +bool +CssmDbAttributeInfo::operator <(const CssmDbAttributeInfo& other) const +{ + if (nameFormat() < other.nameFormat()) return true; + if (other.nameFormat() < nameFormat()) return false; + // nameFormat's are equal. + switch (nameFormat()) + { + case CSSM_DB_ATTRIBUTE_NAME_AS_STRING: + { + int res = strcmp(static_cast(*this), static_cast(other)); + if (res < 0) return true; + if (res > 0) return false; + break; + } + case CSSM_DB_ATTRIBUTE_NAME_AS_OID: + if (static_cast(*this) < static_cast(other)) return true; + if (static_cast(other) < static_cast(*this)) return false; + break; + case CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER: + if (static_cast(*this) < static_cast(other)) return true; + if (static_cast(other) < static_cast(*this)) return false; + break; + default: + CssmError::throwMe(CSSMERR_DL_INVALID_FIELD_NAME); + } + + return format() < other.format(); +} + +bool +CssmDbAttributeInfo::operator ==(const CssmDbAttributeInfo& other) const +{ + if (nameFormat() != other.nameFormat()) return false; + if (format() != other.format()) return false; + switch (nameFormat()) + { + case CSSM_DB_ATTRIBUTE_NAME_AS_STRING: + return !strcmp(static_cast(*this), static_cast(other)); + case CSSM_DB_ATTRIBUTE_NAME_AS_OID: + return static_cast(*this) == static_cast(other); + case CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER: + return static_cast(*this) == static_cast(other); + default: + CssmError::throwMe(CSSMERR_DL_INVALID_FIELD_NAME); + } +} + +// +// CssmDbAttributeData +// +CssmDbAttributeData::operator string() const +{ + switch (format()) { + case CSSM_DB_ATTRIBUTE_FORMAT_STRING: + case CSSM_DB_ATTRIBUTE_FORMAT_BLOB: + return at(0).toString(); + default: + CssmError::throwMe(CSSMERR_DL_INCOMPATIBLE_FIELD_FORMAT); + } +} +CssmDbAttributeData::operator const Guid &() const +{ + if (format() == CSSM_DB_ATTRIBUTE_FORMAT_BLOB) + return *at(0).interpretedAs(); + else + CssmError::throwMe(CSSMERR_DL_INCOMPATIBLE_FIELD_FORMAT); +} + +CssmDbAttributeData::operator bool() const +{ + switch (format()) { + case CSSM_DB_ATTRIBUTE_FORMAT_UINT32: + case CSSM_DB_ATTRIBUTE_FORMAT_SINT32: + return *at(0).interpretedAs(); + default: + CssmError::throwMe(CSSMERR_DL_INCOMPATIBLE_FIELD_FORMAT); + } +} + +CssmDbAttributeData::operator uint32() const +{ + if (format() == CSSM_DB_ATTRIBUTE_FORMAT_UINT32) + return *at(0).interpretedAs(); + else + CssmError::throwMe(CSSMERR_DL_INCOMPATIBLE_FIELD_FORMAT); +} + +CssmDbAttributeData::operator const uint32 *() const +{ + if (format() == CSSM_DB_ATTRIBUTE_FORMAT_MULTI_UINT32) + return reinterpret_cast(Value[0].Data); + else + CssmError::throwMe(CSSMERR_DL_INCOMPATIBLE_FIELD_FORMAT); +} + +CssmDbAttributeData::operator sint32() const +{ + if (format() == CSSM_DB_ATTRIBUTE_FORMAT_SINT32) + return *at(0).interpretedAs(); + else + CssmError::throwMe(CSSMERR_DL_INCOMPATIBLE_FIELD_FORMAT); +} + +CssmDbAttributeData::operator double() const +{ + if (format() == CSSM_DB_ATTRIBUTE_FORMAT_REAL) + return *at(0).interpretedAs(); + else + CssmError::throwMe(CSSMERR_DL_INCOMPATIBLE_FIELD_FORMAT); +} + +CssmDbAttributeData::operator const CssmData &() const +{ + switch (format()) { + case CSSM_DB_ATTRIBUTE_FORMAT_STRING: + case CSSM_DB_ATTRIBUTE_FORMAT_BIG_NUM: + case CSSM_DB_ATTRIBUTE_FORMAT_TIME_DATE: + case CSSM_DB_ATTRIBUTE_FORMAT_BLOB: + case CSSM_DB_ATTRIBUTE_FORMAT_MULTI_UINT32: + return at(0); + default: + CssmError::throwMe(CSSMERR_DL_INCOMPATIBLE_FIELD_FORMAT); + } +} + +void CssmDbAttributeData::set(const CSSM_DB_ATTRIBUTE_INFO &inInfo, const CssmPolyData &inValue, + Allocator &inAllocator) +{ + info(inInfo); + NumberOfValues = 0; + Value = inAllocator.alloc(); + Value[0].Length = 0; + Value[0].Data = inAllocator.alloc(inValue.Length); + Value[0].Length = inValue.Length; + memcpy(Value[0].Data, inValue.Data, inValue.Length); + NumberOfValues = 1; +} + +void CssmDbAttributeData::add(const CssmPolyData &inValue, Allocator &inAllocator) +{ + Value = reinterpret_cast(inAllocator.realloc(Value, sizeof(*Value) * (NumberOfValues + 1))); + CssmAutoData valueCopy(inAllocator, inValue); + Value[NumberOfValues++] = valueCopy.release(); +} + + +void CssmDbAttributeData::copyValues(const CssmDbAttributeData &source, Allocator &alloc) +{ + assert(size() == 0); // must start out empty + + // we're too lazy to arrange for exception safety here + CssmData *vector = alloc.alloc(source.size()); + for (uint32 n = 0; n < source.size(); n++) + vector[n] = CssmAutoData(alloc, source[n]).release(); + + // atomic set results + info().format(source.info().format()); + NumberOfValues = source.size(); + values() = vector; +} + +void CssmDbAttributeData::deleteValues(Allocator &alloc) +{ + // Loop over all values and delete each one. + if (values()) + { + for (uint32 n = 0; n < size(); n++) + { + alloc.free(at(n).data()); + } + alloc.free(values()); + } + NumberOfValues = 0; + values() = NULL; +} + +bool CssmDbAttributeData::operator <(const CssmDbAttributeData &other) const +{ + if (info() < other.info()) return true; + if (other.info() < info()) return false; + + uint32 minSize = min(size(), other.size()); + for (uint32 ix = 0; ix < minSize; ++ix) + { + if (at(ix) < other.at(ix)) + return true; + if (other.at(ix) < at(ix)) + return false; + } + + return size() < other.size(); +} + +void +CssmDbAttributeData::add(const CssmDbAttributeData &src, Allocator &inAllocator) +{ + // Add all the values from another attribute into this attribute. + + Value = reinterpret_cast(inAllocator.realloc(Value, + sizeof(*Value) * (NumberOfValues + src.NumberOfValues))); + + for (uint32 srcIndex = 0; srcIndex < src.NumberOfValues; srcIndex++) { + uint32 destIndex = NumberOfValues + srcIndex; + + Value[destIndex].Length = 0; + Value[destIndex].Data = inAllocator.alloc(src.Value[srcIndex].Length); + Value[destIndex].Length = src.Value[srcIndex].Length; + memcpy(Value[destIndex].Data, src.Value[srcIndex].Data, src.Value[srcIndex].Length); + } + + NumberOfValues += src.NumberOfValues; +} + +bool +CssmDbAttributeData::deleteValue(const CssmData &src, Allocator &inAllocator) +{ + // Delete a single value from this attribute, if it is present. + + for (uint32 i = 0; i < NumberOfValues; i++) + if (CssmData::overlay(Value[i]) == src) + { + inAllocator.free(Value[i].Data); + Value[i].Length = 0; + + NumberOfValues--; + Value[i].Data = Value[NumberOfValues].Data; + Value[i].Length = Value[NumberOfValues].Length; + + return true; + } + + return false; +} + +// Delete those values found in src from this object, if they are present. +// Warning: This is O(N^2) worst case; if this becomes a performance bottleneck +// then it will need to be changed. + +void +CssmDbAttributeData::deleteValues(const CssmDbAttributeData &src, Allocator &inAllocator) +{ + for (uint32 i = 0; i < src.NumberOfValues; i++) + deleteValue(CssmData::overlay(src.Value[i]), inAllocator); +} + +// +// CssmDbRecordAttributeData +// +CssmDbAttributeData * +CssmDbRecordAttributeData::find(const CSSM_DB_ATTRIBUTE_INFO &inInfo) +{ + const CssmDbAttributeInfo &anInfo = CssmDbAttributeInfo::overlay(inInfo); + for (uint32 ix = 0; ix < size(); ++ix) + { + if (at(ix).info() == anInfo) + return &at(ix); + } + + return NULL; +} + +bool +CssmDbRecordAttributeData::operator <(const CssmDbRecordAttributeData &other) const +{ + if (recordType() < other.recordType()) return true; + if (other.recordType() < recordType()) return false; + if (semanticInformation() < other.semanticInformation()) return true; + if (other.semanticInformation() < semanticInformation()) return false; + + uint32 minSize = min(size(), other.size()); + for (uint32 ix = 0; ix < minSize; ++ix) + { + if (at(ix) < other.at(ix)) + return true; + if (other.at(ix) < at(ix)) + return false; + } + + return size() < other.size(); +} + + +// +// CssmAutoDbRecordAttributeData +// +CssmAutoDbRecordAttributeData::~CssmAutoDbRecordAttributeData() +{ + clear(); +} + +void +CssmAutoDbRecordAttributeData::invalidate() +{ + NumberOfAttributes = 0; +} + + + +void +CssmAutoDbRecordAttributeData::clear() +{ + deleteValues(); + ArrayBuilder::clear(); +} + + + +static bool CompareAttributeInfos (const CSSM_DB_ATTRIBUTE_INFO &a, const CSSM_DB_ATTRIBUTE_INFO &b) +{ + // check the format of the names + if (a.AttributeNameFormat != b.AttributeNameFormat) + { + return false; + } + + switch (a.AttributeNameFormat) + { + case CSSM_DB_ATTRIBUTE_NAME_AS_STRING: + { + return strcmp (a.Label.AttributeName, b.Label.AttributeName) == 0; + } + + case CSSM_DB_ATTRIBUTE_NAME_AS_OID: + { + if (a.Label.AttributeOID.Length != b.Label.AttributeOID.Length) + { + return false; + } + + return memcmp (a.Label.AttributeOID.Data, b.Label.AttributeOID.Data, a.Label.AttributeOID.Length) == 0; + } + + + case CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER: + { + return a.Label.AttributeID == b.Label.AttributeID; + } + } + + return true; // just to keep the compiler from complaining +} + + + +CssmDbAttributeData* CssmAutoDbRecordAttributeData::findAttribute (const CSSM_DB_ATTRIBUTE_INFO &info) +{ + // walk through the data, looking for an attribute of the same type + unsigned i; + for (i = 0; i < size (); ++i) + { + CssmDbAttributeData& d = at (i); + CSSM_DB_ATTRIBUTE_INFO &inInfo = d.info (); + + if (CompareAttributeInfos (info, inInfo)) + { + return &d; + } + } + + // found nothing? + return NULL; +} + + + +CssmDbAttributeData& CssmAutoDbRecordAttributeData::getAttributeReference (const CSSM_DB_ATTRIBUTE_INFO &info) +{ + // Either find an existing reference to an attribute in the list, or make a new one. + CssmDbAttributeData *anAttr = findAttribute (info); + if (anAttr) // was this already in the list? + { + // clean it up + anAttr->deleteValues (mValueAllocator); + } + else + { + // make a new one + anAttr = &add(); + } + + return *anAttr; +} + + + +CssmDbAttributeData & +CssmAutoDbRecordAttributeData::add(const CSSM_DB_ATTRIBUTE_INFO &info) +{ + CssmDbAttributeData& anAttr = getAttributeReference (info); + anAttr.info(info); + return anAttr; +} + +CssmDbAttributeData & +CssmAutoDbRecordAttributeData::add(const CSSM_DB_ATTRIBUTE_INFO &info, const CssmPolyData &value) +{ + CssmDbAttributeData &anAttr = getAttributeReference (info); + anAttr.set(info, value, mValueAllocator); + return anAttr; +} + +// +// CssmAutoQuery +// +CssmAutoQuery::CssmAutoQuery(const CSSM_QUERY &query, Allocator &allocator) +: ArrayBuilder(CssmSelectionPredicate::overlayVar(SelectionPredicate), + NumSelectionPredicates, + query.NumSelectionPredicates, allocator) +{ + RecordType = query.RecordType; + Conjunctive = query.Conjunctive; + QueryLimits = query.QueryLimits; + QueryFlags = query.QueryFlags; + for (uint32 ix = 0; ix < query.NumSelectionPredicates; ++ix) + add().set(query.SelectionPredicate[ix], allocator); +} + +CssmAutoQuery::~CssmAutoQuery() +{ + clear(); +} + +void +CssmAutoQuery::clear() +{ + deleteValues(); + ArrayBuilder::clear(); +} + +CssmSelectionPredicate & +CssmAutoQuery::add(CSSM_DB_OPERATOR dbOperator, const CSSM_DB_ATTRIBUTE_INFO &info, const CssmPolyData &value) +{ + CssmSelectionPredicate &predicate = add(); + predicate.dbOperator(dbOperator); + predicate.set(info, value, allocator()); + return predicate; +} diff --git a/libsecurity_cdsa_utilities/lib/cssmdb.h b/libsecurity_cdsa_utilities/lib/cssmdb.h new file mode 100644 index 00000000..a8bf1dd3 --- /dev/null +++ b/libsecurity_cdsa_utilities/lib/cssmdb.h @@ -0,0 +1,866 @@ +/* + * Copyright (c) 2000-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@ + */ + + +// cssmdb.h +// +// classes for the DL related data structures +// + +#ifndef _H_CDSA_UTILITIES_CSSMDB +#define _H_CDSA_UTILITIES_CSSMDB + +#include +#include +#include +#include +#include + + +namespace Security { + + +// +// Template class to build and maintain external arrays. +// Feel free to add and vector<> member functions and behaviours as needed. +// +// This class differs from vector mainly because it does not construct or +// destruct any of the elements it contains. Rather it zero fills the +// storage and returns references to elements. +// Also it does not implement insert(), erase() or assign(). It does implement +// which is equivalent to calling *insert(end()) on a vector. +// +template +class ArrayBuilder { +public: + typedef _Tp value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type* iterator; + typedef const value_type* const_iterator; + typedef value_type& reference; + typedef const value_type& const_reference; + typedef uint32 size_type; + typedef ptrdiff_t difference_type; + + typedef reverse_iterator const_reverse_iterator; + typedef reverse_iterator reverse_iterator; + +protected: + void insert_aux(iterator __position, const _Tp& __x); + void insert_aux(iterator __position); + +public: + iterator begin() { return mArray; } + const_iterator begin() const { return mArray; } + iterator end() { return &mArray[mSize]; } + const_iterator end() const { return &mArray[mSize]; } + + reverse_iterator rbegin() + { return reverse_iterator(end()); } + const_reverse_iterator rbegin() const + { return const_reverse_iterator(end()); } + reverse_iterator rend() + { return reverse_iterator(begin()); } + const_reverse_iterator rend() const + { return const_reverse_iterator(begin()); } + + // Must be defined in base class. + //size_type size() const + //{ return mSize; } + size_type max_size() const + { return size_type(-1) / sizeof(_Tp); } + size_type capacity() const + { return mCapacity; } + bool empty() const + { return begin() == end(); } + + ArrayBuilder(pointer &array, size_type &size, size_type capacity = 0, Allocator &allocator = Allocator::standard()) : + mArray(array), mSize(size), mCapacity(capacity), mAllocator(allocator) + { +#if BUG_GCC + mArray = reinterpret_cast(mAllocator.malloc(sizeof(value_type) * mCapacity)); +#else + mArray = reinterpret_cast(mAllocator.malloc(sizeof(value_type) * mCapacity)); + //mArray = mAllocator.alloc(mCapacity); +#endif + memset(mArray, 0, sizeof(value_type) * mCapacity); + mSize = 0; + } + ~ArrayBuilder() { mAllocator.free(mArray); } + + reference front() { return *begin(); } + const_reference front() const { return *begin(); } + reference back() { return *(end() - 1); } + const_reference back() const { return *(end() - 1); } + + void reserve(size_type newCapacity) + { + if (newCapacity > mCapacity) + { +#if BUG_GCC + mArray = reinterpret_cast(mAllocator.realloc(mArray, sizeof(value_type) * newCapacity)); +#else + mArray = reinterpret_cast(mAllocator.realloc(mArray, sizeof(value_type) * newCapacity)); + //mArray = mAllocator.realloc(mArray, newCapacity)); +#endif + memset(&mArray[mCapacity], 0, sizeof(value_type) * (newCapacity - mCapacity)); + mCapacity = newCapacity; + } + } + + // XXX Replace by push_back and insert. + reference add() + { + if (mSize >= mCapacity) + reserve(max(mSize + 1, mCapacity ? 2 * mCapacity : 1)); + + return mArray[mSize++]; + } + + const_pointer get() const { return mArray; } + pointer release() { const_pointer array = mArray; mArray = NULL; return array; } + void clear() { if (mSize) { memset(mArray, 0, sizeof(value_type) * mSize); } mSize = 0; } + + // Must be defined in base class. + //reference at(size_type ix) { return mArray[ix]; } + //const_reference at(size_type ix) const { return mArray[ix]; } + //reference operator[] (size_type ix) { assert(ix < size()); return at(ix); } + //const_reference operator[] (size_type ix) const { assert(ix < size()); return at(ix); } +protected: + Allocator &allocator() const { return mAllocator; } + +private: + + pointer &mArray; + size_type &mSize; + size_type mCapacity; + Allocator &mAllocator; +}; + + +// +// A CSSM_DL_DB_LIST wrapper. +// Note that there is a DLDBList class elsewhere that is quite +// unrelated to this structure. +// +class CssmDlDbHandle : public PodWrapper { +public: + CssmDlDbHandle() { clearPod(); } + CssmDlDbHandle(CSSM_DL_HANDLE dl, CSSM_DB_HANDLE db) { DLHandle = dl; DBHandle = db; } + + CSSM_DL_HANDLE dl() const { return DLHandle; } + CSSM_DB_HANDLE db() const { return DBHandle; } + + operator bool() const { return DLHandle && DBHandle; } +}; + +inline bool operator < (const CSSM_DL_DB_HANDLE &h1, const CSSM_DL_DB_HANDLE &h2) +{ + return h1.DLHandle < h2.DLHandle + || (h1.DLHandle == h2.DLHandle && h1.DBHandle < h2.DBHandle); +} + +inline bool operator == (const CSSM_DL_DB_HANDLE &h1, const CSSM_DL_DB_HANDLE &h2) +{ + return h1.DLHandle == h2.DLHandle && h1.DBHandle == h2.DBHandle; +} + +inline bool operator != (const CSSM_DL_DB_HANDLE &h1, const CSSM_DL_DB_HANDLE &h2) +{ + return h1.DLHandle != h2.DLHandle || h1.DBHandle != h2.DBHandle; +} + + +class CssmDlDbList : public PodWrapper { +public: + uint32 count() const { return NumHandles; } + uint32 &count() { return NumHandles; } + CssmDlDbHandle *handles() const { return CssmDlDbHandle::overlay(DLDBHandle); } + CssmDlDbHandle * &handles() { return CssmDlDbHandle::overlayVar(DLDBHandle); } + + CssmDlDbHandle &operator [] (uint32 ix) const + { assert(ix < count()); return CssmDlDbHandle::overlay(DLDBHandle[ix]); } + + void setDlDbList(uint32 n, CSSM_DL_DB_HANDLE *list) + { count() = n; handles() = CssmDlDbHandle::overlay(list); } +}; + + +// +// CssmDLPolyData +// +class CssmDLPolyData +{ +public: + CssmDLPolyData(const CSSM_DATA &data, CSSM_DB_ATTRIBUTE_FORMAT format) + : mData(CssmData::overlay(data)), mFormat(format) {} + + // @@@ Don't use assert, but throw an exception. + // @@@ Do a size check on mData as well. + + // @@@ This method is dangerous since the returned string is not guaranteed to be zero terminated. + operator const char *() const + { + assert(mFormat == CSSM_DB_ATTRIBUTE_FORMAT_STRING + || mFormat == CSSM_DB_ATTRIBUTE_FORMAT_TIME_DATE); + return reinterpret_cast(mData.Data); + } + operator bool() const + { + assert(mFormat == CSSM_DB_ATTRIBUTE_FORMAT_UINT32 || mFormat == CSSM_DB_ATTRIBUTE_FORMAT_SINT32); + return *reinterpret_cast(mData.Data); + } + operator uint32() const + { + assert(mFormat == CSSM_DB_ATTRIBUTE_FORMAT_UINT32); + return *reinterpret_cast(mData.Data); + } + operator const uint32 *() const + { + assert(mFormat == CSSM_DB_ATTRIBUTE_FORMAT_MULTI_UINT32); + return reinterpret_cast(mData.Data); + } + operator sint32() const + { + assert(mFormat == CSSM_DB_ATTRIBUTE_FORMAT_SINT32); + return *reinterpret_cast(mData.Data); + } + operator double() const + { + assert(mFormat == CSSM_DB_ATTRIBUTE_FORMAT_REAL); + return *reinterpret_cast(mData.Data); + } + operator CSSM_DATE () const; + operator Guid () const; + operator const CssmData &() const + { + return mData; + } + +private: + const CssmData &mData; + CSSM_DB_ATTRIBUTE_FORMAT mFormat; +}; + + +// +// CssmDbAttributeInfo pod wrapper for CSSM_DB_ATTRIBUTE_INFO +// +class CssmDbAttributeInfo : public PodWrapper +{ +public: + CssmDbAttributeInfo(const CSSM_DB_ATTRIBUTE_INFO &attr) + { assignPod(attr); } + + CssmDbAttributeInfo(const char *name, + CSSM_DB_ATTRIBUTE_FORMAT vFormat = CSSM_DB_ATTRIBUTE_FORMAT_COMPLEX); + CssmDbAttributeInfo(const CSSM_OID &oid, + CSSM_DB_ATTRIBUTE_FORMAT vFormat = CSSM_DB_ATTRIBUTE_FORMAT_COMPLEX); + CssmDbAttributeInfo(uint32 id, + CSSM_DB_ATTRIBUTE_FORMAT vFormat = CSSM_DB_ATTRIBUTE_FORMAT_COMPLEX); + + CSSM_DB_ATTRIBUTE_NAME_FORMAT nameFormat() const { return AttributeNameFormat; } + void nameFormat(CSSM_DB_ATTRIBUTE_NAME_FORMAT nameFormat) { AttributeNameFormat = nameFormat; } + + CSSM_DB_ATTRIBUTE_FORMAT format() const { return AttributeFormat; } + void format(CSSM_DB_ATTRIBUTE_FORMAT format) { AttributeFormat = format; } + + const char *stringName() const + { + assert(nameFormat() == CSSM_DB_ATTRIBUTE_NAME_AS_STRING); + return Label.AttributeName; + } + const CssmOid &oidName() const + { + assert(nameFormat() == CSSM_DB_ATTRIBUTE_NAME_AS_OID); + return CssmOid::overlay(Label.AttributeOID); + } + uint32 intName() const + { + assert(nameFormat() == CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER); + return Label.AttributeID; + } + + operator const char *() const { return stringName(); } + operator const CssmOid &() const { return oidName(); } + operator uint32() const { return intName(); } + + bool operator <(const CssmDbAttributeInfo& other) const; + bool operator ==(const CssmDbAttributeInfo& other) const; + bool operator !=(const CssmDbAttributeInfo& other) const + { return !(*this == other); } +}; + +// +// CssmDbRecordAttributeInfo pod wrapper for CSSM_DB_RECORD_ATTRIBUTE_INFO +// +class CssmDbRecordAttributeInfo : public PodWrapper +{ +public: + CssmDbRecordAttributeInfo() + { DataRecordType = CSSM_DL_DB_RECORD_ANY; } + + CssmDbRecordAttributeInfo(CSSM_DB_RECORDTYPE recordType, uint32 numberOfAttributes, + CSSM_DB_ATTRIBUTE_INFO_PTR attributeInfo) + { + DataRecordType = recordType; + NumberOfAttributes = numberOfAttributes; + AttributeInfo = attributeInfo; + } + + CSSM_DB_RECORDTYPE recordType() const { return DataRecordType; } + void recordType(CSSM_DB_RECORDTYPE recordType) { DataRecordType = recordType; } + + uint32 size() const { return NumberOfAttributes; } + + // attribute access + CssmDbAttributeInfo *&attributes() + { return CssmDbAttributeInfo::overlayVar(AttributeInfo); } + CssmDbAttributeInfo *attributes() const + { return CssmDbAttributeInfo::overlay(AttributeInfo); } + CssmDbAttributeInfo &at(uint32 ix) const + { assert(ix < size()); return attributes()[ix]; } + + CssmDbAttributeInfo &operator [] (uint32 ix) const { return at(ix); } +}; + +// +// CssmAutoDbRecordAttributeInfo pod wrapper for CSSM_DB_RECORD_ATTRIBUTE_INFO +// +class CssmAutoDbRecordAttributeInfo: public CssmDbRecordAttributeInfo, public ArrayBuilder +{ +public: + CssmAutoDbRecordAttributeInfo(uint32 capacity = 0, Allocator &allocator = Allocator::standard()) : + CssmDbRecordAttributeInfo(), + ArrayBuilder(CssmDbAttributeInfo::overlayVar(AttributeInfo), + NumberOfAttributes, capacity, allocator) {} +}; + + +// +// CssmDbAttributeData pod wrapper for CSSM_DB_ATTRIBUTE_DATA +// +class CssmDbAttributeData : public PodWrapper +{ +public: + CssmDbAttributeData() { NumberOfValues = 0; Value = NULL; } + CssmDbAttributeData(const CSSM_DB_ATTRIBUTE_DATA &attr) + { assignPod(attr); } + CssmDbAttributeData(const CSSM_DB_ATTRIBUTE_INFO &info) + { Info = info; NumberOfValues = 0; Value = NULL; } + + CssmDbAttributeInfo &info() { return CssmDbAttributeInfo::overlay(Info); } + const CssmDbAttributeInfo &info() const { return CssmDbAttributeInfo::overlay(Info); } + void info (const CSSM_DB_ATTRIBUTE_INFO &inInfo) { Info = inInfo; } + + CSSM_DB_ATTRIBUTE_FORMAT format() const { return info().format(); } + void format(CSSM_DB_ATTRIBUTE_FORMAT f) { info().format(f); } + + uint32 size() const { return NumberOfValues; } + CssmData *&values() { return CssmData::overlayVar(Value); } + CssmData *values() const { return CssmData::overlay(Value); } + + CssmData &at(unsigned int ix) const + { + if (ix >= size()) CssmError::throwMe(CSSMERR_DL_MISSING_VALUE); + return values()[ix]; + } + + CssmData &operator [] (unsigned int ix) const { return at(ix); } + + template + T at(unsigned int ix) const { return CssmDLPolyData(Value[ix], format()); } + + // this is intentionally unspecified since it could lead to bugs; the + // data is not guaranteed to be NULL-terminated + // operator const char *() const; + + operator string() const; + operator const Guid &() const; + operator bool() const; + operator uint32() const; + operator const uint32 *() const; + operator sint32() const; + operator double() const; + operator const CssmData &() const; + + // set values without allocation (caller owns the data contents) + void set(CssmData &data) { set(1, &data); } + void set(uint32 count, CssmData *datas) { NumberOfValues = count; Value = datas; } + + // Set the value of this Attr (assuming it was not set before). + void set(const CSSM_DB_ATTRIBUTE_INFO &inInfo, const CssmPolyData &inValue, + Allocator &inAllocator); + + // copy (just) the return-value part from another AttributeData to this one + void copyValues(const CssmDbAttributeData &source, Allocator &alloc); + + // Set the value of this Attr (which must be unset so far) + void set(const CSSM_DB_ATTRIBUTE_DATA &source, Allocator &alloc) + { + info(source.Info); + copyValues(source, alloc); + } + + // Add a value to this attribute. + void add(const CssmPolyData &inValue, Allocator &inAllocator); + + void add(const char *value, Allocator &alloc) + { format(CSSM_DB_ATTRIBUTE_FORMAT_STRING); add(CssmPolyData(value), alloc); } + + void add(const std::string &value, Allocator &alloc) + { format(CSSM_DB_ATTRIBUTE_FORMAT_STRING); add(CssmPolyData(value), alloc); } + + void add(uint32 value, Allocator &alloc) + { format(CSSM_DB_ATTRIBUTE_FORMAT_UINT32); add(CssmPolyData(value), alloc); } + + void add(sint32 value, Allocator &alloc) + { format(CSSM_DB_ATTRIBUTE_FORMAT_SINT32); add(CssmPolyData(value), alloc); } + + void add(const CssmData &value, Allocator &alloc) + { format(CSSM_DB_ATTRIBUTE_FORMAT_BLOB); add(CssmPolyData(value), alloc); } + + void add(const CssmDbAttributeData &src, Allocator &inAllocator); + + // delete specific values if they are present in this attribute data + bool deleteValue(const CssmData &src, Allocator &inAllocator); + void deleteValues(const CssmDbAttributeData &src, Allocator &inAllocator); + + void deleteValues(Allocator &inAllocator); + + bool operator <(const CssmDbAttributeData& other) const; +}; + + +// +// CssmDbRecordAttributeData pod wrapper for CSSM_DB_RECORD_ATTRIBUTE_DATA +// +class CssmDbRecordAttributeData : public PodWrapper +{ +public: + CssmDbRecordAttributeData() + { clearPod(); DataRecordType = CSSM_DL_DB_RECORD_ANY; } + + CSSM_DB_RECORDTYPE recordType() const { return DataRecordType; } + void recordType(CSSM_DB_RECORDTYPE recordType) { DataRecordType = recordType; } + + uint32 semanticInformation() const { return SemanticInformation; } + void semanticInformation(uint32 semanticInformation) { SemanticInformation = semanticInformation; } + + uint32 size() const { return NumberOfAttributes; } + CssmDbAttributeData *&attributes() + { return CssmDbAttributeData::overlayVar(AttributeData); } + CssmDbAttributeData *attributes() const + { return CssmDbAttributeData::overlay(AttributeData); } + + // Attributes by position + CssmDbAttributeData &at(unsigned int ix) const + { assert(ix < size()); return attributes()[ix]; } + + CssmDbAttributeData &operator [] (unsigned int ix) const { return at(ix); } + + void deleteValues(Allocator &allocator) + { for (uint32 ix = 0; ix < size(); ++ix) at(ix).deleteValues(allocator); } + + CssmDbAttributeData *find(const CSSM_DB_ATTRIBUTE_INFO &inInfo); + + bool operator <(const CssmDbRecordAttributeData& other) const; +}; + + +// +// CssmAutoDbRecordAttributeData +// +class CssmAutoDbRecordAttributeData : public CssmDbRecordAttributeData, public ArrayBuilder +{ +public: + CssmAutoDbRecordAttributeData(uint32 capacity = 0, + Allocator &valueAllocator = Allocator::standard(), + Allocator &dataAllocator = Allocator::standard()) : + CssmDbRecordAttributeData(), + ArrayBuilder(CssmDbAttributeData::overlayVar(AttributeData), + NumberOfAttributes, capacity, dataAllocator), + mValueAllocator(valueAllocator) {} + ~CssmAutoDbRecordAttributeData(); + + void clear(); + void deleteValues() { CssmDbRecordAttributeData::deleteValues(mValueAllocator); } + void invalidate(); + + CssmDbAttributeData &add() { return ArrayBuilder::add(); } // XXX using doesn't work here. + CssmDbAttributeData &add(const CSSM_DB_ATTRIBUTE_INFO &info); + CssmDbAttributeData &add(const CSSM_DB_ATTRIBUTE_INFO &info, const CssmPolyData &value); + + // So clients can pass this as the allocator argument to add() + operator Allocator &() const { return mValueAllocator; } +private: + Allocator &mValueAllocator; + + CssmDbAttributeData* findAttribute (const CSSM_DB_ATTRIBUTE_INFO &info); + CssmDbAttributeData& getAttributeReference (const CSSM_DB_ATTRIBUTE_INFO &info); +}; + + +// +// CssmSelectionPredicate a PodWrapper for CSSM_SELECTION_PREDICATE +// +class CssmSelectionPredicate : public PodWrapper { +public: + CssmSelectionPredicate() { clearPod(); } + + CSSM_DB_OPERATOR dbOperator() const { return DbOperator; } + void dbOperator(CSSM_DB_OPERATOR dbOperator) { DbOperator = dbOperator; } + + CssmSelectionPredicate(CSSM_DB_OPERATOR inDbOperator) + { dbOperator(inDbOperator); Attribute.NumberOfValues = 0; Attribute.Value = NULL; } + + CssmDbAttributeData &attribute() { return CssmDbAttributeData::overlay(Attribute); } + const CssmDbAttributeData &attribute() const { return CssmDbAttributeData::overlay(Attribute); } + + // Set the value of this CssmSelectionPredicate (assuming it was not set before). + void set(const CSSM_DB_ATTRIBUTE_INFO &inInfo, + const CssmPolyData &inValue, Allocator &inAllocator) + { attribute().set(inInfo, inValue, inAllocator); } + + // Set the value of this CssmSelectionPredicate using another CssmSelectionPredicate's value. + void set(const CSSM_SELECTION_PREDICATE &other, Allocator &inAllocator) + { DbOperator = other.DbOperator; attribute().set(other.Attribute, inAllocator); } + + // Add a value to the list of values for this CssmSelectionPredicate. + void add(const CssmPolyData &inValue, Allocator &inAllocator) + { attribute().add(inValue, inAllocator); } + + void deleteValues(Allocator &inAllocator) { attribute().deleteValues(inAllocator); } +}; + +class CssmQuery : public PodWrapper { +public: + CssmQuery(CSSM_DB_RECORDTYPE type = CSSM_DL_DB_RECORD_ANY) + { clearPod(); RecordType = type; } + + // copy or assign flat from CSSM_QUERY + CssmQuery(const CSSM_QUERY &q) { assignPod(q); } + CssmQuery &operator = (const CSSM_QUERY &q) { assignPod(q); return *this; } + + // flat copy and change record type + CssmQuery(const CssmQuery &q, CSSM_DB_RECORDTYPE type) + { *this = q; RecordType = type; } + + CSSM_DB_RECORDTYPE recordType() const { return RecordType; } + void recordType(CSSM_DB_RECORDTYPE recordType) { RecordType = recordType; } + + CSSM_DB_CONJUNCTIVE conjunctive() const { return Conjunctive; } + void conjunctive(CSSM_DB_CONJUNCTIVE conjunctive) { Conjunctive = conjunctive; } + + CSSM_QUERY_LIMITS queryLimits() const { return QueryLimits; } + void queryLimits(CSSM_QUERY_LIMITS queryLimits) { QueryLimits = queryLimits; } + + CSSM_QUERY_FLAGS queryFlags() const { return QueryFlags; } + void queryFlags(CSSM_QUERY_FLAGS queryFlags) { QueryFlags = queryFlags; } + + uint32 size() const { return NumSelectionPredicates; } + + CssmSelectionPredicate *&predicates() + { return CssmSelectionPredicate::overlayVar(SelectionPredicate); } + CssmSelectionPredicate *predicates() const + { return CssmSelectionPredicate::overlay(SelectionPredicate); } + + CssmSelectionPredicate &at(uint32 ix) const + { assert(ix < size()); return predicates()[ix]; } + + CssmSelectionPredicate &operator[] (uint32 ix) const { return at(ix); } + + void set(uint32 count, CSSM_SELECTION_PREDICATE *preds) + { NumSelectionPredicates = count; SelectionPredicate = preds; } + + void deleteValues(Allocator &allocator) + { for (uint32 ix = 0; ix < size(); ++ix) at(ix).deleteValues(allocator); } +}; + + +class CssmAutoQuery : public CssmQuery, public ArrayBuilder { +public: + CssmAutoQuery(const CSSM_QUERY &query, Allocator &allocator = Allocator::standard()); + CssmAutoQuery(uint32 capacity = 0, Allocator &allocator = Allocator::standard()) : + ArrayBuilder(CssmSelectionPredicate::overlayVar(SelectionPredicate), + NumSelectionPredicates, + capacity, allocator) {} + ~CssmAutoQuery(); + void clear(); + void deleteValues() { CssmQuery::deleteValues(allocator()); } + + CssmSelectionPredicate &add() { return ArrayBuilder::add(); } + CssmSelectionPredicate &add(CSSM_DB_OPERATOR dbOperator, const CSSM_DB_ATTRIBUTE_INFO &info, const CssmPolyData &value); + + // So clients can pass this as the allocator argument to add() + operator Allocator &() const { return allocator(); } +}; + + +// +// DLDbIdentifier +// +class DLDbIdentifier +{ +protected: + class Impl : public RefCount + { + NOCOPY(Impl) + public: + Impl(const CSSM_SUBSERVICE_UID &ssuid,const char *DbName,const CSSM_NET_ADDRESS *DbLocation) : + mCssmSubserviceUid(ssuid),mDbName(DbName,DbLocation) {} + + ~Impl() {} // Must be public since RefPointer uses it. + + // Accessors + const CssmSubserviceUid &ssuid() const { return mCssmSubserviceUid; } + const char *dbName() const { return mDbName.dbName(); } + const CssmNetAddress *dbLocation() const { return mDbName.dbLocation(); } + + // comparison (simple lexicographic) + bool operator < (const Impl &other) const; + bool operator == (const Impl &other) const; + private: + // Private member variables + CssmSubserviceUid mCssmSubserviceUid; + DbName mDbName; + }; + +public: + // Constructors + DLDbIdentifier() {} + DLDbIdentifier(const CSSM_SUBSERVICE_UID &ssuid, const char *DbName, const CSSM_NET_ADDRESS *DbLocation) + : mImpl(new Impl(ssuid, DbName, DbLocation)) {} + DLDbIdentifier(const char *name, const Guid &guid, uint32 ssid, uint32 sstype, + const CSSM_NET_ADDRESS *location = NULL) + : mImpl(new Impl(CssmSubserviceUid(guid, NULL, ssid, sstype), name, location)) { } + + // Conversion Operators + bool operator !() const { return !mImpl; } + operator bool() const { return mImpl; } + + // Operators + bool operator <(const DLDbIdentifier &other) const + { return mImpl && other.mImpl ? *mImpl < *other.mImpl : mImpl.get() < other.mImpl.get(); } + bool operator ==(const DLDbIdentifier &other) const + { return mImpl && other.mImpl ? *mImpl == *other.mImpl : mImpl.get() == other.mImpl.get(); } + DLDbIdentifier &operator =(const DLDbIdentifier &other) + { mImpl = other.mImpl; return *this; } + + // Accessors + const CssmSubserviceUid &ssuid() const { return mImpl->ssuid(); } + const char *dbName() const { return mImpl->dbName(); } + const CssmNetAddress *dbLocation() const { return mImpl->dbLocation(); } + + RefPointer mImpl; +}; + +// Wrappers for index-related CSSM objects. + +class CssmDbIndexInfo : public PodWrapper +{ +public: + CssmDbIndexInfo(const CSSM_DB_INDEX_INFO &attr) + { (CSSM_DB_INDEX_INFO &)*this = attr; } + + CSSM_DB_INDEX_TYPE indexType() const { return IndexType; } + void indexType(CSSM_DB_INDEX_TYPE indexType) { IndexType = indexType; } + + CSSM_DB_INDEXED_DATA_LOCATION dataLocation() const { return IndexedDataLocation; } + void dataLocation(CSSM_DB_INDEXED_DATA_LOCATION dataLocation) + { + IndexedDataLocation = dataLocation; + } + + const CssmDbAttributeInfo &attributeInfo() const + { + return CssmDbAttributeInfo::overlay(Info); + } +}; + + +namespace DataWalkers { + + +// +// DLDbIdentifiers don't walk directly because they have Impl structure and use strings. +// Happily, they are easily transcribed into a walkable form. +// +struct DLDbFlatIdentifier { + CssmSubserviceUid *uid; // module reference + char *name; // string name + CssmNetAddress *address; // optional network address + + DLDbFlatIdentifier(const DLDbIdentifier &ident) : + uid(const_cast(&ident.ssuid())), + name(const_cast(ident.dbName())), + address(const_cast(ident.dbLocation())) + { } + + operator DLDbIdentifier () { return DLDbIdentifier(*uid, name, address); } +}; + +template +DLDbFlatIdentifier *walk(Action &operate, DLDbFlatIdentifier * &ident) +{ + operate(ident); + if (ident->uid) + walk(operate, ident->uid); + walk(operate, ident->name); + if (ident->address) + walk(operate, ident->address); + return ident; +} + + +// +// Walkers for the byzantine data structures of the DL universe. +// Geez, what WERE they smoking when they invented this? +// + +// DbAttributeInfos +template +void enumerate(Action &operate, CssmDbAttributeInfo &info) +{ + switch (info.nameFormat()) { + case CSSM_DB_ATTRIBUTE_NAME_AS_STRING: + walk(operate, info.Label.AttributeName); + break; + case CSSM_DB_ATTRIBUTE_NAME_AS_OID: + walk(operate, info.Label.AttributeOID); + break; + default: + break; + } +} + +template +void walk(Action &operate, CssmDbAttributeInfo &info) +{ + operate(info); + enumerate(operate, info); +} + +template +CssmDbAttributeInfo *walk(Action &operate, CssmDbAttributeInfo * &info) +{ + operate(info); + enumerate(operate, *info); + return info; +} + +// DbRecordAttributeInfo +template +void walk(Action &operate, CssmDbRecordAttributeInfo &info) +{ + operate(info); + enumerateArray(operate, info, &CssmDbRecordAttributeInfo::attributes); +} + +template +CssmDbRecordAttributeInfo *walk(Action &operate, CssmDbRecordAttributeInfo * &info) +{ + operate(info); + enumerateArray(operate, *info, &CssmDbRecordAttributeInfo::attributes); + return info; +} + +// DbAttributeData (Info + value vector) +template +void walk(Action &operate, CssmDbAttributeData &data) +{ + operate(data); + walk(operate, data.info()); + enumerateArray(operate, data, &CssmDbAttributeData::values); +} + +template +CssmDbAttributeData *walk(Action &operate, CssmDbAttributeData * &data) +{ + operate(data); + walk(operate, data->info()); + enumerateArray(operate, *data, &CssmDbAttributeData::values); + return data; +} + +// DbRecordAttributeData (array of ...datas) +template +void walk(Action &operate, CssmDbRecordAttributeData &data) +{ + operate(data); + enumerateArray(operate, data, &CssmDbRecordAttributeData::attributes); +} + +template +CssmDbRecordAttributeData *walk(Action &operate, CssmDbRecordAttributeData * &data) +{ + operate(data); + enumerateArray(operate, *data, &CssmDbRecordAttributeData::attributes); + return data; +} + +// SelectionPredicates +template +CssmSelectionPredicate *walk(Action &operate, CssmSelectionPredicate * &predicate) +{ + operate(predicate); + walk(operate, predicate->attribute()); + return predicate; +} + +template +void walk(Action &operate, CssmSelectionPredicate &predicate) +{ + operate(predicate); + walk(operate, predicate.attribute()); +} + +// Queries +template +void walk(Action &operate, CssmQuery &query) +{ + operate(query); + enumerateArray(operate, query, &CssmQuery::predicates); +} + +template +CssmQuery *walk(Action &operate, CssmQuery * &query) +{ + operate(query); + enumerateArray(operate, *query, &CssmQuery::predicates); + return query; +} + +template +CSSM_QUERY *walk(Action &operate, CSSM_QUERY * &query) +{ + return walk(operate, CssmQuery::overlayVar(query)); +} + + +} // end namespace DataWalkers +} // end namespace Security + + +#endif // _H_CDSA_UTILITIES_CSSMDB diff --git a/libsecurity_cdsa_utilities/lib/cssmdbname.cpp b/libsecurity_cdsa_utilities/lib/cssmdbname.cpp new file mode 100644 index 00000000..02a54119 --- /dev/null +++ b/libsecurity_cdsa_utilities/lib/cssmdbname.cpp @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2000-2001,2003-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@ + */ +#include +#include +#include + +CssmNetAddress::CssmNetAddress(CSSM_DB_RECORDTYPE inAddressType, const CssmData &inAddress) +{ + AddressType = inAddressType; + Address.Length = inAddress.Length; + if (Address.Length > 0) + { + Address.Data = new uint8[Address.Length]; + memcpy (Address.Data, inAddress.Data, Address.Length); + } + else + Address.Data = NULL; +} + +CssmNetAddress::CssmNetAddress(const CSSM_NET_ADDRESS &other) +{ + AddressType = other.AddressType; + Address.Length = other.Address.Length; + if (Address.Length > 0) + { + Address.Data = new uint8[Address.Length]; + memcpy (Address.Data, other.Address.Data, Address.Length); + } + else + Address.Data = NULL; +} + +CssmNetAddress::~CssmNetAddress() +{ + if (Address.Length > 0) + delete Address.Data; +} + +void DbName::CanonicalizeName() +{ + if (mDbNameValid) + { + char* s = cached_realpath(mDbName.c_str(), NULL); + if (s != NULL) + { + mCanonicalName = s; + free(s); + } + else + { + // the most likely situation here is that the file doesn't exist. + // we will pull the path apart and try again. + + // search backward for the delimiter + int n = mDbName.length() - 1; + + // all subpaths must be tested, because there may be more than just + // the file name that doesn't exist. + while (n > 0) + { + while (n > 0 && mDbName[n] != '/') // if the delimiter is 0, we would never + // have gotten here in the first place + { + n -= 1; + } + + if (n > 0) + { + string tmpPath = mDbName.substr(0, n); + s = cached_realpath(tmpPath.c_str(), NULL); + if (s != NULL) + { + mCanonicalName = s; + free(s); + mCanonicalName += mDbName.substr(n, mDbName.length() - n); + return; + } + } + + n -= 1; + } + + // if we get here, all other paths have failed. Just reuse the original string. + mCanonicalName = mDbName; + } + } +} + + + +DbName::DbName(const char *inDbName, const CSSM_NET_ADDRESS *inDbLocation) + : mDbName(inDbName ? inDbName : ""), mDbNameValid(inDbName), mDbLocation(NULL) +{ + if (inDbLocation) + { + mDbLocation = new CssmNetAddress(*inDbLocation); + } + + CanonicalizeName(); +} + +DbName::DbName(const DbName &other) + : mDbName(other.mDbName), mDbNameValid(other.mDbNameValid), mDbLocation(NULL) +{ + if (other.mDbLocation) + { + mDbLocation = new CssmNetAddress(*other.mDbLocation); + } + + CanonicalizeName(); +} + +DbName & +DbName::operator =(const DbName &other) +{ + mDbName = other.mDbName; + mDbNameValid = other.mDbNameValid; + if (other.mDbLocation) + { + mDbLocation = new CssmNetAddress(*other.mDbLocation); + } + + return *this; +} + +DbName::~DbName() +{ + delete mDbLocation; +} diff --git a/libsecurity_cdsa_utilities/lib/cssmdbname.h b/libsecurity_cdsa_utilities/lib/cssmdbname.h new file mode 100644 index 00000000..4986864d --- /dev/null +++ b/libsecurity_cdsa_utilities/lib/cssmdbname.h @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2000-2001,2003-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@ + */ + + +#ifndef _DBNAME_H_ +#define _DBNAME_H_ 1 + +#include +#include +#include +#include + +#ifdef _CPP_DBNAME +# pragma export on +#endif + +// @@@ Should not use using in headers. +using namespace std; + +namespace Security +{ + +//---------------------------------------------------------------- +//typedef struct cssm_net_address { +// CSSM_NET_ADDRESS_TYPE AddressType; +// CSSM_DATA Address; +//} CSSM_NET_ADDRESS, *CSSM_NET_ADDRESS_PTR; +//---------------------------------------------------------------- + +// XXX TODO: Make CssmNetAddress use a factory to constuct netadrress objects based on CSSM_NET_ADDRESS_TYPE! +class CssmNetAddress : public PodWrapper +{ +public: + // Create a CssmNetAddress wrapper. Copies inAddress.Data + CssmNetAddress(CSSM_DB_RECORDTYPE inAddressType, const CssmData &inAddress); + CssmNetAddress(const CSSM_NET_ADDRESS &other); + ~CssmNetAddress(); + CSSM_DB_RECORDTYPE addressType() const { return AddressType; } + const CssmData &address() const { return CssmData::overlay(Address); } + bool operator <(const CssmNetAddress &other) const + { + return AddressType != other.AddressType ? AddressType < other.AddressType : address() < other.address(); + } +}; + +class DbName +{ +public: + DbName (const char *inDbName = NULL, const CSSM_NET_ADDRESS *inDbLocation = NULL); + DbName(const DbName &other); + DbName &operator =(const DbName &other); + ~DbName (); + const char *dbName() const { return mDbNameValid ? mDbName.c_str() : NULL; } + const char *canonicalName() const { return mDbNameValid ? mCanonicalName.c_str() : NULL; } + const CssmNetAddress *dbLocation() const { return mDbLocation; } + bool operator <(const DbName &other) const + { + // invalid is always smaller than valid + if (!mDbNameValid || !other.mDbNameValid) + return mDbNameValid < other.mDbNameValid; + + // If mDbNames are not equal return whether our mDbName is less than others mDbName. + if (canonicalName() != other.canonicalName()) + return mDbName < other.mDbName; + + // DbNames are equal so check for pointer equality of DbLocations + if (mDbLocation == other.mDbLocation) + return false; + + // If either DbLocations is nil the one that is nil is less than the other. + if (mDbLocation == nil || other.mDbLocation == nil) + return mDbLocation < other.mDbLocation; + + // Return which mDbLocation is smaller. + return *mDbLocation < *other.mDbLocation; + } + bool operator ==(const DbName &other) const + { return (!(*this < other)) && (!(other < *this)); } + bool operator !=(const DbName &other) const + { return *this < other || other < *this; } + +private: + void CanonicalizeName(); + + string mDbName; + string mCanonicalName; + bool mDbNameValid; + CssmNetAddress *mDbLocation; +}; + + +namespace DataWalkers +{ + +template +CssmNetAddress *walk(Action &operate, CssmNetAddress * &addr) +{ + operate(addr); + walk(operate, addr->Address); + return addr; +} + +} // end namespace DataWalkers + +} // end namespace Security + +#ifdef _CPP_DBNAME +# pragma export off +#endif + +#endif //_DBNAME_H_ diff --git a/libsecurity_cdsa_utilities/lib/cssmendian.cpp b/libsecurity_cdsa_utilities/lib/cssmendian.cpp new file mode 100644 index 00000000..ac73c09d --- /dev/null +++ b/libsecurity_cdsa_utilities/lib/cssmendian.cpp @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2002-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@ + */ + + +// +// Byte order ("endian-ness") handling +// +#include + +namespace Security { + + +void n2hi(CssmKey::Header &header) +{ + header.HeaderVersion = n2h(header.HeaderVersion); + header.BlobType = n2h(header.BlobType); + header.Format = n2h(header.Format); + header.AlgorithmId = n2h(header.AlgorithmId); + header.KeyClass = n2h(header.KeyClass); + header.LogicalKeySizeInBits = n2h(header.LogicalKeySizeInBits); + header.KeyAttr = n2h(header.KeyAttr); + header.KeyUsage = n2h(header.KeyUsage); + header.WrapAlgorithmId = n2h(header.WrapAlgorithmId); + header.WrapMode = n2h(header.WrapMode); + header.Reserved = n2h(header.Reserved); +} + +void h2ni(CssmKey::Header &key) +{ + n2hi(key); +} + +} // end namespace Security diff --git a/libsecurity_cdsa_utilities/lib/cssmendian.h b/libsecurity_cdsa_utilities/lib/cssmendian.h new file mode 100644 index 00000000..71e23d20 --- /dev/null +++ b/libsecurity_cdsa_utilities/lib/cssmendian.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2002-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@ + */ + + +/* + * cssm utilities + */ +#ifndef _H_CSSMENDIAN +#define _H_CSSMENDIAN + +#include +#include + +namespace Security { + + +// +// Some structs we may want swapped in-place +// +void n2hi(CssmKey::Header &key); +void h2ni(CssmKey::Header &key); + +inline void n2hi(CSSM_KEYHEADER &key) { n2hi(CssmKey::Header::overlay (key));} +inline void h2ni(CSSM_KEYHEADER &key) { h2ni(CssmKey::Header::overlay (key));} + +} // end namespace Security + + +#endif //_H_CSSMENDIAN + diff --git a/libsecurity_cdsa_utilities/lib/cssmerrors.cpp b/libsecurity_cdsa_utilities/lib/cssmerrors.cpp new file mode 100644 index 00000000..e5a3460c --- /dev/null +++ b/libsecurity_cdsa_utilities/lib/cssmerrors.cpp @@ -0,0 +1,129 @@ +/* + * 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@ + */ + + +// +// cssmerrors +// +#include +#include +#include +#include + +namespace Security { + + +CssmError::CssmError(CSSM_RETURN err) : error(err) +{ + SECURITY_EXCEPTION_THROW_CSSM(this, err); +} + + +const char *CssmError::what() const throw () +{ + return "CSSM exception"; +} + + +OSStatus CssmError::osStatus() const +{ + if (error == CSSM_ERRCODE_INVALID_POINTER) + { + return paramErr; + } + + return error; +} + + +int CssmError::unixError() const +{ + OSStatus err = osStatus(); + + // embedded UNIX errno values are returned verbatim + if (err >= errSecErrnoBase && err <= errSecErrnoLimit) + return err - errSecErrnoBase; + + // re-map certain CSSM errors + switch (err) { + case CSSM_ERRCODE_MEMORY_ERROR: + return ENOMEM; + case CSSMERR_APPLEDL_DISK_FULL: + return ENOSPC; + case CSSMERR_APPLEDL_QUOTA_EXCEEDED: + return EDQUOT; + case CSSMERR_APPLEDL_FILE_TOO_BIG: + return EFBIG; + default: + // cannot map this to errno space + return -1; + } +} + + +void CssmError::throwMe(CSSM_RETURN err) +{ + throw CssmError(err); +} + + +CSSM_RETURN CssmError::merge(CSSM_RETURN error, CSSM_RETURN base) +{ + if (0 < error && error < CSSM_ERRORCODE_COMMON_EXTENT) { + return base + error; + } else { + return error; + } +} + +// +// Get a CSSM_RETURN from a CommonError +// +CSSM_RETURN CssmError::cssmError(const CommonError &error, CSSM_RETURN base) +{ + if (const CssmError *cssm = dynamic_cast(&error)) { + return cssmError(cssm->error, base); + } else if (const MachPlusPlus::Error *mach = dynamic_cast(&error)) { + switch (mach->error) { + case BOOTSTRAP_UNKNOWN_SERVICE: + case MIG_SERVER_DIED: + return CSSM_ERRCODE_SERVICE_NOT_AVAILABLE; + default: + return CSSM_ERRCODE_INTERNAL_ERROR; + } + } else { + return error.osStatus(); + } +} + +CSSM_RETURN CssmError::cssmError(CSSM_RETURN error, CSSM_RETURN base) +{ + if (0 < error && error < CSSM_ERRORCODE_COMMON_EXTENT) { + return base + error; + } else { + return error; + } +} + + +} // namespace Security diff --git a/libsecurity_cdsa_utilities/lib/cssmerrors.h b/libsecurity_cdsa_utilities/lib/cssmerrors.h new file mode 100644 index 00000000..a41fd2bf --- /dev/null +++ b/libsecurity_cdsa_utilities/lib/cssmerrors.h @@ -0,0 +1,68 @@ +/* + * 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@ + */ + + +/* + * cssmerrors + */ +#ifndef _H_CSSMERRORS +#define _H_CSSMERRORS + +#include +#include + +namespace Security +{ + +// +// A CSSM-originated error condition, represented by a CSSM_RETURN value. +// This can represent both a convertible base error, or a module-specific +// error condition. +// +class CssmError : public CommonError { +protected: + CssmError(CSSM_RETURN err); +public: + const CSSM_RETURN error; + virtual OSStatus osStatus() const; + virtual int unixError() const; + virtual const char *what () const throw (); + + static CSSM_RETURN merge(CSSM_RETURN error, CSSM_RETURN base); + + static void check(CSSM_RETURN error) { if (error != CSSM_OK) throwMe(error); } + static void throwMe(CSSM_RETURN error) __attribute__((noreturn)); + + // + // Obtain a CSSM_RETURN from any CommonError + // + static CSSM_RETURN cssmError(CSSM_RETURN error, CSSM_RETURN base); + static CSSM_RETURN cssmError(const CommonError &error, CSSM_RETURN base); +}; + + + +} // end namespace Security + + +#endif //_H_CSSMERRORS diff --git a/libsecurity_cdsa_utilities/lib/cssmkey.cpp b/libsecurity_cdsa_utilities/lib/cssmkey.cpp new file mode 100644 index 00000000..9ad142fe --- /dev/null +++ b/libsecurity_cdsa_utilities/lib/cssmkey.cpp @@ -0,0 +1,56 @@ +/* + * 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@ + */ + + +// +// PODWrapper for CssmKey and related types +// +#include + + +// +// Methods for the CssmKey class +// +CssmKey::CssmKey(const CSSM_KEY &key) +{ + KeyHeader = key.KeyHeader; + KeyData = key.KeyData; +} + +CssmKey::CssmKey(const CSSM_DATA &keyData) +{ + clearPod(); + KeyData = keyData; + KeyHeader.HeaderVersion = CSSM_KEYHEADER_VERSION; + KeyHeader.BlobType = CSSM_KEYBLOB_RAW; + KeyHeader.Format = CSSM_KEYBLOB_RAW_FORMAT_NONE; +} + +CssmKey::CssmKey(uint32 length, void *data) +{ + clearPod(); + KeyData = CssmData(data, length); + KeyHeader.HeaderVersion = CSSM_KEYHEADER_VERSION; + KeyHeader.BlobType = CSSM_KEYBLOB_RAW; + KeyHeader.Format = CSSM_KEYBLOB_RAW_FORMAT_NONE; +} diff --git a/libsecurity_cdsa_utilities/lib/cssmkey.h b/libsecurity_cdsa_utilities/lib/cssmkey.h new file mode 100644 index 00000000..4154fb42 --- /dev/null +++ b/libsecurity_cdsa_utilities/lib/cssmkey.h @@ -0,0 +1,151 @@ +/* + * 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@ + */ + + +// +// PODWrapper for CssmKey and related types +// +#ifndef _H_CSSMKEY +#define _H_CSSMKEY + +#include +#include +#include +#include + + +namespace Security { + + +// +// User-friendlier CSSM_KEY objects +// +class CssmKey : public PodWrapper { +public: + CssmKey() { clearPod(); KeyHeader.HeaderVersion = CSSM_KEYHEADER_VERSION; } + // all of the following constructors take over ownership of the key data + CssmKey(const CSSM_KEY &key); + CssmKey(const CSSM_DATA &keyData); + CssmKey(uint32 length, void *data); + +public: + class Header : public PodWrapper { + public: + // access to components of the key header + CSSM_KEYBLOB_TYPE blobType() const { return BlobType; } + void blobType(CSSM_KEYBLOB_TYPE blobType) { BlobType = blobType; } + + CSSM_KEYBLOB_FORMAT blobFormat() const { return Format; } + void blobFormat(CSSM_KEYBLOB_FORMAT blobFormat) { Format = blobFormat; } + + CSSM_KEYCLASS keyClass() const { return KeyClass; } + void keyClass(CSSM_KEYCLASS keyClass) { KeyClass = keyClass; } + + CSSM_KEY_TYPE algorithm() const { return AlgorithmId; } + void algorithm(CSSM_KEY_TYPE algorithm) { AlgorithmId = algorithm; } + + CSSM_KEY_TYPE wrapAlgorithm() const { return WrapAlgorithmId; } + void wrapAlgorithm(CSSM_KEY_TYPE wrapAlgorithm) { WrapAlgorithmId = wrapAlgorithm; } + + CSSM_ENCRYPT_MODE wrapMode() const { return WrapMode; } + void wrapMode(CSSM_ENCRYPT_MODE mode) { WrapMode = mode; } + + bool isWrapped() const { return WrapAlgorithmId != CSSM_ALGID_NONE; } + + const Guid &cspGuid() const { return Guid::overlay(CspId); } + void cspGuid(const Guid &guid) { Guid::overlay(CspId) = guid; } + + uint32 attributes() const { return KeyAttr; } + bool attribute(uint32 attr) const { return KeyAttr & attr; } + void setAttribute(uint32 attr) { KeyAttr |= attr; } + void clearAttribute(uint32 attr) { KeyAttr &= ~attr; } + + uint32 usage() const { return KeyUsage; } + bool useFor(uint32 u) const { return KeyUsage & u; } + + void usage(uint32 u) { KeyUsage |= u; } + void clearUsage(uint32 u) { KeyUsage &= ~u; } + + }; + + // access to the key header + Header &header() { return Header::overlay(KeyHeader); } + const Header &header() const { return Header::overlay(KeyHeader); } + + CSSM_KEYBLOB_TYPE blobType() const { return header().blobType(); } + void blobType(CSSM_KEYBLOB_TYPE blobType) { header().blobType(blobType); } + + CSSM_KEYBLOB_FORMAT blobFormat() const { return header().blobFormat(); } + void blobFormat(CSSM_KEYBLOB_FORMAT blobFormat) { header().blobFormat(blobFormat); } + + CSSM_KEYCLASS keyClass() const { return header().keyClass(); } + void keyClass(CSSM_KEYCLASS keyClass) { header().keyClass(keyClass); } + + CSSM_KEY_TYPE algorithm() const { return header().algorithm(); } + void algorithm(CSSM_KEY_TYPE algorithm) { header().algorithm(algorithm); } + + CSSM_KEY_TYPE wrapAlgorithm() const { return header().wrapAlgorithm(); } + void wrapAlgorithm(CSSM_KEY_TYPE wrapAlgorithm) { header().wrapAlgorithm(wrapAlgorithm); } + + CSSM_ENCRYPT_MODE wrapMode() const { return header().wrapMode(); } + void wrapMode(CSSM_ENCRYPT_MODE mode) { header().wrapMode(mode); } + + bool isWrapped() const { return header().isWrapped(); } + const Guid &cspGuid() const { return header().cspGuid(); } + + uint32 attributes() const { return header().attributes(); } + bool attribute(uint32 a) const { return header().attribute(a); } + void setAttribute(uint32 attr) { header().setAttribute(attr); } + void clearAttribute(uint32 attr) { header().clearAttribute(attr); } + + uint32 usage() const { return header().usage(); } + bool useFor(uint32 u) const { return header().useFor(u); } + + void usage(uint32 u) { header().usage(u); } + void clearUsage(uint32 u) { header().clearUsage(u); } + +public: + // access to the key data + size_t length() const { return KeyData.Length; } + void *data() const { return KeyData.Data; } + operator void * () const { return data(); } + CssmData &keyData() { return CssmData::overlay(KeyData); } + const CssmData &keyData() const { return CssmData::overlay(KeyData); } + operator CssmData & () { return keyData(); } + operator const CssmData & () const { return keyData(); } + operator bool () const { return KeyData.Data != NULL; } + void operator = (const CssmData &data) { KeyData = data; } +}; + + +// +// Wrapped keys are currently identically structured to normal keys. +// But perhaps in the future... +// +typedef CssmKey CssmWrappedKey; + + +} // end namespace Security + + +#endif //_H_CSSMUTILITIES diff --git a/libsecurity_cdsa_utilities/lib/cssmlist.cpp b/libsecurity_cdsa_utilities/lib/cssmlist.cpp new file mode 100644 index 00000000..7fa52a1f --- /dev/null +++ b/libsecurity_cdsa_utilities/lib/cssmlist.cpp @@ -0,0 +1,313 @@ +/* + * 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@ + */ + + +// +// cssmlist - CSSM_LIST operational utilities +// +#include +#include + + +// +// Managing list elements +// +ListElement *ListElement::last() +{ + for (ListElement *p = this; ; p = p->next()) + if (p->next() == NULL) + return p; + // not reached +} + + +ListElement::ListElement(CSSM_WORDID_TYPE word) +{ + ElementType = CSSM_LIST_ELEMENT_WORDID; + WordID = word; +} + +ListElement::ListElement(const CssmData &data) +{ + ElementType = CSSM_LIST_ELEMENT_DATUM; + WordID = 0; + Element.Word = data; +} + +ListElement::ListElement(Allocator &alloc, const CssmData &data) +{ + ElementType = CSSM_LIST_ELEMENT_DATUM; + WordID = 0; + Element.Word = CssmAutoData(alloc, data).release(); +} + +ListElement::ListElement(Allocator &alloc, const string &s) +{ + ElementType = CSSM_LIST_ELEMENT_DATUM; + WordID = 0; + Element.Word = CssmAutoData(alloc, s.data(), s.size()).release(); +} + +ListElement::ListElement(const CssmList &list) +{ + ElementType = CSSM_LIST_ELEMENT_SUBLIST; + WordID = 0; + Element.Sublist = list; +} + + +CssmData &ListElement::data() +{ + assert(type() == CSSM_LIST_ELEMENT_DATUM); + return CssmData::overlay(Element.Word); +} + +const CssmData &ListElement::data() const +{ + assert(type() == CSSM_LIST_ELEMENT_DATUM); + return CssmData::overlay(Element.Word); +} + +ListElement &ListElement::operator = (const CssmData &data) +{ + assert(type() == CSSM_LIST_ELEMENT_DATUM); + Element.Word = data; + return *this; +} + + +CssmList &ListElement::list() +{ + assert(type() == CSSM_LIST_ELEMENT_SUBLIST); + return CssmList::overlay(Element.Sublist); +} + +const CssmList &ListElement::list() const +{ + assert(type() == CSSM_LIST_ELEMENT_SUBLIST); + return CssmList::overlay(Element.Sublist); +} + +TypedList &ListElement::typedList() +{ + return static_cast(list()); +} + +const TypedList &ListElement::typedList() const +{ + return static_cast(list()); +} + +ListElement &ListElement::operator = (const CssmList &list) +{ + assert(type() == CSSM_LIST_ELEMENT_SUBLIST); + Element.Sublist = list; + return *this; +} + + +CSSM_WORDID_TYPE ListElement::word() const +{ + assert(type() == CSSM_LIST_ELEMENT_WORDID); + return WordID; +} + +ListElement &ListElement::operator = (CSSM_WORDID_TYPE word) +{ + assert(type() == CSSM_LIST_ELEMENT_WORDID); + WordID = word; + return *this; +} + + +// +// List operations +// +ListElement &CssmList::operator [] (unsigned ix) const +{ + for (ListElement *elem = first(); elem; elem = elem->next(), ix--) { + if (ix == 0) + return *elem; + } + throw 999; //@@@ +} + +unsigned int CssmList::length() const +{ + unsigned int len = 0; + for (ListElement *elem = first(); elem; elem = elem->next()) + len++; + return len; +} + +CssmList &CssmList::append(ListElement *elem) +{ + if (Tail == NULL) { // first element + Head = Tail = elem; + } else { + Tail->NextElement = elem; + Tail = elem; + } + elem->NextElement = NULL; + return *this; +} + +CssmList &CssmList::insert(ListElement *elem, ListElement *before) +{ + // null before -> append + if (before == NULL) + return append(elem); + + // we have a real position + assert(!empty()); + if (Head == before) { // before first element + elem->NextElement = before; + Head = elem; + } else { // before is not first + for (CSSM_LIST_ELEMENT *p = Head; p; p = p->NextElement) { + if (p->NextElement == before) { + elem->NextElement = before; + p->NextElement = elem; + return *this; + } + } + // end of list, before not in list + throw 999; //@@@ + } + return *this; +} + +CssmList &CssmList::remove(ListElement *elem) +{ + assert(elem); + if (elem == Head) { // remove first element + Head = Head->NextElement; + } else { // subsequent element + for (CSSM_LIST_ELEMENT *p = Head; p; p = p->NextElement) + if (p->NextElement == elem) { + p->NextElement = elem->NextElement; + if (elem->NextElement == NULL) // removing last element + Tail = p; + return *this; + } + // end of list, elem not found + throw 999; //@@@ + } + return *this; +} + +void CssmList::snip() +{ + assert(Head); // can't be empty + if (Head == Tail) { // single element, empty when snipped + Head = Tail = NULL; + } else { // more than one, bypass first + Head = first()->next(); + } +} + + +// +// Deep-destruction of CssmLists and ListElements. +// The underlying assumption is that all components were allocated from a single +// Allocator in canonical chunks. +// +void ListElement::clear(Allocator &alloc) +{ + switch (type()) { + case CSSM_LIST_ELEMENT_WORDID: + break; // no substructure + case CSSM_LIST_ELEMENT_DATUM: + alloc.free(data().data()); + break; + case CSSM_LIST_ELEMENT_SUBLIST: + list().clear(alloc); + break; + default: + assert(false); + } +} + +void CssmList::clear(Allocator &alloc) +{ + ListElement *elem = first(); + while (elem) { + ListElement *next = elem->next(); + destroy(elem, alloc); + elem = next; + } +} + + +// +// Building TypedLists +// +TypedList::TypedList(Allocator &alloc, CSSM_WORDID_TYPE type) +{ + append(new(alloc) ListElement(type)); +} + +TypedList::TypedList(Allocator &alloc, CSSM_WORDID_TYPE type, ListElement *elem1) +{ + append(new(alloc) ListElement(type)); + append(elem1); +} + +TypedList::TypedList(Allocator &alloc, CSSM_WORDID_TYPE type, ListElement *elem1, ListElement *elem2) +{ + append(new(alloc) ListElement(type)); + append(elem1); + append(elem2); +} + +TypedList::TypedList(Allocator &alloc, CSSM_WORDID_TYPE type, ListElement *elem1, ListElement *elem2, ListElement *elem3) +{ + append(new(alloc) ListElement(type)); + append(elem1); + append(elem2); + append(elem3); +} + +TypedList::TypedList(Allocator &alloc, CSSM_WORDID_TYPE type, ListElement *elem1, ListElement *elem2, ListElement *elem3, ListElement *elem4) +{ + append(new(alloc) ListElement(type)); + append(elem1); + append(elem2); + append(elem3); + append(elem4); +} + + +// +// Verify that a TypedList is "proper", i.e. has a first element of WORDID form +// +bool TypedList::isProper() const +{ + return first() && first()->type() == CSSM_LIST_ELEMENT_WORDID; +} + +void TypedList::checkProper(CSSM_RETURN error) const +{ + if (!isProper()) + CssmError::throwMe(error); +} diff --git a/libsecurity_cdsa_utilities/lib/cssmlist.h b/libsecurity_cdsa_utilities/lib/cssmlist.h new file mode 100644 index 00000000..fd594995 --- /dev/null +++ b/libsecurity_cdsa_utilities/lib/cssmlist.h @@ -0,0 +1,269 @@ +/* + * Copyright (c) 2000-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@ + */ + + +// +// cssmlist - CSSM_LIST operational utilities +// +#ifndef _H_CSSMLIST +#define _H_CSSMLIST + +#include +#include +#include + + +namespace Security { + +class CssmList; +class TypedList; + + +// +// A POD Wrapper for CSSM_LIST_ELEMENTs. +// List elements are pseudo-polymorphic, so we provide ways to get and +// set their three personalities. It's up to the caller to get this right; +// you mustn't (for example) call the data() method on a list element that +// is not of (element) type CSSM_LIST_ELEMENT_DATUM. To violate this rule +// will get you an assertion (not exception). +// +class ListElement : public PodWrapper { +public: + // type control + CSSM_LIST_ELEMENT_TYPE type() const { return ElementType; } + bool is(CSSM_LIST_ELEMENT_TYPE t) const { return type() == t; } + + // list element chaining + ListElement * &next() { return ListElement::overlayVar(NextElement); } + ListElement *next() const { return ListElement::overlay(NextElement); } + ListElement *last(); + + // CssmData personality + explicit ListElement(const CssmData &data); + explicit ListElement(Allocator &alloc, const CssmData &data); + explicit ListElement(Allocator &alloc, const std::string &stringData); + + CssmData &data(); + string toString() const { return data().toString(); } + const CssmData &data() const; + ListElement &operator = (const CssmData &data); + operator CssmData &() { return data(); } + operator std::string () const { return toString(); } + bool operator == (const CssmData &other) const { return data() == other; } + bool operator != (const CssmData &other) const { return data() != other; } + + template + void extract(T &destination, CSSM_RETURN error = CSSM_ERRCODE_INVALID_DATA) + { data().extract(destination, error); } + + // CssmList (sublist) personality + explicit ListElement(const CssmList &list); + CssmList &list(); + const CssmList &list() const; + TypedList &typedList(); + const TypedList &typedList() const; + ListElement &operator = (const CssmList &list); + operator CssmList &() { return list(); } + operator TypedList &(); + + // WORDID (number) personality + explicit ListElement(CSSM_WORDID_TYPE word); + CSSM_WORDID_TYPE word() const; + ListElement &operator = (CSSM_WORDID_TYPE word); + operator CSSM_WORDID_TYPE () const { return word(); } + +public: + void *operator new (size_t size, Allocator &alloc) + { return alloc.malloc(size); } + + void clear(Allocator &alloc); // free my contents +}; + +} // end namespace Security + +// specialize destroy() to call clear() for cleanup +inline void destroy(ListElement *elem, Allocator &alloc) +{ + elem->clear(alloc); + alloc.free(elem); +} + +namespace Security { + + +// +// A POD Wrapper for CSSM_LIST. +// CssmList does no memory allocations. Retrieval functions return pointers or +// references into existing content, and modifiers modify in-place without any +// attempt to release previous dynamic content. May the Leaking God be with You. +// +class CssmList : public PodWrapper { +public: + CssmList() { ListType = CSSM_LIST_TYPE_UNKNOWN; Head = Tail = NULL; } + CssmList(const CssmList &list) { *(CssmList *)this = list; } + +public: + CSSM_LIST_TYPE kind() const { return ListType; } // type() reserved for TypedList + + ListElement &operator [] (unsigned ix) const; + unsigned int length() const; + ListElement * &first() { return ListElement::overlayVar(Head); } + ListElement *first() const { return ListElement::overlay(Head); } + ListElement *last() const { return ListElement::overlay(Tail); } + bool empty() const { return first() == NULL; } + + CssmList &append(ListElement *elem); + CssmList &insert(ListElement *elem, ListElement *before); + CssmList &remove(ListElement *elem); + CssmList &operator += (ListElement *elem) { return append(elem); } + CssmList &operator -= (ListElement *elem) { return remove(elem); } + + // logically remove the first element (skip it) + void snip(); + +public: + void clear(Allocator &alloc); // free my contents +}; + +} // end namespace Security + +inline void destroy(CssmList *list, Allocator &alloc) +{ + list->clear(alloc); + alloc.free(list); +} + +namespace Security +{ + +// +// Enhanced overlay for CssmLists whose first element is known to be a wordid. +// +class TypedList : public CssmList { +public: + explicit TypedList(const CSSM_LIST &list) { *(CSSM_LIST *)this = list; } + TypedList(Allocator &alloc, CSSM_WORDID_TYPE type); + TypedList(Allocator &alloc, CSSM_WORDID_TYPE type, ListElement *elem1); + TypedList(Allocator &alloc, CSSM_WORDID_TYPE type, ListElement *elem1, + ListElement *elem2); + TypedList(Allocator &alloc, CSSM_WORDID_TYPE type, ListElement *elem1, + ListElement *elem2, ListElement *elem3); + TypedList(Allocator &alloc, CSSM_WORDID_TYPE type, ListElement *elem1, + ListElement *elem2, ListElement *elem3, ListElement *elem4); + + bool isProper() const; // format check (does not throw) + void checkProper(CSSM_RETURN error = CSSM_ERRCODE_INVALID_SAMPLE_VALUE) const; + static TypedList &overlay(CSSM_LIST &list) + { return static_cast(list); } + static const TypedList &overlay(const CSSM_LIST &list) + { return static_cast(list); } + + CSSM_WORDID_TYPE type() const + { assert(isProper()); return first()->word(); } +}; + +inline ListElement::operator TypedList &() +{ return TypedList::overlay(operator CssmList &()); } + + +// +// Data walkers to parse list elements and lists. +// @@@ Walking lists by recursing over next() is stack intensive. Do this in CssmList walker by loop? +// +namespace DataWalkers { + +// ListElement +template +ListElement *walk(Action &operate, ListElement * &elem) +{ + operate(elem); + switch (elem->type()) { + case CSSM_LIST_ELEMENT_DATUM: + walk(operate, elem->data()); + break; + case CSSM_LIST_ELEMENT_SUBLIST: + walk(operate, elem->list()); + break; + case CSSM_LIST_ELEMENT_WORDID: + break; + default: + secdebug("walkers", "invalid list element type (%ux)", (unsigned)elem->type()); + break; + } + if (elem->next()) + walk(operate, elem->next()); + return elem; +} + +template +ListElement *walk(Action &operate, CSSM_LIST_ELEMENT * &elem) +{ return walk(operate, ListElement::overlayVar(elem)); } + +// CssmList +template +void enumerate(Action &operate, CssmList &list) +{ + if (!list.empty()) { + walk(operate, list.first()); + if (operate.needsRelinking) + list.Tail = list.first()->last(); // re-establish "tail" link + } +} + +template +CssmList *walk(Action &operate, CssmList * &list) +{ + operate(list); + enumerate(operate, *list); + return list; +} + +template +void walk(Action &operate, CssmList &list) +{ + operate(list); + enumerate(operate, list); +} + +template +void walk(Action &operate, CSSM_LIST &list) +{ walk(operate, CssmList::overlay(list)); } + +template +CSSM_LIST *walk(Action &operate, CSSM_LIST * &list) +{ return walk(operate, CssmList::overlayVar(list)); } + +template +TypedList *walk(Action &operate, TypedList * &list) +{ return static_cast(walk(operate, reinterpret_cast(list))); } + +template +void walk(Action &operate, TypedList &list) +{ walk(operate, static_cast(list)); } + + +} // end namespace DataWalkers +} // end namespace Security + + +#endif //_H_CSSMLIST diff --git a/libsecurity_cdsa_utilities/lib/cssmpods.cpp b/libsecurity_cdsa_utilities/lib/cssmpods.cpp new file mode 100644 index 00000000..60e5ddd0 --- /dev/null +++ b/libsecurity_cdsa_utilities/lib/cssmpods.cpp @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2000-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@ + */ + + +// +// Miscellaneous CSSM PODWrappers +// +#include +#include +#include + +// +// GUID <-> string conversions. +// Note that we DO check for {} on input and insist on rigid formatting. +// We don't require a terminating null byte on input, but generate it on output. +// +char *Guid::toString(char buffer[stringRepLength+1]) const +{ + sprintf(buffer, "{%8.8x-%4.4hx-%4.4hx-", + int(n2h(Data1)), n2h(Data2), n2h(Data3)); + for (int n = 0; n < 2; n++) + sprintf(buffer + 20 + 2*n, "%2.2hhx", Data4[n]); + buffer[24] = '-'; + for (int n = 2; n < 8; n++) + sprintf(buffer + 21 + 2*n, "%2.2hhx", Data4[n]); + buffer[37] = '}'; + buffer[38] = '\0'; + return buffer; +} + +string Guid::toString() const +{ + char buffer[stringRepLength+1]; + return toString(buffer); +} + +Guid::Guid(const char *s) +{ + parseGuid(s); +} + +Guid::Guid(const string &s) +{ + parseGuid(s.c_str()); +} + +void Guid::parseGuid(const char *string) +{ + // Arguably, we should be more flexible on input. But exactly what + // padding rules should we follow, and how should we try to interprete + // "doubtful" variations? Given that GUIDs are essentially magic + // cookies, everybody's better off if we just cut-and-paste them + // around the universe... + + // do sanity checking, don't assume that what's passed in makes sense + if (string == NULL) + { + CssmError::throwMe(CSSM_ERRCODE_INVALID_GUID); + } + + // what follows had better be big enough + if (strlen(string) < 37) // needed because the code hard codes the length + { + CssmError::throwMe(CSSM_ERRCODE_INVALID_GUID); + } + + int d1; + uint16 d2, d3; + if (sscanf(string, "{%8x-%4hx-%4hx-", &d1, &d2, &d3) != 3) + CssmError::throwMe(CSSM_ERRCODE_INVALID_GUID); + Data1 = h2n(uint32(d1)); + Data2 = h2n(d2); + Data3 = h2n(d3); + // once, we did not expect the - after byte 2 of Data4 + bool newForm = string[24] == '-'; + for (int n = 0; n < 8; n++) { + unsigned char dn; + if (sscanf(string + 20 + 2*n + (newForm && n >= 2), "%2hhx", &dn) != 1) + CssmError::throwMe(CSSM_ERRCODE_INVALID_GUID); + Data4[n] = dn; + } + if (string[37 - !newForm] != '}') + CssmError::throwMe(CSSM_ERRCODE_INVALID_GUID); +} + + +CssmGuidData::CssmGuidData(const CSSM_GUID &guid) : CssmData(buffer, sizeof(buffer)) +{ + Guid::overlay(guid).toString(buffer); +} + + +// +// CssmSubserviceUids. +// Note that for comparison, we ignore the version field. +// This is not necessarily the Right Choice, but suits certain +// constraints in the Sec* layer. Perhaps we might reconsider +// this after a thorough code review to determine the intended +// (by the standard) semantics and proper use. Yeah, right. +// +CssmSubserviceUid::CssmSubserviceUid(const CSSM_GUID &guid, + const CSSM_VERSION *version, uint32 subserviceId, CSSM_SERVICE_TYPE subserviceType) +{ + Guid = guid; + SubserviceId = subserviceId; + SubserviceType = subserviceType; + if (version) + Version = *version; + else + Version.Major = Version.Minor = 0; +} + + +bool CssmSubserviceUid::operator == (const CSSM_SUBSERVICE_UID &otherUid) const +{ + const CssmSubserviceUid &other = CssmSubserviceUid::overlay(otherUid); + return subserviceId() == other.subserviceId() + && subserviceType() == other.subserviceType() + && guid() == other.guid(); +} + +bool CssmSubserviceUid::operator < (const CSSM_SUBSERVICE_UID &otherUid) const +{ + const CssmSubserviceUid &other = CssmSubserviceUid::overlay(otherUid); + if (subserviceId() < other.subserviceId()) + return true; + if (subserviceId() > other.subserviceId()) + return false; + if (subserviceType() < other.subserviceType()) + return true; + if (subserviceType() > other.subserviceType()) + return false; + return guid() < other.guid(); +} + + +// +// CryptoData & friends +// +CryptoDataClass::~CryptoDataClass() +{ } + +CSSM_RETURN CryptoDataClass::callbackShim(CSSM_DATA *output, void *ctx) +{ + BEGIN_API + *output = reinterpret_cast(ctx)->yield(); + END_API(CSSM) +} diff --git a/libsecurity_cdsa_utilities/lib/cssmpods.h b/libsecurity_cdsa_utilities/lib/cssmpods.h new file mode 100644 index 00000000..1e5eab49 --- /dev/null +++ b/libsecurity_cdsa_utilities/lib/cssmpods.h @@ -0,0 +1,221 @@ +/* + * 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@ + */ + + +// +// Miscellaneous CSSM PODWrappers +// +#ifndef _H_CSSMPODS +#define _H_CSSMPODS + +#include +#include +#include + + +namespace Security { + + +// +// User-friendly GUIDs +// +class Guid : public PodWrapper { +public: + Guid() { /*IFDEBUG(*/ memset(this, 0, sizeof(*this)) /*)*/ ; } + Guid(const CSSM_GUID &rGuid) { memcpy(this, &rGuid, sizeof(*this)); } + Guid(const char *string); + Guid(const std::string &s); + + Guid &operator = (const CSSM_GUID &rGuid) + { memcpy(this, &rGuid, sizeof(CSSM_GUID)); return *this; } + + bool operator == (const CSSM_GUID &other) const + { return (this == &other) || !memcmp(this, &other, sizeof(CSSM_GUID)); } + bool operator != (const CSSM_GUID &other) const + { return (this != &other) && memcmp(this, &other, sizeof(CSSM_GUID)); } + bool operator < (const CSSM_GUID &other) const + { return memcmp(this, &other, sizeof(CSSM_GUID)) < 0; } + size_t hash() const { //@@@ revisit this hash + return Data1 + Data2 << 3 + Data3 << 11 + Data4[3] + Data4[6] << 22; + } + + static const unsigned stringRepLength = 38; // "{x8-x4-x4-x4-x12}" + char *toString(char buffer[stringRepLength+1]) const; // will append \0 + string toString() const; // make std::string + +private: + void parseGuid(const char *string); +}; + +class CssmGuidData : public CssmData { +public: + CssmGuidData(const CSSM_GUID &guid); + +private: + char buffer[Guid::stringRepLength + 1]; +}; + + +// +// User-friendly CSSM_SUBSERVICE_UIDs +// +class CssmSubserviceUid : public PodWrapper { +public: + CssmSubserviceUid() { clearPod(); } + CssmSubserviceUid(const CSSM_SUBSERVICE_UID &rSSuid) { memcpy(this, &rSSuid, sizeof(*this)); } + + CssmSubserviceUid &operator = (const CSSM_SUBSERVICE_UID &rSSuid) + { memcpy(this, &rSSuid, sizeof(CSSM_SUBSERVICE_UID)); return *this; } + + bool operator == (const CSSM_SUBSERVICE_UID &other) const; + bool operator != (const CSSM_SUBSERVICE_UID &other) const { return !(*this == other); } + bool operator < (const CSSM_SUBSERVICE_UID &other) const; + + CssmSubserviceUid(const CSSM_GUID &guid, const CSSM_VERSION *version = NULL, + uint32 subserviceId = 0, + CSSM_SERVICE_TYPE subserviceType = CSSM_SERVICE_DL); + + const ::Guid &guid() const { return ::Guid::overlay(Guid); } + uint32 subserviceId() const { return SubserviceId; } + CSSM_SERVICE_TYPE subserviceType() const { return SubserviceType; } + CSSM_VERSION version() const { return Version; } +}; + + +// +// User-friendler CSSM_CRYPTO_DATA objects +// +class CryptoCallback { +public: + CryptoCallback(CSSM_CALLBACK func, void *ctx = NULL) : mFunction(func), mCtx(ctx) { } + CSSM_CALLBACK function() const { return mFunction; } + void *context() const { return mCtx; } + + CssmData operator () () const + { + CssmData output; + if (CSSM_RETURN err = mFunction(&output, mCtx)) + CssmError::throwMe(err); + return output; + } + +private: + CSSM_CALLBACK mFunction; + void *mCtx; +}; + +class CssmCryptoData : public PodWrapper { +public: + CssmCryptoData() { } + + CssmCryptoData(const CssmData ¶m, CSSM_CALLBACK callback = NULL, void *ctx = NULL) + { Param = const_cast(param); Callback = callback; CallerCtx = ctx; } + + CssmCryptoData(const CssmData ¶m, CryptoCallback &cb) + { Param = const_cast(param); Callback = cb.function(); CallerCtx = cb.context(); } + + CssmCryptoData(CSSM_CALLBACK callback, void *ctx = NULL) + { /* ignore Param */ Callback = callback; CallerCtx = ctx; } + + explicit CssmCryptoData(CryptoCallback &cb) + { /* ignore Param */ Callback = cb.function(); CallerCtx = cb.context(); } + + // member access + CssmData ¶m() { return CssmData::overlay(Param); } + const CssmData ¶m() const { return CssmData::overlay(Param); } + bool hasCallback() const { return Callback != NULL; } + CryptoCallback callback() const { return CryptoCallback(Callback, CallerCtx); } + + // get the value, whichever way is appropriate + CssmData operator () () const + { return hasCallback() ? callback() () : param(); } +}; + +// a CssmCryptoContext whose callback is a virtual class member +class CryptoDataClass : public CssmCryptoData { +public: + CryptoDataClass() : CssmCryptoData(callbackShim, this) { } + virtual ~CryptoDataClass(); + +protected: + virtual CssmData yield() = 0; // must subclass and implement this + +private: + static CSSM_RETURN callbackShim(CSSM_DATA *output, void *ctx); +}; + + +// +// Other PodWrappers for stuff that is barely useful... +// +class CssmKeySize : public PodWrapper { +public: + CssmKeySize() { } + CssmKeySize(uint32 nom, uint32 eff) { LogicalKeySizeInBits = nom; EffectiveKeySizeInBits = eff; } + CssmKeySize(uint32 size) { LogicalKeySizeInBits = EffectiveKeySizeInBits = size; } + + uint32 logical() const { return LogicalKeySizeInBits; } + uint32 effective() const { return EffectiveKeySizeInBits; } + operator uint32 () const { return effective(); } +}; + +inline bool operator == (const CSSM_KEY_SIZE &s1, const CSSM_KEY_SIZE &s2) +{ + return s1.LogicalKeySizeInBits == s2.LogicalKeySizeInBits + && s1.EffectiveKeySizeInBits == s2.EffectiveKeySizeInBits; +} + +inline bool operator != (const CSSM_KEY_SIZE &s1, const CSSM_KEY_SIZE &s2) +{ return !(s1 == s2); } + + +class QuerySizeData : public PodWrapper { +public: + QuerySizeData() { } + QuerySizeData(uint32 in) { SizeInputBlock = in; SizeOutputBlock = 0; } + + uint32 inputSize() const { return SizeInputBlock; } + uint32 inputSize(uint32 size) { return SizeInputBlock = size; } + uint32 outputSize() const { return SizeOutputBlock; } +}; + +inline bool operator == (const CSSM_QUERY_SIZE_DATA &s1, const CSSM_QUERY_SIZE_DATA &s2) +{ + return s1.SizeInputBlock == s2.SizeInputBlock + && s1.SizeOutputBlock == s2.SizeOutputBlock; +} + +inline bool operator != (const CSSM_QUERY_SIZE_DATA &s1, const CSSM_QUERY_SIZE_DATA &s2) +{ return !(s1 == s2); } + + +class CSPOperationalStatistics : + public PodWrapper { +public: +}; + + +} // end namespace Security + + +#endif //_H_CSSMPODS diff --git a/libsecurity_cdsa_utilities/lib/cssmtrust.cpp b/libsecurity_cdsa_utilities/lib/cssmtrust.cpp new file mode 100644 index 00000000..cb20471d --- /dev/null +++ b/libsecurity_cdsa_utilities/lib/cssmtrust.cpp @@ -0,0 +1,48 @@ +/* + * 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@ + */ + + +// +// cssmtrust - CSSM layer Trust (TP) related objects. +// +#include +#include + + +namespace Security { + + +// +// Cleanly release the memory in a TPEvidenceInfo +// +void TPEvidenceInfo::destroy(Allocator &allocator) +{ + // status code array + if (codes() > 0 && StatusCodes) + allocator.free(StatusCodes); + + //@@@ need to free unique id if present +} + + +} // end namespace Security diff --git a/libsecurity_cdsa_utilities/lib/cssmtrust.h b/libsecurity_cdsa_utilities/lib/cssmtrust.h new file mode 100644 index 00000000..a24138a6 --- /dev/null +++ b/libsecurity_cdsa_utilities/lib/cssmtrust.h @@ -0,0 +1,178 @@ +/* + * 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@ + */ + + +// +// cssmtrust - CSSM layer Trust (TP) related objects. +// +#ifndef _H_CSSMTRUST +#define _H_CSSMTRUST + +#include +#include +#include +#include + + +namespace Security { + + +// +// A TP "POLICYINFO" structure, essentially an OID/Data pair. +// +class PolicyInfo : public PodWrapper { +public: + uint32 count() const { return NumberOfPolicyIds; } + uint32 &count() { return NumberOfPolicyIds; } + CssmField *policies() const { return CssmField::overlay(PolicyIds); } + CssmField * &policies() { return CssmField::overlayVar(PolicyIds); } + void *control() const { return PolicyControl; } + + CssmField &operator [] (uint32 ix) + { assert(ix < count()); return policies()[ix]; } + + void setPolicies(uint32 n, CSSM_FIELD *p) + { count() = n; policies() = CssmField::overlay(p); } +}; + + +// +// TP caller authentication contexts +// +class TPCallerAuth : public PodWrapper { +public: + CSSM_TP_STOP_ON stopCriterion() const { return VerificationAbortOn; } + void stopCriterion(CSSM_TP_STOP_ON stop) { VerificationAbortOn = stop; } + + CSSM_TIMESTRING time() const { return VerifyTime; } + void time(CSSM_TIMESTRING newTime) { VerifyTime = newTime; } + + PolicyInfo &policies() { return PolicyInfo::overlay(Policy); } + const PolicyInfo &policies() const { return PolicyInfo::overlay(Policy); } + void setPolicies(uint32 n, CSSM_FIELD *p) { policies().setPolicies(n, p); } + + AccessCredentials *creds() const + { return AccessCredentials::optional(CallerCredentials); } + void creds(AccessCredentials *newCreds) { CallerCredentials = newCreds; } + + uint32 anchorCount() const { return NumberOfAnchorCerts; } + uint32 &anchorCount() { return NumberOfAnchorCerts; } + CssmData *anchors() const { return CssmData::overlay(AnchorCerts); } + CssmData * &anchors() { return CssmData::overlayVar(AnchorCerts); } + + CssmDlDbList *dlDbList() const { return CssmDlDbList::overlay(DBList); } + CssmDlDbList * &dlDbList() { return CssmDlDbList::overlayVar(DBList); } +}; + + +// +// TP Verify Contexts - a monster collection of possibly useful stuff +// when verifying a certificate against trust policies +// +class TPVerifyContext : public PodWrapper { +public: + CSSM_TP_ACTION action() const { return Action; } + CssmData &actionData() { return CssmData::overlay(ActionData); } + const CssmData &actionData() const { return CssmData::overlay(ActionData); } + + // set and reference the CallerAuth component + TPCallerAuth &callerAuth() const { return TPCallerAuth::required(Cred); } + operator TPCallerAuth &() const { return callerAuth(); } + TPCallerAuth *callerAuthPtr() const { return TPCallerAuth::optional(Cred); } + void callerAuthPtr(CSSM_TP_CALLERAUTH_CONTEXT *p) { Cred = p; } + + // forward CallerAuth operations + + CSSM_TP_STOP_ON stopCriterion() const { return callerAuth().stopCriterion(); } + void stopCriterion(CSSM_TP_STOP_ON stop) { return callerAuth().stopCriterion(stop); } + PolicyInfo &policies() const { return callerAuth().policies(); } + void setPolicies(uint32 n, CSSM_FIELD *p) { policies().setPolicies(n, p); } + CSSM_TIMESTRING time() const { return callerAuth().time(); } + void time(CSSM_TIMESTRING newTime) { return callerAuth().time(newTime); } + AccessCredentials *creds() const { return callerAuth().creds(); } + void creds(AccessCredentials *newCreds) const { return callerAuth().creds(newCreds); } + uint32 anchorCount() const { return callerAuth().anchorCount(); } + uint32 &anchorCount() { return callerAuth().anchorCount(); } + CssmData *anchors() const { return callerAuth().anchors(); } + CssmData * &anchors() { return callerAuth().anchors(); } + void anchors(uint32 count, CSSM_DATA *vector) + { anchorCount() = count; anchors() = CssmData::overlay(vector); } + void setDlDbList(uint32 n, CSSM_DL_DB_HANDLE *list) + { callerAuth().dlDbList()->setDlDbList(n, list); } +}; + + +// +// The result of a (raw) TP trust verification call +// +class TPEvidence : public PodWrapper { +public: + CSSM_EVIDENCE_FORM form() const { return EvidenceForm; } + void *data() const { return Evidence; } + operator void *() const { return data(); } + + template + T *as() const { return reinterpret_cast(Evidence); } +}; + +class TPVerifyResult : public PodWrapper { +public: + uint32 count() const { return NumberOfEvidences; } + const TPEvidence &operator [] (uint32 ix) const + { assert(ix < count()); return TPEvidence::overlay(Evidence[ix]); } +}; + + +// +// A PodWrapper for Apple's TP supporting-evidence structure +// +class TPEvidenceInfo : public PodWrapper { +public: + CSSM_TP_APPLE_CERT_STATUS status() const { return StatusBits; } + CSSM_TP_APPLE_CERT_STATUS status(CSSM_TP_APPLE_CERT_STATUS flags) const + { return status() & flags; } + + uint32 index() const { return Index; } + const CssmDlDbHandle &dldb() const { return CssmDlDbHandle::overlay(DlDbHandle); } + CSSM_DB_UNIQUE_RECORD_PTR recordId() const { return UniqueRecord; } + + uint32 codes() const { return NumStatusCodes; } + CSSM_RETURN operator [] (uint32 ix) + { assert(ix < NumStatusCodes); return StatusCodes[ix]; } + + void destroy(Allocator &allocator); +}; + + +// +// Walkers +// +namespace DataWalkers { + + + + +} // end namespace DataWalkers +} // end namespace Security + +#endif //_H_CSSMTRUST diff --git a/libsecurity_cdsa_utilities/lib/cssmwalkers.cpp b/libsecurity_cdsa_utilities/lib/cssmwalkers.cpp new file mode 100644 index 00000000..eb812a2b --- /dev/null +++ b/libsecurity_cdsa_utilities/lib/cssmwalkers.cpp @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2000-2001,2003-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@ + */ + + +// +// cssmwalkers - walkers for standard CSSM datatypes and wrappers +// +#include diff --git a/libsecurity_cdsa_utilities/lib/cssmwalkers.h b/libsecurity_cdsa_utilities/lib/cssmwalkers.h new file mode 100644 index 00000000..cb103439 --- /dev/null +++ b/libsecurity_cdsa_utilities/lib/cssmwalkers.h @@ -0,0 +1,233 @@ +/* + * 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@ + */ + + +// +// cssmwalkers - walkers for standard CSSM datatypes and wrappers +// +#ifndef _H_CSSMWALKERS +#define _H_CSSMWALKERS + +#include +#include +#include +#include + + + +namespace Security { +namespace DataWalkers { + + +// +// There are lots of CSSM data structures that are variable-length records +// of the form { count, pointer-to-array }. If you have a regular PodWrapper +// for it, we can enumerate the array for you right here. Minimum requirement: +// size_t size() const; +// Element &operator [] (uint32 index); +// // and some Element *&foo() that returns a reference-to-array-pointer +// and a reference walker for the element type (as returned by operator []). +// +template +void enumerateArray(Action &operate, Record &record, Element *& (Record::*pointer)()) +{ + if (record.size()) { + Element *&root = (record.*pointer)(); + operate.blob(root, record.size() * sizeof(Element)); + for (uint32 ix = 0; ix < record.size(); ++ix) + walk(operate, record[ix]); + } +} + + +// +// The full set of walkers for CssmData in all its forms. +// +template +void walk(Action &operate, CssmData &data) +{ + operate(data); + operate.blob(data.Data, data.Length); +} + +template +CssmData *walk(Action &operate, CssmData * &data) +{ + operate(data); + operate.blob(data->Data, data->Length); + return data; +} + +template +void walk(Action &operate, CSSM_DATA &data) +{ walk(operate, CssmData::overlay(data)); } + +template +CSSM_DATA *walk(Action &operate, CSSM_DATA * &data) +{ return walk(operate, CssmData::overlayVar(data)); } + + + +// +// Walking a C string is almost regular (the size comes from strlen()). +// Just make sure you honor the needsSize preference of the operator. +// +template +char *walk(Action &operate, char * &s) +{ + if (s) + operate(s, operate.needsSize ? (strlen(s) + 1) : 0); + return s; +} + + +// +// Flattener functions for common CSSM data types that have internal structure. +// +template +CssmKey *walk(Action &operate, CssmKey * &key) +{ + operate(key); + walk(operate, key->keyData()); + return key; +} + +template +CSSM_KEY *walk(Action &operate, CSSM_KEY * &data) +{ return walk(operate, CssmKey::overlayVar(data)); } + +template +CssmCryptoData *walk(Action &operate, CssmCryptoData * &data) +{ + operate(data); + walk(operate, data->param()); + return data; +} + +template +CSSM_CRYPTO_DATA *walk(Action &operate, CSSM_CRYPTO_DATA * &data) +{ return walk(operate, CssmCryptoData::overlayVar(data)); } + +template +void walk(Action &operate, CSSM_PKCS5_PBKDF2_PARAMS &data) +{ + operate(data); + walk(operate, data.Passphrase); +} + +// +// Walkers for flat datatypes +// +template +CSSM_DATE_PTR walk(Action &operate, CSSM_DATE_PTR &date) +{ + operate(date); + return date; +} + +template +CSSM_RANGE_PTR walk(Action &operate, CSSM_RANGE_PTR &range) +{ + operate(range); + return range; +} + +template +CSSM_VERSION_PTR walk(Action &operate, CSSM_VERSION_PTR &version) +{ + operate(version); + return version; +} + +template +CSSM_DL_DB_HANDLE_PTR walk(Action &operate, CSSM_DL_DB_HANDLE_PTR &dlDbHandle) +{ + operate(dlDbHandle); + return dlDbHandle; +} + +template +CssmSubserviceUid *walk(Action &operate, CssmSubserviceUid * &ssUid) +{ + operate(ssUid); + return ssUid; +} + + +// +// A synthetic variant of CssmData to model key derivation (input) parameters, +// which have algorithm dependent structure. This is not likely to be useful +// for anything else; but here's the common ancestor of all its users. +// +class CssmDeriveData { +public: + CssmDeriveData(const CssmData &dat, CSSM_ALGORITHMS alg) + : baseData(dat), algorithm(alg) { } + + CssmData baseData; + CSSM_ALGORITHMS algorithm; + + template + void enumerate(Action &operate) + { + walk(operate, baseData); + switch (algorithm) { + case CSSM_ALGID_PKCS5_PBKDF2: +#if BUG_3762664 + walk(operate, *baseData.interpretedAs + (CSSMERR_CSP_INVALID_ATTR_ALG_PARAMS)); +#else + if (baseData.length() != sizeof(CSSM_PKCS5_PBKDF2_PARAMS)) + CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_ALG_PARAMS); + walk(operate, *(CSSM_PKCS5_PBKDF2_PARAMS *)baseData.data()); +#endif + break; + default: + break; + } + } +}; + + +template +void walk(Action &operate, CssmDeriveData &data) +{ + operate(data); + data.enumerate(operate); +} + +template +CssmDeriveData *walk(Action &operate, CssmDeriveData * &data) +{ + operate(data); + if (data) + data->enumerate(operate); + return data; +} + + + +} // end namespace DataWalkers +} // end namespace Security + +#endif //_H_CSSMWALKERS diff --git a/libsecurity_cdsa_utilities/lib/db++.cpp b/libsecurity_cdsa_utilities/lib/db++.cpp new file mode 100644 index 00000000..2f64123c --- /dev/null +++ b/libsecurity_cdsa_utilities/lib/db++.cpp @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2003-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@ + */ + + +// +// dbm++ - generic C++ layer interface to [n]dbm +// +#include "db++.h" +#include + + +namespace Security { +namespace UnixPlusPlus { + +UnixDb::UnixDb() : mDb(NULL) +{ +} + +UnixDb::UnixDb(const char *path, int flags, int mode, DBTYPE type) : mDb(NULL) +{ + open(path, flags, mode); +} + +UnixDb::UnixDb(const std::string &path, int flags, int mode, DBTYPE type) : mDb(NULL) +{ + open(path, flags, mode); +} + +UnixDb::~UnixDb() +{ + close(); +} + +void UnixDb::open(const char *path, int flags, int mode, DBTYPE type) +{ + if (DB* newDb = ::dbopen(path, flags, mode, type, NULL)) { + close(); + mDb = newDb; + setFd(mDb->fd(mDb)); + secdebug("unixdb", "open(%s,0x%x,0x%x,type=%d)=%p", path, flags, mode, type, mDb); + } else + UnixError::throwMe(); +} + +void UnixDb::open(const std::string &path, int flags, int mode, DBTYPE type) +{ + open(path.c_str(), flags, mode); +} + +void UnixDb::close() +{ + if (mDb) { + secdebug("unixdb", "close(%p)", mDb); + mDb->close(mDb); + mDb = NULL; + setFd(invalidFd); + } +} + +bool UnixDb::get(const CssmData &key, CssmData &value, int flags) const +{ + Data dKey(key); + Data val; + int rc = mDb->get(mDb, &dKey, &val, flags); + secdebug("unixdb", "get(%p,[:%ld],flags=0x%x)=%d[:%ld]", + mDb, key.length(), flags, rc, value.length()); + checkError(rc); + if (!rc) { + value = val; + return true; + } else + return false; +} + +bool UnixDb::get(const CssmData &key, CssmOwnedData &value, int flags) const +{ + CssmData val; + if (get(key, val, flags)) { + value = val; + return true; + } else + return false; +} + +bool UnixDb::put(const CssmData &key, const CssmData &value, int flags) +{ + Data dKey(key); + Data dValue(value); + int rc = mDb->put(mDb, &dKey, &dValue, flags); + secdebug("unixdb", "put(%p,[:%ld],[:%ld],flags=0x%x)=%d", + mDb, key.length(), value.length(), flags, rc); + checkError(rc); + return !rc; +} + +void UnixDb::erase(const CssmData &key, int flags) +{ + Data dKey(key); + secdebug("unixdb", "delete(%p,[:%ld],flags=0x%x)", mDb, key.length(), flags); + checkError(mDb->del(mDb, &dKey, flags)); +} + +bool UnixDb::next(CssmData &key, CssmData &value, int flags /* = R_NEXT */) const +{ + Data dKey, dValue; + int rc = mDb->seq(mDb, &dKey, &dValue, flags); + checkError(rc); + if (!rc) { + key = dKey; + value = dValue; + return true; + } else + return false; +} + + +void UnixDb::flush(int flags) +{ + checkError(mDb->sync(mDb, flags)); +} + + +} // end namespace UnixPlusPlus +} // end namespace Security diff --git a/libsecurity_cdsa_utilities/lib/db++.h b/libsecurity_cdsa_utilities/lib/db++.h new file mode 100644 index 00000000..d947e466 --- /dev/null +++ b/libsecurity_cdsa_utilities/lib/db++.h @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2003-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@ + */ + + +// +// dbm++ - generic C++ layer interface to [n]dbm +// +#ifndef _H_DBMPP +#define _H_DBMPP + +#include +#include +#include +#include +#include + + +namespace Security { +namespace UnixPlusPlus { + + +class UnixDb : public FileDesc { +public: + UnixDb(); + UnixDb(const char *path, int flags = O_RDWR, int mode = 0666, DBTYPE type = DB_HASH); + UnixDb(const std::string &path, int flags = O_RDWR, int mode = 0666, DBTYPE type = DB_HASH); + + virtual ~UnixDb(); + + void open(const char *path, int flags = O_RDWR, int mode = 0666, DBTYPE type = DB_HASH); + void open(const std::string &path, int flags = O_RDWR, int mode = 0666, DBTYPE type = DB_HASH); + void close(); + + bool get(const CssmData &key, CssmData &value, int flags = 0) const; + bool get(const CssmData &key, CssmOwnedData &value, int flags = 0) const; + bool put(const CssmData &key, const CssmData &value, int flags = 0); + void erase(const CssmData &key, int flags = 0); + void flush(int flags = 0); + + bool next(CssmData &key, CssmData &value, int flags = R_NEXT) const; + bool first(CssmData &key, CssmData &value) const + { return next(key, value, R_FIRST); } + + operator bool () const + { return mDb; } + +public: + struct Data : public PodWrapper { + template + Data(const T &src) { DBT::data = src.data(); DBT::size = src.length(); } + + Data() { } + Data(void *data, size_t length) { DBT::data = data; DBT::size = length; } + Data(const DBT &dat) { DBT::data = dat.data; DBT::size = dat.size; } + + void *data() const { return DBT::data; } + size_t length() const { return size; } + operator bool () const { return DBT::data != NULL; } + operator CssmData () const { return CssmData(data(), length()); } + }; + +private: + DB *mDb; +}; + + +} // end namespace UnixPlusPlus +} // end namespace Security + + +#endif //_H_DBMPP diff --git a/libsecurity_cdsa_utilities/lib/digestobject.h b/libsecurity_cdsa_utilities/lib/digestobject.h new file mode 100644 index 00000000..8faad537 --- /dev/null +++ b/libsecurity_cdsa_utilities/lib/digestobject.h @@ -0,0 +1,134 @@ +/* + * 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@ + */ + + +/* + * digestobject.h - generic virtual Digest base class + */ + +#ifndef _DIGEST_OBJECT_H_ +#define _DIGEST_OBJECT_H_ + +#include +#include + +/* common virtual digest class */ +class DigestObject { +public: + DigestObject() : mInitFlag(false), mIsDone(false) { } + virtual ~DigestObject() { } + + /* + * The remaining functions must be implemented by subclass. + */ + /* init is reusable */ + virtual void digestInit() = 0; + + /* add some data */ + virtual void digestUpdate( + const void *data, + size_t len) = 0; + + /* obtain digest (once only per init, update, ... cycle) */ + virtual void digestFinal( + void *digest) = 0; /* RETURNED, alloc'd by caller */ + + /* sublass-specific copy */ + virtual DigestObject *digestClone() const = 0; + + virtual size_t digestSizeInBytes() const = 0; + +protected: + bool mInitFlag; + bool mIsDone; + + bool initFlag() { return mInitFlag; } + void setInitFlag(bool flag) { mInitFlag = flag; } + bool isDone() { return mIsDone; } + void setIsDone(bool done) { mIsDone = done; } +}; + +/* + * NullDigest.h - nop digest for use with raw signature algorithms. + * NullDigest(someData) = someData. + */ +class NullDigest : public DigestObject +{ +public: + NullDigest() : mInBuf(NULL), mInBufSize(0) + { + } + + void digestInit() + { + /* reusable - reset */ + if(mInBufSize) { + assert(mInBuf != NULL); + memset(mInBuf, 0, mInBufSize); + Allocator::standard().free(mInBuf); + mInBufSize = 0; + mInBuf = NULL; + } + } + + ~NullDigest() + { + digestInit(); + } + + void digestUpdate( + const void *data, + size_t len) + { + mInBuf = Allocator::standard().realloc(mInBuf, mInBufSize + len); + memmove((uint8 *)mInBuf + mInBufSize, data, len); + mInBufSize += len; + } + + virtual void digestFinal( + void *digest) + { + memmove(digest, mInBuf, mInBufSize); + } + + virtual DigestObject *digestClone() const + { + NullDigest *cloned = new NullDigest; + cloned->digestUpdate(mInBuf, mInBufSize); + return cloned; + } + + /* unique to NullDigest - just obtain current data ptr, no copy */ + virtual const void *digestPtr() { return mInBuf; } + + size_t digestSizeInBytes() const + { + return mInBufSize; + } + +private: + void *mInBuf; + size_t mInBufSize; +}; + +#endif /* _DIGEST_OBJECT_H_ */ diff --git a/libsecurity_cdsa_utilities/lib/generator.mk b/libsecurity_cdsa_utilities/lib/generator.mk new file mode 100644 index 00000000..2e701383 --- /dev/null +++ b/libsecurity_cdsa_utilities/lib/generator.mk @@ -0,0 +1,26 @@ +# Makefile for generated files. + +PERL=/usr/bin/perl + +CDSA_HEADERS_DIR = Headers/cdsa +CDSA_UTILITIES_DIR = Sources/cdsa_utilities + +GEN_ERRORCODES = $(CDSA_UTILITIES_DIR)/generator.pl +ERRORCODES_GEN = $(patsubst %,$(CDSA_UTILITIES_DIR)/%,errorcodes.gen) +ERRORCODES_DEPENDS = $(GEN_ERRORCODES)\ + $(patsubst %,$(CDSA_HEADERS_DIR)/%,cssmerr.h) + +build: $(ERRORCODES_GEN) + +clean: + rm -f $(ERRORCODES_GEN) + +debug: build + +profile: build + +.PHONY: build clean debug profile + +$(ERRORCODES_GEN): $(ERRORCODE_DEPENDS) + (cd $(CDSA_UTILITIES_DIR);\ + $(PERL) ./generator.pl ../../$(CDSA_HEADERS_DIR) .) diff --git a/libsecurity_cdsa_utilities/lib/generator.pl b/libsecurity_cdsa_utilities/lib/generator.pl new file mode 100644 index 00000000..1b3fd9ad --- /dev/null +++ b/libsecurity_cdsa_utilities/lib/generator.pl @@ -0,0 +1,89 @@ +#!/usr/bin/perl +# +# generator.pl - derive various and sundry C++ code from the CDSA header files +# +# Usage: +# perl generator.pl input-directory output-directory +# +# Perry The Cynic, Fall 1999. +# +$ERR_H="cssmerr.h"; +$APPLE_ERR_H="cssmapple.h"; + +$SOURCEDIR=$ARGV[0]; # directory with cdsa headers +$TARGETDIR=$ARGV[1]; # where to put the output file +@INPUTFILES=@ARGV[2 .. 9999]; # list of input files + +$TABLES="$TARGETDIR/errorcodes.gen"; # error name tables + +$tabs = "\t\t\t"; # argument indentation (noncritical) +$warning = "This file was automatically generated. Do not edit on penalty of futility!"; + + +# +# Parse CSSM error header and build table of all named codes +# +open(ERR, "$SOURCEDIR/$ERR_H") or die "Cannot open $ERR_H: $^E"; +open(APPLE_ERR, "$SOURCEDIR/$APPLE_ERR_H") or die "Cannot open $APPLE_ERR_H: $^E"; +$/=undef; # big gulp mode +$errors = . ; +close(ERR); close(APPLE_ERR); + +@fullErrors = $errors =~ /^\s+CSSMERR_([A-Z_]+)/gm; +@convertibles = $errors =~ /^\s+CSSM_ERRCODE_([A-Z_]+)\s*=\s*([0-9xXA-Fa-f]+)/gm; + +while ($name = shift @convertibles) { + $value = shift @convertibles or die; + $convErrors[hex $value] = $name; +}; + + +# +# Read Keychain-level headers for more error codes (errSecBlahBlah) +# +open(ERR, "cat " . join(" ", @INPUTFILES) . "|") or die "Cannot open error header files"; +$/=undef; # still gulping +$_ = ; +@kcerrors = /err((?:Sec|Authorization)\w+)\s*=\s*-?\d+/gm; +close(ERR); + + +# +# Now we will generate the error name tables. +# +open(OUT, ">$TABLES") or die "Cannot write $TABLES: $^E"; +select OUT; + +print < +#include + diff --git a/libsecurity_cdsa_utilities/lib/handleobject.h b/libsecurity_cdsa_utilities/lib/handleobject.h new file mode 100644 index 00000000..80fbae33 --- /dev/null +++ b/libsecurity_cdsa_utilities/lib/handleobject.h @@ -0,0 +1,47 @@ +/* + * 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@ + */ + + +// +// handleobject - give an object a process-global unique handle +// +#ifndef _H_HANDLEOBJECT +#define _H_HANDLEOBJECT + +#include +#include + +// +// definitions kept here so other code doesn't have to modify #includes +// + +namespace Security +{ + +typedef TypedHandle HandledObject; + +typedef MappingHandle HandleObject; + +} // end namespace Security + +#endif //_H_HANDLEOBJECT diff --git a/libsecurity_cdsa_utilities/lib/handletemplates.cpp b/libsecurity_cdsa_utilities/lib/handletemplates.cpp new file mode 100644 index 00000000..db747003 --- /dev/null +++ b/libsecurity_cdsa_utilities/lib/handletemplates.cpp @@ -0,0 +1,39 @@ +/* + * Copyright (c) 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 + +// +// Instantiate the explicit MappingHandle subclasses. If there start to be +// a lot of these, break this into multiple .cpp files so useless classes +// aren't linked in everywhere. +// + +template class TypedHandle; // HandledObject + +template class MappingHandle; // HandleObject + +template class MappingHandle; // U32HandleObject diff --git a/libsecurity_cdsa_utilities/lib/handletemplates.h b/libsecurity_cdsa_utilities/lib/handletemplates.h new file mode 100644 index 00000000..6644e2fd --- /dev/null +++ b/libsecurity_cdsa_utilities/lib/handletemplates.h @@ -0,0 +1,294 @@ +/* + * Copyright (c) 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@ + */ + + +// +// Templates to support HandleObject-like objects +// +#ifndef _H_HANDLETEMPLATES +#define _H_HANDLETEMPLATES + +#include +#include +#include +#include + +#if __GNUC__ > 2 +#include +using __gnu_cxx::hash_map; +#else +#include +#endif + +namespace Security +{ + +// +// A TypedHandle is a trivial mixin class whose only feature is that +// it has a *handle* whose type is of the caller's choosing. Subclasses +// need to assign such a handle during creation. +// +template +struct TypedHandle +{ +public: + typedef _Handle Handle; + + static const _Handle invalidHandle = 0; + + _Handle handle() const { return mMyHandle; } + bool validHandle() const { return mValid; } + +protected: + TypedHandle(_Handle h); + TypedHandle(); + + void setHandle(_Handle h) + { + assert(!mValid); // guard against redefinition + mMyHandle = h; + mValid = true; + } + void clearHandle() + { + assert(mValid); + mValid = false; + } + +private: + _Handle mMyHandle; // our handle value + bool mValid; // is the handle (still) valid? +}; + +// +// MappingHandle wraps a map indexed by handles of the chosen type. +// A MappingHandle makes up its own handle based on some mechanism that you +// know nothing about. +// +// Please be very careful about the limits of the object contract here. +// We promise to invent a suitable, unique handle for each MappingHandle in +// existence within one address space. We promise that if you hand that +// handle to the various MappingHandle<>::find() variants, we will give you +// back the MappingHandle that created it. We promise to throw if you pass +// a bad handle to those MappingHandle<>::find() variants. This is the +// entire contract. +// +template +class MappingHandle : public TypedHandle<_Handle> +{ +protected: + class State; + +public: + typedef typename TypedHandle<_Handle>::Handle Handle; + virtual ~MappingHandle() + { + State &st = state(); + StLock _(st); + st.erase(this); + } + + template + static SubType &find(_Handle handle, CSSM_RETURN error); + + template + static Subtype &findAndLock(_Handle handle, CSSM_RETURN error); + + template + static Subtype &findAndKill(_Handle handle, CSSM_RETURN error); + + template + static RefPointer findRef(_Handle handle, CSSM_RETURN error); + + template + static RefPointer findRefAndLock(_Handle handle, CSSM_RETURN error); + + template + static RefPointer findRefAndKill(_Handle handle, CSSM_RETURN error); + + // @@@ Remove when 4003540 is fixed + template + static void findAllRefs(std::vector<_Handle> &refs) { + state().findAllRefs(refs); + } + +protected: + virtual void lock(); + virtual bool tryLock(); + + typedef hash_map<_Handle, MappingHandle<_Handle> *> HandleMap; + + MappingHandle(); + + class State : public Mutex, public HandleMap + { + public: + State(); + uint32_t nextSeq() { return ++sequence; } + + bool handleInUse(_Handle h); + MappingHandle<_Handle> *find(_Handle h, CSSM_RETURN error); + typename HandleMap::iterator locate(_Handle h, CSSM_RETURN error); + void add(_Handle h, MappingHandle<_Handle> *obj); + void erase(MappingHandle<_Handle> *obj); + void erase(typename HandleMap::iterator &it); + // @@@ Remove when 4003540 is fixed + template void findAllRefs(std::vector<_Handle> &refs); + + private: + uint32_t sequence; + }; + +private: + // + // Create the handle to be used by the map + // + void make(); + + static ModuleNexus::State> state; +}; + +// +// MappingHandle class methods +// Type-specific ways to access the map in various ways +// +template +template +inline Subclass &MappingHandle<_Handle>::find(_Handle handle, CSSM_RETURN error) +{ + Subclass *sub; + if (!(sub = dynamic_cast(state().find(handle, error)))) + CssmError::throwMe(error); + return *sub; +} + +template +template +inline Subclass &MappingHandle<_Handle>::findAndLock(_Handle handle, + CSSM_RETURN error) +{ + for (;;) { + typename HandleMap::iterator it = state().locate(handle, error); + StLock _(state(), true); // locate() locked it + Subclass *sub; + if (!(sub = dynamic_cast(it->second))) + CssmError::throwMe(error); // bad type + if (it->second->tryLock()) // try to lock it + return *sub; // okay, go + Thread::yield(); // object lock failed, backoff and retry + } +} + +template +template +inline Subclass &MappingHandle<_Handle>::findAndKill(_Handle handle, + CSSM_RETURN error) +{ + for (;;) { + typename HandleMap::iterator it = state().locate(handle, error); + StLock _(state(), true); // locate() locked it + Subclass *sub; + if (!(sub = dynamic_cast(it->second))) + CssmError::throwMe(error); // bad type + if (it->second->tryLock()) { // try to lock it + state().erase(it); // kill the handle + return *sub; // okay, go + } + Thread::yield(); // object lock failed, backoff and retry + } +} + +template +template +inline RefPointer MappingHandle<_Handle>::findRef(_Handle handle, + CSSM_RETURN error) +{ + typename HandleMap::iterator it = state().locate(handle, error); + StLock _(state(), true); // locate() locked it + Subclass *sub; + if (!(sub = dynamic_cast(it->second))) + CssmError::throwMe(error); + return sub; +} + +template +template +inline RefPointer MappingHandle<_Handle>::findRefAndLock(_Handle handle, + CSSM_RETURN error) +{ + for (;;) { + typename HandleMap::iterator it = state().locate(handle, error); + StLock _(state(), true); // locate() locked it + Subclass *sub; + if (!(sub = dynamic_cast(it->second))) + CssmError::throwMe(error); // bad type + if (it->second->tryLock()) // try to lock it + return sub; // okay, go + Thread::yield(); // object lock failed, backoff and retry + } +} + +template +template +inline RefPointer MappingHandle<_Handle>::findRefAndKill(_Handle handle, + CSSM_RETURN error) +{ + for (;;) { + typename HandleMap::iterator it = state().locate(handle, error); + StLock _(state(), true); // locate() locked it + Subclass *sub; + if (!(sub = dynamic_cast(it->second))) + CssmError::throwMe(error); // bad type + if (it->second->tryLock()) { // try to lock it + state().erase(it); // kill the handle + return sub; // okay, go + } + Thread::yield(); // object lock failed, backoff and retry + } +} + +// +// @@@ Remove when 4003540 is fixed +// +// This is a hack to fix 3981388 and should NOT be used elsewhere. +// Also, do not follow this code's example: State methods should not +// implement type-specific behavior. +// +template +template +void MappingHandle<_Handle>::State::findAllRefs(std::vector<_Handle> &refs) +{ + StLock _(*this); + typename HandleMap::iterator it = (*this).begin(); + for (; it != (*this).end(); ++it) + { + Subtype *obj = dynamic_cast(it->second); + if (obj) + refs.push_back(it->first); + } +} + + +} // end namespace Security + +#endif //_H_HANDLETEMPLATES diff --git a/libsecurity_cdsa_utilities/lib/handletemplates_defs.h b/libsecurity_cdsa_utilities/lib/handletemplates_defs.h new file mode 100644 index 00000000..5a6c7597 --- /dev/null +++ b/libsecurity_cdsa_utilities/lib/handletemplates_defs.h @@ -0,0 +1,204 @@ +/* + * Copyright (c) 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@ + */ + + +// +// adjunct to handletemplates.h +// +// this header should only be #included by source files defining +// TypedHandle or MappingHandle subclasses +// +// @@@ Should use non-CSSM error codes +// +#ifndef _H_HANDLETEMPLATES_DEFS +#define _H_HANDLETEMPLATES_DEFS + +#include +#include +#include +#include +#include +#include + +namespace Security +{ + +// +// TypedHandle +// +template +TypedHandle<_Handle>::TypedHandle() + : mMyHandle(invalidHandle), mValid(false) +{ +} + +template +TypedHandle<_Handle>::TypedHandle(_Handle h) + : mMyHandle(h), mValid(true) +{ +} + + +// +// MappingHandle instance methods +// +template +MappingHandle<_Handle>::MappingHandle() : TypedHandle<_Handle>() +{ + make(); +} + +template +void MappingHandle<_Handle>::make() +{ + StLock _(state()); + + _Handle hbase = reinterpret_cast(this); + for (;;) { + _Handle handle = hbase ^ state().nextSeq(); + if (!state().handleInUse(handle)) { + // assumes sizeof(unsigned long) >= sizeof(handle) + secdebug("handleobj", "create %#lx for %p", static_cast(handle), this); + TypedHandle<_Handle>::setHandle(handle); + state().add(handle, this); + return; + } + } +} + +// The default locking virtual methods do nothing and succeed. +template +void MappingHandle<_Handle>::lock() { } + +template +bool MappingHandle<_Handle>::tryLock() { return true; } + + +// +// MappingHandle::State +// + +// The default State constructor should not be inlined in a standard +// header: its use via ModuleNexus would result in the inlined code +// appearing *everywhere* the State object might have to be constructed. +template +MappingHandle<_Handle>::State::State() + : sequence(1) +{ +} + +// +// Check if the handle is already in the map. Caller must already hold +// the map lock. Intended for use by a subclass' implementation of +// MappingHandle<...>::make(). +// +template +bool MappingHandle<_Handle>::State::handleInUse(_Handle h) +{ + return (HandleMap::find(h) != (*this).end()); +} + +// +// Observing proper map locking, locate a handle in the global handle map +// and return a pointer to its object. Throw CssmError(error) if it cannot +// be found, or it is corrupt. +// +template +MappingHandle<_Handle> *MappingHandle<_Handle>::State::find(_Handle h, CSSM_RETURN error) +{ + StLock _(*this); + typename HandleMap::const_iterator it = HandleMap::find(h); + if (it == (*this).end()) + CssmError::throwMe(error); + MappingHandle<_Handle> *obj = it->second; + if (obj == NULL || obj->handle() != h) + CssmError::throwMe(error); + return obj; +} + +// +// Look up the handle given in the global handle map. +// If not found, or if the object is corrupt, throw an exception. +// Otherwise, hold the State lock and return an iterator to the map entry. +// Caller must release the State lock in a timely manner. +// +template +typename MappingHandle<_Handle>::HandleMap::iterator +MappingHandle<_Handle>::State::locate(_Handle h, CSSM_RETURN error) +{ + StLock locker(*this); + typename HandleMap::iterator it = HandleMap::find(h); + if (it == (*this).end()) + CssmError::throwMe(error); + MappingHandle<_Handle> *obj = it->second; + if (obj == NULL || obj->handle() != h) + CssmError::throwMe(error); + locker.release(); + return it; +} + +// +// Add a handle and its associated object to the map. Caller must already +// hold the map lock, and is responsible for collision-checking prior to +// calling this method. Intended for use by a subclass' implementation of +// MappingHandle<...>::make(). +// +template +void MappingHandle<_Handle>::State::add(_Handle h, MappingHandle<_Handle> *obj) +{ + (*this)[h] = obj; +} + +// +// Clean up the handle for an object that dies. Caller must already hold +// the map lock. +// Note that an object MAY clear its handle before (in which case we do nothing). +// In particular, killHandle will do this. +// +template +void MappingHandle<_Handle>::State::erase(MappingHandle<_Handle> *obj) +{ + if (obj->validHandle()) + HandleMap::erase(obj->handle()); +} + +template +void MappingHandle<_Handle>::State::erase(typename HandleMap::iterator &it) +{ + if (it->second->validHandle()) + HandleMap::erase(it); +} + + +// +// All explicit instantiations of MappingHandle subclasses get the +// generation of their 'state' member for free (if they #include this +// file). +// +template +ModuleNexus::State> MappingHandle<_Handle>::state; + + +} // end namespace Security + +#endif //_H_HANDLETEMPLATES_DEFS diff --git a/libsecurity_cdsa_utilities/lib/objectacl.cpp b/libsecurity_cdsa_utilities/lib/objectacl.cpp new file mode 100644 index 00000000..3fc1d6bd --- /dev/null +++ b/libsecurity_cdsa_utilities/lib/objectacl.cpp @@ -0,0 +1,660 @@ +/* + * 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@ + */ + + +// +// objectacl - core implementation of an ACL-bearing object +// +#include +#include +#include +#include +#include +#include + +#include //@@@ impure - will be removed + +using namespace DataWalkers; + + +// +// The static map of available ACL subject makers. +// These are the kinds of ACL subjects we can deal with. +// +ModuleNexus ObjectAcl::makers; + + +// +// Create an ObjectAcl +// +ObjectAcl::ObjectAcl(Allocator &alloc) : allocator(alloc), mNextHandle(1) +{ +} + +ObjectAcl::ObjectAcl(const AclEntryPrototype &proto, Allocator &alloc) + : allocator(alloc), mNextHandle(1) +{ + cssmSetInitial(proto); +} + +ObjectAcl::~ObjectAcl() +{ } + + +// +// Set an "initial ACL" from a CSSM-style initial ACL argument. +// This will replace the owner, as well as replace the entire ACL +// with a single-item slot, as per CSSM specification. +// +void ObjectAcl::cssmSetInitial(const AclEntryPrototype &proto) +{ + mOwner = OwnerEntry(proto); + add(proto.s_tag(), proto); + IFDUMPING("acl", debugDump("create/proto")); +} + +void ObjectAcl::cssmSetInitial(const AclSubjectPointer &subject) +{ + mOwner = OwnerEntry(subject); + add("", subject); + IFDUMPING("acl", debugDump("create/subject")); +} + +ObjectAcl::Entry::~Entry() +{ +} + + +// +// ObjectAcl::validate validates an access authorization claim. +// Returns normally if 'auth' is granted to the bearer of 'cred'. +// Otherwise, throws a suitable (ACL-related) CssmError exception. +// +class BaseValidationContext : public AclValidationContext { +public: + BaseValidationContext(const AccessCredentials *cred, + AclAuthorization auth, AclValidationEnvironment *env) + : AclValidationContext(cred, auth, env) { } + + uint32 count() const { return cred() ? cred()->samples().length() : 0; } + uint32 size() const { return count(); } + const TypedList &sample(uint32 n) const + { assert(n < count()); return cred()->samples()[n]; } + + void matched(const TypedList *) const { } // ignore match info +}; + + +bool ObjectAcl::validates(AclAuthorization auth, const AccessCredentials *cred, + AclValidationEnvironment *env) +{ + BaseValidationContext ctx(cred, auth, env); + return validates(ctx); +} + +bool ObjectAcl::validates(AclValidationContext &ctx) +{ + // make sure we are ready to go + instantiateAcl(); + + IFDUMPING("acleval", Debug::dump("< range; + if (getRange(ctx.s_credTag(), range) == 0) // no such tag + CssmError::throwMe(CSSM_ERRCODE_ACL_ENTRY_TAG_NOT_FOUND); + // try each entry in turn + for (EntryMap::const_iterator it = range.first; it != range.second; it++) { + const AclEntry &slot = it->second; + IFDUMPING("acleval", (Debug::dump(" EVAL["), slot.debugDump(), Debug::dump("]"))); + if (slot.authorizes(ctx.authorization())) { + ctx.init(this, slot.subject); + ctx.entryTag(slot.tag); + if (slot.validate(ctx)) { + IFDUMPING("acleval", Debug::dump(">PASS>>\n")); + return true; // passed + } + IFDUMPING("acleval", Debug::dump(" NO")); + } + } + IFDUMPING("acleval", Debug::dump(">FAIL>>\n")); + return false; // no joy +} + +void ObjectAcl::validate(AclAuthorization auth, const AccessCredentials *cred, + AclValidationEnvironment *env) +{ + if (!validates(auth, cred, env)) + CssmError::throwMe(CSSM_ERRCODE_OPERATION_AUTH_DENIED); +} + +void ObjectAcl::validate(AclValidationContext &ctx) +{ + if (!validates(ctx)) + CssmError::throwMe(CSSM_ERRCODE_OPERATION_AUTH_DENIED); +} + + +void ObjectAcl::validateOwner(AclAuthorization authorizationHint, + const AccessCredentials *cred, AclValidationEnvironment *env) +{ + BaseValidationContext ctx(cred, authorizationHint, env); + validateOwner(ctx); +} + +void ObjectAcl::validateOwner(AclValidationContext &ctx) +{ + instantiateAcl(); + if (mOwner.validate(ctx)) + return; + CssmError::throwMe(CSSM_ERRCODE_OPERATION_AUTH_DENIED); +} + + +// +// Export an ObjectAcl to two memory blobs: public and private data separated. +// This is a standard two-pass size+copy operation. +// +void ObjectAcl::exportBlob(CssmData &publicBlob, CssmData &privateBlob) +{ + instantiateAcl(); + Writer::Counter pubSize, privSize; + Endian entryCount = mEntries.size(); + mOwner.exportBlob(pubSize, privSize); + pubSize(entryCount); + for (EntryMap::iterator it = begin(); it != end(); it++) + it->second.exportBlob(pubSize, privSize); + publicBlob = CssmData(allocator.malloc(pubSize), pubSize); + privateBlob = CssmData(allocator.malloc(privSize), privSize); + Writer pubWriter(publicBlob), privWriter(privateBlob); + mOwner.exportBlob(pubWriter, privWriter); + pubWriter(entryCount); + for (EntryMap::iterator it = begin(); it != end(); it++) + it->second.exportBlob(pubWriter, privWriter); + IFDUMPING("acl", debugDump("exported")); +} + + +// +// Import an ObjectAcl's contents from two memory blobs representing public and +// private contents, respectively. These blobs must have been generated by the +// export method. +// Prior contents (if any) are deleted and replaced. +// +void ObjectAcl::importBlob(const void *publicBlob, const void *privateBlob) +{ + Reader pubReader(publicBlob), privReader(privateBlob); + mOwner.importBlob(pubReader, privReader); + Endian entryCountIn; pubReader(entryCountIn); + uint32 entryCount = entryCountIn; + + mEntries.erase(begin(), end()); + for (uint32 n = 0; n < entryCount; n++) { + AclEntry newEntry; + newEntry.importBlob(pubReader, privReader); + add(newEntry.tag, newEntry); + } + IFDUMPING("acl", debugDump("imported")); +} + + +// +// Import/export helpers for subjects. +// This is exported to (subject implementation) callers to maintain consistency +// in binary format handling. +// +AclSubject *ObjectAcl::importSubject(Reader &pub, Reader &priv) +{ + Endian typeAndVersion; pub(typeAndVersion); + return make(typeAndVersion, pub, priv); +} + + +// +// Setup/update hooks +// +void ObjectAcl::instantiateAcl() +{ + // nothing by default +} + +void ObjectAcl::changedAcl() +{ + // nothing by default +} + + +// +// ACL utility methods +// +unsigned int ObjectAcl::getRange(const std::string &tag, + pair &range) const +{ + if (!tag.empty()) { // tag restriction in effect + range = mEntries.equal_range(tag); + uint32 count = mEntries.count(tag); + if (count == 0) + CssmError::throwMe(CSSM_ERRCODE_INVALID_ACL_ENTRY_TAG); + return count; + } else { // try all tags + range.first = mEntries.begin(); + range.second = mEntries.end(); + return mEntries.size(); + } +} + +ObjectAcl::EntryMap::iterator ObjectAcl::findEntryHandle(CSSM_ACL_HANDLE handle) +{ + for (EntryMap::iterator it = mEntries.begin(); it != mEntries.end(); it++) + if (it->second.handle == handle) + return it; + CssmError::throwMe(CSSMERR_CSSM_INVALID_HANDLE_USAGE); //%%% imprecise error code +} + + +// +// CSSM style ACL access and modification functions. +// +void ObjectAcl::cssmGetAcl(const char *tag, uint32 &count, AclEntryInfo * &acls) +{ + instantiateAcl(); + pair range; + count = getRange(tag ? tag : "", range); + acls = allocator.alloc(count); + uint32 n = 0; + for (EntryMap::const_iterator it = range.first; it != range.second; it++, n++) { + acls[n].EntryHandle = it->second.handle; + it->second.toEntryInfo(acls[n].EntryPublicInfo, allocator); + } + count = n; +} + +void ObjectAcl::cssmChangeAcl(const AclEdit &edit, + const AccessCredentials *cred, AclValidationEnvironment *env) +{ + IFDUMPING("acl", debugDump("acl-change-from")); + + // make sure we're ready to go + instantiateAcl(); + + // validate access credentials + validateOwner(CSSM_ACL_AUTHORIZATION_CHANGE_ACL, cred, env); + + // what is Thy wish, effendi? + switch (edit.EditMode) { + case CSSM_ACL_EDIT_MODE_ADD: { + const AclEntryInput &input = Required(edit.newEntry()); + add(input.proto().s_tag(), input.proto()); + } + break; + case CSSM_ACL_EDIT_MODE_REPLACE: { + // keep the handle, and try for some modicum of atomicity + EntryMap::iterator it = findEntryHandle(edit.handle()); + AclEntryPrototype proto = Required(edit.newEntry()).proto(); // (bypassing callbacks) + add(proto.s_tag(), proto, edit.handle()); + mEntries.erase(it); + } + break; + case CSSM_ACL_EDIT_MODE_DELETE: + mEntries.erase(findEntryHandle(edit.OldEntryHandle)); + break; + default: + CssmError::throwMe(CSSM_ERRCODE_INVALID_ACL_EDIT_MODE); + } + + // notify change + changedAcl(); + + IFDUMPING("acl", debugDump("acl-change-to")); +} + +void ObjectAcl::cssmGetOwner(AclOwnerPrototype &outOwner) +{ + instantiateAcl(); + outOwner.TypedSubject = mOwner.subject->toList(allocator); + outOwner.Delegate = mOwner.delegate; +} + +void ObjectAcl::cssmChangeOwner(const AclOwnerPrototype &newOwner, + const AccessCredentials *cred, AclValidationEnvironment *env) +{ + IFDUMPING("acl", debugDump("owner-change-from")); + + instantiateAcl(); + + // only the owner entry can match + validateOwner(CSSM_ACL_AUTHORIZATION_CHANGE_OWNER, cred, env); + + // okay, replace it + mOwner = newOwner; + + changedAcl(); + + IFDUMPING("acl", debugDump("owner-change-to")); +} + + +// +// Load a set of ACL entries from an AclEntryInfo array. +// This completely replaces the ACL's entries. +// Note that we will adopt the handles in the infos, so they better be proper +// (unique, nonzero). +// +template +void ObjectAcl::owner(const Input &input) +{ + IFDUMPING("acl", debugDump("owner-load-old")); + mOwner = OwnerEntry(input); + IFDUMPING("acl", debugDump("owner-load-new")); +} + +template void ObjectAcl::owner(const AclOwnerPrototype &); +template void ObjectAcl::owner(const AclSubjectPointer &); + + +void ObjectAcl::entries(uint32 count, const AclEntryInfo *info) +{ + IFDUMPING("acl", debugDump("entries-load-old")); + mEntries.erase(mEntries.begin(), mEntries.end()); + for (uint32 n = 0; n < count; n++, info++) + add(info->proto().s_tag(), info->proto()); + IFDUMPING("acl", debugDump("entries-load-new")); +} + + +// +// Clear out the ACL and return it to un-initialized state +// +void ObjectAcl::clear() +{ + mOwner = OwnerEntry(); + mEntries.erase(mEntries.begin(), mEntries.end()); + secdebug("acl", "%p cleared", this); +} + + +// +// Common gate to add an ACL entry +// +void ObjectAcl::add(const std::string &tag, const AclEntry &newEntry) +{ + add(tag, newEntry, mNextHandle++); +} + +void ObjectAcl::add(const std::string &tag, AclEntry newEntry, CSSM_ACL_HANDLE handle) +{ + //@@@ This should use a hook-registry mechanism. But for now, we are explicit: + if (!newEntry.authorizesAnything) { + for (AclAuthorizationSet::const_iterator it = newEntry.authorizations.begin(); + it != newEntry.authorizations.end(); it++) + if (*it >= CSSM_ACL_AUTHORIZATION_PREAUTH_BASE && + *it < CSSM_ACL_AUTHORIZATION_PREAUTH_END) { + // preauthorization right - special handling + if (newEntry.subject->type() != CSSM_ACL_SUBJECT_TYPE_PREAUTH_SOURCE) + newEntry.subject = + new PreAuthorizationAcls::SourceAclSubject(newEntry.subject); + } + } + + mEntries.insert(make_pair(tag, newEntry))->second.handle = handle; + if (handle >= mNextHandle) + mNextHandle = handle + 1; // don't reuse this handle (in this ACL) +} + + +// +// Common features of ACL entries/owners +// +void ObjectAcl::Entry::init(const AclSubjectPointer &subject, bool delegate) +{ + this->subject = subject; + this->delegate = delegate; +} + +void ObjectAcl::Entry::importBlob(Reader &pub, Reader &priv) +{ + // the delegation flag is 4 bytes for historic reasons + Endian del; + pub(del); + delegate = del; + + subject = importSubject(pub, priv); +} + + +// +// An OwnerEntry is a restricted EntryPrototype for use as the ACL owner. +// +bool ObjectAcl::OwnerEntry::authorizes(AclAuthorization) const +{ + return true; // owner can do anything +} + +bool ObjectAcl::OwnerEntry::validate(const AclValidationContext &ctx) const +{ + return subject->validate(ctx); // simple subject match - no strings attached +} + + +// +// An AclEntry has some extra goodies +// +ObjectAcl::AclEntry::AclEntry(const AclEntryPrototype &proto) : Entry(proto) +{ + tag = proto.s_tag(); + if (proto.authorization().contains(CSSM_ACL_AUTHORIZATION_ANY)) + authorizesAnything = true; // anything else wouldn't add anything + else if (proto.authorization().empty()) + authorizesAnything = true; // not in standard, but common sense + else { + authorizesAnything = false; + authorizations = proto.authorization(); + } + //@@@ not setting time range + // handle = not set here. Set by caller when the AclEntry is created. +} + +ObjectAcl::AclEntry::AclEntry(const AclSubjectPointer &subject) : Entry(subject) +{ + authorizesAnything = true; // by default, everything + //@@@ not setting time range +} + +void ObjectAcl::AclEntry::toEntryInfo(CSSM_ACL_ENTRY_PROTOTYPE &info, Allocator &alloc) const +{ + info.TypedSubject = subject->toList(alloc); + info.Delegate = delegate; + info.Authorization = authorizesAnything ? + AuthorizationGroup(CSSM_ACL_AUTHORIZATION_ANY, alloc) : + AuthorizationGroup(authorizations, alloc); + //@@@ info.TimeRange = + assert(tag.length() <= CSSM_MODULE_STRING_SIZE); + memcpy(info.EntryTag, tag.c_str(), tag.length() + 1); +} + +bool ObjectAcl::AclEntry::authorizes(AclAuthorization auth) const +{ + return authorizesAnything || authorizations.find(auth) != authorizations.end(); +} + +bool ObjectAcl::AclEntry::validate(const AclValidationContext &ctx) const +{ + //@@@ not checking time ranges + return subject->validate(ctx); +} + +void ObjectAcl::AclEntry::importBlob(Reader &pub, Reader &priv) +{ + Entry::importBlob(pub, priv); + const char *s; pub(s); tag = s; + + // authorizesAnything is on disk as a 4-byte flag + Endian tmpAuthorizesAnything; + pub(tmpAuthorizesAnything); + authorizesAnything = tmpAuthorizesAnything; + + authorizations.erase(authorizations.begin(), authorizations.end()); + if (!authorizesAnything) { + Endian countIn; pub(countIn); + uint32 count = countIn; + + for (uint32 n = 0; n < count; n++) { + Endian auth; pub(auth); + authorizations.insert(auth); + } + } + //@@@ import time range +} + + +// +// Subject factory and makers +// +AclSubject::Maker::Maker(CSSM_ACL_SUBJECT_TYPE type) + : mType(type) +{ + ObjectAcl::makers()[type] = this; +} + +AclSubject *ObjectAcl::make(const TypedList &list) +{ + if (!list.isProper()) + CssmError::throwMe(CSSM_ERRCODE_INVALID_ACL_SUBJECT_VALUE); + return makerFor(list.type()).make(list); +} + +AclSubject *ObjectAcl::make(uint32 typeAndVersion, Reader &pub, Reader &priv) +{ + // this type is encoded as (version << 24) | type + return makerFor(typeAndVersion & ~AclSubject::versionMask).make(typeAndVersion >> AclSubject::versionShift, pub, priv); +} + +AclSubject::Maker &ObjectAcl::makerFor(CSSM_ACL_SUBJECT_TYPE type) +{ + AclSubject::Maker *maker = makers()[type]; + if (maker == NULL) + CssmError::throwMe(CSSM_ERRCODE_ACL_SUBJECT_TYPE_NOT_SUPPORTED); + return *maker; +} + + +// +// Parsing helper for subject makers. +// Note that count/array exclude the first element of list, which is the subject type wordid. +// +void AclSubject::Maker::crack(const CssmList &list, uint32 count, ListElement **array, ...) +{ + if (count != list.length() - 1) + CssmError::throwMe(CSSM_ERRCODE_INVALID_ACL_SUBJECT_VALUE); + if (count > 0) { + va_list args; + va_start(args, array); + ListElement *elem = list.first()->next(); + for (uint32 n = 0; n < count; n++, elem = elem->next()) { + CSSM_LIST_ELEMENT_TYPE expectedType = va_arg(args, CSSM_LIST_ELEMENT_TYPE); + if (elem->type() != expectedType) + CssmError::throwMe(CSSM_ERRCODE_INVALID_ACL_SUBJECT_VALUE); + array[n] = elem; + } + va_end(args); + } +} + +CSSM_WORDID_TYPE AclSubject::Maker::getWord(const ListElement &elem, + int min /*= 0*/, int max /*= INT_MAX*/) +{ + if (elem.type() != CSSM_LIST_ELEMENT_WORDID) + CssmError::throwMe(CSSM_ERRCODE_INVALID_ACL_SUBJECT_VALUE); + CSSM_WORDID_TYPE value = elem; + if (value < min || value > max) + CssmError::throwMe(CSSM_ERRCODE_INVALID_ACL_SUBJECT_VALUE); + return value; +} + + +// +// Debug dumping support. +// Leave the ObjectAcl::debugDump method in (stubbed out) +// to keep the virtual table layout stable, and to allow +// proper linking in weird mix-and-match scenarios. +// +void ObjectAcl::debugDump(const char *what) const +{ +#if defined(DEBUGDUMP) + if (!what) + what = "Dump"; + Debug::dump("%p ACL %s: %d entries\n", this, what, int(mEntries.size())); + Debug::dump(" OWNER ["); mOwner.debugDump(); Debug::dump("]\n"); + for (EntryMap::const_iterator it = begin(); it != end(); it++) { + const AclEntry &ent = it->second; + Debug::dump(" (%ld:%s) [", ent.handle, ent.tag.c_str()); + ent.debugDump(); + Debug::dump("]\n"); + } + Debug::dump("%p ACL END\n", this); +#endif //DEBUGDUMP +} + +#if defined(DEBUGDUMP) + +void ObjectAcl::Entry::debugDump() const +{ + if (subject) { + if (AclSubject::Version v = subject->version()) + Debug::dump("V=%d ", v); + subject->debugDump(); + } else { + Debug::dump("NULL subject"); + } + if (delegate) + Debug::dump(" DELEGATE"); +} + +void ObjectAcl::AclEntry::debugDump() const +{ + Entry::debugDump(); + if (authorizesAnything) { + Debug::dump(" auth(ALL)"); + } else { + Debug::dump(" auth("); + for (AclAuthorizationSet::iterator it = authorizations.begin(); + it != authorizations.end(); it++) { + if (*it >= CSSM_ACL_AUTHORIZATION_PREAUTH_BASE + && *it < CSSM_ACL_AUTHORIZATION_PREAUTH_END) + Debug::dump(" PRE(%d)", *it - CSSM_ACL_AUTHORIZATION_PREAUTH_BASE); + else + Debug::dump(" %d", *it); + } + Debug::dump(")"); + } +} + +#endif //DEBUGDUMP diff --git a/libsecurity_cdsa_utilities/lib/objectacl.h b/libsecurity_cdsa_utilities/lib/objectacl.h new file mode 100644 index 00000000..f464eab9 --- /dev/null +++ b/libsecurity_cdsa_utilities/lib/objectacl.h @@ -0,0 +1,250 @@ +/* + * 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@ + */ + + +// +// objectacl - core implementation of an ACL-bearing object +// +#ifndef _OBJECTACL +#define _OBJECTACL + +#include +#include +#include +#include +#include + + +namespace Security { + + +// +// An in-memory ACL object. +// This class implements an ACL-for-a-protected-object. It is complete in that +// it provides full ACL management functionality. You still need to (globally) +// register makers for the ACL subject types you want to use. +// Note that ObjectAcl does no integrity checking. ObjectAcl objects need to be +// protected from hostile access (by e.g. address space separation), and exported +// ACLs need to be protected somehow (by hiding, signing, or whatever works in +// your situation). +// +class ObjectAcl { + friend AclSubject::Maker::Maker(CSSM_ACL_SUBJECT_TYPE); + +public: + typedef RefPointer AclSubjectPointer; + + typedef LowLevelMemoryUtilities::Writer Writer; + typedef LowLevelMemoryUtilities::Reader Reader; + +public: + ObjectAcl(Allocator &alloc); + ObjectAcl(const AclEntryPrototype &proto, Allocator &alloc); + virtual ~ObjectAcl(); + + Allocator &allocator; + + + // + // access control validation (evaluation) + // + + // validate(): succeed or throw exception + void validate(AclAuthorization auth, const AccessCredentials *cred, + AclValidationEnvironment *env = NULL); + void validate(AclValidationContext &ctx); + + // validates(): return true or false (or throw on error) + bool validates(AclAuthorization auth, const AccessCredentials *cred, + AclValidationEnvironment *env = NULL); + bool validates(AclValidationContext &ctx); + + // owner validation (simpler) + void validateOwner(AclAuthorization authorizationHint, const AccessCredentials *cred, + AclValidationEnvironment *env = NULL); + void validateOwner(AclValidationContext &ctx); + + // CSSM-style ACL access operations + // (Gets are not const because underlying implementations usually want them writable) + void cssmGetAcl(const char *tag, uint32 &count, AclEntryInfo * &acls); + void cssmChangeAcl(const AclEdit &edit, const AccessCredentials *cred, + AclValidationEnvironment *env = NULL); + void cssmGetOwner(AclOwnerPrototype &owner); + void cssmChangeOwner(const AclOwnerPrototype &newOwner, const AccessCredentials *cred, + AclValidationEnvironment *env = NULL); + + void cssmSetInitial(const AclEntryPrototype &proto); + void cssmSetInitial(const AclSubjectPointer &subject); + + // Acl I/O (to/from memory blobs) + void exportBlob(CssmData &publicBlob, CssmData &privateBlob); + void importBlob(const void *publicBlob, const void *privateBlob); + + // clear everything from this ACL (return it to un-initialized state) + void clear(); + + // setup hooks (called to delayed-construct the contents before use) - empty defaults + virtual void instantiateAcl(); // called before ACL contents are used by external calls + virtual void changedAcl(); // called after an ACL has been (possibly) changed + + // debug dump support (always there but stubbed out unless DEBUGDUMP) + virtual void debugDump(const char *what = NULL) const; + +public: + class Entry { + public: + AclSubjectPointer subject; // subject representation + bool delegate; // delegation flag + + Entry() { } // make invalid Entry + + void toOwnerInfo(CSSM_ACL_OWNER_PROTOTYPE &info, + Allocator &alloc) const; // encode copy in CSSM format + + virtual bool authorizes(AclAuthorization auth) const = 0; + virtual bool validate(const AclValidationContext &ctx) const = 0; + + template + void exportBlob(Action &pub, Action &priv) + { + Endian del = delegate; pub(del); // 4 bytes delegate flag + exportSubject(subject, pub, priv); // subject itself (polymorphic) + } + void importBlob(Reader &pub, Reader &priv); + + IFDUMP(virtual void debugDump() const); + + private: + void init(const AclSubjectPointer &subject, bool delegate = false); + void init(const TypedList &subject, bool delegate = false) { init(make(subject), delegate); } + + protected: + Entry(const AclEntryPrototype &proto) { init(proto.subject(), proto.delegate()); } + Entry(const AclOwnerPrototype &proto) { init(proto.subject()); } + Entry(const AclSubjectPointer &subject) { init(subject); } + virtual ~Entry(); + }; + + class OwnerEntry : public Entry { + public: + OwnerEntry() { } // invalid OwnerEntry + template + OwnerEntry(const Input &owner) : Entry(owner) { } + + bool authorizes(AclAuthorization auth) const; + bool validate(const AclValidationContext &ctx) const; + }; + + class AclEntry : public Entry { + public: + std::string tag; // entry tag + AclAuthorizationSet authorizations; // set of authorizations + bool authorizesAnything; // has the _ANY authorization tag + //@@@ time range not yet implemented + CSSM_ACL_HANDLE handle; // entry handle + + AclEntry() { } // invalid AclEntry + AclEntry(const AclSubjectPointer &subject); + AclEntry(const AclEntryPrototype &proto); + + void toEntryInfo(CSSM_ACL_ENTRY_PROTOTYPE &info, + Allocator &alloc) const; // encode copy in CSSM format + + bool authorizes(AclAuthorization auth) const; + bool validate(const AclValidationContext &ctx) const; + + template + void exportBlob(Action &pub, Action &priv) + { + Entry::exportBlob(pub, priv); + const char *s = tag.c_str(); pub(s); + uint32 aa = authorizesAnything; pub(aa); + if (!authorizesAnything) { + Endian count = authorizations.size(); pub(count); + for (AclAuthorizationSet::iterator it = authorizations.begin(); + it != authorizations.end(); it++) { + Endian auth = *it; pub(auth); + } + } + //@@@ export time range + } + void importBlob(Reader &pub, Reader &priv); + + IFDUMP(void debugDump() const); + }; + +public: + // These helpers deal with transferring one subject from/to reader/writer streams. + // You'd usually only call those from complex subject implementations (e.g. threshold) + template + static void exportSubject(AclSubject *subject, Action &pub, Action &priv) + { + Endian typeAndVersion = subject->type() | subject->version() << AclSubject::versionShift; + pub(typeAndVersion); + subject->exportBlob(pub, priv); + } + static AclSubject *importSubject(Reader &pub, Reader &priv); + +public: + typedef std::multimap EntryMap; + + EntryMap::iterator begin() { return mEntries.begin(); } + EntryMap::iterator end() { return mEntries.end(); } + EntryMap::const_iterator begin() const { return mEntries.begin(); } + EntryMap::const_iterator end() const { return mEntries.end(); } + + unsigned int getRange(const std::string &tag, + pair &range) const; + EntryMap::iterator findEntryHandle(CSSM_ACL_HANDLE handle); + + // construct an AclSubject through the Maker registry (by subject type) + static AclSubject *make(const TypedList &list); // make from CSSM form + static AclSubject *make(uint32 typeAndVersion, + Reader &pub, Reader &priv); // make from export form + +protected: + template + void owner(const Input &input); + void entries(uint32 count, const AclEntryInfo *infos); + +private: + void add(const std::string &tag, const AclEntry &newEntry); + void add(const std::string &tag, AclEntry newEntry, CSSM_ACL_HANDLE handle); + +private: + EntryMap mEntries; // ACL entries indexed by tag + OwnerEntry mOwner; // ACL owner entry + CSSM_ACL_HANDLE mNextHandle; // next unused entry handle value + +private: + typedef map MakerMap; + static ModuleNexus makers; // registered subject Makers + + static AclSubject::Maker &makerFor(CSSM_ACL_SUBJECT_TYPE type); +}; + + +} // end namespace Security + + +#endif //_OBJECTACL diff --git a/libsecurity_cdsa_utilities/lib/osxverifier.cpp b/libsecurity_cdsa_utilities/lib/osxverifier.cpp new file mode 100644 index 00000000..a9616415 --- /dev/null +++ b/libsecurity_cdsa_utilities/lib/osxverifier.cpp @@ -0,0 +1,177 @@ +/* + * 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. + */ + + +// +// osxsigner - MacOS X's standard code signing algorithm. +// +#include +#include +#include +#include +#include +#include +#include // debug only + + +using namespace CodeSigning; + + +namespace Security { + + +// +// Create a Verifier from a code object. +// +// This does not add any auxiliary information blobs. You can do that +// by calling add() after construction, of course. +// +OSXVerifier::OSXVerifier(OSXCode *code) +{ + mPath = code->canonicalPath(); + secdebug("codesign", "building verifier for %s", mPath.c_str()); + + // build new-style verifier + CFRef staticCode = code->codeRef(); + switch (OSStatus rc = SecCodeCopyDesignatedRequirement(staticCode, + kSecCSDefaultFlags, &mRequirement.aref())) { + case noErr: + secdebug("codesign", " is signed; canonical requirement loaded"); + break; + case errSecCSUnsigned: + secdebug("codesign", " is unsigned; no requirement"); + break; + default: + MacOSError::throwMe(rc); + } + + // build old-style verifier + makeLegacyHash(code, mLegacyHash); + secdebug("codesign", " hash generated"); +} + + +// +// Create a Verifier from hash, path, and requirement. +// Again, this has no auxiliary data when constructed. +// +OSXVerifier::OSXVerifier(const SHA1::Byte *hash, const std::string &path) + : mPath(path) +{ + secdebug("codesign", "building verifier from hash %p and path=%s", hash, path.c_str()); + if (hash) + memcpy(mLegacyHash, hash, sizeof(mLegacyHash)); + else + memset(mLegacyHash, 0, sizeof(mLegacyHash)); +} + + +OSXVerifier::~OSXVerifier() +{ + secdebug("codesign", "%p verifier destroyed", this); +} + + +// +// Add an auxiliary comment blob. +// Note that we only allow one auxiliary blob for each magic number. +// +void OSXVerifier::add(const BlobCore *blob) +{ + if (blob->is()) { +#if defined(NDEBUG) + secdebug("codesign", "%p verifier adds requirement", this); +#else + secdebug("codesign", "%p verifier adds requirement %s", this, + Dumper::dump(Requirement::specific(blob), true).c_str()); +#endif //NDEBUG + MacOSError::check(SecRequirementCreateWithData(CFTempData(*blob), + kSecCSDefaultFlags, &mRequirement.aref())); + } else { + secdebug("codesign", "%p verifier adds blob (0x%x,%zd)", + this, blob->magic(), blob->length()); + BlobCore * &slot = mAuxiliary[blob->magic()]; + if (slot) + ::free(slot); + slot = blob->clone(); + } +} + + +// +// Find a comment blob, by magic number +// +const BlobCore *OSXVerifier::find(BlobCore::Magic magic) +{ + AuxMap::const_iterator it = mAuxiliary.find(magic); + return (it == mAuxiliary.end()) ? NULL : it->second; +} + + +void OSXVerifier::makeLegacyHash(OSXCode *code, SHA1::Digest digest) +{ + secdebug("codesign", "calculating legacy hash for %s", code->canonicalPath().c_str()); + UnixPlusPlus::AutoFileDesc fd(code->executablePath(), O_RDONLY); + char buffer[legacyHashLimit]; + size_t size = fd.read(buffer, legacyHashLimit); + SHA1 hash; + hash(buffer, size); + hash.finish(digest); +} + + +// +// The AuxMap helper class provides a map-to-Blob-pointers with automatic memory management. +// +OSXVerifier::AuxMap::AuxMap(const OSXVerifier::AuxMap &src) +{ + for (const_iterator it = src.begin(); it != src.end(); it++) + this->insert(*it); +} + +OSXVerifier::AuxMap::~AuxMap() +{ + for (const_iterator it = this->begin(); it != this->end(); ++it) + ::free(it->second); +} + + +#if DEBUGDUMP + +void OSXVerifier::dump() const +{ + static const SHA1::Digest nullDigest = { 0 }; + if (!memcmp(mLegacyHash, nullDigest, sizeof(mLegacyHash))) { + Debug::dump("(no hash)"); + } else { + Debug::dump("oldHash="); + Debug::dumpData(mLegacyHash, sizeof(mLegacyHash)); + } + if (mRequirement) { + CFRef reqData; + if (!SecRequirementCopyData(mRequirement, 0, &reqData.aref())) { + Debug::dump(" Requirement =>"); + ((const Requirement *)CFDataGetBytePtr(reqData))->dump(); + } + } else { + Debug::dump(" NO REQ"); + } +} + +#endif //DEBUGDUMP + +} // end namespace Security diff --git a/libsecurity_cdsa_utilities/lib/osxverifier.h b/libsecurity_cdsa_utilities/lib/osxverifier.h new file mode 100644 index 00000000..a431c338 --- /dev/null +++ b/libsecurity_cdsa_utilities/lib/osxverifier.h @@ -0,0 +1,93 @@ +/* + * 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. + */ + + +// +// osxsigner - MacOS X's standard code signing algorithm. +// +#ifndef _H_OSXVERIFIER +#define _H_OSXVERIFIER + +#include +#include +#include +#include +#include +#include +#include + +namespace Security { + + +// +// A standard OS X style signature verifier. +// This encapsulates the different modes of signing/verifying currently +// supported. It knows nothing about the way this is represented in +// keychain access control lists; this knowledge resides exclusively +// in acl_codesigning. +// +class OSXVerifier { +public: + static const size_t legacyHashLimit = 16 * 1024; + static const uint32_t commentAlignment = 4; + +public: + // make a Verifier from a code reference object + OSXVerifier(OSXCode *code); // makes both legacy hash and SecRequirement + OSXVerifier(const SHA1::Byte *hash, const std::string &path); // just hash + ~OSXVerifier(); + + // components + const unsigned char *legacyHash() const { return mLegacyHash; } + std::string path() const { return mPath; } + SecRequirementRef requirement() const { return mRequirement; } + +public: + // handle other (not explicitly understood) information in the verifier + class AuxMap : public std::map { + public: + AuxMap() { } + AuxMap(const AuxMap &src); + ~AuxMap(); + }; + + AuxMap::const_iterator beginAux() const { return mAuxiliary.begin(); } + AuxMap::const_iterator endAux() const { return mAuxiliary.end(); } + + void add(const BlobCore *info); + const BlobCore *find(BlobCore::Magic magic); + + template + static const BlobType *find() + { return static_cast(find(BlobType::typeMagic)); } + +public: + static void makeLegacyHash(OSXCode *code, SHA1::Digest digest); + + IFDUMP(void dump() const); + +private: + SHA1::Digest mLegacyHash; // legacy page hash + std::string mPath; // path to originating code (comment) + CFCopyRef mRequirement; // CS-style requirement + AuxMap mAuxiliary; // other data (does not include mRequirement) +}; + +} // end namespace Security + + +#endif //_H_OSXVERIFIER diff --git a/libsecurity_cdsa_utilities/lib/u32handleobject.cpp b/libsecurity_cdsa_utilities/lib/u32handleobject.cpp new file mode 100644 index 00000000..6bd056c4 --- /dev/null +++ b/libsecurity_cdsa_utilities/lib/u32handleobject.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (c) 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 + diff --git a/libsecurity_cdsa_utilities/lib/u32handleobject.h b/libsecurity_cdsa_utilities/lib/u32handleobject.h new file mode 100644 index 00000000..630f9246 --- /dev/null +++ b/libsecurity_cdsa_utilities/lib/u32handleobject.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 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@ + */ + + +#ifndef _H_U32HANDLEOBJECT +#define _H_U32HANDLEOBJECT + +#include +#include + +// +// 32-bit unsigned handle object +// Specifically meant for securityd handles sent to clients +// + +namespace Security +{ + +typedef MappingHandle U32HandleObject; + +} // end namespace Security + +#endif //_H_U32HANDLEOBJECT diff --git a/libsecurity_cdsa_utilities/lib/uniformrandom.cpp b/libsecurity_cdsa_utilities/lib/uniformrandom.cpp new file mode 100644 index 00000000..a87a6cde --- /dev/null +++ b/libsecurity_cdsa_utilities/lib/uniformrandom.cpp @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2000-2001,2003-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@ + */ + + +// +// uniformrandom - uniformly distributed random number operators +// + +#include + + +namespace Security { + + + + +} // end namespace Security diff --git a/libsecurity_cdsa_utilities/lib/uniformrandom.h b/libsecurity_cdsa_utilities/lib/uniformrandom.h new file mode 100644 index 00000000..5fc9d4ae --- /dev/null +++ b/libsecurity_cdsa_utilities/lib/uniformrandom.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2000-2001,2003-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@ + */ + + +// +// uniformrandom - uniformly distributed random number operators +// +#ifndef _H_UNIFORMRANDOM +#define _H_UNIFORMRANDOM + +#include + + +namespace Security { + + +// +// Uniform binary blob generator. +// This operator deals exclusively in byte arrays. +// +template +class UniformRandomBlobs : public Generator { +public: + using Generator::random; + + template + void random(Object &obj) { random(&obj, sizeof(obj)); } + + void random(CssmData &data) { random(data.data(), data.length()); } +}; + + +}; // end namespace Security + + +#endif //_H_UNIFORMRANDOM diff --git a/libsecurity_cdsa_utilities/lib/walkers.cpp b/libsecurity_cdsa_utilities/lib/walkers.cpp new file mode 100644 index 00000000..23b510c2 --- /dev/null +++ b/libsecurity_cdsa_utilities/lib/walkers.cpp @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2000-2001,2003-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@ + */ + + +// +// walkers - facilities for traversing and manipulating recursive data structures +// +#include + + +namespace Security { +namespace DataWalkers { + + +// +// Free all recorded storage nodes for a ChunkFreeWalker +// +void ChunkFreeWalker::free() +{ + for (set::iterator it = freeSet.begin(); it != freeSet.end(); it++) + allocator.free(*it); + freeSet.erase(freeSet.begin(), freeSet.end()); +} + + +} // end namespace DataWalkers +} // end namespace Security diff --git a/libsecurity_cdsa_utilities/lib/walkers.h b/libsecurity_cdsa_utilities/lib/walkers.h new file mode 100644 index 00000000..4d4baa3f --- /dev/null +++ b/libsecurity_cdsa_utilities/lib/walkers.h @@ -0,0 +1,393 @@ +/* + * Copyright (c) 2000-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@ + */ + + +// +// walkers - facilities for traversing and manipulating recursive data structures +// +// Very briefly, this facility allows for deep traversals of (potentially) recursive +// data structures through templated structure "walkers." Standard operations include +// deep copying to a contiguous memory buffer, size calculation, deep freeing, reconstitution +// after relocation (e.g. via IPC), and others. You can add other operations (e.g. scattered deep +// copy, debug dumping, etc.) by defining operations classes and applying them to the +// existing walkers. You can also extend the reach of the facility to new data structures +// by writing appropriate walker functions for them. +// +// NOTE: We no longer have a default walker for flat structures. You must define +// a walk(operate, foo * &) function for every data type encountered during a walk +// or you will get compile-time errors. +// +// For more detailed rules and regulations, see the accompanying documentation. +// +#ifndef _H_WALKERS +#define _H_WALKERS + +#include +#include +#include +#include +#include + + +namespace Security { +namespace DataWalkers { + +#define WALKERDEBUG 0 + + +#if WALKERDEBUG +# define DEBUGWALK(who) secdebug("walkers", "walk " who " %s@%p (%ld)", \ + Debug::typeName(addr).c_str(), addr, size) +#else +# define DEBUGWALK(who) /* nothing */ +#endif + + +// +// SizeWalker simply walks a structure and calculates how many bytes +// CopyWalker would use to make a flat copy. This is naturally at least +// the sum of all relevant sizes, but can be more due to alignment and +// counting overhead. +// +class SizeWalker : public LowLevelMemoryUtilities::Writer::Counter { +public: + template + void operator () (T &obj, size_t size = sizeof(T)) { } + + template + void operator () (T *addr, size_t size = sizeof(T)) + { DEBUGWALK("size"); LowLevelMemoryUtilities::Writer::Counter::insert(size); } + + void blob(void *addr, size_t size) + { (*this)(addr, size); } + + void reserve(size_t space) + { LowLevelMemoryUtilities::Writer::Counter::insert(space); } + + static const bool needsRelinking = false; + static const bool needsSize = true; +}; + + +// +// CopyWalker makes a deep, flat copy of a structure. The result will work +// just like the original (with all elements recursively copied), except that +// it occupies contiguous memory. +// +class CopyWalker : public LowLevelMemoryUtilities::Writer { +public: + CopyWalker() { } + CopyWalker(void *base) : LowLevelMemoryUtilities::Writer(base) { } + +public: + template + void operator () (T &obj, size_t size = sizeof(T)) + { } + + template + void operator () (T * &addr, size_t size = sizeof(T)) + { + DEBUGWALK("copy"); + if (addr) + addr = reinterpret_cast(LowLevelMemoryUtilities::Writer::operator () (addr, size)); + } + + template + void blob(T * &addr, size_t size) + { (*this)(addr, size); } + + static const bool needsRelinking = true; + static const bool needsSize = true; +}; + + +// +// Walk a structure and apply a constant linear shift to all pointers +// encountered. This is useful when a structure and its deep components +// have been linearly shifted by something (say, an IPC transit). +// +class ReconstituteWalker { +public: + ReconstituteWalker(off_t offset) : mOffset(offset) { } + ReconstituteWalker(void *ptr, void *base) + : mOffset(LowLevelMemoryUtilities::difference(ptr, base)) { } + + template + void operator () (T &obj, size_t size = sizeof(T)) + { } + + template + void operator () (T * &addr, size_t size = 0) + { + DEBUGWALK("reconstitute"); + if (addr) + addr = LowLevelMemoryUtilities::increment(addr, mOffset); + } + + template + void blob(T * &addr, size_t size) + { (*this)(addr, size); } + + static const bool needsRelinking = true; + static const bool needsSize = false; + +private: + off_t mOffset; +}; + + +// +// Make an element-by-element copy of a structure. Each pointer followed +// uses a separate allocation for its pointed-to storage. +// +class ChunkCopyWalker { +public: + ChunkCopyWalker(Allocator &alloc = Allocator::standard()) : allocator(alloc) { } + + Allocator &allocator; + + template + void operator () (T &obj, size_t size = sizeof(T)) + { } + + template + void operator () (T * &addr, size_t size = sizeof(T)) + { + DEBUGWALK("chunkcopy"); +#if BUG_GCC + T *copy = reinterpret_cast(allocator.malloc(size)); +#else + T *copy = allocator.malloc(size); +#endif + memcpy(copy, addr, size); + addr = copy; + } + + template + void blob(T * &addr, size_t size) + { (*this)(addr, size); } + + static const bool needsRelinking = true; + static const bool needsSize = true; +}; + + +// +// Walk a structure and call an Allocator to separate free each node. +// This is safe for non-trees (i.e. shared subsidiary nodes); such will +// only be freed once. +// +class ChunkFreeWalker { +public: + ChunkFreeWalker(Allocator &alloc = Allocator::standard()) : allocator(alloc) { } + + Allocator &allocator; + + template + void operator () (T &obj, size_t size = 0) + { } + + template + void operator () (T *addr, size_t size = 0) + { + DEBUGWALK("chunkfree"); + freeSet.insert(addr); + } + + void blob(void *addr, size_t size) + { (*this)(addr, 0); } + + void free(); + ~ChunkFreeWalker() { free(); } + + static const bool needsRelinking = false; + static const bool needsSize = false; + +private: + std::set freeSet; +}; + + +// +// Stand-alone operations for a single structure web. +// These simply create, use, and discard their operator objects internally. +// +template +size_t size(T obj) +{ + SizeWalker w; + walk(w, obj); + return w; +} + +// Special version for const pointer's +template +size_t size(const T *obj) +{ return size(const_cast(obj)); } + + +template +T *copy(const T *obj, void *addr) +{ + if (obj == NULL) + return NULL; + CopyWalker w(addr); + walk(w, const_cast(obj)); + return const_cast(obj); +} + +template +T *copy(const T *obj, Allocator &alloc, size_t size) +{ + if (obj == NULL) + return NULL; + return copy(obj, alloc.malloc(size)); +} + +template +T *copy(const T *obj, Allocator &alloc = Allocator::standard()) +{ + return obj ? copy(obj, alloc, size(obj)) : NULL; +} + + +template +void relocate(T *obj, T *base) +{ + if (obj) { + ReconstituteWalker w(LowLevelMemoryUtilities::difference(obj, base)); + walk(w, base); + } +} + + +// +// chunkCopy and chunkFree can take pointer and non-pointer arguments. +// Don't try to declare the T arguments const (overload resolution will +// mess you over if you try). Just take const and nonconst Ts and take +// the const away internally. +// +template +typename Nonconst::Type *chunkCopy(T *obj, Allocator &alloc = Allocator::standard()) +{ + if (obj) { + ChunkCopyWalker w(alloc); + return walk(w, unconst_ref_cast(obj)); + } else + return NULL; +} + +template +T chunkCopy(T obj, Allocator &alloc = Allocator::standard()) +{ + ChunkCopyWalker w(alloc); + walk(w, obj); + return obj; +} + +template +void chunkFree(T *obj, Allocator &alloc = Allocator::standard()) +{ + if (obj) { + ChunkFreeWalker w(alloc); + walk(w, unconst_ref_cast(obj)); + } +} + +template +void chunkFree(const T &obj, Allocator &alloc = Allocator::standard()) +{ + ChunkFreeWalker w(alloc); + walk(w, obj); +} + + +// +// Copier combines SizeWalker and CopyWalker into one operational package. +// this is useful if you need both the copy and its size (and don't want +// to re-run size()). Copier (like copy()) only applies to one object. +// +template +class Copier { +public: + Copier(const T *obj, Allocator &alloc = Allocator::standard()) : allocator(alloc) + { + if (obj == NULL) { + mValue = NULL; + mLength = 0; + } else { + mLength = size(const_cast(obj)); +#if BUG_GCC + mValue = reinterpret_cast(alloc.malloc(mLength)); +#else + mValue = alloc.malloc(mLength); +#endif + mValue = copy(obj, mValue); + } + } + + Copier(const T *obj, uint32 count, Allocator &alloc = Allocator::standard()) + : allocator(alloc) + { + if (obj == NULL) { + mValue = NULL; + mLength = 0; + } else { + SizeWalker sizer; + sizer.reserve(sizeof(T) * count); // initial vector size + for (uint32 n = 0; n < count; n++) + walk(sizer, const_cast(obj[n])); // dependent data sizes + mLength = sizer; +#if BUG_GCC + mValue = reinterpret_cast(alloc.malloc(mLength)); +#else + mValue = alloc.malloc(mLength); +#endif + CopyWalker copier(LowLevelMemoryUtilities::increment(mValue, sizeof(T) * count)); + for (uint32 n = 0; n < count; n++) { + mValue[n] = obj[n]; + walk(copier, mValue[n]); + } + } + } + + Allocator &allocator; + + ~Copier() { allocator.free(mValue); } + + T *value() const { return mValue; } + operator T *() const { return value(); } + size_t length() const { return mLength; } + + T *keep() { T *result = mValue; mValue = NULL; return result; } + +private: + T *mValue; + size_t mLength; +}; + + +} // end namespace DataWalkers +} // end namespace Security + +#endif //_H_WALKERS diff --git a/libsecurity_cdsa_utilities/libsecurity_cdsa_utilities.xcodeproj/project.pbxproj b/libsecurity_cdsa_utilities/libsecurity_cdsa_utilities.xcodeproj/project.pbxproj new file mode 100644 index 00000000..df02c6ce --- /dev/null +++ b/libsecurity_cdsa_utilities/libsecurity_cdsa_utilities.xcodeproj/project.pbxproj @@ -0,0 +1,699 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 1865FBF01472415600FD79DF /* objectacl.h in Headers */ = {isa = PBXBuildFile; fileRef = C2BFD03306E6CDFE0047EA99 /* objectacl.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1865FBF11472415600FD79DF /* aclsubject.h in Headers */ = {isa = PBXBuildFile; fileRef = C2BFD03106E6CDFE0047EA99 /* aclsubject.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1865FBF21472415600FD79DF /* cssmacl.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CF64CF7052A3278008ED0EA /* cssmacl.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1865FBF31472415600FD79DF /* acl_any.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CF64CE1052A3278008ED0EA /* acl_any.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1865FBF41472415600FD79DF /* acl_codesigning.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CF64CE3052A3278008ED0EA /* acl_codesigning.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1865FBF51472415600FD79DF /* acl_comment.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CF64CE5052A3278008ED0EA /* acl_comment.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1865FBF61472415600FD79DF /* acl_password.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CF64CE7052A3278008ED0EA /* acl_password.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1865FBF71472415600FD79DF /* acl_preauth.h in Headers */ = {isa = PBXBuildFile; fileRef = C2371E3F06DD3E5E00E15E6F /* acl_preauth.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1865FBF81472415600FD79DF /* acl_process.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CF64CE9052A3278008ED0EA /* acl_process.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1865FBF91472415600FD79DF /* acl_prompted.h in Headers */ = {isa = PBXBuildFile; fileRef = C2BFD0E706E792410047EA99 /* acl_prompted.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1865FBFA1472415600FD79DF /* acl_protectedpw.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CF64CEB052A3278008ED0EA /* acl_protectedpw.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1865FBFB1472415600FD79DF /* acl_secret.h in Headers */ = {isa = PBXBuildFile; fileRef = C2BFD05B06E6D0560047EA99 /* acl_secret.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1865FBFC1472415600FD79DF /* acl_threshold.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CF64CED052A3278008ED0EA /* acl_threshold.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1865FBFD1472415600FD79DF /* AuthorizationData.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C838EA4058163A4006DA084 /* AuthorizationData.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1865FBFE1472415600FD79DF /* AuthorizationWalkers.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C838EA5058163A4006DA084 /* AuthorizationWalkers.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1865FBFF1472415600FD79DF /* callback.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CF64CEF052A3278008ED0EA /* callback.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1865FC001472415600FD79DF /* constdata.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CF64CF3052A3278008ED0EA /* constdata.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1865FC011472415600FD79DF /* context.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CF64CF5052A3278008ED0EA /* context.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1865FC021472415600FD79DF /* cssmaclpod.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CF64CF9052A3278008ED0EA /* cssmaclpod.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1865FC031472415600FD79DF /* cssmalloc.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CF64CFB052A3278008ED0EA /* cssmalloc.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1865FC041472415600FD79DF /* cssmbridge.h in Headers */ = {isa = PBXBuildFile; fileRef = C21A3EBE0545BEFA00C40B2E /* cssmbridge.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1865FC051472415600FD79DF /* cssmcert.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CF64CFD052A3278008ED0EA /* cssmcert.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1865FC061472415600FD79DF /* cssmcred.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CF64CFF052A3278008ED0EA /* cssmcred.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1865FC071472415600FD79DF /* cssmdata.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CF64D01052A3278008ED0EA /* cssmdata.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1865FC081472415600FD79DF /* cssmdates.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CF64D03052A3278008ED0EA /* cssmdates.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1865FC091472415600FD79DF /* cssmdb.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C088044053219880049BBEF /* cssmdb.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1865FC0A1472415600FD79DF /* cssmdbname.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C66D5E905321B2700537B59 /* cssmdbname.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1865FC0B1472415600FD79DF /* cssmendian.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CF64D07052A3278008ED0EA /* cssmendian.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1865FC0C1472415600FD79DF /* cssmerrors.h in Headers */ = {isa = PBXBuildFile; fileRef = C22EC42A052B8E4900D55C69 /* cssmerrors.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1865FC0D1472415600FD79DF /* cssmkey.h in Headers */ = {isa = PBXBuildFile; fileRef = C21A3EC00545BEFA00C40B2E /* cssmkey.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1865FC0E1472415600FD79DF /* cssmlist.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CF64D0B052A3278008ED0EA /* cssmlist.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1865FC0F1472415600FD79DF /* cssmpods.h in Headers */ = {isa = PBXBuildFile; fileRef = C21A3EC20545BEFA00C40B2E /* cssmpods.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1865FC101472415600FD79DF /* cssmtrust.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CF64D0D052A3278008ED0EA /* cssmtrust.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1865FC111472415600FD79DF /* cssmwalkers.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CF64D11052A3278008ED0EA /* cssmwalkers.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1865FC121472415600FD79DF /* db++.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CF64D13052A3278008ED0EA /* db++.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1865FC131472415600FD79DF /* digestobject.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CF64D14052A3278008ED0EA /* digestobject.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1865FC141472415600FD79DF /* handleobject.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CF64D16052A3278008ED0EA /* handleobject.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1865FC151472415600FD79DF /* handletemplates.h in Headers */ = {isa = PBXBuildFile; fileRef = 4E494DA80E0B084900026B9C /* handletemplates.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1865FC161472415600FD79DF /* handletemplates_defs.h in Headers */ = {isa = PBXBuildFile; fileRef = 4E494DA90E0B084900026B9C /* handletemplates_defs.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1865FC171472415600FD79DF /* KeySchema.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C38951C0534B198009CF879 /* KeySchema.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1865FC181472415600FD79DF /* Schema.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C96461A05378CCD00499C82 /* Schema.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1865FC191472415600FD79DF /* osxverifier.h in Headers */ = {isa = PBXBuildFile; fileRef = C2C1DC540A2CD98A00D1B02B /* osxverifier.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1865FC1A1472415600FD79DF /* u32handleobject.h in Headers */ = {isa = PBXBuildFile; fileRef = B61D0F900E0CF46700EC386B /* u32handleobject.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1865FC1B1472415700FD79DF /* uniformrandom.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CF64D23052A3278008ED0EA /* uniformrandom.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1865FC1C1472415700FD79DF /* walkers.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CF64D25052A3278008ED0EA /* walkers.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 4C088047053219880049BBEF /* cssmdb.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C088043053219880049BBEF /* cssmdb.cpp */; }; + 4C3895410534B31D009CF879 /* KeySchema.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C3895400534B31D009CF879 /* KeySchema.cpp */; }; + 4C66D5EA05321B2700537B59 /* cssmdbname.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C66D5E805321B2700537B59 /* cssmdbname.cpp */; }; + 4C838EA6058163A4006DA084 /* AuthorizationData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C838EA3058163A4006DA084 /* AuthorizationData.cpp */; }; + 4C838EA7058163A4006DA084 /* AuthorizationData.h in Sources */ = {isa = PBXBuildFile; fileRef = 4C838EA4058163A4006DA084 /* AuthorizationData.h */; }; + 4C838EA8058163A4006DA084 /* AuthorizationWalkers.h in Sources */ = {isa = PBXBuildFile; fileRef = 4C838EA5058163A4006DA084 /* AuthorizationWalkers.h */; }; + 4C92661705349551004B0E72 /* cssmerrors.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C22EC429052B8E4900D55C69 /* cssmerrors.cpp */; }; + 4C96462105378CEE00499C82 /* Schema.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C96462005378CEE00499C82 /* Schema.cpp */; }; + 4CF64D26052A3278008ED0EA /* acl_any.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CF64CE0052A3278008ED0EA /* acl_any.cpp */; }; + 4CF64D28052A3278008ED0EA /* acl_codesigning.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CF64CE2052A3278008ED0EA /* acl_codesigning.cpp */; }; + 4CF64D2A052A3278008ED0EA /* acl_comment.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CF64CE4052A3278008ED0EA /* acl_comment.cpp */; }; + 4CF64D2C052A3278008ED0EA /* acl_password.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CF64CE6052A3278008ED0EA /* acl_password.cpp */; }; + 4CF64D2E052A3278008ED0EA /* acl_process.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CF64CE8052A3278008ED0EA /* acl_process.cpp */; }; + 4CF64D30052A3278008ED0EA /* acl_protectedpw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CF64CEA052A3278008ED0EA /* acl_protectedpw.cpp */; }; + 4CF64D32052A3278008ED0EA /* acl_threshold.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CF64CEC052A3278008ED0EA /* acl_threshold.cpp */; }; + 4CF64D34052A3278008ED0EA /* callback.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CF64CEE052A3278008ED0EA /* callback.cpp */; }; + 4CF64D38052A3278008ED0EA /* constdata.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CF64CF2052A3278008ED0EA /* constdata.cpp */; }; + 4CF64D3A052A3278008ED0EA /* context.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CF64CF4052A3278008ED0EA /* context.cpp */; }; + 4CF64D3C052A3278008ED0EA /* cssmacl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CF64CF6052A3278008ED0EA /* cssmacl.cpp */; }; + 4CF64D3E052A3278008ED0EA /* cssmaclpod.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CF64CF8052A3278008ED0EA /* cssmaclpod.cpp */; }; + 4CF64D40052A3278008ED0EA /* cssmalloc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CF64CFA052A3278008ED0EA /* cssmalloc.cpp */; }; + 4CF64D42052A3278008ED0EA /* cssmcert.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CF64CFC052A3278008ED0EA /* cssmcert.cpp */; }; + 4CF64D44052A3278008ED0EA /* cssmcred.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CF64CFE052A3278008ED0EA /* cssmcred.cpp */; }; + 4CF64D46052A3278008ED0EA /* cssmdata.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CF64D00052A3278008ED0EA /* cssmdata.cpp */; }; + 4CF64D48052A3278008ED0EA /* cssmdates.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CF64D02052A3278008ED0EA /* cssmdates.cpp */; }; + 4CF64D4C052A3278008ED0EA /* cssmendian.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CF64D06052A3278008ED0EA /* cssmendian.cpp */; }; + 4CF64D50052A3278008ED0EA /* cssmlist.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CF64D0A052A3278008ED0EA /* cssmlist.cpp */; }; + 4CF64D52052A3278008ED0EA /* cssmtrust.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CF64D0C052A3278008ED0EA /* cssmtrust.cpp */; }; + 4CF64D56052A3278008ED0EA /* cssmwalkers.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CF64D10052A3278008ED0EA /* cssmwalkers.cpp */; }; + 4CF64D58052A3278008ED0EA /* db++.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CF64D12052A3278008ED0EA /* db++.cpp */; }; + 4CF64D5B052A3278008ED0EA /* handleobject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CF64D15052A3278008ED0EA /* handleobject.cpp */; }; + 4CF64D68052A3278008ED0EA /* uniformrandom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CF64D22052A3278008ED0EA /* uniformrandom.cpp */; }; + 4CF64D6A052A3278008ED0EA /* walkers.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CF64D24052A3278008ED0EA /* walkers.cpp */; }; + 4EE92EA30E2415C100F97B89 /* handletemplates.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4EE92EA20E2415C100F97B89 /* handletemplates.cpp */; }; + B61D0F910E0CF46700EC386B /* u32handleobject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B61D0F8F0E0CF46700EC386B /* u32handleobject.cpp */; }; + C21A3EC40545BEFA00C40B2E /* cssmkey.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C21A3EBF0545BEFA00C40B2E /* cssmkey.cpp */; }; + C21A3EC60545BEFA00C40B2E /* cssmpods.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C21A3EC10545BEFA00C40B2E /* cssmpods.cpp */; }; + C2371E4006DD3E5E00E15E6F /* acl_preauth.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2371E3E06DD3E5E00E15E6F /* acl_preauth.cpp */; }; + C2BFD03406E6CDFE0047EA99 /* aclsubject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2BFD03006E6CDFE0047EA99 /* aclsubject.cpp */; }; + C2BFD03506E6CDFE0047EA99 /* objectacl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2BFD03206E6CDFE0047EA99 /* objectacl.cpp */; }; + C2BFD05C06E6D0560047EA99 /* acl_secret.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2BFD05A06E6D0560047EA99 /* acl_secret.cpp */; }; + C2BFD0E806E792410047EA99 /* acl_prompted.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2BFD0E606E792410047EA99 /* acl_prompted.cpp */; }; + C2C1DC550A2CD98A00D1B02B /* osxverifier.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2C1DC530A2CD98A00D1B02B /* osxverifier.cpp */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 182BB4ED146F2727000BF1F3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 182BB4E8146F2727000BF1F3 /* libsecurity_utilities.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 4CA2A53A0523D32800978A7B; + remoteInfo = libsecurity_utilities; + }; + 182BB4F0146F2734000BF1F3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 182BB4E8146F2727000BF1F3 /* libsecurity_utilities.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = C2C9C69D0CECBE8400B3FE07; + remoteInfo = libsecurity_utilitiesDTrace; + }; + 4C1E266E0540A5D5002A7E83 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4CA2A5330523D2CD00978A7B /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4CF9C5B80535E557009B9B8D; + remoteInfo = Schemas; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 182BB4E8146F2727000BF1F3 /* libsecurity_utilities.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libsecurity_utilities.xcodeproj; path = ../libsecurity_utilities/libsecurity_utilities.xcodeproj; sourceTree = ""; }; + 1879B515146DD045007E536C /* base.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = base.xcconfig; sourceTree = ""; }; + 1879B516146DD045007E536C /* debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = debug.xcconfig; sourceTree = ""; }; + 1879B517146DD045007E536C /* lib.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = lib.xcconfig; sourceTree = ""; }; + 1879B518146DD045007E536C /* release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = release.xcconfig; sourceTree = ""; }; + 4C088043053219880049BBEF /* cssmdb.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = cssmdb.cpp; sourceTree = ""; }; + 4C088044053219880049BBEF /* cssmdb.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cssmdb.h; sourceTree = ""; }; + 4C38951C0534B198009CF879 /* KeySchema.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = KeySchema.h; sourceTree = ""; }; + 4C38951D0534B198009CF879 /* KeySchema.m4 */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = KeySchema.m4; sourceTree = ""; }; + 4C3895400534B31D009CF879 /* KeySchema.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = KeySchema.cpp; sourceTree = ""; }; + 4C66D5E805321B2700537B59 /* cssmdbname.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = cssmdbname.cpp; sourceTree = ""; }; + 4C66D5E905321B2700537B59 /* cssmdbname.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cssmdbname.h; sourceTree = ""; }; + 4C838EA3058163A4006DA084 /* AuthorizationData.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = AuthorizationData.cpp; sourceTree = ""; }; + 4C838EA4058163A4006DA084 /* AuthorizationData.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = AuthorizationData.h; sourceTree = ""; }; + 4C838EA5058163A4006DA084 /* AuthorizationWalkers.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = AuthorizationWalkers.h; sourceTree = ""; }; + 4C96461A05378CCD00499C82 /* Schema.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Schema.h; sourceTree = ""; }; + 4C96461B05378CCD00499C82 /* Schema.m4 */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = Schema.m4; sourceTree = ""; }; + 4C96462005378CEE00499C82 /* Schema.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = Schema.cpp; sourceTree = ""; }; + 4CA2A53A0523D32800978A7B /* libsecurity_cdsa_utilities.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libsecurity_cdsa_utilities.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 4CF64CE0052A3278008ED0EA /* acl_any.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = acl_any.cpp; sourceTree = ""; }; + 4CF64CE1052A3278008ED0EA /* acl_any.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = acl_any.h; sourceTree = ""; }; + 4CF64CE2052A3278008ED0EA /* acl_codesigning.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = acl_codesigning.cpp; sourceTree = ""; }; + 4CF64CE3052A3278008ED0EA /* acl_codesigning.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = acl_codesigning.h; sourceTree = ""; }; + 4CF64CE4052A3278008ED0EA /* acl_comment.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = acl_comment.cpp; sourceTree = ""; }; + 4CF64CE5052A3278008ED0EA /* acl_comment.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = acl_comment.h; sourceTree = ""; }; + 4CF64CE6052A3278008ED0EA /* acl_password.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = acl_password.cpp; sourceTree = ""; }; + 4CF64CE7052A3278008ED0EA /* acl_password.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = acl_password.h; sourceTree = ""; }; + 4CF64CE8052A3278008ED0EA /* acl_process.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = acl_process.cpp; sourceTree = ""; }; + 4CF64CE9052A3278008ED0EA /* acl_process.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = acl_process.h; sourceTree = ""; }; + 4CF64CEA052A3278008ED0EA /* acl_protectedpw.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = acl_protectedpw.cpp; sourceTree = ""; }; + 4CF64CEB052A3278008ED0EA /* acl_protectedpw.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = acl_protectedpw.h; sourceTree = ""; }; + 4CF64CEC052A3278008ED0EA /* acl_threshold.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = acl_threshold.cpp; sourceTree = ""; }; + 4CF64CED052A3278008ED0EA /* acl_threshold.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = acl_threshold.h; sourceTree = ""; }; + 4CF64CEE052A3278008ED0EA /* callback.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = callback.cpp; sourceTree = ""; }; + 4CF64CEF052A3278008ED0EA /* callback.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = callback.h; sourceTree = ""; }; + 4CF64CF2052A3278008ED0EA /* constdata.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = constdata.cpp; sourceTree = ""; }; + 4CF64CF3052A3278008ED0EA /* constdata.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = constdata.h; sourceTree = ""; }; + 4CF64CF4052A3278008ED0EA /* context.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = context.cpp; sourceTree = ""; }; + 4CF64CF5052A3278008ED0EA /* context.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = context.h; sourceTree = ""; }; + 4CF64CF6052A3278008ED0EA /* cssmacl.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = cssmacl.cpp; sourceTree = ""; }; + 4CF64CF7052A3278008ED0EA /* cssmacl.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cssmacl.h; sourceTree = ""; }; + 4CF64CF8052A3278008ED0EA /* cssmaclpod.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = cssmaclpod.cpp; sourceTree = ""; }; + 4CF64CF9052A3278008ED0EA /* cssmaclpod.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cssmaclpod.h; sourceTree = ""; }; + 4CF64CFA052A3278008ED0EA /* cssmalloc.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = cssmalloc.cpp; sourceTree = ""; }; + 4CF64CFB052A3278008ED0EA /* cssmalloc.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cssmalloc.h; sourceTree = ""; }; + 4CF64CFC052A3278008ED0EA /* cssmcert.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = cssmcert.cpp; sourceTree = ""; }; + 4CF64CFD052A3278008ED0EA /* cssmcert.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cssmcert.h; sourceTree = ""; }; + 4CF64CFE052A3278008ED0EA /* cssmcred.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = cssmcred.cpp; sourceTree = ""; }; + 4CF64CFF052A3278008ED0EA /* cssmcred.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cssmcred.h; sourceTree = ""; }; + 4CF64D00052A3278008ED0EA /* cssmdata.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = cssmdata.cpp; sourceTree = ""; }; + 4CF64D01052A3278008ED0EA /* cssmdata.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cssmdata.h; sourceTree = ""; }; + 4CF64D02052A3278008ED0EA /* cssmdates.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = cssmdates.cpp; sourceTree = ""; }; + 4CF64D03052A3278008ED0EA /* cssmdates.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cssmdates.h; sourceTree = ""; }; + 4CF64D06052A3278008ED0EA /* cssmendian.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = cssmendian.cpp; sourceTree = ""; }; + 4CF64D07052A3278008ED0EA /* cssmendian.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cssmendian.h; sourceTree = ""; }; + 4CF64D0A052A3278008ED0EA /* cssmlist.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = cssmlist.cpp; sourceTree = ""; }; + 4CF64D0B052A3278008ED0EA /* cssmlist.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cssmlist.h; sourceTree = ""; }; + 4CF64D0C052A3278008ED0EA /* cssmtrust.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = cssmtrust.cpp; sourceTree = ""; }; + 4CF64D0D052A3278008ED0EA /* cssmtrust.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cssmtrust.h; sourceTree = ""; }; + 4CF64D10052A3278008ED0EA /* cssmwalkers.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = cssmwalkers.cpp; sourceTree = ""; }; + 4CF64D11052A3278008ED0EA /* cssmwalkers.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cssmwalkers.h; sourceTree = ""; }; + 4CF64D12052A3278008ED0EA /* db++.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = "db++.cpp"; sourceTree = ""; }; + 4CF64D13052A3278008ED0EA /* db++.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = "db++.h"; sourceTree = ""; }; + 4CF64D14052A3278008ED0EA /* digestobject.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = digestobject.h; sourceTree = ""; }; + 4CF64D15052A3278008ED0EA /* handleobject.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = handleobject.cpp; sourceTree = ""; }; + 4CF64D16052A3278008ED0EA /* handleobject.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = handleobject.h; sourceTree = ""; }; + 4CF64D22052A3278008ED0EA /* uniformrandom.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = uniformrandom.cpp; sourceTree = ""; }; + 4CF64D23052A3278008ED0EA /* uniformrandom.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = uniformrandom.h; sourceTree = ""; }; + 4CF64D24052A3278008ED0EA /* walkers.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = walkers.cpp; sourceTree = ""; }; + 4CF64D25052A3278008ED0EA /* walkers.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = walkers.h; sourceTree = ""; }; + 4CF9C5B90535E557009B9B8D /* Schemas */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; path = Schemas; sourceTree = BUILT_PRODUCTS_DIR; }; + 4E494DA80E0B084900026B9C /* handletemplates.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = handletemplates.h; sourceTree = ""; }; + 4E494DA90E0B084900026B9C /* handletemplates_defs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = handletemplates_defs.h; sourceTree = ""; }; + 4EE92EA20E2415C100F97B89 /* handletemplates.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = handletemplates.cpp; sourceTree = ""; }; + B61D0F8F0E0CF46700EC386B /* u32handleobject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = u32handleobject.cpp; sourceTree = ""; }; + B61D0F900E0CF46700EC386B /* u32handleobject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = u32handleobject.h; sourceTree = ""; }; + C21A3EBE0545BEFA00C40B2E /* cssmbridge.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cssmbridge.h; sourceTree = ""; }; + C21A3EBF0545BEFA00C40B2E /* cssmkey.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = cssmkey.cpp; sourceTree = ""; }; + C21A3EC00545BEFA00C40B2E /* cssmkey.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cssmkey.h; sourceTree = ""; }; + C21A3EC10545BEFA00C40B2E /* cssmpods.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = cssmpods.cpp; sourceTree = ""; }; + C21A3EC20545BEFA00C40B2E /* cssmpods.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cssmpods.h; sourceTree = ""; }; + C22EC429052B8E4900D55C69 /* cssmerrors.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = cssmerrors.cpp; sourceTree = ""; }; + C22EC42A052B8E4900D55C69 /* cssmerrors.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cssmerrors.h; sourceTree = ""; }; + C2371E3E06DD3E5E00E15E6F /* acl_preauth.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = acl_preauth.cpp; sourceTree = ""; }; + C2371E3F06DD3E5E00E15E6F /* acl_preauth.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = acl_preauth.h; sourceTree = ""; }; + C2BFD03006E6CDFE0047EA99 /* aclsubject.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = aclsubject.cpp; sourceTree = ""; }; + C2BFD03106E6CDFE0047EA99 /* aclsubject.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = aclsubject.h; sourceTree = ""; }; + C2BFD03206E6CDFE0047EA99 /* objectacl.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = objectacl.cpp; sourceTree = ""; }; + C2BFD03306E6CDFE0047EA99 /* objectacl.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = objectacl.h; sourceTree = ""; }; + C2BFD05A06E6D0560047EA99 /* acl_secret.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = acl_secret.cpp; sourceTree = ""; }; + C2BFD05B06E6D0560047EA99 /* acl_secret.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = acl_secret.h; sourceTree = ""; }; + C2BFD0E606E792410047EA99 /* acl_prompted.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = acl_prompted.cpp; sourceTree = ""; }; + C2BFD0E706E792410047EA99 /* acl_prompted.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = acl_prompted.h; sourceTree = ""; }; + C2C1DC530A2CD98A00D1B02B /* osxverifier.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = osxverifier.cpp; sourceTree = ""; }; + C2C1DC540A2CD98A00D1B02B /* osxverifier.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = osxverifier.h; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 4CA2A5370523D32800978A7B /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 182BB4E9146F2727000BF1F3 /* Products */ = { + isa = PBXGroup; + children = ( + 182BB4EE146F2727000BF1F3 /* libsecurity_utilities.a */, + ); + name = Products; + sourceTree = ""; + }; + 1879B514146DD045007E536C /* config */ = { + isa = PBXGroup; + children = ( + 1879B515146DD045007E536C /* base.xcconfig */, + 1879B516146DD045007E536C /* debug.xcconfig */, + 1879B517146DD045007E536C /* lib.xcconfig */, + 1879B518146DD045007E536C /* release.xcconfig */, + ); + name = config; + path = ../config; + sourceTree = ""; + }; + 4C38953B0534B2FD009CF879 /* derived_src */ = { + isa = PBXGroup; + children = ( + 4C3895400534B31D009CF879 /* KeySchema.cpp */, + 4C96462005378CEE00499C82 /* Schema.cpp */, + ); + path = derived_src; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 4CA2A52F0523D2CD00978A7B = { + isa = PBXGroup; + children = ( + 182BB4E8146F2727000BF1F3 /* libsecurity_utilities.xcodeproj */, + 4CF64CDB052A3236008ED0EA /* lib */, + 1879B514146DD045007E536C /* config */, + 4C38953B0534B2FD009CF879 /* derived_src */, + 4CA2A53B0523D32800978A7B /* Products */, + ); + sourceTree = ""; + }; + 4CA2A53B0523D32800978A7B /* Products */ = { + isa = PBXGroup; + children = ( + 4CA2A53A0523D32800978A7B /* libsecurity_cdsa_utilities.a */, + 4CF9C5B90535E557009B9B8D /* Schemas */, + ); + name = Products; + sourceTree = ""; + }; + 4CF64CDB052A3236008ED0EA /* lib */ = { + isa = PBXGroup; + children = ( + C29CE2B906DD5BD60051AFA9 /* ACLs */, + 4C838EA3058163A4006DA084 /* AuthorizationData.cpp */, + 4C838EA4058163A4006DA084 /* AuthorizationData.h */, + 4C838EA5058163A4006DA084 /* AuthorizationWalkers.h */, + 4CF64CEE052A3278008ED0EA /* callback.cpp */, + 4CF64CEF052A3278008ED0EA /* callback.h */, + 4CF64CF2052A3278008ED0EA /* constdata.cpp */, + 4CF64CF3052A3278008ED0EA /* constdata.h */, + 4CF64CF4052A3278008ED0EA /* context.cpp */, + 4CF64CF5052A3278008ED0EA /* context.h */, + 4CF64CF8052A3278008ED0EA /* cssmaclpod.cpp */, + 4CF64CF9052A3278008ED0EA /* cssmaclpod.h */, + 4CF64CFA052A3278008ED0EA /* cssmalloc.cpp */, + 4CF64CFB052A3278008ED0EA /* cssmalloc.h */, + C21A3EBE0545BEFA00C40B2E /* cssmbridge.h */, + 4CF64CFC052A3278008ED0EA /* cssmcert.cpp */, + 4CF64CFD052A3278008ED0EA /* cssmcert.h */, + 4CF64CFE052A3278008ED0EA /* cssmcred.cpp */, + 4CF64CFF052A3278008ED0EA /* cssmcred.h */, + 4CF64D00052A3278008ED0EA /* cssmdata.cpp */, + 4CF64D01052A3278008ED0EA /* cssmdata.h */, + 4CF64D02052A3278008ED0EA /* cssmdates.cpp */, + 4CF64D03052A3278008ED0EA /* cssmdates.h */, + 4C088043053219880049BBEF /* cssmdb.cpp */, + 4C088044053219880049BBEF /* cssmdb.h */, + 4C66D5E805321B2700537B59 /* cssmdbname.cpp */, + 4C66D5E905321B2700537B59 /* cssmdbname.h */, + 4CF64D06052A3278008ED0EA /* cssmendian.cpp */, + 4CF64D07052A3278008ED0EA /* cssmendian.h */, + C22EC429052B8E4900D55C69 /* cssmerrors.cpp */, + C22EC42A052B8E4900D55C69 /* cssmerrors.h */, + C21A3EBF0545BEFA00C40B2E /* cssmkey.cpp */, + C21A3EC00545BEFA00C40B2E /* cssmkey.h */, + 4CF64D0A052A3278008ED0EA /* cssmlist.cpp */, + 4CF64D0B052A3278008ED0EA /* cssmlist.h */, + C21A3EC10545BEFA00C40B2E /* cssmpods.cpp */, + C21A3EC20545BEFA00C40B2E /* cssmpods.h */, + 4CF64D0C052A3278008ED0EA /* cssmtrust.cpp */, + 4CF64D0D052A3278008ED0EA /* cssmtrust.h */, + 4CF64D10052A3278008ED0EA /* cssmwalkers.cpp */, + 4CF64D11052A3278008ED0EA /* cssmwalkers.h */, + 4CF64D12052A3278008ED0EA /* db++.cpp */, + 4CF64D13052A3278008ED0EA /* db++.h */, + 4CF64D14052A3278008ED0EA /* digestobject.h */, + 4CF64D15052A3278008ED0EA /* handleobject.cpp */, + 4CF64D16052A3278008ED0EA /* handleobject.h */, + 4EE92EA20E2415C100F97B89 /* handletemplates.cpp */, + 4E494DA80E0B084900026B9C /* handletemplates.h */, + 4E494DA90E0B084900026B9C /* handletemplates_defs.h */, + 4C38951C0534B198009CF879 /* KeySchema.h */, + 4C38951D0534B198009CF879 /* KeySchema.m4 */, + 4C96461A05378CCD00499C82 /* Schema.h */, + 4C96461B05378CCD00499C82 /* Schema.m4 */, + C2C1DC530A2CD98A00D1B02B /* osxverifier.cpp */, + C2C1DC540A2CD98A00D1B02B /* osxverifier.h */, + B61D0F8F0E0CF46700EC386B /* u32handleobject.cpp */, + B61D0F900E0CF46700EC386B /* u32handleobject.h */, + 4CF64D22052A3278008ED0EA /* uniformrandom.cpp */, + 4CF64D23052A3278008ED0EA /* uniformrandom.h */, + 4CF64D24052A3278008ED0EA /* walkers.cpp */, + 4CF64D25052A3278008ED0EA /* walkers.h */, + ); + path = lib; + sourceTree = ""; + }; + C29CE2B906DD5BD60051AFA9 /* ACLs */ = { + isa = PBXGroup; + children = ( + C2BFD03306E6CDFE0047EA99 /* objectacl.h */, + C2BFD03206E6CDFE0047EA99 /* objectacl.cpp */, + C2BFD03106E6CDFE0047EA99 /* aclsubject.h */, + C2BFD03006E6CDFE0047EA99 /* aclsubject.cpp */, + 4CF64CF7052A3278008ED0EA /* cssmacl.h */, + 4CF64CF6052A3278008ED0EA /* cssmacl.cpp */, + C2BFD02B06E6CDE10047EA99 /* Subjects */, + ); + name = ACLs; + sourceTree = ""; + }; + C2BFD02B06E6CDE10047EA99 /* Subjects */ = { + isa = PBXGroup; + children = ( + 4CF64CE0052A3278008ED0EA /* acl_any.cpp */, + 4CF64CE1052A3278008ED0EA /* acl_any.h */, + 4CF64CE2052A3278008ED0EA /* acl_codesigning.cpp */, + 4CF64CE3052A3278008ED0EA /* acl_codesigning.h */, + 4CF64CE4052A3278008ED0EA /* acl_comment.cpp */, + 4CF64CE5052A3278008ED0EA /* acl_comment.h */, + 4CF64CE6052A3278008ED0EA /* acl_password.cpp */, + 4CF64CE7052A3278008ED0EA /* acl_password.h */, + C2371E3E06DD3E5E00E15E6F /* acl_preauth.cpp */, + C2371E3F06DD3E5E00E15E6F /* acl_preauth.h */, + 4CF64CE8052A3278008ED0EA /* acl_process.cpp */, + 4CF64CE9052A3278008ED0EA /* acl_process.h */, + C2BFD0E606E792410047EA99 /* acl_prompted.cpp */, + C2BFD0E706E792410047EA99 /* acl_prompted.h */, + 4CF64CEA052A3278008ED0EA /* acl_protectedpw.cpp */, + 4CF64CEB052A3278008ED0EA /* acl_protectedpw.h */, + C2BFD05A06E6D0560047EA99 /* acl_secret.cpp */, + C2BFD05B06E6D0560047EA99 /* acl_secret.h */, + 4CF64CEC052A3278008ED0EA /* acl_threshold.cpp */, + 4CF64CED052A3278008ED0EA /* acl_threshold.h */, + ); + name = Subjects; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 1865FBEF1472410900FD79DF /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 1865FBF01472415600FD79DF /* objectacl.h in Headers */, + 1865FBF11472415600FD79DF /* aclsubject.h in Headers */, + 1865FBF21472415600FD79DF /* cssmacl.h in Headers */, + 1865FBF31472415600FD79DF /* acl_any.h in Headers */, + 1865FBF41472415600FD79DF /* acl_codesigning.h in Headers */, + 1865FBF51472415600FD79DF /* acl_comment.h in Headers */, + 1865FBF61472415600FD79DF /* acl_password.h in Headers */, + 1865FBF71472415600FD79DF /* acl_preauth.h in Headers */, + 1865FBF81472415600FD79DF /* acl_process.h in Headers */, + 1865FBF91472415600FD79DF /* acl_prompted.h in Headers */, + 1865FBFA1472415600FD79DF /* acl_protectedpw.h in Headers */, + 1865FBFB1472415600FD79DF /* acl_secret.h in Headers */, + 1865FBFC1472415600FD79DF /* acl_threshold.h in Headers */, + 1865FBFD1472415600FD79DF /* AuthorizationData.h in Headers */, + 1865FBFE1472415600FD79DF /* AuthorizationWalkers.h in Headers */, + 1865FBFF1472415600FD79DF /* callback.h in Headers */, + 1865FC001472415600FD79DF /* constdata.h in Headers */, + 1865FC011472415600FD79DF /* context.h in Headers */, + 1865FC021472415600FD79DF /* cssmaclpod.h in Headers */, + 1865FC031472415600FD79DF /* cssmalloc.h in Headers */, + 1865FC041472415600FD79DF /* cssmbridge.h in Headers */, + 1865FC051472415600FD79DF /* cssmcert.h in Headers */, + 1865FC061472415600FD79DF /* cssmcred.h in Headers */, + 1865FC071472415600FD79DF /* cssmdata.h in Headers */, + 1865FC081472415600FD79DF /* cssmdates.h in Headers */, + 1865FC091472415600FD79DF /* cssmdb.h in Headers */, + 1865FC0A1472415600FD79DF /* cssmdbname.h in Headers */, + 1865FC0B1472415600FD79DF /* cssmendian.h in Headers */, + 1865FC0C1472415600FD79DF /* cssmerrors.h in Headers */, + 1865FC0D1472415600FD79DF /* cssmkey.h in Headers */, + 1865FC0E1472415600FD79DF /* cssmlist.h in Headers */, + 1865FC0F1472415600FD79DF /* cssmpods.h in Headers */, + 1865FC101472415600FD79DF /* cssmtrust.h in Headers */, + 1865FC111472415600FD79DF /* cssmwalkers.h in Headers */, + 1865FC121472415600FD79DF /* db++.h in Headers */, + 1865FC131472415600FD79DF /* digestobject.h in Headers */, + 1865FC141472415600FD79DF /* handleobject.h in Headers */, + 1865FC151472415600FD79DF /* handletemplates.h in Headers */, + 1865FC161472415600FD79DF /* handletemplates_defs.h in Headers */, + 1865FC171472415600FD79DF /* KeySchema.h in Headers */, + 1865FC181472415600FD79DF /* Schema.h in Headers */, + 1865FC191472415600FD79DF /* osxverifier.h in Headers */, + 1865FC1A1472415600FD79DF /* u32handleobject.h in Headers */, + 1865FC1B1472415700FD79DF /* uniformrandom.h in Headers */, + 1865FC1C1472415700FD79DF /* walkers.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 4CA2A5390523D32800978A7B /* libsecurity_cdsa_utilities */ = { + isa = PBXNativeTarget; + buildConfigurationList = C27AD2F60987FCDD001272E0 /* Build configuration list for PBXNativeTarget "libsecurity_cdsa_utilities" */; + buildPhases = ( + 1865FBEF1472410900FD79DF /* Headers */, + 4CA2A5360523D32800978A7B /* Sources */, + 4CA2A5370523D32800978A7B /* Frameworks */, + 18B96B0114743F65005A4D2E /* ShellScript */, + ); + buildRules = ( + ); + dependencies = ( + 182BB4F1146F2734000BF1F3 /* PBXTargetDependency */, + 4CFF43000535E5E900638F31 /* PBXTargetDependency */, + ); + name = libsecurity_cdsa_utilities; + productName = libsecurity_cdsa_utilities.a; + productReference = 4CA2A53A0523D32800978A7B /* libsecurity_cdsa_utilities.a */; + productType = "com.apple.product-type.library.static"; + }; + 4CF9C5B80535E557009B9B8D /* Schemas */ = { + isa = PBXNativeTarget; + buildConfigurationList = C27AD2F20987FCDD001272E0 /* Build configuration list for PBXNativeTarget "Schemas" */; + buildPhases = ( + 4CFF42FC0535E5B100638F31 /* ShellScript */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Schemas; + productInstallPath = /usr/local/bin; + productName = KeySchema; + productReference = 4CF9C5B90535E557009B9B8D /* Schemas */; + productType = "com.apple.product-type.tool"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 4CA2A5330523D2CD00978A7B /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0420; + }; + buildConfigurationList = C27AD2FA0987FCDD001272E0 /* Build configuration list for PBXProject "libsecurity_cdsa_utilities" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 1; + knownRegions = ( + English, + Japanese, + French, + German, + ); + mainGroup = 4CA2A52F0523D2CD00978A7B; + productRefGroup = 4CA2A53B0523D32800978A7B /* Products */; + projectDirPath = ""; + projectReferences = ( + { + ProductGroup = 182BB4E9146F2727000BF1F3 /* Products */; + ProjectRef = 182BB4E8146F2727000BF1F3 /* libsecurity_utilities.xcodeproj */; + }, + ); + projectRoot = ""; + targets = ( + 4CA2A5390523D32800978A7B /* libsecurity_cdsa_utilities */, + 4CF9C5B80535E557009B9B8D /* Schemas */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXReferenceProxy section */ + 182BB4EE146F2727000BF1F3 /* libsecurity_utilities.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libsecurity_utilities.a; + remoteRef = 182BB4ED146F2727000BF1F3 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; +/* End PBXReferenceProxy section */ + +/* Begin PBXShellScriptBuildPhase section */ + 18B96B0114743F65005A4D2E /* 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}\""; + }; + 4CFF42FC0535E5B100638F31 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "TARGET=$BUILT_PRODUCTS_DIR/derived_src/KeySchema.cpp\nmkdir -p $BUILT_PRODUCTS_DIR/derived_src\n/usr/bin/m4 lib/KeySchema.m4 > $TARGET.new\ncmp -s $TARGET.new $TARGET || mv $TARGET.new $TARGET\nTARGET=$BUILT_PRODUCTS_DIR/derived_src/Schema.cpp\n/usr/bin/m4 lib/Schema.m4 > $TARGET.new\ncmp -s $TARGET.new $TARGET || mv $TARGET.new $TARGET"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 4CA2A5360523D32800978A7B /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4CF64D26052A3278008ED0EA /* acl_any.cpp in Sources */, + 4CF64D28052A3278008ED0EA /* acl_codesigning.cpp in Sources */, + 4CF64D2A052A3278008ED0EA /* acl_comment.cpp in Sources */, + 4CF64D2C052A3278008ED0EA /* acl_password.cpp in Sources */, + 4CF64D2E052A3278008ED0EA /* acl_process.cpp in Sources */, + 4CF64D30052A3278008ED0EA /* acl_protectedpw.cpp in Sources */, + 4CF64D32052A3278008ED0EA /* acl_threshold.cpp in Sources */, + 4CF64D34052A3278008ED0EA /* callback.cpp in Sources */, + 4CF64D38052A3278008ED0EA /* constdata.cpp in Sources */, + 4CF64D3A052A3278008ED0EA /* context.cpp in Sources */, + 4CF64D3C052A3278008ED0EA /* cssmacl.cpp in Sources */, + 4CF64D3E052A3278008ED0EA /* cssmaclpod.cpp in Sources */, + 4CF64D40052A3278008ED0EA /* cssmalloc.cpp in Sources */, + 4CF64D42052A3278008ED0EA /* cssmcert.cpp in Sources */, + 4CF64D44052A3278008ED0EA /* cssmcred.cpp in Sources */, + 4CF64D46052A3278008ED0EA /* cssmdata.cpp in Sources */, + 4CF64D48052A3278008ED0EA /* cssmdates.cpp in Sources */, + 4C088047053219880049BBEF /* cssmdb.cpp in Sources */, + 4C66D5EA05321B2700537B59 /* cssmdbname.cpp in Sources */, + 4CF64D4C052A3278008ED0EA /* cssmendian.cpp in Sources */, + 4C92661705349551004B0E72 /* cssmerrors.cpp in Sources */, + 4CF64D50052A3278008ED0EA /* cssmlist.cpp in Sources */, + 4CF64D52052A3278008ED0EA /* cssmtrust.cpp in Sources */, + 4CF64D56052A3278008ED0EA /* cssmwalkers.cpp in Sources */, + 4CF64D58052A3278008ED0EA /* db++.cpp in Sources */, + 4CF64D5B052A3278008ED0EA /* handleobject.cpp in Sources */, + 4EE92EA30E2415C100F97B89 /* handletemplates.cpp in Sources */, + 4C3895410534B31D009CF879 /* KeySchema.cpp in Sources */, + 4C96462105378CEE00499C82 /* Schema.cpp in Sources */, + 4CF64D68052A3278008ED0EA /* uniformrandom.cpp in Sources */, + 4CF64D6A052A3278008ED0EA /* walkers.cpp in Sources */, + C21A3EC40545BEFA00C40B2E /* cssmkey.cpp in Sources */, + C21A3EC60545BEFA00C40B2E /* cssmpods.cpp in Sources */, + 4C838EA6058163A4006DA084 /* AuthorizationData.cpp in Sources */, + 4C838EA7058163A4006DA084 /* AuthorizationData.h in Sources */, + 4C838EA8058163A4006DA084 /* AuthorizationWalkers.h in Sources */, + C2371E4006DD3E5E00E15E6F /* acl_preauth.cpp in Sources */, + C2BFD03406E6CDFE0047EA99 /* aclsubject.cpp in Sources */, + C2BFD03506E6CDFE0047EA99 /* objectacl.cpp in Sources */, + C2BFD05C06E6D0560047EA99 /* acl_secret.cpp in Sources */, + C2BFD0E806E792410047EA99 /* acl_prompted.cpp in Sources */, + C2C1DC550A2CD98A00D1B02B /* osxverifier.cpp in Sources */, + B61D0F910E0CF46700EC386B /* u32handleobject.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 182BB4F1146F2734000BF1F3 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = libsecurity_utilitiesDTrace; + targetProxy = 182BB4F0146F2734000BF1F3 /* PBXContainerItemProxy */; + }; + 4CFF43000535E5E900638F31 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 4CF9C5B80535E557009B9B8D /* Schemas */; + targetProxy = 4C1E266E0540A5D5002A7E83 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + C27AD2F30987FCDD001272E0 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + }; + name = Debug; + }; + C27AD2F50987FCDD001272E0 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + }; + name = Release; + }; + C27AD2F70987FCDD001272E0 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1879B516146DD045007E536C /* debug.xcconfig */; + buildSettings = { + PUBLIC_HEADERS_FOLDER_PATH = /usr/local/include/security_cdsa_utilities; + SKIP_INSTALL = NO; + }; + name = Debug; + }; + C27AD2F90987FCDD001272E0 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1879B518146DD045007E536C /* release.xcconfig */; + buildSettings = { + PUBLIC_HEADERS_FOLDER_PATH = /usr/local/include/security_cdsa_utilities; + SKIP_INSTALL = NO; + }; + name = Release; + }; + C27AD2FB0987FCDD001272E0 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1879B517146DD045007E536C /* lib.xcconfig */; + buildSettings = { + }; + name = Debug; + }; + C27AD2FD0987FCDD001272E0 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1879B517146DD045007E536C /* lib.xcconfig */; + buildSettings = { + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + C27AD2F20987FCDD001272E0 /* Build configuration list for PBXNativeTarget "Schemas" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C27AD2F30987FCDD001272E0 /* Debug */, + C27AD2F50987FCDD001272E0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C27AD2F60987FCDD001272E0 /* Build configuration list for PBXNativeTarget "libsecurity_cdsa_utilities" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C27AD2F70987FCDD001272E0 /* Debug */, + C27AD2F90987FCDD001272E0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C27AD2FA0987FCDD001272E0 /* Build configuration list for PBXProject "libsecurity_cdsa_utilities" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C27AD2FB0987FCDD001272E0 /* Debug */, + C27AD2FD0987FCDD001272E0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 4CA2A5330523D2CD00978A7B /* Project object */; +} diff --git a/libsecurity_cdsa_utils/Info-security_cdsa_utils.plist b/libsecurity_cdsa_utils/Info-security_cdsa_utils.plist new file mode 100644 index 00000000..0c67376e --- /dev/null +++ b/libsecurity_cdsa_utils/Info-security_cdsa_utils.plist @@ -0,0 +1,5 @@ + + + + + diff --git a/libsecurity_cdsa_utils/lib/cuCdsaUtils.cpp b/libsecurity_cdsa_utils/lib/cuCdsaUtils.cpp new file mode 100644 index 00000000..76c899c7 --- /dev/null +++ b/libsecurity_cdsa_utils/lib/cuCdsaUtils.cpp @@ -0,0 +1,777 @@ +/* + * Copyright (c) 2001-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. + */ + +/* + File: cuCdsaUtils.cpp + + Description: common CDSA access utilities + + Author: dmitch +*/ + +#include "cuCdsaUtils.h" +#include +#include +#include +#include /* for cssmPerror() */ +#include +#include +#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 * cuAppMalloc (CSSM_SIZE size, void *allocRef) { + return( malloc(size) ); +} + +void cuAppFree (void *mem_ptr, void *allocRef) { + free(mem_ptr); + return; +} + +void * cuAppRealloc (void *ptr, CSSM_SIZE size, void *allocRef) { + return( realloc( ptr, size ) ); +} + +void * cuAppCalloc (uint32 num, CSSM_SIZE size, void *allocRef) { + return( calloc( num, size ) ); +} + +static CSSM_API_MEMORY_FUNCS memFuncs = { + cuAppMalloc, + cuAppFree, + cuAppRealloc, + cuAppCalloc, + NULL + }; + +CSSM_BOOL cuCompareCssmData(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 cuCssmStartup() +{ + 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) + { + cuPrintError("CSSM_Init", crtn); + return CSSM_FALSE; + } + else { + cssmInitd = CSSM_TRUE; + return CSSM_TRUE; + } +} + +/* + * Attach to CSP. Returns zero on error. + */ +CSSM_CSP_HANDLE cuCspStartup( + CSSM_BOOL bareCsp) // true ==> CSP, false ==> CSP/DL +{ + CSSM_CSP_HANDLE cspHand; + CSSM_RETURN crtn; + const CSSM_GUID *guid; + + /* common CSSM init */ + if(cuCssmStartup() == 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) { + cuPrintError("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) { + cuPrintError("CSSM_ModuleAttach()", crtn); + return 0; + } + return cspHand; +} + +/* Attach to DL side of CSPDL */ +CSSM_DL_HANDLE cuDlStartup() +{ + CSSM_DL_HANDLE dlHand = 0; + CSSM_RETURN crtn; + + if(cuCssmStartup() == CSSM_FALSE) { + return 0; + } + crtn = CSSM_ModuleLoad(&gGuidAppleCSPDL, + CSSM_KEY_HIERARCHY_NONE, + NULL, // eventHandler + NULL); // AppNotifyCallbackCtx + if(crtn) { + cuPrintError("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) { + cuPrintError("CSSM_ModuleAttach(Apple CSPDL)", crtn); + return 0; + } + return dlHand; +} + +CSSM_CL_HANDLE cuClStartup() +{ + CSSM_CL_HANDLE clHand; + CSSM_RETURN crtn; + + if(cuCssmStartup() == CSSM_FALSE) { + return 0; + } + crtn = CSSM_ModuleLoad(&gGuidAppleX509CL, + CSSM_KEY_HIERARCHY_NONE, + NULL, // eventHandler + NULL); // AppNotifyCallbackCtx + if(crtn) { + cuPrintError("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) { + cuPrintError("CSSM_ModuleAttach(AppleCL)", crtn); + return 0; + } + else { + return clHand; + } +} + +CSSM_TP_HANDLE cuTpStartup() +{ + CSSM_TP_HANDLE tpHand; + CSSM_RETURN crtn; + + if(cuCssmStartup() == CSSM_FALSE) { + return 0; + } + crtn = CSSM_ModuleLoad(&gGuidAppleX509TP, + CSSM_KEY_HIERARCHY_NONE, + NULL, // eventHandler + NULL); // AppNotifyCallbackCtx + if(crtn) { + cuPrintError("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) { + cuPrintError("CSSM_ModuleAttach(AppleTP)", crtn); + return 0; + } + else { + return tpHand; + } +} + +/* detach and unload */ +CSSM_RETURN cuCspDetachUnload( + CSSM_CSP_HANDLE cspHand, + CSSM_BOOL bareCsp) // true ==> CSP, false ==> CSP/DL +{ + CSSM_RETURN crtn = CSSM_ModuleDetach(cspHand); + if(crtn) { + return crtn; + } + const CSSM_GUID *guid; + if(bareCsp) { + guid = &gGuidAppleCSP; + } + else { + guid = &gGuidAppleCSPDL; + } + return CSSM_ModuleUnload(guid, NULL, NULL); +} + +CSSM_RETURN cuClDetachUnload( + CSSM_CL_HANDLE clHand) +{ + CSSM_RETURN crtn = CSSM_ModuleDetach(clHand); + if(crtn) { + return crtn; + } + return CSSM_ModuleUnload(&gGuidAppleX509CL, NULL, NULL); + +} + +CSSM_RETURN cuDlDetachUnload( + CSSM_DL_HANDLE dlHand) +{ + CSSM_RETURN crtn = CSSM_ModuleDetach(dlHand); + if(crtn) { + return crtn; + } + return CSSM_ModuleUnload(&gGuidAppleCSPDL, NULL, NULL); + +} +CSSM_RETURN cuTpDetachUnload( + CSSM_TP_HANDLE tpHand) +{ + CSSM_RETURN crtn = CSSM_ModuleDetach(tpHand); + if(crtn) { + return crtn; + } + return CSSM_ModuleUnload(&gGuidAppleX509TP, NULL, NULL); + +} + +/* + * open a DB, ensure it's empty. + */ +CSSM_DB_HANDLE cuDbStartup( + CSSM_DL_HANDLE dlHand, // from dlStartup() + const char *dbName) +{ + CSSM_DB_HANDLE dbHand = 0; + CSSM_RETURN crtn; + CSSM_DBINFO dbInfo; + + /* first delete possible existing DB, ignore error */ + crtn = CSSM_DL_DbDelete(dlHand, dbName, NULL, NULL); + switch(crtn) { + /* only allowed error is "no such file" */ + case CSSM_OK: + case CSSMERR_DL_DATASTORE_DOESNOT_EXIST: + break; + default: + cuPrintError("CSSM_DL_DbDelete", crtn); + return 0; + } + + memset(&dbInfo, 0, sizeof(CSSM_DBINFO)); + + /* now create it */ + crtn = CSSM_DL_DbCreate(dlHand, + dbName, + NULL, // DbLocation + &dbInfo, + // &Security::KeychainCore::Schema::DBInfo, + CSSM_DB_ACCESS_PRIVILEGED, + NULL, // CredAndAclEntry + NULL, // OpenParameters + &dbHand); + if(crtn) { + cuPrintError("CSSM_DL_DbCreate", crtn); + } + return dbHand; +} + +/* + * Attach to existing DB or create an empty new one. + */ +CSSM_DB_HANDLE cuDbStartupByName(CSSM_DL_HANDLE dlHand, + char *dbName, + CSSM_BOOL doCreate, + CSSM_BOOL quiet) +{ + CSSM_RETURN crtn; + CSSM_DB_HANDLE dbHand; + + /* try 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(crtn == CSSM_OK) { + return dbHand; + } + if(!doCreate) { + if(!quiet) { + printf("***no such data base (%s)\n", dbName); + cuPrintError("CSSM_DL_DbOpen", crtn); + } + return 0; + } + /* have to create one */ + return cuDbStartup(dlHand, dbName); +} + +/* + * 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 cuAddContextAttribute(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) { + cuPrintError("CSSM_UpdateContextAttributes", crtn); + } + return crtn; +} + + +/* + * Derive symmetric key. + * Note in the X CSP, we never return an IV. + */ +CSSM_RETURN cuCspDeriveKey(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) { + cuPrintError("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) { + cuPrintError("CSSM_DeriveKey", crtn); + return crtn; + } + crtn = CSSM_DeleteContext(ccHand); + if(crtn) { + cuPrintError("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 cuCspGenKeyPair(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) { + cuPrintError("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) { + cuPrintError("CSSM_GenerateAlgorithmParams", crtn); + CSSM_DeleteContext(ccHand); + return crtn; + } + cuAppFree(dummy.Data, NULL); + } + break; + #endif /* DO_DSA_GEN_PARAMS */ + default: + break; + } + + /* optionally specify DL/DB storage location */ + if(dlDbHand) { + crtn = cuAddContextAttribute(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) { + cuPrintError("CSSM_GenerateKeyPair", ocrtn); + } + crtn = CSSM_DeleteContext(ccHand); + if(crtn) { + cuPrintError("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 cuAddCertToKC( + 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 cuDER_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 cuPrintError(const char *op, CSSM_RETURN err) +{ + cssmPerror(op, err); +} + +/* + * Verify a CRL against system anchors and intermediate certs. + */ +CSSM_RETURN cuCrlVerify( + CSSM_TP_HANDLE tpHand, + CSSM_CL_HANDLE clHand, + CSSM_CSP_HANDLE cspHand, + const CSSM_DATA *crlData, + CSSM_DL_DB_HANDLE_PTR certKeychain, // intermediate certs + const CSSM_DATA *anchors, // optional - if NULL, use Trust Settings + uint32 anchorCount) +{ + /* 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)); + 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; + */ + CSSM_FIELD policyId; + CSSM_APPLE_TP_CRL_OPTIONS crlOpts; + policyId.FieldOid = CSSMOID_APPLE_TP_REVOCATION_CRL; + policyId.FieldValue.Data = (uint8 *)&crlOpts; + policyId.FieldValue.Length = sizeof(crlOpts); + crlOpts.Version = CSSM_APPLE_TP_CRL_OPTS_VERSION; + /* perhaps this should be user-specifiable */ + crlOpts.CrlFlags = CSSM_TP_ACTION_FETCH_CRL_FROM_NET; + crlOpts.crlStore = NULL; + + authCtx.Policy.NumberOfPolicyIds = 1; + authCtx.Policy.PolicyIds = &policyId; + authCtx.Policy.PolicyControl = NULL; + + authCtx.VerifyTime = NULL; + authCtx.VerificationAbortOn = CSSM_TP_STOP_ON_POLICY; + authCtx.CallbackWithVerifiedCert = NULL; + + /* anchors */ + authCtx.NumberOfAnchorCerts = anchorCount; + authCtx.AnchorCerts = const_cast(anchors); + + /* DBList of intermediate certs, plus possible System.keychain and + * system roots */ + CSSM_DL_DB_HANDLE handles[3]; + unsigned numDbs = 0; + CSSM_DL_HANDLE dlHand = 0; + if(certKeychain != NULL) { + handles[0] = *certKeychain; + numDbs++; + } + if(anchors == NULL) { + /* Trust Settings requires two more DBs */ + if(numDbs == 0) { + /* new DL handle */ + dlHand = cuDlStartup(); + handles[numDbs].DLHandle = dlHand; + handles[numDbs + 1].DLHandle = dlHand; + } + else { + /* use the same one passed in for certKeychain */ + handles[numDbs].DLHandle = handles[0].DLHandle; + handles[numDbs + 1].DLHandle = handles[0].DLHandle; + } + handles[numDbs].DBHandle = cuDbStartupByName(handles[numDbs].DLHandle, + (char*) ADMIN_CERT_STORE_PATH, CSSM_FALSE, CSSM_TRUE); + numDbs++; + + handles[numDbs].DBHandle = cuDbStartupByName(handles[numDbs].DLHandle, + (char*) SYSTEM_ROOT_STORE_PATH, CSSM_FALSE, CSSM_TRUE); + numDbs++; + } + CSSM_DL_DB_LIST dlDbList; + dlDbList.DLDBHandle = handles; + dlDbList.NumHandles = numDbs; + + 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; + + /* CSSM_APPLE_TP_ACTION_DATA */ + CSSM_APPLE_TP_ACTION_DATA tpAction; + if(anchors == NULL) { + /* enable Trust Settings */ + tpAction.Version = CSSM_APPLE_TP_ACTION_VERSION; + tpAction.ActionFlags = CSSM_TP_ACTION_TRUST_SETTINGS; + vfyCtx.ActionData.Data = (uint8 *)&tpAction; + vfyCtx.ActionData.Length = sizeof(tpAction); + } + + /* cook up CSSM_ENCODED_CRL */ + CSSM_ENCODED_CRL encCrl; + encCrl.CrlType = CSSM_CRL_TYPE_X_509v2; + encCrl.CrlEncoding = CSSM_CRL_ENCODING_DER; + encCrl.CrlBlob = *crlData; + + /* CDSA API requires a SignerCertGroup; for us, all the certs are in + * certKeyChain... */ + CSSM_CERTGROUP certGroup; + certGroup.CertType = CSSM_CERT_X_509v1; + certGroup.CertEncoding = CSSM_CERT_ENCODING_DER; + certGroup.NumCerts = 0; + certGroup.GroupList.CertList = NULL; + certGroup.CertGroupType = CSSM_CERTGROUP_DATA; + + CSSM_RETURN crtn = CSSM_TP_CrlVerify(tpHand, + clHand, + cspHand, + &encCrl, + &certGroup, + &vfyCtx, + NULL); // RevokerVerifyResult + if(crtn) { + cuPrintError("CSSM_TP_CrlVerify", crtn); + } + if(anchors == NULL) { + /* close the DBs and maybe the DL we opened */ + unsigned dexToClose = (certKeychain == NULL) ? 0 : 1; + CSSM_DL_DbClose(handles[dexToClose++]); + CSSM_DL_DbClose(handles[dexToClose]); + if(dlHand != 0) { + cuDlDetachUnload(dlHand); + } + } + return crtn; +} + diff --git a/libsecurity_cdsa_utils/lib/cuCdsaUtils.h b/libsecurity_cdsa_utils/lib/cuCdsaUtils.h new file mode 100644 index 00000000..a4843c88 --- /dev/null +++ b/libsecurity_cdsa_utils/lib/cuCdsaUtils.h @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2001-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. + */ + +/* + File: cuCdsaUtils.h + + Description: common CDSA access utilities + + Author: dmitch +*/ + +#ifndef _COMMON_CDSA_UTILS_H_ +#define _COMMON_CDSA_UTILS_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* common memory allocators shared by app and CSSM */ +extern void * cuAppMalloc (CSSM_SIZE size, void *allocRef); +extern void cuAppFree (void *mem_ptr, void *allocRef); +extern void * cuAppRealloc (void *ptr, CSSM_SIZE size, void *allocRef); +extern void * cuAppCalloc (uint32 num, CSSM_SIZE size, void *allocRef); + +#define APP_MALLOC(s) cuAppMalloc(s, NULL) +#define APP_FREE(p) cuAppFree(p, NULL) +#define APP_REALLOC(p, s) cuAppRealloc(p, s, NULL) +#define APP_CALLOC(n, s) cuAppRealloc(n, s, NULL) + +extern CSSM_BOOL cuCompareCssmData( + const CSSM_DATA *d1, + const CSSM_DATA *d2); + +/* OID flavor of same, which will break when an OID is not a CSSM_DATA */ +#define cuCompareOid(o1, o2) cuCompareCssmData(o1, o2) + +void cuPrintError(const char *op, CSSM_RETURN err); + +/* Init CSSM; returns CSSM_FALSE on error. Reusable. */ +extern CSSM_BOOL cuCssmStartup(); + +/* Attach to CSP. Returns zero on error. */ +extern CSSM_CSP_HANDLE cuCspStartup( + CSSM_BOOL bareCsp); // true ==> CSP, false ==> CSP/DL + +/* Attach to DL side of CSPDL. */ +extern CSSM_DL_HANDLE cuDlStartup(); + +/* Attach to CL, TP */ +extern CSSM_CL_HANDLE cuClStartup(); +extern CSSM_TP_HANDLE cuTpStartup(); + +/* Open a DB, ensure it's empty. */ +CSSM_DB_HANDLE cuDbStartup( + CSSM_DL_HANDLE dlHand, // from dlStartup() + const char *dbName); + +/* Attach to existing DB or create an empty new one. */ +CSSM_DB_HANDLE cuDbStartupByName(CSSM_DL_HANDLE dlHand, + char *dbName, + CSSM_BOOL doCreate, + CSSM_BOOL quiet); + +/* detach and unload */ +CSSM_RETURN cuCspDetachUnload( + CSSM_CSP_HANDLE cspHand, + CSSM_BOOL bareCsp); // true ==> CSP, false ==> CSP/DL +CSSM_RETURN cuClDetachUnload( + CSSM_CL_HANDLE clHand); +CSSM_RETURN cuDlDetachUnload( + CSSM_DL_HANDLE dlHand); +CSSM_RETURN cuTpDetachUnload( + CSSM_TP_HANDLE tpHand); +/* + * Derive symmetric key using PBE. + */ +extern CSSM_RETURN cuCspDeriveKey(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 cuCspGenKeyPair(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 cuRefKeyToRaw(CSSM_CSP_HANDLE cspHand, + const CSSM_KEY *refKey, + CSSM_KEY_PTR rawKey); // RETURNED + +/* + * Add a certificate to a keychain. + */ +CSSM_RETURN cuAddCertToKC( + 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 cuDER_ToInt( + const CSSM_DATA *DER_Data); + +/* + * Verify a CRL against system anchors and intermediate certs. + */ +CSSM_RETURN cuCrlVerify( + CSSM_TP_HANDLE tpHand, + CSSM_CL_HANDLE clHand, + CSSM_CSP_HANDLE cspHand, + const CSSM_DATA *crlData, + CSSM_DL_DB_HANDLE_PTR certKeychain, // intermediate certs + const CSSM_DATA *anchors, // optional - if NULL, use Trust Settings + uint32 anchorCount); + +#ifdef __cplusplus +} +#endif + +#endif /* _COMMON_CDSA_UTILS_H_ */ diff --git a/libsecurity_cdsa_utils/lib/cuDbUtils.cpp b/libsecurity_cdsa_utils/lib/cuDbUtils.cpp new file mode 100644 index 00000000..494c6052 --- /dev/null +++ b/libsecurity_cdsa_utils/lib/cuDbUtils.cpp @@ -0,0 +1,574 @@ +/* + * Copyright (c) 2002-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. + */ + +/* + File: cuDbUtils.cpp + + Description: CDSA DB access utilities + + Author: dmitch +*/ + +#include "cuCdsaUtils.h" +#include "cuTimeStr.h" +#include "cuDbUtils.h" +#include "cuPrintCert.h" +#include +#include +#include +#include /* private SecInferLabelFromX509Name() */ +#include /* for cssmPerror() */ +#include +#include +#include +#include +#include /* private API */ + +#ifndef NDEBUG +#define dprintf(args...) printf(args) +#else +#define dprintf(args...) +#endif + +/* + * Add a certificate to an open DLDB. + */ +CSSM_RETURN cuAddCertToDb( + CSSM_DL_DB_HANDLE dlDbHand, + const CSSM_DATA *cert, + CSSM_CERT_TYPE certType, + CSSM_CERT_ENCODING certEncoding, + const char *printName, // C string + const CSSM_DATA *publicKeyHash) +{ + CSSM_DB_ATTRIBUTE_DATA attrs[6]; + CSSM_DB_RECORD_ATTRIBUTE_DATA recordAttrs; + CSSM_DB_ATTRIBUTE_DATA_PTR attr = &attrs[0]; + CSSM_DATA certTypeData; + CSSM_DATA certEncData; + CSSM_DATA printNameData; + CSSM_RETURN crtn; + CSSM_DB_UNIQUE_RECORD_PTR recordPtr; + + /* issuer and serial number required, fake 'em */ + CSSM_DATA issuer = {6, (uint8 *)"issuer"}; + CSSM_DATA serial = {6, (uint8 *)"serial"}; + + /* we spec six attributes, skipping alias */ + certTypeData.Data = (uint8 *)&certType; + certTypeData.Length = sizeof(CSSM_CERT_TYPE); + certEncData.Data = (uint8 *)&certEncoding; + certEncData.Length = sizeof(CSSM_CERT_ENCODING); + printNameData.Data = (uint8 *)printName; + printNameData.Length = strlen(printName) + 1; + + 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*) "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 = (char*) "PublicKeyHash"; + attr->Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_BLOB; + attr->NumberOfValues = 1; + attr->Value = (CSSM_DATA_PTR)publicKeyHash; + + 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 = &issuer; + + 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 = &serial; + + recordAttrs.DataRecordType = CSSM_DL_DB_RECORD_X509_CERTIFICATE; + recordAttrs.SemanticInformation = 0; + recordAttrs.NumberOfAttributes = 6; + recordAttrs.AttributeData = attrs; + + crtn = CSSM_DL_DataInsert(dlDbHand, + CSSM_DL_DB_RECORD_X509_CERTIFICATE, + &recordAttrs, + cert, + &recordPtr); + if(crtn) { + cuPrintError("CSSM_DL_DataInsert", crtn); + } + else { + CSSM_DL_FreeUniqueRecord(dlDbHand, recordPtr); + } + return crtn; +} + +static CSSM_RETURN cuAddCrlSchema( + CSSM_DL_DB_HANDLE dlDbHand); + +static void cuInferCrlLabel( + 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 cuSearchNumericExtension( + 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(!cuCompareOid(&exten->extnId, oid)) { + continue; + } + if(exten->format != CSSM_X509_DATAFORMAT_PARSED) { + dprintf("***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 9 + +CSSM_RETURN cuAddCrlToDb( + CSSM_DL_DB_HANDLE dlDbHand, + CSSM_CL_HANDLE clHand, + const CSSM_DATA *crl, + const CSSM_DATA *URI) // optional +{ + 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 = NULL; // mallocd by CL + CSSM_DATA_PTR crlValue = NULL; // 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 = NULL; + char *nextUpdate = NULL; + unsigned timeLen; + uint32 crlNumber; + uint32 deltaCrlNumber; + CSSM_DATA crlNumberData; + CSSM_DATA deltaCrlNumberData; + bool crlNumberPresent = false; + bool deltaCrlPresent = false; + CSSM_DATA attrUri; + + /* get normalized issuer name as Issuer attr */ + crtn = CSSM_CL_CrlGetFirstFieldValue(clHand, + crl, + &CSSMOID_X509V1IssuerName, + &result, + &numFields, + &issuer); + if(crtn) { + cuPrintError("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) { + cuPrintError("CSSM_CL_CrlGetFirstFieldValue(Issuer)", crtn); + goto errOut; + } + CSSM_CL_CrlAbortQuery(clHand, result); + if(crlValue == NULL) { + dprintf("***CSSM_CL_CrlGetFirstFieldValue: value error (1)\n"); + crtn = CSSMERR_CL_INVALID_CRL_POINTER; + goto errOut; + } + if((crlValue->Data == NULL) || + (crlValue->Length != sizeof(CSSM_X509_SIGNED_CRL))) { + dprintf("***CSSM_CL_CrlGetFirstFieldValue: value error (2)\n"); + crtn = CSSMERR_CL_INVALID_CRL_POINTER; + goto errOut; + } + 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: + dprintf("***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 */ + cuInferCrlLabel(&tbsCrl->issuer, &printNameData); + + /* cook up CSSM_TIMESTRING versions of this/next update */ + thisUpdate = cuX509TimeToCssmTimestring(&tbsCrl->thisUpdate, &timeLen); + if(thisUpdate == NULL) { + dprintf("***Badly formatted thisUpdate\n"); + } + else { + thisUpdateData.Data = (uint8 *)thisUpdate; + thisUpdateData.Length = timeLen; + } + if(tbsCrl->nextUpdate.time.Data != NULL) { + nextUpdate = cuX509TimeToCssmTimestring(&tbsCrl->nextUpdate, &timeLen); + if(nextUpdate == NULL) { + dprintf("***Badly formatted nextUpdate\n"); + } + else { + nextUpdateData.Data = (uint8 *)nextUpdate; + nextUpdateData.Length = timeLen; + } + } + else { + /* + * NextUpdate not present; fake it by using "virtual end of time" + */ + CSSM_X509_TIME tempTime = { 0, // timeType, not used + { strlen(CSSM_APPLE_CRL_END_OF_TIME), + (uint8 *)CSSM_APPLE_CRL_END_OF_TIME} }; + nextUpdate = cuX509TimeToCssmTimestring(&tempTime, &timeLen); + nextUpdateData.Data = (uint8 *)nextUpdate; + nextUpdateData.Length = CSSM_TIME_STRLEN; + } + + /* optional CrlNumber and DeltaCrlNumber */ + if(cuSearchNumericExtension(&tbsCrl->extensions, + &CSSMOID_CrlNumber, + &crlNumber)) { + crlNumberData.Data = (uint8 *)&crlNumber; + crlNumberData.Length = sizeof(uint32); + crlNumberPresent = true; + } + if(cuSearchNumericExtension(&tbsCrl->extensions, + &CSSMOID_DeltaCrlIndicator, + &deltaCrlNumber)) { + deltaCrlNumberData.Data = (uint8 *)&deltaCrlNumber; + deltaCrlNumberData.Length = sizeof(uint32); + deltaCrlPresent = true; + } + + attr->Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING; + attr->Info.Label.AttributeName = (char*) "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 = (char*) "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 = (char*) "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 = (char*) "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 = (char*) "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 = (char*) "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 = (char*) "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 = (char*) "DeltaCrlNumber"; + attr->Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_UINT32; + attr->NumberOfValues = 1; + attr->Value = &deltaCrlNumberData; + attr++; + } + if(URI) { + /* ensure URI string does not contain NULL */ + attrUri = *URI; + if((attrUri.Length != 0) && + (attrUri.Data[attrUri.Length - 1] == 0)) { + attrUri.Length--; + } + attr->Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING; + attr->Info.Label.AttributeName = (char*) "URI"; + attr->Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_BLOB; + attr->NumberOfValues = 1; + attr->Value = &attrUri; + attr++; + } + recordAttrs.DataRecordType = CSSM_DL_DB_RECORD_X509_CRL; + recordAttrs.SemanticInformation = 0; + recordAttrs.NumberOfAttributes = 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 = cuAddCrlSchema(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 == CSSM_OK) { + CSSM_DL_FreeUniqueRecord(dlDbHand, recordPtr); + } + +errOut: + /* free all the stuff we allocated to get here */ + if(issuer) { + CSSM_CL_FreeFieldValue(clHand, &CSSMOID_X509V1IssuerName, issuer); + } + if(crlValue) { + CSSM_CL_FreeFieldValue(clHand, &CSSMOID_X509V2CRLSignedCrlCStruct, crlValue); + } + if(thisUpdate) { + free(thisUpdate); + } + if(nextUpdate) { + free(nextUpdate); + } + return crtn; +} + + +/* + * Update an existing DLDB to be CRL-capable. + */ +static CSSM_RETURN cuAddCrlSchema( + 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); +} + +/* + * Search DB for all records of type CRL or cert, calling appropriate + * parse/print routine for each record. + */ +CSSM_RETURN cuDumpCrlsCerts( + CSSM_DL_DB_HANDLE dlDbHand, + CSSM_CL_HANDLE clHand, + CSSM_BOOL isCert, + unsigned &numItems, // returned + CSSM_BOOL verbose) +{ + CSSM_QUERY query; + CSSM_DB_UNIQUE_RECORD_PTR record = NULL; + CSSM_HANDLE resultHand; + CSSM_RETURN crtn; + CSSM_DATA certCrl; + const char *itemStr; + + numItems = 0; + itemStr = isCert ? "Certificate" : "CRL"; + + /* just search by recordType, no predicates, no attributes */ + if(isCert) { + query.RecordType = CSSM_DL_DB_RECORD_X509_CERTIFICATE; + } + else { + query.RecordType = CSSM_DL_DB_RECORD_X509_CRL; + } + 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? + + certCrl.Data = NULL; + certCrl.Length = 0; + crtn = CSSM_DL_DataGetFirst(dlDbHand, + &query, + &resultHand, + NULL, // no attrs + &certCrl, + &record); + switch(crtn) { + case CSSM_OK: + break; // proceed + case CSSMERR_DL_ENDOFDATA: + /* no data, otherwise OK */ + return CSSM_OK; + case CSSMERR_DL_INVALID_RECORDTYPE: + /* invalid record type just means "this hasn't been set up + * for certs yet". */ + return crtn; + default: + cuPrintError("DataGetFirst", crtn); + return crtn; + } + + /* got one; print it */ + dprintf("%s %u:\n", itemStr, numItems); + if(isCert) { + printCert(certCrl.Data, certCrl.Length, verbose); + } + else { + printCrl(certCrl.Data, certCrl.Length, verbose); + } + CSSM_DL_FreeUniqueRecord(dlDbHand, record); + APP_FREE(certCrl.Data); + certCrl.Data = NULL; + certCrl.Length = 0; + numItems++; + + /* get the rest */ + for(;;) { + crtn = CSSM_DL_DataGetNext(dlDbHand, + resultHand, + NULL, + &certCrl, + &record); + switch(crtn) { + case CSSM_OK: + dprintf("%s %u:\n", itemStr, numItems); + if(isCert) { + printCert(certCrl.Data, certCrl.Length, verbose); + } + else { + printCrl(certCrl.Data, certCrl.Length, verbose); + } + CSSM_DL_FreeUniqueRecord(dlDbHand, record); + APP_FREE(certCrl.Data); + certCrl.Data = NULL; + certCrl.Length = 0; + numItems++; + break; // and go again + case CSSMERR_DL_ENDOFDATA: + /* normal termination */ + return CSSM_OK; + default: + cuPrintError("DataGetNext", crtn); + return crtn; + } + } + /* NOT REACHED */ +} + diff --git a/libsecurity_cdsa_utils/lib/cuDbUtils.h b/libsecurity_cdsa_utils/lib/cuDbUtils.h new file mode 100644 index 00000000..62ba854a --- /dev/null +++ b/libsecurity_cdsa_utils/lib/cuDbUtils.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2002-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. + */ + +/* + File: cuDbUtils.h + + Description: CDSA DB access utilities + + Author: dmitch +*/ + +#ifndef _CU_DB_UTILS_H_ +#define _CU_DB_UTILS_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Add a certificate to an open DLDB. + */ +CSSM_RETURN cuAddCertToDb( + CSSM_DL_DB_HANDLE dlDbHand, + const CSSM_DATA *cert, + CSSM_CERT_TYPE certType, + CSSM_CERT_ENCODING certEncoding, + const char *printName, // C string + const CSSM_DATA *publicKeyHash); // ?? + +/* + * Add a CRL to an open DL/DB. + */ +CSSM_RETURN cuAddCrlToDb( + CSSM_DL_DB_HANDLE dlDbHand, + CSSM_CL_HANDLE clHand, + const CSSM_DATA *crl, + const CSSM_DATA *URI); // optional + +/* + * Search DB for all records of type CRL or cert, calling appropriate + * parse/print routine for each record. + */ +CSSM_RETURN cuDumpCrlsCerts( + CSSM_DL_DB_HANDLE dlDbHand, + CSSM_CL_HANDLE clHand, + CSSM_BOOL isCert, + unsigned &numItems, // returned + CSSM_BOOL verbose); + +#ifdef __cplusplus +} +#endif + +#endif /* _CU_DB_UTILS_H_ */ diff --git a/libsecurity_cdsa_utils/lib/cuEnc64.c b/libsecurity_cdsa_utils/lib/cuEnc64.c new file mode 100644 index 00000000..59dfbdc9 --- /dev/null +++ b/libsecurity_cdsa_utils/lib/cuEnc64.c @@ -0,0 +1,392 @@ +/* + * 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 new file mode 100644 index 00000000..77cb958b --- /dev/null +++ b/libsecurity_cdsa_utils/lib/cuEnc64.h @@ -0,0 +1,67 @@ +/* + * 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/lib/cuFileIo.c b/libsecurity_cdsa_utils/lib/cuFileIo.c new file mode 100644 index 00000000..513e8b22 --- /dev/null +++ b/libsecurity_cdsa_utils/lib/cuFileIo.c @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2001-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. + */ + +/* + File: cuFileIo.c + + Description: simple file read/write utilities +*/ + +#include +#include +#include +#include +#include +#include +#include +#include "cuFileIo.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_cdsa_utils/lib/cuFileIo.h b/libsecurity_cdsa_utils/lib/cuFileIo.h new file mode 100644 index 00000000..bb3de3f8 --- /dev/null +++ b/libsecurity_cdsa_utils/lib/cuFileIo.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2001-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. + */ + +/* + File: cuFileIo.h + + Description: 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_cdsa_utils/lib/cuOidParser.cpp b/libsecurity_cdsa_utils/lib/cuOidParser.cpp new file mode 100644 index 00000000..aa9326ce --- /dev/null +++ b/libsecurity_cdsa_utils/lib/cuOidParser.cpp @@ -0,0 +1,314 @@ +/* + * Copyright (c) 2002-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. + */ + +/* + * cuOidParser.cpp - parse an Intel-style OID, with the assistance + * of dumpasn1.cfg + */ + +#include +#include +#include +#include +#include "cuOidParser.h" +#include "cuFileIo.h" +#include +#include +#include +#include +#include +#include +#include + +/* get config file from .. or from . */ +#define CONFIG_FILE_NAME "dumpasn1.cfg" +static const char *CONFIG_FILE1 = "../"CONFIG_FILE_NAME; +static const char *CONFIG_FILE2 = CONFIG_FILE_NAME; +/* or from here via getenv */ +#define CONFIG_FILE_ENV "LOCAL_BUILD_DIR" + +static const char *OID_ENTRY_START = "OID = "; +static const char *OID_DESCR_START = "Description = "; +/* + * Read entire file with extra bytes left over in the mallocd buffer. + */ +int readFileExtra( + const char *fileName, + unsigned extraBytes, + unsigned char **bytes, // mallocd and returned + CSSM_SIZE *numBytes) // returned +{ + int rtn; + int fd; + unsigned char *buf; + struct stat sb; + size_t size; + + *numBytes = 0; + *bytes = NULL; + fd = open(fileName, O_RDONLY, 0); + if(fd < 0) { + return 1; + } + rtn = fstat(fd, &sb); + if(rtn) { + goto errOut; + } + size = sb.st_size; + buf = (unsigned char *)malloc(size + extraBytes); + 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; +} + +/* + * Attempt to read dumpasn1.cfg from various places. If we can't find it, + * printOid() function will just print raw bytes as it + * would if the .cfg file did not contain the desired OID. + */ +static CSSM_DATA_PTR readConfig() +{ + CSSM_DATA_PTR configData = NULL; + int rtn; + + configData = (CSSM_DATA_PTR)malloc(sizeof(CSSM_DATA)); + if(configData == NULL) { + return NULL; + } + /* malloc one extra byte, we'll null it later */ + rtn = readFileExtra(CONFIG_FILE1, 1, &configData->Data, + &configData->Length); + if(rtn) { + rtn = readFileExtra(CONFIG_FILE2, 1, &configData->Data, + &configData->Length); + } + if(rtn) { + char fileName[100]; + char *localBuildDir = getenv(CONFIG_FILE_ENV); + if(localBuildDir == NULL) { + rtn = 1; + } + else { + sprintf(fileName, "%s/%s", localBuildDir, CONFIG_FILE_NAME); + rtn = readFileExtra(fileName, 1, &configData->Data, + &configData->Length); + } + } + if(rtn == 0) { + /* make the whole shebang one long C string */ + configData->Data[configData->Length++] = '\0'; + return configData; + } + else { + free(configData); + return NULL; + } +} + +/* + * The heart of this module. + * + * -- Convert Intel-style OID to a string which might be found + * in the config file + * -- search config file for that string + * -- if found, use that entry in config file to output meaningful + * string and return CSSM_TRUE. Else return CSSM_FALSE. + */ +static CSSM_BOOL parseOidWithConfig( + const CSSM_DATA_PTR configData, + const CSSM_OID_PTR oid, + char *strBuf) +{ + char *fullOidStr = NULL; + char *ourEntry = NULL; + char *nextEntry = NULL; + char *descStart = NULL; + char *cp; + unsigned i; + CSSM_BOOL brtn; + char *nextCr; // next CR if any + char *nextNl; // next NL if any + char *eol; // end of line + int len; + + if(configData == NULL) { + return CSSM_FALSE; + } + + /* cook up a full OID string, with tag and length */ + fullOidStr = (char *)malloc((3 * oid->Length) + + // 2 chars plus space per byte + strlen(OID_ENTRY_START) + // "OID = " + 6 + // 06 xx - tag and length + 1); // NULL + if(fullOidStr == NULL) { + return CSSM_FALSE; + } + /* subsequent errors to errOut: */ + + sprintf(fullOidStr, "OID = 06 %02X", (unsigned)oid->Length); + cp = fullOidStr + strlen(fullOidStr); + for(i=0; iLength; i++) { + /* move cp to current end of string */ + cp += strlen(cp); + /* add one byte */ + sprintf(cp, " %02X", oid->Data[i]); + } + + /* + * Let's play it loose and assume that there are no embedded NULLs + * in the config file. Thus we can use the spiffy string functions + * in stdlib. + */ + ourEntry = strstr((char *)configData->Data, fullOidStr); + if(ourEntry == NULL) { + brtn = CSSM_FALSE; + goto errOut; + } + + /* get position of NEXT full entry - may be NULL (end of file) */ + nextEntry = strstr(ourEntry+1, OID_ENTRY_START); + + /* get position of our entry's description line */ + descStart = strstr(ourEntry+1, OID_DESCR_START); + + /* handle not found/overflow */ + if( (descStart == NULL) || // no more description lines + ( (descStart > nextEntry) && // no description in THIS entry + (nextEntry != NULL) ) ) { // make sure this is valid + brtn = CSSM_FALSE; + goto errOut; + } + + /* set descStart to after the leader */ + descStart += strlen(OID_DESCR_START); + + /* + * descStart points to the text we're interested in. + * First find end of line, any style. + */ + nextNl = strchr(descStart, '\n'); + nextCr = strchr(descStart, '\r'); + if((nextNl == NULL) && (nextCr == NULL)) { + /* no line terminator, go to eof */ + eol = (char *)configData->Data + configData->Length; + } + else if(nextCr == NULL) { + eol = nextNl; + } + else if(nextNl == NULL) { + eol = nextCr; + } + else if(nextNl < nextCr) { + /* both present, take first one */ + eol = nextNl; + } + else { + eol = nextCr; + } + + /* caller's string buf = remainder of description line */ + len = eol - descStart; + if(len > (OID_PARSER_STRING_SIZE - 1)) { + /* fixed-length output buf, avoid overflow */ + len = OID_PARSER_STRING_SIZE - 1; + } + memcpy(strBuf, descStart, len); + strBuf[len] = '\0'; + brtn = CSSM_TRUE; +errOut: + if(fullOidStr != NULL) { + free(fullOidStr); + } + return brtn; +} + +/*** OidParser class ***/ +OidParser::OidParser(bool noConfig) +{ + if(noConfig) { + configData = NULL; + } + else { + configData = readConfig(); + } +} + +OidParser::~OidParser() +{ + if(configData == NULL) { + return; + } + if(configData->Data != NULL) { + free(configData->Data); + } + free(configData); +} + +/* + * Parse an Intel-style OID, generating a C string in caller-supplied buffer. + */ +void OidParser::oidParse( + const unsigned char *oidp, + unsigned oidLen, + char *strBuf) +{ + unsigned i; + CSSM_OID oid; + + oid.Data = (uint8 *)oidp; + oid.Length = oidLen; + + if((oidLen == 0) || (oidp == NULL)) { + strcpy(strBuf, "EMPTY"); + return; + } + if(parseOidWithConfig(configData, &oid, strBuf) == CSSM_FALSE) { + /* no config file, just dump the bytes */ + char cbuf[8]; + + sprintf(strBuf, "OID : < 06 %02X ", (unsigned)oid.Length); + for(i=0; i"); + } +} + + diff --git a/libsecurity_cdsa_utils/lib/cuOidParser.h b/libsecurity_cdsa_utils/lib/cuOidParser.h new file mode 100644 index 00000000..fcadc5a7 --- /dev/null +++ b/libsecurity_cdsa_utils/lib/cuOidParser.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2002-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. + * + * cuOidParser.cpp - parse an Intel-style OID, with the assistance of + * dumpasn1.cfg. + * + * The config file is looked for in the following locations: + * + * current working directory (.) + * parent directory (..) + * The directory specified by the environment variable LOCAL_BUILD_DIR + * + * OidParser will still work if the config file is not found, but OIDs + * will be dispayed in raw hex format. + */ + +#ifndef _OID_PARSER_H_ +#define _OID_PARSER_H_ + +#include + +/* + * Generated strings go into a client-allocated char array of + * this size. + */ +#define OID_PARSER_STRING_SIZE 120 + +class OidParser +{ +private: + CSSM_DATA_PTR configData; // contents of dumpasn1.cfg +public: + /* costruct with noConfig true - skip reading config file */ + OidParser(bool noConfig=false); + ~OidParser(); + + /* + * Parse an Intel-style OID, generating a C string in + * caller-supplied buffer. + */ + void oidParse( + const unsigned char *oidp, + unsigned oidLen, + char *strBuf); + +}; + +#endif /* _OID_PARSER_H_ */ diff --git a/libsecurity_cdsa_utils/lib/cuPem.cpp b/libsecurity_cdsa_utils/lib/cuPem.cpp new file mode 100644 index 00000000..6675ef60 --- /dev/null +++ b/libsecurity_cdsa_utils/lib/cuPem.cpp @@ -0,0 +1,198 @@ +/* + * 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. + */ + +/* + File: cuPem.h + + Description: PEM encode/decode routines + + Author: dmitch + +*/ + +#include "cuPem.h" +#include +#include +#include +#include +#include "cuEnc64.h" + +#define PEM_SCAN_LEN 8192 + +/* + * Determine if specified blob appears to be PEM format. + * Returns 1 if so, 0 if not. + */ +int isPem( + const unsigned char *inData, + unsigned inDataLen) +{ + /* + * 1. The entire blob must be printable ASCII. + */ + const unsigned char *cp = inData; + for(unsigned dex=0; dex PEM_SCAN_LEN) { + len = PEM_SCAN_LEN; + } + memcpy(buf, inData, len); + buf[len] = '\0'; + const char *p = strstr((const char *)buf, "-----BEGIN "); + if(p == NULL) { + return 0; + } + + /* + * Now the last PEM_SCAN_LEN chars or inDataLen, whichever is less. + */ + if(inDataLen > PEM_SCAN_LEN) { + memcpy(buf, inData + inDataLen - PEM_SCAN_LEN, PEM_SCAN_LEN); + buf[PEM_SCAN_LEN] = '\0'; + } + /* else we already have whole blob in buf[] */ + p = strstr((const char *)buf, "-----END "); + if(p == NULL) { + return 0; + } + /* success */ + return 1; +} + +int pemEncode( + const unsigned char *inData, + unsigned inDataLen, + unsigned char **outData, + unsigned *outDataLen, + const char *headerString) +{ + unsigned char *enc; + unsigned encLen; + + /* First base64 encode */ + enc = cuEnc64WithLines(inData, inDataLen, 64, &encLen); + if(enc == NULL) { + /* malloc error is actually the only known failure */ + printf("***pemEncode: Error encoding file. Aborting.\n"); + return -1; + } + + /* estimate outsize - just be sloppy, way conservative */ + unsigned outSize = encLen + (2 * strlen(headerString)) + 200; + *outData = (unsigned char *)malloc(outSize); + sprintf((char *)*outData, "-----BEGIN %s-----\n%s-----END %s-----\n", + headerString, (char *)enc, headerString); + *outDataLen = strlen((char *)*outData); + + if((*outData)[*outDataLen - 1] == '\0') { + (*outDataLen)--; + } + free(enc); + return 0; +} + +int pemDecode( + const unsigned char *inData, + unsigned inDataLen, + unsigned char **outData, + unsigned *outDataLen) +{ + char *cp; + char *curr1, *curr2; + char *startPem = NULL; + char *endPem = NULL; + unsigned char *out; + unsigned outLen; + int ourRtn = 0; + char *freeCp = NULL; + + /* make the whole thing a NULL-terminated string */ + if(inData[inDataLen - 1] != '\0') { + cp = freeCp = (char *)malloc(inDataLen + 1); + memmove(cp, inData, inDataLen); + cp[inDataLen] = '\0'; + inDataLen++; + } + else { + /* already is */ + cp = (char *)inData; + } + + /* cp is start of NULL-terminated buffer, size inDataLen */ + /* skip over everything until "-----" */ + curr1 = strstr(cp, "-----"); + if(curr1 == NULL) { + printf("***pemDecode: no terminator found\n"); + ourRtn = -1; + goto abort; + } + + /* find end of separator line, handling both flavors of terminator */ + cp = curr1; + curr1 = strchr(cp, '\n'); + curr2 = strchr(cp, '\r'); + if((curr1 == NULL) & (curr2 == NULL)) { + printf("***pemDecode: Bad PEM format (1)\n"); + ourRtn = -1; + goto abort; + } + if(curr1 == NULL) { + startPem = curr2; + } + else { + startPem = curr1; + } + + /* startPem points to end of separator line */ + /* locate ending terminator and lop it off */ + curr1 = strstr(startPem, "-----"); + if(curr1 == NULL) { + printf("***pemDecode: Bad PEM format (2)\n"); + ourRtn = -1; + goto abort; + } + endPem = curr1; + /* endPem points to last PEM data plus one */ + + out = cuDec64((unsigned char *)startPem, endPem-startPem, &outLen); + if(out == NULL) { + printf("Bad PEM format (3)\n"); + ourRtn = -1; + goto abort; + } + *outData = out; + *outDataLen = outLen; +abort: + if(freeCp) { + free(freeCp); + } + return ourRtn; +} + diff --git a/libsecurity_cdsa_utils/lib/cuPem.h b/libsecurity_cdsa_utils/lib/cuPem.h new file mode 100644 index 00000000..58a08fde --- /dev/null +++ b/libsecurity_cdsa_utils/lib/cuPem.h @@ -0,0 +1,50 @@ +/* + * 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. + */ + +/* + File: cuPem.h + + Description: PEM encode/decode routines + + Author: dmitch +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +int isPem( + const unsigned char *inData, + unsigned inDataLen); + +int pemEncode( + const unsigned char *inData, + unsigned inFileLen, + unsigned char **outData, + unsigned *outDataLen, + const char *headerString); + +int pemDecode( + const unsigned char *inData, + unsigned inFileLen, + unsigned char **outData, + unsigned *outDataLen); + +#ifdef __cplusplus +} +#endif diff --git a/libsecurity_cdsa_utils/lib/cuPrintCert.cpp b/libsecurity_cdsa_utils/lib/cuPrintCert.cpp new file mode 100644 index 00000000..5972e4da --- /dev/null +++ b/libsecurity_cdsa_utils/lib/cuPrintCert.cpp @@ -0,0 +1,1500 @@ +/* + * Copyright (c) 2002 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. + */ + +/* + * cuPrintCert.cpp - Parse a cert or CRL, dump contents. + */ +#include "cuCdsaUtils.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "cuPrintCert.h" +#include "cuOidParser.h" +#include "cuTimeStr.h" +#include +#include +#include + +static const char *months[] = { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" +}; + +static void printTimeStr(const CSSM_DATA *cssmTime) +{ + struct tm tm; + + /* ignore cssmTime->timeType for now */ + if(cuTimeStringToTm((char *)cssmTime->Data, cssmTime->Length, &tm)) { + printf("***Bad time string format***\n"); + return; + } + if(tm.tm_mon > 11) { + printf("***Bad time string format***\n"); + return; + } + printf("%02d:%02d:%02d %s %d, %04d\n", + tm.tm_hour, tm.tm_min, tm.tm_sec, + months[tm.tm_mon], tm.tm_mday, tm.tm_year + 1900); + +} + + +static void printTime(const CSSM_X509_TIME *cssmTime) +{ + /* ignore cssmTime->timeType for now */ + printTimeStr(&cssmTime->time); +} + +static void printDataAsHex( + const CSSM_DATA *d, + unsigned maxToPrint = 0) // optional, 0 means print it all +{ + unsigned i; + bool more = false; + uint32 len = d->Length; + uint8 *cp = d->Data; + + if((maxToPrint != 0) && (len > maxToPrint)) { + len = maxToPrint; + more = true; + } + for(i=0; iLength + * Tag is implied + */ +static void printOid(OidParser &parser, const CSSM_DATA *oid) +{ + char strBuf[OID_PARSER_STRING_SIZE]; + + if(oid == NULL) { + printf("NULL\n"); + return; + } + if((oid->Length == 0) || (oid->Data == NULL)) { + printf("EMPTY\n"); + return; + } + parser.oidParse(oid->Data, oid->Length, strBuf); + printf("%s\n", strBuf); +} + +/* + * Used to print generic blobs which we don't really understand. + * The bytesToPrint argument is usually thing->Length; it's here because snacc + * peports lengths of bit strings in BITS. Caller knows this and + * modifies bytesToPrint accordingly. In any case, bytesToPrint is the + * max number of valid bytes in *thing->Data. + */ +#define BLOB_LENGTH_PRINT 3 + +static void printBlobBytes( + const char *blobType, + const char *quanta, // e.g., "bytes', "bits" + uint32 bytesToPrint, + const CSSM_DATA *thing) +{ + uint32 dex; + uint32 toPrint = bytesToPrint; + + if(toPrint > BLOB_LENGTH_PRINT) { + toPrint = BLOB_LENGTH_PRINT; + } + printf("%s; Length %u %s; data = ", + blobType, (unsigned)thing->Length, quanta); + for(dex=0; dexData[dex]); + if(dex == (toPrint - 1)) { + break; + } + } + if(dex < bytesToPrint) { + printf(" ...\n"); + } + else { + printf("\n"); + } +} + +/* + * Print an IA5String or Printable string. Null terminator is not assumed. + * Trailing newline is printed. + */ +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 printDerThing( + CSSM_BER_TAG tagType, + const CSSM_DATA *thing, + OidParser &parser) +{ + switch(tagType) { + case BER_TAG_INTEGER: + printf("%d\n", cuDER_ToInt(thing)); + return; + case BER_TAG_BOOLEAN: + if(thing->Length != 1) { + printf("***malformed BER_TAG_BOOLEAN: length %u data ", + (unsigned)thing->Length); + } + printf("%u\n", cuDER_ToInt(thing)); + return; + case BER_TAG_PRINTABLE_STRING: + case BER_TAG_IA5_STRING: + case BER_TAG_T61_STRING: + case BER_TAG_PKIX_UTF8_STRING: // mostly printable.... + printString(thing); + return; + case BER_TAG_OCTET_STRING: + printBlobBytes("Byte string", "bytes", thing->Length, thing); + return; + case BER_TAG_BIT_STRING: + printBlobBytes("Bit string", "bits", (thing->Length + 7) / 8, thing); + return; + case BER_TAG_SEQUENCE: + printBlobBytes("Sequence", "bytes", thing->Length, thing); + return; + case BER_TAG_SET: + printBlobBytes("Set", "bytes", thing->Length, thing); + return; + case BER_TAG_OID: + printf("OID = "); + printOid(parser, thing); + break; + default: + printf("not displayed (tagType = %s; length %u)\n", + tagTypeString(tagType), (unsigned)thing->Length); + break; + + } +} + +/* compare two OIDs, return CSSM_TRUE if identical */ +static CSSM_BOOL compareOids( + const CSSM_OID *oid1, + const CSSM_OID *oid2) +{ + if((oid1 == NULL) || (oid2 == NULL)) { + return CSSM_FALSE; + } + if(oid1->Length != oid2->Length) { + return CSSM_FALSE; + } + if(memcmp(oid1->Data, oid2->Data, oid1->Length)) { + return CSSM_FALSE; + } + else { + return CSSM_TRUE; + } +} + +/* + * Following a CSSMOID_ECDSA_WithSpecified algorithm is another encoded + * CSSM_X509_ALGORITHM_IDENTIFIER containing the digest algorithm OID. + * Decode and print the OID. + */ +static void printECDSA_SigAlgParams( + const CSSM_DATA *params, + OidParser &parser) +{ + SecAsn1CoderRef coder = NULL; + if(SecAsn1CoderCreate(&coder)) { + printf("***Error in SecAsn1CoderCreate()\n"); + return; + } + CSSM_X509_ALGORITHM_IDENTIFIER algParams; + memset(&algParams, 0, sizeof(algParams)); + if(SecAsn1DecodeData(coder, params, kSecAsn1AlgorithmIDTemplate, + &algParams)) { + printf("***Error decoding CSSM_X509_ALGORITHM_IDENTIFIER\n"); + goto errOut; + } + printOid(parser, &algParams.algorithm); +errOut: + SecAsn1CoderRelease(coder); +} + +static void printSigAlg( + const CSSM_X509_ALGORITHM_IDENTIFIER *sigAlg, + OidParser &parser) +{ + printOid(parser, &sigAlg->algorithm); + if(sigAlg->parameters.Data != NULL) { + printf(" alg params : "); + if(compareOids(&sigAlg->algorithm, &CSSMOID_ecPublicKey) && + (sigAlg->parameters.Data[0] == BER_TAG_OID) && + (sigAlg->parameters.Length > 2)) { + /* + * An OID accompanying an ECDSA public key. The OID is an ECDSA curve. + * Do a quickie DER-decode of the OID - it's here in encoded form + * because this field is an ASN_ANY - and print the resulting OID. + */ + CSSM_OID curveOid = {sigAlg->parameters.Length-2, sigAlg->parameters.Data+2}; + printOid(parser, &curveOid); + } + else if(compareOids(&sigAlg->algorithm, &CSSMOID_ECDSA_WithSpecified)) { + /* + * The accompanying params specify the digest algorithm. + */ + printECDSA_SigAlgParams(&sigAlg->parameters, parser); + } + else { + /* All others - ASN_ANY - punt */ + printDataAsHex(&sigAlg->parameters, 8); + } + } +} + +static void printRdn( + const CSSM_X509_RDN *rdnp, + OidParser &parser) +{ + CSSM_X509_TYPE_VALUE_PAIR *ptvp; + unsigned pairDex; + const char *fieldName; + + for(pairDex=0; pairDexnumberOfPairs; pairDex++) { + ptvp = &rdnp->AttributeTypeAndValue[pairDex]; + if(compareOids(&ptvp->type, &CSSMOID_CountryName)) { + fieldName = "Country "; + } + else if(compareOids(&ptvp->type, &CSSMOID_OrganizationName)) { + fieldName = "Org "; + } + else if(compareOids(&ptvp->type, &CSSMOID_LocalityName)) { + fieldName = "Locality "; + } + else if(compareOids(&ptvp->type, &CSSMOID_OrganizationalUnitName)) { + fieldName = "OrgUnit "; + } + else if(compareOids(&ptvp->type, &CSSMOID_CommonName)) { + fieldName = "Common Name "; + } + else if(compareOids(&ptvp->type, &CSSMOID_Surname)) { + fieldName = "Surname "; + } + else if(compareOids(&ptvp->type, &CSSMOID_Title)) { + fieldName = "Title "; + } + else if(compareOids(&ptvp->type, &CSSMOID_Surname)) { + fieldName = "Surname "; + } + else if(compareOids(&ptvp->type, &CSSMOID_StateProvinceName)) { + fieldName = "State "; + } + else if(compareOids(&ptvp->type, &CSSMOID_CollectiveStateProvinceName)) { + fieldName = "Coll. State "; + } + else if(compareOids(&ptvp->type, &CSSMOID_EmailAddress)) { + /* deprecated, used by Thawte */ + fieldName = "Email addrs "; + } + else if(compareOids(&ptvp->type, &CSSMOID_Description)) { + fieldName = "Description "; + } + else { + fieldName = "Other name "; + } + printf(" %s : ", fieldName); + printDerThing(ptvp->valueType, &ptvp->value, parser); + } /* for each type/value pair */ +} + +static CSSM_RETURN printName( + const CSSM_X509_NAME *x509Name, + OidParser &parser) +{ + CSSM_X509_RDN_PTR rdnp; + unsigned rdnDex; + + for(rdnDex=0; rdnDexnumberOfRDNs; rdnDex++) { + rdnp = &x509Name->RelativeDistinguishedName[rdnDex]; + printRdn(rdnp, parser); + } + + return CSSM_OK; +} + +static void printKeyHeader( + const CSSM_KEYHEADER &hdr) +{ + printf(" Algorithm : "); + switch(hdr.AlgorithmId) { + case CSSM_ALGID_RSA: + printf("RSA\n"); + break; + case CSSM_ALGID_DSA: + printf("DSA\n"); + break; + case CSSM_ALGID_FEE: + printf("FEE\n"); + break; + case CSSM_ALGID_DH: + printf("Diffie-Hellman\n"); + break; + case CSSM_ALGID_ECDSA: + printf("ECDSA\n"); + break; + default: + printf("Unknown(%u(d), 0x%x)\n", (unsigned)hdr.AlgorithmId, + (unsigned)hdr.AlgorithmId); + } + printf(" Key Size : %u bits\n", (unsigned)hdr.LogicalKeySizeInBits); + printf(" Key Use : "); + CSSM_KEYUSE usage = hdr.KeyUsage; + if(usage & CSSM_KEYUSE_ANY) { + printf("CSSM_KEYUSE_ANY "); + } + if(usage & CSSM_KEYUSE_ENCRYPT) { + printf("CSSM_KEYUSE_ENCRYPT "); + } + if(usage & CSSM_KEYUSE_DECRYPT) { + printf("CSSM_KEYUSE_DECRYPT "); + } + if(usage & CSSM_KEYUSE_SIGN) { + printf("CSSM_KEYUSE_SIGN "); + } + if(usage & CSSM_KEYUSE_VERIFY) { + printf("CSSM_KEYUSE_VERIFY "); + } + if(usage & CSSM_KEYUSE_SIGN_RECOVER) { + printf("CSSM_KEYUSE_SIGN_RECOVER "); + } + if(usage & CSSM_KEYUSE_VERIFY_RECOVER) { + printf("CSSM_KEYUSE_VERIFY_RECOVER "); + } + if(usage & CSSM_KEYUSE_WRAP) { + printf("CSSM_KEYUSE_WRAP "); + } + if(usage & CSSM_KEYUSE_UNWRAP) { + printf("CSSM_KEYUSE_UNWRAP "); + } + if(usage & CSSM_KEYUSE_DERIVE) { + printf("CSSM_KEYUSE_DERIVE "); + } + printf("\n"); + +} + +/* + * Print contents of a CE_GeneralName as best we can. + */ +static void printGeneralName( + const CE_GeneralName *name, + OidParser &parser) +{ + switch(name->nameType) { + case GNT_RFC822Name: + printf(" RFC822Name : "); + printString(&name->name); + break; + case GNT_DNSName: + printf(" DNSName : "); + printString(&name->name); + break; + case GNT_URI: + printf(" URI : "); + printString(&name->name); + break; + case GNT_IPAddress: + printf(" IP Address : "); + for(unsigned i=0; iname.Length; i++) { + printf("%d", name->name.Data[i]); + if(i < (name->name.Length - 1)) { + printf("."); + } + } + printf("\n"); + break; + case GNT_RegisteredID: + printf(" RegisteredID : "); + printOid(parser, &name->name); + break; + case GNT_X400Address: + /* ORAddress, a very complicated struct - punt */ + printf(" X400Address : "); + printBlobBytes("Sequence", "bytes", name->name.Length, &name->name); + break; + case GNT_DirectoryName: + if(!name->berEncoded) { + /* CL parsed it for us into an CSSM_X509_NAME */ + if(name->name.Length != sizeof(CSSM_X509_NAME)) { + printf("***MALFORMED GNT_DirectoryName\n"); + break; + } + const CSSM_X509_NAME *x509Name = + (const CSSM_X509_NAME *)name->name.Data; + printf(" Dir Name :\n"); + printName(x509Name, parser); + } + else { + /* encoded Name (i.e. CSSM_X509_NAME) */ + printf(" Dir Name : "); + printBlobBytes("Byte string", "bytes", + name->name.Length, &name->name); + } + break; + case GNT_EdiPartyName: + /* sequence EDIPartyName */ + printf(" EdiPartyName : "); + printBlobBytes("Sequence", "bytes", name->name.Length, &name->name); + break; + case GNT_OtherName: + { + printf(" OtherName :\n"); + if(name->name.Length != sizeof(CE_OtherName)) { + printf("***Malformed CE_OtherName\n"); + break; + } + CE_OtherName *other = (CE_OtherName *)name->name.Data; + printf(" typeID : "); + printOid(parser, &other->typeId); + printf(" value : "); + printDataAsHex(&other->value, 0); + break; + } + } +} + + +/* + * Print contents of a CE_GeneralNames as best we can. + */ +static void printGeneralNames( + const CE_GeneralNames *generalNames, + OidParser &parser) +{ + unsigned i; + CE_GeneralName *name; + + for(i=0; inumNames; i++) { + name = &generalNames->generalName[i]; + printGeneralName(name, parser); + } +} + +static int printCdsaExtensionCommon( + const CSSM_X509_EXTENSION *cssmExt, + OidParser &parser, + bool expectParsed, + CSSM_BOOL verbose, + bool extraIndent = false) +{ + if(extraIndent) { + printf(" Extension : "); printOid(parser, &cssmExt->extnId); + printf(" Critical : %s\n", cssmExt->critical ? "TRUE" : "FALSE"); + } + else { + printf("Extension struct : "); printOid(parser, &cssmExt->extnId); + printf(" Critical : %s\n", cssmExt->critical ? "TRUE" : "FALSE"); + } + + /* currently (since Radar 3593624), these are both always valid */ + #if 0 + /* this prevents printing pre-encoded extensions in clxutils/extenTest */ + if((cssmExt->BERvalue.Data == NULL) || + (cssmExt->value.parsedValue == NULL)) { /* actually, one of three variants */ + printf("***Malformed CSSM_X509_EXTENSION (1)\n"); + return 1; + } + #endif + switch(cssmExt->format) { + case CSSM_X509_DATAFORMAT_ENCODED: + if(expectParsed) { + printf("Bad CSSM_X509_EXTENSION; expected FORMAT_PARSED\n"); + return 1; + } + break; + case CSSM_X509_DATAFORMAT_PARSED: + if(!expectParsed) { + printf("Bad CSSM_X509_EXTENSION; expected FORMAT_ENCODED\n"); + return 1; + } + break; + case CSSM_X509_DATAFORMAT_PAIR: + /* unsupported */ + printf("Bad CSSM_X509_EXTENSION format:FORMAT_PAIR\n"); + return 1; + default: + printf("***Unknown CSSM_X509_EXTENSION.format\n"); + return 1; + } + return 0; +} + +static int printExtensionCommon( + const CSSM_DATA &value, + OidParser &parser, + CSSM_BOOL verbose, + bool expectParsed = true) +{ + if(value.Length != sizeof(CSSM_X509_EXTENSION)) { + printf("***malformed CSSM_FIELD (1)\n"); + return 1; + } + CSSM_X509_EXTENSION *cssmExt = (CSSM_X509_EXTENSION *)value.Data; + return printCdsaExtensionCommon(cssmExt, parser, expectParsed, verbose); +} + + +static void printKeyUsage( + const CSSM_DATA &value) +{ + CE_KeyUsage usage; + CSSM_X509_EXTENSION *cssmExt = (CSSM_X509_EXTENSION *)value.Data; + + usage = *((CE_KeyUsage *)cssmExt->value.parsedValue); + printf(" usage : "); + if(usage & CE_KU_DigitalSignature) { + printf("DigitalSignature "); + } + if(usage & CE_KU_NonRepudiation) { + printf("NonRepudiation "); + } + if(usage & CE_KU_KeyEncipherment) { + printf("KeyEncipherment "); + } + if(usage & CE_KU_DataEncipherment) { + printf("DataEncipherment "); + } + if(usage & CE_KU_KeyAgreement) { + printf("KeyAgreement "); + } + if(usage & CE_KU_KeyCertSign) { + printf("KeyCertSign "); + } + if(usage & CE_KU_CRLSign) { + printf("CRLSign "); + } + if(usage & CE_KU_EncipherOnly) { + printf("EncipherOnly "); + } + if(usage & CE_KU_DecipherOnly) { + printf("DecipherOnly "); + } + printf("\n"); + +} + +static void printBasicConstraints( + const CSSM_DATA &value) +{ + CSSM_X509_EXTENSION *cssmExt = (CSSM_X509_EXTENSION *)value.Data; + CE_BasicConstraints *bc = (CE_BasicConstraints *)cssmExt->value.parsedValue; + printf(" CA : %s\n", bc->cA ? "TRUE" : "FALSE"); + if(bc->pathLenConstraintPresent) { + printf(" pathLenConstr : %u\n", (unsigned)bc->pathLenConstraint); + } +} + +static void printExtKeyUsage( + const CSSM_DATA &value, + OidParser &parser) +{ + CSSM_X509_EXTENSION *cssmExt = (CSSM_X509_EXTENSION *)value.Data; + CE_ExtendedKeyUsage *eku = (CE_ExtendedKeyUsage *)cssmExt->value.parsedValue; + unsigned oidDex; + for(oidDex=0; oidDexnumPurposes; oidDex++) { + printf(" purpose %2d : ", oidDex); + printOid(parser, &eku->purposes[oidDex]); + } +} + +static void printCssmAuthorityKeyId( + const CE_AuthorityKeyID *akid, + OidParser &parser) +{ + if(akid->keyIdentifierPresent) { + printf(" Auth KeyID : "); + printDataAsHex(&akid->keyIdentifier, +8); + } + if(akid->generalNamesPresent) { + printGeneralNames(akid->generalNames, parser); + } + if(akid->serialNumberPresent) { + printf(" serialNumber : "); + printDataAsHex(&akid->serialNumber, 8); + } +} + +static void printAuthorityKeyId( + const CSSM_DATA &value, + OidParser &parser) +{ + CSSM_X509_EXTENSION *cssmExt = (CSSM_X509_EXTENSION *)value.Data; + CE_AuthorityKeyID *akid = (CE_AuthorityKeyID *)cssmExt->value.parsedValue; + printCssmAuthorityKeyId(akid, parser); +} + +static void printSubjectIssuerAltName( + const CSSM_DATA &value, + OidParser &parser) +{ + CSSM_X509_EXTENSION *cssmExt = (CSSM_X509_EXTENSION *)value.Data; + CE_GeneralNames *san = (CE_GeneralNames *)cssmExt->value.parsedValue; + printGeneralNames(san, parser); +} + +static void printDistPointName( + const CE_DistributionPointName *dpn, + OidParser &parser) +{ + switch(dpn->nameType) { + case CE_CDNT_FullName: + printGeneralNames(dpn->dpn.fullName, parser); + break; + case CE_CDNT_NameRelativeToCrlIssuer: + printRdn(dpn->dpn.rdn, parser); + break; + default: + printf("***BOGUS CE_DistributionPointName.nameType\n"); + break; + } +} + +static void printDistPoint( + const CE_CRLDistributionPoint *dp, + OidParser &parser) +{ + if(dp->distPointName) { + printf(" Dist pt Name :\n"); + printDistPointName(dp->distPointName, parser); + } + printf(" reasonsPresent : %s\n", dp->reasonsPresent ? "TRUE" : "FALSE"); + if(dp->reasonsPresent) { + /* FIXME - parse */ + printf(" reasons : 0x%X\n", dp->reasons); + } + if(dp->crlIssuer) { + printf(" CRLIssuer :\n"); + printGeneralNames(dp->crlIssuer, parser); + } +} + +static void printDistributionPoints( + const CSSM_DATA &value, + OidParser &parser) +{ + CSSM_X509_EXTENSION *cssmExt = (CSSM_X509_EXTENSION *)value.Data; + CE_CRLDistPointsSyntax *dps = (CE_CRLDistPointsSyntax *)cssmExt->value.parsedValue; + + for(unsigned dex=0; dexnumDistPoints; dex++) { + printf(" Dist pt %d :\n", dex); + printDistPoint(&dps->distPoints[dex], parser); + } +} + +static void printValueOrNotPresent( + CSSM_BOOL present, + CSSM_BOOL value) +{ + if(!present) { + printf("\n"); + } + else if(value) { + printf("TRUE\n"); + } + else { + printf("FALSE"); + } +} + +static void printIssuingDistributionPoint( + const CE_IssuingDistributionPoint *idp, + OidParser &parser) +{ + if(idp->distPointName) { + printf(" Dist pt :\n"); + printDistPointName(idp->distPointName, parser); + } + printf(" Only user certs : "); + printValueOrNotPresent(idp->onlyUserCertsPresent, idp->onlyUserCerts); + printf(" Only CA certs : "); + printValueOrNotPresent(idp->onlyCACertsPresent, idp->onlyCACerts); + printf(" Only some reason: "); + printValueOrNotPresent(idp->onlySomeReasonsPresent, idp->onlySomeReasons); + printf(" Indirectl CRL : "); + printValueOrNotPresent(idp->indirectCrlPresent, idp->indirectCrl); +} + +static void printCertPolicies( + const CSSM_DATA &value, + OidParser &parser) +{ + CSSM_X509_EXTENSION *cssmExt = (CSSM_X509_EXTENSION *)value.Data; + CE_CertPolicies *cdsaObj = (CE_CertPolicies *)cssmExt->value.parsedValue; + for(unsigned polDex=0; polDexnumPolicies; polDex++) { + CE_PolicyInformation *cPolInfo = &cdsaObj->policies[polDex]; + printf(" Policy %2d : ID ", polDex); + printOid(parser, &cPolInfo->certPolicyId); + for(unsigned qualDex=0; qualDexnumPolicyQualifiers; qualDex++) { + CE_PolicyQualifierInfo *cQualInfo = &cPolInfo->policyQualifiers[qualDex]; + printf(" Qual %2d : ID ", qualDex); + printOid(parser, &cQualInfo->policyQualifierId); + if(cuCompareCssmData(&cQualInfo->policyQualifierId, + &CSSMOID_QT_CPS)) { + printf(" CPS : "); + printString(&cQualInfo->qualifier); + } + else { + printf(" unparsed : "); + printDataAsHex(&cQualInfo->qualifier, 8); + } + } + } +} + +static void printNetscapeCertType( + const CSSM_DATA &value) +{ + CE_NetscapeCertType certType; + CSSM_X509_EXTENSION *cssmExt = (CSSM_X509_EXTENSION *)value.Data; + + certType = *((CE_NetscapeCertType *)cssmExt->value.parsedValue); + printf(" certType : "); + if(certType & CE_NCT_SSL_Client) { + printf("SSL_Client "); + } + if(certType & CE_NCT_SSL_Server) { + printf("SSL_Server "); + } + if(certType & CE_NCT_SMIME) { + printf("S/MIME "); + } + if(certType & CE_NCT_ObjSign) { + printf("ObjectSign "); + } + if(certType & CE_NCT_Reserved) { + printf("Reserved "); + } + if(certType & CE_NCT_SSL_CA) { + printf("SSL_CA "); + } + if(certType & CE_NCT_SMIME_CA) { + printf("SMIME_CA "); + } + if(certType & CE_NCT_ObjSignCA) { + printf("ObjSignCA "); + } + printf("\n"); +} + +static void printAuthorityInfoAccess( + const CSSM_DATA &value, + OidParser &parser) +{ + CSSM_X509_EXTENSION *cssmExt = (CSSM_X509_EXTENSION *)value.Data; + CE_AuthorityInfoAccess *info = (CE_AuthorityInfoAccess *)cssmExt->value.parsedValue; + + printf(" numDescriptions : %lu\n", (unsigned long)info->numAccessDescriptions); + for(unsigned dex=0; dexnumAccessDescriptions; dex++) { + printf(" description %u : \n", dex); + printf(" accessMethod : "); + CE_AccessDescription *descr = &info->accessDescriptions[dex]; + printOid(parser, &descr->accessMethod); + printGeneralName(&descr->accessLocation, parser); + } +} + +static void printQualCertStatements( + const CSSM_DATA &value, + OidParser &parser) +{ + CSSM_X509_EXTENSION *cssmExt = (CSSM_X509_EXTENSION *)value.Data; + CE_QC_Statements *qcss = (CE_QC_Statements *)cssmExt->value.parsedValue; + + printf(" numQCStatements : %lu\n", (unsigned long)qcss->numQCStatements); + for(unsigned dex=0; dexnumQCStatements; dex++) { + CE_QC_Statement *qcs = &qcss->qcStatements[dex]; + + printf(" statement %u : \n", dex); + printf(" statementId : "); + printOid(parser, &qcs->statementId); + if(qcs->semanticsInfo) { + printf(" semanticsInfo :\n"); + CE_SemanticsInformation *si = qcs->semanticsInfo; + if(si->semanticsIdentifier) { + printf(" semanticsId : "); + printOid(parser, si->semanticsIdentifier); + } + if(si->nameRegistrationAuthorities) { + printf(" nameRegAuth :\n"); + printGeneralNames(si->nameRegistrationAuthorities, parser); + } + } + if(qcs->otherInfo) { + printf(" otherInfo : "); printDataAsHex(qcs->otherInfo, 8); + } + } +} + +/* print one field */ +void printCertField( + const CSSM_FIELD &field, + OidParser &parser, + CSSM_BOOL verbose) +{ + const CSSM_DATA *thisData = &field.FieldValue; + const CSSM_OID *thisOid = &field.FieldOid; + + if(cuCompareCssmData(thisOid, &CSSMOID_X509V1Version)) { + if(verbose) { + printf("Version : %u\n", cuDER_ToInt(thisData)); + } + } + else if(cuCompareCssmData(thisOid, &CSSMOID_X509V1SerialNumber)) { + printf("Serial Number : "); printDataAsHex(thisData, 0); + } + else if(cuCompareCssmData(thisOid, &CSSMOID_X509V1IssuerNameCStruct)) { + printf("Issuer Name :\n"); + CSSM_X509_NAME_PTR name = (CSSM_X509_NAME_PTR)thisData->Data; + if((name == NULL) || (thisData->Length != sizeof(CSSM_X509_NAME))) { + printf(" ***malformed CSSM_X509_NAME\n"); + } + else { + printName(name, parser); + } + } + else if(cuCompareCssmData(thisOid, &CSSMOID_X509V1SubjectNameCStruct)) { + printf("Subject Name :\n"); + CSSM_X509_NAME_PTR name = (CSSM_X509_NAME_PTR)thisData->Data; + if((name == NULL) || (thisData->Length != sizeof(CSSM_X509_NAME))) { + printf(" ***malformed CSSM_X509_NAME\n"); + } + else { + printName(name, parser); + } + } + else if(cuCompareCssmData(thisOid, &CSSMOID_X509V1ValidityNotBefore)) { + CSSM_X509_TIME *cssmTime = (CSSM_X509_TIME *)thisData->Data; + if((cssmTime == NULL) || (thisData->Length != sizeof(CSSM_X509_TIME))) { + printf(" ***malformed CSSM_X509_TIME\n"); + } + else if(verbose) { + printf("Not Before : "); printString(&cssmTime->time); + printf(" : "); + printTime(cssmTime); + } + else { + printf("Not Before : "); + printTime(cssmTime); + } + } + else if(cuCompareCssmData(thisOid, &CSSMOID_X509V1ValidityNotAfter)) { + CSSM_X509_TIME *cssmTime = (CSSM_X509_TIME *)thisData->Data; + if((cssmTime == NULL) || (thisData->Length != sizeof(CSSM_X509_TIME))) { + printf(" ***malformed CSSM_X509_TIME\n"); + } + else if(verbose) { + printf("Not After : "); printString(&cssmTime->time); + printf(" : "); + printTime(cssmTime); + } + else { + printf("Not After : "); + printTime(cssmTime); + } + } + else if(cuCompareCssmData(thisOid, &CSSMOID_X509V1SignatureAlgorithmTBS)) { + if(verbose) { + /* normally skip, it's the same as TBS sig alg */ + printf("TBS Sig Algorithm : "); + CSSM_X509_ALGORITHM_IDENTIFIER *algId = + (CSSM_X509_ALGORITHM_IDENTIFIER *)thisData->Data; + if((algId == NULL) || + (thisData->Length != sizeof(CSSM_X509_ALGORITHM_IDENTIFIER))) { + printf(" ***malformed CSSM_X509_ALGORITHM_IDENTIFIER\n"); + } + else { + printSigAlg(algId, parser); + } + } + } + else if(cuCompareCssmData(thisOid, &CSSMOID_X509V1SignatureAlgorithm)) { + printf("Cert Sig Algorithm : "); + CSSM_X509_ALGORITHM_IDENTIFIER *algId = + (CSSM_X509_ALGORITHM_IDENTIFIER *)thisData->Data; + if((algId == NULL) || + (thisData->Length != sizeof(CSSM_X509_ALGORITHM_IDENTIFIER))) { + printf(" ***malformed CSSM_X509_ALGORITHM_IDENTIFIER\n"); + } + else { + printSigAlg(algId, parser); + } + } + else if(cuCompareCssmData(thisOid, &CSSMOID_X509V1CertificateIssuerUniqueId)) { + if(verbose) { + printf("Issuer UniqueId : "); + printDerThing(BER_TAG_BIT_STRING, thisData, parser); + } + } + else if(cuCompareCssmData(thisOid, &CSSMOID_X509V1CertificateSubjectUniqueId)) { + if(verbose) { + printf("Subject UniqueId : "); + printDerThing(BER_TAG_BIT_STRING, thisData, parser); + } + } + else if(cuCompareCssmData(thisOid, &CSSMOID_X509V1SubjectPublicKeyCStruct)) { + CSSM_X509_SUBJECT_PUBLIC_KEY_INFO *pubKeyInfo = + (CSSM_X509_SUBJECT_PUBLIC_KEY_INFO *)thisData->Data; + printf("Pub Key Algorithm : "); + if((pubKeyInfo == NULL) || + (thisData->Length != sizeof(CSSM_X509_SUBJECT_PUBLIC_KEY_INFO))) { + printf(" ***malformed CSSM_X509_SUBJECT_PUBLIC_KEY_INFO\n"); + } + else { + printSigAlg(&pubKeyInfo->algorithm, parser); + printf("Pub key Bytes : Length %u bytes : ", + (unsigned)pubKeyInfo->subjectPublicKey.Length); + printDataAsHex(&pubKeyInfo->subjectPublicKey, 8); + } + } + else if(cuCompareCssmData(thisOid, &CSSMOID_CSSMKeyStruct)) { + CSSM_KEY_PTR cssmKey = (CSSM_KEY_PTR)thisData->Data; + printf("CSSM Key :\n"); + if((cssmKey == NULL) || + (thisData->Length != sizeof(CSSM_KEY))) { + printf(" ***malformed CSSM_KEY\n"); + } + else { + printKeyHeader(cssmKey->KeyHeader); + if(verbose) { + printf(" Key Blob : "); + printDataAsHex(&cssmKey->KeyData, 8); + } + } + } + else if(cuCompareCssmData(thisOid, &CSSMOID_X509V1Signature)) { + printf("Signature : %u bytes : ", (unsigned)thisData->Length); + printDataAsHex(thisData, 8); + } + else if(cuCompareCssmData(thisOid, &CSSMOID_X509V3CertificateExtensionCStruct)) { + if(printExtensionCommon(*thisData, parser, verbose, false)) { + return; + } + CSSM_X509_EXTENSION *cssmExt = (CSSM_X509_EXTENSION *)thisData->Data; + printf(" Unparsed data : "); printDataAsHex(&cssmExt->BERvalue, 8); + } + else if(cuCompareCssmData(thisOid, &CSSMOID_KeyUsage)) { + if(printExtensionCommon(*thisData, parser, verbose)) { + return; + } + printKeyUsage(*thisData); + } + else if(cuCompareCssmData(thisOid, &CSSMOID_BasicConstraints)) { + if(printExtensionCommon(*thisData, parser, verbose)) { + return; + } + printBasicConstraints(*thisData); + } + else if(cuCompareCssmData(thisOid, &CSSMOID_ExtendedKeyUsage)) { + if(printExtensionCommon(*thisData, parser, verbose)) { + return; + } + printExtKeyUsage(*thisData, parser); + } + else if(cuCompareCssmData(thisOid, &CSSMOID_SubjectKeyIdentifier)) { + if(printExtensionCommon(*thisData, parser, verbose)) { + return; + } + CSSM_X509_EXTENSION *cssmExt = (CSSM_X509_EXTENSION *)thisData->Data; + CSSM_DATA_PTR cdata = (CSSM_DATA_PTR)cssmExt->value.parsedValue; + if((cdata == NULL) || (cdata->Data == NULL)) { + printf("****Malformed extension (no parsedValue)\n"); + } + else { + printf(" Subject KeyID : "); printDataAsHex(cdata, 8); + } + } + else if(cuCompareCssmData(thisOid, &CSSMOID_AuthorityKeyIdentifier)) { + if(printExtensionCommon(*thisData, parser, verbose)) { + return; + } + printAuthorityKeyId(*thisData, parser); + } + else if(cuCompareCssmData(thisOid, &CSSMOID_SubjectAltName)) { + if(printExtensionCommon(*thisData, parser, verbose)) { + return; + } + printSubjectIssuerAltName(*thisData, parser); + } + else if(cuCompareCssmData(thisOid, &CSSMOID_IssuerAltName)) { + if(printExtensionCommon(*thisData, parser, verbose)) { + return; + } + printSubjectIssuerAltName(*thisData, parser); + } + else if(cuCompareCssmData(thisOid, &CSSMOID_CertificatePolicies)) { + if(printExtensionCommon(*thisData, parser, verbose)) { + return; + } + printCertPolicies(*thisData, parser); + } + else if(cuCompareCssmData(thisOid, &CSSMOID_NetscapeCertType)) { + if(printExtensionCommon(*thisData, parser, verbose)) { + return; + } + printNetscapeCertType(*thisData); + } + else if(cuCompareCssmData(thisOid, &CSSMOID_CrlDistributionPoints)) { + if(printExtensionCommon(*thisData, parser, verbose)) { + return; + } + printDistributionPoints(*thisData, parser); + } + else if(cuCompareCssmData(thisOid, &CSSMOID_AuthorityInfoAccess)) { + if(printExtensionCommon(*thisData, parser, verbose)) { + return; + } + printAuthorityInfoAccess(*thisData, parser); + } + else if(cuCompareCssmData(thisOid, &CSSMOID_SubjectInfoAccess)) { + if(printExtensionCommon(*thisData, parser, verbose)) { + return; + } + printAuthorityInfoAccess(*thisData, parser); + } + else if(cuCompareCssmData(thisOid, &CSSMOID_QC_Statements)) { + if(printExtensionCommon(*thisData, parser, verbose)) { + return; + } + printQualCertStatements(*thisData, parser); + } + else if(cuCompareCssmData(thisOid, &CSSMOID_X509V1IssuerName)) { + if(verbose) { + printf("Normalized Issuer : "); + printDataAsHex(thisData, 8); + } + } + else if(cuCompareCssmData(thisOid, &CSSMOID_X509V1SubjectName)) { + if(verbose) { + printf("Normalized Subject : "); + printDataAsHex(thisData, 8); + } + } + else if(cuCompareCssmData(thisOid, &CSSMOID_X509V1IssuerNameStd)) { + if(verbose) { + printf("DER-encoded issuer : "); + printDataAsHex(thisData, 8); + } + } + else if(cuCompareCssmData(thisOid, &CSSMOID_X509V1SubjectNameStd)) { + if(verbose) { + printf("DER-encoded subject: "); + printDataAsHex(thisData, 8); + } + } + else { + printf("Other field: : "); printOid(parser, thisOid); + } +} + +void printCrlExten( + const CSSM_X509_EXTENSION *exten, + CSSM_BOOL verbose, + OidParser &parser) +{ + const CSSM_OID *oid = &exten->extnId; + const void *thisData = exten->value.parsedValue; + + if(exten->format == CSSM_X509_DATAFORMAT_ENCODED) { + if(printCdsaExtensionCommon(exten, parser, false, verbose)) { + return; + } + printf(" Unparsed data : "); printDataAsHex(&exten->BERvalue, 8); + } + else if(exten->format != CSSM_X509_DATAFORMAT_PARSED) { + printf("***Badly formatted CSSM_X509_EXTENSION\n"); + return; + } + else if(cuCompareCssmData(oid, &CSSMOID_AuthorityKeyIdentifier)) { + if(printCdsaExtensionCommon(exten, parser, true, verbose)) { + return; + } + printCssmAuthorityKeyId((CE_AuthorityKeyID *)thisData, parser); + } + else if(cuCompareCssmData(oid, &CSSMOID_IssuerAltName)) { + if(printCdsaExtensionCommon(exten, parser, true, verbose)) { + return; + } + printGeneralNames((CE_GeneralNames *)thisData, parser); + } + else if(cuCompareCssmData(oid, &CSSMOID_CrlNumber)) { + if(printCdsaExtensionCommon(exten, parser, true, verbose)) { + return; + } + printf(" CRL Number : %u\n", *((unsigned *)thisData)); + } + else if(cuCompareCssmData(oid, &CSSMOID_DeltaCrlIndicator)) { + if(printCdsaExtensionCommon(exten, parser, true, verbose)) { + return; + } + printf(" Delta CRL Base : %u\n", *((unsigned *)thisData)); + } + else if(cuCompareCssmData(oid, &CSSMOID_IssuingDistributionPoint)) { + if(printCdsaExtensionCommon(exten, parser, true, verbose)) { + return; + } + printIssuingDistributionPoint((CE_IssuingDistributionPoint *)thisData, + parser); + } + else { + /* should never happen - we're out of sync with the CL */ + printf("UNKNOWN EXTENSION : "); printOid(parser, oid); + } +} + +void printCrlEntryExten( + const CSSM_X509_EXTENSION *exten, + CSSM_BOOL verbose, + OidParser &parser) +{ + const CSSM_OID *oid = &exten->extnId; + const void *thisData = exten->value.parsedValue; + + if(exten->format == CSSM_X509_DATAFORMAT_ENCODED) { + if(printCdsaExtensionCommon(exten, parser, false, verbose, true)) { + return; + } + printf(" Unparsed data: "); printDataAsHex(&exten->BERvalue, 8); + } + else if(exten->format != CSSM_X509_DATAFORMAT_PARSED) { + printf("***Badly formatted CSSM_X509_EXTENSION\n"); + return; + } + else if(cuCompareCssmData(oid, &CSSMOID_CrlReason)) { + if(printCdsaExtensionCommon(exten, parser, true, verbose, true)) { + return; + } + CE_CrlReason *cr = (CE_CrlReason *)thisData; + const char *reason = "UNKNOWN"; + switch(*cr) { + case CE_CR_Unspecified: + reason = "CE_CR_Unspecified"; break; + case CE_CR_KeyCompromise: + reason = "CE_CR_KeyCompromise"; break; + case CE_CR_CACompromise: + reason = "CE_CR_CACompromise"; break; + case CE_CR_AffiliationChanged: + reason = "CE_CR_AffiliationChanged"; break; + case CE_CR_Superseded: + reason = "CE_CR_Superseded"; break; + case CE_CR_CessationOfOperation: + reason = "CE_CR_CessationOfOperation"; break; + case CE_CR_CertificateHold: + reason = "CE_CR_CertificateHold"; break; + case CE_CR_RemoveFromCRL: + reason = "CE_CR_RemoveFromCRL"; break; + default: + break; + } + printf(" CRL Reason : %s\n", reason); + } + else if(cuCompareCssmData(oid, &CSSMOID_HoldInstructionCode)) { + if(printCdsaExtensionCommon(exten, parser, true, verbose, true)) { + return; + } + printf(" Hold Instr : "); + printOid(parser, (CSSM_OID_PTR)thisData); + } + else if(cuCompareCssmData(oid, &CSSMOID_InvalidityDate)) { + if(printCdsaExtensionCommon(exten, parser, true, verbose, true)) { + return; + } + printf(" Invalid Date : "); + printTimeStr((CSSM_DATA_PTR)thisData); + } + else if(cuCompareCssmData(oid, &CSSMOID_CertIssuer)) { + if(printCdsaExtensionCommon(exten, parser, true, verbose, true)) { + return; + } + printGeneralNames((CE_GeneralNames *)thisData, parser); + } + else { + /* should never happen - we're out of sync with the CL */ + printf("UNKNOWN EXTENSION : "); printOid(parser, oid); + } +} + +void printCrlFields( + const CSSM_X509_SIGNED_CRL *signedCrl, + CSSM_BOOL verbose, + OidParser &parser) +{ + unsigned i; + const CSSM_X509_TBS_CERTLIST *tbsCrl = &signedCrl->tbsCertList; + + if(tbsCrl->version.Data) { + printf("Version : %d\n", cuDER_ToInt(&tbsCrl->version)); + } + + printf("TBS Sig Algorithm : "); + const CSSM_X509_ALGORITHM_IDENTIFIER *algId = &tbsCrl->signature; + printSigAlg(algId, parser); + + printf("Issuer Name :\n"); + printName(&tbsCrl->issuer, parser); + + printf("This Update : "); + printTime(&tbsCrl->thisUpdate); + printf("Next Update : "); + if(tbsCrl->nextUpdate.time.Data) { + printTime(&tbsCrl->nextUpdate); + } + else { + printf("\n"); + } + + CSSM_X509_REVOKED_CERT_LIST_PTR certList = tbsCrl->revokedCertificates; + if(certList) { + if(verbose) { + printf("Num Revoked Certs : %d\n", + (int)certList->numberOfRevokedCertEntries); + for(i=0; inumberOfRevokedCertEntries; i++) { + CSSM_X509_REVOKED_CERT_ENTRY_PTR entry; + entry = &certList->revokedCertEntry[i]; + printf("Revoked Cert %d :\n", (int)i); + printf(" Serial number : "); + printDataAsHex(&entry->certificateSerialNumber, 0); + printf(" Revocation time : "); + printTime(&entry->revocationDate); + const CSSM_X509_EXTENSIONS *cssmExtens = &entry->extensions; + uint32 numExtens = cssmExtens->numberOfExtensions; + if(numExtens == 0) { + continue; + } + printf(" Num Extensions : %u\n", (unsigned)numExtens); + for(unsigned dex=0; dexextensions[dex], verbose, + parser); + } + } + } + else { + printf("Num Revoked Certs : %d (use verbose option to see)\n", + (int)certList->numberOfRevokedCertEntries); + } + } + + const CSSM_X509_EXTENSIONS *crlExtens = &tbsCrl->extensions; + if(crlExtens->numberOfExtensions) { + printf("Num CRL Extensions : %d\n", + (int)crlExtens->numberOfExtensions); + for(i=0; inumberOfExtensions; i++) { + printCrlExten(&crlExtens->extensions[i], verbose, parser); + } + } + + const CSSM_X509_SIGNATURE *sig = &signedCrl->signature; + if(sig->encrypted.Data) { + printf("Signature : %u bytes : ", (unsigned)sig->encrypted.Length); + printDataAsHex(&sig->encrypted, 8); + } +} + + +/* connect to CSSM/CL lazily, once */ +static CSSM_CL_HANDLE clHand = 0; + +int printCert( + const unsigned char *certData, + unsigned certLen, + CSSM_BOOL verbose) +{ + CSSM_FIELD_PTR fieldPtr; // mallocd by CL + uint32 i; + uint32 numFields; + OidParser parser; + CSSM_DATA cert; + + if(clHand == 0) { + clHand = cuClStartup(); + if(clHand == 0) { + printf("***Error connecting to CSSM cert module; aborting cert " + "display\n"); + return 0; + } + } + cert.Data = (uint8 *)certData; + cert.Length = certLen; + + CSSM_RETURN crtn = CSSM_CL_CertGetAllFields(clHand, + &cert, + &numFields, + &fieldPtr); + if(crtn) { + cuPrintError("CSSM_CL_CertGetAllFields", crtn); + return crtn; + } + + for(i=0; iData == NULL) || + (value->Length != sizeof(CSSM_X509_SIGNED_CRL))) { + printf("***CSSM_CL_CrlGetFirstFieldValue: value error (2)\n"); + return 1; + } + const CSSM_X509_SIGNED_CRL *signedCrl = + (const CSSM_X509_SIGNED_CRL *)value->Data; + printCrlFields(signedCrl, verbose, parser); + + crtn = CSSM_CL_FreeFieldValue(clHand, + &CSSMOID_X509V2CRLSignedCrlCStruct, + value); + if(crtn) { + cuPrintError("CSSM_CL_FreeFieldValue", crtn); + return crtn; + } + return 0; +} + + +void printCertShutdown() +{ + if(clHand != 0) { + CSSM_ModuleDetach(clHand); + } +} diff --git a/libsecurity_cdsa_utils/lib/cuPrintCert.h b/libsecurity_cdsa_utils/lib/cuPrintCert.h new file mode 100644 index 00000000..b62ec735 --- /dev/null +++ b/libsecurity_cdsa_utils/lib/cuPrintCert.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2002 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. + */ + +/* + * cuPrintCert.h - text-based cert/CRL parser using CL + */ + +#ifndef _PRINT_CERT_H_ +#define _PRINT_CERT_H_ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* print one field */ +void printCertField( + const CSSM_FIELD &field, + OidParser &parser, + CSSM_BOOL verbose); + +/* parse cert & print it */ +int printCert( + const unsigned char *certData, + unsigned certLen, + CSSM_BOOL verbose); + +/* print parsed CRL */ +void printCrlFields( + const CSSM_X509_SIGNED_CRL *signedCrl, + OidParser &parser); + +/* parse CRL & print it */ +int printCrl( + const unsigned char *crlData, + unsigned crlLen, + CSSM_BOOL verbose); + + +void printCertShutdown(); + +#ifdef __cplusplus +} +#endif + +#endif /* _PRINT_CERT_H_ */ diff --git a/libsecurity_cdsa_utils/lib/cuTimeStr.cpp b/libsecurity_cdsa_utils/lib/cuTimeStr.cpp new file mode 100644 index 00000000..39028cac --- /dev/null +++ b/libsecurity_cdsa_utils/lib/cuTimeStr.cpp @@ -0,0 +1,293 @@ +/* + * Copyright (c) 2002 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. + */ + +/* + * cuTimeStr.cpp - time string routines + */ +#include "cuTimeStr.h" +#include "cuCdsaUtils.h" +#include +#include +#include +#include +#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 cuTimeStringToTm( + const char *str, + unsigned len, + struct tm *tmp) +{ + char szTemp[5]; + unsigned isUtc = 0; + unsigned noSeconds = 0; + 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_NOSEC_LEN: // 2-digit year, no seconds, not y2K compliant + isUtc = 1; + noSeconds = 1; + break; + case UTC_TIME_STRLEN: // 2-digit year, not Y2K compliant + isUtc = 1; + break; + case GENERALIZED_TIME_STRLEN: // 4-digit year + 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, though we tolerate + * 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 */ + if(noSeconds) { + tmp->tm_sec = 0; + } + else { + 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; +} + +#define MAX_TIME_STR_LEN 30 + +/* protects time(), gmtime() */ +static pthread_mutex_t timeMutex = PTHREAD_MUTEX_INITIALIZER; + +char *cuTimeAtNowPlus(int secFromNow, + timeSpec spec) +{ + struct tm utc; + char *outStr; + time_t baseTime; + + pthread_mutex_lock(&timeMutex); + baseTime = time(NULL); + baseTime += (time_t)secFromNow; + utc = *gmtime(&baseTime); + pthread_mutex_unlock(&timeMutex); + + outStr = (char *)APP_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; +} + +/* + * 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 *cuX509TimeToCssmTimestring( + 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/libsecurity_cdsa_utils/lib/cuTimeStr.h b/libsecurity_cdsa_utils/lib/cuTimeStr.h new file mode 100644 index 00000000..cad00720 --- /dev/null +++ b/libsecurity_cdsa_utils/lib/cuTimeStr.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2002 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. + */ + +/* + * cuTimeStr.h = Time string utilities. + */ + +#ifndef _TIME_STR_H_ +#define _TIME_STR_H_ + +#include +#include + +#define UTC_TIME_NOSEC_LEN 11 +#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 cuTimeStringToTm( + const char *str, + unsigned len, + struct tm *tmp); + +typedef enum { + TIME_UTC, + TIME_CSSM, + TIME_GEN +} timeSpec; + +/* + * Return an APP_MALLOCd time string, specified format and time relative + * to 'now' in seconds. + */ +char *cuTimeAtNowPlus( + int secFromNow, + timeSpec spec); + +/* + * 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 *cuX509TimeToCssmTimestring( + const CSSM_X509_TIME *x509Time, + unsigned *rtnLen); // for caller's convenience + +#ifdef __cplusplus +} +#endif + +#endif /* _TIME_STR_H_ */ diff --git a/libsecurity_cdsa_utils/libsecurity_cdsa_utils.xcodeproj/project.pbxproj b/libsecurity_cdsa_utils/libsecurity_cdsa_utils.xcodeproj/project.pbxproj new file mode 100644 index 00000000..bc4c73ab --- /dev/null +++ b/libsecurity_cdsa_utils/libsecurity_cdsa_utils.xcodeproj/project.pbxproj @@ -0,0 +1,270 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 1865FBCF14723BB300FD79DF /* cuCdsaUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C7502EE0540CC4200056564 /* cuCdsaUtils.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1865FBD014723BB300FD79DF /* cuDbUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C7502F00540CC4200056564 /* cuDbUtils.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1865FBD114723BB300FD79DF /* cuEnc64.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C7502F20540CC4200056564 /* cuEnc64.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1865FBD214723BB300FD79DF /* cuFileIo.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C7502F40540CC4200056564 /* cuFileIo.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1865FBD314723BB300FD79DF /* cuOidParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C7502F60540CC4200056564 /* cuOidParser.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1865FBD414723BB300FD79DF /* cuPem.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C7502F80540CC4200056564 /* cuPem.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1865FBD514723BB300FD79DF /* cuPrintCert.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C7502FA0540CC4200056564 /* cuPrintCert.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1865FBD614723BB300FD79DF /* cuTimeStr.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C7502FC0540CC4200056564 /* cuTimeStr.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 4C7502FD0540CC4200056564 /* cuCdsaUtils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C7502ED0540CC4200056564 /* cuCdsaUtils.cpp */; settings = {COMPILER_FLAGS = "-fno-rtti -fno-exceptions"; }; }; + 4C7502FF0540CC4200056564 /* cuDbUtils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C7502EF0540CC4200056564 /* cuDbUtils.cpp */; settings = {COMPILER_FLAGS = "-fno-rtti -fno-exceptions"; }; }; + 4C7503010540CC4200056564 /* cuEnc64.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C7502F10540CC4200056564 /* cuEnc64.c */; }; + 4C7503030540CC4200056564 /* cuFileIo.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C7502F30540CC4200056564 /* cuFileIo.c */; }; + 4C7503050540CC4200056564 /* cuOidParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C7502F50540CC4200056564 /* cuOidParser.cpp */; settings = {COMPILER_FLAGS = "-fno-rtti -fno-exceptions"; }; }; + 4C7503070540CC4200056564 /* cuPem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C7502F70540CC4200056564 /* cuPem.cpp */; settings = {COMPILER_FLAGS = "-fno-rtti -fno-exceptions"; }; }; + 4C7503090540CC4200056564 /* cuPrintCert.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C7502F90540CC4200056564 /* cuPrintCert.cpp */; settings = {COMPILER_FLAGS = "-fno-rtti -fno-exceptions"; }; }; + 4C75030B0540CC4200056564 /* cuTimeStr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C7502FB0540CC4200056564 /* cuTimeStr.cpp */; settings = {COMPILER_FLAGS = "-fno-rtti -fno-exceptions"; }; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 1879B51B146DD04F007E536C /* base.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = base.xcconfig; sourceTree = ""; }; + 1879B51C146DD04F007E536C /* debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = debug.xcconfig; sourceTree = ""; }; + 1879B51D146DD04F007E536C /* lib.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = lib.xcconfig; sourceTree = ""; }; + 1879B51E146DD04F007E536C /* release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = release.xcconfig; sourceTree = ""; }; + 4C7502ED0540CC4200056564 /* cuCdsaUtils.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = cuCdsaUtils.cpp; sourceTree = ""; }; + 4C7502EE0540CC4200056564 /* cuCdsaUtils.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cuCdsaUtils.h; sourceTree = ""; }; + 4C7502EF0540CC4200056564 /* cuDbUtils.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = cuDbUtils.cpp; sourceTree = ""; }; + 4C7502F00540CC4200056564 /* cuDbUtils.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cuDbUtils.h; sourceTree = ""; }; + 4C7502F10540CC4200056564 /* cuEnc64.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = cuEnc64.c; sourceTree = ""; }; + 4C7502F20540CC4200056564 /* cuEnc64.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cuEnc64.h; sourceTree = ""; }; + 4C7502F30540CC4200056564 /* cuFileIo.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = cuFileIo.c; sourceTree = ""; }; + 4C7502F40540CC4200056564 /* cuFileIo.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cuFileIo.h; sourceTree = ""; }; + 4C7502F50540CC4200056564 /* cuOidParser.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = cuOidParser.cpp; sourceTree = ""; }; + 4C7502F60540CC4200056564 /* cuOidParser.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cuOidParser.h; sourceTree = ""; }; + 4C7502F70540CC4200056564 /* cuPem.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = cuPem.cpp; sourceTree = ""; }; + 4C7502F80540CC4200056564 /* cuPem.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cuPem.h; sourceTree = ""; }; + 4C7502F90540CC4200056564 /* cuPrintCert.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = cuPrintCert.cpp; sourceTree = ""; }; + 4C7502FA0540CC4200056564 /* cuPrintCert.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cuPrintCert.h; sourceTree = ""; }; + 4C7502FB0540CC4200056564 /* cuTimeStr.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = cuTimeStr.cpp; sourceTree = ""; }; + 4C7502FC0540CC4200056564 /* cuTimeStr.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cuTimeStr.h; sourceTree = ""; }; + 4CA1FEBE052A3C8100F22E42 /* libsecurity_cdsa_utils.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libsecurity_cdsa_utils.a; sourceTree = BUILT_PRODUCTS_DIR; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 4CA1FEBB052A3C8100F22E42 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 1879B51A146DD04F007E536C /* config */ = { + isa = PBXGroup; + children = ( + 1879B51B146DD04F007E536C /* base.xcconfig */, + 1879B51C146DD04F007E536C /* debug.xcconfig */, + 1879B51D146DD04F007E536C /* lib.xcconfig */, + 1879B51E146DD04F007E536C /* release.xcconfig */, + ); + name = config; + path = ../config; + sourceTree = ""; + }; + 4C7502EC0540CC4200056564 /* lib */ = { + isa = PBXGroup; + children = ( + 4C7502ED0540CC4200056564 /* cuCdsaUtils.cpp */, + 4C7502EE0540CC4200056564 /* cuCdsaUtils.h */, + 4C7502EF0540CC4200056564 /* cuDbUtils.cpp */, + 4C7502F00540CC4200056564 /* cuDbUtils.h */, + 4C7502F10540CC4200056564 /* cuEnc64.c */, + 4C7502F20540CC4200056564 /* cuEnc64.h */, + 4C7502F30540CC4200056564 /* cuFileIo.c */, + 4C7502F40540CC4200056564 /* cuFileIo.h */, + 4C7502F50540CC4200056564 /* cuOidParser.cpp */, + 4C7502F60540CC4200056564 /* cuOidParser.h */, + 4C7502F70540CC4200056564 /* cuPem.cpp */, + 4C7502F80540CC4200056564 /* cuPem.h */, + 4C7502F90540CC4200056564 /* cuPrintCert.cpp */, + 4C7502FA0540CC4200056564 /* cuPrintCert.h */, + 4C7502FB0540CC4200056564 /* cuTimeStr.cpp */, + 4C7502FC0540CC4200056564 /* cuTimeStr.h */, + ); + path = lib; + sourceTree = ""; + }; + 4CA1FEA7052A3C3800F22E42 = { + isa = PBXGroup; + children = ( + 4C7502EC0540CC4200056564 /* lib */, + 1879B51A146DD04F007E536C /* config */, + 4CA1FEBF052A3C8100F22E42 /* Products */, + ); + sourceTree = ""; + }; + 4CA1FEBF052A3C8100F22E42 /* Products */ = { + isa = PBXGroup; + children = ( + 4CA1FEBE052A3C8100F22E42 /* libsecurity_cdsa_utils.a */, + ); + name = Products; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 4CA1FEB9052A3C8100F22E42 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 1865FBCF14723BB300FD79DF /* cuCdsaUtils.h in Headers */, + 1865FBD014723BB300FD79DF /* cuDbUtils.h in Headers */, + 1865FBD114723BB300FD79DF /* cuEnc64.h in Headers */, + 1865FBD214723BB300FD79DF /* cuFileIo.h in Headers */, + 1865FBD314723BB300FD79DF /* cuOidParser.h in Headers */, + 1865FBD414723BB300FD79DF /* cuPem.h in Headers */, + 1865FBD514723BB300FD79DF /* cuPrintCert.h in Headers */, + 1865FBD614723BB300FD79DF /* cuTimeStr.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 4CA1FEBD052A3C8100F22E42 /* libsecurity_cdsa_utils */ = { + isa = PBXNativeTarget; + buildConfigurationList = C27AD3040987FCDE001272E0 /* Build configuration list for PBXNativeTarget "libsecurity_cdsa_utils" */; + buildPhases = ( + 4CA1FEB9052A3C8100F22E42 /* Headers */, + 4CA1FEBA052A3C8100F22E42 /* Sources */, + 4CA1FEBB052A3C8100F22E42 /* Frameworks */, + 18B96B0414743F83005A4D2E /* ShellScript */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = libsecurity_cdsa_utils; + productName = libsecurity_cdsa_utils; + productReference = 4CA1FEBE052A3C8100F22E42 /* libsecurity_cdsa_utils.a */; + productType = "com.apple.product-type.library.static"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 4CA1FEAB052A3C3800F22E42 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0420; + }; + buildConfigurationList = C27AD3080987FCDE001272E0 /* Build configuration list for PBXProject "libsecurity_cdsa_utils" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 1; + knownRegions = ( + en, + ); + mainGroup = 4CA1FEA7052A3C3800F22E42; + productRefGroup = 4CA1FEBF052A3C8100F22E42 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 4CA1FEBD052A3C8100F22E42 /* libsecurity_cdsa_utils */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXShellScriptBuildPhase section */ + 18B96B0414743F83005A4D2E /* 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 = ( + 4C7502FD0540CC4200056564 /* cuCdsaUtils.cpp in Sources */, + 4C7502FF0540CC4200056564 /* cuDbUtils.cpp in Sources */, + 4C7503010540CC4200056564 /* cuEnc64.c in Sources */, + 4C7503030540CC4200056564 /* cuFileIo.c in Sources */, + 4C7503050540CC4200056564 /* cuOidParser.cpp in Sources */, + 4C7503070540CC4200056564 /* cuPem.cpp in Sources */, + 4C7503090540CC4200056564 /* cuPrintCert.cpp in Sources */, + 4C75030B0540CC4200056564 /* cuTimeStr.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + C27AD3050987FCDE001272E0 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1879B51C146DD04F007E536C /* debug.xcconfig */; + buildSettings = { + PUBLIC_HEADERS_FOLDER_PATH = /usr/local/include/security_cdsa_utils; + SKIP_INSTALL = NO; + }; + name = Debug; + }; + C27AD3070987FCDE001272E0 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1879B51E146DD04F007E536C /* release.xcconfig */; + buildSettings = { + PUBLIC_HEADERS_FOLDER_PATH = /usr/local/include/security_cdsa_utils; + SKIP_INSTALL = NO; + }; + name = Release; + }; + C27AD3090987FCDE001272E0 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1879B51D146DD04F007E536C /* lib.xcconfig */; + buildSettings = { + }; + name = Debug; + }; + C27AD30B0987FCDE001272E0 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1879B51D146DD04F007E536C /* lib.xcconfig */; + buildSettings = { + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + C27AD3040987FCDE001272E0 /* Build configuration list for PBXNativeTarget "libsecurity_cdsa_utils" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C27AD3050987FCDE001272E0 /* Debug */, + C27AD3070987FCDE001272E0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C27AD3080987FCDE001272E0 /* Build configuration list for PBXProject "libsecurity_cdsa_utils" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C27AD3090987FCDE001272E0 /* Debug */, + C27AD30B0987FCDE001272E0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 4CA1FEAB052A3C3800F22E42 /* Project object */; +} diff --git a/libsecurity_checkpw/APPLE_LICENSE b/libsecurity_checkpw/APPLE_LICENSE new file mode 100644 index 00000000..71fe6fd7 --- /dev/null +++ b/libsecurity_checkpw/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/libsecurity_checkpw/Info-security_checkpw.plist b/libsecurity_checkpw/Info-security_checkpw.plist new file mode 100644 index 00000000..7685bd64 --- /dev/null +++ b/libsecurity_checkpw/Info-security_checkpw.plist @@ -0,0 +1,5 @@ + + + + + diff --git a/libsecurity_checkpw/checkpw.pam b/libsecurity_checkpw/checkpw.pam new file mode 100644 index 00000000..24096454 --- /dev/null +++ b/libsecurity_checkpw/checkpw.pam @@ -0,0 +1,3 @@ +# libsecurity_checkpw: auth account +auth required pam_opendirectory.so use_first_pass +account required pam_opendirectory.so no_check_home no_check_shell diff --git a/libsecurity_checkpw/lib/checkpw.c b/libsecurity_checkpw/lib/checkpw.c new file mode 100644 index 00000000..f5207f7d --- /dev/null +++ b/libsecurity_checkpw/lib/checkpw.c @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2000-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. + */ + +#include +#include + +#include "checkpw.h" +#include + +#define PAM_STACK_NAME "checkpw" + +int checkpw_internal_pam( const char* uname, const char* password ) +{ + int checkpwret = CHECKPW_FAILURE; + + int pamret = PAM_SUCCESS; + pam_handle_t *pamh; + struct pam_conv pamc; + pamc.conv = &openpam_nullconv; + + pamret = pam_start(PAM_STACK_NAME, uname, &pamc, &pamh); + if (PAM_SUCCESS != pamret) + { + syslog(LOG_WARNING,"PAM: Unable to start pam."); + goto pamerr_no_end; + } + + pamret = pam_set_item(pamh, PAM_AUTHTOK, password); + if (PAM_SUCCESS != pamret) + { + syslog(LOG_WARNING,"PAM: Unable to set password."); + goto pamerr; + } + + pamret = pam_authenticate(pamh, 0); + if (PAM_SUCCESS != pamret) + { + syslog(LOG_WARNING,"PAM: Unable to authenticate."); + checkpwret = CHECKPW_BADPASSWORD; + goto pamerr; + } + + pamret = pam_acct_mgmt(pamh, 0); + if (PAM_SUCCESS != pamret) + { + if (PAM_NEW_AUTHTOK_REQD == pamret) + { + syslog(LOG_WARNING,"PAM: Unable to authorize, password needs to be changed."); + } else { + syslog(LOG_WARNING,"PAM: Unable to authorize."); + } + + goto pamerr; + } + + checkpwret = CHECKPW_SUCCESS; + +pamerr: + pam_end(pamh, pamret); +pamerr_no_end: + return checkpwret; + +} + +int checkpw_internal( const struct passwd* pw, const char* password ) +{ + return checkpw(pw->pw_name, password); +} + +int checkpw( const char* userName, const char* password ) +{ + int siResult = CHECKPW_FAILURE; + // workaround for 3965234; I assume the empty string is OK... + const char *thePassword = password ? password : ""; + + if (userName == NULL) + return CHECKPW_UNKNOWNUSER; + + siResult = checkpw_internal_pam(userName, thePassword); + switch (siResult) { + case CHECKPW_SUCCESS: + case CHECKPW_UNKNOWNUSER: + case CHECKPW_BADPASSWORD: + break; + default: + usleep(500000); + siResult = checkpw_internal_pam(userName, thePassword); + break; + } + + return siResult; +} + diff --git a/libsecurity_checkpw/lib/checkpw.h b/libsecurity_checkpw/lib/checkpw.h new file mode 100644 index 00000000..4625903d --- /dev/null +++ b/libsecurity_checkpw/lib/checkpw.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2000-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. + */ + +#ifndef __CHKUSRNAMPASSWD_H__ +#define __CHKUSRNAMPASSWD_H__ + +#include + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +enum { + CHECKPW_SUCCESS = 0, + CHECKPW_UNKNOWNUSER = -1, + CHECKPW_BADPASSWORD = -2, + CHECKPW_FAILURE = -3 +}; + +/*! + @function checkpw + + checks a username/password combination. + + @param username (input) username as a UTF8 string + @param password (input) password as a UTF8 string + + @result CHECKPW_SUCCESS username/password correct + CHECKPW_UNKNOWNUSER no such user + CHECKPW_BADPASSWORD wrong password + CHECKPW_FAILURE failed to communicate with DirectoryServices + + @discussion Deprecated and should no longer be used. + Username/password combinations can be checked in two ways: + 1) PAM(3): with the "checkpw" service. + 2) OpenDirectory: ODRecordVerifyPassword() - if you are + currently using OpenDirectory. +*/ + +int checkpw( const char* userName, const char* password ) + __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_1,__MAC_10_7,__IPHONE_NA,__IPHONE_NA); + +#ifdef __cplusplus +} +#endif + +#endif // __CHKUSRNAMPASSWD_H__ diff --git a/libsecurity_checkpw/lib/security_checkpw.exp b/libsecurity_checkpw/lib/security_checkpw.exp new file mode 100644 index 00000000..bf209d81 --- /dev/null +++ b/libsecurity_checkpw/lib/security_checkpw.exp @@ -0,0 +1,2 @@ +_checkpw +_checkpw_internal diff --git a/libsecurity_checkpw/libsecurity_checkpw.xcodeproj/project.pbxproj b/libsecurity_checkpw/libsecurity_checkpw.xcodeproj/project.pbxproj new file mode 100644 index 00000000..28f56cc2 --- /dev/null +++ b/libsecurity_checkpw/libsecurity_checkpw.xcodeproj/project.pbxproj @@ -0,0 +1,385 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 1C6C40271121FC0C00031CDE /* test-checkpw.c in Sources */ = {isa = PBXBuildFile; fileRef = 1CD90B631101115E008DD07F /* test-checkpw.c */; }; + 1C6C40291121FC0C00031CDE /* libpam.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 1CD90B8F110112DD008DD07F /* libpam.dylib */; }; + 1C6C402A1121FC0C00031CDE /* libsecurity_checkpw.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CA1FEBE052A3C8100F22E42 /* libsecurity_checkpw.a */; }; + 1CB7B4C411065DDB003458C5 /* libsecurity_checkpw.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CA1FEBE052A3C8100F22E42 /* libsecurity_checkpw.a */; }; + 1CD90B71110111A4008DD07F /* test-checkpw.c in Sources */ = {isa = PBXBuildFile; fileRef = 1CD90B631101115E008DD07F /* test-checkpw.c */; }; + 1CD90B90110112DD008DD07F /* libpam.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 1CD90B8F110112DD008DD07F /* libpam.dylib */; }; + 1CD90BA2110113AE008DD07F /* libpam.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 1CD90B8F110112DD008DD07F /* libpam.dylib */; }; + 4CCF8664052A491D00F2E8D8 /* checkpw.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CCF8662052A491D00F2E8D8 /* checkpw.c */; }; + 4CF36F400581369C00834D11 /* checkpw.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CCF8663052A491D00F2E8D8 /* checkpw.h */; settings = {ATTRIBUTES = (); }; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 1C6C40251121FC0C00031CDE /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4CA1FEAB052A3C3800F22E42 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4CA1FEBD052A3C8100F22E42; + remoteInfo = libsecurity_checkpw; + }; + 1CD90B6E11011196008DD07F /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4CA1FEAB052A3C3800F22E42 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4CA1FEBD052A3C8100F22E42; + remoteInfo = libsecurity_checkpw; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 1844616B146E966100B12992 /* base.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = base.xcconfig; sourceTree = ""; }; + 1844616C146E966100B12992 /* debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = debug.xcconfig; sourceTree = ""; }; + 1844616D146E966100B12992 /* lib.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = lib.xcconfig; sourceTree = ""; }; + 1844616E146E966100B12992 /* release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = release.xcconfig; sourceTree = ""; }; + 1C6C402F1121FC0C00031CDE /* perf-checkpw */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "perf-checkpw"; sourceTree = BUILT_PRODUCTS_DIR; }; + 1CB7B49511065A36003458C5 /* checkpw.pam */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = checkpw.pam; sourceTree = ""; }; + 1CD90B631101115E008DD07F /* test-checkpw.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "test-checkpw.c"; path = "test/test-checkpw.c"; sourceTree = ""; }; + 1CD90B6711011176008DD07F /* test-checkpw */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "test-checkpw"; sourceTree = BUILT_PRODUCTS_DIR; }; + 1CD90B8F110112DD008DD07F /* libpam.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libpam.dylib; path = /usr/lib/libpam.dylib; sourceTree = ""; }; + 4CA1FEBE052A3C8100F22E42 /* libsecurity_checkpw.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libsecurity_checkpw.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 4CCBFF50057FFCA600981D43 /* security_checkpw.exp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.exports; path = security_checkpw.exp; sourceTree = ""; }; + 4CCF8662052A491D00F2E8D8 /* checkpw.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = checkpw.c; sourceTree = ""; }; + 4CCF8663052A491D00F2E8D8 /* checkpw.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = checkpw.h; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 1C6C40281121FC0C00031CDE /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 1C6C40291121FC0C00031CDE /* libpam.dylib in Frameworks */, + 1C6C402A1121FC0C00031CDE /* libsecurity_checkpw.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1CD90B6511011176008DD07F /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 1CD90BA2110113AE008DD07F /* libpam.dylib in Frameworks */, + 1CB7B4C411065DDB003458C5 /* libsecurity_checkpw.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4CA1FEBB052A3C8100F22E42 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 1CD90B90110112DD008DD07F /* libpam.dylib in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 1844616A146E966100B12992 /* config */ = { + isa = PBXGroup; + children = ( + 1844616B146E966100B12992 /* base.xcconfig */, + 1844616C146E966100B12992 /* debug.xcconfig */, + 1844616D146E966100B12992 /* lib.xcconfig */, + 1844616E146E966100B12992 /* release.xcconfig */, + ); + name = config; + path = ../config; + sourceTree = ""; + }; + 1CD90B6011011149008DD07F /* test */ = { + isa = PBXGroup; + children = ( + 1CD90B631101115E008DD07F /* test-checkpw.c */, + ); + name = test; + sourceTree = ""; + }; + 4CA1FEA7052A3C3800F22E42 = { + isa = PBXGroup; + children = ( + 1CB7B49511065A36003458C5 /* checkpw.pam */, + 4CCF8661052A491D00F2E8D8 /* lib */, + 1844616A146E966100B12992 /* config */, + 1CD90B6011011149008DD07F /* test */, + 4CA1FEBF052A3C8100F22E42 /* Products */, + 1CD90B8F110112DD008DD07F /* libpam.dylib */, + ); + sourceTree = ""; + }; + 4CA1FEBF052A3C8100F22E42 /* Products */ = { + isa = PBXGroup; + children = ( + 4CA1FEBE052A3C8100F22E42 /* libsecurity_checkpw.a */, + 1CD90B6711011176008DD07F /* test-checkpw */, + 1C6C402F1121FC0C00031CDE /* perf-checkpw */, + ); + name = Products; + sourceTree = ""; + }; + 4CCF8661052A491D00F2E8D8 /* lib */ = { + isa = PBXGroup; + children = ( + 4CCF8662052A491D00F2E8D8 /* checkpw.c */, + 4CCF8663052A491D00F2E8D8 /* checkpw.h */, + 4CCBFF50057FFCA600981D43 /* security_checkpw.exp */, + ); + path = lib; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 4CA1FEB9052A3C8100F22E42 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 4CF36F400581369C00834D11 /* checkpw.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 1C6C40211121FC0C00031CDE /* perf-checkpw */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1C6C402B1121FC0C00031CDE /* Build configuration list for PBXNativeTarget "perf-checkpw" */; + buildPhases = ( + 1C6C40261121FC0C00031CDE /* Sources */, + 1C6C40281121FC0C00031CDE /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + 1C6C40241121FC0C00031CDE /* PBXTargetDependency */, + ); + name = "perf-checkpw"; + productName = "test-checkpw"; + productReference = 1C6C402F1121FC0C00031CDE /* perf-checkpw */; + productType = "com.apple.product-type.tool"; + }; + 1CD90B6611011176008DD07F /* test-checkpw */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1CD90B77110111C3008DD07F /* Build configuration list for PBXNativeTarget "test-checkpw" */; + buildPhases = ( + 1CD90B6411011176008DD07F /* Sources */, + 1CD90B6511011176008DD07F /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + 1CD90B6F11011196008DD07F /* PBXTargetDependency */, + ); + name = "test-checkpw"; + productName = "test-checkpw"; + productReference = 1CD90B6711011176008DD07F /* test-checkpw */; + productType = "com.apple.product-type.tool"; + }; + 4CA1FEBD052A3C8100F22E42 /* libsecurity_checkpw */ = { + isa = PBXNativeTarget; + buildConfigurationList = C27AD3120987FCDE001272E0 /* Build configuration list for PBXNativeTarget "libsecurity_checkpw" */; + buildPhases = ( + 4CA1FEB9052A3C8100F22E42 /* Headers */, + 4CA1FEBA052A3C8100F22E42 /* Sources */, + 4CA1FEBB052A3C8100F22E42 /* Frameworks */, + 1CE6F80B11066C3000300DAA /* Install PAM config */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = libsecurity_checkpw; + productName = libsecurity_checkpw; + productReference = 4CA1FEBE052A3C8100F22E42 /* libsecurity_checkpw.a */; + productType = "com.apple.product-type.library.static"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 4CA1FEAB052A3C3800F22E42 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0420; + }; + buildConfigurationList = C27AD3160987FCDE001272E0 /* Build configuration list for PBXProject "libsecurity_checkpw" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 1; + knownRegions = ( + en, + ); + mainGroup = 4CA1FEA7052A3C3800F22E42; + productRefGroup = 4CA1FEBF052A3C8100F22E42 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 4CA1FEBD052A3C8100F22E42 /* libsecurity_checkpw */, + 1CD90B6611011176008DD07F /* test-checkpw */, + 1C6C40211121FC0C00031CDE /* perf-checkpw */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXShellScriptBuildPhase section */ + 1CE6F80B11066C3000300DAA /* Install PAM config */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 8; + files = ( + ); + inputPaths = ( + ); + name = "Install PAM config"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 1; + shellPath = /bin/sh; + shellScript = "name=checkpw\n\nmkdir -p \"${DSTROOT}/private/etc/pam.d/\"\ncp \"${PROJECT_DIR}/${name}.pam\" \"${DSTROOT}/private/etc/pam.d/${name}\""; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 1C6C40261121FC0C00031CDE /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1C6C40271121FC0C00031CDE /* test-checkpw.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1CD90B6411011176008DD07F /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1CD90B71110111A4008DD07F /* test-checkpw.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4CA1FEBA052A3C8100F22E42 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4CCF8664052A491D00F2E8D8 /* checkpw.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 1C6C40241121FC0C00031CDE /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 4CA1FEBD052A3C8100F22E42 /* libsecurity_checkpw */; + targetProxy = 1C6C40251121FC0C00031CDE /* PBXContainerItemProxy */; + }; + 1CD90B6F11011196008DD07F /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 4CA1FEBD052A3C8100F22E42 /* libsecurity_checkpw */; + targetProxy = 1CD90B6E11011196008DD07F /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 1C6C402C1121FC0C00031CDE /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "perf-checkpw"; + }; + name = Debug; + }; + 1C6C402E1121FC0C00031CDE /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "perf-checkpw"; + }; + name = Release; + }; + 1CD90B6911011179008DD07F /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "test-checkpw"; + }; + name = Debug; + }; + 1CD90B6B11011179008DD07F /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "test-checkpw"; + }; + name = Release; + }; + C27AD3130987FCDE001272E0 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1844616C146E966100B12992 /* debug.xcconfig */; + buildSettings = { + }; + name = Debug; + }; + C27AD3150987FCDE001272E0 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1844616E146E966100B12992 /* release.xcconfig */; + buildSettings = { + }; + name = Release; + }; + C27AD3170987FCDE001272E0 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1844616D146E966100B12992 /* lib.xcconfig */; + buildSettings = { + }; + name = Debug; + }; + C27AD3190987FCDE001272E0 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1844616D146E966100B12992 /* lib.xcconfig */; + buildSettings = { + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1C6C402B1121FC0C00031CDE /* Build configuration list for PBXNativeTarget "perf-checkpw" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1C6C402C1121FC0C00031CDE /* Debug */, + 1C6C402E1121FC0C00031CDE /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 1CD90B77110111C3008DD07F /* Build configuration list for PBXNativeTarget "test-checkpw" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1CD90B6911011179008DD07F /* Debug */, + 1CD90B6B11011179008DD07F /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C27AD3120987FCDE001272E0 /* Build configuration list for PBXNativeTarget "libsecurity_checkpw" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C27AD3130987FCDE001272E0 /* Debug */, + C27AD3150987FCDE001272E0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C27AD3160987FCDE001272E0 /* Build configuration list for PBXProject "libsecurity_checkpw" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C27AD3170987FCDE001272E0 /* Debug */, + C27AD3190987FCDE001272E0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 4CA1FEAB052A3C3800F22E42 /* Project object */; +} diff --git a/libsecurity_checkpw/test/perf-checkpw.c b/libsecurity_checkpw/test/perf-checkpw.c new file mode 100644 index 00000000..425827d5 --- /dev/null +++ b/libsecurity_checkpw/test/perf-checkpw.c @@ -0,0 +1,24 @@ + + +#include +#include + +int +main(int argv, char *argc[]) +{ + char *uname = "local"; + char *pass = "local"; + int retval = 0, i = 0; + + for(i=0; i < 1024; i++) + { + retval = checkpw(uname, pass); + if (0 != retval) + { + printf("Incorrect password.\n"); + break; + } + } + + return retval; +} diff --git a/libsecurity_checkpw/test/test-checkpw.c b/libsecurity_checkpw/test/test-checkpw.c new file mode 100644 index 00000000..ded96a89 --- /dev/null +++ b/libsecurity_checkpw/test/test-checkpw.c @@ -0,0 +1,35 @@ + + +#include +#include +#include +#include +#include + +const char *prompt = "checkpw test prompt:"; + +int +main(int argv, char *argc[]) +{ + char *uname; + int retval = 0; + struct passwd *pw = NULL; + + uname = (char*)getenv("USER"); + if ( NULL == uname) + { + uid_t uid = getuid(); + struct passwd *pw = getpwuid(uid); + uname = pw->pw_name; + } + + retval = checkpw(uname, getpass(prompt)); + if (0 == retval) + { + printf("Password is okay.\n"); + } else { + printf("Incorrect password.\n"); + } + + return retval; +} diff --git a/libsecurity_cms/APPLE_LICENSE b/libsecurity_cms/APPLE_LICENSE new file mode 100644 index 00000000..71fe6fd7 --- /dev/null +++ b/libsecurity_cms/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/libsecurity_cms/Info-security_cms.plist b/libsecurity_cms/Info-security_cms.plist new file mode 100644 index 00000000..0c67376e --- /dev/null +++ b/libsecurity_cms/Info-security_cms.plist @@ -0,0 +1,5 @@ + + + + + diff --git a/libsecurity_cms/lib/CMSDecoder.cpp b/libsecurity_cms/lib/CMSDecoder.cpp new file mode 100644 index 00000000..93ccab3f --- /dev/null +++ b/libsecurity_cms/lib/CMSDecoder.cpp @@ -0,0 +1,958 @@ +/* + * 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@ + */ + +/* + * CMSDecoder.cpp - Interface for decoding CMS messages. + */ + +#include "CMSDecoder.h" +#include "CMSPrivate.h" +#include "CMSUtils.h" +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#pragma mark --- Private types and definitions --- + +/* + * Decoder state. + */ +typedef enum { + DS_Init, /* between CMSDecoderCreate and CMSDecoderUpdateMessage */ + DS_Updating, /* between first CMSDecoderUpdateMessage and CMSDecoderFinalizeMessage */ + DS_Final /* CMSDecoderFinalizeMessage has been called */ +} CMSDecoderState; + +/* + * Caller's CMSDecoderRef points to one of these. + */ +struct _CMSDecoder { + CFRuntimeBase base; + CMSDecoderState decState; + SecArenaPoolRef arena; /* the decoder's arena */ + SecCmsDecoderRef decoder; + CFDataRef detachedContent; + CFTypeRef keychainOrArray; /* from CMSDecoderSetSearchKeychain() */ + + /* + * The following are valid (and quiescent) after CMSDecoderFinalizeMessage(). + */ + SecCmsMessageRef cmsMsg; + Boolean wasEncrypted; /* valid after CMSDecoderFinalizeMessage() */ + SecCmsSignedDataRef signedData; /* if there is one... */ + /* only non-NULL if we found a signedData */ + size_t numSigners; + CSSM_OID *eContentType; + /* etc. */ +}; + +static void cmsDecoderInit(CFTypeRef dec); +static void cmsDecoderFinalize(CFTypeRef dec); + +static CFRuntimeClass cmsDecoderRuntimeClass = +{ + 0, /* version */ + "CMSDecoder", + cmsDecoderInit, + NULL, /* copy */ + cmsDecoderFinalize, + NULL, /* equal - just use pointer equality */ + NULL, /* hash, ditto */ + NULL, /* copyFormattingDesc */ + NULL /* copyDebugDesc */ +}; + +#pragma mark --- Private Routines --- + +static CFTypeID cmsDecoderTypeID = _kCFRuntimeNotATypeID; + +/* one time only class init, called via pthread_once() in CMSDecoderGetTypeID() */ +static void cmsDecoderClassInitialize(void) +{ + cmsDecoderTypeID = + _CFRuntimeRegisterClass((const CFRuntimeClass * const)&cmsDecoderRuntimeClass); +} + +/* init called out from _CFRuntimeCreateInstance() */ +static void cmsDecoderInit(CFTypeRef dec) +{ + char *start = ((char *)dec) + sizeof(CFRuntimeBase); + memset(start, 0, sizeof(struct _CMSDecoder) - sizeof(CFRuntimeBase)); +} + +/* + * Dispose of a CMSDecoder. Called out from CFRelease(). + */ +static void cmsDecoderFinalize( + CFTypeRef dec) +{ + CMSDecoderRef cmsDecoder = (CMSDecoderRef)dec; + if(cmsDecoder == NULL) { + return; + } + if(cmsDecoder->decoder != NULL) { + /* + * Normally this gets freed in SecCmsDecoderFinish - this is + * an error case. + * FIXME: SecCmsDecoderDestroy() appears to destroy the + * cmsMsg too! Plus there's a comment there re: a leak... + */ + SecCmsDecoderDestroy(cmsDecoder->decoder); + } + CFRELEASE(cmsDecoder->detachedContent); + CFRELEASE(cmsDecoder->keychainOrArray); + if(cmsDecoder->cmsMsg != NULL) { + SecCmsMessageDestroy(cmsDecoder->cmsMsg); + } + if(cmsDecoder->arena != NULL) { + SecArenaPoolFree(cmsDecoder->arena, false); + } +} + + +/* + * Given detached content and a valid (decoded) SignedData, digest the detached + * content. This occurs at the later of {CMSDecoderFinalizeMessage() finding a + * SignedData when already have detachedContent, or CMSDecoderSetDetachedContent() + * when we already have a SignedData). + */ +static OSStatus cmsDigestDetachedContent( + CMSDecoderRef cmsDecoder) +{ + ASSERT((cmsDecoder->signedData != NULL) && (cmsDecoder->detachedContent != NULL)); + + SECAlgorithmID **digestAlgorithms = SecCmsSignedDataGetDigestAlgs(cmsDecoder->signedData); + if(digestAlgorithms == NULL) { + return errSecUnknownFormat; + } + SecCmsDigestContextRef digcx = SecCmsDigestContextStartMultiple(digestAlgorithms); + if(digcx == NULL) { + return memFullErr; + } + CSSM_DATA **digests = NULL; + + SecCmsDigestContextUpdate(digcx, CFDataGetBytePtr(cmsDecoder->detachedContent), + CFDataGetLength(cmsDecoder->detachedContent)); + /* note this frees the digest content regardless */ + OSStatus ortn = SecCmsDigestContextFinishMultiple(digcx, cmsDecoder->arena, &digests); + if(ortn) { + ortn = cmsRtnToOSStatus(ortn); + CSSM_PERROR("SecCmsDigestContextFinishMultiple", ortn); + return ortn; + } + ortn = SecCmsSignedDataSetDigests(cmsDecoder->signedData, digestAlgorithms, digests); + if(ortn) { + ortn = cmsRtnToOSStatus(ortn); + CSSM_PERROR("SecCmsSignedDataSetDigests", ortn); + } + return ortn; +} + +#pragma mark --- Start of Public API --- + +CFTypeID CMSDecoderGetTypeID(void) +{ + static pthread_once_t once = PTHREAD_ONCE_INIT; + + if(cmsDecoderTypeID == _kCFRuntimeNotATypeID) { + pthread_once(&once, &cmsDecoderClassInitialize); + } + return cmsDecoderTypeID; +} + +/* + * Create a CMSDecoder. Result must eventually be freed via CFRelease(). + */ +OSStatus CMSDecoderCreate( + CMSDecoderRef *cmsDecoderOut) /* RETURNED */ +{ + CMSDecoderRef cmsDecoder = NULL; + + uint32_t extra = sizeof(*cmsDecoder) - sizeof(cmsDecoder->base); + cmsDecoder = (CMSDecoderRef)_CFRuntimeCreateInstance(NULL, CMSDecoderGetTypeID(), + extra, NULL); + if(cmsDecoder == NULL) { + return memFullErr; + } + cmsDecoder->decState = DS_Init; + *cmsDecoderOut = cmsDecoder; + return noErr; +} + +/* + * Feed raw bytes of the message to be decoded into the decoder. Can be called + * multiple times. + */ +OSStatus CMSDecoderUpdateMessage( + CMSDecoderRef cmsDecoder, + const void *msgBytes, + size_t msgBytesLen) +{ + if(cmsDecoder == NULL) { + return paramErr; + } + + OSStatus ortn; + switch(cmsDecoder->decState) { + case DS_Init: + /* First time through; set up */ + ASSERT(cmsDecoder->decoder == NULL); + ASSERT(cmsDecoder->arena == NULL); + ortn = SecArenaPoolCreate(1024, &cmsDecoder->arena); + if(ortn) { + return cmsRtnToOSStatus(ortn); + } + ortn = SecCmsDecoderCreate(cmsDecoder->arena, + NULL, NULL, NULL, NULL, NULL, NULL, &cmsDecoder->decoder); + if(ortn) { + ortn = cmsRtnToOSStatus(ortn); + CSSM_PERROR("SecCmsDecoderCreate", ortn); + return ortn; + } + cmsDecoder->decState = DS_Updating; + break; + + case DS_Updating: + ASSERT(cmsDecoder->decoder != NULL); + break; + + case DS_Final: + /* Too late for another update */ + return paramErr; + + default: + dprintf("CMSDecoderUpdateMessage: bad decState\n"); + return internalComponentErr; + } + + /* FIXME - CFIndex same size as size_t on 64bit? */ + ortn = SecCmsDecoderUpdate(cmsDecoder->decoder, msgBytes, (CFIndex)msgBytesLen); + if(ortn) { + ortn = cmsRtnToOSStatus(ortn, errSecUnknownFormat); + CSSM_PERROR("SecCmsDecoderUpdate", ortn); + } + return ortn; +} + +/* + * Indicate that no more CMSDecoderUpdateMessage() calls are forthcoming; + * finish decoding the message. We parse the message as best we can, up to + * but not including verifying individual signerInfos. + */ +OSStatus CMSDecoderFinalizeMessage( + CMSDecoderRef cmsDecoder) +{ + if(cmsDecoder == NULL) { + return paramErr; + } + if(cmsDecoder->decState != DS_Updating) { + return paramErr; + } + ASSERT(cmsDecoder->decoder != NULL); + OSStatus ortn = SecCmsDecoderFinish(cmsDecoder->decoder, &cmsDecoder->cmsMsg); + cmsDecoder->decState = DS_Final; + + /* SecCmsDecoderFinish destroyed the decoder even on failure */ + cmsDecoder->decoder = NULL; + + if(ortn) { + ortn = cmsRtnToOSStatus(ortn, errSecUnknownFormat); + CSSM_PERROR("SecCmsDecoderFinish", ortn); + return ortn; + } + + ASSERT(cmsDecoder->cmsMsg != NULL); + cmsDecoder->wasEncrypted = SecCmsMessageIsEncrypted(cmsDecoder->cmsMsg); + + /* Look for a SignedData */ + int numContentInfos = SecCmsMessageContentLevelCount(cmsDecoder->cmsMsg); + int dex; + for(dex=0; dexcmsMsg, dex); + SECOidTag tag = SecCmsContentInfoGetContentTypeTag(ci); + switch(tag) { + case SEC_OID_PKCS7_SIGNED_DATA: + cmsDecoder->signedData = + (SecCmsSignedDataRef)SecCmsContentInfoGetContent(ci); + /* dig down one more layer for eContentType */ + ci = SecCmsSignedDataGetContentInfo(cmsDecoder->signedData); + cmsDecoder->eContentType = SecCmsContentInfoGetContentTypeOID(ci); + break; + default: + break; + } + if(cmsDecoder->signedData != NULL) { + break; + } + + } + + /* minimal processing of optional signedData... */ + if(cmsDecoder->signedData != NULL) { + cmsDecoder->numSigners = (size_t) + SecCmsSignedDataSignerInfoCount(cmsDecoder->signedData); + if(cmsDecoder->detachedContent != NULL) { + /* time to calculate digests from detached content */ + ortn = cmsDigestDetachedContent(cmsDecoder); + } + } + return ortn; +} + +/* + * A signed CMS message optionally includes the data which was signed. If the + * message does not include the signed data, caller specifies the signed data + * (the "detached content") here. + * + * This can be called either before or after the actual decoding of the message + * (via CMSDecoderUpdateMessage() and CMSDecoderFinalizeMessage()); the only + * restriction is that, if detached content is required, this function must + * be called befoere successfully ascertaining the signature status via + * CMSDecoderCopySignerStatus(). + */ +OSStatus CMSDecoderSetDetachedContent( + CMSDecoderRef cmsDecoder, + CFDataRef detachedContent) +{ + if((cmsDecoder == NULL) || (detachedContent == NULL)) { + return paramErr; + } + cmsDecoder->detachedContent = detachedContent; + CFRetain(detachedContent); + + if(cmsDecoder->signedData != NULL) { + /* time to calculate digests from detached content */ + ASSERT(cmsDecoder->decState == DS_Final); + return cmsDigestDetachedContent(cmsDecoder); + } + return noErr; +} + +/* + * Obtain the detached content specified in CMSDecoderSetDetachedContent(). + * Returns a NULL detachedContent if no detached content has been specified. + * Caller must CFRelease() the result. + */ +OSStatus CMSDecoderCopyDetachedContent( + CMSDecoderRef cmsDecoder, + CFDataRef *detachedContent) /* RETURNED */ +{ + if((cmsDecoder == NULL) || (detachedContent == NULL)) { + return paramErr; + } + if(cmsDecoder->detachedContent != NULL) { + CFRetain(cmsDecoder->detachedContent); + } + *detachedContent = cmsDecoder->detachedContent; + return noErr; +} + +/* + * Optionally specify a SecKeychainRef, or an array of them, containing + * intermediate certs to be used in verifying a signed message's signer + * certs. By default, the default keychain search list is used for this. + * Specify an empty CFArrayRef to search *no* keychains for intermediate + * certs. + * IF this is called, it must be called before CMSDecoderCopySignerStatus(). + */ +OSStatus CMSDecoderSetSearchKeychain( + CMSDecoderRef cmsDecoder, + CFTypeRef keychainOrArray) +{ + if(cmsDecoder == NULL) { + return paramErr; + } + cmsDecoder->keychainOrArray = keychainOrArray; + if(keychainOrArray) { + CFRetain(keychainOrArray); + } + return noErr; +} + +/* + * Obtain the number of signers of a message. A result of zero indicates that + * the message was not signed. + */ +OSStatus CMSDecoderGetNumSigners( + CMSDecoderRef cmsDecoder, + size_t *numSigners) /* RETURNED */ +{ + if((cmsDecoder == NULL) || (numSigners == NULL)) { + return paramErr; + } + if(cmsDecoder->decState != DS_Final) { + return paramErr; + } + *numSigners = cmsDecoder->numSigners; + return noErr; +} + +/* + * Obtain the status of a CMS message's signature. A CMS message can + * be signed my multiple signers; this function returns the status + * associated with signer 'n' as indicated by the signerIndex parameter. + */ +OSStatus CMSDecoderCopySignerStatus( + CMSDecoderRef cmsDecoder, + size_t signerIndex, + CFTypeRef policyOrArray, + Boolean evaluateSecTrust, + CMSSignerStatus *signerStatus, /* optional; RETURNED */ + SecTrustRef *secTrust, /* optional; RETURNED */ + OSStatus *certVerifyResultCode) /* optional; RETURNED */ +{ + if((cmsDecoder == NULL) || (cmsDecoder->decState != DS_Final)) { + return paramErr; + } + + /* initialize return values */ + if(signerStatus) { + *signerStatus = kCMSSignerUnsigned; + } + if(secTrust) { + *secTrust = NULL; + } + if(certVerifyResultCode) { + *certVerifyResultCode = 0; + } + + if(cmsDecoder->signedData == NULL) { + *signerStatus = kCMSSignerUnsigned; /* redundant, I know, but explicit */ + return noErr; + } + ASSERT(cmsDecoder->numSigners > 0); + if(signerIndex >= cmsDecoder->numSigners) { + *signerStatus = kCMSSignerInvalidIndex; + return noErr; + } + if(!SecCmsSignedDataHasDigests(cmsDecoder->signedData)) { + *signerStatus = kCMSSignerNeedsDetachedContent; + return noErr; + } + + /* + * OK, we should be able to verify this signerInfo. + * I think we have to do the SecCmsSignedDataVerifySignerInfo first + * in order get all the cert pieces into place before returning them + * to the caller. + */ + SecTrustRef theTrust = NULL; + OSStatus vfyRtn = SecCmsSignedDataVerifySignerInfo(cmsDecoder->signedData, + signerIndex, + /* + * FIXME this cast should not be necessary, but libsecurity_smime + * declares this argument as a SecKeychainRef + */ + (SecKeychainRef)cmsDecoder->keychainOrArray, + policyOrArray, + &theTrust); + /* Subsequent errors to errOut: */ + + /* + * NOTE the smime lib did NOT evaluate that SecTrust - it only does + * SecTrustEvaluate() if we don't ask for a copy. + * + * FIXME deal with multitudes of status returns here...for now, proceed with + * obtaining components the caller wants and assume that a nonzero vfyRtn + * means "bad signature". + */ + OSStatus ortn = noErr; + SecTrustResultType secTrustResult; + CSSM_RETURN tpVfyStatus = CSSM_OK; + OSStatus evalRtn; + + if(secTrust != NULL) { + *secTrust = theTrust; + /* we'll release our reference at the end */ + if (theTrust) + CFRetain(theTrust); + } + SecCmsSignerInfoRef signerInfo = + SecCmsSignedDataGetSignerInfo(cmsDecoder->signedData, signerIndex); + if(signerInfo == NULL) { + /* should never happen */ + ASSERT(0); + dprintf("CMSDecoderCopySignerStatus: no signerInfo\n"); + ortn = internalComponentErr; + goto errOut; + } + + /* now do the actual cert verify */ + if(evaluateSecTrust) { + evalRtn = SecTrustEvaluate(theTrust, &secTrustResult); + if(evalRtn) { + /* should never happen */ + CSSM_PERROR("SecTrustEvaluate", evalRtn); + dprintf("CMSDecoderCopySignerStatus: SecTrustEvaluate error\n"); + ortn = internalComponentErr; + goto errOut; + } + switch(secTrustResult) { + case kSecTrustResultUnspecified: + /* cert chain valid, no special UserTrust assignments */ + case kSecTrustResultProceed: + /* cert chain valid AND user explicitly trusts this */ + break; + case kSecTrustResultDeny: + tpVfyStatus = CSSMERR_APPLETP_TRUST_SETTING_DENY; + break; + case kSecTrustResultConfirm: + dprintf("SecTrustEvaluate reported confirm\n"); + tpVfyStatus = CSSMERR_TP_NOT_TRUSTED; + break; + default: + { + /* get low-level TP error */ + OSStatus tpStatus; + ortn = SecTrustGetCssmResultCode(theTrust, &tpStatus); + if(ortn) { + CSSM_PERROR("SecTrustGetCssmResultCode", ortn); + } + else { + tpVfyStatus = tpStatus; + } + CSSM_PERROR("TP status after SecTrustEvaluate", tpVfyStatus); + break; + } + } /* switch(secTrustResult) */ + } /* evaluateSecTrust true */ + if(certVerifyResultCode != NULL) { + *certVerifyResultCode = tpVfyStatus; + } + + /* cook up global status based on vfyRtn and tpVfyStatus */ + if(signerStatus != NULL) { + if((vfyRtn == noErr) && (tpVfyStatus == CSSM_OK)) { + *signerStatus = kCMSSignerValid; + } + else if(vfyRtn != noErr) { + /* this could mean other things, but for now... */ + *signerStatus = kCMSSignerInvalidSignature; + } + else { + *signerStatus = kCMSSignerInvalidCert; + } + } +errOut: + CFRELEASE(theTrust); + return ortn; +} + +/* + * Obtain the email address of signer 'signerIndex' of a CMS message, if + * present. + * + * This cannot be called until after CMSDecoderFinalizeMessage() is called. + */ +OSStatus CMSDecoderCopySignerEmailAddress( + CMSDecoderRef cmsDecoder, + size_t signerIndex, + CFStringRef *signerEmailAddress) /* RETURNED */ +{ + if((cmsDecoder == NULL) || + (signerEmailAddress == NULL) || + (cmsDecoder->signedData == NULL) || /* not signed */ + (signerIndex >= cmsDecoder->numSigners) || /* index out of range */ + (cmsDecoder->decState != DS_Final)) { + return paramErr; + } + + SecCmsSignerInfoRef signerInfo = + SecCmsSignedDataGetSignerInfo(cmsDecoder->signedData, signerIndex); + if(signerInfo == NULL) { + /* should never happen */ + ASSERT(0); + dprintf("CMSDecoderCopySignerEmailAddress: no signerInfo\n"); + return internalComponentErr; + } + + /* + * This is leaking memory in libsecurityKeychain per Radar 4412699. + */ + *signerEmailAddress = SecCmsSignerInfoGetSignerEmailAddress(signerInfo); + return noErr; +} + +/* + * Obtain the certificate of signer 'signerIndex' of a CMS message, if + * present. + * + * This cannot be called until after CMSDecoderFinalizeMessage() is called. + */ +OSStatus CMSDecoderCopySignerCert( + CMSDecoderRef cmsDecoder, + size_t signerIndex, + SecCertificateRef *signerCert) /* RETURNED */ +{ + if((cmsDecoder == NULL) || + (signerCert == NULL) || + (cmsDecoder->signedData == NULL) || /* not signed */ + (signerIndex >= cmsDecoder->numSigners) || /* index out of range */ + (cmsDecoder->decState != DS_Final)) { + return paramErr; + } + + SecCmsSignerInfoRef signerInfo = + SecCmsSignedDataGetSignerInfo(cmsDecoder->signedData, signerIndex); + if(signerInfo == NULL) { + /* should never happen */ + ASSERT(0); + dprintf("CMSDecoderCopySignerCertificate: no signerInfo\n"); + return internalComponentErr; + } + *signerCert = SecCmsSignerInfoGetSigningCertificate(signerInfo, NULL); + /* libsecurity_smime does NOT retain that */ + if(*signerCert == NULL) { + /* should never happen */ + ASSERT(0); + dprintf("CMSDecoderCopySignerCertificate: no signerCert\n"); + return internalComponentErr; + } + CFRetain(*signerCert); + return noErr; +} + +/* + * Determine whether a CMS message was encrypted, and if so, whether we were + * able to decrypt it. + */ +OSStatus CMSDecoderIsContentEncrypted( + CMSDecoderRef cmsDecoder, + Boolean *wasEncrypted) +{ + if((cmsDecoder == NULL) || (wasEncrypted == NULL)) { + return paramErr; + } + if(cmsDecoder->decState != DS_Final) { + return paramErr; + } + *wasEncrypted = cmsDecoder->wasEncrypted; + return noErr; +} + +/* + * Obtain the eContentType OID for a SignedData's EncapsulatedContentType, if + * present. + */ +OSStatus CMSDecoderCopyEncapsulatedContentType( + CMSDecoderRef cmsDecoder, + CFDataRef *eContentType) /* RETURNED */ +{ + if((cmsDecoder == NULL) || (eContentType == NULL)) { + return paramErr; + } + if(cmsDecoder->decState != DS_Final) { + return paramErr; + } + if(cmsDecoder->signedData == NULL) { + *eContentType = NULL; + } + else { + CSSM_OID *ecOid = cmsDecoder->eContentType; + *eContentType = CFDataCreate(NULL, ecOid->Data, ecOid->Length); + } + return noErr; +} + +/* + * Obtain an array of all of the certificates in a message. Elements of the + * returned array are SecCertificateRefs. The caller must CFRelease the returned + * array. + * This cannot be called until after CMSDecoderFinalizeMessage() is called. + */ +OSStatus CMSDecoderCopyAllCerts( + CMSDecoderRef cmsDecoder, + CFArrayRef *certs) /* RETURNED */ +{ + if((cmsDecoder == NULL) || (certs == NULL)) { + return paramErr; + } + if(cmsDecoder->decState != DS_Final) { + return paramErr; + } + if(cmsDecoder->signedData == NULL) { + /* message wasn't signed */ + *certs = NULL; + return noErr; + } + + /* NULL_terminated array of CSSM_DATA ptrs */ + CSSM_DATA_PTR *cssmCerts = SecCmsSignedDataGetCertificateList(cmsDecoder->signedData); + if((cssmCerts == NULL) || (*cssmCerts == NULL)) { + *certs = NULL; + return noErr; + } + + CFMutableArrayRef allCerts = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); + CSSM_DATA_PTR *cssmCert; + for(cssmCert=cssmCerts; *cssmCert!=NULL; cssmCert++) { + OSStatus ortn; + SecCertificateRef cfCert; + ortn = SecCertificateCreateFromData(*cssmCert, + CSSM_CERT_X_509v3, CSSM_CERT_ENCODING_DER, + &cfCert); + if(ortn) { + CFRelease(allCerts); + return ortn; + } + CFArrayAppendValue(allCerts, cfCert); + /* the array holds the only needed refcount */ + CFRelease(cfCert); + } + *certs = allCerts; + return noErr; +} + +/* + * Obtain the actual message content (payload), if any. If the message was + * signed with detached content this will return NULL. + * Caller must CFRelease the result. + */ +OSStatus CMSDecoderCopyContent( + CMSDecoderRef cmsDecoder, + CFDataRef *content) /* RETURNED */ +{ + if((cmsDecoder == NULL) || (content == NULL)) { + return paramErr; + } + if(cmsDecoder->decState != DS_Final) { + return paramErr; + } + if(cmsDecoder->cmsMsg == NULL) { + /* Hmmm....looks like the finalize call failed */ + return paramErr; + } + CSSM_DATA_PTR odata = SecCmsMessageGetContent(cmsDecoder->cmsMsg); + if((odata == NULL) || (odata->Length == 0)) { + /* i.e., detached content */ + *content = NULL; + return noErr; + } + *content = CFDataCreate(NULL, (const UInt8 *)odata->Data, odata->Length); + return noErr; +} + +#pragma mark --- SPI declared in CMSPrivate.h --- + +/* + * Obtain the SecCmsMessageRef associated with a CMSDecoderRef. Intended + * to be called after decoding the message (i.e., after + * CMSDecoderFinalizeMessage() to gain finer access to the contents of the + * SecCmsMessageRef than is otherwise available via the CMSDecoder interface. + * Returns a NULL SecCmsMessageRef if CMSDecoderFinalizeMessage() has not been + * called. + * + * The CMSDecoder retains ownership of the returned SecCmsMessageRef. + */ +OSStatus CMSDecoderGetCmsMessage( + CMSDecoderRef cmsDecoder, + SecCmsMessageRef *cmsMessage) /* RETURNED */ +{ + if((cmsDecoder == NULL) || (cmsMessage == NULL)) { + return paramErr; + } + /* any state, whether we have a msg or not is OK */ + *cmsMessage = cmsDecoder->cmsMsg; + return noErr; +} + +/* + * Optionally specify a SecCmsDecoderRef to use with a CMSDecoderRef. + * If this is called, it must be called before the first call to + * CMSDecoderUpdateMessage(). The CMSDecoderRef takes ownership of the + * incoming SecCmsDecoderRef. + */ +OSStatus CMSDecoderSetDecoder( + CMSDecoderRef cmsDecoder, + SecCmsDecoderRef decoder) +{ + if((cmsDecoder == NULL) || (decoder == NULL)) { + return paramErr; + } + switch(cmsDecoder->decState) { + case DS_Init: + ASSERT(cmsDecoder->decoder == NULL); + cmsDecoder->decoder = decoder; + cmsDecoder->decState = DS_Updating; + return noErr; + case DS_Updating: + case DS_Final: + return paramErr; + } + return noErr; +} + +/* + * Obtain the SecCmsDecoderRef associated with a CMSDecoderRef. + * Returns a NULL SecCmsDecoderRef if neither CMSDecoderSetDecoder() nor + * CMSDecoderUpdateMessage() has been called. + * The CMSDecoderRef retains ownership of the SecCmsDecoderRef. + */ +OSStatus CMSDecoderGetDecoder( + CMSDecoderRef cmsDecoder, + SecCmsDecoderRef *decoder) /* RETURNED */ +{ + if((cmsDecoder == NULL) || (decoder == NULL)) { + return paramErr; + } + /* any state, whether we have a decoder or not is OK */ + *decoder = cmsDecoder->decoder; + return noErr; +} + +/* + * Obtain the signing time of signer 'signerIndex' of a CMS message, if + * present. This is an unauthenticate time, although it is part of the + * signed attributes of the message. + * + * Returns paramErr 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 CMSDecoderCopySignerSigningTime( + CMSDecoderRef cmsDecoder, + size_t signerIndex, /* usually 0 */ + CFAbsoluteTime *signingTime) /* RETURNED */ +{ + OSStatus status = paramErr; + SecCmsMessageRef cmsg; + SecCmsSignedDataRef signedData = NULL; + int numContentInfos = 0; + + require(cmsDecoder && signingTime, xit); + require_noerr(CMSDecoderGetCmsMessage(cmsDecoder, &cmsg), xit); + numContentInfos = SecCmsMessageContentLevelCount(cmsg); + for (int dex = 0; !signedData && dex < numContentInfos; dex++) + { + SecCmsContentInfoRef ci = SecCmsMessageContentLevel(cmsg, dex); + SECOidTag tag = SecCmsContentInfoGetContentTypeTag(ci); + if (tag == SEC_OID_PKCS7_SIGNED_DATA) + if ((signedData = SecCmsSignedDataRef(SecCmsContentInfoGetContent(ci)))) + if (SecCmsSignerInfoRef signerInfo = SecCmsSignedDataGetSignerInfo(signedData, (int)signerIndex)) + { + status = SecCmsSignerInfoGetSigningTime(signerInfo, signingTime); + break; + } + } +xit: + return status; +} + +/* + * Obtain the timestamp of signer 'signerIndex' of a CMS message, if + * present. This timestamp is an authenticated timestamp provided by + * a timestamping authority. + * + * Returns paramErr 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 CMSDecoderCopySignerTimestamp( + CMSDecoderRef cmsDecoder, + size_t signerIndex, /* usually 0 */ + CFAbsoluteTime *timestamp) /* RETURNED */ +{ + OSStatus status = paramErr; + SecCmsMessageRef cmsg; + SecCmsSignedDataRef signedData = NULL; + int numContentInfos = 0; + + require(cmsDecoder && timestamp, xit); + require_noerr(CMSDecoderGetCmsMessage(cmsDecoder, &cmsg), xit); + numContentInfos = SecCmsMessageContentLevelCount(cmsg); + for (int dex = 0; !signedData && dex < numContentInfos; dex++) + { + SecCmsContentInfoRef ci = SecCmsMessageContentLevel(cmsg, dex); + SECOidTag tag = SecCmsContentInfoGetContentTypeTag(ci); + if (tag == SEC_OID_PKCS7_SIGNED_DATA) + if ((signedData = SecCmsSignedDataRef(SecCmsContentInfoGetContent(ci)))) + if (SecCmsSignerInfoRef signerInfo = SecCmsSignedDataGetSignerInfo(signedData, (int)signerIndex)) + { + status = SecCmsSignerInfoGetTimestampTime(signerInfo, timestamp); + break; + } + } + +xit: + return status; +} + +/* + * Obtain an array of the certificates in a timestamp response. Elements of the + * returned array are SecCertificateRefs. The caller must CFRelease the returned + * array. This timestamp is an authenticated timestamp provided by + * a timestamping authority. + * + * Returns paramErr if the CMS message was not signed or if signerIndex + * is greater than the number of signers of the message minus one. It returns + * errSecItemNotFound if no certificates were found. + * + * This cannot be called until after CMSDecoderFinalizeMessage() is called. + */ +OSStatus CMSDecoderCopySignerTimestampCertificates( + CMSDecoderRef cmsDecoder, + size_t signerIndex, /* usually 0 */ + CFArrayRef *certificateRefs) /* RETURNED */ +{ + OSStatus status = paramErr; + SecCmsMessageRef cmsg; + SecCmsSignedDataRef signedData = NULL; + int numContentInfos = 0; + + require(cmsDecoder && certificateRefs, xit); + require_noerr(CMSDecoderGetCmsMessage(cmsDecoder, &cmsg), xit); + numContentInfos = SecCmsMessageContentLevelCount(cmsg); + for (int dex = 0; !signedData && dex < numContentInfos; dex++) + { + SecCmsContentInfoRef ci = SecCmsMessageContentLevel(cmsg, dex); + SECOidTag tag = SecCmsContentInfoGetContentTypeTag(ci); + if (tag == SEC_OID_PKCS7_SIGNED_DATA) + if ((signedData = SecCmsSignedDataRef(SecCmsContentInfoGetContent(ci)))) + if (SecCmsSignerInfoRef signerInfo = SecCmsSignedDataGetSignerInfo(signedData, (int)signerIndex)) + { + CFArrayRef certList = SecCmsSignerInfoGetTimestampCertList(signerInfo); + require_action(certList, xit, status = errSecItemNotFound); + *certificateRefs = CFArrayCreateCopy(kCFAllocatorDefault, certList); + status = noErr; + break; + } + } + +xit: + return status; +} diff --git a/libsecurity_cms/lib/CMSDecoder.h b/libsecurity_cms/lib/CMSDecoder.h new file mode 100644 index 00000000..4ee58e36 --- /dev/null +++ b/libsecurity_cms/lib/CMSDecoder.h @@ -0,0 +1,362 @@ +/* + * 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@ + */ + +/* + * CMSDecoder.h - decode, decrypt, and/or verify signatures of messages in the + * Cryptographic Message Syntax (CMS), per RFC 3852. + * + * See CMSEncoder.h for general information about CMS messages. + */ + +#ifndef _CMS_DECODER_H_ +#define _CMS_DECODER_H_ + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Opaque reference to a CMS decoder object. + * This is a CF object, with standard CF semantics; dispose of it + * with CFRelease(). + */ +typedef struct _CMSDecoder *CMSDecoderRef; + +CFTypeID CMSDecoderGetTypeID(void); + +/* + * Status of signature and signer information in a signed message. + */ +enum { + kCMSSignerUnsigned = 0, /* message was not signed */ + kCMSSignerValid, /* message was signed and signature verify OK */ + kCMSSignerNeedsDetachedContent, /* message was signed but needs detached content + * to verify */ + kCMSSignerInvalidSignature, /* message was signed but had a signature error */ + kCMSSignerInvalidCert, /* message was signed but an error occurred in verifying + * the signer's certificate */ + kCMSSignerInvalidIndex /* specified signer index out of range */ +}; +typedef uint32_t CMSSignerStatus; + +/* + * Create a CMSDecoder. Result must eventually be freed via CFRelease(). + */ +OSStatus CMSDecoderCreate( + CMSDecoderRef *cmsDecoderOut) /* RETURNED */ + __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); + +/* + * Feed raw bytes of the message to be decoded into the decoder. Can be called + * multiple times. + * Returns errSecUnknownFormat upon detection of improperly formatted CMS + * message. + */ +OSStatus CMSDecoderUpdateMessage( + CMSDecoderRef cmsDecoder, + const void *msgBytes, + size_t msgBytesLen) + __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); + +/* + * Indicate that no more CMSDecoderUpdateMessage() calls are forthcoming; + * finish decoding the message. + * Returns errSecUnknownFormat upon detection of improperly formatted CMS + * message. + */ +OSStatus CMSDecoderFinalizeMessage( + CMSDecoderRef cmsDecoder) + __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); + +/* + * A signed CMS message optionally includes the data which was signed. If the + * message does not include the signed data, caller specifies the signed data + * (the "detached content") here. + * + * This can be called either before or after the actual decoding of the message + * (via CMSDecoderUpdateMessage() and CMSDecoderFinalizeMessage()); the only + * restriction is that, if detached content is required, this function must + * be called befoere successfully ascertaining the signature status via + * CMSDecoderCopySignerStatus(). + */ +OSStatus CMSDecoderSetDetachedContent( + CMSDecoderRef cmsDecoder, + CFDataRef detachedContent) + __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); + +/* + * Obtain the detached content specified in CMSDecoderSetDetachedContent(). + * Returns a NULL detachedContent if no detached content has been specified. + * Caller must CFRelease() the result. + */ +OSStatus CMSDecoderCopyDetachedContent( + CMSDecoderRef cmsDecoder, + CFDataRef *detachedContentOut) /* RETURNED */ + __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); + +/* + * Optionally specify a SecKeychainRef, or an array of them, containing + * intermediate certs to be used in verifying a signed message's signer + * certs. By default, the default keychain search list is used for this. + * Specify an empty CFArrayRef to search *no* keychains for intermediate + * certs. + * If this is called, it must be called before CMSDecoderCopySignerStatus(). + */ +OSStatus CMSDecoderSetSearchKeychain( + CMSDecoderRef cmsDecoder, + CFTypeRef keychainOrArray) + __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); + +/* + * Obtain the number of signers of a message. A result of zero indicates that + * the message was not signed. + * This cannot be called until after CMSDecoderFinalizeMessage() is called. + */ +OSStatus CMSDecoderGetNumSigners( + CMSDecoderRef cmsDecoder, + size_t *numSignersOut) /* RETURNED */ + __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); + +/* + * Obtain the status of a CMS message's signature. A CMS message can + * be signed my multiple signers; this function returns the status + * associated with signer 'n' as indicated by the signerIndex parameter. + * + * This cannot be called until after CMSDecoderFinalizeMessage() is called. + * + * Note that signature and certificate verification of a decoded message + * does *not* occur until this routine is called. + * + * All returned values are optional - pass NULL if you don't need a + * particular parameter. + * + * Note that errors like "bad signature" and "bad cert" do NOT cause this + * routine to return a nonzero error status itself; such errors are reported + * in the various out parameters, listed below. + * + * Inputs: + * ------- + * cmsDecoder : a CMSDecoder which has successfully performed a + * CMSDecoderFinalizeMessage(). + * signerIndex : indicates which of 'n' signers is being examined. + * Range is 0...(numSigners-1). + * policyOrArray : Either a SecPolicyRef or a CFArray of them. + * These policies are used to verify the signer's certificate. + * evaluateSecTrust : When TRUE, causes the SecTrust oebject created for the + * evaluation of the signer cert to actually be evaluated + * via SecTrustEvaluate(). When FALSE, the caller performs + * the SecTrustEvaluate() operation on the SecTrust object + * returned via the secTrust out parameter. + * NOTE: it is hazardous and not recommended to pass in FALSE + * for the evaluateSecTrust parameter as well as NULL for the + * secTrust out parameter, since no evaluation of the signer + * cert can occur in that situation. + * + * Outputs: + * -------- + * signerStatusOut -- An enum indicating the overall status. + * kCMSSignerUnsigned : message was not signed. + * kCMSSignerValid : both signature and signer certificate verified OK. + * kCMSSignerNeedsDetachedContent : a call to CMSDecoderSetDetachedContent() + * is required to ascertain the signature status. + * kCMSSignerInvalidSignature : bad signature. + * kCMSSignerInvalidCert : an error occurred verifying the signer's certificate. + * Further information available via the secTrust and + * certVerifyResultCode parameters. This will never be + * returned if evaluateSecTrust is FALSE. + * kCMSSignerInvalidIndex : specified signerIndex is larger than the number of + * signers (minus 1). + * + * secTrustOut -- The SecTrust object used to verify the signer's + * certificate. Caller must CFRelease this. + * certVerifyResultCodeOut -- The result of the certificate verification. If + * the evaluateSecTrust argument is set to FALSE on + * input, this out parameter is undefined on return. + * + * The certVerifyResultCode value can indicate a large number of errors; some of + * the most common and interesting errors are: + * + * CSSMERR_TP_INVALID_ANCHOR_CERT : The cert was verified back to a + * self-signed (root) cert which was present in the message, but + * that root cert is not a known, trusted root cert. + * CSSMERR_TP_NOT_TRUSTED: The cert could not be verified back to + * a root cert. + * CSSMERR_TP_VERIFICATION_FAILURE: A root cert was found which does + * not self-verify. + * CSSMERR_TP_VERIFY_ACTION_FAILED: Indicates a failure of the requested + * policy action. + * CSSMERR_TP_INVALID_CERTIFICATE: Indicates a bad leaf cert. + * CSSMERR_TP_CERT_EXPIRED: A cert in the chain was expired at the time of + * verification. + * CSSMERR_TP_CERT_NOT_VALID_YET: A cert in the chain was not yet valie at + * the time of verification. + */ +OSStatus CMSDecoderCopySignerStatus( + CMSDecoderRef cmsDecoder, + size_t signerIndex, + CFTypeRef policyOrArray, + Boolean evaluateSecTrust, + CMSSignerStatus *signerStatusOut, /* optional; RETURNED */ + SecTrustRef *secTrustOut, /* optional; RETURNED */ + OSStatus *certVerifyResultCodeOut) /* optional; RETURNED */ + __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); + +/* + * Obtain the email address of signer 'signerIndex' of a CMS message, if + * present. + * + * Returns paramErr 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 CMSDecoderCopySignerEmailAddress( + CMSDecoderRef cmsDecoder, + size_t signerIndex, + CFStringRef *signerEmailAddressOut) /* RETURNED */ + __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); + +/* + * Obtain the certificate of signer 'signerIndex' of a CMS message, if + * present. + * + * Returns paramErr 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 CMSDecoderCopySignerCert( + CMSDecoderRef cmsDecoder, + size_t signerIndex, + SecCertificateRef *signerCertOut) /* RETURNED */ + __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); + +/* + * Determine whether a CMS message was encrypted. Returns TRUE if so, FALSE if not. + * Note that if the message was encrypted, and the decoding succeeded, (i.e., + * CMSDecoderFinalizeMessage() returned noErr), then the message was successfully + * decrypted. + * This cannot be called until after CMSDecoderFinalizeMessage() is called. + */ +OSStatus CMSDecoderIsContentEncrypted( + CMSDecoderRef cmsDecoder, + Boolean *isEncryptedOut) + __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); + +/* + * Obtain the eContentType OID for a SignedData's EncapsulatedContentType, if + * present. If the message was not signed this will return NULL. + * This cannot be called until after CMSDecoderFinalizeMessage() is called. + * The returned OID's data is in the same format as a CSSM_OID; i.e., it's + * the encoded content of the OID, not including the tag and length bytes. + */ +OSStatus CMSDecoderCopyEncapsulatedContentType( + CMSDecoderRef cmsDecoder, + CFDataRef *eContentTypeOut) /* RETURNED */ + __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); + +/* + * Obtain an array of all of the certificates in a message. Elements of the + * returned array are SecCertificateRefs. The caller must CFRelease the returned + * array. If a message does not contain any certificates (which is the case for + * a message which is encrypted but not signed), the returned *certs value + * is NULL. The function will return noErr in this case. + * This cannot be called until after CMSDecoderFinalizeMessage() is called. + */ +OSStatus CMSDecoderCopyAllCerts( + CMSDecoderRef cmsDecoder, + CFArrayRef *certsOut) /* RETURNED */ + __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); + +/* + * Obtain the actual message content (payload), if any. If the message was + * signed with detached content this will return NULL. + * Caller must CFRelease the result. + * This cannot be called until after CMSDecoderFinalizeMessage() is called. + */ +OSStatus CMSDecoderCopyContent( + CMSDecoderRef cmsDecoder, + CFDataRef *contentOut) /* RETURNED */ + __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); + +/* + * Obtain the signing time of signer 'signerIndex' of a CMS message, if + * present. This is an unauthenticate time, although it is part of the + * signed attributes of the message. + * + * Returns paramErr 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 CMSDecoderCopySignerSigningTime( + CMSDecoderRef cmsDecoder, + size_t signerIndex, + CFAbsoluteTime *signingTime) /* 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. + * + * Returns paramErr 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 CMSDecoderCopySignerTimestamp( + CMSDecoderRef cmsDecoder, + size_t signerIndex, + CFAbsoluteTime *timestamp) /* RETURNED */ + __OSX_AVAILABLE_STARTING(__MAC_10_8, __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 + * array. This timestamp is an authenticated timestamp provided by + * a timestamping authority. + * + * Returns paramErr if the CMS message was not signed or if signerIndex + * is greater than the number of signers of the message minus one. It returns + * errSecItemNotFound if no certificates were found. + * + * This cannot be called until after CMSDecoderFinalizeMessage() is called. + */ +OSStatus CMSDecoderCopySignerTimestampCertificates( + CMSDecoderRef cmsDecoder, + size_t signerIndex, /* usually 0 */ + CFArrayRef *certificateRefs) /* RETURNED */ + __OSX_AVAILABLE_STARTING(__MAC_10_8, __IPHONE_NA); + +#ifdef __cplusplus +} +#endif + +#endif /* _CMS_DECODER_H_ */ + diff --git a/libsecurity_cms/lib/CMSEncoder.cpp b/libsecurity_cms/lib/CMSEncoder.cpp new file mode 100644 index 00000000..d41e2af3 --- /dev/null +++ b/libsecurity_cms/lib/CMSEncoder.cpp @@ -0,0 +1,1437 @@ +/* + * 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@ + */ + +/* + * CMSEncoder.cpp - encode, sign, and/or encrypt CMS messages. + */ + +#include "CMSEncoder.h" +#include "CMSPrivate.h" +#include "CMSUtils.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#pragma mark --- Private types and definitions --- + +/* + * Encoder state. + */ +typedef enum { + ES_Init, /* between CMSEncoderCreate and earlier of CMSEncoderUpdateContent + * and CMSEncodeGetCmsMessage */ + ES_Msg, /* created cmsMsg in CMSEncodeGetCmsMessage, but no encoder yet */ + ES_Updating, /* between first CMSEncoderUpdateContent and CMSEncoderCopyEncodedContent */ + ES_Final /* CMSEncoderCopyEncodedContent has been called */ +} CMSEncoderState; + +/* + * High-level operation: what are we doing? + */ +typedef enum { + EO_Sign, + EO_Encrypt, + EO_SignEncrypt +} CMSEncoderOp; + +/* + * Caller's CMSEncoderRef points to one of these. + */ +struct _CMSEncoder { + CFRuntimeBase base; + CMSEncoderState encState; + CMSEncoderOp op; + Boolean detachedContent; + CSSM_OID eContentType; + CFMutableArrayRef signers; + CFMutableArrayRef recipients; + CFMutableArrayRef otherCerts; + CMSSignedAttributes signedAttributes; + CFAbsoluteTime signingTime; + SecCmsMessageRef cmsMsg; + SecArenaPoolRef arena; /* the encoder's arena */ + SecCmsEncoderRef encoder; + CSSM_DATA encoderOut; /* output goes here... */ + bool customCoder; /* unless this is set by + * CMSEncoderSetEncoder */ + CMSCertificateChainMode chainMode; +}; + +static void cmsEncoderInit(CFTypeRef enc); +static void cmsEncoderFinalize(CFTypeRef enc); + +static CFRuntimeClass cmsEncoderRuntimeClass = +{ + 0, /* version */ + "CMSEncoder", + cmsEncoderInit, + NULL, /* copy */ + cmsEncoderFinalize, + NULL, /* equal - just use pointer equality */ + NULL, /* hash, ditto */ + NULL, /* copyFormattingDesc */ + NULL /* copyDebugDesc */ +}; + +void +CmsMessageSetTSACallback(CMSEncoderRef cmsEncoder, SecCmsTSACallback tsaCallback); + +#pragma mark --- Private routines --- + +/* + * Decode a CFStringRef representation of an integer + */ +static int cfStringToNumber( + CFStringRef inStr) +{ + int max = 32; + char buf[max]; + if (!inStr || !CFStringGetCString(inStr, buf, max-1, kCFStringEncodingASCII)) + return -1; + return atoi(buf); +} + +/* + * Encode an integer component of an OID, return resulting number of bytes; + * actual bytes are mallocd and returned in *encodeArray. + */ +static unsigned encodeNumber( + int num, + unsigned char **encodeArray) // mallocd and RETURNED +{ + unsigned char *result; + unsigned dex; + unsigned numDigits = 0; + unsigned scratch; + + /* trival case - 0 maps to 0 */ + if(num == 0) { + *encodeArray = (unsigned char *)malloc(1); + **encodeArray = 0; + return 1; + } + + /* first calculate the number of digits in num, base 128 */ + scratch = (unsigned)num; + while(scratch != 0) { + numDigits++; + scratch >>= 7; + } + + result = (unsigned char *)malloc(numDigits); + scratch = (unsigned)num; + for(dex=0; dex>= 7; + } + + /* all digits except the last one have m.s. bit set */ + for(dex=0; dex<(numDigits - 1); dex++) { + result[dex] |= 0x80; + } + + *encodeArray = result; + return numDigits; +} + +/* + * Given an OID in dotted-decimal string representation, convert to binary + * DER format. Returns a pointer in outOid which the caller must free(), + * as well as the length of the data in outLen. + * Function returns 0 if successful, non-zero otherwise. + */ +static int encodeOid( + const unsigned char *inStr, + unsigned char **outOid, + unsigned int *outLen) +{ + unsigned char **digits = NULL; /* array of char * from encodeNumber */ + unsigned *numDigits = NULL; /* array of unsigned from encodeNumber */ + unsigned digit; + unsigned numDigitBytes; /* total #of output chars */ + unsigned char firstByte; + unsigned char *outP; + unsigned numsToProcess; + CFStringRef oidStr = NULL; + CFArrayRef argvRef = NULL; + int num, argc, result = 1; + + /* parse input string into array of substrings */ + if (!inStr || !outOid || !outLen) goto cleanExit; + oidStr = CFStringCreateWithCString(NULL, (const char *)inStr, kCFStringEncodingASCII); + if (!oidStr) goto cleanExit; + argvRef = CFStringCreateArrayBySeparatingStrings(NULL, oidStr, CFSTR(".")); + if (!argvRef) goto cleanExit; + argc = CFArrayGetCount(argvRef); + if (argc < 3) goto cleanExit; + + /* first two numbers in OID munge together */ + num = cfStringToNumber((CFStringRef)CFArrayGetValueAtIndex(argvRef, 0)); + if (num < 0) goto cleanExit; + firstByte = (40 * num); + num = cfStringToNumber((CFStringRef)CFArrayGetValueAtIndex(argvRef, 1)); + if (num < 0) goto cleanExit; + firstByte += num; + numDigitBytes = 1; + + numsToProcess = argc - 2; + if(numsToProcess > 0) { + /* skip this loop in the unlikely event that input is only two numbers */ + digits = (unsigned char **) malloc(numsToProcess * sizeof(unsigned char *)); + numDigits = (unsigned *) malloc(numsToProcess * sizeof(unsigned)); + for(digit=0; digitData. + * + * Function returns 0 if successful, non-zero otherwise. + */ + +static int convertOid( + CFTypeRef inRef, + CSSM_OID *outOid) +{ + if (!inRef || !outOid) + return paramErr; + + unsigned char *oidData = NULL; + unsigned int oidLen = 0; + + if (CFGetTypeID(inRef) == CFStringGetTypeID()) { + // CFStringRef: OID representation is a dotted-decimal string + CFStringRef inStr = (CFStringRef)inRef; + CFIndex max = CFStringGetLength(inStr) * 3; + char buf[max]; + if (!CFStringGetCString(inStr, buf, max-1, kCFStringEncodingASCII)) + return paramErr; + + if(encodeOid((unsigned char *)buf, &oidData, &oidLen) != 0) + return paramErr; + } + else if (CFGetTypeID(inRef) == CFDataGetTypeID()) { + // CFDataRef: OID representation is in binary DER format + CFDataRef inData = (CFDataRef)inRef; + oidLen = (unsigned int) CFDataGetLength(inData); + oidData = (unsigned char *) malloc(oidLen); + memcpy(oidData, CFDataGetBytePtr(inData), oidLen); + } + else { + // Not in a format we understand + return paramErr; + } + outOid->Length = oidLen; + outOid->Data = (uint8 *)oidData; + return 0; +} + +static CFTypeID cmsEncoderTypeID = _kCFRuntimeNotATypeID; + +/* one time only class init, called via pthread_once() in CMSEncoderGetTypeID() */ +static void cmsEncoderClassInitialize(void) +{ + cmsEncoderTypeID = + _CFRuntimeRegisterClass((const CFRuntimeClass * const)&cmsEncoderRuntimeClass); +} + +/* init called out from _CFRuntimeCreateInstance() */ +static void cmsEncoderInit(CFTypeRef enc) +{ + char *start = ((char *)enc) + sizeof(CFRuntimeBase); + memset(start, 0, sizeof(struct _CMSEncoder) - sizeof(CFRuntimeBase)); +} + +/* + * Dispose of a CMSEncoder. Called out from CFRelease(). + */ +static void cmsEncoderFinalize( + CFTypeRef enc) +{ + CMSEncoderRef cmsEncoder = (CMSEncoderRef)enc; + if(cmsEncoder == NULL) { + return; + } + if(cmsEncoder->eContentType.Data != NULL) { + free(cmsEncoder->eContentType.Data); + } + CFRELEASE(cmsEncoder->signers); + CFRELEASE(cmsEncoder->recipients); + CFRELEASE(cmsEncoder->otherCerts); + if(cmsEncoder->cmsMsg != NULL) { + SecCmsMessageDestroy(cmsEncoder->cmsMsg); + } + if(cmsEncoder->arena != NULL) { + SecArenaPoolFree(cmsEncoder->arena, false); + } + if(cmsEncoder->encoder != NULL) { + /* + * Normally this gets freed in SecCmsEncoderFinish - this is + * an error case. + */ + SecCmsEncoderDestroy(cmsEncoder->encoder); + } +} + +static OSStatus cmsSetupEncoder( + CMSEncoderRef cmsEncoder) +{ + OSStatus ortn; + + ASSERT(cmsEncoder->arena == NULL); + ASSERT(cmsEncoder->encoder == NULL); + + ortn = SecArenaPoolCreate(1024, &cmsEncoder->arena); + if(ortn) { + return cmsRtnToOSStatus(ortn); + } + ortn = SecCmsEncoderCreate(cmsEncoder->cmsMsg, + NULL, NULL, // no callback + &cmsEncoder->encoderOut, // data goes here + cmsEncoder->arena, + NULL, NULL, // no password callback (right?) + NULL, NULL, // decrypt key callback + NULL, NULL, // detached digests + &cmsEncoder->encoder); + if(ortn) { + return cmsRtnToOSStatus(ortn); + } + return noErr; +} + +/* + * Set up a SecCmsMessageRef for a SignedData creation. + */ +static OSStatus cmsSetupForSignedData( + CMSEncoderRef cmsEncoder) +{ + ASSERT((cmsEncoder->signers != NULL) || (cmsEncoder->otherCerts != NULL)); + + SecCmsContentInfoRef contentInfo = NULL; + SecCmsSignedDataRef signedData = NULL; + OSStatus ortn; + + /* build chain of objects: message->signedData->data */ + if(cmsEncoder->cmsMsg != NULL) { + SecCmsMessageDestroy(cmsEncoder->cmsMsg); + } + cmsEncoder->cmsMsg = SecCmsMessageCreate(NULL); + if(cmsEncoder->cmsMsg == NULL) { + return internalComponentErr; + } + + signedData = SecCmsSignedDataCreate(cmsEncoder->cmsMsg); + if(signedData == NULL) { + return internalComponentErr; + } + contentInfo = SecCmsMessageGetContentInfo(cmsEncoder->cmsMsg); + ortn = SecCmsContentInfoSetContentSignedData(cmsEncoder->cmsMsg, contentInfo, + signedData); + if(ortn) { + return cmsRtnToOSStatus(ortn); + } + contentInfo = SecCmsSignedDataGetContentInfo(signedData); + if(cmsEncoder->eContentType.Data != NULL) { + /* Override the default eContentType of id-data */ + ortn = SecCmsContentInfoSetContentOther(cmsEncoder->cmsMsg, + contentInfo, + NULL, /* data - provided to encoder, not here */ + cmsEncoder->detachedContent, + &cmsEncoder->eContentType); + } + else { + ortn = SecCmsContentInfoSetContentData(cmsEncoder->cmsMsg, + contentInfo, + NULL, /* data - provided to encoder, not here */ + cmsEncoder->detachedContent); + } + if(ortn) { + ortn = cmsRtnToOSStatus(ortn); + CSSM_PERROR("SecCmsContentInfoSetContent*", ortn); + return ortn; + } + + /* optional 'global' (per-SignedData) certs */ + if(cmsEncoder->otherCerts != NULL) { + ortn = SecCmsSignedDataAddCertList(signedData, cmsEncoder->otherCerts); + if(ortn) { + ortn = cmsRtnToOSStatus(ortn); + CSSM_PERROR("SecCmsSignedDataAddCertList", ortn); + return ortn; + } + } + + /* SignerInfos, one per signer */ + CFIndex numSigners = 0; + if(cmsEncoder->signers != NULL) { + /* this is optional...in case we're just creating a cert bundle */ + numSigners = CFArrayGetCount(cmsEncoder->signers); + } + CFIndex dex; + SecKeychainRef ourKc = NULL; + SecCertificateRef ourCert = NULL; + SecCmsCertChainMode chainMode = SecCmsCMCertChain; + + switch(cmsEncoder->chainMode) { + case kCMSCertificateNone: + chainMode = SecCmsCMNone; + break; + case kCMSCertificateSignerOnly: + chainMode = SecCmsCMCertOnly; + break; + case kCMSCertificateChainWithRoot: + chainMode = SecCmsCMCertChainWithRoot; + break; + default: + break; + } + for(dex=0; dexsigners, dex); + ortn = SecIdentityCopyCertificate(ourId, &ourCert); + if(ortn) { + CSSM_PERROR("SecIdentityCopyCertificate", ortn); + break; + } + ortn = SecKeychainItemCopyKeychain((SecKeychainItemRef)ourCert, &ourKc); + if(ortn) { + CSSM_PERROR("SecKeychainItemCopyKeychain", ortn); + break; + } + signerInfo = SecCmsSignerInfoCreate(cmsEncoder->cmsMsg, ourId, SEC_OID_SHA1); + if (signerInfo == NULL) { + ortn = internalComponentErr; + break; + } + + /* we want the cert chain included for this one */ + /* NOTE the usage parameter is currently unused by the SMIME lib */ + ortn = SecCmsSignerInfoIncludeCerts(signerInfo, chainMode, + certUsageEmailSigner); + if(ortn) { + ortn = cmsRtnToOSStatus(ortn); + CSSM_PERROR("SecCmsSignerInfoIncludeCerts", ortn); + break; + } + + /* other options */ + if(cmsEncoder->signedAttributes & kCMSAttrSmimeCapabilities) { + ortn = SecCmsSignerInfoAddSMIMECaps(signerInfo); + if(ortn) { + ortn = cmsRtnToOSStatus(ortn); + CSSM_PERROR("SecCmsSignerInfoAddSMIMEEncKeyPrefs", ortn); + break; + } + } + if(cmsEncoder->signedAttributes & kCMSAttrSmimeEncryptionKeyPrefs) { + ortn = SecCmsSignerInfoAddSMIMEEncKeyPrefs(signerInfo, ourCert, ourKc); + if(ortn) { + ortn = cmsRtnToOSStatus(ortn); + CSSM_PERROR("SecCmsSignerInfoAddSMIMEEncKeyPrefs", ortn); + break; + } + } + if(cmsEncoder->signedAttributes & kCMSAttrSmimeMSEncryptionKeyPrefs) { + ortn = SecCmsSignerInfoAddMSSMIMEEncKeyPrefs(signerInfo, ourCert, ourKc); + if(ortn) { + ortn = cmsRtnToOSStatus(ortn); + CSSM_PERROR("SecCmsSignerInfoAddMSSMIMEEncKeyPrefs", ortn); + break; + } + } + if(cmsEncoder->signedAttributes & kCMSAttrSigningTime) { + if (cmsEncoder->signingTime == 0) + cmsEncoder->signingTime = CFAbsoluteTimeGetCurrent(); + ortn = SecCmsSignerInfoAddSigningTime(signerInfo, cmsEncoder->signingTime); + if(ortn) { + ortn = cmsRtnToOSStatus(ortn); + CSSM_PERROR("SecCmsSignerInfoAddSigningTime", ortn); + break; + } + } + + ortn = SecCmsSignedDataAddSignerInfo(signedData, signerInfo); + if(ortn) { + ortn = cmsRtnToOSStatus(ortn); + CSSM_PERROR("SecCmsSignedDataAddSignerInfo", ortn); + break; + } + + CFRELEASE(ourKc); + CFRELEASE(ourCert); + ourKc = NULL; + ourCert = NULL; + } + if(ortn) { + CFRELEASE(ourKc); + CFRELEASE(ourCert); + } + return ortn; +} + +/* + * Set up a SecCmsMessageRef for a EnvelopedData creation. + */ +static OSStatus cmsSetupForEnvelopedData( + CMSEncoderRef cmsEncoder) +{ + ASSERT(cmsEncoder->op == EO_Encrypt); + ASSERT(cmsEncoder->recipients != NULL); + + SecCmsContentInfoRef contentInfo = NULL; + SecCmsEnvelopedDataRef envelopedData = NULL; + SECOidTag algorithmTag; + int keySize; + OSStatus ortn; + + /* + * Find encryption algorithm...unfortunately we need a NULL-terminated array + * of SecCertificateRefs for this. + */ + CFIndex numCerts = CFArrayGetCount(cmsEncoder->recipients); + CFIndex dex; + SecCertificateRef *certArray = (SecCertificateRef *)malloc( + (numCerts+1) * sizeof(SecCertificateRef)); + + for(dex=0; dexrecipients, dex); + } + certArray[numCerts] = NULL; + ortn = SecSMIMEFindBulkAlgForRecipients(certArray, &algorithmTag, &keySize); + free(certArray); + if(ortn) { + CSSM_PERROR("SecSMIMEFindBulkAlgForRecipients", ortn); + return ortn; + } + + /* build chain of objects: message->envelopedData->data */ + if(cmsEncoder->cmsMsg != NULL) { + SecCmsMessageDestroy(cmsEncoder->cmsMsg); + } + cmsEncoder->cmsMsg = SecCmsMessageCreate(NULL); + if(cmsEncoder->cmsMsg == NULL) { + return internalComponentErr; + } + envelopedData = SecCmsEnvelopedDataCreate(cmsEncoder->cmsMsg, + algorithmTag, keySize); + if(envelopedData == NULL) { + return internalComponentErr; + } + contentInfo = SecCmsMessageGetContentInfo(cmsEncoder->cmsMsg); + ortn = SecCmsContentInfoSetContentEnvelopedData(cmsEncoder->cmsMsg, + contentInfo, envelopedData); + if(ortn) { + ortn = cmsRtnToOSStatus(ortn); + CSSM_PERROR("SecCmsContentInfoSetContentEnvelopedData", ortn); + return ortn; + } + contentInfo = SecCmsEnvelopedDataGetContentInfo(envelopedData); + if(cmsEncoder->eContentType.Data != NULL) { + /* Override the default ContentType of id-data */ + ortn = SecCmsContentInfoSetContentOther(cmsEncoder->cmsMsg, + contentInfo, + NULL, /* data - provided to encoder, not here */ + FALSE, /* detachedContent */ + &cmsEncoder->eContentType); + } + else { + ortn = SecCmsContentInfoSetContentData(cmsEncoder->cmsMsg, + contentInfo, + NULL /* data - provided to encoder, not here */, + cmsEncoder->detachedContent); + } + if(ortn) { + ortn = cmsRtnToOSStatus(ortn); + CSSM_PERROR("SecCmsContentInfoSetContentData*", ortn); + return ortn; + } + + /* + * create & attach recipient information, one for each recipient + */ + for(dex=0; dexrecipients, dex); + recipientInfo = SecCmsRecipientInfoCreate(cmsEncoder->cmsMsg, thisRecip); + ortn = SecCmsEnvelopedDataAddRecipient(envelopedData, recipientInfo); + if(ortn) { + ortn = cmsRtnToOSStatus(ortn); + CSSM_PERROR("SecCmsEnvelopedDataAddRecipient", ortn); + return ortn; + } + } + return noErr; +} + +/* + * Set up cmsMsg. Called from either the first call to CMSEncoderUpdateContent, or + * from CMSEncodeGetCmsMessage(). + */ +static OSStatus cmsSetupCmsMsg( + CMSEncoderRef cmsEncoder) +{ + ASSERT(cmsEncoder != NULL); + ASSERT(cmsEncoder->encState == ES_Init); + + /* figure out what high-level operation we're doing */ + if((cmsEncoder->signers != NULL) || (cmsEncoder->otherCerts != NULL)) { + if(cmsEncoder->recipients != NULL) { + cmsEncoder->op = EO_SignEncrypt; + } + else { + cmsEncoder->op = EO_Sign; + } + } + else if(cmsEncoder->recipients != NULL) { + cmsEncoder->op = EO_Encrypt; + } + else { + dprintf("CMSEncoderUpdateContent: nothing to do\n"); + return paramErr; + } + + OSStatus ortn = noErr; + + switch(cmsEncoder->op) { + case EO_Sign: + case EO_SignEncrypt: + /* If we're signing & encrypting, do the signing first */ + ortn = cmsSetupForSignedData(cmsEncoder); + break; + case EO_Encrypt: + ortn = cmsSetupForEnvelopedData(cmsEncoder); + break; + } + cmsEncoder->encState = ES_Msg; + return ortn; +} + +/* + * ASN.1 template for decoding a ContentInfo. + */ +typedef struct { + CSSM_OID contentType; + CSSM_DATA content; +} SimpleContentInfo; + +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, + offsetof(SimpleContentInfo, content), + kSecAsn1AnyTemplate }, + { 0, } +}; + +/* + * Obtain the content of a contentInfo, This basically strips off the contentType OID + * and returns its ASN_ANY content, allocated the provided coder's memory space. + */ +static OSStatus cmsContentInfoContent( + SecAsn1CoderRef asn1Coder, + const CSSM_DATA *contentInfo, + CSSM_DATA *content) /* RETURNED */ +{ + OSStatus ortn; + SimpleContentInfo decodedInfo; + + memset(&decodedInfo, 0, sizeof(decodedInfo)); + ortn = SecAsn1DecodeData(asn1Coder, contentInfo, + cmsSimpleContentInfoTemplate, &decodedInfo); + if(ortn) { + return ortn; + } + if(decodedInfo.content.Data == NULL) { + dprintf("***Error decoding contentInfo: no content\n"); + return internalComponentErr; + } + *content = decodedInfo.content; + return noErr; +} + +#pragma mark --- Start of Public API --- + +CFTypeID CMSEncoderGetTypeID(void) +{ + static pthread_once_t once = PTHREAD_ONCE_INIT; + + if(cmsEncoderTypeID == _kCFRuntimeNotATypeID) { + pthread_once(&once, &cmsEncoderClassInitialize); + } + return cmsEncoderTypeID; +} + +/* + * Create a CMSEncoder. Result must eventually be freed via CFRelease(). + */ +OSStatus CMSEncoderCreate( + CMSEncoderRef *cmsEncoderOut) /* RETURNED */ +{ + CMSEncoderRef cmsEncoder = NULL; + + uint32_t extra = sizeof(*cmsEncoder) - sizeof(cmsEncoder->base); + cmsEncoder = (CMSEncoderRef)_CFRuntimeCreateInstance(NULL, CMSEncoderGetTypeID(), + extra, NULL); + if(cmsEncoder == NULL) { + return memFullErr; + } + cmsEncoder->encState = ES_Init; + cmsEncoder->chainMode = kCMSCertificateChain; + *cmsEncoderOut = cmsEncoder; + return noErr; +} + +#pragma mark --- Getters & Setters --- + +/* + * Specify signers of the CMS message; implies that the message will be signed. + */ +OSStatus CMSEncoderAddSigners( + CMSEncoderRef cmsEncoder, + CFTypeRef signerOrArray) +{ + if(cmsEncoder == NULL) { + return paramErr; + } + if(cmsEncoder->encState != ES_Init) { + return paramErr; + } + return cmsAppendToArray(signerOrArray, &cmsEncoder->signers, SecIdentityGetTypeID()); +} + +/* + * Obtain an array of signers as specified in CMSEncoderSetSigners(). + */ +OSStatus CMSEncoderCopySigners( + CMSEncoderRef cmsEncoder, + CFArrayRef *signers) +{ + if((cmsEncoder == NULL) || (signers == NULL)) { + return paramErr; + } + if(cmsEncoder->signers != NULL) { + CFRetain(cmsEncoder->signers); + } + *signers = cmsEncoder->signers; + return noErr; +} + +/* + * Specify recipients of the message. Implies that the message will be encrypted. + */ +OSStatus CMSEncoderAddRecipients( + CMSEncoderRef cmsEncoder, + CFTypeRef recipientOrArray) +{ + if(cmsEncoder == NULL) { + return paramErr; + } + if(cmsEncoder->encState != ES_Init) { + return paramErr; + } + return cmsAppendToArray(recipientOrArray, &cmsEncoder->recipients, + SecCertificateGetTypeID()); +} + +/* + * Obtain an array of recipients as specified in CMSEncoderSetRecipients(). + */ +OSStatus CMSEncoderCopyRecipients( + CMSEncoderRef cmsEncoder, + CFArrayRef *recipients) +{ + if((cmsEncoder == NULL) || (recipients == NULL)) { + return paramErr; + } + if(cmsEncoder->recipients != NULL) { + CFRetain(cmsEncoder->recipients); + } + *recipients = cmsEncoder->recipients; + return noErr; +} + +/* + * Specify additional certs to include in a signed message. + */ +OSStatus CMSEncoderAddSupportingCerts( + CMSEncoderRef cmsEncoder, + CFTypeRef certOrArray) +{ + if(cmsEncoder == NULL) { + return paramErr; + } + if(cmsEncoder->encState != ES_Init) { + return paramErr; + } + return cmsAppendToArray(certOrArray, &cmsEncoder->otherCerts, + SecCertificateGetTypeID()); +} + +/* + * Obtain the SecCertificates provided in CMSEncoderAddSupportingCerts(). + */ +OSStatus CMSEncoderCopySupportingCerts( + CMSEncoderRef cmsEncoder, + CFArrayRef *certs) /* RETURNED */ +{ + if((cmsEncoder == NULL) || (certs == NULL)) { + return paramErr; + } + if(cmsEncoder->otherCerts != NULL) { + CFRetain(cmsEncoder->otherCerts); + } + *certs = cmsEncoder->otherCerts; + return noErr; +} + +OSStatus CMSEncoderSetHasDetachedContent( + CMSEncoderRef cmsEncoder, + Boolean detachedContent) +{ + if(cmsEncoder == NULL) { + return paramErr; + } + if(cmsEncoder->encState != ES_Init) { + return paramErr; + } + cmsEncoder->detachedContent = detachedContent; + return noErr; +} + +OSStatus CMSEncoderGetHasDetachedContent( + CMSEncoderRef cmsEncoder, + Boolean *detachedContent) /* RETURNED */ +{ + if((cmsEncoder == NULL) || (detachedContent == NULL)) { + return paramErr; + } + *detachedContent = cmsEncoder->detachedContent; + return noErr; +} + +/* + * Optionally specify an eContentType OID for the inner EncapsulatedData for + * a signed message. The default eContentType, used of this function is not + * called, is id-data. + */ +OSStatus CMSEncoderSetEncapsulatedContentType( + CMSEncoderRef cmsEncoder, + const CSSM_OID *eContentType) +{ + if((cmsEncoder == NULL) || (eContentType == NULL)) { + return paramErr; + } + if(cmsEncoder->encState != ES_Init) { + return paramErr; + } + + CSSM_OID *ecOid = &cmsEncoder->eContentType; + if(ecOid->Data != NULL) { + free(ecOid->Data); + } + cmsCopyCmsData(eContentType, ecOid); + return noErr; +} + +OSStatus CMSEncoderSetEncapsulatedContentTypeOID( + CMSEncoderRef cmsEncoder, + CFTypeRef eContentTypeOID) +{ + // convert eContentTypeOID to a CSSM_OID + CSSM_OID contentType = { 0, NULL }; + if (!eContentTypeOID || convertOid(eContentTypeOID, &contentType) != 0) + return paramErr; + OSStatus result = CMSEncoderSetEncapsulatedContentType(cmsEncoder, &contentType); + if (contentType.Data) + free(contentType.Data); + return result; +} + +/* + * Obtain the eContentType OID specified in CMSEncoderSetEncapsulatedContentType(). + */ +OSStatus CMSEncoderCopyEncapsulatedContentType( + CMSEncoderRef cmsEncoder, + CFDataRef *eContentType) +{ + if((cmsEncoder == NULL) || (eContentType == NULL)) { + return paramErr; + } + + CSSM_OID *ecOid = &cmsEncoder->eContentType; + if(ecOid->Data == NULL) { + *eContentType = NULL; + } + else { + *eContentType = CFDataCreate(NULL, ecOid->Data, ecOid->Length); + } + return noErr; +} + +/* + * Optionally specify signed attributes. Only meaningful when creating a + * signed message. If this is called, it must be called before + * CMSEncoderUpdateContent(). + */ +OSStatus CMSEncoderAddSignedAttributes( + CMSEncoderRef cmsEncoder, + CMSSignedAttributes signedAttributes) +{ + if(cmsEncoder == NULL) { + return paramErr; + } + if(cmsEncoder->encState != ES_Init) { + return paramErr; + } + cmsEncoder->signedAttributes = signedAttributes; + return noErr; +} + +/* + * Set the signing time for a CMSEncoder. + * This is only used if the kCMSAttrSigningTime attribute is included. + */ +OSStatus CMSEncoderSetSigningTime( + CMSEncoderRef cmsEncoder, + CFAbsoluteTime time) +{ + if(cmsEncoder == NULL) { + return paramErr; + } + if(cmsEncoder->encState != ES_Init) { + return paramErr; + } + cmsEncoder->signingTime = time; + return noErr; +} + + +OSStatus CMSEncoderSetCertificateChainMode( + CMSEncoderRef cmsEncoder, + CMSCertificateChainMode chainMode) +{ + if(cmsEncoder == NULL) { + return paramErr; + } + if(cmsEncoder->encState != ES_Init) { + return paramErr; + } + switch(chainMode) { + case kCMSCertificateNone: + case kCMSCertificateSignerOnly: + case kCMSCertificateChain: + case kCMSCertificateChainWithRoot: + break; + default: + return paramErr; + } + cmsEncoder->chainMode = chainMode; + return noErr; +} + +OSStatus CMSEncoderGetCertificateChainMode( + CMSEncoderRef cmsEncoder, + CMSCertificateChainMode *chainModeOut) +{ + if(cmsEncoder == NULL) { + return paramErr; + } + *chainModeOut = cmsEncoder->chainMode; + return noErr; +} + +void +CmsMessageSetTSACallback(CMSEncoderRef cmsEncoder, SecCmsTSACallback tsaCallback) +{ + if (cmsEncoder->cmsMsg) + SecCmsMessageSetTSACallback(cmsEncoder->cmsMsg, tsaCallback); +} + +void +CmsMessageSetTSAContext(CMSEncoderRef cmsEncoder, CFTypeRef tsaContext) +{ + if (cmsEncoder->cmsMsg) + SecCmsMessageSetTSAContext(cmsEncoder->cmsMsg, tsaContext); +} + +#pragma mark --- Action --- + +/* + * Feed content bytes into the encoder. + * Can be called multiple times. + * No 'setter' routines can be called after this function has been called. + */ +OSStatus CMSEncoderUpdateContent( + CMSEncoderRef cmsEncoder, + const void *content, + size_t contentLen) +{ + if(cmsEncoder == NULL) { + return paramErr; + } + + OSStatus ortn = noErr; + switch(cmsEncoder->encState) { + case ES_Init: + /* + * First time thru: do the CmsMsg setup. + */ + ortn = cmsSetupCmsMsg(cmsEncoder); + if(ortn) { + return ortn; + } + /* fall thru to set up the encoder */ + + case ES_Msg: + /* We have a cmsMsg but no encoder; create one */ + ASSERT(cmsEncoder->cmsMsg != NULL); + ASSERT(cmsEncoder->encoder == NULL); + ortn = cmsSetupEncoder(cmsEncoder); + if(ortn) { + return ortn; + } + /* only legal calls now are update and finalize */ + cmsEncoder->encState = ES_Updating; + break; + + case ES_Updating: + ASSERT(cmsEncoder->encoder != NULL); + break; + + case ES_Final: + /* Too late for another update */ + return paramErr; + + default: + return internalComponentErr; + } + + /* FIXME - CFIndex same size as size_t on 64bit? */ + ortn = SecCmsEncoderUpdate(cmsEncoder->encoder, content, (CFIndex)contentLen); + if(ortn) { + ortn = cmsRtnToOSStatus(ortn); + CSSM_PERROR("SecCmsEncoderUpdate", ortn); + } + return ortn; +} + +/* + * Finish encoding the message and obtain the encoded result. + * Caller must CFRelease the result. + */ +OSStatus CMSEncoderCopyEncodedContent( + CMSEncoderRef cmsEncoder, + CFDataRef *encodedContent) +{ + if((cmsEncoder == NULL) || (encodedContent == NULL)) { + return paramErr; + } + + OSStatus ortn; + + switch(cmsEncoder->encState) { + case ES_Updating: + /* normal termination */ + break; + case ES_Final: + /* already been called */ + return paramErr; + case ES_Msg: + case ES_Init: + /* + * The only time these are legal is when we're doing a SignedData + * with certificates only (no signers, no content). + */ + if((cmsEncoder->signers != NULL) || + (cmsEncoder->recipients != NULL) || + (cmsEncoder->otherCerts == NULL)) { + return paramErr; + } + + /* Set up for certs only */ + ortn = cmsSetupForSignedData(cmsEncoder); + if(ortn) { + return ortn; + } + /* and an encoder */ + ortn = cmsSetupEncoder(cmsEncoder); + if(ortn) { + return ortn; + } + break; + } + + + ASSERT(cmsEncoder->encoder != NULL); + ortn = SecCmsEncoderFinish(cmsEncoder->encoder); + /* regardless of the outcome, the encoder itself has been freed */ + cmsEncoder->encoder = NULL; + if(ortn) { + return cmsRtnToOSStatus(ortn); + } + cmsEncoder->encState = ES_Final; + + if((cmsEncoder->encoderOut.Data == NULL) && !cmsEncoder->customCoder) { + /* not sure how this could happen... */ + dprintf("Successful encode, but no data\n"); + return internalComponentErr; + } + if(cmsEncoder->customCoder) { + /* we're done */ + *encodedContent = NULL; + return noErr; + } + + /* in two out of three cases, we're done */ + switch(cmsEncoder->op) { + case EO_Sign: + case EO_Encrypt: + *encodedContent = CFDataCreate(NULL, (const UInt8 *)cmsEncoder->encoderOut.Data, + cmsEncoder->encoderOut.Length); + return noErr; + case EO_SignEncrypt: + /* proceed, more work to do */ + break; + } + + /* + * Signing & encrypting. + * Due to bugs in the libsecurity_smime encoder, it can't encode nested + * ContentInfos in one shot. So we do another pass, specifying the SignedData + * inside of the ContentInfo we just created as the data to encrypt. + */ + SecAsn1CoderRef asn1Coder = NULL; + CSSM_DATA signedData = {0, NULL}; + + ortn = SecAsn1CoderCreate(&asn1Coder); + if(ortn) { + return ortn; + } + ortn = cmsContentInfoContent(asn1Coder, &cmsEncoder->encoderOut, &signedData); + if(ortn) { + goto errOut; + } + + /* now just encrypt that, one-shot */ + ortn = CMSEncode(NULL, /* no signers this time */ + cmsEncoder->recipients, + &CSSMOID_PKCS7_SignedData, /* fake out encoder so it doesn't try to actually + * encode the signedData - this asserts the + * SEC_OID_OTHER OID tag in the EnvelopedData's + * ContentInfo */ + FALSE, /* detachedContent */ + kCMSAttrNone, /* signedAttributes - none this time */ + signedData.Data, signedData.Length, + encodedContent); + +errOut: + if(asn1Coder) { + SecAsn1CoderRelease(asn1Coder); + } + return ortn; +} + +#pragma mark --- High-level API --- + +/* + * High-level, one-shot encoder function. + */ +OSStatus CMSEncode( + CFTypeRef signers, + CFTypeRef recipients, + const CSSM_OID *eContentType, + Boolean detachedContent, + CMSSignedAttributes signedAttributes, + const void *content, + size_t contentLen, + CFDataRef *encodedContent) /* RETURNED */ +{ + if((signers == NULL) && (recipients == NULL)) { + return paramErr; + } + if(encodedContent == NULL) { + return paramErr; + } + + CMSEncoderRef cmsEncoder; + OSStatus ortn; + + /* set up the encoder */ + ortn = CMSEncoderCreate(&cmsEncoder); + if(ortn) { + return ortn; + } + + /* subsequent errors to errOut: */ + if(signers) { + ortn = CMSEncoderAddSigners(cmsEncoder, signers); + if(ortn) { + goto errOut; + } + } + if(recipients) { + ortn = CMSEncoderAddRecipients(cmsEncoder, recipients); + if(ortn) { + goto errOut; + } + } + if(eContentType) { + ortn = CMSEncoderSetEncapsulatedContentType(cmsEncoder, eContentType); + if(ortn) { + goto errOut; + } + } + if(detachedContent) { + ortn = CMSEncoderSetHasDetachedContent(cmsEncoder, detachedContent); + if(ortn) { + goto errOut; + } + } + if(signedAttributes) { + ortn = CMSEncoderAddSignedAttributes(cmsEncoder, signedAttributes); + if(ortn) { + goto errOut; + } + } + /* GO */ + ortn = CMSEncoderUpdateContent(cmsEncoder, content, contentLen); + if(ortn) { + goto errOut; + } + ortn = CMSEncoderCopyEncodedContent(cmsEncoder, encodedContent); + +errOut: + CFRelease(cmsEncoder); + return ortn; +} + +OSStatus CMSEncodeContent( + CFTypeRef signers, + CFTypeRef recipients, + CFTypeRef eContentTypeOID, + Boolean detachedContent, + CMSSignedAttributes signedAttributes, + const void *content, + size_t contentLen, + CFDataRef *encodedContentOut) /* RETURNED */ +{ + // convert eContentTypeOID to a CSSM_OID + CSSM_OID contentType = { 0, NULL }; + if (eContentTypeOID && convertOid(eContentTypeOID, &contentType) != 0) + return paramErr; + const CSSM_OID *contentTypePtr = (eContentTypeOID) ? &contentType : NULL; + OSStatus result = CMSEncode(signers, recipients, contentTypePtr, + detachedContent, signedAttributes, + content, contentLen, encodedContentOut); + if (contentType.Data) + free(contentType.Data); + return result; +} + +#pragma mark --- SPI routines declared in CMSPrivate.h --- + +/* + * Obtain the SecCmsMessageRef associated with a CMSEncoderRef. + * If we don't have a SecCmsMessageRef yet, we create one now. + * This is the only place where we go to state ES_Msg. + */ +OSStatus CMSEncoderGetCmsMessage( + CMSEncoderRef cmsEncoder, + SecCmsMessageRef *cmsMessage) /* RETURNED */ +{ + if((cmsEncoder == NULL) || (cmsMessage == NULL)) { + return paramErr; + } + if(cmsEncoder->cmsMsg != NULL) { + ASSERT(cmsEncoder->encState != ES_Init); + *cmsMessage = cmsEncoder->cmsMsg; + return noErr; + } + + OSStatus ortn = cmsSetupCmsMsg(cmsEncoder); + if(ortn) { + return ortn; + } + *cmsMessage = cmsEncoder->cmsMsg; + + /* Don't set up encoder yet; caller might do that via CMSEncoderSetEncoder */ + cmsEncoder->encState = ES_Msg; + return noErr; +} + +/* + * Optionally specify a SecCmsEncoderRef to use with a CMSEncoderRef. + * If this is called, it must be called before the first call to + * CMSEncoderUpdateContent(). The CMSEncoderRef takes ownership of the + * incoming SecCmsEncoderRef. + */ +OSStatus CMSEncoderSetEncoder( + CMSEncoderRef cmsEncoder, + SecCmsEncoderRef encoder) +{ + if((cmsEncoder == NULL) || (encoder == NULL)) { + return paramErr; + } + + OSStatus ortn; + + switch(cmsEncoder->encState) { + case ES_Init: + /* No message, no encoder */ + ASSERT(cmsEncoder->cmsMsg == NULL); + ASSERT(cmsEncoder->encoder == NULL); + ortn = cmsSetupCmsMsg(cmsEncoder); + if(ortn) { + return ortn; + } + /* drop thru to set encoder */ + case ES_Msg: + /* cmsMsg but no encoder */ + ASSERT(cmsEncoder->cmsMsg != NULL); + ASSERT(cmsEncoder->encoder == NULL); + cmsEncoder->encoder = encoder; + cmsEncoder->encState = ES_Updating; + cmsEncoder->customCoder = true; /* we won't see data */ + return noErr; + default: + /* no can do, too late */ + return paramErr; + } +} + +/* + * Obtain the SecCmsEncoderRef associated with a CMSEncoderRef. + * Returns a NULL SecCmsEncoderRef if neither CMSEncoderSetEncoder nor + * CMSEncoderUpdateContent() has been called. + * The CMSEncoderRef retains ownership of the SecCmsEncoderRef. + */ +OSStatus CMSEncoderGetEncoder( + CMSEncoderRef cmsEncoder, + SecCmsEncoderRef *encoder) /* RETURNED */ +{ + if((cmsEncoder == NULL) || (encoder == NULL)) { + return paramErr; + } + + /* any state, whether we have an encoder or not is OK */ + *encoder = cmsEncoder->encoder; + return noErr; +} + +#include + +/* + * Obtain the timestamp of signer 'signerIndex' of a CMS message, if + * present. This timestamp is an authenticated timestamp provided by + * a timestamping authority. + * + * Returns paramErr 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 CMSEncoderCopyEncodedContent() is called. + */ +OSStatus CMSEncoderCopySignerTimestamp( + CMSEncoderRef cmsEncoder, + size_t signerIndex, /* usually 0 */ + CFAbsoluteTime *timestamp) /* RETURNED */ +{ + OSStatus status = paramErr; + SecCmsMessageRef cmsg; + SecCmsSignedDataRef signedData = NULL; + int numContentInfos = 0; + + require(cmsEncoder && timestamp, xit); + require_noerr(CMSEncoderGetCmsMessage(cmsEncoder, &cmsg), xit); + numContentInfos = SecCmsMessageContentLevelCount(cmsg); + for (int dex = 0; !signedData && dex < numContentInfos; dex++) + { + SecCmsContentInfoRef ci = SecCmsMessageContentLevel(cmsg, dex); + SECOidTag tag = SecCmsContentInfoGetContentTypeTag(ci); + if (tag == SEC_OID_PKCS7_SIGNED_DATA) + if ((signedData = SecCmsSignedDataRef(SecCmsContentInfoGetContent(ci)))) + if (SecCmsSignerInfoRef signerInfo = SecCmsSignedDataGetSignerInfo(signedData, (int)signerIndex)) + { + status = SecCmsSignerInfoGetTimestampTime(signerInfo, timestamp); + break; + } + } + +xit: + return status; +} diff --git a/libsecurity_cms/lib/CMSEncoder.h b/libsecurity_cms/lib/CMSEncoder.h new file mode 100644 index 00000000..0ae1d8c8 --- /dev/null +++ b/libsecurity_cms/lib/CMSEncoder.h @@ -0,0 +1,403 @@ +/* + * 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@ + */ + +/* + * CMSEncoder.h - encode, sign, and/or encrypt messages in the Cryptographic + * Message Syntax (CMS), per RFC 3852. + * + * A CMS message can be signed, encrypted, or both. A message can be signed by + * an arbitrary number of signers; in this module, signers are expressed as + * SecIdentityRefs. A message can be encrypted for an arbitrary number of + * recipients; recipients are expressed here as SecCertificateRefs. + * + * In CMS terminology, this module performs encryption using the EnvelopedData + * ContentType and signing using the SignedData ContentType. + * + * If the message is both signed and encrypted, it uses "nested ContentInfos" + * in CMS terminology; in this implementation, signed & encrypted messages + * are implemented as an EnvelopedData containing a SignedData. + */ + +#ifndef _CMS_ENCODER_H_ +#define _CMS_ENCODER_H_ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Opaque reference to a CMS encoder object. + * This is a CF object, with standard CF semantics; dispose of it + * with CFRelease(). + */ +typedef struct _CMSEncoder *CMSEncoderRef; + +CFTypeID CMSEncoderGetTypeID(void) + __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); + +/* + * Create a CMSEncoder. Result must eventually be freed via CFRelease(). + */ +OSStatus CMSEncoderCreate( + CMSEncoderRef *cmsEncoderOut) /* RETURNED */ + __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); + +/* + * Specify signers of the CMS message; implies that the message will be signed. + * + * -- Caller can pass in one signer, as a SecIdentityRef, or an array of + * signers, as a CFArray of SecIdentityRefs. + * -- Can be called multiple times. + * -- If the message is not to be signed, don't call this. + * -- If this is called, it must be called before the first call to + * CMSEncoderUpdateContent(). + */ +OSStatus CMSEncoderAddSigners( + CMSEncoderRef cmsEncoder, + CFTypeRef signerOrArray) + __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); + +/* + * Obtain an array of signers as specified in CMSEncoderSetSigners(). + * Returns a NULL signers array if CMSEncoderSetSigners() has not been called. + * Caller must CFRelease the result. + */ +OSStatus CMSEncoderCopySigners( + CMSEncoderRef cmsEncoder, + CFArrayRef *signersOut) /* RETURNED */ + __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); + +/* + * Specify recipients of the message. Implies that the message will + * be encrypted. + * + * -- Caller can pass in one recipient, as a SecCertificateRef, or an + * array of recipients, as a CFArray of SecCertificateRefs. + * -- Can be called multiple times. + * -- If the message is not to be encrypted, don't call this. + * -- If this is called, it must be called before the first call to + * CMSEncoderUpdateContent(). + */ +OSStatus CMSEncoderAddRecipients( + CMSEncoderRef cmsEncoder, + CFTypeRef recipientOrArray) + __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); + +/* + * Obtain an array of recipients as specified in CMSEncoderSetRecipients(). + * Returns a NULL recipients array if CMSEncoderSetRecipients() has not been + * called. + * Caller must CFRelease the result. + */ +OSStatus CMSEncoderCopyRecipients( + CMSEncoderRef cmsEncoder, + CFArrayRef *recipientsOut) /* RETURNED */ + __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); + +/* + * A signed message optionally includes the data to be signed. If the message + * is *not* to include the data to be signed, call this function with a value + * of TRUE for detachedContent. The default, if this function is not called, + * is detachedContent=FALSE, i.e., the message contains the data to be signed. + * + * -- Encrypted messages can not use detached content. (This restriction + * also applies to messages that are both signed and encrypted.) + * -- If this is called, it must be called before the first call to + * CMSEncoderUpdateContent(). + */ +OSStatus CMSEncoderSetHasDetachedContent( + CMSEncoderRef cmsEncoder, + Boolean detachedContent) + __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); + +/* + * Obtain a Boolean indicating whether the current message will have detached + * content. + * Returns the value specified in CMSEncoderHasDetachedContent() if that + * function has been called; else returns the default FALSE. + */ +OSStatus CMSEncoderGetHasDetachedContent( + CMSEncoderRef cmsEncoder, + Boolean *detachedContentOut) /* RETURNED */ + __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); + +/* + * Optionally specify an eContentType OID for the inner EncapsulatedData for + * a signed message. The default eContentType, used if this function is not + * called, is id-data (which is the normal eContentType for applications such + * as SMIME). + * + * If this is called, it must be called before the first call to + * CMSEncoderUpdateContent(). + * + * NOTE: This function is deprecated in Mac OS X 10.7 and later; + * please use CMSEncoderSetEncapsulatedContentTypeOID() instead. + */ +OSStatus CMSEncoderSetEncapsulatedContentType( + CMSEncoderRef cmsEncoder, + const CSSM_OID *eContentType) + /* DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; */ + __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); + +/* + * Optionally specify an eContentType OID for the inner EncapsulatedData for + * a signed message. The default eContentTypeOID, used if this function is not + * called, is id-data (which is the normal eContentType for applications such + * as SMIME). + * + * The eContentTypeOID parameter may be specified as a CF string, e.g.: + * CFSTR("1.2.840.113549.1.7.1") + * + * If this is called, it must be called before the first call to + * CMSEncoderUpdateContent(). + */ +OSStatus CMSEncoderSetEncapsulatedContentTypeOID( + CMSEncoderRef cmsEncoder, + CFTypeRef eContentTypeOID) + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); + +/* + * Obtain the eContentType OID specified in CMSEncoderSetEncapsulatedContentType(). + * If CMSEncoderSetEncapsulatedContentType() has not been called this returns a + * NULL pointer. + * The returned OID's data is in the same format as the data provided to + * CMSEncoderSetEncapsulatedContentType;, i.e., it's the encoded content of + * the OID, not including the tag and length bytes. + */ +OSStatus CMSEncoderCopyEncapsulatedContentType( + CMSEncoderRef cmsEncoder, + CFDataRef *eContentTypeOut) /* RETURNED */ + __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); + +/* + * Signed CMS messages can contain arbitrary sets of certificates beyond those + * indicating the identity of the signer(s). This function provides a means of + * adding these other certs. For normal signed messages it is not necessary to + * call this; the signer cert(s) and the intermediate certs needed to verify the + * signer(s) will be included in the message implicitly. + * + * -- Caller can pass in one cert, as a SecCertificateRef, or an array of certs, + * as a CFArray of SecCertificateRefs. + * -- If this is called, it must be called before the first call to + * CMSEncoderUpdateContent(). + * -- There is a "special case" use of CMS messages which involves neither + * signing nor encryption, but does include certificates. This is commonly + * used to transport "bags" of certificates. When constructing such a + * message, all an application needs to do is to create a CMSEncoderRef, + * call CMSEncoderAddSupportingCerts() one or more times, and then call + * CMSEncoderCopyEncodedContent() to get the resulting cert bag. No 'content' + * need be specified. (This is in fact the primary intended use for + * this function.) + */ +OSStatus CMSEncoderAddSupportingCerts( + CMSEncoderRef cmsEncoder, + CFTypeRef certOrArray) + __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); + +/* + * Obtain the SecCertificates provided in CMSEncoderAddSupportingCerts(). + * If CMSEncoderAddSupportingCerts() has not been called this will return a + * NULL value for *certs. + * Caller must CFRelease the result. + */ +OSStatus CMSEncoderCopySupportingCerts( + CMSEncoderRef cmsEncoder, + CFArrayRef *certsOut) /* RETURNED */ + __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); + +/* + * Standard signed attributes, optionally specified in + * CMSEncoderAddSignedAttributes(). + */ +enum { + kCMSAttrNone = 0x0000, + /* + * S/MIME Capabilities - identifies supported signature, encryption, and + * digest algorithms. + */ + kCMSAttrSmimeCapabilities = 0x0001, + /* + * Indicates that a cert is the preferred cert for S/MIME encryption. + */ + kCMSAttrSmimeEncryptionKeyPrefs = 0x0002, + /* + * Same as kCMSSmimeEncryptionKeyPrefs, using an attribute OID preferred + * by Microsoft. + */ + kCMSAttrSmimeMSEncryptionKeyPrefs = 0x0004, + /* + * Include the signing time. + */ + kCMSAttrSigningTime = 0x0008 +}; +typedef uint32_t CMSSignedAttributes; + +/* + * Optionally specify signed attributes. Only meaningful when creating a + * signed message. If this is called, it must be called before + * CMSEncoderUpdateContent(). + */ +OSStatus CMSEncoderAddSignedAttributes( + CMSEncoderRef cmsEncoder, + CMSSignedAttributes signedAttributes) + __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); + +/* + * Specification of what certificates to include in a signed message. + */ +enum { + kCMSCertificateNone = 0, /* don't include any certificates */ + kCMSCertificateSignerOnly, /* only include signer certificate(s) */ + kCMSCertificateChain, /* signer certificate chain up to but not + * including root certiticate */ + kCMSCertificateChainWithRoot /* signer certificate chain including root */ +}; +typedef uint32_t CMSCertificateChainMode; + +/* + * Optionally specify which certificates, if any, to include in a + * signed CMS message. The default, if this is not called, is + * kCMSCertificateChain, in which case the signer cert plus all CA + * certs needed to verify the signer cert, except for the root + * cert, are included. + * If this is called, it must be called before + * CMSEncoderUpdateContent(). + */ +OSStatus CMSEncoderSetCertificateChainMode( + CMSEncoderRef cmsEncoder, + CMSCertificateChainMode chainMode) + __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); + +/* + * Obtain indication of which signer certs are to be included + * in a signed CMS message. + */ +OSStatus CMSEncoderGetCertificateChainMode( + CMSEncoderRef cmsEncoder, + CMSCertificateChainMode *chainModeOut) + __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); + +/* + * Feed content bytes into the encoder. + * Can be called multiple times. + * No 'setter' routines can be called after this function has been called. + */ +OSStatus CMSEncoderUpdateContent( + CMSEncoderRef cmsEncoder, + const void *content, + size_t contentLen) + __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); + +/* + * Finish encoding the message and obtain the encoded result. + * Caller must CFRelease the result. + */ +OSStatus CMSEncoderCopyEncodedContent( + CMSEncoderRef cmsEncoder, + CFDataRef *encodedContentOut) /* RETURNED */ + __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); + +/* + * High-level, one-shot encoder function. + * + * Inputs (all except for content optional, though at least one + * of {signers, recipients} must be non-NULL) + * ------------------------------------------------------------ + * signers : signer identities. Either a SecIdentityRef, or a + * CFArray of them. + * recipients : recipient certificates. Either a SecCertificateRef, + * or a CFArray of them. + * eContentType : contentType for inner EncapsulatedData. + * detachedContent : when true, do not include the signed data in the message. + * signedAttributes : Specifies which standard signed attributes are to be + * included in the message. + * content : raw content to be signed and/or encrypted. + * + * Output + * ------ + * encodedContent : the result of the encoding. + * + * NOTE: This function is deprecated in Mac OS X 10.7 and later; + * please use CMSEncodeContent() instead. + */ +OSStatus CMSEncode( + CFTypeRef signers, + CFTypeRef recipients, + const CSSM_OID *eContentType, + Boolean detachedContent, + CMSSignedAttributes signedAttributes, + const void *content, + size_t contentLen, + CFDataRef *encodedContentOut) /* RETURNED */ + /* DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; */ + __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); + + +/* + * High-level, one-shot encoder function. + * + * Inputs (all except for content optional, though at least one + * of {signers, recipients} must be non-NULL) + * ------------------------------------------------------------ + * signers : signer identities. Either a SecIdentityRef, or a + * CFArray of them. + * recipients : recipient certificates. Either a SecCertificateRef, + * or a CFArray of them. + * eContentTypeOID : contentType OID for inner EncapsulatedData, e.g.: + * CFSTR("1.2.840.113549.1.7.1") + * detachedContent : when true, do not include the signed data in the message. + * signedAttributes : Specifies which standard signed attributes are to be + * included in the message. + * content : raw content to be signed and/or encrypted. + * + * Output + * ------ + * encodedContent : the result of the encoding. + */ +OSStatus CMSEncodeContent( + CFTypeRef signers, + CFTypeRef recipients, + CFTypeRef eContentTypeOID, + Boolean detachedContent, + CMSSignedAttributes signedAttributes, + const void *content, + size_t contentLen, + CFDataRef *encodedContentOut) /* RETURNED */ + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); + +OSStatus CMSEncoderCopySignerTimestamp( + CMSEncoderRef cmsEncoder, + size_t signerIndex, /* usually 0 */ + CFAbsoluteTime *timestamp) /* RETURNED */ + __OSX_AVAILABLE_STARTING(__MAC_10_8, __IPHONE_NA); + +#ifdef __cplusplus +} +#endif + +#endif /* _CMS_ENCODER_H_ */ + diff --git a/libsecurity_cms/lib/CMSPrivate.h b/libsecurity_cms/lib/CMSPrivate.h new file mode 100644 index 00000000..bf2e7ab4 --- /dev/null +++ b/libsecurity_cms/lib/CMSPrivate.h @@ -0,0 +1,132 @@ +/* + * 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@ + */ + +/* + * CMSPrivate.h - access to low-level CMS objects used by CMSDecoder and CMSEncoder. + */ +#ifndef _CMS_PRIVATE_H_ +#define _CMS_PRIVATE_H_ + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/*** + *** Private CMSEncoder routines + ***/ + +/* + * Obtain the SecCmsMessageRef associated with a CMSEncoderRef. Intended + * to be called after (optionally) setting the encoder's various attributes + * via CMSEncoderAddSigners(), CMSEncoderAddRecipients(), etc. and before + * the first call to CMSEncoderUpdateContent(). The returned SecCmsMessageRef + * will be initialized per the previously specified attributes; the caller + * can manipulate the SecCmsMessageRef prior to proceeding with + * CMSEncoderUpdateContent() calls. + */ +OSStatus CMSEncoderGetCmsMessage( + CMSEncoderRef cmsEncoder, + SecCmsMessageRef *cmsMessage); /* RETURNED */ + +/* + * Optionally specify a SecCmsEncoderRef to use with a CMSEncoderRef. + * If this is called, it must be called before the first call to + * CMSEncoderUpdateContent(). The CMSEncoderRef takes ownership of the + * incoming SecCmsEncoderRef. + */ +OSStatus CMSEncoderSetEncoder( + CMSEncoderRef cmsEncoder, + SecCmsEncoderRef encoder); + +/* + * Obtain the SecCmsEncoderRef associated with a CMSEncoderRef. + * Returns a NULL SecCmsEncoderRef if neither CMSEncoderSetEncoder nor + * CMSEncoderUpdateContent() has been called. + * The CMSEncoderRef retains ownership of the SecCmsEncoderRef. + */ +OSStatus CMSEncoderGetEncoder( + CMSEncoderRef cmsEncoder, + SecCmsEncoderRef *encoder); /* RETURNED */ + +/* + * Set the signing time for a CMSEncoder. + * This is only used if the kCMSAttrSigningTime attribute is included. + */ +OSStatus CMSEncoderSetSigningTime( + CMSEncoderRef cmsEncoder, + CFAbsoluteTime time); + +void +CmsMessageSetTSAContext(CMSEncoderRef cmsEncoder, CFTypeRef tsaContext); + +/*** + *** Private CMSDecoder routines + ***/ + +/* + * Obtain the SecCmsMessageRef associated with a CMSDecoderRef. Intended + * to be called after decoding the message (i.e., after + * CMSDecoderFinalizeMessage() to gain finer access to the contents of the + * SecCmsMessageRef than is otherwise available via the CMSDecoder interface. + * Returns a NULL SecCmsMessageRef if CMSDecoderFinalizeMessage() has not been + * called. + * + * The CMSDecoder retains ownership of the returned SecCmsMessageRef. + */ +OSStatus CMSDecoderGetCmsMessage( + CMSDecoderRef cmsDecoder, + SecCmsMessageRef *cmsMessage); /* RETURNED */ + + +/* + * Optionally specify a SecCmsDecoderRef to use with a CMSDecoderRef. + * If this is called, it must be called before the first call to + * CMSDecoderUpdateMessage(). The CMSDecoderRef takes ownership of the + * incoming SecCmsDecoderRef. + */ +OSStatus CMSDecoderSetDecoder( + CMSDecoderRef cmsDecoder, + SecCmsDecoderRef decoder); + +/* + * Obtain the SecCmsDecoderRef associated with a CMSDecoderRef. + * Returns a NULL SecCmsDecoderRef if neither CMSDecoderSetDecoder() nor + * CMSDecoderUpdateMessage() has been called. + * The CMSDecoderRef retains ownership of the SecCmsDecoderRef. + */ +OSStatus CMSDecoderGetDecoder( + CMSDecoderRef cmsDecoder, + SecCmsDecoderRef *decoder); /* RETURNED */ + +#ifdef __cplusplus +} +#endif + +#endif /* _CMS_PRIVATE_H_ */ + diff --git a/libsecurity_cms/lib/CMSUtils.cpp b/libsecurity_cms/lib/CMSUtils.cpp new file mode 100644 index 00000000..712d7ed6 --- /dev/null +++ b/libsecurity_cms/lib/CMSUtils.cpp @@ -0,0 +1,145 @@ +/* + * 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@ + */ + +/* + * CMSUtils.cpp - common utility routines for libCMS. + * Created 1/12/06 by Doug Mitchell. + */ + +#include "CMSUtils.h" +#include +#include +#include +#include +#include +#include + +/* + * Copy a CSSM_DATA, mallocing the result. + */ +void cmsCopyCmsData( + const CSSM_DATA *src, + CSSM_DATA *dst) +{ + dst->Data = (uint8 *)malloc(src->Length); + memmove(dst->Data, src->Data, src->Length); + dst->Length = src->Length; +} + +/* + * Append a CF type, or the contents of an array, to another array. + * destination array will be created if necessary. + * If srcItemOrArray is not of the type specified in expectedType, + * paramErr will be returned. + */ +OSStatus cmsAppendToArray( + CFTypeRef srcItemOrArray, + CFMutableArrayRef *dstArray, + CFTypeID expectedType) +{ + if(srcItemOrArray == NULL) { + return noErr; + } + if(*dstArray == NULL) { + *dstArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); + } + CFTypeID inType = CFGetTypeID(srcItemOrArray); + if(inType == CFArrayGetTypeID()) { + CFArrayRef srcArray = (CFArrayRef)srcItemOrArray; + CFRange srcRange = {0, CFArrayGetCount(srcArray)}; + CFArrayAppendArray(*dstArray, srcArray, srcRange); + } + else if(inType == expectedType) { + CFArrayAppendValue(*dstArray, srcItemOrArray); + } + else { + return paramErr; + } + return noErr; +} + +/* + * Munge an OSStatus returned from libsecurity_smime, which may well be an ASN.1 private + * error code, to a real OSStatus. + */ +OSStatus cmsRtnToOSStatus( + OSStatus smimeRtn, // from libsecurity_smime + OSStatus defaultRtn) // use this if we can't map smimeRtn +{ + if(smimeRtn == SECFailure) { + /* This is a SECStatus. Try to get detailed error info. */ + smimeRtn = PORT_GetError(); + if(smimeRtn == 0) { + /* S/MIME just gave us generic error; no further info available; punt. */ + dprintf("cmsRtnToOSStatus: SECFailure, no status avilable\n"); + return defaultRtn ? defaultRtn : internalComponentErr; + } + /* else proceed to map smimeRtn to OSStatus */ + } + if(!IS_SEC_ERROR(smimeRtn)) { + /* isn't ASN.1 or S/MIME error; use as is. */ + return smimeRtn; + } + + /* Convert SECErrorCodes to OSStatus */ + switch(smimeRtn) { + case SEC_ERROR_BAD_DER: + case SEC_ERROR_BAD_DATA: + return errSecUnknownFormat; + case SEC_ERROR_NO_MEMORY: + return memFullErr; + case SEC_ERROR_IO: + return ioErr; + case SEC_ERROR_OUTPUT_LEN: + case SEC_ERROR_INPUT_LEN: + case SEC_ERROR_INVALID_ARGS: + case SEC_ERROR_INVALID_ALGORITHM: + case SEC_ERROR_INVALID_AVA: + case SEC_ERROR_INVALID_TIME: + return paramErr; + case SEC_ERROR_PKCS7_BAD_SIGNATURE: + case SEC_ERROR_BAD_SIGNATURE: + return CSSMERR_CSP_VERIFY_FAILED; + case SEC_ERROR_EXPIRED_CERTIFICATE: + case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE: + return CSSMERR_TP_CERT_EXPIRED; + case SEC_ERROR_REVOKED_CERTIFICATE: + return CSSMERR_TP_CERT_REVOKED; + case SEC_ERROR_UNKNOWN_ISSUER: + case SEC_ERROR_UNTRUSTED_ISSUER: + case SEC_ERROR_UNTRUSTED_CERT: + return CSSMERR_TP_NOT_TRUSTED; + case SEC_ERROR_CERT_USAGES_INVALID: + case SEC_ERROR_INADEQUATE_KEY_USAGE: + return CSSMERR_CSP_KEY_USAGE_INCORRECT; + case SEC_INTERNAL_ONLY: + return internalComponentErr; + case SEC_ERROR_NO_USER_INTERACTION: + return errSecInteractionNotAllowed; + case SEC_ERROR_USER_CANCELLED: + return userCanceledErr; + default: + dprintf("cmsRtnToOSStatus: smimeRtn 0x%x\n", smimeRtn); + return defaultRtn ? defaultRtn : internalComponentErr; + } +} diff --git a/libsecurity_cms/lib/CMSUtils.h b/libsecurity_cms/lib/CMSUtils.h new file mode 100644 index 00000000..1d705d92 --- /dev/null +++ b/libsecurity_cms/lib/CMSUtils.h @@ -0,0 +1,84 @@ +/* + * 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@ + */ + +/* + * CMSUtils.h - common utility routines for libCMS. + */ + +#ifndef _CMS_UTILS_H_ +#define _CMS_UTILS_H_ + +#include +#include /* cssmPerror() */ +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Copy a CSSM_DATA, mallocing the result. + */ +void cmsCopyCmsData( + const CSSM_DATA *src, + CSSM_DATA *dst); + +/* + * Append a CF type, or the contents of an array, to another array. + * destination array will be created if necessary. + * If srcItemOrArray is not of the type specified in expectedType, + * paramErr will be returned. + */ +OSStatus cmsAppendToArray( + CFTypeRef srcItemOrArray, + CFMutableArrayRef *dstArray, + CFTypeID expectedType); + +/* + * Munge an OSStatus returned from libsecurity_smime, which may well be an ASN.1 private + * error code, to a real OSStatus. + */ +OSStatus cmsRtnToOSStatus( + OSStatus smimeRtn, // from libsecurity_smime + OSStatus defaultRtn = 0); // use this if we can't map smimeRtn + +#define CFRELEASE(cfr) if(cfr != NULL) { CFRelease(cfr); } + +#define DEBUG 0 +#if DEBUG +#define ASSERT(s) assert(s) +#define CSSM_PERROR(s, r) cssmPerror(s, r) +#define dprintf(args...) printf(args) +#else +#define ASSERT(s) +#define CSSM_PERROR(s, r) +#define dprintf(args...) +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* _CMS_UTILS_H_ */ + diff --git a/libsecurity_cms/lib/security_cms.exp b/libsecurity_cms/lib/security_cms.exp new file mode 100644 index 00000000..f43d1c02 --- /dev/null +++ b/libsecurity_cms/lib/security_cms.exp @@ -0,0 +1,46 @@ +_CMSEncode +_CMSEncodeContent +_CMSEncoderAddSupportingCerts +_CMSEncoderAddRecipients +_CMSEncoderAddSigners +_CMSEncoderCopySupportingCerts +_CMSEncoderCopyRecipients +_CMSEncoderCopySigners +_CMSEncoderCreate +_CMSEncoderCopyEncodedContent +_CMSEncoderGetCmsMessage +_CMSEncoderSetHasDetachedContent +_CMSEncoderGetHasDetachedContent +_CMSEncoderCopyEncapsulatedContentType +_CMSEncoderGetEncoder +_CMSEncoderGetTypeID +_CMSEncoderSetEncapsulatedContentType +_CMSEncoderSetEncapsulatedContentTypeOID +_CMSEncoderSetEncoder +_CMSEncoderAddSignedAttributes +_CMSEncoderSetSigningTime +_CMSEncoderSetCertificateChainMode +_CMSEncoderGetCertificateChainMode +_CMSEncoderUpdateContent +_CMSDecoderCopyAllCerts +_CMSDecoderCopyContent +_CMSDecoderCopyDetachedContent +_CMSDecoderCopySignerStatus +_CMSDecoderCreate +_CMSDecoderGetTypeID +_CMSDecoderFinalizeMessage +_CMSDecoderGetDecoder +_CMSDecoderCopyEncapsulatedContentType +_CMSDecoderIsContentEncrypted +_CMSDecoderGetNumSigners +_CMSDecoderSetDecoder +_CMSDecoderSetDetachedContent +_CMSDecoderUpdateMessage +_CMSDecoderGetCmsMessage +_CMSDecoderSetSearchKeychain +_CMSDecoderCopySignerEmailAddress +_CMSDecoderCopySignerCert +_CMSDecoderCopySignerSigningTime +_CMSDecoderCopySignerTimestamp +_CMSDecoderCopySignerTimestampCertificates +_CMSEncoderCopySignerTimestamp diff --git a/libsecurity_cms/libsecurity_cms.xcodeproj/project.pbxproj b/libsecurity_cms/libsecurity_cms.xcodeproj/project.pbxproj new file mode 100644 index 00000000..3ee93813 --- /dev/null +++ b/libsecurity_cms/libsecurity_cms.xcodeproj/project.pbxproj @@ -0,0 +1,215 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 052C07EA09894ADA00E7641D /* CMSDecoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 052C07E609894ADA00E7641D /* CMSDecoder.h */; settings = {ATTRIBUTES = (); }; }; + 052C07EB09894ADA00E7641D /* CMSEncoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 052C07E709894ADA00E7641D /* CMSEncoder.h */; settings = {ATTRIBUTES = (); }; }; + 052C07EC09894ADA00E7641D /* CMSPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 052C07E809894ADA00E7641D /* CMSPrivate.h */; settings = {ATTRIBUTES = (); }; }; + 052C07ED09894ADA00E7641D /* CMSUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = 052C07E909894ADA00E7641D /* CMSUtils.h */; }; + 052C07F709894AF300E7641D /* CMSDecoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 052C07F409894AF300E7641D /* CMSDecoder.cpp */; }; + 052C07F809894AF300E7641D /* CMSEncoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 052C07F509894AF300E7641D /* CMSEncoder.cpp */; }; + 052C07F909894AF300E7641D /* CMSUtils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 052C07F609894AF300E7641D /* CMSUtils.cpp */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 052C07E609894ADA00E7641D /* CMSDecoder.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = CMSDecoder.h; sourceTree = ""; }; + 052C07E709894ADA00E7641D /* CMSEncoder.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = CMSEncoder.h; sourceTree = ""; }; + 052C07E809894ADA00E7641D /* CMSPrivate.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = CMSPrivate.h; sourceTree = ""; }; + 052C07E909894ADA00E7641D /* CMSUtils.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = CMSUtils.h; sourceTree = ""; }; + 052C07F409894AF300E7641D /* CMSDecoder.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = CMSDecoder.cpp; sourceTree = ""; }; + 052C07F509894AF300E7641D /* CMSEncoder.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = CMSEncoder.cpp; sourceTree = ""; }; + 052C07F609894AF300E7641D /* CMSUtils.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = CMSUtils.cpp; sourceTree = ""; }; + 18446177146E984400B12992 /* base.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = base.xcconfig; sourceTree = ""; }; + 18446178146E984400B12992 /* debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = debug.xcconfig; sourceTree = ""; }; + 18446179146E984400B12992 /* lib.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = lib.xcconfig; sourceTree = ""; }; + 1844617A146E984400B12992 /* release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = release.xcconfig; sourceTree = ""; }; + 4CA1FEBE052A3C8100F22E42 /* libsecurity_cms.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libsecurity_cms.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 4CCB008B05800B0B00981D43 /* security_cms.exp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.exports; path = security_cms.exp; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 4CA1FEBB052A3C8100F22E42 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 18446176146E984400B12992 /* config */ = { + isa = PBXGroup; + children = ( + 18446177146E984400B12992 /* base.xcconfig */, + 18446178146E984400B12992 /* debug.xcconfig */, + 18446179146E984400B12992 /* lib.xcconfig */, + 1844617A146E984400B12992 /* release.xcconfig */, + ); + name = config; + path = ../config; + sourceTree = ""; + }; + 4C308388053237100028A8C6 /* lib */ = { + isa = PBXGroup; + children = ( + 052C07F409894AF300E7641D /* CMSDecoder.cpp */, + 052C07F509894AF300E7641D /* CMSEncoder.cpp */, + 052C07F609894AF300E7641D /* CMSUtils.cpp */, + 052C07E609894ADA00E7641D /* CMSDecoder.h */, + 052C07E709894ADA00E7641D /* CMSEncoder.h */, + 052C07E809894ADA00E7641D /* CMSPrivate.h */, + 052C07E909894ADA00E7641D /* CMSUtils.h */, + 4CCB008B05800B0B00981D43 /* security_cms.exp */, + ); + path = lib; + sourceTree = ""; + }; + 4CA1FEA7052A3C3800F22E42 = { + isa = PBXGroup; + children = ( + 4C308388053237100028A8C6 /* lib */, + 18446176146E984400B12992 /* config */, + 4CA1FEBF052A3C8100F22E42 /* Products */, + ); + sourceTree = ""; + }; + 4CA1FEBF052A3C8100F22E42 /* Products */ = { + isa = PBXGroup; + children = ( + 4CA1FEBE052A3C8100F22E42 /* libsecurity_cms.a */, + ); + name = Products; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 4CA1FEB9052A3C8100F22E42 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 052C07ED09894ADA00E7641D /* CMSUtils.h in Headers */, + 052C07EC09894ADA00E7641D /* CMSPrivate.h in Headers */, + 052C07EA09894ADA00E7641D /* CMSDecoder.h in Headers */, + 052C07EB09894ADA00E7641D /* CMSEncoder.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 4CA1FEBD052A3C8100F22E42 /* libsecurity_cms */ = { + isa = PBXNativeTarget; + buildConfigurationList = C263E67509A2971B000043F1 /* Build configuration list for PBXNativeTarget "libsecurity_cms" */; + buildPhases = ( + 4CA1FEB9052A3C8100F22E42 /* Headers */, + 4CA1FEBA052A3C8100F22E42 /* Sources */, + 4CA1FEBB052A3C8100F22E42 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = libsecurity_cms; + productName = libsecurity_cms; + productReference = 4CA1FEBE052A3C8100F22E42 /* libsecurity_cms.a */; + productType = "com.apple.product-type.library.static"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 4CA1FEAB052A3C3800F22E42 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0420; + }; + buildConfigurationList = C263E67909A2971B000043F1 /* Build configuration list for PBXProject "libsecurity_cms" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 1; + knownRegions = ( + en, + ); + mainGroup = 4CA1FEA7052A3C3800F22E42; + productRefGroup = 4CA1FEBF052A3C8100F22E42 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 4CA1FEBD052A3C8100F22E42 /* libsecurity_cms */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXSourcesBuildPhase section */ + 4CA1FEBA052A3C8100F22E42 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 052C07F709894AF300E7641D /* CMSDecoder.cpp in Sources */, + 052C07F809894AF300E7641D /* CMSEncoder.cpp in Sources */, + 052C07F909894AF300E7641D /* CMSUtils.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + C263E67609A2971B000043F1 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 18446178146E984400B12992 /* debug.xcconfig */; + buildSettings = { + }; + name = Debug; + }; + C263E67809A2971B000043F1 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1844617A146E984400B12992 /* release.xcconfig */; + buildSettings = { + }; + name = Release; + }; + C263E67A09A2971B000043F1 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 18446179146E984400B12992 /* lib.xcconfig */; + buildSettings = { + }; + name = Debug; + }; + C263E67C09A2971B000043F1 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 18446179146E984400B12992 /* lib.xcconfig */; + buildSettings = { + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + C263E67509A2971B000043F1 /* Build configuration list for PBXNativeTarget "libsecurity_cms" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C263E67609A2971B000043F1 /* Debug */, + C263E67809A2971B000043F1 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C263E67909A2971B000043F1 /* Build configuration list for PBXProject "libsecurity_cms" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C263E67A09A2971B000043F1 /* Debug */, + C263E67C09A2971B000043F1 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 4CA1FEAB052A3C3800F22E42 /* Project object */; +} diff --git a/libsecurity_codesigning/APPLE_LICENSE b/libsecurity_codesigning/APPLE_LICENSE new file mode 100644 index 00000000..71fe6fd7 --- /dev/null +++ b/libsecurity_codesigning/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/libsecurity_codesigning/Info-security_codesigning.plist b/libsecurity_codesigning/Info-security_codesigning.plist new file mode 100644 index 00000000..0c67376e --- /dev/null +++ b/libsecurity_codesigning/Info-security_codesigning.plist @@ -0,0 +1,5 @@ + + + + + diff --git a/libsecurity_codesigning/dtrace/codesign-watch.d b/libsecurity_codesigning/dtrace/codesign-watch.d new file mode 100755 index 00000000..64aa5fd4 --- /dev/null +++ b/libsecurity_codesigning/dtrace/codesign-watch.d @@ -0,0 +1,368 @@ +#!/usr/sbin/dtrace -q -s +/* + * Demonstration D script for watching Code Signing activity in the system + * + * As presented, this script will record and report all Code Signing activity + * in one process (argument=pid), or all processes (argument='*'). + * You are encouraged to modify it as you will. (A good start is to comment out + * the print statements you don't like to see.) + */ +typedef uint64_t DTHandle; /* generic API handle (NOT a pointer) */ +typedef uint8_t Hash[20]; /* SHA-1 */ + +typedef struct { /* from implementation */ + uint32_t cputype; + uint32_t cpusubtype; + off_t offset; + uint8_t fileOnly; +} DiskRepContext; + + +/* + * Local variables used for suitable casting (only) + */ +self uint8_t *hash; + + +/* + * Startup (this may take a while) + */ +:::BEGIN +{ + printf("Ready...\n"); +} + + +/* + * Finishing (add statistics tracers here) + */ +:::END +{ +} + + +/* + * Track kernel-related objects. + * Each process has their own, and they're usually created very early. + */ +struct { + DTHandle rep; /* DiskRep */ + DTHandle staticCode; /* static code */ + DTHandle code; /* dynamic code */ +} kernel[pid_t]; + + +/* + * Track DiskRep objects. + * DiskReps are drivers for on-disk formats. Beyond their natural concerns, + * they also carry the path information for StaticCode objects. + */ +typedef struct { + DTHandle me; /* own handle, if valid */ + string path; /* canonical path */ + string type; /* type string */ + DiskRepContext ctx; /* construction context, if any */ + DTHandle sub; /* sub-DiskRep if any */ +} DiskRep; +DiskRep rep[DTHandle]; /* all the DiskReps we've seen */ + +self uint64_t ctx; /* passes construction context, NULL if none */ + +codesign$1:::diskrep-create-* /* preset none */ +{ self->ctx = 0; } + +codesign$1:::diskrep-create-kernel +{ + rep[arg0].me = kernel[pid].rep = arg0; + rep[arg0].path = "(kernel)"; + rep[arg0].type = "kernel"; + printf("%8u %s[%d]%s(%p,KERNEL)\n", + timestamp, execname, pid, probename, arg0); +} + +codesign$1:::diskrep-create-macho +{ + rep[arg0].me = arg0; + rep[arg0].path = copyinstr(arg1); + rep[arg0].type = "macho"; + self->ctx = arg2; + printf("%8u %s[%d]%s(%p,%s)\n", + timestamp, execname, pid, probename, arg0, rep[arg0].path); +} + +codesign$1:::diskrep-create-bundle-path +{ + rep[arg0].me = arg0; + rep[arg0].path = copyinstr(arg1); + rep[arg0].type = "bundle"; + self->ctx = arg2; + rep[arg0].sub = arg3; + printf("%8u %s[%d]%s(%p,%s,%p)\n", + timestamp, execname, pid, probename, + arg0, rep[arg0].path, rep[arg0].sub); +} + +codesign$1:::diskrep-create-bundle-ref +{ + rep[arg0].me = arg0; + rep[arg0].path = "(from ref)"; + rep[arg0].type = "bundle"; + self->ctx = arg2; + rep[arg0].sub = arg3; + printf("%8u %s[%d]%s(%p,%s,%p)\n", + timestamp, execname, pid, probename, + arg0, rep[arg0].path, rep[arg0].sub); +} + +codesign$1:::diskrep-create-file +{ + rep[arg0].me = arg0; + rep[arg0].path = copyinstr(arg1); + rep[arg0].type = "file"; + printf("%8u %s[%d]%s(%p,%s)\n", + timestamp, execname, pid, probename, arg0, rep[arg0].path); +} + +self DiskRepContext *ctxp; + +codesign$1:::diskrep-create-* +/ self->ctx / +{ + self->ctxp = (DiskRepContext *)copyin(self->ctx, sizeof(DiskRepContext)); + rep[arg0].ctx = *self->ctxp; + printf("%8u %s[%d] ...context: arch=(0x%x,0x%x) offset=0x%x file=%d\n", + timestamp, execname, pid, + self->ctxp->cputype, self->ctxp->cpusubtype, + self->ctxp->offset, self->ctxp->fileOnly); +} + +codesign$1:::diskrep-destroy +{ + printf("%8u %s[%d]%s(%p,%s)\n", + timestamp, execname, pid, probename, arg0, rep[arg0].path); + rep[arg0].me = 0; +} + + +/* + * Track Code Signing API objects + */ +typedef struct { + DTHandle me; + DTHandle host; + DTHandle staticCode; /* lazily acquired */ + uint8_t *hash; /* dynamic hash from identify() */ +} Code; +Code code[DTHandle]; + +typedef struct { + DTHandle me; + DTHandle rep; + uint8_t *hash; /* static hash from ...::cdHash() */ +} StaticCode; +StaticCode staticCode[DTHandle]; + + +codesign$1:::static-create +/ arg1 == kernel[pid].rep / +{ + staticCode[arg0].me = kernel[pid].staticCode = arg0; + staticCode[arg0].rep = arg1; + printf("%8u %s[%d]%s(%p=KERNEL[%p])\n", + timestamp, execname, pid, probename, arg0, arg1); +} + +codesign$1:::static-create +/ arg1 != kernel[pid].rep / +{ + staticCode[arg0].me = arg0; + staticCode[arg0].rep = arg1; + printf("%8u %s[%d]%s(%p,%s[%p])\n", + timestamp, execname, pid, probename, arg0, rep[arg1].path, arg1); +} + +codesign$1:::dynamic-create +/ arg1 == 0 / +{ + code[arg0].me = kernel[pid].code = arg0; + printf("%8u %s[%d]%s(%p=KERNEL)\n", + timestamp, execname, pid, probename, arg0); +} + +codesign$1:::dynamic-create +/ arg1 == kernel[pid].code / +{ + code[arg0].me = arg0; + printf("%8u %s[%d]%s(%p,)\n", + timestamp, execname, pid, probename, arg0); +} + +codesign$1:::dynamic-create +/ arg1 != 0 && arg1 != kernel[pid].code / +{ + code[arg0].me = arg0; + code[arg0].host = arg1; + printf("%8u %s[%d]%s(%p,%p)\n", + timestamp, execname, pid, probename, arg0, arg1); +} + +security_debug$1:::sec-destroy +/ code[arg0].me == arg0 / +{ + code[arg0].me = 0; + printf("%8u %s[%d]destroy code(%p)\n", + timestamp, execname, pid, arg0); +} + +security_debug$1:::sec-destroy +/ staticCode[arg0].me == arg0 / +{ + staticCode[arg0].me = 0; + printf("%8u %s[%d]destroy staticCode(%p)\n", + timestamp, execname, pid, arg0); +} + + +/* + * Identification operations + */ +codesign$1:::guest-identify-* +{ + printf("%8u %s[%d]%s(%p,%d,%s[%p])\n", + timestamp, execname, pid, probename, + arg0, arg1, rep[staticCode[arg2].rep].path, arg2); + code[arg0].staticCode = arg2; +} + +codesign$1:::guest-cdhash-* +{ + self->hash = code[arg0].hash = (uint8_t *)copyin(arg1, sizeof(Hash)); + printf("%8u %s[%d]%s(%p,H\"%02x%02x%02x...%02x%02x\")\n", + timestamp, execname, pid, probename, arg0, + self->hash[0], self->hash[1], self->hash[2], self->hash[18], self->hash[19]); +} + +codesign$1:::static-cdhash +{ + self->hash = staticCode[arg0].hash = (uint8_t *)copyin(arg1, sizeof(Hash)); + printf("%8u %s[%d]%s(%p,H\"%02x%02x%02x...%02x%02x\")\n", + timestamp, execname, pid, probename, arg0, + self->hash[0], self->hash[1], self->hash[2], self->hash[18], self->hash[19]); +} + + +/* + * Guest registry/proxy management in securityd + */ +typedef struct { + DTHandle guest; + string path; + uint32_t status; + uint8_t *hash; +} SDGuest; +SDGuest guests[DTHandle, DTHandle]; /* host x guest */ + +securityd*:::host-register +{ + printf("%8u HOST DYNAMIC(%p,%d)\n", + timestamp, arg0, arg1); +} + +securityd*:::host-proxy +{ + printf("%8u HOST PROXY(%p,%d)\n", + timestamp, arg0, arg1); +} + +securityd*:::host-unregister +{ + printf("%8u HOST DESTROYED(%p)\n", + timestamp, arg0); +} + +securityd*:::guest-create +{ + guests[arg0, arg2].guest = arg2; + guests[arg0, arg2].path = copyinstr(arg5); + guests[arg0, arg2].status = arg3; + printf("%8u GUEST CREATE(%p,%s[0x%x],host=0x%x,status=0x%x,flags=%d)\n", + timestamp, + arg0, guests[arg0, arg2].path, arg2, arg1, arg3, arg4); +} + +securityd*:::guest-cdhash +/ arg2 != 0 / +{ + self->hash = guests[arg0, arg1].hash = (uint8_t *)copyin(arg2, sizeof(Hash)); + printf("%8u GUEST HASH(%p,%s[0x%x],H\"%02x%02x%02x...%02x%02x\")\n", + timestamp, + arg0, guests[arg0, arg1].path, arg1, + self->hash[0], self->hash[1], self->hash[2], self->hash[18], self->hash[19]); +} + +securityd*:::guest-cdhash +/ arg2 == 0 / +{ + printf("%8u GUEST HASH(%p,%s[0x%x],NONE)\n", + timestamp, arg0, guests[arg0, arg1].path, arg1); +} + +securityd*:::guest-change +{ + printf("%8u GUEST CHANGE(%p,%s[0x%x],status=0x%x)\n", + timestamp, + arg0, guests[arg0, arg1].path, arg1, arg2); +} + +securityd*:::guest-destroy +{ + printf("%8u GUEST DESTROY(%p,%s[0x%x])\n", + timestamp, + arg0, guests[arg0, arg1].path, arg1); +} + + +/* + * Signing Mach-O allocation tracking + */ +codesign$1:::allocate-arch +{ + printf("%8u %s[%d]%s(%s,%d)\n", + timestamp, execname, pid, probename, copyinstr(arg0), arg1); +} + +codesign$1:::allocate-archn +{ + printf("%8u %s[%d]%s((0x%x,0x%x),%d)\n", + timestamp, execname, pid, probename, arg0, arg1, arg2); +} + +codesign$1:::allocate-write +{ + printf("%8u %s[%d]%s(%s,offset 0x%x,%d of %d)\n", + timestamp, execname, pid, probename, + copyinstr(arg0), arg1, arg2, arg3); +} + +codesign$1:::allocate-validate +{ + printf("%8u %s[%d]%s(%s,%d)\n", + timestamp, execname, pid, probename, copyinstr(arg0), arg1); +} + + +/* + * Evaluation tracking + */ +codesign$1:::eval-dynamic-start +{ + printf("%8u %s[%d]%s(%p,%s)\n", + timestamp, execname, pid, probename, arg0, copyinstr(arg1)); +} + +codesign$1:::eval-dynamic-end +{ + printf("%8u %s[%d]%s(%p)\n", + timestamp, execname, pid, probename, arg0); +} + diff --git a/libsecurity_codesigning/dtrace/reqint.d b/libsecurity_codesigning/dtrace/reqint.d new file mode 100755 index 00000000..16632617 --- /dev/null +++ b/libsecurity_codesigning/dtrace/reqint.d @@ -0,0 +1,133 @@ +#!/usr/sbin/dtrace -q -s + + +string opnames[unsigned]; /* common opcode names */ + + +dtrace:::BEGIN +{ + printf("ready...\n"); + opnames[0] = "never"; + opnames[1] = "always"; + opnames[2] = "identifier..."; + opnames[3] = "anchor apple"; + opnames[4] = "anchor = ..."; + opnames[5] = "!legacy infokey!"; + opnames[6] = "AND"; + opnames[7] = "OR"; + opnames[8] = "cdhash"; + opnames[9] = "NOT"; + opnames[10] = "info[...]"; + opnames[11] = "cert[subject...]"; + opnames[12] = "anchor trusted..."; + opnames[13] = "anchor trusted..."; + opnames[14] = "cert[field...]"; + opnames[15] = "anchor apple generic"; + opnames[16] = "entitlement[...]"; + opnames[17] = "cert[policy...]"; + opnames[18] = "anchor NAMED"; + opnames[19] = "(NAMED)"; +} + + +codesign*:::eval-reqint-start +{ + printf("%8u %s[%d] START(%p,%d)\n", + timestamp, execname, pid, + arg0, arg1); +} + +codesign*:::eval-reqint-end +{ + @eval[arg1] = count(); +} + +codesign*:::eval-reqint-end +/ arg1 == 0 / +{ + printf("%8u %s[%d] SUCCESS\n", + timestamp, execname, pid); +} + +codesign*:::eval-reqint-end +/ arg1 == 4294900246 / +{ + printf("%8u %s[%d] FAIL\n", + timestamp, execname, pid); +} + +codesign*:::eval-reqint-end +/ arg1 != 4294900246 && arg1 != 0 / +{ + printf("%8u %s[%d] FAIL(%d)\n", + timestamp, execname, pid, + arg1); +} + +codesign*:::eval-reqint-unknown* +{ + printf("%8u %s[%d] %s(%d)\n", + timestamp, execname, pid, probename, + arg0); +} + +codesign*:::eval-reqint-fragment-load +/ arg2 != 0 / +{ + printf("%8u %s[%d] frag-load(%s,%s,%p)\n", + timestamp, execname, pid, + copyinstr(arg0), copyinstr(arg1), arg2); + @fragload[copyinstr(arg0), copyinstr(arg1)] = count(); + @fraguse[copyinstr(arg0), copyinstr(arg1)] = count(); +} + +codesign*:::eval-reqint-fragment-load +/ arg2 == 0 / +{ + printf("%8u %s[%d] frag-load(%s,%s,FAILED)\n", + timestamp, execname, pid, + copyinstr(arg0), copyinstr(arg1)); + @fragload[copyinstr(arg0), copyinstr(arg1)] = count(); + @fraguse[copyinstr(arg0), copyinstr(arg1)] = count(); +} + +codesign*:::eval-reqint-fragment-hit +{ + printf("%8u %s[%d] frag-hit(%s,%s)\n", + timestamp, execname, pid, + copyinstr(arg0), copyinstr(arg1)); + @fraguse[copyinstr(arg0), copyinstr(arg1)] = count(); +} + + +/* + * Trace opcodes as they're encountered and evaluated + */ +codesign*:::eval-reqint-op +{ + self->traced = 0; + @opcodes[arg0] = count(); +} + +codesign*:::eval-reqint-op +/ !self->traced / +{ + printf("%8u %s[%d] %s\n", timestamp, execname, pid, + opnames[arg0]); +} + + +/* + * Print out aggregates at the end + */ +dtrace:::END +{ + printf("\nREQUIREMENT EVALUATIONS:\n"); + printa("\t%d (%@d)\n", @eval); + + printf("\nREQUIREMENT OPCODES EVALUATED:\n"); + printa("\t%5d (%@d)\n", @opcodes); + + printf("\nFRAGMENTS LOADED:\n"); + printa("\t%s %s (%@d)\n", @fragload); +} diff --git a/libsecurity_codesigning/dtrace/sp-watch.d b/libsecurity_codesigning/dtrace/sp-watch.d new file mode 100755 index 00000000..194d5724 --- /dev/null +++ b/libsecurity_codesigning/dtrace/sp-watch.d @@ -0,0 +1,52 @@ +#!/usr/sbin/dtrace -qs +# +# +# +self unsigned char *cdhash; + +syspolicy*:::assess-* +{ + self->cdhash = 0; +} + +self string type; +syspolicy*:::assess-outcome-* / arg1 == 1 / { type = "execute"; } +syspolicy*:::assess-outcome-* / arg1 == 2 / { type = "install"; } + +syspolicy*:::assess-outcome-accept +{ + printf("accept %s %s;%s", self->type, copyinstr(arg0), copyinstr(arg1)); + self->cdhash = copyin(arg2, 20); +} + +syspolicy*:::assess-outcome-deny +{ + printf("deny %s %s;%s", self->type, copyinstr(arg0), copyinstr(arg1)); + self->cdhash = copyin(arg2, 20); +} + +syspolicy*:::assess-outcome-default +{ + printf("default %s %s;%s", self->type, copyinstr(arg0), copyinstr(arg1)); + self->cdhash = copyin(arg2, 20); +} + +syspolicy*:::assess-outcome-unsigned +{ + printf("unsigned %s %s;", self->type, copyinstr(arg0)); +} + +syspolicy*:::assess-* +/ self->cdhash / +{ + printf(";%02.2x%02.2x%02.2x%02.2x%02.2x%02.2x%02.2x%02.2x%02.2x%02.2x%02.2x%02.2x%02.2x%02.2x%02.2x%02.2x%02.2x%02.2x%02.2x%02.2x", + self->cdhash[0], self->cdhash[1], self->cdhash[2], self->cdhash[3], self->cdhash[4], + self->cdhash[5], self->cdhash[6], self->cdhash[7], self->cdhash[8], self->cdhash[9], + self->cdhash[10], self->cdhash[11], self->cdhash[12], self->cdhash[13], self->cdhash[14], + self->cdhash[15], self->cdhash[16], self->cdhash[17], self->cdhash[18], self->cdhash[19]); +} + +syspolicy*:::assess-* +{ + printf("\n"); +} diff --git a/libsecurity_codesigning/gke/gkclear b/libsecurity_codesigning/gke/gkclear new file mode 100755 index 00000000..e7fab61f --- /dev/null +++ b/libsecurity_codesigning/gke/gkclear @@ -0,0 +1,84 @@ +#!/usr/bin/python +# +# gkclear - clear system state for Gatekeeper recording sessions +# +# This removes DetachedSignatures, resets SystemPolicy, and removes existing gke files. +# +import sys +import os +import signal +import errno +import subprocess +import shutil + + +# +# Usage and fail +# +def usage(): + print >>sys.stderr, "Usage: %s" % sys.argv[0] + sys.exit(2) + +def fail(whatever): + print >>sys.stderr, "%s: %s" % (sys.argv[0], whatever) + sys.exit(1) + + +# +# Argument processing +# +if len(sys.argv) != 1: + usage() + + +# +# Places and things +# +db = "/var/db/" +detachedsignatures = db + "DetachedSignatures" +gkeauth = db + "gke.auth" +gkesigs = db + "gke.sigs" +policydb = db + "SystemPolicy" +policydb_default = db + ".SystemPolicy-default" + + +# must be root +if os.getuid() != 0: + fail("Must have root privileges") + + +# +# Make sure Gatekeeper is disabled +# +subprocess.check_call(["/usr/sbin/spctl", "--master-disable"]) + + +# +# Clear detached signatures database +# +for file in [detachedsignatures, gkeauth, gkesigs]: + try: + os.remove(file) + except OSError, e: + if e[0] != errno.ENOENT: + raise + + +# +# Reset system policy to default values +# +shutil.copyfile(policydb_default, policydb) + + +# +# Kill any extant syspolicyd to flush state +# +null = open("/dev/null", "w") +subprocess.call(["/usr/bin/killall", "syspolicyd"], stderr=null) + + +# +# Done +# +print "System state has been reset." +sys.exit(0) diff --git a/libsecurity_codesigning/gke/gkgenerate b/libsecurity_codesigning/gke/gkgenerate new file mode 100755 index 00000000..b62383f1 --- /dev/null +++ b/libsecurity_codesigning/gke/gkgenerate @@ -0,0 +1,101 @@ +#!/usr/bin/python +# +# gkgenerate - produce Gatekeeper explicit allow data +# +# gkgenerate [--output name] files... +# will collect GKE data from all files and write two output files (name.auth and name.sigs) +# that are ready to drop into a /var/db for pickup. +# +import sys +import os +import signal +import errno +import subprocess +import argparse +import plistlib +import uuid + + +# +# Parameters and constants +# +authfile = "gke.auth" +sigfile = "gke.dsig" + + +# +# Usage and fail +# +def usage(): + print >>sys.stderr, "Usage: %s sourcedir" % sys.argv[0] + sys.exit(2) + +def fail(whatever): + print >>sys.stderr, "%s: %s" % (sys.argv[0], whatever) + sys.exit(1) + + +# +# Argument processing +# +parser = argparse.ArgumentParser() +parser.add_argument("--output", default="./gke", help="name of output files") +parser.add_argument("--uuid", default=uuid.uuid4(), help="explicitly specify the uuid stamp") +parser.add_argument("--empty", action='store_true', help="allow empty output sets") +parser.add_argument('source', nargs='+', help='files generated by the gkrecord command') +args = parser.parse_args() + +authfile = args.output + ".auth" +sigsfile = args.output + ".sigs" + + +# +# Start by collecting authority evidence from the authority records +# +auth = { } +sigs = { } +for source in args.source: + if source[0] == '+': + data = plistlib.readPlist(source[1:]) + auth.update(data["authority"]) + sigs.update(data["signatures"]) + else: + data = plistlib.readPlist(source) + auth.update(data["authority"]) + +if not auth and not args.empty: + fail("No authority records (nothing to do)") + + +# +# Scrub the authority records to remove incriminating evidence +# +new_auth = { } +for rec in auth.values(): + u = uuid.uuid4() + rec["path"] = "(gke)" + del rec["status"] + new_auth[str(u)] = rec +auth = new_auth + + +# +# The authority file is written as-is, as a plist +# +wrap = dict( + authority=auth, + uuid=str(args.uuid) +) +plistlib.writePlist(wrap, authfile) +print "Wrote %d authority record(s) to %s" % (len(auth), authfile) + + +# +# The signatures are written as tightly packed signature blobs +# +sigblobs = open(sigsfile, "w") +for sig in sigs: + sigdata = sigs[sig] + sigblobs.write(sigdata["signature"].data) +sigblobs.close() +print "Wrote %d signature record(s) to %s" % (len(sigs), sigsfile) diff --git a/libsecurity_codesigning/gke/gkhandmake b/libsecurity_codesigning/gke/gkhandmake new file mode 100755 index 00000000..35f63fde --- /dev/null +++ b/libsecurity_codesigning/gke/gkhandmake @@ -0,0 +1,109 @@ +#!/usr/bin/python +# +# gkhandmake - manually create a recorded snippet +# +# gkhandmake path type source outputfile +# +import sys +import os +import signal +import errno +import subprocess +import plistlib + + +# +# Usage and fail +# +def usage(): + print >>sys.stderr, "Usage: %s program specfile outputfile" % sys.argv[0] + sys.exit(2) + +def fail(whatever): + print >>sys.stderr, "%s: %s" % (sys.argv[0], whatever) + sys.exit(1) + + +# +# Argument processing +# +if len(sys.argv) != 4: + usage() +path=os.path.abspath(sys.argv[1]) +specfile=sys.argv[2] +outputfile = sys.argv[3] +type=1 # always execution + + +# +# If the output file already exists, bail +# +if os.path.exists(outputfile): + fail("already exists: %s" % outputfile) + + +# +# We'll let the detached signature live in case we need to inspect it +# +sigpath = "/tmp/%s.dsig" % os.path.basename(path.strip('/')) + + +# +# Generate an adhoc detached signature with the given resource specification +# + +display = subprocess.check_call(["/usr/bin/codesign", + "--sign", "-", + "--detached", sigpath, + "--resource-rules", specfile, + path +]) + + +# +# Now verify it so we can extract the cdhash +# +display = subprocess.Popen(["/usr/bin/codesign", + "--display", "--verbose=3", + "--detached", sigpath, + path +], stderr=subprocess.PIPE) +(stdout, stderr) = display.communicate() + +cdhash = None +for line in stderr.split('\n'): + if line.startswith("CDHash="): + cdhash = line[7:] + break +if cdhash is None: + fail("no cdhash in generated signature?!") + + +# +# Pack up a single (detached) signature as a snippet +# under the given path +# +with open(sigpath, "r") as sigfile: + sigdata = sigfile.read() +auth = { } +sigs = { } + +auth[path] = dict( + type=type, + path=path, + status=9, + cdhash=cdhash +) + +sigs[path] = dict( + type=type, + path=path, + signature=plistlib.Data(sigdata) +) +gkedict = dict( + authority = auth, + signatures = sigs +) +plistlib.writePlist(gkedict, outputfile) + +sys.exit(0) diff --git a/libsecurity_codesigning/gke/gklist b/libsecurity_codesigning/gke/gklist new file mode 100755 index 00000000..ed00e55f --- /dev/null +++ b/libsecurity_codesigning/gke/gklist @@ -0,0 +1,18 @@ +#!/usr/bin/python +# +# gklist - report Gatekeeper MessageTracer data since last reset +# +# mtdebug --reset +# ... exercise Gatekeeper ... +# gklist +# +import os +import plistlib + + +data = os.popen("mtdebug --plist", "r") +for mt in plistlib.readPlistFromString(data.read()): + if mt["com.apple.message.domain"] == "com.apple.security.assessment.outcome": + outcome = mt["com.apple.message.signature"] + id = mt["com.apple.message.signature2"] + print outcome, "--", id diff --git a/libsecurity_codesigning/gke/gkmerge b/libsecurity_codesigning/gke/gkmerge new file mode 100755 index 00000000..bef6c2a6 --- /dev/null +++ b/libsecurity_codesigning/gke/gkmerge @@ -0,0 +1,50 @@ +#!/usr/bin/python +# +# gkmerge - merge Gatekeeper whitelist snippets +# +# gkmerge [--output name] files... +# Takes GKE data from all files, merges it together, and writes it to a new snippet file 'output'. +# +import sys +import os +import signal +import errno +import subprocess +import argparse +import plistlib +import uuid + + +# +# Usage and fail +# +def fail(whatever): + print >>sys.stderr, "%s: %s" % (sys.argv[0], whatever) + sys.exit(1) + + +# +# Argument processing +# +parser = argparse.ArgumentParser() +parser.add_argument("--output", default="./snippet.gke", help="name of output file") +parser.add_argument('source', nargs='+', help='files generated by the gkrecord command') +args = parser.parse_args() + + +# +# Merge all the plist data from the input files, overriding with later files +# +gkedict = { } +for source in args.source: + data = plistlib.readPlist(source) + gkedict.update(data) + + +# +# Write it back out as a snippet file +# +plistlib.writePlist(gkedict, args.output) +print "Wrote %d authority records + %d signatures to %s" % ( + len(gkedict["authority"]), len(gkedict["signatures"]), args.output +) diff --git a/libsecurity_codesigning/gke/gkrecord b/libsecurity_codesigning/gke/gkrecord new file mode 100755 index 00000000..52616881 --- /dev/null +++ b/libsecurity_codesigning/gke/gkrecord @@ -0,0 +1,198 @@ +#!/usr/bin/python +# +# gkrecord - record Gatekeeper rejection activity +# +# gkrecord filename +# +import sys +import os +import signal +import errno +import subprocess +import tempfile +import plistlib + + +# +# Usage and fail +# +def usage(): + print >>sys.stderr, "Usage: %s outputfile" % sys.argv[0] + sys.exit(2) + +def fail(whatever): + print >>sys.stderr, "%s: %s" % (sys.argv[0], whatever) + sys.exit(1) + + +# +# Argument processing +# +if len(sys.argv) != 2: + usage() +outputfile = sys.argv[1] + + +# +# If the output file already exists, bail +# +if os.path.exists(outputfile): + fail("already exists: %s" % outputfile) + + +# +# Places and things +# +collect = "/tmp/gke/" + + +# must be root +if os.getuid() != 0: + fail("Must have root privileges") + + +# +# Make sure Gatekeeper is disabled +# +subprocess.check_call(["/usr/sbin/spctl", "--master-disable"]) + + +# +# make sure we have a fresh syspolicyd and get its pid +# +subprocess.check_call(["/usr/sbin/spctl", "--assess", "--ignore-cache", "/bin/ls"]) +try: + psax = subprocess.check_output("ps ax|grep syspolicyd|grep -v grep", shell=True).split("\n") + if len(psax) != 2: # [ found_syspolicyd, '' ] + fail("Cannot find syspolicyd") + spd_pid = int(psax[0].split()[0]) +except subprocess.CalledProcessError: + fail("Cannot find syspolicyd") + + +# +# run collector dtrace script until dtrace dies. +# recorder_mode arguments are (path, type, label, cdhash, flags) +# +DSCRIPT = ''' +syspolicy$1:::recorder_mode { printf("RECORD;%d;%d", arg1, arg4); } + +self unsigned char *cdhash; + +syspolicy$1:::recorder_mode +{ + self->cdhash = copyin(arg3, 20); + printf(";%02.2x%02.2x%02.2x%02.2x%02.2x%02.2x%02.2x%02.2x%02.2x%02.2x%02.2x%02.2x%02.2x%02.2x%02.2x%02.2x%02.2x%02.2x%02.2x%02.2x", + self->cdhash[0], self->cdhash[1], self->cdhash[2], self->cdhash[3], self->cdhash[4], + self->cdhash[5], self->cdhash[6], self->cdhash[7], self->cdhash[8], self->cdhash[9], + self->cdhash[10], self->cdhash[11], self->cdhash[12], self->cdhash[13], self->cdhash[14], + self->cdhash[15], self->cdhash[16], self->cdhash[17], self->cdhash[18], self->cdhash[19]); + printf(";%s\\n", copyinstr(arg0)); +} + +syspolicy$1:::recorder_mode_adhoc_path +{ + printf("SIGNATURE;%d;%s;%s\\n", arg1, copyinstr(arg2), copyinstr(arg0)); +} + +syspolicy$1:::assess-outcome-unsigned +{ + printf("UNSIGNED;%d;%s\\n", arg1, copyinstr(arg0)); +} + +syspolicy$1:::assess-outcome-broken +{ + printf("BROKEN;%d;%d;%s\\n", arg1, arg2, copyinstr(arg0)); +} +''' + +def sigint(sig, ctx): + os.kill(spd_pid, signal.SIGINT) +signal.signal(signal.SIGINT, sigint) + +(authfd, authfile) = tempfile.mkstemp() +dtrace = subprocess.Popen(["dtrace", "-qs", "/dev/stdin", str(spd_pid)], stdin=subprocess.PIPE, stdout=authfd, stderr=subprocess.PIPE) +print "Exercise the programs to be whitelisted now. Interrupt this script (^C) when you are done." +(stdout, stderr) = dtrace.communicate(input=DSCRIPT) +signal.signal(signal.SIGINT, signal.SIG_DFL) +if stderr: + fail("dtrace failed: %s" % stderr) +os.lseek(authfd, os.SEEK_SET, 0) # rewind + + +# +# Collect all the data into dicts +# +auth = { } +sigs = { } +unsigned = { } +badsigned = { } +errors = { } + +file = os.fdopen(authfd, "r") +for line in file: + (cmd, s, args) = line.strip().partition(";") + if s != ";": + continue # spurious +# print cmd, "--->", args + if cmd == "RECORD": + (type, status, cdhash, path) = args.split(";", 3) + auth[path] = dict( + path=path, + type=type, + status=status, + cdhash=cdhash + ) + elif cmd == "SIGNATURE": + (type, sigpath, path) = args.split(";", 2) + with open(sigpath, "r") as sigfile: + sigdata = sigfile.read() + sigs[path] = dict( + path=path, + type=type, + signature=plistlib.Data(sigdata) + ) + elif cmd == "UNSIGNED": + (type, path) = args.split(";", 1) + unsigned[path] = dict( + path=path, + type=type + ) + elif cmd == "BROKEN": + (type, exception, path) = args.split(";", 2) + badsigned[path] = dict( + path=path, + type=type, + exception=exception + ) + +# unsigned code that had a good detached signature recorded is okay +for rec in sigs: + if rec in unsigned: + del unsigned[rec] + + +# +# Pack them up as a single output (plist) file +# +gkedict = dict( + authority = auth, + signatures = sigs +) +plistlib.writePlist(gkedict, outputfile) + + +# +# Report on any problems found +# +for rec in unsigned.values(): + print >>sys.stderr, "PROBLEM: unsigned type %d object not whitelisted: %s" % (rec["type"], rec["path"]) +for rec in badsigned.values(): + print >>sys.stderr, "PROBLEM: broken code signature; object not whitelisted: %s" % rec["path"] + + +# +# Done +# +print "Recorded %d authorization(s), %d signature(s) in %s" % (len(auth), len(sigs), outputfile) +sys.exit(0) diff --git a/libsecurity_codesigning/lib/CSCommon.h b/libsecurity_codesigning/lib/CSCommon.h new file mode 100644 index 00000000..883d57bc --- /dev/null +++ b/libsecurity_codesigning/lib/CSCommon.h @@ -0,0 +1,298 @@ +/* + * 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 CSCommon + CSCommon is the common header of all Code Signing API headers. + It defines types, constants, and error codes. +*/ +#ifndef _H_CSCOMMON +#define _H_CSCOMMON + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + + +/* + Code Signing specific OSStatus codes. + [Assigned range 0xFFFE_FAxx]. +*/ +enum { + errSecCSUnimplemented = -67072, /* unimplemented code signing feature */ + errSecCSInvalidObjectRef = -67071, /* invalid API object reference */ + errSecCSInvalidFlags = -67070, /* invalid or inappropriate API flag(s) specified */ + errSecCSObjectRequired = -67069, /* a required pointer argument was NULL */ + errSecCSStaticCodeNotFound = -67068, /* cannot find code object on disk */ + errSecCSUnsupportedGuestAttributes = -67067, /* cannot locate guests using this attribute set */ + errSecCSInvalidAttributeValues = -67066, /* given attribute values are invalid */ + errSecCSNoSuchCode = -67065, /* host has no guest with the requested attributes */ + errSecCSMultipleGuests = -67064, /* ambiguous guest specification (host has multiple guests with these attribute values) */ + errSecCSGuestInvalid = -67063, /* code identity has been invalidated */ + errSecCSUnsigned = -67062, /* code object is not signed at all */ + errSecCSSignatureFailed = -67061, /* invalid signature (code or signature have been modified) */ + errSecCSSignatureNotVerifiable = -67060, /* the code cannot be read by the verifier (file system permissions etc.) */ + errSecCSSignatureUnsupported = -67059, /* unsupported type or version of signature */ + errSecCSBadDictionaryFormat = -67058, /* a required plist file or resource is malformed */ + errSecCSResourcesNotSealed = -67057, /* resources are present but not sealed by signature */ + errSecCSResourcesNotFound = -67056, /* code has no resources but signature indicates they must be present */ + errSecCSResourcesInvalid = -67055, /* the sealed resource directory is invalid */ + errSecCSBadResource = -67054, /* a sealed resource is missing or invalid */ + errSecCSResourceRulesInvalid = -67053, /* invalid resource specification rule(s) */ + errSecCSReqInvalid = -67052, /* invalid or corrupted code requirement(s) */ + errSecCSReqUnsupported = -67051, /* unsupported type or version of code requirement(s) */ + errSecCSReqFailed = -67050, /* code failed to satisfy specified code requirement(s) */ + errSecCSBadObjectFormat = -67049, /* object file format unrecognized, invalid, or unsuitable */ + errSecCSInternalError = -67048, /* internal error in Code Signing subsystem */ + errSecCSHostReject = -67047, /* code rejected its host */ + errSecCSNotAHost = -67046, /* attempt to specify guest of code that is not a host */ + errSecCSSignatureInvalid = -67045, /* invalid or unsupported format for signature */ + errSecCSHostProtocolRelativePath = -67044, /* host protocol violation - absolute guest path required */ + errSecCSHostProtocolContradiction = -67043, /* host protocol violation - contradictory hosting modes */ + errSecCSHostProtocolDedicationError = -67042, /* host protocol violation - operation not allowed with/for a dedicated guest */ + errSecCSHostProtocolNotProxy = -67041, /* host protocol violation - proxy hosting not engaged */ + errSecCSHostProtocolStateError = -67040, /* host protocol violation - invalid guest state change request */ + errSecCSHostProtocolUnrelated = -67039, /* host protocol violation - the given guest is not a guest of the given host */ + /* -67038 obsolete (no longer issued) */ + errSecCSNotSupported = -67037, /* operation inapplicable or not supported for this type of code */ + errSecCSCMSTooLarge = -67036, /* signature too large to embed (size limitation of on-disk representation) */ + errSecCSHostProtocolInvalidHash = -67035, /* host protocol violation - invalid guest hash */ + errSecCSStaticCodeChanged = -67034, /* the code on disk does not match what is running */ + errSecCSDBDenied = -67033, /* permission to use a database denied */ + errSecCSDBAccess = -67032, /* cannot access a database */ + errSecCSSigDBDenied = errSecCSDBDenied, + errSecCSSigDBAccess = errSecCSDBAccess, + errSecCSHostProtocolInvalidAttribute = -67031, /* host returned invalid or inconsistent guest attributes */ + errSecCSInfoPlistFailed = -67030, /* invalid Info.plist (plist or signature have been modified) */ + errSecCSNoMainExecutable = -67029, /* the code has no main executable file */ + errSecCSBadBundleFormat = -67028, /* bundle format unrecognized, invalid, or unsuitable */ + errSecCSNoMatches = -67027, /* no matches for search or update operation */ + errSecCSFileHardQuarantined = -67026, /* File created by an AppSandbox, exec/open not allowed */ + errSecCSOutdated = -67025, /* presented data is out of date */ + errSecCSDbCorrupt = -67024, /* a system database of file is corrupt */ +}; + + +/* + * Code Signing specific CFError "user info" keys. + * In calls that can return CFErrorRef indications, if a CFErrorRef is actually + * returned, its "user info" dictionary may contain some of the following keys + * to more closely describe the circumstances of the failure. + * Do not rely on the presence of any particular key to categorize a problem; + * always use the primary OSStatus return for that. The data contained under + * these keys is always supplemental and optional. + */ +extern const CFStringRef kSecCFErrorArchitecture; /* CFStringRef: name of architecture causing the problem */ +extern const CFStringRef kSecCFErrorPattern; /* CFStringRef: invalid resource selection pattern encountered */ +extern const CFStringRef kSecCFErrorResourceSeal; /* CFTypeRef: invalid component in resource seal (CodeResources) */ +extern const CFStringRef kSecCFErrorResourceAdded; /* CFURLRef: unsealed resource found */ +extern const CFStringRef kSecCFErrorResourceAltered; /* CFURLRef: modified resource found */ +extern const CFStringRef kSecCFErrorResourceMissing; /* CFURLRef: sealed (non-optional) resource missing */ +extern const CFStringRef kSecCFErrorInfoPlist; /* CFTypeRef: Info.plist dictionary or component thereof found invalid */ +extern const CFStringRef kSecCFErrorGuestAttributes; /* CFTypeRef: Guest attribute set of element not accepted */ +extern const CFStringRef kSecCFErrorRequirementSyntax; /* CFStringRef: compilation error for Requirement source */ +extern const CFStringRef kSecCFErrorPath; /* CFURLRef: subcomponent containing the error */ + + +/*! + @typedef SecCodeRef + This is the type of a reference to running code. + + In many (but not all) calls, this can be passed to a SecStaticCodeRef + argument, which performs an implicit SecCodeCopyStaticCode call and + operates on the result. +*/ +typedef struct __SecCode *SecCodeRef; /* running code */ + +/*! + @typedef SecStaticCodeRef + This is the type of a reference to static code on disk. +*/ +typedef struct __SecCode const *SecStaticCodeRef; /* code on disk */ + +/*! + @typedef SecRequirementRef + This is the type of a reference to a code requirement. +*/ +typedef struct __SecRequirement *SecRequirementRef; /* code requirement */ + + +/*! + @typedef SecGuestRef + An abstract handle to identify a particular Guest in the context of its Host. + + Guest handles are assigned by the host at will, with kSecNoGuest (zero) being + reserved as the null value. They can be reused for new children if desired. +*/ +typedef u_int32_t SecGuestRef; + +enum { + kSecNoGuest = 0, /* not a valid SecGuestRef */ +}; + + +/*! + @typedef SecCSFlags + This is the type of flags arguments to Code Signing API calls. + It provides a bit mask of request and option flags. All of the bits in these + masks are reserved to Apple; if you set any bits not defined in these headers, + the behavior is generally undefined. + + This list describes the flags that are shared among several Code Signing API calls. + Flags that only apply to one call are defined and documented with that call. + Global flags are assigned from high order down (31 -> 0); call-specific flags + are assigned from the bottom up (0 -> 31). + + @constant kSecCSDefaultFlags + When passed to a flags argument throughout, indicates that default behavior + is desired. Do not mix with other flags values. + @constant kSecCSConsiderExpiration + When passed to a call that performs code validation, requests that code signatures + made by expired certificates be rejected. By default, expiration of participating + certificates is not automatic grounds for rejection. +*/ +typedef uint32_t SecCSFlags; + +enum { + kSecCSDefaultFlags = 0, /* no particular flags (default behavior) */ + + kSecCSConsiderExpiration = 1 << 31, /* consider expired certificates invalid */ + kSecCSEnforceRevocationChecks = 1 << 30, /* force revocation checks regardless of preference settings */ +}; + + +/*! + @typedef SecCodeSignatureFlags + This is the type of option flags that can be embedded in a code signature + during signing, and that govern the use of the signature thereafter. + Some of these flags can be set through the codesign(1) command's --options + argument; some are set implicitly based on signing circumstances; and all + can be set with the kSecCodeSignerFlags item of a signing information dictionary. + + @constant kSecCodeSignatureHost + Indicates that the code may act as a host that controls and supervises guest + code. If this flag is not set in a code signature, the code is never considered + eligible to be a host, and any attempt to act like one will be ignored or rejected. + @constant kSecCodeSignatureAdhoc + The code has been sealed without a signing identity. No identity may be retrieved + from it, and any code requirement placing restrictions on the signing identity + will fail. This flag is set by the code signing API and cannot be set explicitly. + @constant kSecCodeSignatureForceHard + Implicitly set the "hard" status bit for the code when it starts running. + This bit indicates that the code prefers to be denied access to a resource + if gaining such access would cause its invalidation. Since the hard bit is + sticky, setting this option bit guarantees that the code will always have + it set. + @constant kSecCodeSignatureForceKill + Implicitly set the "kill" status bit for the code when it starts running. + This bit indicates that the code wishes to be terminated with prejudice if + it is ever invalidated. Since the kill bit is sticky, setting this option bit + guarantees that the code will always be dynamically valid, since it will die + immediately if it becomes invalid. + @constant kSecCodeSignatureForceExpiration + Forces the kSecCSConsiderExpiration flag on all validations of the code. + */ +typedef uint32_t SecCodeSignatureFlags; + +enum { + kSecCodeSignatureHost = 0x0001, /* may host guest code */ + kSecCodeSignatureAdhoc = 0x0002, /* must be used without signer */ + kSecCodeSignatureForceHard = 0x0100, /* always set HARD mode on launch */ + kSecCodeSignatureForceKill = 0x0200, /* always set KILL mode on launch */ + kSecCodeSignatureForceExpiration = 0x0400, /* force certificate expiration checks */ +}; + + +/*! + @typedef SecCodeStatus + The code signing system attaches a set of status flags to each running code. + These flags are maintained by the code's host, and can be read by anyone. + A code may change its own flags, a host may change its guests' flags, + and root may change anyone's flags. However, these flags are sticky in that + each can change in only one direction (and never back, for the lifetime of the code). + Not even root can violate this restriction. + + There are other flags in SecCodeStatus that are not publicly documented. + Do not rely on them, and do not ever attempt to explicitly set them. + + @constant kSecCodeStatusValid + Indicates that the code is dynamically valid, i.e. it started correctly + and has not been invalidated since then. The valid bit can only be cleared. + + Warning: This bit is not your one-stop shortcut to determining the validity of code. + It represents the dynamic component of the full validity function; if this + bit is unset, the code is definitely invalid, but the converse is not always true. + In fact, code hosts may represent the outcome of some delayed static validation work in this bit, + and thus it strictly represents a blend of (all of) dynamic and (some of) static validity, + depending on the implementation of the particular host managing the code. You can (only) + rely that (1) dynamic invalidation will clear this bit; and (2) the combination + of static validation and dynamic validity (as performed by the SecCodeCheckValidity* APIs) + will give a correct answer. + + @constant kSecCodeStatusHard + Indicates that the code prefers to be denied access to resources if gaining access + would invalidate it. This bit can only be set. + It is undefined whether code that is marked hard and is already invalid will still + be denied access to a resource that would invalidate it if it were still valid. That is, + the code may or may not get access to such a resource while being invalid, and that choice + may appear random. + + @constant kSecCodeStatusKill + Indicates that the code wants to be killed (terminated) if it ever loses its validity. + This bit can only be set. Code that has the kill flag set will never be dynamically invalid + (and live). Note however that a change in static validity does not necessarily trigger instant + death. +*/ +typedef uint32_t SecCodeStatus; +enum { + kSecCodeStatusValid = 0x0001, + kSecCodeStatusHard = 0x0100, + kSecCodeStatusKill = 0x0200, +}; + + +/*! + @typedef SecRequirementType + An enumeration indicating different types of internal requirements for code. + */ +typedef uint32_t SecRequirementType; + +enum { + kSecHostRequirementType = 1, /* what hosts may run us */ + kSecGuestRequirementType = 2, /* what guests we may run */ + kSecDesignatedRequirementType = 3, /* designated requirement */ + kSecLibraryRequirementType = 4, /* what libraries we may link against */ + kSecPluginRequirementType = 5, /* what plug-ins we may load */ + kSecInvalidRequirementType, /* invalid type of Requirement (must be last) */ + kSecRequirementTypeCount = kSecInvalidRequirementType /* number of valid requirement types */ +}; + + +#ifdef __cplusplus +} +#endif + +#endif //_H_CSCOMMON diff --git a/libsecurity_codesigning/lib/CSCommonPriv.h b/libsecurity_codesigning/lib/CSCommonPriv.h new file mode 100644 index 00000000..f87f4541 --- /dev/null +++ b/libsecurity_codesigning/lib/CSCommonPriv.h @@ -0,0 +1,118 @@ +/* + * 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 CSCommonPriv + SecStaticCodePriv is the private counter-part to CSCommon. Its contents are not + official API, and are subject to change without notice. +*/ +#ifndef _H_CSCOMMONPRIV +#define _H_CSCOMMONPRIV + +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +/*! + @typedef SecCodeDirectoryFlagTable + This constant array can be used to translate between names and values + of CodeDirectory flag bits. The table ends with an entry with NULL name. + The elements are in no particular order. + @field name The official text name of the flag. + @field value The binary value of the flag. + @field signable True if the flag can be specified during signing. False if it is set + internally and can only be read from a signature. + */ +typedef struct { + const char *name; + uint32_t value; + bool signable; +} SecCodeDirectoryFlagTable; + +extern const SecCodeDirectoryFlagTable kSecCodeDirectoryFlagTable[]; + + +/*! + Blob types (magic numbers) for blobs used by Code Signing. + + @constant kSecCodeMagicRequirement Magic number for individual code requirements. + @constant kSecCodeMagicRequirementSet Magic number for a collection of + individual code requirements, indexed by requirement type. This is used + for internal requirement sets. + @constant kSecCodeMagicCodeDirectory Magic number for a CodeDirectory. + @constant kSecCodeMagicEmbeddedSignature Magic number for a SuperBlob + containing all the signing components that are usually embedded within + a main executable. + @constant kSecCodeMagicDetachedSignature Magic number for a SuperBlob that + contains all the data for all architectures of a signature, including any + data that is usually written to separate files. This is the format of + detached signatures if the program is capable of having multiple architectures. + @constant kSecCodeMagicEntitlement Magic number for a standard entitlement blob. + @constant kSecCodeMagicByte The first byte (in NBO) shared by all these magic + numbers. This is not a valid ASCII character; test for this to distinguish + between text and binary data if you expect a code signing-related binary blob. + */ + +enum { + kSecCodeMagicRequirement = 0xfade0c00, /* single requirement */ + kSecCodeMagicRequirementSet = 0xfade0c01, /* requirement set */ + kSecCodeMagicCodeDirectory = 0xfade0c02, /* CodeDirectory */ + kSecCodeMagicEmbeddedSignature = 0xfade0cc0, /* single-architecture embedded signature */ + kSecCodeMagicDetachedSignature = 0xfade0cc1, /* detached multi-architecture signature */ + kSecCodeMagicEntitlement = 0xfade7171, /* entitlement blob */ + + kSecCodeMagicByte = 0xfa /* shared first byte */ +}; + + +/*! + Types of cryptographic digests (hashes) used to hold code signatures + together. + + Each combination of type, length, and other parameters is a separate + hash type; we don't understand "families" here. + + These type codes govern the digest links that connect a CodeDirectory + to its subordinate data structures (code pages, resources, etc.) + They do not directly control other uses of hashes (such as the + hash-of-CodeDirectory identifiers used in requirements). + */ +enum { + kSecCodeSignatureNoHash = 0, /* null value */ + kSecCodeSignatureHashSHA1 = 1, /* SHA-1 */ + kSecCodeSignatureHashSHA256 = 2, /* SHA-256 */ + kSecCodeSignatureHashPrestandardSkein160x256 = 32, /* Skein, 160 bits, 256 bit pool */ + kSecCodeSignatureHashPrestandardSkein256x512 = 33, /* Skein, 256 bits, 512 bit pool */ + + kSecCodeSignatureDefaultDigestAlgorithm = kSecCodeSignatureHashSHA1 +}; + + +#ifdef __cplusplus +} +#endif + +#endif //_H_CSCOMMON diff --git a/libsecurity_codesigning/lib/Code.cpp b/libsecurity_codesigning/lib/Code.cpp new file mode 100644 index 00000000..ab5072ae --- /dev/null +++ b/libsecurity_codesigning/lib/Code.cpp @@ -0,0 +1,284 @@ +/* + * Copyright (c) 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@ + */ + +// +// Code - SecCode API objects +// +#include "Code.h" +#include "StaticCode.h" +#include +#include "cskernel.h" +#include +#include + +namespace Security { +namespace CodeSigning { + + +// +// Construction +// +SecCode::SecCode(SecCode *host) + : mHost(host), mIdentified(false) +{ + CODESIGN_DYNAMIC_CREATE(this, host); +} + + +// +// Clean up a SecCode object +// +SecCode::~SecCode() throw() +try { +} catch (...) { + return; +} + + +// +// CF-level comparison of SecStaticCode objects compares CodeDirectory hashes if signed, +// and falls back on comparing canonical paths if (both are) not. +// +bool SecCode::equal(SecCFObject &secOther) +{ + SecCode *other = static_cast(&secOther); + CFDataRef mine = this->cdHash(); + CFDataRef his = other->cdHash(); + if (mine || his) + return mine && his && CFEqual(mine, his); + else + return this->staticCode()->equal(*other->staticCode()); +} + +CFHashCode SecCode::hash() +{ + if (CFDataRef h = this->cdHash()) + return CFHash(h); + else + return this->staticCode()->hash(); +} + + +// +// Yield the host Code +// +SecCode *SecCode::host() const +{ + return mHost; +} + + +// +// Yield the static code. This is cached. +// The caller does not own the object returned; it lives (at least) as long +// as the SecCode it was derived from. +// +SecStaticCode *SecCode::staticCode() +{ + if (!mIdentified) { + this->identify(); + mIdentified = true; + } + assert(mStaticCode); + return mStaticCode; +} + + +// +// Yield the CodeDirectory hash as presented by our host. +// This usually is the same as the hash of staticCode().codeDirectory(), but might not +// if files are changing on disk while code is running. +// +CFDataRef SecCode::cdHash() +{ + if (!mIdentified) { + this->identify(); + mIdentified = true; + } + return mCDHash; // can be NULL (host has no dynamic identity for guest) +} + + +// +// Retrieve current dynamic status. +// +SecCodeStatus SecCode::status() +{ + if (this->isRoot()) + return kSecCodeStatusValid; // root of trust, presumed valid + else + return this->host()->getGuestStatus(this); +} + +void SecCode::status(SecCodeStatusOperation operation, CFDictionaryRef arguments) +{ + if (this->isRoot()) + MacOSError::throwMe(errSecCSHostProtocolStateError); + else + this->host()->changeGuestStatus(this, operation, arguments); +} + + +// +// By default, we have no guests +// +SecCode *SecCode::locateGuest(CFDictionaryRef) +{ + return NULL; +} + + +// +// By default, we self-identify by asking our host to identify us. +// (This is currently only overridden in the root-of-trust (kernel) implementation.) +// +void SecCode::identify() +{ + mStaticCode.take(host()->identifyGuest(this, &mCDHash.aref())); +} + + +// +// The default implementation cannot map guests to disk +// +SecStaticCode *SecCode::identifyGuest(SecCode *, CFDataRef *) +{ + MacOSError::throwMe(errSecCSNoSuchCode); +} + + +// +// Master validation function. +// +// This is the most important function in all of Code Signing. It performs +// dynamic validation on running code. Despite its simple structure, it does +// everything that's needed to establish whether a Code is currently valid... +// with a little help from StaticCode, format drivers, type drivers, and so on. +// +// This function validates internal requirements in the hosting chain. It does +// not validate external requirements - the caller needs to do that with a separate call. +// +void SecCode::checkValidity(SecCSFlags flags) +{ + if (this->isRoot()) { + // the root-of-trust is valid by definition + CODESIGN_EVAL_DYNAMIC_ROOT(this); + return; + } + DTRACK(CODESIGN_EVAL_DYNAMIC, this, (char*)this->staticCode()->mainExecutablePath().c_str()); + + // + // Do not reorder the operations below without thorough cogitation. There are + // interesting dependencies and significant performance issues. There is also + // client code that relies on errors being noticed in a particular order. + // + // For the most part, failure of (reliable) identity will cause exceptions to be + // thrown, and success is indicated by survival. If you make it to the end, + // you have won the validity race. (Good rat.) + // + + // check my host first, recursively + this->host()->checkValidity(flags); + + SecStaticCode *myDisk = this->staticCode(); + SecStaticCode *hostDisk = this->host()->staticCode(); + + // check my static state + myDisk->validateDirectory(); + + // check my own dynamic state + if (!(this->host()->getGuestStatus(this) & kSecCodeStatusValid)) + MacOSError::throwMe(errSecCSGuestInvalid); + + // check that static and dynamic views are consistent + if (this->cdHash() && !CFEqual(this->cdHash(), myDisk->cdHash())) + MacOSError::throwMe(errSecCSStaticCodeChanged); + + // check host/guest constraints + if (!this->host()->isRoot()) { // not hosted by root of trust + myDisk->validateRequirements(kSecHostRequirementType, hostDisk, errSecCSHostReject); + hostDisk->validateRequirements(kSecGuestRequirementType, myDisk); + } +} + + +// +// By default, we track no validity for guests (we don't have any) +// +uint32_t SecCode::getGuestStatus(SecCode *guest) +{ + MacOSError::throwMe(errSecCSNoSuchCode); +} + +void SecCode::changeGuestStatus(SecCode *guest, SecCodeStatusOperation operation, CFDictionaryRef arguments) +{ + MacOSError::throwMe(errSecCSNoSuchCode); +} + + +// +// Given a bag of attribute values, automagically come up with a SecCode +// without any other information. +// This is meant to be the "just do what makes sense" generic call, for callers +// who don't want to engage in the fascinating dance of manual guest enumeration. +// +// Note that we expect the logic embedded here to change over time (in backward +// compatible fashion, one hopes), and that it's all right to use heuristics here +// as long as it's done sensibly. +// +// Be warned that the present logic is quite a bit ad-hoc, and will likely not +// handle arbitrary combinations of proxy hosting, dynamic hosting, and dedicated +// hosting all that well. +// +SecCode *SecCode::autoLocateGuest(CFDictionaryRef attributes, SecCSFlags flags) +{ + // special case: with no attributes at all, return the root of trust + if (CFDictionaryGetCount(attributes) == 0) + return KernelCode::active()->retain(); + + // main logic: we need a pid, and we'll take a canonical guest id as an option + int pid = 0; + if (!cfscan(attributes, "{%O=%d}", kSecGuestAttributePid, &pid)) + CSError::throwMe(errSecCSUnsupportedGuestAttributes, kSecCFErrorGuestAttributes, attributes); + if (SecCode *process = + KernelCode::active()->locateGuest(CFTemp("{%O=%d}", kSecGuestAttributePid, pid))) { + SecPointer code; + code.take(process); // locateGuest gave us a retained object + if (code->staticCode()->flag(kSecCodeSignatureHost)) { + // might be a code host. Let's find out + CFRef rest = makeCFMutableDictionary(attributes); + CFDictionaryRemoveValue(rest, kSecGuestAttributePid); + if (SecCode *guest = code->locateGuest(rest)) + return guest; + } + if (!CFDictionaryGetValue(attributes, kSecGuestAttributeCanonical)) { + // only "soft" attributes, and no hosting is happening. Return the (non-)host itself + return code.yield(); + } + } + MacOSError::throwMe(errSecCSNoSuchCode); +} + + +} // end namespace CodeSigning +} // end namespace Security diff --git a/libsecurity_codesigning/lib/Code.h b/libsecurity_codesigning/lib/Code.h new file mode 100644 index 00000000..715378c2 --- /dev/null +++ b/libsecurity_codesigning/lib/Code.h @@ -0,0 +1,89 @@ +/* + * 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@ + */ + +// +// Code - SecCode API objects +// +#ifndef _H_CODE +#define _H_CODE + +#include "cs.h" +#include "Requirements.h" +#include + +namespace Security { +namespace CodeSigning { + + +class SecStaticCode; + + +// +// A SecCode object represents running code in the system. It must be subclassed +// to implement a particular notion of code. +// +class SecCode : public SecCFObject { + NOCOPY(SecCode) + friend class KernelCode; // overrides identify() to set mStaticCode/mCDHash +public: + SECCFFUNCTIONS(SecCode, SecCodeRef, errSecCSInvalidObjectRef, gCFObjects().Code) + + SecCode(SecCode *host); + virtual ~SecCode() throw(); + + bool equal(SecCFObject &other); + CFHashCode hash(); + + SecCode *host() const; + bool isRoot() const { return host() == NULL; } + SecStaticCode *staticCode(); // cached. Result lives as long as this SecCode + CFDataRef cdHash(); + + SecCodeStatus status(); // dynamic status + void status(SecCodeStatusOperation operation, CFDictionaryRef arguments); + + // primary virtual drivers. Caller owns the result + virtual void identify(); + virtual SecCode *locateGuest(CFDictionaryRef attributes); + virtual SecStaticCode *identifyGuest(SecCode *guest, CFDataRef *cdhash); + + void checkValidity(SecCSFlags flags); + virtual SecCodeStatus getGuestStatus(SecCode *guest); + virtual void changeGuestStatus(SecCode *guest, SecCodeStatusOperation operation, CFDictionaryRef arguments); + +public: + // perform "autolocation" (root-based heuristic). Caller owns the result + static SecCode *autoLocateGuest(CFDictionaryRef attributes, SecCSFlags flags); + +private: + SecPointer mHost; + bool mIdentified; // called identify(), mStaticCode & mCDHash are valid + SecPointer mStaticCode; // (static) code origin + CFRef mCDHash; // (dynamic) CodeDirectory hash as per host +}; + + +} // end namespace CodeSigning +} // end namespace Security + +#endif // !_H_CODE diff --git a/libsecurity_codesigning/lib/CodeSigner.cpp b/libsecurity_codesigning/lib/CodeSigner.cpp new file mode 100644 index 00000000..e40620b9 --- /dev/null +++ b/libsecurity_codesigning/lib/CodeSigner.cpp @@ -0,0 +1,262 @@ +/* + * 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@ + */ + +// +// CodeSigner - SecCodeSigner API objects +// +#include "CodeSigner.h" +#include "signer.h" +#include "reqparser.h" +#include "renum.h" +#include "csdatabase.h" +#include "drmaker.h" +#include "csutilities.h" +#include +#include +#include +#include + +namespace Security { + +__SEC_CFTYPE(SecIdentity) + +namespace CodeSigning { + +using namespace UnixPlusPlus; + + +// +// A helper for parsing out a CFDictionary signing-data specification +// +class SecCodeSigner::Parser : CFDictionary { +public: + Parser(SecCodeSigner &signer, CFDictionaryRef parameters); + + bool getBool(CFStringRef key) const + { + if (CFBooleanRef flag = get(key)) + return flag == kCFBooleanTrue; + else + return false; + } +}; + + +// +// Construct a SecCodeSigner +// +SecCodeSigner::SecCodeSigner(SecCSFlags flags) + : mOpFlags(flags), mRequirements(NULL), mDigestAlgorithm(kSecCodeSignatureDefaultDigestAlgorithm) +{ +} + + +// +// Clean up a SecCodeSigner +// +SecCodeSigner::~SecCodeSigner() throw() +try { + ::free((Requirements *)mRequirements); +} catch (...) { + return; +} + + +// +// Parse an input parameter dictionary and set ready-to-use parameters +// +void SecCodeSigner::parameters(CFDictionaryRef paramDict) +{ + Parser(*this, paramDict); + if (!valid()) + MacOSError::throwMe(errSecCSInvalidObjectRef); +} + + +// +// Roughly check for validity. +// This isn't thorough; it just sees if if looks like we've set up the object appropriately. +// +bool SecCodeSigner::valid() const +{ + if (mOpFlags & kSecCSRemoveSignature) + return true; + return mSigner; +} + + +// +// Sign code +// +void SecCodeSigner::sign(SecStaticCode *code, SecCSFlags flags) +{ + Signer operation(*this, code); + if ((flags | mOpFlags) & kSecCSRemoveSignature) { + secdebug("signer", "%p will remove signature from %p", this, code); + operation.remove(flags); + } else { + if (!valid()) + MacOSError::throwMe(errSecCSInvalidObjectRef); + secdebug("signer", "%p will sign %p (flags 0x%x)", this, code, flags); + operation.sign(flags); + } + code->resetValidity(); +} + + +// +// ReturnDetachedSignature is called by writers or editors that try to return +// detached signature data (rather than annotate the target). +// +void SecCodeSigner::returnDetachedSignature(BlobCore *blob, Signer &signer) +{ + assert(mDetached); + if (CFGetTypeID(mDetached) == CFURLGetTypeID()) { + // URL to destination file + AutoFileDesc fd(cfString(CFURLRef(mDetached.get())), O_WRONLY | O_CREAT | O_TRUNC); + fd.writeAll(*blob); + } else if (CFGetTypeID(mDetached) == CFDataGetTypeID()) { + CFDataAppendBytes(CFMutableDataRef(mDetached.get()), + (const UInt8 *)blob, blob->length()); + } else if (CFGetTypeID(mDetached) == CFNullGetTypeID()) { + signatureDatabaseWriter().storeCode(blob, signer.path().c_str()); + } else + assert(false); +} + + +// +// Our DiskRep::signingContext methods communicate with the signing subsystem +// in terms those callers can easily understand. +// +string SecCodeSigner::sdkPath(const std::string &path) const +{ + assert(path[0] == '/'); // need absolute path here + if (mSDKRoot) + return cfString(mSDKRoot) + path; + else + return path; +} + +bool SecCodeSigner::isAdhoc() const +{ + return mSigner == SecIdentityRef(kCFNull); +} + + +// +// The actual parsing operation is done in the Parser class. +// +// Note that we need to copy or retain all incoming data. The caller has no requirement +// to keep the parameters dictionary around. +// +SecCodeSigner::Parser::Parser(SecCodeSigner &state, CFDictionaryRef parameters) + : CFDictionary(parameters, errSecCSBadDictionaryFormat) +{ + // the signer may be an identity or null + state.mSigner = SecIdentityRef(get(kSecCodeSignerIdentity)); + if (state.mSigner) + if (CFGetTypeID(state.mSigner) != SecIdentityGetTypeID() && !CFEqual(state.mSigner, kCFNull)) + MacOSError::throwMe(errSecCSInvalidObjectRef); + + // the flags need some augmentation + if (CFNumberRef flags = get(kSecCodeSignerFlags)) { + state.mCdFlagsGiven = true; + state.mCdFlags = cfNumber(flags); + } else + state.mCdFlagsGiven = false; + + // digest algorithms are specified as a numeric code + if (CFNumberRef digestAlgorithm = get(kSecCodeSignerDigestAlgorithm)) + state.mDigestAlgorithm = cfNumber(digestAlgorithm); + + if (CFNumberRef cmsSize = get(CFSTR("cmssize"))) + state.mCMSSize = cfNumber(cmsSize); + else + state.mCMSSize = 9000; // likely big enough + + // signing time can be a CFDateRef or null + if (CFTypeRef time = get(kSecCodeSignerSigningTime)) { + if (CFGetTypeID(time) == CFDateGetTypeID() || time == kCFNull) + state.mSigningTime = CFDateRef(time); + else + MacOSError::throwMe(errSecCSInvalidObjectRef); + } + + if (CFStringRef ident = get(kSecCodeSignerIdentifier)) + state.mIdentifier = cfString(ident); + + if (CFStringRef prefix = get(kSecCodeSignerIdentifierPrefix)) + state.mIdentifierPrefix = cfString(prefix); + + // requirements can be binary or string (to be compiled) + if (CFTypeRef reqs = get(kSecCodeSignerRequirements)) { + if (CFGetTypeID(reqs) == CFDataGetTypeID()) { // binary form + const Requirements *rp = (const Requirements *)CFDataGetBytePtr(CFDataRef(reqs)); + state.mRequirements = rp->clone(); + } else if (CFGetTypeID(reqs) == CFStringGetTypeID()) { // text form + state.mRequirements = parseRequirements(cfString(CFStringRef(reqs))); + } else + MacOSError::throwMe(errSecCSInvalidObjectRef); + } else + state.mRequirements = NULL; + + state.mNoMachO = getBool(CFSTR("no-macho")); + + state.mPageSize = get(kSecCodeSignerPageSize); + + // detached can be (destination) file URL or (mutable) Data to be appended-to + if ((state.mDetached = get(kSecCodeSignerDetached))) { + CFTypeID type = CFGetTypeID(state.mDetached); + if (type != CFURLGetTypeID() && type != CFDataGetTypeID() && type != CFNullGetTypeID()) + MacOSError::throwMe(errSecCSInvalidObjectRef); + } + + state.mDryRun = getBool(kSecCodeSignerDryRun); + + state.mResourceRules = get(kSecCodeSignerResourceRules); + + state.mApplicationData = get(kSecCodeSignerApplicationData); + state.mEntitlementData = get(kSecCodeSignerEntitlements); + + state.mSDKRoot = get(kSecCodeSignerSDKRoot); + + if (CFBooleanRef timestampRequest = get(kSecCodeSignerRequireTimestamp)) { + state.mWantTimeStamp = timestampRequest == kCFBooleanTrue; + } else { // pick default + state.mWantTimeStamp = false; + if (state.mSigner && state.mSigner != SecIdentityRef(kCFNull)) { + CFRef signerCert; + MacOSError::check(SecIdentityCopyCertificate(state.mSigner, &signerCert.aref())); + if (certificateHasField(signerCert, devIdLeafMarkerOID)) + state.mWantTimeStamp = true; + } + } + state.mTimestampAuthentication = get(kSecCodeSignerTimestampAuthentication); + state.mTimestampService = get(kSecCodeSignerTimestampServer); + state.mNoTimeStampCerts = getBool(kSecCodeSignerTimestampOmitCertificates); +} + + +} // end namespace CodeSigning +} // end namespace Security diff --git a/libsecurity_codesigning/lib/CodeSigner.h b/libsecurity_codesigning/lib/CodeSigner.h new file mode 100644 index 00000000..71f9cc3b --- /dev/null +++ b/libsecurity_codesigning/lib/CodeSigner.h @@ -0,0 +1,98 @@ +/* + * 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@ + */ + +// +// CodeSigner - SecCodeSigner API objects +// +#ifndef _H_CODESIGNER +#define _H_CODESIGNER + +#include "cs.h" +#include "StaticCode.h" +#include "cdbuilder.h" +#include +#include + +namespace Security { +namespace CodeSigning { + + +// +// A SecCode object represents running code in the system. It must be subclassed +// to implement a particular notion of code. +// +class SecCodeSigner : public SecCFObject, public DiskRep::SigningContext { + NOCOPY(SecCodeSigner) +public: + class Parser; + class Signer; + +public: + SECCFFUNCTIONS(SecCodeSigner, SecCodeSignerRef, errSecCSInvalidObjectRef, gCFObjects().CodeSigner) + + SecCodeSigner(SecCSFlags flags); + virtual ~SecCodeSigner() throw(); + + void parameters(CFDictionaryRef args); // parse and set parameters + bool valid() const; + + void sign(SecStaticCode *code, SecCSFlags flags); + void remove(SecStaticCode *code, SecCSFlags flags); + + void returnDetachedSignature(BlobCore *blob, Signer &signer); + +protected: + std::string sdkPath(const std::string &path) const; + bool isAdhoc() const; + +private: + // parsed parameter set + SecCSFlags mOpFlags; // operation flags + CFRef mSigner; // signing identity + CFRef mDetached; // detached-signing information (NULL => attached) + CFRef mResourceRules; // explicit resource collection rules (override) + CFRef mSigningTime; // signing time desired (kCFNull for none) + CFRef mApplicationData; // contents of application slot + CFRef mEntitlementData; // entitlement configuration data + CFRef mSDKRoot; // substitute filesystem root for sub-component lookup + const Requirements *mRequirements; // internal code requirements + size_t mCMSSize; // size estimate for CMS blob + uint32_t mCdFlags; // CodeDirectory flags + bool mCdFlagsGiven; // CodeDirectory flags were specified + CodeDirectory::HashAlgorithm mDigestAlgorithm; // interior digest (hash) algorithm + std::string mIdentifier; // unique identifier override + std::string mIdentifierPrefix; // prefix for un-dotted default identifiers + bool mNoMachO; // override to perform non-Mach-O signing + bool mDryRun; // dry run (do not change target) + CFRef mPageSize; // main executable page size + CFRef mTimestampAuthentication; // identity for client-side authentication to the Timestamp server + CFRef mTimestampService; // URL for Timestamp server + bool mWantTimeStamp; // use a Timestamp server + bool mNoTimeStampCerts; // don't request certificates with timestamping request +}; + + +} // end namespace CodeSigning +} // end namespace Security + +#endif // !_H_CODESIGNER diff --git a/libsecurity_codesigning/lib/CodeSigning.h b/libsecurity_codesigning/lib/CodeSigning.h new file mode 100644 index 00000000..a33e9e73 --- /dev/null +++ b/libsecurity_codesigning/lib/CodeSigning.h @@ -0,0 +1,37 @@ +/* + * 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 _H_CODESIGNING +#define _H_CODESIGNING + + +/*! + @header CodeSigning + This header file includes all the headers that are needed to use + the client interface to Code Signing. + It does not include headers for the other Code Signing related interfaces. + */ +#include +#include +#include + +#endif //_H_CODESIGNING diff --git a/libsecurity_codesigning/lib/RequirementKeywords.h b/libsecurity_codesigning/lib/RequirementKeywords.h new file mode 100644 index 00000000..bd0438e3 --- /dev/null +++ b/libsecurity_codesigning/lib/RequirementKeywords.h @@ -0,0 +1,24 @@ + "guest", + "host", + "designated", + "library", + "plugin", + "or", + "and", + "always", + "true", + "never", + "false", + "identifier", + "cdhash", + "anchor", + "apple", + "generic", + "certificate", + "cert", + "trusted", + "info", + "entitlement", + "exists", + "leaf", + "root", diff --git a/libsecurity_codesigning/lib/RequirementLexer.cpp b/libsecurity_codesigning/lib/RequirementLexer.cpp new file mode 100644 index 00000000..ac8b2bdb --- /dev/null +++ b/libsecurity_codesigning/lib/RequirementLexer.cpp @@ -0,0 +1,1268 @@ +/* $ANTLR 2.7.7 (20120228): "requirements.grammar" -> "RequirementLexer.cpp"$ */ +#include "RequirementLexer.hpp" +#include +#include +#include +#include +#include +#include +#include + + +#include "requirement.h" +#include "reqmaker.h" +#include "csutilities.h" +#include +#include +#include // OID coding +using namespace CodeSigning; +typedef Requirement::Maker Maker; + +ANTLR_BEGIN_NAMESPACE(Security_CodeSigning) +RequirementLexer::RequirementLexer(std::istream& in) + : antlr::CharScanner(new antlr::CharBuffer(in),true) +{ + initLiterals(); +} + +RequirementLexer::RequirementLexer(antlr::InputBuffer& ib) + : antlr::CharScanner(ib,true) +{ + initLiterals(); +} + +RequirementLexer::RequirementLexer(const antlr::LexerSharedInputState& state) + : antlr::CharScanner(state,true) +{ + initLiterals(); +} + +void RequirementLexer::initLiterals() +{ + literals["certificate"] = 25; + literals["always"] = 16; + literals["host"] = 6; + literals["guest"] = 5; + literals["cdhash"] = 21; + literals["entitlement"] = 29; + literals["library"] = 8; + literals["never"] = 18; + literals["cert"] = 26; + literals["plugin"] = 9; + literals["or"] = 11; + literals["leaf"] = 42; + literals["info"] = 28; + literals["designated"] = 7; + literals["apple"] = 23; + literals["trusted"] = 27; + literals["true"] = 17; + literals["and"] = 12; + literals["root"] = 43; + literals["anchor"] = 22; + literals["false"] = 19; + literals["generic"] = 24; + literals["identifier"] = 20; + literals["exists"] = 30; +} + +antlr::RefToken RequirementLexer::nextToken() +{ + antlr::RefToken theRetToken; + for (;;) { + antlr::RefToken theRetToken; + int _ttype = antlr::Token::INVALID_TYPE; + resetText(); + try { // for lexical and char stream error handling + switch ( LA(1)) { + case 0x22 /* '\"' */ : + { + mSTRING(true); + theRetToken=_returnToken; + break; + } + case 0x3b /* ';' */ : + { + mSEMI(true); + theRetToken=_returnToken; + break; + } + case 0x28 /* '(' */ : + { + mLPAREN(true); + theRetToken=_returnToken; + break; + } + case 0x29 /* ')' */ : + { + mRPAREN(true); + theRetToken=_returnToken; + break; + } + case 0x5b /* '[' */ : + { + mLBRACK(true); + theRetToken=_returnToken; + break; + } + case 0x5d /* ']' */ : + { + mRBRACK(true); + theRetToken=_returnToken; + break; + } + case 0x2c /* ',' */ : + { + mCOMMA(true); + theRetToken=_returnToken; + break; + } + case 0x7e /* '~' */ : + { + mSUBS(true); + theRetToken=_returnToken; + break; + } + case 0x2d /* '-' */ : + { + mNEG(true); + theRetToken=_returnToken; + break; + } + case 0x21 /* '!' */ : + { + mNOT(true); + theRetToken=_returnToken; + break; + } + case 0x2a /* '*' */ : + { + mSTAR(true); + theRetToken=_returnToken; + break; + } + case 0x9 /* '\t' */ : + case 0xa /* '\n' */ : + case 0x20 /* ' ' */ : + { + mWS(true); + theRetToken=_returnToken; + break; + } + case 0x23 /* '#' */ : + { + mSHELLCOMMENT(true); + theRetToken=_returnToken; + break; + } + default: + if ((LA(1) == 0x2f /* '/' */ ) && (_tokenSet_0.member(LA(2)))) { + mPATHNAME(true); + theRetToken=_returnToken; + } + else if ((LA(1) == 0x48 /* 'H' */ ) && (LA(2) == 0x22 /* '\"' */ )) { + mHASHCONSTANT(true); + theRetToken=_returnToken; + } + else if ((LA(1) == 0x30 /* '0' */ ) && (LA(2) == 0x78 /* 'x' */ )) { + mHEXCONSTANT(true); + theRetToken=_returnToken; + } + else if ((LA(1) == 0x3d /* '=' */ ) && (LA(2) == 0x3e /* '>' */ )) { + mARROW(true); + theRetToken=_returnToken; + } + else if ((LA(1) == 0x3c /* '<' */ ) && (LA(2) == 0x3d /* '=' */ )) { + mLE(true); + theRetToken=_returnToken; + } + else if ((LA(1) == 0x3e /* '>' */ ) && (LA(2) == 0x3d /* '=' */ )) { + mGE(true); + theRetToken=_returnToken; + } + else if ((LA(1) == 0x3d /* '=' */ ) && (LA(2) == 0x3d /* '=' */ )) { + mEQQL(true); + theRetToken=_returnToken; + } + else if ((LA(1) == 0x2f /* '/' */ ) && (LA(2) == 0x2a /* '*' */ )) { + mC_COMMENT(true); + theRetToken=_returnToken; + } + else if ((LA(1) == 0x2f /* '/' */ ) && (LA(2) == 0x2f /* '/' */ )) { + mCPP_COMMENT(true); + theRetToken=_returnToken; + } + else if ((_tokenSet_0.member(LA(1))) && (true)) { + mDOTKEY(true); + theRetToken=_returnToken; + } + else if (((LA(1) >= 0x30 /* '0' */ && LA(1) <= 0x39 /* '9' */ )) && (true)) { + mINTEGER(true); + theRetToken=_returnToken; + } + else if ((LA(1) == 0x3c /* '<' */ ) && (true)) { + mLESS(true); + theRetToken=_returnToken; + } + else if ((LA(1) == 0x3e /* '>' */ ) && (true)) { + mGT(true); + theRetToken=_returnToken; + } + else if ((LA(1) == 0x3d /* '=' */ ) && (true)) { + mEQL(true); + theRetToken=_returnToken; + } + else { + if (LA(1)==EOF_CHAR) + { + uponEOF(); + _returnToken = makeToken(antlr::Token::EOF_TYPE); + } + else {throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn());} + } + } + if ( !_returnToken ) + goto tryAgain; // found SKIP token + + _ttype = _returnToken->getType(); + _returnToken->setType(_ttype); + return _returnToken; + } + catch (antlr::RecognitionException& e) { + throw antlr::TokenStreamRecognitionException(e); + } + catch (antlr::CharStreamIOException& csie) { + throw antlr::TokenStreamIOException(csie.io); + } + catch (antlr::CharStreamException& cse) { + throw antlr::TokenStreamException(cse.getMessage()); + } +tryAgain:; + } +} + +void RequirementLexer::mIDENT(bool _createToken) { + int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); + _ttype = IDENT; + std::string::size_type _saveIndex; + + { + switch ( LA(1)) { + case 0x41 /* 'A' */ : + case 0x42 /* 'B' */ : + case 0x43 /* 'C' */ : + case 0x44 /* 'D' */ : + case 0x45 /* 'E' */ : + case 0x46 /* 'F' */ : + case 0x47 /* 'G' */ : + case 0x48 /* 'H' */ : + case 0x49 /* 'I' */ : + case 0x4a /* 'J' */ : + case 0x4b /* 'K' */ : + case 0x4c /* 'L' */ : + case 0x4d /* 'M' */ : + case 0x4e /* 'N' */ : + case 0x4f /* 'O' */ : + case 0x50 /* 'P' */ : + case 0x51 /* 'Q' */ : + case 0x52 /* 'R' */ : + case 0x53 /* 'S' */ : + case 0x54 /* 'T' */ : + case 0x55 /* 'U' */ : + case 0x56 /* 'V' */ : + case 0x57 /* 'W' */ : + case 0x58 /* 'X' */ : + case 0x59 /* 'Y' */ : + case 0x5a /* 'Z' */ : + { + matchRange('A','Z'); + break; + } + case 0x61 /* 'a' */ : + case 0x62 /* 'b' */ : + case 0x63 /* 'c' */ : + case 0x64 /* 'd' */ : + case 0x65 /* 'e' */ : + case 0x66 /* 'f' */ : + case 0x67 /* 'g' */ : + case 0x68 /* 'h' */ : + case 0x69 /* 'i' */ : + case 0x6a /* 'j' */ : + case 0x6b /* 'k' */ : + case 0x6c /* 'l' */ : + case 0x6d /* 'm' */ : + case 0x6e /* 'n' */ : + case 0x6f /* 'o' */ : + case 0x70 /* 'p' */ : + case 0x71 /* 'q' */ : + case 0x72 /* 'r' */ : + case 0x73 /* 's' */ : + case 0x74 /* 't' */ : + case 0x75 /* 'u' */ : + case 0x76 /* 'v' */ : + case 0x77 /* 'w' */ : + case 0x78 /* 'x' */ : + case 0x79 /* 'y' */ : + case 0x7a /* 'z' */ : + { + matchRange('a','z'); + break; + } + default: + { + throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn()); + } + } + } + { // ( ... )* + for (;;) { + switch ( LA(1)) { + case 0x41 /* 'A' */ : + case 0x42 /* 'B' */ : + case 0x43 /* 'C' */ : + case 0x44 /* 'D' */ : + case 0x45 /* 'E' */ : + case 0x46 /* 'F' */ : + case 0x47 /* 'G' */ : + case 0x48 /* 'H' */ : + case 0x49 /* 'I' */ : + case 0x4a /* 'J' */ : + case 0x4b /* 'K' */ : + case 0x4c /* 'L' */ : + case 0x4d /* 'M' */ : + case 0x4e /* 'N' */ : + case 0x4f /* 'O' */ : + case 0x50 /* 'P' */ : + case 0x51 /* 'Q' */ : + case 0x52 /* 'R' */ : + case 0x53 /* 'S' */ : + case 0x54 /* 'T' */ : + case 0x55 /* 'U' */ : + case 0x56 /* 'V' */ : + case 0x57 /* 'W' */ : + case 0x58 /* 'X' */ : + case 0x59 /* 'Y' */ : + case 0x5a /* 'Z' */ : + { + matchRange('A','Z'); + break; + } + case 0x61 /* 'a' */ : + case 0x62 /* 'b' */ : + case 0x63 /* 'c' */ : + case 0x64 /* 'd' */ : + case 0x65 /* 'e' */ : + case 0x66 /* 'f' */ : + case 0x67 /* 'g' */ : + case 0x68 /* 'h' */ : + case 0x69 /* 'i' */ : + case 0x6a /* 'j' */ : + case 0x6b /* 'k' */ : + case 0x6c /* 'l' */ : + case 0x6d /* 'm' */ : + case 0x6e /* 'n' */ : + case 0x6f /* 'o' */ : + case 0x70 /* 'p' */ : + case 0x71 /* 'q' */ : + case 0x72 /* 'r' */ : + case 0x73 /* 's' */ : + case 0x74 /* 't' */ : + case 0x75 /* 'u' */ : + case 0x76 /* 'v' */ : + case 0x77 /* 'w' */ : + case 0x78 /* 'x' */ : + case 0x79 /* 'y' */ : + case 0x7a /* 'z' */ : + { + matchRange('a','z'); + break; + } + case 0x30 /* '0' */ : + case 0x31 /* '1' */ : + case 0x32 /* '2' */ : + case 0x33 /* '3' */ : + case 0x34 /* '4' */ : + case 0x35 /* '5' */ : + case 0x36 /* '6' */ : + case 0x37 /* '7' */ : + case 0x38 /* '8' */ : + case 0x39 /* '9' */ : + { + matchRange('0','9'); + break; + } + default: + { + goto _loop46; + } + } + } + _loop46:; + } // ( ... )* + _ttype = testLiteralsTable(text.substr(_begin, text.length()-_begin),_ttype); + if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { + _token = makeToken(_ttype); + _token->setText(text.substr(_begin, text.length()-_begin)); + } + _returnToken = _token; + _saveIndex=0; +} + +void RequirementLexer::mDOTKEY(bool _createToken) { + int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); + _ttype = DOTKEY; + std::string::size_type _saveIndex; + + mIDENT(false); + { // ( ... )* + for (;;) { + if ((LA(1) == 0x2e /* '.' */ )) { + match("."); + { + switch ( LA(1)) { + case 0x41 /* 'A' */ : + case 0x42 /* 'B' */ : + case 0x43 /* 'C' */ : + case 0x44 /* 'D' */ : + case 0x45 /* 'E' */ : + case 0x46 /* 'F' */ : + case 0x47 /* 'G' */ : + case 0x48 /* 'H' */ : + case 0x49 /* 'I' */ : + case 0x4a /* 'J' */ : + case 0x4b /* 'K' */ : + case 0x4c /* 'L' */ : + case 0x4d /* 'M' */ : + case 0x4e /* 'N' */ : + case 0x4f /* 'O' */ : + case 0x50 /* 'P' */ : + case 0x51 /* 'Q' */ : + case 0x52 /* 'R' */ : + case 0x53 /* 'S' */ : + case 0x54 /* 'T' */ : + case 0x55 /* 'U' */ : + case 0x56 /* 'V' */ : + case 0x57 /* 'W' */ : + case 0x58 /* 'X' */ : + case 0x59 /* 'Y' */ : + case 0x5a /* 'Z' */ : + case 0x61 /* 'a' */ : + case 0x62 /* 'b' */ : + case 0x63 /* 'c' */ : + case 0x64 /* 'd' */ : + case 0x65 /* 'e' */ : + case 0x66 /* 'f' */ : + case 0x67 /* 'g' */ : + case 0x68 /* 'h' */ : + case 0x69 /* 'i' */ : + case 0x6a /* 'j' */ : + case 0x6b /* 'k' */ : + case 0x6c /* 'l' */ : + case 0x6d /* 'm' */ : + case 0x6e /* 'n' */ : + case 0x6f /* 'o' */ : + case 0x70 /* 'p' */ : + case 0x71 /* 'q' */ : + case 0x72 /* 'r' */ : + case 0x73 /* 's' */ : + case 0x74 /* 't' */ : + case 0x75 /* 'u' */ : + case 0x76 /* 'v' */ : + case 0x77 /* 'w' */ : + case 0x78 /* 'x' */ : + case 0x79 /* 'y' */ : + case 0x7a /* 'z' */ : + { + mIDENT(false); + break; + } + case 0x30 /* '0' */ : + case 0x31 /* '1' */ : + case 0x32 /* '2' */ : + case 0x33 /* '3' */ : + case 0x34 /* '4' */ : + case 0x35 /* '5' */ : + case 0x36 /* '6' */ : + case 0x37 /* '7' */ : + case 0x38 /* '8' */ : + case 0x39 /* '9' */ : + { + mINTEGER(false); + break; + } + default: + { + throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn()); + } + } + } + } + else { + goto _loop50; + } + + } + _loop50:; + } // ( ... )* + _ttype = testLiteralsTable(_ttype); + if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { + _token = makeToken(_ttype); + _token->setText(text.substr(_begin, text.length()-_begin)); + } + _returnToken = _token; + _saveIndex=0; +} + +void RequirementLexer::mINTEGER(bool _createToken) { + int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); + _ttype = INTEGER; + std::string::size_type _saveIndex; + + { // ( ... )+ + int _cnt68=0; + for (;;) { + if (((LA(1) >= 0x30 /* '0' */ && LA(1) <= 0x39 /* '9' */ ))) { + matchRange('0','9'); + } + else { + if ( _cnt68>=1 ) { goto _loop68; } else {throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn());} + } + + _cnt68++; + } + _loop68:; + } // ( ... )+ + if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { + _token = makeToken(_ttype); + _token->setText(text.substr(_begin, text.length()-_begin)); + } + _returnToken = _token; + _saveIndex=0; +} + +void RequirementLexer::mPATHNAME(bool _createToken) { + int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); + _ttype = PATHNAME; + std::string::size_type _saveIndex; + + match("/"); + mIDENT(false); + { // ( ... )+ + int _cnt53=0; + for (;;) { + if ((LA(1) == 0x2f /* '/' */ )) { + match("/"); + mIDENT(false); + } + else { + if ( _cnt53>=1 ) { goto _loop53; } else {throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn());} + } + + _cnt53++; + } + _loop53:; + } // ( ... )+ + if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { + _token = makeToken(_ttype); + _token->setText(text.substr(_begin, text.length()-_begin)); + } + _returnToken = _token; + _saveIndex=0; +} + +void RequirementLexer::mHASHCONSTANT(bool _createToken) { + int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); + _ttype = HASHCONSTANT; + std::string::size_type _saveIndex; + + _saveIndex = text.length(); + match('H' /* charlit */ ); + text.erase(_saveIndex); + _saveIndex = text.length(); + match('\"' /* charlit */ ); + text.erase(_saveIndex); + { // ( ... )+ + int _cnt56=0; + for (;;) { + if ((_tokenSet_1.member(LA(1)))) { + mHEX(false); + } + else { + if ( _cnt56>=1 ) { goto _loop56; } else {throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn());} + } + + _cnt56++; + } + _loop56:; + } // ( ... )+ + _saveIndex = text.length(); + match('\"' /* charlit */ ); + text.erase(_saveIndex); + if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { + _token = makeToken(_ttype); + _token->setText(text.substr(_begin, text.length()-_begin)); + } + _returnToken = _token; + _saveIndex=0; +} + +void RequirementLexer::mHEX(bool _createToken) { + int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); + _ttype = HEX; + std::string::size_type _saveIndex; + + switch ( LA(1)) { + case 0x30 /* '0' */ : + case 0x31 /* '1' */ : + case 0x32 /* '2' */ : + case 0x33 /* '3' */ : + case 0x34 /* '4' */ : + case 0x35 /* '5' */ : + case 0x36 /* '6' */ : + case 0x37 /* '7' */ : + case 0x38 /* '8' */ : + case 0x39 /* '9' */ : + { + matchRange('0','9'); + break; + } + case 0x61 /* 'a' */ : + case 0x62 /* 'b' */ : + case 0x63 /* 'c' */ : + case 0x64 /* 'd' */ : + case 0x65 /* 'e' */ : + case 0x66 /* 'f' */ : + { + matchRange('a','f'); + break; + } + case 0x41 /* 'A' */ : + case 0x42 /* 'B' */ : + case 0x43 /* 'C' */ : + case 0x44 /* 'D' */ : + case 0x45 /* 'E' */ : + case 0x46 /* 'F' */ : + { + matchRange('A','F'); + break; + } + default: + { + throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn()); + } + } + if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { + _token = makeToken(_ttype); + _token->setText(text.substr(_begin, text.length()-_begin)); + } + _returnToken = _token; + _saveIndex=0; +} + +void RequirementLexer::mHEXCONSTANT(bool _createToken) { + int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); + _ttype = HEXCONSTANT; + std::string::size_type _saveIndex; + + _saveIndex = text.length(); + match('0' /* charlit */ ); + text.erase(_saveIndex); + _saveIndex = text.length(); + match('x' /* charlit */ ); + text.erase(_saveIndex); + { // ( ... )+ + int _cnt59=0; + for (;;) { + if ((_tokenSet_1.member(LA(1)))) { + mHEX(false); + } + else { + if ( _cnt59>=1 ) { goto _loop59; } else {throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn());} + } + + _cnt59++; + } + _loop59:; + } // ( ... )+ + if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { + _token = makeToken(_ttype); + _token->setText(text.substr(_begin, text.length()-_begin)); + } + _returnToken = _token; + _saveIndex=0; +} + +void RequirementLexer::mSTRING(bool _createToken) { + int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); + _ttype = STRING; + std::string::size_type _saveIndex; + + _saveIndex = text.length(); + match('\"' /* charlit */ ); + text.erase(_saveIndex); + { // ( ... )* + for (;;) { + switch ( LA(1)) { + case 0x5c /* '\\' */ : + { + { + _saveIndex = text.length(); + match('\\' /* charlit */ ); + text.erase(_saveIndex); + match('\"' /* charlit */ ); + } + break; + } + case 0x0 /* '\0' */ : + case 0x1 /* '\1' */ : + case 0x2 /* '\2' */ : + case 0x3 /* '\3' */ : + case 0x4 /* '\4' */ : + case 0x5 /* '\5' */ : + case 0x6 /* '\6' */ : + case 0x7 /* '\7' */ : + case 0x8 /* '\10' */ : + case 0x9 /* '\t' */ : + case 0xa /* '\n' */ : + case 0xb /* '\13' */ : + case 0xc /* '\14' */ : + case 0xd /* '\r' */ : + case 0xe /* '\16' */ : + case 0xf /* '\17' */ : + case 0x10 /* '\20' */ : + case 0x11 /* '\21' */ : + case 0x12 /* '\22' */ : + case 0x13 /* '\23' */ : + case 0x14 /* '\24' */ : + case 0x15 /* '\25' */ : + case 0x16 /* '\26' */ : + case 0x17 /* '\27' */ : + case 0x18 /* '\30' */ : + case 0x19 /* '\31' */ : + case 0x1a /* '\32' */ : + case 0x1b /* '\33' */ : + case 0x1c /* '\34' */ : + case 0x1d /* '\35' */ : + case 0x1e /* '\36' */ : + case 0x1f /* '\37' */ : + case 0x20 /* ' ' */ : + case 0x21 /* '!' */ : + case 0x23 /* '#' */ : + case 0x24 /* '$' */ : + case 0x25 /* '%' */ : + case 0x26 /* '&' */ : + case 0x27 /* '\'' */ : + case 0x28 /* '(' */ : + case 0x29 /* ')' */ : + case 0x2a /* '*' */ : + case 0x2b /* '+' */ : + case 0x2c /* ',' */ : + case 0x2d /* '-' */ : + case 0x2e /* '.' */ : + case 0x2f /* '/' */ : + case 0x30 /* '0' */ : + case 0x31 /* '1' */ : + case 0x32 /* '2' */ : + case 0x33 /* '3' */ : + case 0x34 /* '4' */ : + case 0x35 /* '5' */ : + case 0x36 /* '6' */ : + case 0x37 /* '7' */ : + case 0x38 /* '8' */ : + case 0x39 /* '9' */ : + case 0x3a /* ':' */ : + case 0x3b /* ';' */ : + case 0x3c /* '<' */ : + case 0x3d /* '=' */ : + case 0x3e /* '>' */ : + case 0x3f /* '?' */ : + case 0x40 /* '@' */ : + case 0x41 /* 'A' */ : + case 0x42 /* 'B' */ : + case 0x43 /* 'C' */ : + case 0x44 /* 'D' */ : + case 0x45 /* 'E' */ : + case 0x46 /* 'F' */ : + case 0x47 /* 'G' */ : + case 0x48 /* 'H' */ : + case 0x49 /* 'I' */ : + case 0x4a /* 'J' */ : + case 0x4b /* 'K' */ : + case 0x4c /* 'L' */ : + case 0x4d /* 'M' */ : + case 0x4e /* 'N' */ : + case 0x4f /* 'O' */ : + case 0x50 /* 'P' */ : + case 0x51 /* 'Q' */ : + case 0x52 /* 'R' */ : + case 0x53 /* 'S' */ : + case 0x54 /* 'T' */ : + case 0x55 /* 'U' */ : + case 0x56 /* 'V' */ : + case 0x57 /* 'W' */ : + case 0x58 /* 'X' */ : + case 0x59 /* 'Y' */ : + case 0x5a /* 'Z' */ : + case 0x5b /* '[' */ : + case 0x5d /* ']' */ : + case 0x5e /* '^' */ : + case 0x5f /* '_' */ : + case 0x60 /* '`' */ : + case 0x61 /* 'a' */ : + case 0x62 /* 'b' */ : + case 0x63 /* 'c' */ : + case 0x64 /* 'd' */ : + case 0x65 /* 'e' */ : + case 0x66 /* 'f' */ : + case 0x67 /* 'g' */ : + case 0x68 /* 'h' */ : + case 0x69 /* 'i' */ : + case 0x6a /* 'j' */ : + case 0x6b /* 'k' */ : + case 0x6c /* 'l' */ : + case 0x6d /* 'm' */ : + case 0x6e /* 'n' */ : + case 0x6f /* 'o' */ : + case 0x70 /* 'p' */ : + case 0x71 /* 'q' */ : + case 0x72 /* 'r' */ : + case 0x73 /* 's' */ : + case 0x74 /* 't' */ : + case 0x75 /* 'u' */ : + case 0x76 /* 'v' */ : + case 0x77 /* 'w' */ : + case 0x78 /* 'x' */ : + case 0x79 /* 'y' */ : + case 0x7a /* 'z' */ : + case 0x7b /* '{' */ : + case 0x7c /* '|' */ : + case 0x7d /* '}' */ : + case 0x7e /* '~' */ : + case 0x7f: + { + { + { + match(_tokenSet_2); + } + } + break; + } + default: + { + goto _loop65; + } + } + } + _loop65:; + } // ( ... )* + _saveIndex = text.length(); + match('\"' /* charlit */ ); + text.erase(_saveIndex); + if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { + _token = makeToken(_ttype); + _token->setText(text.substr(_begin, text.length()-_begin)); + } + _returnToken = _token; + _saveIndex=0; +} + +void RequirementLexer::mARROW(bool _createToken) { + int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); + _ttype = ARROW; + std::string::size_type _saveIndex; + + match("=>"); + if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { + _token = makeToken(_ttype); + _token->setText(text.substr(_begin, text.length()-_begin)); + } + _returnToken = _token; + _saveIndex=0; +} + +void RequirementLexer::mSEMI(bool _createToken) { + int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); + _ttype = SEMI; + std::string::size_type _saveIndex; + + match(';' /* charlit */ ); + if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { + _token = makeToken(_ttype); + _token->setText(text.substr(_begin, text.length()-_begin)); + } + _returnToken = _token; + _saveIndex=0; +} + +void RequirementLexer::mLPAREN(bool _createToken) { + int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); + _ttype = LPAREN; + std::string::size_type _saveIndex; + + match('(' /* charlit */ ); + if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { + _token = makeToken(_ttype); + _token->setText(text.substr(_begin, text.length()-_begin)); + } + _returnToken = _token; + _saveIndex=0; +} + +void RequirementLexer::mRPAREN(bool _createToken) { + int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); + _ttype = RPAREN; + std::string::size_type _saveIndex; + + match(')' /* charlit */ ); + if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { + _token = makeToken(_ttype); + _token->setText(text.substr(_begin, text.length()-_begin)); + } + _returnToken = _token; + _saveIndex=0; +} + +void RequirementLexer::mLBRACK(bool _createToken) { + int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); + _ttype = LBRACK; + std::string::size_type _saveIndex; + + match('[' /* charlit */ ); + if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { + _token = makeToken(_ttype); + _token->setText(text.substr(_begin, text.length()-_begin)); + } + _returnToken = _token; + _saveIndex=0; +} + +void RequirementLexer::mRBRACK(bool _createToken) { + int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); + _ttype = RBRACK; + std::string::size_type _saveIndex; + + match(']' /* charlit */ ); + if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { + _token = makeToken(_ttype); + _token->setText(text.substr(_begin, text.length()-_begin)); + } + _returnToken = _token; + _saveIndex=0; +} + +void RequirementLexer::mLESS(bool _createToken) { + int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); + _ttype = LESS; + std::string::size_type _saveIndex; + + match('<' /* charlit */ ); + if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { + _token = makeToken(_ttype); + _token->setText(text.substr(_begin, text.length()-_begin)); + } + _returnToken = _token; + _saveIndex=0; +} + +void RequirementLexer::mGT(bool _createToken) { + int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); + _ttype = GT; + std::string::size_type _saveIndex; + + match('>' /* charlit */ ); + if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { + _token = makeToken(_ttype); + _token->setText(text.substr(_begin, text.length()-_begin)); + } + _returnToken = _token; + _saveIndex=0; +} + +void RequirementLexer::mLE(bool _createToken) { + int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); + _ttype = LE; + std::string::size_type _saveIndex; + + match("<="); + if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { + _token = makeToken(_ttype); + _token->setText(text.substr(_begin, text.length()-_begin)); + } + _returnToken = _token; + _saveIndex=0; +} + +void RequirementLexer::mGE(bool _createToken) { + int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); + _ttype = GE; + std::string::size_type _saveIndex; + + match(">="); + if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { + _token = makeToken(_ttype); + _token->setText(text.substr(_begin, text.length()-_begin)); + } + _returnToken = _token; + _saveIndex=0; +} + +void RequirementLexer::mCOMMA(bool _createToken) { + int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); + _ttype = COMMA; + std::string::size_type _saveIndex; + + match(',' /* charlit */ ); + if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { + _token = makeToken(_ttype); + _token->setText(text.substr(_begin, text.length()-_begin)); + } + _returnToken = _token; + _saveIndex=0; +} + +void RequirementLexer::mEQL(bool _createToken) { + int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); + _ttype = EQL; + std::string::size_type _saveIndex; + + match('=' /* charlit */ ); + if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { + _token = makeToken(_ttype); + _token->setText(text.substr(_begin, text.length()-_begin)); + } + _returnToken = _token; + _saveIndex=0; +} + +void RequirementLexer::mEQQL(bool _createToken) { + int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); + _ttype = EQQL; + std::string::size_type _saveIndex; + + match("=="); + if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { + _token = makeToken(_ttype); + _token->setText(text.substr(_begin, text.length()-_begin)); + } + _returnToken = _token; + _saveIndex=0; +} + +void RequirementLexer::mSUBS(bool _createToken) { + int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); + _ttype = SUBS; + std::string::size_type _saveIndex; + + match('~' /* charlit */ ); + if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { + _token = makeToken(_ttype); + _token->setText(text.substr(_begin, text.length()-_begin)); + } + _returnToken = _token; + _saveIndex=0; +} + +void RequirementLexer::mNEG(bool _createToken) { + int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); + _ttype = NEG; + std::string::size_type _saveIndex; + + match('-' /* charlit */ ); + if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { + _token = makeToken(_ttype); + _token->setText(text.substr(_begin, text.length()-_begin)); + } + _returnToken = _token; + _saveIndex=0; +} + +void RequirementLexer::mNOT(bool _createToken) { + int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); + _ttype = NOT; + std::string::size_type _saveIndex; + + match('!' /* charlit */ ); + if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { + _token = makeToken(_ttype); + _token->setText(text.substr(_begin, text.length()-_begin)); + } + _returnToken = _token; + _saveIndex=0; +} + +void RequirementLexer::mSTAR(bool _createToken) { + int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); + _ttype = STAR; + std::string::size_type _saveIndex; + + match('*' /* charlit */ ); + if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { + _token = makeToken(_ttype); + _token->setText(text.substr(_begin, text.length()-_begin)); + } + _returnToken = _token; + _saveIndex=0; +} + +void RequirementLexer::mWS(bool _createToken) { + int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); + _ttype = WS; + std::string::size_type _saveIndex; + + { // ( ... )+ + int _cnt89=0; + for (;;) { + switch ( LA(1)) { + case 0x20 /* ' ' */ : + { + match(' ' /* charlit */ ); + break; + } + case 0xa /* '\n' */ : + { + match('\n' /* charlit */ ); + newline(); + break; + } + case 0x9 /* '\t' */ : + { + match('\t' /* charlit */ ); + break; + } + default: + { + if ( _cnt89>=1 ) { goto _loop89; } else {throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn());} + } + } + _cnt89++; + } + _loop89:; + } // ( ... )+ + _ttype = antlr::Token::SKIP; + if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { + _token = makeToken(_ttype); + _token->setText(text.substr(_begin, text.length()-_begin)); + } + _returnToken = _token; + _saveIndex=0; +} + +void RequirementLexer::mSHELLCOMMENT(bool _createToken) { + int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); + _ttype = SHELLCOMMENT; + std::string::size_type _saveIndex; + + match('#' /* charlit */ ); + { // ( ... )* + for (;;) { + if ((_tokenSet_3.member(LA(1)))) { + matchNot('\n' /* charlit */ ); + } + else { + goto _loop92; + } + + } + _loop92:; + } // ( ... )* + _ttype = antlr::Token::SKIP; + if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { + _token = makeToken(_ttype); + _token->setText(text.substr(_begin, text.length()-_begin)); + } + _returnToken = _token; + _saveIndex=0; +} + +void RequirementLexer::mC_COMMENT(bool _createToken) { + int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); + _ttype = C_COMMENT; + std::string::size_type _saveIndex; + + match("/*"); + { // ( ... )* + for (;;) { + if ((LA(1) == 0x2a /* '*' */ ) && (_tokenSet_4.member(LA(2)))) { + { + match('*' /* charlit */ ); + { + matchNot('/' /* charlit */ ); + } + } + } + else if ((_tokenSet_5.member(LA(1)))) { + { + matchNot('*' /* charlit */ ); + } + } + else { + goto _loop98; + } + + } + _loop98:; + } // ( ... )* + match("*/"); + _ttype = antlr::Token::SKIP; + if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { + _token = makeToken(_ttype); + _token->setText(text.substr(_begin, text.length()-_begin)); + } + _returnToken = _token; + _saveIndex=0; +} + +void RequirementLexer::mCPP_COMMENT(bool _createToken) { + int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); + _ttype = CPP_COMMENT; + std::string::size_type _saveIndex; + + match("//"); + { // ( ... )* + for (;;) { + if ((_tokenSet_3.member(LA(1)))) { + matchNot('\n' /* charlit */ ); + } + else { + goto _loop101; + } + + } + _loop101:; + } // ( ... )* + _ttype = antlr::Token::SKIP; + if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { + _token = makeToken(_ttype); + _token->setText(text.substr(_begin, text.length()-_begin)); + } + _returnToken = _token; + _saveIndex=0; +} + + +const unsigned long RequirementLexer::_tokenSet_0_data_[] = { 0UL, 0UL, 134217726UL, 134217726UL, 0UL, 0UL, 0UL, 0UL }; +const antlr::BitSet RequirementLexer::_tokenSet_0(_tokenSet_0_data_,8); +const unsigned long RequirementLexer::_tokenSet_1_data_[] = { 0UL, 67043328UL, 126UL, 126UL, 0UL, 0UL, 0UL, 0UL }; +// 0 1 2 3 4 5 6 7 8 +const antlr::BitSet RequirementLexer::_tokenSet_1(_tokenSet_1_data_,8); +const unsigned long RequirementLexer::_tokenSet_2_data_[] = { 4294967295UL, 4294967291UL, 4026531839UL, 4294967295UL, 0UL, 0UL, 0UL, 0UL }; +// 0x0 0x1 0x2 0x3 0x4 0x5 0x6 0x7 0x8 0x9 0xa 0xb 0xc 0xd 0xe 0xf 0x10 +// 0x11 0x12 0x13 0x14 0x15 0x16 0x17 0x18 0x19 0x1a 0x1b 0x1c 0x1d 0x1e +// 0x1f ! # $ % & \' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 +const antlr::BitSet RequirementLexer::_tokenSet_2(_tokenSet_2_data_,8); +const unsigned long RequirementLexer::_tokenSet_3_data_[] = { 4294966271UL, 4294967295UL, 4294967295UL, 4294967295UL, 0UL, 0UL, 0UL, 0UL }; +// 0x0 0x1 0x2 0x3 0x4 0x5 0x6 0x7 0x8 0x9 0xb 0xc 0xd 0xe 0xf 0x10 0x11 +// 0x12 0x13 0x14 0x15 0x16 0x17 0x18 0x19 0x1a 0x1b 0x1c 0x1d 0x1e 0x1f +// ! \" # $ % & \' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 +const antlr::BitSet RequirementLexer::_tokenSet_3(_tokenSet_3_data_,8); +const unsigned long RequirementLexer::_tokenSet_4_data_[] = { 4294967295UL, 4294934527UL, 4294967295UL, 4294967295UL, 0UL, 0UL, 0UL, 0UL }; +// 0x0 0x1 0x2 0x3 0x4 0x5 0x6 0x7 0x8 0x9 0xa 0xb 0xc 0xd 0xe 0xf 0x10 +// 0x11 0x12 0x13 0x14 0x15 0x16 0x17 0x18 0x19 0x1a 0x1b 0x1c 0x1d 0x1e +// 0x1f ! \" # $ % & \' ( ) * + , - . 0 1 2 3 4 5 6 7 8 +const antlr::BitSet RequirementLexer::_tokenSet_4(_tokenSet_4_data_,8); +const unsigned long RequirementLexer::_tokenSet_5_data_[] = { 4294967295UL, 4294966271UL, 4294967295UL, 4294967295UL, 0UL, 0UL, 0UL, 0UL }; +// 0x0 0x1 0x2 0x3 0x4 0x5 0x6 0x7 0x8 0x9 0xa 0xb 0xc 0xd 0xe 0xf 0x10 +// 0x11 0x12 0x13 0x14 0x15 0x16 0x17 0x18 0x19 0x1a 0x1b 0x1c 0x1d 0x1e +// 0x1f ! \" # $ % & \' ( ) + , - . / 0 1 2 3 4 5 6 7 8 +const antlr::BitSet RequirementLexer::_tokenSet_5(_tokenSet_5_data_,8); + +ANTLR_END_NAMESPACE diff --git a/libsecurity_codesigning/lib/RequirementLexer.hpp b/libsecurity_codesigning/lib/RequirementLexer.hpp new file mode 100644 index 00000000..ed5758f6 --- /dev/null +++ b/libsecurity_codesigning/lib/RequirementLexer.hpp @@ -0,0 +1,77 @@ +#ifndef INC_RequirementLexer_hpp_ +#define INC_RequirementLexer_hpp_ + +#include +/* $ANTLR 2.7.7 (20120228): "requirements.grammar" -> "RequirementLexer.hpp"$ */ +#include +#include +#include +#include "RequirementParserTokenTypes.hpp" +#include + +#include "requirement.h" +using namespace CodeSigning; +typedef Requirement::Maker Maker; + +ANTLR_BEGIN_NAMESPACE(Security_CodeSigning) +class CUSTOM_API RequirementLexer : public antlr::CharScanner, public RequirementParserTokenTypes +{ +private: + void initLiterals(); +public: + bool getCaseSensitiveLiterals() const + { + return true; + } +public: + RequirementLexer(std::istream& in); + RequirementLexer(antlr::InputBuffer& ib); + RequirementLexer(const antlr::LexerSharedInputState& state); + antlr::RefToken nextToken(); + protected: void mIDENT(bool _createToken); + public: void mDOTKEY(bool _createToken); + public: void mINTEGER(bool _createToken); + public: void mPATHNAME(bool _createToken); + public: void mHASHCONSTANT(bool _createToken); + protected: void mHEX(bool _createToken); + public: void mHEXCONSTANT(bool _createToken); + public: void mSTRING(bool _createToken); + public: void mARROW(bool _createToken); + public: void mSEMI(bool _createToken); + public: void mLPAREN(bool _createToken); + public: void mRPAREN(bool _createToken); + public: void mLBRACK(bool _createToken); + public: void mRBRACK(bool _createToken); + public: void mLESS(bool _createToken); + public: void mGT(bool _createToken); + public: void mLE(bool _createToken); + public: void mGE(bool _createToken); + public: void mCOMMA(bool _createToken); + public: void mEQL(bool _createToken); + public: void mEQQL(bool _createToken); + public: void mSUBS(bool _createToken); + public: void mNEG(bool _createToken); + public: void mNOT(bool _createToken); + public: void mSTAR(bool _createToken); + public: void mWS(bool _createToken); + public: void mSHELLCOMMENT(bool _createToken); + public: void mC_COMMENT(bool _createToken); + public: void mCPP_COMMENT(bool _createToken); +private: + + static const unsigned long _tokenSet_0_data_[]; + static const antlr::BitSet _tokenSet_0; + static const unsigned long _tokenSet_1_data_[]; + static const antlr::BitSet _tokenSet_1; + static const unsigned long _tokenSet_2_data_[]; + static const antlr::BitSet _tokenSet_2; + static const unsigned long _tokenSet_3_data_[]; + static const antlr::BitSet _tokenSet_3; + static const unsigned long _tokenSet_4_data_[]; + static const antlr::BitSet _tokenSet_4; + static const unsigned long _tokenSet_5_data_[]; + static const antlr::BitSet _tokenSet_5; +}; + +ANTLR_END_NAMESPACE +#endif /*INC_RequirementLexer_hpp_*/ diff --git a/libsecurity_codesigning/lib/RequirementParser.cpp b/libsecurity_codesigning/lib/RequirementParser.cpp new file mode 100644 index 00000000..90995c99 --- /dev/null +++ b/libsecurity_codesigning/lib/RequirementParser.cpp @@ -0,0 +1,1303 @@ +/* $ANTLR 2.7.7 (20120228): "requirements.grammar" -> "RequirementParser.cpp"$ */ +#include "RequirementParser.hpp" +#include +#include +#include + +#include "requirement.h" +#include "reqmaker.h" +#include "csutilities.h" +#include +#include +#include // OID coding +using namespace CodeSigning; +typedef Requirement::Maker Maker; + +ANTLR_BEGIN_NAMESPACE(Security_CodeSigning) + + // + // Collect error messages. + // Note that the immediate caller takes the absence of collected error messages + // to indicate compilation success. + // + void RequirementParser::reportError(const antlr::RecognitionException &ex) + { + errors += ex.toString() + "\n"; + } + + void RequirementParser::reportError(const std::string &s) + { + errors += s + "\n"; + } + + + // + // Parser helper functions + // + string RequirementParser::hexString(const string &s) + { + if (s.size() % 2) + throw antlr::SemanticException("odd number of digits"); + const char *p = s.data(); + string result; + for (unsigned n = 0; n < s.length(); n += 2) { + char c; + sscanf(p+n, "%2hhx", &c); + result.push_back(c); + } + return result; + } + + void RequirementParser::hashString(const string &s, SHA1::Digest hash) + { + if (s.size() != 2 * SHA1::digestLength) + throw antlr::SemanticException("invalid hash length"); + memcpy(hash, hexString(s).data(), SHA1::digestLength); + } + + static const char *matchPrefix(const string &key, const char *prefix) + { + unsigned pLength = strlen(prefix); + if (!key.compare(0, pLength, prefix, 0, pLength)) + return key.c_str() + pLength; + else + return NULL; + } + + void RequirementParser::certMatchOperation(Maker &maker, int32_t slot, string key) + { + if (matchPrefix(key, "subject.")) { + maker.put(opCertField); + maker.put(slot); + maker.put(key); + } else if (const char *oids = matchPrefix(key, "field.")) { + maker.put(opCertGeneric); + maker.put(slot); + CssmAutoData oid(Allocator::standard()); oid.fromOid(oids); + maker.putData(oid.data(), oid.length()); + } else if (const char *oids = matchPrefix(key, "extension.")) { + maker.put(opCertGeneric); + maker.put(slot); + CssmAutoData oid(Allocator::standard()); oid.fromOid(oids); + maker.putData(oid.data(), oid.length()); + } else if (const char *oids = matchPrefix(key, "policy.")) { + maker.put(opCertPolicy); + maker.put(slot); + CssmAutoData oid(Allocator::standard()); oid.fromOid(oids); + maker.putData(oid.data(), oid.length()); + } else { + throw antlr::SemanticException(key + ": unrecognized certificate field"); + } + } + +RequirementParser::RequirementParser(antlr::TokenBuffer& tokenBuf, int k) +: antlr::LLkParser(tokenBuf,k) +{ +} + +RequirementParser::RequirementParser(antlr::TokenBuffer& tokenBuf) +: antlr::LLkParser(tokenBuf,2) +{ +} + +RequirementParser::RequirementParser(antlr::TokenStream& lexer, int k) +: antlr::LLkParser(lexer,k) +{ +} + +RequirementParser::RequirementParser(antlr::TokenStream& lexer) +: antlr::LLkParser(lexer,2) +{ +} + +RequirementParser::RequirementParser(const antlr::ParserSharedInputState& state) +: antlr::LLkParser(state,2) +{ +} + +BlobCore * RequirementParser::autosense() { + BlobCore *result = NULL; + + try { // for error handling + switch ( LA(1)) { + case LPAREN: + case NOT: + case LITERAL_always: + case LITERAL_true: + case LITERAL_never: + case LITERAL_false: + case LITERAL_identifier: + case LITERAL_cdhash: + case LITERAL_anchor: + case LITERAL_certificate: + case LITERAL_cert: + case LITERAL_info: + case LITERAL_entitlement: + { + result=requirement(); + break; + } + case LITERAL_guest: + case LITERAL_host: + case LITERAL_designated: + case LITERAL_library: + case LITERAL_plugin: + case INTEGER: + { + result=requirementSet(); + break; + } + default: + { + throw antlr::NoViableAltException(LT(1), getFilename()); + } + } + } + catch (antlr::RecognitionException& ex) { + reportError(ex); + recover(ex,_tokenSet_0); + } + return result; +} + +Requirement * RequirementParser::requirement() { + Requirement *result = NULL; + + try { // for error handling + result=requirementElement(); + match(antlr::Token::EOF_TYPE); + } + catch (antlr::RecognitionException& ex) { + reportError(ex); + recover(ex,_tokenSet_0); + } + return result; +} + +Requirements * RequirementParser::requirementSet() { + Requirements *result = NULL; + Requirements::Maker maker; + + try { // for error handling + { // ( ... )+ + int _cnt4=0; + for (;;) { + if (((LA(1) >= LITERAL_guest && LA(1) <= INTEGER))) { + uint32_t t; Requirement *req; + t=requirementType(); + match(ARROW); + req=requirementElement(); + maker.add(t, req); + } + else { + if ( _cnt4>=1 ) { goto _loop4; } else {throw antlr::NoViableAltException(LT(1), getFilename());} + } + + _cnt4++; + } + _loop4:; + } // ( ... )+ + result = errors.empty() ? maker() : NULL; + match(antlr::Token::EOF_TYPE); + } + catch (antlr::RecognitionException& ex) { + reportError(ex); + recover(ex,_tokenSet_0); + } + return result; +} + +uint32_t RequirementParser::requirementType() { + uint32_t type = kSecInvalidRequirementType; + antlr::RefToken stype = antlr::nullToken; + + try { // for error handling + switch ( LA(1)) { + case LITERAL_guest: + { + match(LITERAL_guest); + type = kSecGuestRequirementType; + break; + } + case LITERAL_host: + { + match(LITERAL_host); + type = kSecHostRequirementType; + break; + } + case LITERAL_designated: + { + match(LITERAL_designated); + type = kSecDesignatedRequirementType; + break; + } + case LITERAL_library: + { + match(LITERAL_library); + type = kSecLibraryRequirementType; + break; + } + case LITERAL_plugin: + { + match(LITERAL_plugin); + type = kSecPluginRequirementType; + break; + } + case INTEGER: + { + stype = LT(1); + match(INTEGER); + type = atol(stype->getText().c_str()); + break; + } + default: + { + throw antlr::NoViableAltException(LT(1), getFilename()); + } + } + } + catch (antlr::RecognitionException& ex) { + reportError(ex); + recover(ex,_tokenSet_1); + } + return type; +} + +Requirement * RequirementParser::requirementElement() { + Requirement *result = NULL; + Requirement::Maker maker; + + try { // for error handling + expr(maker); + result = maker(); + { // ( ... )* + for (;;) { + if ((LA(1) == SEMI)) { + fluff(); + } + else { + goto _loop9; + } + + } + _loop9:; + } // ( ... )* + } + catch (antlr::RecognitionException& ex) { + reportError(ex); + recover(ex,_tokenSet_2); + } + return result; +} + +void RequirementParser::expr( + Maker &maker +) { + Maker::Label label(maker); + + try { // for error handling + term(maker); + { // ( ... )* + for (;;) { + if ((LA(1) == LITERAL_or)) { + match(LITERAL_or); + maker.insert(label) = opOr; + term(maker); + } + else { + goto _loop12; + } + + } + _loop12:; + } // ( ... )* + } + catch (antlr::RecognitionException& ex) { + reportError(ex); + recover(ex,_tokenSet_3); + } +} + +void RequirementParser::fluff() { + + try { // for error handling + match(SEMI); + } + catch (antlr::RecognitionException& ex) { + reportError(ex); + recover(ex,_tokenSet_4); + } +} + +void RequirementParser::term( + Maker &maker +) { + Maker::Label label(maker); + + try { // for error handling + primary(maker); + { // ( ... )* + for (;;) { + if ((LA(1) == LITERAL_and)) { + match(LITERAL_and); + maker.insert(label) = opAnd; + primary(maker); + } + else { + goto _loop15; + } + + } + _loop15:; + } // ( ... )* + } + catch (antlr::RecognitionException& ex) { + reportError(ex); + recover(ex,_tokenSet_5); + } +} + +void RequirementParser::primary( + Maker &maker +) { + + try { // for error handling + switch ( LA(1)) { + case NOT: + { + match(NOT); + maker.put(opNot); + primary(maker); + break; + } + case LITERAL_always: + case LITERAL_true: + { + { + switch ( LA(1)) { + case LITERAL_always: + { + match(LITERAL_always); + break; + } + case LITERAL_true: + { + match(LITERAL_true); + break; + } + default: + { + throw antlr::NoViableAltException(LT(1), getFilename()); + } + } + } + maker.put(opTrue); + break; + } + case LITERAL_never: + case LITERAL_false: + { + { + switch ( LA(1)) { + case LITERAL_never: + { + match(LITERAL_never); + break; + } + case LITERAL_false: + { + match(LITERAL_false); + break; + } + default: + { + throw antlr::NoViableAltException(LT(1), getFilename()); + } + } + } + maker.put(opFalse); + break; + } + case LITERAL_anchor: + case LITERAL_certificate: + case LITERAL_cert: + { + certspec(maker); + break; + } + case LITERAL_info: + { + infospec(maker); + break; + } + case LITERAL_entitlement: + { + entitlementspec(maker); + break; + } + case LITERAL_identifier: + { + match(LITERAL_identifier); + string code; + eql(); + code=identifierString(); + maker.ident(code); + break; + } + case LITERAL_cdhash: + { + match(LITERAL_cdhash); + SHA1::Digest digest; + eql(); + hash(digest); + maker.cdhash(digest); + break; + } + default: + if ((LA(1) == LPAREN) && (_tokenSet_6.member(LA(2)))) { + match(LPAREN); + expr(maker); + match(RPAREN); + } + else if ((LA(1) == LPAREN) && (LA(2) == DOTKEY || LA(2) == STRING)) { + match(LPAREN); + string name; + name=identifierString(); + match(RPAREN); + maker.put(opNamedCode); maker.put(name); + } + else { + throw antlr::NoViableAltException(LT(1), getFilename()); + } + } + } + catch (antlr::RecognitionException& ex) { + reportError(ex); + recover(ex,_tokenSet_7); + } +} + +void RequirementParser::certspec( + Maker &maker +) { + + try { // for error handling + if ((LA(1) == LITERAL_anchor) && (LA(2) == LITERAL_apple)) { + match(LITERAL_anchor); + match(LITERAL_apple); + appleanchor(maker); + } + else if ((LA(1) == LITERAL_anchor) && (LA(2) == LITERAL_generic)) { + match(LITERAL_anchor); + match(LITERAL_generic); + match(LITERAL_apple); + maker.put(opAppleGenericAnchor); + } + else if ((LA(1) == LITERAL_anchor || LA(1) == LITERAL_certificate || LA(1) == LITERAL_cert) && (LA(2) == LITERAL_trusted)) { + { + switch ( LA(1)) { + case LITERAL_certificate: + { + match(LITERAL_certificate); + break; + } + case LITERAL_cert: + { + match(LITERAL_cert); + break; + } + case LITERAL_anchor: + { + match(LITERAL_anchor); + break; + } + default: + { + throw antlr::NoViableAltException(LT(1), getFilename()); + } + } + } + match(LITERAL_trusted); + maker.trustedAnchor(); + } + else if ((LA(1) == LITERAL_certificate || LA(1) == LITERAL_cert) && (_tokenSet_8.member(LA(2)))) { + { + switch ( LA(1)) { + case LITERAL_certificate: + { + match(LITERAL_certificate); + break; + } + case LITERAL_cert: + { + match(LITERAL_cert); + break; + } + default: + { + throw antlr::NoViableAltException(LT(1), getFilename()); + } + } + } + int32_t slot; + slot=certSlot(); + { + switch ( LA(1)) { + case EQL: + case EQQL: + case LBRACK: + case HASHCONSTANT: + case DOTKEY: + case STRING: + case PATHNAME: + { + certslotspec(maker, slot); + break; + } + case LITERAL_trusted: + { + match(LITERAL_trusted); + maker.trustedAnchor(slot); + break; + } + default: + { + throw antlr::NoViableAltException(LT(1), getFilename()); + } + } + } + } + else if ((LA(1) == LITERAL_anchor) && (_tokenSet_9.member(LA(2)))) { + match(LITERAL_anchor); + certslotspec(maker, Requirement::anchorCert); + } + else { + throw antlr::NoViableAltException(LT(1), getFilename()); + } + + } + catch (antlr::RecognitionException& ex) { + reportError(ex); + recover(ex,_tokenSet_7); + } +} + +void RequirementParser::infospec( + Maker &maker +) { + string key; + + try { // for error handling + match(LITERAL_info); + key=bracketKey(); + maker.put(opInfoKeyField); maker.put(key); + match_suffix(maker); + } + catch (antlr::RecognitionException& ex) { + reportError(ex); + recover(ex,_tokenSet_7); + } +} + +void RequirementParser::entitlementspec( + Maker &maker +) { + string key; + + try { // for error handling + match(LITERAL_entitlement); + key=bracketKey(); + maker.put(opEntitlementField); maker.put(key); + match_suffix(maker); + } + catch (antlr::RecognitionException& ex) { + reportError(ex); + recover(ex,_tokenSet_7); + } +} + +void RequirementParser::eql() { + + try { // for error handling + switch ( LA(1)) { + case EQL: + { + match(EQL); + break; + } + case EQQL: + { + match(EQQL); + break; + } + case HASHCONSTANT: + case DOTKEY: + case STRING: + case PATHNAME: + { + empty(); + break; + } + default: + { + throw antlr::NoViableAltException(LT(1), getFilename()); + } + } + } + catch (antlr::RecognitionException& ex) { + reportError(ex); + recover(ex,_tokenSet_10); + } +} + +string RequirementParser::identifierString() { + string result; + antlr::RefToken dk = antlr::nullToken; + antlr::RefToken s = antlr::nullToken; + + try { // for error handling + switch ( LA(1)) { + case DOTKEY: + { + dk = LT(1); + match(DOTKEY); + result = dk->getText(); + break; + } + case STRING: + { + s = LT(1); + match(STRING); + result = s->getText(); + break; + } + default: + { + throw antlr::NoViableAltException(LT(1), getFilename()); + } + } + } + catch (antlr::RecognitionException& ex) { + reportError(ex); + recover(ex,_tokenSet_7); + } + return result; +} + +void RequirementParser::hash( + SHA1::Digest digest +) { + antlr::RefToken hash = antlr::nullToken; + + try { // for error handling + hash = LT(1); + match(HASHCONSTANT); + hashString(hash->getText(), digest); + } + catch (antlr::RecognitionException& ex) { + reportError(ex); + recover(ex,_tokenSet_7); + } +} + +void RequirementParser::appleanchor( + Maker &maker +) { + + try { // for error handling + switch ( LA(1)) { + case antlr::Token::EOF_TYPE: + case LITERAL_guest: + case LITERAL_host: + case LITERAL_designated: + case LITERAL_library: + case LITERAL_plugin: + case INTEGER: + case LITERAL_or: + case LITERAL_and: + case RPAREN: + case SEMI: + { + empty(); + maker.put(opAppleAnchor); + break; + } + case LITERAL_generic: + { + match(LITERAL_generic); + maker.put(opAppleGenericAnchor); + break; + } + case DOTKEY: + case STRING: + { + string name; + name=identifierString(); + maker.put(opNamedAnchor); maker.put(name); + break; + } + default: + { + throw antlr::NoViableAltException(LT(1), getFilename()); + } + } + } + catch (antlr::RecognitionException& ex) { + reportError(ex); + recover(ex,_tokenSet_7); + } +} + +int32_t RequirementParser::certSlot() { + int32_t slot = 0; + antlr::RefToken s = antlr::nullToken; + antlr::RefToken ss = antlr::nullToken; + + try { // for error handling + switch ( LA(1)) { + case INTEGER: + { + s = LT(1); + match(INTEGER); + slot = atol(s->getText().c_str()); + break; + } + case NEG: + { + match(NEG); + ss = LT(1); + match(INTEGER); + slot = -atol(ss->getText().c_str()); + break; + } + case LITERAL_leaf: + { + match(LITERAL_leaf); + slot = Requirement::leafCert; + break; + } + case LITERAL_root: + { + match(LITERAL_root); + slot = Requirement::anchorCert; + break; + } + default: + { + throw antlr::NoViableAltException(LT(1), getFilename()); + } + } + } + catch (antlr::RecognitionException& ex) { + reportError(ex); + recover(ex,_tokenSet_11); + } + return slot; +} + +void RequirementParser::certslotspec( + Maker &maker, int32_t slot +) { + string key; + + try { // for error handling + switch ( LA(1)) { + case EQL: + case EQQL: + case HASHCONSTANT: + case DOTKEY: + case STRING: + case PATHNAME: + { + eql(); + SHA1::Digest digest; + certificateDigest(digest); + maker.anchor(slot, digest); + break; + } + case LBRACK: + { + key=bracketKey(); + certMatchOperation(maker, slot, key); + match_suffix(maker); + break; + } + default: + { + throw antlr::NoViableAltException(LT(1), getFilename()); + } + } + } + catch (antlr::RecognitionException& ex) { + reportError(ex); + recover(ex,_tokenSet_7); + } +} + +void RequirementParser::empty() { + + try { // for error handling + } + catch (antlr::RecognitionException& ex) { + reportError(ex); + recover(ex,_tokenSet_12); + } +} + +void RequirementParser::certificateDigest( + SHA1::Digest digest +) { + + try { // for error handling + switch ( LA(1)) { + case HASHCONSTANT: + { + hash(digest); + break; + } + case DOTKEY: + case STRING: + case PATHNAME: + { + string path; + path=pathstring(); + if (CFRef certData = cfLoadFile(path)) + hashOfCertificate(CFDataGetBytePtr(certData), CFDataGetLength(certData), digest); + else + throw antlr::SemanticException(path + ": not found"); + + break; + } + default: + { + throw antlr::NoViableAltException(LT(1), getFilename()); + } + } + } + catch (antlr::RecognitionException& ex) { + reportError(ex); + recover(ex,_tokenSet_7); + } +} + +string RequirementParser::bracketKey() { + string key; + + try { // for error handling + match(LBRACK); + key=stringvalue(); + match(RBRACK); + } + catch (antlr::RecognitionException& ex) { + reportError(ex); + recover(ex,_tokenSet_13); + } + return key; +} + +void RequirementParser::match_suffix( + Maker &maker +) { + + try { // for error handling + switch ( LA(1)) { + case antlr::Token::EOF_TYPE: + case LITERAL_guest: + case LITERAL_host: + case LITERAL_designated: + case LITERAL_library: + case LITERAL_plugin: + case INTEGER: + case LITERAL_or: + case LITERAL_and: + case RPAREN: + case LITERAL_exists: + case SEMI: + { + empty(); + { + switch ( LA(1)) { + case LITERAL_exists: + { + match(LITERAL_exists); + break; + } + case antlr::Token::EOF_TYPE: + case LITERAL_guest: + case LITERAL_host: + case LITERAL_designated: + case LITERAL_library: + case LITERAL_plugin: + case INTEGER: + case LITERAL_or: + case LITERAL_and: + case RPAREN: + case SEMI: + { + break; + } + default: + { + throw antlr::NoViableAltException(LT(1), getFilename()); + } + } + } + maker.put(matchExists); + break; + } + case EQL: + case EQQL: + { + { + switch ( LA(1)) { + case EQL: + { + match(EQL); + break; + } + case EQQL: + { + match(EQQL); + break; + } + default: + { + throw antlr::NoViableAltException(LT(1), getFilename()); + } + } + } + MatchOperation mop = matchEqual; string value; + { + switch ( LA(1)) { + case STAR: + { + match(STAR); + mop = matchEndsWith; + break; + } + case HEXCONSTANT: + case DOTKEY: + case STRING: + { + break; + } + default: + { + throw antlr::NoViableAltException(LT(1), getFilename()); + } + } + } + value=datavalue(); + { + switch ( LA(1)) { + case STAR: + { + match(STAR); + mop = (mop == matchEndsWith) ? matchContains : matchBeginsWith; + break; + } + case antlr::Token::EOF_TYPE: + case LITERAL_guest: + case LITERAL_host: + case LITERAL_designated: + case LITERAL_library: + case LITERAL_plugin: + case INTEGER: + case LITERAL_or: + case LITERAL_and: + case RPAREN: + case SEMI: + { + break; + } + default: + { + throw antlr::NoViableAltException(LT(1), getFilename()); + } + } + } + maker.put(mop); maker.put(value); + break; + } + case SUBS: + { + match(SUBS); + string value; + value=datavalue(); + maker.put(matchContains); maker.put(value); + break; + } + case LESS: + { + match(LESS); + string value; + value=datavalue(); + maker.put(matchLessThan); maker.put(value); + break; + } + case GT: + { + match(GT); + string value; + value=datavalue(); + maker.put(matchGreaterThan); maker.put(value); + break; + } + case LE: + { + match(LE); + string value; + value=datavalue(); + maker.put(matchLessEqual); maker.put(value); + break; + } + case GE: + { + match(GE); + string value; + value=datavalue(); + maker.put(matchGreaterEqual); maker.put(value); + break; + } + default: + { + throw antlr::NoViableAltException(LT(1), getFilename()); + } + } + } + catch (antlr::RecognitionException& ex) { + reportError(ex); + recover(ex,_tokenSet_7); + } +} + +string RequirementParser::datavalue() { + string result; + antlr::RefToken hex = antlr::nullToken; + + try { // for error handling + switch ( LA(1)) { + case DOTKEY: + case STRING: + { + result=stringvalue(); + break; + } + case HEXCONSTANT: + { + hex = LT(1); + match(HEXCONSTANT); + result = hexString(hex->getText()); + break; + } + default: + { + throw antlr::NoViableAltException(LT(1), getFilename()); + } + } + } + catch (antlr::RecognitionException& ex) { + reportError(ex); + recover(ex,_tokenSet_14); + } + return result; +} + +string RequirementParser::stringvalue() { + string result; + antlr::RefToken dk = antlr::nullToken; + antlr::RefToken s = antlr::nullToken; + + try { // for error handling + switch ( LA(1)) { + case DOTKEY: + { + dk = LT(1); + match(DOTKEY); + result = dk->getText(); + break; + } + case STRING: + { + s = LT(1); + match(STRING); + result = s->getText(); + break; + } + default: + { + throw antlr::NoViableAltException(LT(1), getFilename()); + } + } + } + catch (antlr::RecognitionException& ex) { + reportError(ex); + recover(ex,_tokenSet_15); + } + return result; +} + +string RequirementParser::pathstring() { + string result; + antlr::RefToken dk = antlr::nullToken; + antlr::RefToken s = antlr::nullToken; + antlr::RefToken pn = antlr::nullToken; + + try { // for error handling + switch ( LA(1)) { + case DOTKEY: + { + dk = LT(1); + match(DOTKEY); + result = dk->getText(); + break; + } + case STRING: + { + s = LT(1); + match(STRING); + result = s->getText(); + break; + } + case PATHNAME: + { + pn = LT(1); + match(PATHNAME); + result = pn->getText(); + break; + } + default: + { + throw antlr::NoViableAltException(LT(1), getFilename()); + } + } + } + catch (antlr::RecognitionException& ex) { + reportError(ex); + recover(ex,_tokenSet_7); + } + return result; +} + +void RequirementParser::initializeASTFactory( antlr::ASTFactory& ) +{ +} +const char* RequirementParser::tokenNames[] = { + "<0>", + "EOF", + "<2>", + "NULL_TREE_LOOKAHEAD", + "ARROW", + "\"guest\"", + "\"host\"", + "\"designated\"", + "\"library\"", + "\"plugin\"", + "INTEGER", + "\"or\"", + "\"and\"", + "LPAREN", + "RPAREN", + "NOT", + "\"always\"", + "\"true\"", + "\"never\"", + "\"false\"", + "\"identifier\"", + "\"cdhash\"", + "\"anchor\"", + "\"apple\"", + "\"generic\"", + "\"certificate\"", + "\"cert\"", + "\"trusted\"", + "\"info\"", + "\"entitlement\"", + "\"exists\"", + "EQL", + "EQQL", + "STAR", + "SUBS", + "LESS", + "GT", + "LE", + "GE", + "LBRACK", + "RBRACK", + "NEG", + "\"leaf\"", + "\"root\"", + "HASHCONSTANT", + "HEXCONSTANT", + "DOTKEY", + "STRING", + "PATHNAME", + "SEMI", + "IDENT", + "HEX", + "COMMA", + "WS", + "SHELLCOMMENT", + "C_COMMENT", + "CPP_COMMENT", + 0 +}; + +const unsigned long RequirementParser::_tokenSet_0_data_[] = { 2UL, 0UL, 0UL, 0UL }; +// EOF +const antlr::BitSet RequirementParser::_tokenSet_0(_tokenSet_0_data_,4); +const unsigned long RequirementParser::_tokenSet_1_data_[] = { 16UL, 0UL, 0UL, 0UL }; +// ARROW +const antlr::BitSet RequirementParser::_tokenSet_1(_tokenSet_1_data_,4); +const unsigned long RequirementParser::_tokenSet_2_data_[] = { 2018UL, 0UL, 0UL, 0UL }; +// EOF "guest" "host" "designated" "library" "plugin" INTEGER +const antlr::BitSet RequirementParser::_tokenSet_2(_tokenSet_2_data_,4); +const unsigned long RequirementParser::_tokenSet_3_data_[] = { 18402UL, 131072UL, 0UL, 0UL }; +// EOF "guest" "host" "designated" "library" "plugin" INTEGER RPAREN SEMI +const antlr::BitSet RequirementParser::_tokenSet_3(_tokenSet_3_data_,4); +const unsigned long RequirementParser::_tokenSet_4_data_[] = { 2018UL, 131072UL, 0UL, 0UL }; +// EOF "guest" "host" "designated" "library" "plugin" INTEGER SEMI +const antlr::BitSet RequirementParser::_tokenSet_4(_tokenSet_4_data_,4); +const unsigned long RequirementParser::_tokenSet_5_data_[] = { 20450UL, 131072UL, 0UL, 0UL }; +// EOF "guest" "host" "designated" "library" "plugin" INTEGER "or" RPAREN +// SEMI +const antlr::BitSet RequirementParser::_tokenSet_5(_tokenSet_5_data_,4); +const unsigned long RequirementParser::_tokenSet_6_data_[] = { 914333696UL, 0UL, 0UL, 0UL }; +// LPAREN NOT "always" "true" "never" "false" "identifier" "cdhash" "anchor" +// "certificate" "cert" "info" "entitlement" +const antlr::BitSet RequirementParser::_tokenSet_6(_tokenSet_6_data_,4); +const unsigned long RequirementParser::_tokenSet_7_data_[] = { 24546UL, 131072UL, 0UL, 0UL }; +// EOF "guest" "host" "designated" "library" "plugin" INTEGER "or" "and" +// RPAREN SEMI +const antlr::BitSet RequirementParser::_tokenSet_7(_tokenSet_7_data_,4); +const unsigned long RequirementParser::_tokenSet_8_data_[] = { 1024UL, 3584UL, 0UL, 0UL }; +// INTEGER NEG "leaf" "root" +const antlr::BitSet RequirementParser::_tokenSet_8(_tokenSet_8_data_,4); +const unsigned long RequirementParser::_tokenSet_9_data_[] = { 2147483648UL, 118913UL, 0UL, 0UL }; +// EQL EQQL LBRACK HASHCONSTANT DOTKEY STRING PATHNAME +const antlr::BitSet RequirementParser::_tokenSet_9(_tokenSet_9_data_,4); +const unsigned long RequirementParser::_tokenSet_10_data_[] = { 0UL, 118784UL, 0UL, 0UL }; +// HASHCONSTANT DOTKEY STRING PATHNAME +const antlr::BitSet RequirementParser::_tokenSet_10(_tokenSet_10_data_,4); +const unsigned long RequirementParser::_tokenSet_11_data_[] = { 2281701376UL, 118913UL, 0UL, 0UL }; +// "trusted" EQL EQQL LBRACK HASHCONSTANT DOTKEY STRING PATHNAME +const antlr::BitSet RequirementParser::_tokenSet_11(_tokenSet_11_data_,4); +const unsigned long RequirementParser::_tokenSet_12_data_[] = { 1073766370UL, 249856UL, 0UL, 0UL }; +// EOF "guest" "host" "designated" "library" "plugin" INTEGER "or" "and" +// RPAREN "exists" HASHCONSTANT DOTKEY STRING PATHNAME SEMI +const antlr::BitSet RequirementParser::_tokenSet_12(_tokenSet_12_data_,4); +const unsigned long RequirementParser::_tokenSet_13_data_[] = { 3221250018UL, 131197UL, 0UL, 0UL }; +// EOF "guest" "host" "designated" "library" "plugin" INTEGER "or" "and" +// RPAREN "exists" EQL EQQL SUBS LESS GT LE GE SEMI +const antlr::BitSet RequirementParser::_tokenSet_13(_tokenSet_13_data_,4); +const unsigned long RequirementParser::_tokenSet_14_data_[] = { 24546UL, 131074UL, 0UL, 0UL }; +// EOF "guest" "host" "designated" "library" "plugin" INTEGER "or" "and" +// RPAREN STAR SEMI +const antlr::BitSet RequirementParser::_tokenSet_14(_tokenSet_14_data_,4); +const unsigned long RequirementParser::_tokenSet_15_data_[] = { 24546UL, 131330UL, 0UL, 0UL }; +// EOF "guest" "host" "designated" "library" "plugin" INTEGER "or" "and" +// RPAREN STAR RBRACK SEMI +const antlr::BitSet RequirementParser::_tokenSet_15(_tokenSet_15_data_,4); + + +ANTLR_END_NAMESPACE diff --git a/libsecurity_codesigning/lib/RequirementParser.hpp b/libsecurity_codesigning/lib/RequirementParser.hpp new file mode 100644 index 00000000..c93719e1 --- /dev/null +++ b/libsecurity_codesigning/lib/RequirementParser.hpp @@ -0,0 +1,153 @@ +#ifndef INC_RequirementParser_hpp_ +#define INC_RequirementParser_hpp_ + +#include +/* $ANTLR 2.7.7 (20120228): "requirements.grammar" -> "RequirementParser.hpp"$ */ +#include +#include +#include "RequirementParserTokenTypes.hpp" +#include + + +#include "requirement.h" +using namespace CodeSigning; +typedef Requirement::Maker Maker; + +ANTLR_BEGIN_NAMESPACE(Security_CodeSigning) +class CUSTOM_API RequirementParser : public antlr::LLkParser, public RequirementParserTokenTypes +{ + +public: + std::string errors; + void reportError(const antlr::RecognitionException &ex); + void reportError(const std::string &s); + +private: + static string hexString(const string &s); + static void hashString(const string &s, SHA1::Digest hash); + void certMatchOperation(Maker &maker, int32_t slot, string key); +public: + void initializeASTFactory( antlr::ASTFactory& factory ); +protected: + RequirementParser(antlr::TokenBuffer& tokenBuf, int k); +public: + RequirementParser(antlr::TokenBuffer& tokenBuf); +protected: + RequirementParser(antlr::TokenStream& lexer, int k); +public: + RequirementParser(antlr::TokenStream& lexer); + RequirementParser(const antlr::ParserSharedInputState& state); + int getNumTokens() const + { + return RequirementParser::NUM_TOKENS; + } + const char* getTokenName( int type ) const + { + if( type > getNumTokens() ) return 0; + return RequirementParser::tokenNames[type]; + } + const char* const* getTokenNames() const + { + return RequirementParser::tokenNames; + } + public: BlobCore * autosense(); + public: Requirement * requirement(); + public: Requirements * requirementSet(); + public: uint32_t requirementType(); + public: Requirement * requirementElement(); + public: void expr( + Maker &maker + ); + public: void fluff(); + public: void term( + Maker &maker + ); + public: void primary( + Maker &maker + ); + public: void certspec( + Maker &maker + ); + public: void infospec( + Maker &maker + ); + public: void entitlementspec( + Maker &maker + ); + public: void eql(); + public: string identifierString(); + public: void hash( + SHA1::Digest digest + ); + public: void appleanchor( + Maker &maker + ); + public: int32_t certSlot(); + public: void certslotspec( + Maker &maker, int32_t slot + ); + public: void empty(); + public: void certificateDigest( + SHA1::Digest digest + ); + public: string bracketKey(); + public: void match_suffix( + Maker &maker + ); + public: string datavalue(); + public: string stringvalue(); + public: string pathstring(); +public: + antlr::RefAST getAST() + { + return returnAST; + } + +protected: + antlr::RefAST returnAST; +private: + static const char* tokenNames[]; +#ifndef NO_STATIC_CONSTS + static const int NUM_TOKENS = 57; +#else + enum { + NUM_TOKENS = 57 + }; +#endif + + static const unsigned long _tokenSet_0_data_[]; + static const antlr::BitSet _tokenSet_0; + static const unsigned long _tokenSet_1_data_[]; + static const antlr::BitSet _tokenSet_1; + static const unsigned long _tokenSet_2_data_[]; + static const antlr::BitSet _tokenSet_2; + static const unsigned long _tokenSet_3_data_[]; + static const antlr::BitSet _tokenSet_3; + static const unsigned long _tokenSet_4_data_[]; + static const antlr::BitSet _tokenSet_4; + static const unsigned long _tokenSet_5_data_[]; + static const antlr::BitSet _tokenSet_5; + static const unsigned long _tokenSet_6_data_[]; + static const antlr::BitSet _tokenSet_6; + static const unsigned long _tokenSet_7_data_[]; + static const antlr::BitSet _tokenSet_7; + static const unsigned long _tokenSet_8_data_[]; + static const antlr::BitSet _tokenSet_8; + static const unsigned long _tokenSet_9_data_[]; + static const antlr::BitSet _tokenSet_9; + static const unsigned long _tokenSet_10_data_[]; + static const antlr::BitSet _tokenSet_10; + static const unsigned long _tokenSet_11_data_[]; + static const antlr::BitSet _tokenSet_11; + static const unsigned long _tokenSet_12_data_[]; + static const antlr::BitSet _tokenSet_12; + static const unsigned long _tokenSet_13_data_[]; + static const antlr::BitSet _tokenSet_13; + static const unsigned long _tokenSet_14_data_[]; + static const antlr::BitSet _tokenSet_14; + static const unsigned long _tokenSet_15_data_[]; + static const antlr::BitSet _tokenSet_15; +}; + +ANTLR_END_NAMESPACE +#endif /*INC_RequirementParser_hpp_*/ diff --git a/libsecurity_codesigning/lib/RequirementParserTokenTypes.hpp b/libsecurity_codesigning/lib/RequirementParserTokenTypes.hpp new file mode 100644 index 00000000..388c3781 --- /dev/null +++ b/libsecurity_codesigning/lib/RequirementParserTokenTypes.hpp @@ -0,0 +1,75 @@ +#ifndef INC_RequirementParserTokenTypes_hpp_ +#define INC_RequirementParserTokenTypes_hpp_ + +ANTLR_BEGIN_NAMESPACE(Security_CodeSigning) +/* $ANTLR 2.7.7 (20120228): "requirements.grammar" -> "RequirementParserTokenTypes.hpp"$ */ + +#ifndef CUSTOM_API +# define CUSTOM_API +#endif + +#ifdef __cplusplus +struct CUSTOM_API RequirementParserTokenTypes { +#endif + enum { + EOF_ = 1, + ARROW = 4, + LITERAL_guest = 5, + LITERAL_host = 6, + LITERAL_designated = 7, + LITERAL_library = 8, + LITERAL_plugin = 9, + INTEGER = 10, + LITERAL_or = 11, + LITERAL_and = 12, + LPAREN = 13, + RPAREN = 14, + NOT = 15, + LITERAL_always = 16, + LITERAL_true = 17, + LITERAL_never = 18, + LITERAL_false = 19, + LITERAL_identifier = 20, + LITERAL_cdhash = 21, + LITERAL_anchor = 22, + LITERAL_apple = 23, + LITERAL_generic = 24, + LITERAL_certificate = 25, + LITERAL_cert = 26, + LITERAL_trusted = 27, + LITERAL_info = 28, + LITERAL_entitlement = 29, + LITERAL_exists = 30, + EQL = 31, + EQQL = 32, + STAR = 33, + SUBS = 34, + LESS = 35, + GT = 36, + LE = 37, + GE = 38, + LBRACK = 39, + RBRACK = 40, + NEG = 41, + LITERAL_leaf = 42, + LITERAL_root = 43, + HASHCONSTANT = 44, + HEXCONSTANT = 45, + DOTKEY = 46, + STRING = 47, + PATHNAME = 48, + SEMI = 49, + IDENT = 50, + HEX = 51, + COMMA = 52, + WS = 53, + SHELLCOMMENT = 54, + C_COMMENT = 55, + CPP_COMMENT = 56, + NULL_TREE_LOOKAHEAD = 3 + }; +#ifdef __cplusplus +}; +#endif +ANTLR_END_NAMESPACE +#endif /*INC_RequirementParserTokenTypes_hpp_*/ diff --git a/libsecurity_codesigning/lib/RequirementParserTokenTypes.txt b/libsecurity_codesigning/lib/RequirementParserTokenTypes.txt new file mode 100644 index 00000000..5bb59753 --- /dev/null +++ b/libsecurity_codesigning/lib/RequirementParserTokenTypes.txt @@ -0,0 +1,55 @@ +// $ANTLR 2.7.7 (20120228): requirements.grammar -> RequirementParserTokenTypes.txt$ +RequirementParser // output token vocab name +ARROW=4 +LITERAL_guest="guest"=5 +LITERAL_host="host"=6 +LITERAL_designated="designated"=7 +LITERAL_library="library"=8 +LITERAL_plugin="plugin"=9 +INTEGER=10 +LITERAL_or="or"=11 +LITERAL_and="and"=12 +LPAREN=13 +RPAREN=14 +NOT=15 +LITERAL_always="always"=16 +LITERAL_true="true"=17 +LITERAL_never="never"=18 +LITERAL_false="false"=19 +LITERAL_identifier="identifier"=20 +LITERAL_cdhash="cdhash"=21 +LITERAL_anchor="anchor"=22 +LITERAL_apple="apple"=23 +LITERAL_generic="generic"=24 +LITERAL_certificate="certificate"=25 +LITERAL_cert="cert"=26 +LITERAL_trusted="trusted"=27 +LITERAL_info="info"=28 +LITERAL_entitlement="entitlement"=29 +LITERAL_exists="exists"=30 +EQL=31 +EQQL=32 +STAR=33 +SUBS=34 +LESS=35 +GT=36 +LE=37 +GE=38 +LBRACK=39 +RBRACK=40 +NEG=41 +LITERAL_leaf="leaf"=42 +LITERAL_root="root"=43 +HASHCONSTANT=44 +HEXCONSTANT=45 +DOTKEY=46 +STRING=47 +PATHNAME=48 +SEMI=49 +IDENT=50 +HEX=51 +COMMA=52 +WS=53 +SHELLCOMMENT=54 +C_COMMENT=55 +CPP_COMMENT=56 diff --git a/libsecurity_codesigning/lib/Requirements.cpp b/libsecurity_codesigning/lib/Requirements.cpp new file mode 100644 index 00000000..5169f0f9 --- /dev/null +++ b/libsecurity_codesigning/lib/Requirements.cpp @@ -0,0 +1,92 @@ +/* + * 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@ + */ + +// +// Requirements - SecRequirement API objects +// +#include "Requirements.h" + +namespace Security { +namespace CodeSigning { + + +// +// Create from a Requirement blob in memory +// +SecRequirement::SecRequirement(const void *data, size_t length) + : mReq(NULL) +{ + const Requirement *req = (const Requirement *)data; + if (!req->validateBlob(length)) + MacOSError::throwMe(errSecCSReqInvalid); + mReq = req->clone(); +} + + +// +// Create from a genuine Requirement object +// +SecRequirement::SecRequirement(const Requirement *req, bool transferOwnership) + : mReq(NULL) +{ + if (!req->validateBlob()) + MacOSError::throwMe(errSecCSReqInvalid); + + if (transferOwnership) + mReq = req; + else + mReq = req->clone(); +} + + +// +// Clean up a SecRequirement object +// +SecRequirement::~SecRequirement() throw() +try { + ::free((void *)mReq); +} catch (...) { + return; +} + + +// +// CF-level comparison of SecRequirement objects compares the entire requirement +// structure for equality. This means that two requirement programs are recognized +// as equal if they're written identically (modulo comments and syntactic sugar). +// Obviously, equality of outcome is not in the cards. :-) +// +bool SecRequirement::equal(SecCFObject &secOther) +{ + SecRequirement *other = static_cast(&secOther); + return !memcmp(this->requirement(), other->requirement(), this->requirement()->length()); +} + +CFHashCode SecRequirement::hash() +{ + return CFHash(CFTempDataWrap(*this->requirement())); +} + + +} // end namespace CodeSigning +} // end namespace Security diff --git a/libsecurity_codesigning/lib/Requirements.h b/libsecurity_codesigning/lib/Requirements.h new file mode 100644 index 00000000..e2c6ccc7 --- /dev/null +++ b/libsecurity_codesigning/lib/Requirements.h @@ -0,0 +1,64 @@ +/* + * 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@ + */ + +// +// Requirements - SecRequirement API objects +// +#ifndef _H_REQUIREMENTS +#define _H_REQUIREMENTS + +#include "cs.h" +#include "requirement.h" + +namespace Security { +namespace CodeSigning { + + +// +// A SecRequirement object acts as the API representation for a code +// requirement. All its semantics are within the Requirement object it holds. +// The SecRequirement just manages the API appearances. +// +class SecRequirement : public SecCFObject { + NOCOPY(SecRequirement) +public: + SECCFFUNCTIONS(SecRequirement, SecRequirementRef, errSecCSInvalidObjectRef, gCFObjects().Requirement) + + SecRequirement(const void *data, size_t length); + SecRequirement(const Requirement *req, bool transferOwnership = false); + virtual ~SecRequirement() throw(); + + bool equal(SecCFObject &other); + CFHashCode hash(); + + const Requirement *requirement() const { return mReq; } + +private: + const Requirement *mReq; +}; + + +} // end namespace CodeSigning +} // end namespace Security + +#endif // !_H_REQUIREMENTS diff --git a/libsecurity_codesigning/lib/SecAssessment.cpp b/libsecurity_codesigning/lib/SecAssessment.cpp new file mode 100644 index 00000000..7acc660a --- /dev/null +++ b/libsecurity_codesigning/lib/SecAssessment.cpp @@ -0,0 +1,387 @@ +/* + * 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@ + */ +#include "cs.h" +#include "SecAssessment.h" +#include "policydb.h" +#include "policyengine.h" +#include "xpcengine.h" +#include "csutilities.h" +#include +#include +#include +#include +#include + +using namespace CodeSigning; + + +// +// CF Objects +// +struct _SecAssessment : private CFRuntimeBase { +public: + _SecAssessment(CFURLRef p, CFDictionaryRef r) : path(p), result(r) { } + + CFCopyRef path; + CFRef result; + +public: + static _SecAssessment &ref(SecAssessmentRef r) + { return *(_SecAssessment *)r; } + + // CF Boiler-plate + void *operator new (size_t size) + { + return (void *)_CFRuntimeCreateInstance(NULL, SecAssessmentGetTypeID(), + sizeof(_SecAssessment) - sizeof(CFRuntimeBase), NULL); + } + + static void finalize(CFTypeRef obj) + { ((_SecAssessment *)obj)->~_SecAssessment(); } +}; + +typedef _SecAssessment SecAssessment; + + +static const CFRuntimeClass assessmentClass = { + 0, // version + "SecAssessment", // name + NULL, // init + NULL, // copy + SecAssessment::finalize, // finalize + NULL, // equal + NULL, // hash + NULL, // formatting + NULL // debug string +}; + + +static dispatch_once_t assessmentOnce; +CFTypeID assessmentType = _kCFRuntimeNotATypeID; + +CFTypeID SecAssessmentGetTypeID() +{ + + dispatch_once(&assessmentOnce, ^void() { + if ((assessmentType = _CFRuntimeRegisterClass(&assessmentClass)) == _kCFRuntimeNotATypeID) + abort(); + }); + return assessmentType; +} + + +// +// Common dictionary constants +// +CFStringRef kSecAssessmentContextKeyOperation = CFSTR("operation"); +CFStringRef kSecAssessmentOperationTypeExecute = CFSTR("operation:execute"); +CFStringRef kSecAssessmentOperationTypeInstall = CFSTR("operation:install"); +CFStringRef kSecAssessmentOperationTypeOpenDocument = CFSTR("operation:lsopen"); + + +// +// Read-only in-process access to the policy database +// +class ReadPolicy : public PolicyDatabase { +public: + ReadPolicy() : PolicyDatabase(defaultDatabase) { } +}; +ModuleNexus gDatabase; + + +// +// An on-demand instance of the policy engine +// +ModuleNexus gEngine; + + +// +// Policy evaluation ("assessment") operations +// +CFStringRef kSecAssessmentAssessmentVerdict = CFSTR("assessment:verdict"); +CFStringRef kSecAssessmentAssessmentOriginator = CFSTR("assessment:originator"); +CFStringRef kSecAssessmentAssessmentAuthority = CFSTR("assessment:authority"); +CFStringRef kSecAssessmentAssessmentSource = CFSTR("assessment:authority:source"); +CFStringRef kSecAssessmentAssessmentAuthorityRow = CFSTR("assessment:authority:row"); +CFStringRef kSecAssessmentAssessmentAuthorityOverride = CFSTR("assessment:authority:override"); +CFStringRef kSecAssessmentAssessmentFromCache = CFSTR("assessment:authority:cached"); + +CFStringRef kDisabledOverride = CFSTR("security disabled"); + +CFStringRef kSecAssessmentContextKeyCertificates = CFSTR("context:certificates"); // obsolete + +SecAssessmentRef SecAssessmentCreate(CFURLRef path, + SecAssessmentFlags flags, + CFDictionaryRef context, + CFErrorRef *errors) +{ + BEGIN_CSAPI + + if (flags & kSecAssessmentFlagAsynchronous) + MacOSError::throwMe(errSecCSUnimplemented); + + AuthorityType type = typeFor(context, kAuthorityExecute); + CFRef result = makeCFMutableDictionary(); + + SYSPOLICY_ASSESS_API(cfString(path).c_str(), int(type), flags); + + try { + // check the object cache first unless caller denied that or we need extended processing + if (!(flags & (kSecAssessmentFlagRequestOrigin | kSecAssessmentFlagIgnoreCache))) { + if (gDatabase().checkCache(path, type, result)) + return new SecAssessment(path, result.yield()); + } + + if (flags & kSecAssessmentFlagDirect) { + // ask the engine right here to do its thing + SYSPOLICY_ASSESS_LOCAL(); + gEngine().evaluate(path, type, flags, context, result); + } else { + // relay the question to our daemon for consideration + SYSPOLICY_ASSESS_REMOTE(); + xpcEngineAssess(path, flags, context, result); + } + } catch (CommonError &error) { + switch (error.osStatus()) { + case CSSMERR_TP_CERT_REVOKED: + throw; + default: + if (!overrideAssessment()) + throw; // let it go as an error + break; + } + // record the error we would have returned + cfadd(result, "{%O=#F,'assessment:error'=%d}}", kSecAssessmentAssessmentVerdict, error.osStatus()); + } catch (...) { + // catch stray errors not conforming to the CommonError scheme + if (!overrideAssessment()) + throw; // let it go as an error + cfadd(result, "{%O=#F}", kSecAssessmentAssessmentVerdict); + } + return new SecAssessment(path, result.yield()); + + END_CSAPI_ERRORS1(NULL) +} + + +static void traceResult(SecAssessment &assessment, CFDictionaryRef result) +{ + if (CFDictionaryGetValue(result, CFSTR("assessment:remote"))) + return; // just traced in syspolicyd + + CFRef url = CFURLCopyAbsoluteURL(assessment.path); + string sanitized = cfString(url); + string::size_type rslash = sanitized.rfind('/'); + if (rslash != string::npos) + sanitized = sanitized.substr(rslash+1); + string::size_type dot = sanitized.rfind('.'); + if (dot != string::npos) + sanitized = sanitized.substr(dot+1); + else + sanitized = "(none)"; + + string identifier = "UNBUNDLED"; + if (CFRef bundle = CFBundleCreate(NULL, assessment.path)) + if (CFStringRef ident = CFBundleGetIdentifier(bundle)) + identifier = cfString(ident); + + string authority = "UNSPECIFIED"; + bool overridden = false; + if (CFDictionaryRef authdict = CFDictionaryRef(CFDictionaryGetValue(result, kSecAssessmentAssessmentAuthority))) { + if (CFStringRef auth = CFStringRef(CFDictionaryGetValue(authdict, kSecAssessmentAssessmentSource))) + authority = cfString(auth); + else + authority = "no authority"; + if (CFTypeRef override = CFDictionaryGetValue(authdict, kSecAssessmentAssessmentAuthorityOverride)) + if (CFEqual(override, kDisabledOverride)) + overridden = true; + } + + MessageTrace trace("com.apple.security.assessment.outcome", NULL); + trace.add("signature2", "bundle:%s", identifier.c_str()); + if (CFDictionaryGetValue(result, kSecAssessmentAssessmentVerdict) == kCFBooleanFalse) { + trace.add("signature", "denied:%s", authority.c_str()); + trace.add("signature3", sanitized.c_str()); + trace.send("assessment denied for %s", sanitized.c_str()); + } else if (overridden) { + trace.add("signature", "override:%s", authority.c_str()); + trace.add("signature3", sanitized.c_str()); + trace.send("assessment denied for %s but overridden", sanitized.c_str()); + } else { + trace.add("signature", "granted:%s", authority.c_str()); + trace.add("signature3", sanitized.c_str()); + trace.send("assessment granted for %s by %s", sanitized.c_str(), authority.c_str()); + } +} + + +// +// At present, CopyResult simply retrieves the result already formed by Create. +// In the future, this will be more lazy. +// +CFDictionaryRef SecAssessmentCopyResult(SecAssessmentRef assessmentRef, + SecAssessmentFlags flags, + CFErrorRef *errors) +{ + BEGIN_CSAPI + + SecAssessment &assessment = SecAssessment::ref(assessmentRef); + CFCopyRef result = assessment.result; + if (!(flags & kSecAssessmentFlagEnforce) && overrideAssessment()) { + // turn rejections into approvals, but note that we did that + if (CFDictionaryGetValue(result, kSecAssessmentAssessmentVerdict) == kCFBooleanFalse) { + CFRef adulterated = makeCFMutableDictionary(result.get()); + CFDictionarySetValue(adulterated, kSecAssessmentAssessmentVerdict, kCFBooleanTrue); + if (CFDictionaryRef authority = CFDictionaryRef(CFDictionaryGetValue(adulterated, kSecAssessmentAssessmentAuthority))) { + CFRef authority2 = makeCFMutableDictionary(authority); + CFDictionarySetValue(authority2, kSecAssessmentAssessmentAuthorityOverride, kDisabledOverride); + CFDictionarySetValue(adulterated, kSecAssessmentAssessmentAuthority, authority2); + } else { + cfadd(adulterated, "{%O={%O=%O}}", + kSecAssessmentAssessmentAuthority, kSecAssessmentAssessmentAuthorityOverride, kDisabledOverride); + } + result = adulterated.get(); + } + } + traceResult(assessment, result); + return result.yield(); + + END_CSAPI_ERRORS1(NULL) +} + + +// +// Policy editing operations. +// These all make permanent changes to the system-wide authority records. +// +CFStringRef kSecAssessmentContextKeyUpdate = CFSTR("update"); +CFStringRef kSecAssessmentUpdateOperationAdd = CFSTR("update:add"); +CFStringRef kSecAssessmentUpdateOperationRemove = CFSTR("update:remove"); +CFStringRef kSecAssessmentUpdateOperationEnable = CFSTR("update:enable"); +CFStringRef kSecAssessmentUpdateOperationDisable = CFSTR("update:disable"); +CFStringRef kSecAssessmentUpdateOperationFind = CFSTR("update:find"); + +CFStringRef kSecAssessmentUpdateKeyAuthorization = CFSTR("update:authorization"); +CFStringRef kSecAssessmentUpdateKeyPriority = CFSTR("update:priority"); +CFStringRef kSecAssessmentUpdateKeyLabel = CFSTR("update:label"); +CFStringRef kSecAssessmentUpdateKeyExpires = CFSTR("update:expires"); +CFStringRef kSecAssessmentUpdateKeyAllow = CFSTR("update:allow"); +CFStringRef kSecAssessmentUpdateKeyRemarks = CFSTR("update:remarks"); + +CFStringRef kSecAssessmentUpdateKeyRow = CFSTR("update:row"); +CFStringRef kSecAssessmentUpdateKeyCount = CFSTR("update:count"); +CFStringRef kSecAssessmentUpdateKeyFound = CFSTR("update:found"); + +CFStringRef kSecAssessmentRuleKeyID = CFSTR("rule:id"); +CFStringRef kSecAssessmentRuleKeyPriority = CFSTR("rule:priority"); +CFStringRef kSecAssessmentRuleKeyAllow = CFSTR("rule:allow"); +CFStringRef kSecAssessmentRuleKeyLabel = CFSTR("rule:label"); +CFStringRef kSecAssessmentRuleKeyRemarks = CFSTR("rule:remarks"); +CFStringRef kSecAssessmentRuleKeyRequirement = CFSTR("rule:requirement"); +CFStringRef kSecAssessmentRuleKeyType = CFSTR("rule:type"); +CFStringRef kSecAssessmentRuleKeyExpires = CFSTR("rule:expires"); +CFStringRef kSecAssessmentRuleKeyDisabled = CFSTR("rule:disabled"); +CFStringRef kSecAssessmentRuleKeyBookmark = CFSTR("rule:bookmark"); + + +Boolean SecAssessmentUpdate(CFTypeRef target, + SecAssessmentFlags flags, + CFDictionaryRef context, + CFErrorRef *errors) +{ + if (CFDictionaryRef outcome = SecAssessmentCopyUpdate(target, flags, context, errors)) { + CFRelease(outcome); + return true; + } else { + return false; + } +} + +CFDictionaryRef SecAssessmentCopyUpdate(CFTypeRef target, + SecAssessmentFlags flags, + CFDictionaryRef context, + CFErrorRef *errors) +{ + BEGIN_CSAPI + + CFDictionary ctx(context, errSecCSInvalidAttributeValues); + + if (flags & kSecAssessmentFlagDirect) { + // ask the engine right here to do its thing + return gEngine().update(target, flags, ctx); + } else { + // relay the question to our daemon for consideration + return xpcEngineUpdate(target, flags, ctx); + } + + END_CSAPI_ERRORS1(false) +} + + +// +// The fcntl of System Policies. +// For those very special requests. +// +Boolean SecAssessmentControl(CFStringRef control, void *arguments, CFErrorRef *errors) +{ + BEGIN_CSAPI + + if (CFEqual(control, CFSTR("ui-enable"))) { + setAssessment(true); + MessageTrace trace("com.apple.security.assessment.state", "enable"); + trace.send("enable assessment outcomes"); + return true; + } else if (CFEqual(control, CFSTR("ui-disable"))) { + setAssessment(false); + MessageTrace trace("com.apple.security.assessment.state", "disable"); + trace.send("disable assessment outcomes"); + return true; + } else if (CFEqual(control, CFSTR("ui-status"))) { + CFBooleanRef &result = *(CFBooleanRef*)(arguments); + if (overrideAssessment()) + result = kCFBooleanFalse; + else + result = kCFBooleanTrue; + return true; + } else if (CFEqual(control, CFSTR("ui-enable-devid"))) { + CFTemp ctx("{%O=%s}", kSecAssessmentUpdateKeyLabel, "Developer ID"); + if (CFDictionaryRef result = gEngine().enable(NULL, kAuthorityInvalid, kSecCSDefaultFlags, ctx)) + CFRelease(result); + return true; + } else if (CFEqual(control, CFSTR("ui-disable-devid"))) { + CFTemp ctx("{%O=%s}", kSecAssessmentUpdateKeyLabel, "Developer ID"); + if (CFDictionaryRef result = gEngine().disable(NULL, kAuthorityInvalid, kSecCSDefaultFlags, ctx)) + CFRelease(result); + return true; + } else if (CFEqual(control, CFSTR("ui-get-devid"))) { + CFBooleanRef &result = *(CFBooleanRef*)(arguments); + if (gEngine().value("SELECT disabled FROM authority WHERE label = 'Developer ID';", true)) + result = kCFBooleanFalse; + else + result = kCFBooleanTrue; + return true; + } else + MacOSError::throwMe(errSecCSInvalidAttributeValues); + + END_CSAPI_ERRORS1(false) +} diff --git a/libsecurity_codesigning/lib/SecAssessment.h b/libsecurity_codesigning/lib/SecAssessment.h new file mode 100644 index 00000000..96665816 --- /dev/null +++ b/libsecurity_codesigning/lib/SecAssessment.h @@ -0,0 +1,296 @@ +/* + * 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@ + */ +#ifndef _H_SECASSESSMENT +#define _H_SECASSESSMENT + +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +/*! + * @type SecAccessmentRef An assessment being performed. + */ +typedef struct _SecAssessment *SecAssessmentRef; + + +/*! + * CF-standard type function + */ +CFTypeID SecAssessmentGetTypeID(); + + +/* + * Notifications sent when the policy authority database changes. + * (Should move to /usr/include/notify_keys.h eventually.) + */ +#define kNotifySecAssessmentMasterSwitch "com.apple.security.assessment.masterswitch" +#define kNotifySecAssessmentUpdate "com.apple.security.assessment.update" + + +/*! + * Primary operation types. These are operations the system policy can express + * opinions on. They are not operations *on* the system configuration itself. + * (For those, see SecAssessmentUpdate below.) + * + * @constant kSecAssessmentContextKeyOperation Context key describing the type of operation + * being contemplated. The default varies depending on the API call used. + * @constant kSecAssessmentOperationTypeExecute Value denoting the operation of running or executing + * code on the system. + * @constant kSecAssessmentOperationTypeInstall Value denoting the operation of installing + * software into the system. + * @constant kSecAssessmentOperationTypeOpenDocument Value denoting the operation of opening + * (in the LaunchServices sense) of documents. + */ +extern CFStringRef kSecAssessmentContextKeyOperation; // proposed operation +extern CFStringRef kSecAssessmentOperationTypeExecute; // .. execute code +extern CFStringRef kSecAssessmentOperationTypeInstall; // .. install software +extern CFStringRef kSecAssessmentOperationTypeOpenDocument; // .. LaunchServices-level document open + + +/*! + Operational flags for SecAssessment calls + + @type SecAssessmentFlags A mask of flag bits passed to SecAssessment calls to influence their + operation. + + @constant kSecAssessmentDefaultFlags Pass this to indicate that default behavior is desired. + @constant kSecAssessmentFlagIgnoreCache Do not use cached information; always perform a full + evaluation of system policy. This may be substantially slower. + @constant kSecAssessmentFlagNoCache Do not save any evaluation outcome in the system caches. + Any content already there is left undisturbed. Independent of kSecAssessmentFlagIgnoreCache. + @constant kSecAssessmentFlagEnforce Perform normal operations even if assessments have been + globally bypassed (which would usually approve anything). + + Flags common to multiple calls are assigned from high-bit down. Flags for particular calls + are assigned low-bit up, and are documented with that call. + */ +typedef uint64_t SecAssessmentFlags; +enum { + kSecAssessmentDefaultFlags = 0, // default behavior + + kSecAssessmentFlagDirect = 1 << 30, // in-process evaluation + kSecAssessmentFlagAsynchronous = 1 << 29, // request asynchronous operation + kSecAssessmentFlagIgnoreCache = 1 << 28, // do not search cache + kSecAssessmentFlagNoCache = 1 << 27, // do not populate cache + kSecAssessmentFlagEnforce = 1 << 26, // force on (disable bypass switches) +}; + + +/*! + @function SecAssessmentCreate + Ask the system for its assessment of a proposed operation. + + @param path CFURL describing the file central to the operation - the program + to be executed, archive to be installed, plugin to be loaded, etc. + @param flags Operation flags and options. Pass kSecAssessmentDefaultFlags for default + behavior. + @param context Optional CFDictionaryRef containing additional information bearing + on the requested assessment. + @param errors Standard CFError argument for reporting errors. Note that declining to permit + the proposed operation is not an error. Inability to arrive at a judgment is. + @result On success, a SecAssessment object that can be queried for its outcome. + On error, NULL (with *errors set). + + Option flags: + + @constant kSecAssessmentFlagRequestOrigin Request additional work to produce information on + the originator (signer) of the object being discussed. + + Context keys: + + @constant kSecAssessmentContextKeyOperation Type of operation (see overview above). This defaults + to the kSecAssessmentOperationTypeExecute. + */ +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 +extern CFStringRef kSecAssessmentAssessmentSource; // CFStringRef: primary source of authority +extern CFStringRef kSecAssessmentAssessmentFromCache; // present if result is from cache +extern CFStringRef kSecAssessmentAssessmentAuthorityRow; // (internal) +extern CFStringRef kSecAssessmentAssessmentAuthorityOverride; // (internal) + +extern CFStringRef kDisabledOverride; // AuthorityOverride value for "Gatekeeper is disabled" + +enum { + kSecAssessmentFlagRequestOrigin = 1 << 0, // request origin information (slower) +}; + +SecAssessmentRef SecAssessmentCreate(CFURLRef path, + SecAssessmentFlags flags, + CFDictionaryRef context, + CFErrorRef *errors); + + +/*! + @function SecAssessmentCopyResult + + Extract results from a completed assessment and return them as a CFDictionary. + + @param assessment A SecAssessmentRef created with SecAssessmentCreate. + @param flags Operation flags and options. Pass kSecAssessmentDefaultFlags for default + behavior. + @errors Standard CFError argument for reporting errors. Note that declining to permit + the proposed operation is not an error. Inability to form a judgment is. + @result On success, a CFDictionary describing the outcome and various corroborating + data as requested by flags. The caller owns this dictionary and should release it + when done with it. On error, NULL (with *errors set). + + Assessment result keys (dictionary keys returned on success): + + @constant kSecAssessmentAssessmentVerdict A CFBoolean value indicating whether the system policy + allows (kCFBooleanTrue) or denies (kCFBooleanFalse) the proposed operation. + @constant kSecAssessmentAssessmentAuthority A CFDictionary describing what sources of authority + were used to arrive at this result. + @constant kSecAssessmentAssessmentOriginator A human-readable CFString describing the originator + of the signature securing the subject of the verdict. Requires kSecAssessmentFlagRequireOrigin. + May be missing anyway if no reliable source of origin can be determined. + */ +CFDictionaryRef SecAssessmentCopyResult(SecAssessmentRef assessment, + SecAssessmentFlags flags, + CFErrorRef *errors); + + +/*! + @function SecAssessmentCopyUpdate + Make changes to the system policy configuration. + + @param path CFTypeRef describing the subject of the operation. Depending on the operation, + this may be a CFURL denoting a (single) file or bundle; a SecRequirement describing + a group of files; a CFNumber denoting an existing rule by rule number, or NULL to perform + global changes. + @param flags Operation flags and options. Pass kSecAssessmentDefaultFlags for default + behavior. + @param context Required CFDictionaryRef containing information bearing + on the requested assessment. Must at least contain the kSecAssessmentContextKeyEdit key. + @param errors Standard CFError argument for reporting errors. Note that declining to permit + the proposed operation is not an error. Inability to form a judgment is. + @result Returns On success, a CFDictionary containing information pertaining to the completed operation. + Caller must CFRelease it when done. On failure, NULL, with *errors set if provided. + + Note: The SecAssessmentUpdate variant does not return data. It returns True on success, or False on error. + + Context keys and values: + + @constant kSecAssessmentContextKeyEdit Required context key describing the kind of change + requested to the system policy configuration. Currently understood values: + @constant kSecAssessmentUpdateOperationAdd Add a new rule to the assessment rule database. + @constant kSecAssessmentUpdateOperationRemove Remove rules from the rule database. + @constant kSecAssessmentUpdateOperationEnable (Re)enable rules in the rule database. + @constant kSecAssessmentUpdateOperationDisable Disable rules in the rule database. + @constant kSecAssessmentUpdateOperationFind Locate and return rules from the rule database. + This operation does not change the database, and does not require authorization or privileges. + + @constant kSecAssessmentUpdateKeyAuthorization A CFData containing the external form of a + system AuthorizationRef used to authorize the change. The call will automatically generate + a suitable authorization if this is missing; however, if the request is on behalf of + another client, an AuthorizationRef should be created there and passed along here. + @constant kSecAssessmentUpdateKeyPriority CFNumber denoting a (floating point) priority + for the rule(s) being processed. + @constant kSecAssessmentUpdateKeyLabel CFString denoting a label string applied to the rule(s) + being processed. + @constant kSecAssessmentUpdateKeyExpires CFDate denoting an (absolute, future) expiration date + for rule(s) being processed. + @constant kSecAssessmentUpdateKeyAllow CFBoolean denoting whether a new rule allows or denies + assessment. The default is to allow; set to kCFBooleanFalse to create a negative (denial) rule. + @constant kSecAssessmentUpdateKeyRemarks CFString containing a colloquial description or comment + about a newly created rule. This is mean to be human readable and is not used when evaluating rules. + + Keys returned as the result of a successful kSecAssessmentUpdateOperationFind operation: + + @constant kSecAssessmentRuleKeyID A CFNumber uniquely identifying a rule. + @constant kSecAssessmentRuleKeyPriority A CFNumber indicating the rule's priority. + This is a floating point number. Higher values indicate higher priority. + @constant kSecAssessmentRuleKeyAllow A CFBoolean indicating whether the rule allows (true) or denies (false) the operation. + @constant kSecAssessmentRuleKeyLabel An optional CFString labeling the rule. Multiple rules may have the same label; + this can be used to group rules. Labels are not presented to the user. The label has no effect on evaluation. + @constant kSecAssessmentRuleKeyRemarks An optional CFString containing user-readable text characterizing the rule's meaning. + The remark has no effect on the evaluation. + @constant kSecAssessmentRuleKeyRequirement A CFString containing the (text form of) the code requirement governing the rule's match. + @constant kSecAssessmentRuleKeyType A CFString denoting the type of operation governed by the rule. + One of the kSecAssessmentOperationType* constants. + @constant kSecAssessmentRuleKeyExpires A CFDate indicating when the rule expires. Absent if the rule does not expire. Expired rules are never returned. + @constant kSecAssessmentRuleKeyDisabled A CFNumber; non zero if temporarily disabled. Optional. + @constant kSecAssessmentRuleKeyBookmark A CFData with the bookmark to the rule. Optional. + */ +extern CFStringRef kSecAssessmentContextKeyUpdate; // proposed operation +extern CFStringRef kSecAssessmentUpdateOperationAdd; // add rule to policy database +extern CFStringRef kSecAssessmentUpdateOperationRemove; // remove rule from policy database +extern CFStringRef kSecAssessmentUpdateOperationEnable; // enable rule(s) in policy database +extern CFStringRef kSecAssessmentUpdateOperationDisable; // disable rule(s) in policy database +extern CFStringRef kSecAssessmentUpdateOperationFind; // extract rule(s) from the policy database + +extern CFStringRef kSecAssessmentContextKeyCertificates; // obsolete +extern CFStringRef kSecAssessmentUpdateKeyAuthorization; // [CFData] external form of governing authorization + +extern CFStringRef kSecAssessmentUpdateKeyPriority; // rule priority +extern CFStringRef kSecAssessmentUpdateKeyLabel; // rule label +extern CFStringRef kSecAssessmentUpdateKeyExpires; // rule expiration +extern CFStringRef kSecAssessmentUpdateKeyAllow; // rule outcome (allow/deny) +extern CFStringRef kSecAssessmentUpdateKeyRemarks; // rule remarks (human readable) + +extern CFStringRef kSecAssessmentUpdateKeyRow; // rule identifier (CFNumber; add only) +extern CFStringRef kSecAssessmentUpdateKeyCount; // count of changed rules (CFNumber) +extern CFStringRef kSecAssessmentUpdateKeyFound; // set of found rules (CFArray of CFDictionaries) + +extern CFStringRef kSecAssessmentRuleKeyID; // rule content returned: rule ID +extern CFStringRef kSecAssessmentRuleKeyPriority; // rule content returned: rule priority (floating point) +extern CFStringRef kSecAssessmentRuleKeyAllow; // rule content returned: rule allows (boolean) +extern CFStringRef kSecAssessmentRuleKeyLabel; // rule content returned: rule label (string; optional) +extern CFStringRef kSecAssessmentRuleKeyRemarks; // rule content returned: rule remarks (string; optional) +extern CFStringRef kSecAssessmentRuleKeyRequirement; // rule content returned: rule code requirement (string) +extern CFStringRef kSecAssessmentRuleKeyType; // rule content returned: rule type (string) +extern CFStringRef kSecAssessmentRuleKeyExpires; // rule content returned: rule expiration (CFDate; optional) +extern CFStringRef kSecAssessmentRuleKeyDisabled; // rule content returned: rule disabled (CFNumber; nonzero means temporarily disabled) +extern CFStringRef kSecAssessmentRuleKeyBookmark; // rule content returned: bookmark data (CFBookmark; optional) + +CFDictionaryRef SecAssessmentCopyUpdate(CFTypeRef target, + SecAssessmentFlags flags, + CFDictionaryRef context, + CFErrorRef *errors); + +Boolean SecAssessmentUpdate(CFTypeRef target, + SecAssessmentFlags flags, + CFDictionaryRef context, + CFErrorRef *errors); + + +/*! + @function SecAssessmentControl + Miscellaneous system policy operations. + + @param control A CFString indicating which operation is requested. + @param arguments Arguments to the operation as documented for control. + @param errors Standard CFErrorRef * argument to report errors. + @result Returns True on success. Returns False on failure (and sets *errors). + */ +Boolean SecAssessmentControl(CFStringRef control, void *arguments, CFErrorRef *errors); + + +#ifdef __cplusplus +} +#endif + +#endif //_H_SECASSESSMENT diff --git a/libsecurity_codesigning/lib/SecCode.cpp b/libsecurity_codesigning/lib/SecCode.cpp new file mode 100644 index 00000000..f5b300f6 --- /dev/null +++ b/libsecurity_codesigning/lib/SecCode.cpp @@ -0,0 +1,268 @@ +/* + * 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@ + */ + +// +// SecCode - API frame for SecCode objects. +// +// Note that some SecCode* functions take SecStaticCodeRef arguments in order to +// accept either static or dynamic code references, operating on the respective +// StaticCode. Those functions are in SecStaticCode.cpp, not here, despite their name. +// +#include "cs.h" +#include "Code.h" +#include "cskernel.h" +#include + +using namespace CodeSigning; + + +// +// CFError user info keys +// +const CFStringRef kSecCFErrorArchitecture = CFSTR("SecCSArchitecture"); +const CFStringRef kSecCFErrorPattern = CFSTR("SecCSPattern"); +const CFStringRef kSecCFErrorResourceSeal = CFSTR("SecCSResourceSeal"); +const CFStringRef kSecCFErrorResourceAdded = CFSTR("SecCSResourceAdded"); +const CFStringRef kSecCFErrorResourceAltered = CFSTR("SecCSResourceAltered"); +const CFStringRef kSecCFErrorResourceMissing = CFSTR("SecCSResourceMissing"); +const CFStringRef kSecCFErrorInfoPlist = CFSTR("SecCSInfoPlist"); +const CFStringRef kSecCFErrorGuestAttributes = CFSTR("SecCSGuestAttributes"); +const CFStringRef kSecCFErrorRequirementSyntax = CFSTR("SecRequirementSyntax"); +const CFStringRef kSecCFErrorPath = CFSTR("SecComponentPath"); + + +// +// CF-standard type code functions +// +CFTypeID SecCodeGetTypeID(void) +{ + BEGIN_CSAPI + return gCFObjects().Code.typeID; + END_CSAPI1(_kCFRuntimeNotATypeID) +} + + +// +// Get a reference to the calling code. +// +OSStatus SecCodeCopySelf(SecCSFlags flags, SecCodeRef *selfRef) +{ + BEGIN_CSAPI + + checkFlags(flags); + CFRef attributes = makeCFMutableDictionary(1, + kSecGuestAttributePid, CFTempNumber(getpid()).get()); + CodeSigning::Required(selfRef) = SecCode::autoLocateGuest(attributes, flags)->handle(false); + + END_CSAPI +} + + +// +// Get the dynamic status of a code. +// +OSStatus SecCodeGetStatus(SecCodeRef codeRef, SecCSFlags flags, SecCodeStatus *status) +{ + BEGIN_CSAPI + + checkFlags(flags); + CodeSigning::Required(status) = SecCode::required(codeRef)->status(); + + END_CSAPI +} + + +// +// Change the dynamic status of a code +// +OSStatus SecCodeSetStatus(SecCodeRef codeRef, SecCodeStatusOperation operation, + CFDictionaryRef arguments, SecCSFlags flags) +{ + BEGIN_CSAPI + + checkFlags(flags); + SecCode::required(codeRef)->status(operation, arguments); + + END_CSAPI +} + + +// +// Get the StaticCode for an Code +// +OSStatus SecCodeCopyStaticCode(SecCodeRef codeRef, SecCSFlags flags, SecStaticCodeRef *staticCodeRef) +{ + BEGIN_CSAPI + + checkFlags(flags); + SecPointer staticCode = SecCode::required(codeRef)->staticCode(); + CodeSigning::Required(staticCodeRef) = staticCode ? staticCode->handle() : NULL; + + END_CSAPI +} + + +// +// Get the host for an Code +// +OSStatus SecCodeCopyHost(SecCodeRef guestRef, SecCSFlags flags, SecCodeRef *hostRef) +{ + BEGIN_CSAPI + + checkFlags(flags); + SecPointer host = SecCode::required(guestRef)->host(); + CodeSigning::Required(hostRef) = host ? host->handle() : NULL; + + END_CSAPI +} + + +// +// Find a guest by attribute(s) +// +const CFStringRef kSecGuestAttributeCanonical = CFSTR("canonical"); +const CFStringRef kSecGuestAttributeHash = CFSTR("codedirectory-hash"); +const CFStringRef kSecGuestAttributeMachPort = CFSTR("mach-port"); +const CFStringRef kSecGuestAttributePid = CFSTR("pid"); +const CFStringRef kSecGuestAttributeArchitecture = CFSTR("architecture"); +const CFStringRef kSecGuestAttributeSubarchitecture = CFSTR("subarchitecture"); + +OSStatus SecCodeCopyGuestWithAttributes(SecCodeRef hostRef, + CFDictionaryRef attributes, SecCSFlags flags, SecCodeRef *guestRef) +{ + BEGIN_CSAPI + + checkFlags(flags); + if (hostRef) { + if (SecCode *guest = SecCode::required(hostRef)->locateGuest(attributes)) + CodeSigning::Required(guestRef) = guest->handle(false); + else + return errSecCSNoSuchCode; + } else + CodeSigning::Required(guestRef) = SecCode::autoLocateGuest(attributes, flags)->handle(false); + + END_CSAPI +} + + +// +// Shorthand for getting the SecCodeRef for a UNIX process +// +OSStatus SecCodeCreateWithPID(pid_t pid, SecCSFlags flags, SecCodeRef *processRef) +{ + BEGIN_CSAPI + + checkFlags(flags); + if (SecCode *guest = KernelCode::active()->locateGuest(CFTemp("{%O=%d}", kSecGuestAttributePid, pid))) + CodeSigning::Required(processRef) = guest->handle(false); + else + return errSecCSNoSuchCode; + + END_CSAPI +} + + +// +// Check validity of an Code +// +OSStatus SecCodeCheckValidity(SecCodeRef codeRef, SecCSFlags flags, + SecRequirementRef requirementRef) +{ + return SecCodeCheckValidityWithErrors(codeRef, flags, requirementRef, NULL); +} + +OSStatus SecCodeCheckValidityWithErrors(SecCodeRef codeRef, SecCSFlags flags, + SecRequirementRef requirementRef, CFErrorRef *errors) +{ + BEGIN_CSAPI + + checkFlags(flags, + kSecCSConsiderExpiration + | kSecCSEnforceRevocationChecks); + SecPointer code = SecCode::required(codeRef); + code->checkValidity(flags); + if (const SecRequirement *req = SecRequirement::optional(requirementRef)) + code->staticCode()->validateRequirement(req->requirement(), errSecCSReqFailed); + + END_CSAPI_ERRORS +} + + +// +// Collect suitably laundered information about the code signature of a SecStaticCode +// and return it as a CFDictionary. +// +// This API contracts to return a few pieces of information even for unsigned +// code. This means that a SecStaticCodeRef is usable as a basic indentifier +// (i.e. handle) for any code out there. +// +const CFStringRef kSecCodeInfoCertificates = CFSTR("certificates"); +const CFStringRef kSecCodeInfoChangedFiles = CFSTR("changed-files"); +const CFStringRef kSecCodeInfoCMS = CFSTR("cms"); +const CFStringRef kSecCodeInfoDesignatedRequirement = CFSTR("designated-requirement"); +const CFStringRef kSecCodeInfoEntitlements = CFSTR("entitlements"); +const CFStringRef kSecCodeInfoEntitlementsDict = CFSTR("entitlements-dict"); +const CFStringRef kSecCodeInfoFormat = CFSTR("format"); +const CFStringRef kSecCodeInfoDigestAlgorithm = CFSTR("digest-algorithm"); +const CFStringRef kSecCodeInfoIdentifier = CFSTR("identifier"); +const CFStringRef kSecCodeInfoImplicitDesignatedRequirement = CFSTR("implicit-requirement"); +const CFStringRef kSecCodeInfoMainExecutable = CFSTR("main-executable"); +const CFStringRef kSecCodeInfoPList = CFSTR("info-plist"); +const CFStringRef kSecCodeInfoRequirements = CFSTR("requirements"); +const CFStringRef kSecCodeInfoRequirementData = CFSTR("requirement-data"); +const CFStringRef kSecCodeInfoSource = CFSTR("source"); +const CFStringRef kSecCodeInfoStatus = CFSTR("status"); +const CFStringRef kSecCodeInfoTime = CFSTR("signing-time"); +const CFStringRef kSecCodeInfoTimestamp = CFSTR("signing-timestamp"); +const CFStringRef kSecCodeInfoTrust = CFSTR("trust"); +const CFStringRef kSecCodeInfoUnique = CFSTR("unique"); + +const CFStringRef kSecCodeInfoCodeDirectory = CFSTR("CodeDirectory"); +const CFStringRef kSecCodeInfoCodeOffset = CFSTR("CodeOffset"); +const CFStringRef kSecCodeInfoResourceDirectory = CFSTR("ResourceDirectory"); + + +OSStatus SecCodeCopySigningInformation(SecStaticCodeRef codeRef, SecCSFlags flags, + CFDictionaryRef *infoRef) +{ + BEGIN_CSAPI + + checkFlags(flags, + kSecCSInternalInformation + | kSecCSSigningInformation + | kSecCSRequirementInformation + | kSecCSDynamicInformation + | kSecCSContentInformation); + + SecPointer code = SecStaticCode::requiredStatic(codeRef); + CFRef info = code->signingInformation(flags); + + if (flags & kSecCSDynamicInformation) + if (SecPointer dcode = SecStaticCode::optionalDynamic(codeRef)) + info.take(cfmake("{+%O,%O=%u}", info.get(), kSecCodeInfoStatus, dcode->status())); + + CodeSigning::Required(infoRef) = info.yield(); + + END_CSAPI +} + diff --git a/libsecurity_codesigning/lib/SecCode.h b/libsecurity_codesigning/lib/SecCode.h new file mode 100644 index 00000000..4ae85d90 --- /dev/null +++ b/libsecurity_codesigning/lib/SecCode.h @@ -0,0 +1,431 @@ +/* + * 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 SecCode + SecCode represents separately indentified running code in the system. + In addition to UNIX processes, this can also include (with suitable support) + scripts, applets, widgets, etc. +*/ +#ifndef _H_SECCODE +#define _H_SECCODE + +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +/*! + @function SecCodeGetTypeID + Returns the type identifier of all SecCode instances. +*/ +CFTypeID SecCodeGetTypeID(void); + + +/*! + @function SecCodeCopySelf + Obtains a SecCode object for the code making the call. + The calling code is determined in a way that is subject to modification over + time, but obeys the following rules. If it is a UNIX process, its process id (pid) + is always used. If it is an active code host that has a dedicated guest, such a guest + is always preferred. If it is a host that has called SecHostSelectGuest, such selection + is considered until revoked. + + @param flags Optional flags. Pass kSecCSDefaultFlags for standard behavior. + @param self Upon successful return, contains a SecCodeRef representing the caller. + + @result Upon success, noErr. Upon error, an OSStatus value documented in + CSCommon.h or certain other Security framework headers. + */ +OSStatus SecCodeCopySelf(SecCSFlags flags, SecCodeRef *self); + + +/*! + @function SecCodeCopyStaticCode + Given a SecCode object, locate its origin in the file system and return + a SecStaticCode object representing it. + + The link established by this call is generally reliable but is NOT guaranteed + to be secure. + + Many API functions taking SecStaticCodeRef arguments will also directly + accept a SecCodeRef and apply this translation implicitly, operating on + its result or returning its error code if any. Each of these functions + calls out that behavior in its documentation. + + If the code was obtained from a universal (aka "fat") program file, + the resulting SecStaticCodeRef will refer only to the architecture actually + being used. This means that multiple running codes started from the same file + may conceivably result in different static code references if they ended up + using different execution architectures. (This is unusual but possible.) + + @param code A valid SecCode object reference representing code running + on the system. + @param flags Optional flags. Pass kSecCSDefaultFlags for standard behavior. + @param staticCode On successful return, a SecStaticCode object reference representing + the file system origin of the given SecCode. On error, unchanged. + @result Upon success, noErr. Upon error, an OSStatus value documented in + CSCommon.h or certain other Security framework headers. +*/ +OSStatus SecCodeCopyStaticCode(SecCodeRef code, SecCSFlags flags, SecStaticCodeRef *staticCode); + + +/*! + @function SecCodeCopyHost + Given a SecCode object, identify the (different) SecCode object that acts + as its host. A SecCode's host acts as a supervisor and controller, + and is the ultimate authority on the its dynamic validity and status. + The host relationship is securely established (absent reported errors). + + @param code A valid SecCode object reference representing code running + on the system. + @param flags Optional flags. Pass kSecCSDefaultFlags for standard behavior. + @param host On successful return, a SecCode object reference identifying + the code's host. + @result Upon success, noErr. Upon error, an OSStatus value documented in + CSCommon.h or certain other Security framework headers. +*/ +OSStatus SecCodeCopyHost(SecCodeRef guest, SecCSFlags flags, SecCodeRef *host); + + +/*! + @function SecCodeCopyGuestWithAttributes + This is the omnibus API function for obtaining dynamic code references. + In general, it asks a particular code acting as a code host to locate + and return a guest with given attributes. Different hosts support + different combinations of attributes and values for guest selection. + + Asking the NULL host invokes system default procedures for obtaining + any running code in the system with the attributes given. The returned + code may be anywhere in the system. + + The methods a host uses to identify, separate, and control its guests + are specific to each type of host. This call provides a generic abstraction layer + that allows uniform interrogation of all hosts. A SecCode that does not + act as a host will always return errSecCSNoSuchCode. A SecCode that does + support hosting may return itself to signify that the attribute refers to + itself rather than one of its hosts. + + @param host A valid SecCode object reference representing code running + on the system that acts as a Code Signing host. As a special case, passing + NULL indicates that the Code Signing root of trust should be used as a starting + point. Currently, that is the system kernel. + @param attributes A CFDictionary containing zero or more attribute selector + values. Each selector has a CFString key and associated CFTypeRef value. + The key name identifies the attribute being specified; the associated value, + whose type depends on the the key name, selects a particular value or other + constraint on that attribute. Each host only supports particular combinations + of keys and values, and errors will be returned if any unsupported set is requested. + As a special case, NULL is taken to mean an empty attribute set. + Note that some hosts that support hosting chains (guests being hosts) + may return sub-guests in this call. In other words, do not assume that + a SecCodeRef returned by this call is a direct guest of the queried host + (though it will be a proximate guest, i.e. a guest's guest some way down). + Asking the NULL host for NULL attributes returns a code reference for the system root + of trust (at present, the running Darwin kernel). + @param flags Optional flags. Pass kSecCSDefaultFlags for standard behavior. + @param guest On successful return, a SecCode object reference identifying + the particular guest of the host that owns the attribute value(s) specified. + This argument will not be changed if the call fails (does not return noErr). + @result Upon success, noErr. Upon error, an OSStatus value documented in + CSCommon.h or certain other Security framework headers. In particular: + @error errSecCSUnsupportedGuestAttributes The host does not support the attribute + type given by attributeType. + @error errSecCSInvalidAttributeValues The type of value given for a guest + attribute is not supported by the host. + @error errSecCSNoSuchCode The host has no guest with the attribute value given + by attributeValue, even though the value is of a supported type. This may also + be returned if the host code does not currently act as a Code Signing host. + @error errSecCSNotAHost The specified host cannot, in fact, act as a code + host. (It is missing the kSecCodeSignatureHost option flag in its code + signature.) + @error errSecCSMultipleGuests The attributes specified do not uniquely identify + a guest (the specification is ambiguous). +*/ +extern const CFStringRef kSecGuestAttributeCanonical; +extern const CFStringRef kSecGuestAttributeHash; +extern const CFStringRef kSecGuestAttributeMachPort; +extern const CFStringRef kSecGuestAttributePid; +extern const CFStringRef kSecGuestAttributeArchitecture; +extern const CFStringRef kSecGuestAttributeSubarchitecture; + +OSStatus SecCodeCopyGuestWithAttributes(SecCodeRef host, + CFDictionaryRef attributes, SecCSFlags flags, SecCodeRef *guest); + + +/*! + @function SecCodeCheckValidity + Performs dynamic validation of the given SecCode object. The call obtains and + verifies the signature on the code object. It checks the validity of only those + sealed components required to establish identity. It checks the SecCode's + dynamic validity status as reported by its host. It ensures that the SecCode's + host is in turn valid. Finally, it validates the code against a SecRequirement + if one is given. The call succeeds if all these conditions are satisfactory. + It fails otherwise. + + This call is secure against attempts to modify the file system source of the + SecCode. + + @param code The code object to be validated. + @param flags Optional flags. Pass kSecCSDefaultFlags for standard behavior. + @param requirement An optional code requirement specifying additional conditions + the code object must satisfy to be considered valid. If NULL, no additional + requirements are imposed. + @param errors An optional pointer to a CFErrorRef variable. If the call fails + (and something other than noErr is returned), and this argument is non-NULL, + a CFErrorRef is stored there further describing the nature and circumstances + of the failure. The caller must CFRelease() this error object when done with it. + @result If validation passes, noErr. If validation fails, an OSStatus value + documented in CSCommon.h or certain other Security framework headers. +*/ +OSStatus SecCodeCheckValidity(SecCodeRef code, SecCSFlags flags, + SecRequirementRef requirement); + +OSStatus SecCodeCheckValidityWithErrors(SecCodeRef code, SecCSFlags flags, + SecRequirementRef requirement, CFErrorRef *errors); + + +/*! + @function SecCodeCopyPath + For a given Code or StaticCode object, returns a URL to a location on disk where the + code object can be found. For single files, the URL points to that file. + For bundles, it points to the directory containing the entire bundle. + + This returns the same URL as the kSecCodeInfoMainExecutable key returned + by SecCodeCopySigningInformation. + + @param code The Code or StaticCode object to be located. For a Code + argument, its StaticCode is processed as per SecCodeCopyStaticCode. + @param flags Optional flags. Pass kSecCSDefaultFlags for standard behavior. + @param path On successful return, contains a CFURL identifying the location + on disk of the staticCode object. + @result On success, noErr. On error, an OSStatus value + documented in CSCommon.h or certain other Security framework headers. +*/ +OSStatus SecCodeCopyPath(SecStaticCodeRef staticCode, SecCSFlags flags, + CFURLRef *path); + + +/*! + @function SecCodeCopyDesignatedRequirement + For a given Code or StaticCode object, determines its Designated Code Requirement. + The Designated Requirement is the SecRequirement that the code believes + should be used to properly identify it in the future. + + If the SecCode contains an explicit Designated Requirement, a copy of that + is returned. If it does not, a SecRequirement is implicitly constructed from + its signing authority and its embedded unique identifier. No Designated + Requirement can be obtained from code that is unsigned. Code that is modified + after signature, improperly signed, or has become invalid, may or may not yield + a Designated Requirement. This call does not validate the SecStaticCode argument. + + @param code The Code or StaticCode object to be interrogated. For a Code + argument, its StaticCode is processed as per SecCodeCopyStaticCode. + @param flags Optional flags. Pass kSecCSDefaultFlags for standard behavior. + @param requirement On successful return, contains a copy of a SecRequirement + object representing the code's Designated Requirement. On error, unchanged. + @result On success, noErr. On error, an OSStatus value + documented in CSCommon.h or certain other Security framework headers. +*/ +OSStatus SecCodeCopyDesignatedRequirement(SecStaticCodeRef code, SecCSFlags flags, + SecRequirementRef *requirement); + + +/* + @function SecCodeCopySigningInformation + For a given Code or StaticCode object, extract various pieces of information + from its code signature and return them in the form of a CFDictionary. The amount + and detail level of the data is controlled by the flags passed to the call. + + If the code exists but is not signed at all, this call will succeed and return + a dictionary that does NOT contain the kSecCodeInfoIdentifier key. This is the + recommended way to check quickly whether a code is signed. + + If the signing data for the code is corrupt or invalid, this call may fail or it + may return partial data. To ensure that only valid data is returned (and errors + are raised for invalid data), you must successfully call one of the CheckValidity + functions on the code before calling CopySigningInformation. + + @param code The Code or StaticCode object to be interrogated. For a Code + argument, its StaticCode is processed as per SecCodeCopyStaticCode. + Note that dynamic information (kSecCSDynamicInformation) cannot be obtained + for a StaticCode argument. + @param flags Optional flags. Use any or all of the kSecCS*Information flags + to select what information to return. A generic set of entries is returned + regardless; you may specify kSecCSDefaultFlags for just those. + @param information A CFDictionary containing information about the code is stored + here on successful completion. The contents of the dictionary depend on + the flags passed. Regardless of flags, the kSecCodeInfoIdentifier key is + always present if the code is signed, and always absent if the code is + unsigned. + Note that some of the objects returned are (retained) "live" API objects + used by the code signing infrastructure. Making changes to these objects + is unsupported and may cause subsequent code signing operations on the + affected code to behave in undefined ways. + @result On success, noErr. On error, an OSStatus value + documented in CSCommon.h or certain other Security framework headers. + + Flags: + + @constant kSecCSSigningInformation Return cryptographic signing information, + including the certificate chain and CMS data (if any). For ad-hoc signed + code, there are no certificates and the CMS data is empty. + @constant kSecCSRequirementInformation Return information about internal code + requirements embedded in the code. This includes the Designated Requirement. + @constant kSecCSInternalInformation Return internal code signing information. + This information is for use by Apple, and is subject to change without notice. + It will not be further documented here. + @constant kSecCSDynamicInformation Return dynamic validity information about + the Code. The subject code must be a SecCodeRef (not a SecStaticCodeRef). + @constant kSecCSContentInformation Return more information about the file system + contents making up the signed code on disk. It is not generally advisable to + make use of this information, but some utilities (such as software-update + tools) may find it useful. + + Dictionary keys: + + @constant kSecCodeInfoCertificates A CFArray of SecCertificates identifying the + certificate chain of the signing certificate as seen by the system. Absent + for ad-hoc signed code. May be partial or absent in error cases. + @constant kSecCodeInfoChangedFiles A CFArray of CFURLs identifying all files in + the code that may have been modified by the process of signing it. (In other + words, files not in this list will not have been touched by the signing operation.) + @constant kSecCodeInfoCMS A CFData containing the CMS cryptographic object that + secures the code signature. Empty for ad-hoc signed code. + @constant kSecCodeInfoDesignatedRequirement A SecRequirement describing the + actual Designated Requirement of the code. + @constant kSecCodeInfoEntitlements A CFData containing the embedded entitlement + blob of the code, if any. + @constant kSecCodeInfoEntitlementsDict A CFDictionary containing the embedded entitlements + of the code if it has entitlements and they are in standard dictionary form. + Absent if the code has no entitlements, or they are in a different format (in which + case, see kSecCodeInfoEntitlements). + @constant kSecCodeInfoFormat A CFString characterizing the type and format of + the code. Suitable for display to a (knowledeable) user. + @constant kSecCodeInfoDigestAlgorithm A CFNumber indicating the kind of cryptographic + hash function used within the signature to seal its pieces together. + @constant kSecCodeInfoIdentifier A CFString with the actual signing identifier + sealed into the signature. Absent for unsigned code. + @constant kSecCodeInfoImplicitDesignatedRequirement A SecRequirement describing + the designated requirement that the system did generate, or would have generated, + for the code. If the Designated Requirement was implicitly generated, this is + the same object as kSecCodeInfoDesignatedRequirement; this can be used to test + for an explicit Designated Requirement. + @constant kSecCodeInfoMainExecutable A CFURL identifying the main executable file + of the code. For single files, that is the file itself. For bundles, it is the + main executable as identified by its Info.plist. + @constant kSecCodeInfoPList A retained CFDictionary referring to the secured Info.plist + as seen by code signing. Absent if no Info.plist is known to the code signing + subsystem. Note that this is not the same dictionary as the one CFBundle would + give you (CFBundle is free to add entries to the on-disk plist). + @constant kSecCodeInfoRequirements A CFString describing the internal requirements + of the code in canonical syntax. + @constant kSecCodeInfoRequirementsData A CFData containing the internal requirements + of the code as a binary blob. + @constant kSecCodeInfoSource A CFString describing the source of the code signature + used for the code object. The values are meant to be shown in informational + displays; do not rely on the precise value returned. + @constant kSecCodeInfoStatus A CFNumber containing the dynamic status word of the + (running) code. This is a snapshot at the time the API is executed and may be + out of date by the time you examine it. Do note however that most of the bits + are sticky and thus some values are permanently reliable. Be careful. + @constant kSecCodeInfoTime A CFDate describing the signing date (securely) embedded + in the code signature. Note that a signer is able to omit this date or pre-date + it. Nobody certifies that this was really the date the code was signed; however, + you do know that this is the date the signer wanted you to see. + Ad-hoc signatures have no CMS and thus never have secured signing dates. + @constant kSecCodeInfoTimestamp A CFDate describing the signing date as (securely) + certified by a timestamp authority service. This time cannot be falsified by the + signer; you trust the timestamp authority's word on this. + Ad-hoc signatures have no CMS and thus never have secured signing dates. + @constant kSecCodeInfoTrust The (retained) SecTrust object the system uses to + evaluate the validity of the code's signature. You may use the SecTrust API + to extract detailed information, particularly for reasons why certificate + validation may have failed. This object may continue to be used for further + evaluations of this code; if you make any changes to it, behavior is undefined. + @constant kSecCodeInfoUnique A CFData binary identifier that uniquely identifies + the static code in question. It can be used to recognize this particular code + (and none other) now or in the future. Compare to kSecCodeInfoIdentifier, which + remains stable across (developer-approved) updates. + This is currently the SHA-1 hash of the code's CodeDirectory. However, future + versions of the system may use a different algorithm for newly signed code. + Already-signed code not change the reported value in this case. + @constant kSecCodeSignerFlags A CFNumber with the dynamic state of the object. + Contants are defined by the type SecCodeSignatureFlags. + */ +enum { + kSecCSInternalInformation = 1 << 0, + kSecCSSigningInformation = 1 << 1, + kSecCSRequirementInformation = 1 << 2, + kSecCSDynamicInformation = 1 << 3, + kSecCSContentInformation = 1 << 4 +}; + + /* flag required to get this value */ +extern const CFStringRef kSecCodeInfoCertificates; /* Signing */ +extern const CFStringRef kSecCodeInfoChangedFiles; /* Content */ +extern const CFStringRef kSecCodeInfoCMS; /* Signing */ +extern const CFStringRef kSecCodeInfoDesignatedRequirement; /* Requirement */ +extern const CFStringRef kSecCodeInfoEntitlements; /* Requirement */ +extern const CFStringRef kSecCodeInfoEntitlementsDict; /* Requirement */ +extern const CFStringRef kSecCodeInfoFormat; /* generic */ +extern const CFStringRef kSecCodeInfoDigestAlgorithm; /* generic */ +extern const CFStringRef kSecCodeInfoIdentifier; /* generic */ +extern const CFStringRef kSecCodeInfoImplicitDesignatedRequirement; /* Requirement */ +extern const CFStringRef kSecCodeInfoMainExecutable; /* generic */ +extern const CFStringRef kSecCodeInfoPList; /* generic */ +extern const CFStringRef kSecCodeInfoRequirements; /* Requirement */ +extern const CFStringRef kSecCodeInfoRequirementData; /* Requirement */ +extern const CFStringRef kSecCodeInfoSource; /* generic */ +extern const CFStringRef kSecCodeInfoStatus; /* Dynamic */ +extern const CFStringRef kSecCodeInfoTime; /* Signing */ +extern const CFStringRef kSecCodeInfoTimestamp; /* Signing */ +extern const CFStringRef kSecCodeInfoTrust; /* Signing */ +extern const CFStringRef kSecCodeInfoUnique; /* generic */ +extern const CFStringRef kSecCodeSignerFlags; /* dynamic */ + +OSStatus SecCodeCopySigningInformation(SecStaticCodeRef code, SecCSFlags flags, + CFDictionaryRef *information); + + +/* + @function SecCodeMapMemory + For a given Code or StaticCode object, ask the kernel to accept the signing information + currently attached to it in the caller and use it to validate memory page-ins against it, + updating dynamic validity state accordingly. This change affects all processes that have + the main executable of this code mapped. + + @param code A Code or StaticCode object representing the signed code whose main executable + should be subject to page-in validation. + @param flags Optional flags. Pass kSecCSDefaultFlags for standard behavior. + */ +OSStatus SecCodeMapMemory(SecStaticCodeRef code, SecCSFlags flags); + + +#ifdef __cplusplus +} +#endif + +#endif //_H_SECCODE diff --git a/libsecurity_codesigning/lib/SecCodeHost.cpp b/libsecurity_codesigning/lib/SecCodeHost.cpp new file mode 100644 index 00000000..f6989f29 --- /dev/null +++ b/libsecurity_codesigning/lib/SecCodeHost.cpp @@ -0,0 +1,117 @@ +/* + * Copyright (c) 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@ + */ + +// +// SecCodeHost - Host Code API +// +#include "cs.h" +#include "SecCodeHost.h" +#include +#include +#include + +using namespace CodeSigning; + + +// +// Munge a CFDictionary into a CssmData representing its plist +// +class DictData : public CFRef { +public: + DictData(CFDictionaryRef dict) : CFRef(makeCFData(dict)) { } + + operator CssmData() const + { + if (*this) + return CssmData::wrap(CFDataGetBytePtr(*this), CFDataGetLength(*this)); + else + return CssmData(); + } +}; + + +OSStatus SecHostCreateGuest(SecGuestRef host, + uint32_t status, CFURLRef path, CFDictionaryRef attributes, + SecCSFlags flags, SecGuestRef *newGuest) +{ + BEGIN_CSAPI + + checkFlags(flags, kSecCSDedicatedHost | kSecCSGenerateGuestHash); + CodeSigning::Required(newGuest) = SecurityServer::ClientSession().createGuest(host, + status, cfString(path).c_str(), CssmData(), DictData(attributes), flags); + + END_CSAPI +} + +OSStatus SecHostRemoveGuest(SecGuestRef host, SecGuestRef guest, SecCSFlags flags) +{ + BEGIN_CSAPI + + checkFlags(flags); + SecurityServer::ClientSession().removeGuest(host, guest); + + END_CSAPI +} + +OSStatus SecHostSelectGuest(SecGuestRef guestRef, SecCSFlags flags) +{ + BEGIN_CSAPI + + checkFlags(flags); + SecurityServer::ClientSession().selectGuest(guestRef); + + END_CSAPI +} + + +OSStatus SecHostSelectedGuest(SecCSFlags flags, SecGuestRef *guestRef) +{ + BEGIN_CSAPI + + checkFlags(flags); + CodeSigning::Required(guestRef) = SecurityServer::ClientSession().selectedGuest(); + + END_CSAPI +} + +OSStatus SecHostSetGuestStatus(SecGuestRef guestRef, + uint32_t status, CFDictionaryRef attributes, + SecCSFlags flags) +{ + BEGIN_CSAPI + + checkFlags(flags); + SecurityServer::ClientSession().setGuestStatus(guestRef, status, DictData(attributes)); + + END_CSAPI +} + +OSStatus SecHostSetHostingPort(mach_port_t hostingPort, SecCSFlags flags) +{ + BEGIN_CSAPI + + checkFlags(flags); + SecurityServer::ClientSession().registerHosting(hostingPort, flags); + + END_CSAPI +} diff --git a/libsecurity_codesigning/lib/SecCodeHost.h b/libsecurity_codesigning/lib/SecCodeHost.h new file mode 100644 index 00000000..dd70b8ab --- /dev/null +++ b/libsecurity_codesigning/lib/SecCodeHost.h @@ -0,0 +1,241 @@ +/* + * Copyright (c) 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@ + */ + +/*! + @header SecCodeHost + This header provides the hosting API for Code Signing. These are calls + that are (only) made by code that is hosting guests. + In the context of Code Signing, a Host is code that creates and manages other + codes from which it defends its own integrity. As part of that duty, it maintains + state for each of its children, and answers questions about them. + + A Host is externally represented by a SecCodeRef (it is a SecCode object). + So is a Guest. There is no specific API object to represent Hosts or Guests. + Within the Hosting API, guests are identified by simple numeric handles that + are unique and valid only in the context of their specific host. + + The functions in this API always apply to the Host making the API calls. + They cannot be used to (directly) interrogate another host. +*/ +#ifndef _H_SECCODEHOST +#define _H_SECCODEHOST + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/*! + @header SecCodeHost + This header describes the Code Signing Hosting API. These are calls made + by code that wishes to become a Host in the Code Signing Host/Guest infrastructure. + Hosting allows the caller to establish separate, independent code identities + (SecCodeRefs) for parts of itself, usually because it is loading and managing + code in the form of scripts, plugins, etc. + + The Hosting API does not directly connect to the Code Signing Client APIs. + Certain calls in the client API will cause internal queries to hosts about their + guests. The Host side of these queries is managed through this API. The results + will eventually be delivered to client API callers in appropriate form. + + If code never calls any of the Hosting API functions, it is deemed to not have + guests and not act as a Host. This is the default and requires no action. + + Hosting operates in one of two modes, dynamic or proxy. Whichever mode is first + engaged prevails for the lifetime of the caller. There is no way to switch between + the two, and calling an API belonging to the opposite mode will fail. + + In dynamic hosting mode, the caller provides a Mach port that receives direct + queries about its guests. Dynamic mode is engaged by calling SecHostSetHostingPort. + + In proxy hosting mode, the caller provides information about its guests as + guests are created, removed, or change status. The system caches this information + and answers queries about guests from this pool of information. The caller is not + directly involved in answering such queries, and has no way to intervene. +*/ + + +/*! + @function SecHostCreateGuest + Create a new Guest and describe its initial properties. + + This call activates Hosting Proxy Mode. From here on, the system will record + guest information provided through SecHostCreateGuest, SecHostSetGuestStatus, and + SecHostRemoveGuest, and report hosting status to callers directly. This mode + is incompatible with dynamic host mode as established by a call to SecHostSetHostingPort. + + @param host Pass kSecNoGuest to create a guest of the process itself. + To create a guest of another guest (extending the hosting chain), pass the SecGuestRef + of the guest to act as the new guest's host. If host has a dedicated guest, + it will be deemed to be be the actual host, recursively. + @param status The Code Signing status word for the new guest. These are combinations + of the kSecCodeStatus* flags in . Note that the proxy will enforce + the rules for the stickiness of these bits. In particular, if you don't pass the + kSecCodeStatusValid bit during creation, your new guest will be born invalid and will + never have a valid identity. + @param path The canonical path to the guest's code on disk. This is the path you would + pass to SecStaticCodeCreateWithPath to make a static code object reference. You must + use an absolute path. + @param attributes An optional CFDictionaryRef containing attributes that can be used + to locate this particular guest among all of the caller's guests. The "canonical" + attribute is automatically added for the value of guestRef. If you pass NULL, + no other attributes are established for the guest. + While any key can be used in the attributes dictionary, the kSecGuestAttribute* constants + (in SecCode.h) are conventionally used here. + @param flags Optional flags. Pass kSecCSDefaultFlags for standard behavior, or + a combination of the flags defined below for special features. + @result Upon success, noErr. Upon error, an OSStatus value documented in + CSCommon.h or certain other Security framework headers. + @param newGuest Upon successful creation of the new guest, the new SecGuestRef + that should be used to identify the new guest from here on. + + @constant kSecCSDedicatedHost Declares dedicated hosting for the given host. + In dedicated hosting, the host has exactly one guest (the one this call is + introducing), and the host will spend all of its time from here on running + that guest (or on its behalf). This declaration is irreversable for the lifetime + of the host. Note that this is a declaration about the given host, and is not + binding upon other hosts on either side of the hosting chain, though they in turn + may declare dedicated hosting if desired. + It is invalid to declare dedicated hosting if other guests have already been + introduced for this host, and it is invalid to introduce additional guests + for this host after this call. + @constant kSecCSGenerateGuestHash Ask the proxy to generate the binary identifier + (hash of CodeDirectory) from the copy on disk at the path given. This is not optimal + since an attacker with write access may be able to substitute a different copy just + in time, but it is convenient. For optimal security, the host should calculate the + hash from the loaded in-memory signature of its guest and pass the result as an + attribute with key kSecGuestAttributeHash. +*/ +enum { + kSecCSDedicatedHost = 1 << 0, + kSecCSGenerateGuestHash = 1 << 1, +}; + +OSStatus SecHostCreateGuest(SecGuestRef host, + uint32_t status, CFURLRef path, CFDictionaryRef attributes, + SecCSFlags flags, SecGuestRef *newGuest); + + +/*! + @function SecHostRemoveGuest + Announce that the guest with the given guestRef has permanently disappeared. + It removes all memory of the guest from the hosting system. You cannot remove + a dedicated guest. + + @param host The SecGuestRef that was used to create guest. You cannot specify + a proximate host (host of a host) here. However, the substitution for dedicated + guests described for SecHostCreateGuest also takes place here. + @param guest The handle for a Guest previously created with SecHostCreateGuest + that has not previously been destroyed. This guest is to be destroyed now. + @param flags Optional flags. Pass kSecCSDefaultFlags for standard behavior. + @result Upon success, noErr. Upon error, an OSStatus value documented in + CSCommon.h or certain other Security framework headers. +*/ +OSStatus SecHostRemoveGuest(SecGuestRef host, SecGuestRef guest, SecCSFlags flags); + + +/*! + @function SecHostSelectGuest + Tell the Code Signing host subsystem that the calling thread will now act + on behalf of the given Guest. This must be a valid Guest previously created + with SecHostCreateGuest. + + @param guestRef The handle for a Guest previously created with SecHostCreateGuest + on whose behalf this thread will act from now on. This setting will be remembered + until it is changed (or the thread terminates). + To indicate that the thread will act on behalf of the Host itself (rather than + any Guest), pass kSecNoGuest. + @param flags Optional flags. Pass kSecCSDefaultFlags for standard behavior. + @result Upon success, noErr. Upon error, an OSStatus value documented in + CSCommon.h or certain other Security framework headers. +*/ +OSStatus SecHostSelectGuest(SecGuestRef guestRef, SecCSFlags flags); + + +/*! + @function SecHostSelectedGuest + Retrieve the handle for the Guest currently selected for the calling thread. + + @param flags Optional flags. Pass kSecCSDefaultFlags for standard behavior. + @param guestRef Will be assigned the SecGuestRef currently in effect for + the calling thread. If no Guest is active on this thread (i.e. the thread + is acting for the Host), the return value is kSecNoGuest. + @result Upon success, noErr. Upon error, an OSStatus value documented in + CSCommon.h or certain other Security framework headers. +*/ +OSStatus SecHostSelectedGuest(SecCSFlags flags, SecGuestRef *guestRef); + + +/*! + @function SecHostSetGuestStatus + Updates the status of a particular guest. + + @param guestRef The handle for a Guest previously created with SecHostCreateGuest + on whose behalf this thread will act from now on. This setting will be remembered + until it is changed (or the thread terminates). + @param status The new Code Signing status word for the guest. The proxy enforces + the restrictions on changes to guest status; in particular, the kSecCodeStatusValid bit can only + be cleared, and the kSecCodeStatusHard and kSecCodeStatusKill flags can only be set. Pass the previous + guest status to indicate that no change is desired. + @param attributes An optional dictionary containing attributes to be used to distinguish + this guest from all guests of the caller. If given, it completely replaces the attributes + specified earlier. If NULL, previously established attributes are retained. + @param flags Optional flags. Pass kSecCSDefaultFlags for standard behavior. + @result Upon success, noErr. Upon error, an OSStatus value documented in + CSCommon.h or certain other Security framework headers. + */ +OSStatus SecHostSetGuestStatus(SecGuestRef guestRef, + uint32_t status, CFDictionaryRef attributes, + SecCSFlags flags); + + +/*! + @function SecHostSetHostingPort + Tells the Code Signing Hosting subsystem that the calling code will directly respond + to hosting inquiries over the given port. + + This API should be the first hosting API call made. With it, the calling code takes + direct responsibility for answering questions about its guests using the hosting IPC + services. The SecHostCreateGuest, SecHostDestroyGuest and SecHostSetGuestStatus calls + are not valid after this. The SecHostSelectGuest and SecHostSelectedGuest calls will + still work, and will use whatever SecGuestRefs the caller has assigned in its internal + data structures. + + This call cannot be undone; once it is made, record-and-forward facilities are + disabled for the lifetime of the calling code. + + @param hostingPort A Mach message port with send rights. This port will be recorded + and handed to parties interested in querying the host about its children. + @param flags Optional flags. Pass kSecCSDefaultFlags for standard behavior. + @result Upon success, noErr. Upon error, an OSStatus value documented in + CSCommon.h or certain other Security framework headers. + */ +OSStatus SecHostSetHostingPort(mach_port_t hostingPort, SecCSFlags flags); + + +#ifdef __cplusplus +} +#endif + +#endif //_H_SECCODEHOST diff --git a/libsecurity_codesigning/lib/SecCodeHostLib.c b/libsecurity_codesigning/lib/SecCodeHostLib.c new file mode 100644 index 00000000..50dadf16 --- /dev/null +++ b/libsecurity_codesigning/lib/SecCodeHostLib.c @@ -0,0 +1,124 @@ +/* + * 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@ + */ +#include "SecCodeHost.h" +#include "SecCodeHostLib.h" +#include +#include +#include +#include + + +// +// Global state +// +mach_port_t gServerPort; +SecCSFlags gInitFlags; + + +// +// Framing macros and facilities +// +#define UCSP_ARGS gServerPort, mig_get_reply_port(), &securitydCreds, &rcode +#define ATTRDATA(attr) (void *)(attr), (attr) ? strlen((attr)) : 0 + +#define CALL(func) \ + security_token_t securitydCreds; \ + CSSM_RETURN rcode; \ + if (KERN_SUCCESS != func) \ + return errSecCSInternalError; \ + if (securitydCreds.val[0] != 0) \ + return CSSM_ERRCODE_VERIFICATION_FAILURE; \ + return rcode + + + +// +// Mandatory initialization call +// +OSStatus SecHostLibInit(SecCSFlags flags) +{ + if (gServerPort != MACH_PORT_NULL) // re-initialization attempt + return errSecCSInternalError; + + mach_port_t bootstrapPort; + if (KERN_SUCCESS != task_get_bootstrap_port(mach_task_self(), &bootstrapPort)) + return errSecCSInternalError; + static char serverName[BOOTSTRAP_MAX_NAME_LEN] = SECURITYSERVER_BOOTSTRAP_NAME; + if (KERN_SUCCESS != bootstrap_look_up(bootstrapPort, serverName, &gServerPort)) + return errSecCSInternalError; + + ClientSetupInfo info = { 0x1234, SSPROTOVERSION }; + CALL(ucsp_client_setup(UCSP_ARGS, mach_task_self(), info, "?:unspecified")); +} + + +// +// Guest creation. +// At this time, this ONLY supports the creation of (one) dedicated guest. +// +OSStatus SecHostLibCreateGuest(SecGuestRef host, + uint32_t status, const char *path, const char *attributeXML, + SecCSFlags flags, SecGuestRef *newGuest) +{ + return SecHostLibCreateGuest2(host, status, path, "", 0, attributeXML, flags, newGuest); +} + +OSStatus SecHostLibCreateGuest2(SecGuestRef host, + uint32_t status, const char *path, const void *cdhash, size_t cdhashLength, const char *attributeXML, + SecCSFlags flags, SecGuestRef *newGuest) +{ + if (flags != kSecCSDedicatedHost) + return errSecCSInvalidFlags; + + CALL(ucsp_client_createGuest(UCSP_ARGS, host, status, path, + (void *)cdhash, cdhashLength, ATTRDATA(attributeXML), flags, newGuest)); +} + + +// +// Update the status of a guest. +// +OSStatus SecHostLibSetGuestStatus(SecGuestRef guestRef, + uint32_t status, const char *attributeXML, + SecCSFlags flags) +{ + CALL(ucsp_client_setGuestStatus(UCSP_ARGS, guestRef, status, ATTRDATA(attributeXML))); +} + + +// +// Enable dynamic hosting mode. +// +OSStatus SecHostSetHostingPort(mach_port_t hostingPort, SecCSFlags flags) +{ + CALL(ucsp_client_registerHosting(UCSP_ARGS, hostingPort, flags)); +} + + +// +// Helper for checked incorporation of code. +// +OSStatus SecHostLibCheckLoad(const char *path, SecRequirementType type) +{ + CALL(ucsp_client_helpCheckLoad(UCSP_ARGS, path, type)); +} diff --git a/libsecurity_codesigning/lib/SecCodeHostLib.h b/libsecurity_codesigning/lib/SecCodeHostLib.h new file mode 100644 index 00000000..813b3993 --- /dev/null +++ b/libsecurity_codesigning/lib/SecCodeHostLib.h @@ -0,0 +1,110 @@ +/* + * 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 SecCodeHostLib + This header provides a subset of the hosting API for Code Signing. + This subset functionality is implemented as a static library written + entirely in C, and depends on nothing except the system library and the + C runtime. It is thus suitable to be used by low-level libraries and + other such system facilities. On the other hand, it does not provide the + full functionality of . + + This file is documented as a delta to , which + you should consult as a baseline. +*/ +#ifndef _H_SECCODEHOSTLIB +#define _H_SECCODEHOSTLIB + +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +/*! + @function SecHostLibInit + This function must be called first to use the SecCodeHostLib facility. + */ +OSStatus SecHostLibInit(SecCSFlags flags); + + +/*! + @function SecHostLibCreateGuest + This function declares a code host, engages hosting proxy services for it, + and creates a guest with given attributes and state. + + NOTE: This version of the function currently only supports dedicated hosting. + If you do not pass the kSecCSDedicatedHost flag, the call will fail. + */ +OSStatus SecHostLibCreateGuest(SecGuestRef host, + uint32_t status, const char *path, const char *attributeXML, + SecCSFlags flags, SecGuestRef *newGuest) DEPRECATED_ATTRIBUTE; + +OSStatus SecHostLibCreateGuest2(SecGuestRef host, + uint32_t status, const char *path, const void *cdhash, size_t cdhashLength, const char *attributeXML, + SecCSFlags flags, SecGuestRef *newGuest); + + +/*! + @function SecHostLibSetGuestStatus + This function can change the state or attributes (or both) of a given guest. + It performs all the work of SecHostSetGuestStatus. + */ +OSStatus SecHostLibSetGuestStatus(SecGuestRef guestRef, + uint32_t status, const char *attributeXML, + SecCSFlags flags); + + +/*! + @function SecHostLibSetHostingPort + Register a Mach port to receive hosting queries on. This enables (and locks) + dynamic hosting mode, and is incompatible with all proxy-mode calls. + You still must call SecHostLibInit first. + */ +OSStatus SecHostSetHostingPort(mach_port_t hostingPort, SecCSFlags flags); + + +/* + Functionality from SecCodeHost.h that is genuinely missing here: + +OSStatus SecHostRemoveGuest(SecGuestRef host, SecGuestRef guest, SecCSFlags flags); + +OSStatus SecHostSelectGuest(SecGuestRef guestRef, SecCSFlags flags); + +OSStatus SecHostSelectedGuest(SecCSFlags flags, SecGuestRef *guestRef); + +*/ + + +/*! + */ +OSStatus SecHostLibCheckLoad(const char *path, SecRequirementType type); + + +#ifdef __cplusplus +} +#endif + +#endif //_H_SECCODEHOSTLIB diff --git a/libsecurity_codesigning/lib/SecCodePriv.h b/libsecurity_codesigning/lib/SecCodePriv.h new file mode 100644 index 00000000..54759b82 --- /dev/null +++ b/libsecurity_codesigning/lib/SecCodePriv.h @@ -0,0 +1,185 @@ +/* + * Copyright (c) 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@ + */ + +/*! + @header SecCodePriv + SecCodePriv is the private counter-part to SecCode. Its contents are not + official API, and are subject to change without notice. +*/ +#ifndef _H_SECCODEPRIV +#define _H_SECCODEPRIV + +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +/* + * Private constants for SecCodeCopySigningInformation. + * These are returned with the + */ +extern const CFStringRef kSecCodeInfoCodeDirectory; /* Internal */ +extern const CFStringRef kSecCodeInfoCodeOffset; /* Internal */ +extern const CFStringRef kSecCodeInfoResourceDirectory; /* Internal */ + + +/*! + @function SecCodeGetStatus + Retrieves the dynamic status for a SecCodeRef. + + The dynamic status of a code can change at any time; the value returned is a snapshot + in time that is inherently stale by the time it is received by the caller. However, + since the status bits can only change in certain ways, some information is indefinitely + valid. For example, an indication of invalidity (kSecCodeStatusValid bit off) is permanent + since the valid bit cannot be set once clear, while an indication of validity (bit set) + may already be out of date. + Use this call with caution; it is usually wiser to call the validation API functions + and let then consider the status as part of their holistic computation. However, + SecCodeGetStatus is useful at times to capture persistent (sticky) status configurations. + + @param code A valid SecCode object reference representing code running + on the system. + @param flags Optional flags. Pass kSecCSDefaultFlags for standard behavior. + @param status Upon successful return, contains the dynamic status of code as + determined by its host. + + @result Upon success, noErr. Upon error, an OSStatus value documented in + CSCommon.h or certain other Security framework headers. + */ +OSStatus SecCodeGetStatus(SecCodeRef code, SecCSFlags flags, SecCodeStatus *status); + + +/*! + @function SecCodeSetStatus + Change the dynamic status of a SecCodeRef. + + @param code A valid SecCode object reference representing code running + on the system. + @param flags Optional flags. Pass kSecCSDefaultFlags for standard behavior. + @param status Upon successful return, contains the dynamic status of code as + determined by its host. + + @result Upon success, noErr. Upon error, an OSStatus value documented in + CSCommon.h or certain other Security framework headers. + */ +typedef uint32_t SecCodeStatusOperation; +enum { + kSecCodeOperationNull = 0, + kSecCodeOperationInvalidate = 1, + kSecCodeOperationSetHard = 2, + kSecCodeOperationSetKill = 3, +}; + +OSStatus SecCodeSetStatus(SecCodeRef code, SecCodeStatusOperation operation, + CFDictionaryRef arguments, SecCSFlags flags); + + +/*! + @function SecCodeCopyInternalRequirement + For a given Code or StaticCode object, retrieves a particular kind of internal + requirement that was sealed during signing. + + This function will always fail for unsigned code. Requesting a type of internal + requirement that was not given during signing is not an error. + + Specifying a type of kSecDesignatedRequirementType is not the same as calling + SecCodeCopyDesignatedRequirement. This function will only return an explicit + Designated Requirement if one was specified during signing. SecCodeCopyDesignatedRequirement + will synthesize a suitable Designated Requirement if one was not given explicitly. + + @param code The Code or StaticCode object to be interrogated. For a Code + argument, its StaticCode is processed as per SecCodeCopyStaticCode. + @param type A SecRequirementType specifying which internal requirement is being + requested. + @param flags Optional flags. Pass kSecCSDefaultFlags for standard behavior. + @param requirement On successful return, contains a copy of the internal requirement + of the given type included in the given code. If the code has no such internal + requirement, this argument is set to NULL (with no error). + @result On success, noErr. On error, an OSStatus value + documented in CSCommon.h or certain other Security framework headers. +*/ +OSStatus SecCodeCopyInternalRequirement(SecStaticCodeRef code, SecRequirementType type, + SecCSFlags flags, SecRequirementRef *requirement); + + +/*! + @function SecCodeCreateWithPID + Asks the kernel to return a SecCode object for a process identified + by a UNIX process id (pid). This is a shorthand for asking SecGetRootCode() + for a guest whose "pid" attribute has the given pid value. + + This is a deprecated convenience function. + Call SecCodeCopyGuestWithAttributes instead. + + @param pid A process id for an existing UNIX process on the system. + @param flags Optional flags. Pass kSecCSDefaultFlags for standard behavior. + @param process On successful return, a SecCode object reference identifying + the requesteed process. + @result Upon success, noErr. Upon error, an OSStatus value documented in + CSCommon.h or certain other Security framework headers. +*/ +OSStatus SecCodeCreateWithPID(pid_t pid, SecCSFlags flags, SecCodeRef *process) + AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_6; + + +/* + @function SecCodeSetDetachedSignature + For a given Code or StaticCode object, explicitly specify the detached signature + data used to verify it. + This call unconditionally overrides any signature embedded in the Code and any + previously specified detached signature; only the signature data specified here + will be used from now on for this Code object. If NULL data is specified, the + code object is returned to its natural signing state (before a detached + signature was first attached to it). + Any call to this function voids all cached validations for the Code object. + Validations will be performed again as needed in the future. This call does not, + by itself, perform or trigger any validations. + Please note that it is possible to have multiple Code objects for the same static + or dynamic code entity in the system. This function only attaches signature data + to the particular SecStaticCodeRef involved. It is your responsibility to understand + the object graph and pick the right one(s). + + @param code A Code or StaticCode object whose signature information is to be changed. + @param signature A CFDataRef containing the signature data to be used for validating + the given Code. This must be exactly the data previously generated as a detached + signature by the SecCodeSignerAddSignature API or the codesign(1) command with + the -D/--detached option. + If signature is NULL, discards any previously set signature data and reverts + to using the embedded signature, if any. If not NULL, the data is retained and used + for future validation operations. + The data may be retained or copied. Behavior is undefined if this object + is modified after this call before it is replaced through another call to this + function). + @param flags Optional flags. Pass kSecCSDefaultFlags for standard behavior. + */ +OSStatus SecCodeSetDetachedSignature(SecStaticCodeRef code, CFDataRef signature, + SecCSFlags flags); + + +#ifdef __cplusplus +} +#endif + +#endif //_H_SECCODE diff --git a/libsecurity_codesigning/lib/SecCodeSigner.cpp b/libsecurity_codesigning/lib/SecCodeSigner.cpp new file mode 100644 index 00000000..d5e7438f --- /dev/null +++ b/libsecurity_codesigning/lib/SecCodeSigner.cpp @@ -0,0 +1,110 @@ +/* + * 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@ + */ + +// +// SecCode - API frame for SecCode objects. +// +// Note that some SecCode* functions take SecStaticCodeRef arguments in order to +// accept either static or dynamic code references, operating on the respective +// StaticCode. Those functions are in SecStaticCode.cpp, not here, despite their name. +// +#include "cs.h" +#include "CodeSigner.h" +#include "cskernel.h" + +using namespace CodeSigning; + + +// +// Parameter keys +// +const CFStringRef kSecCodeSignerApplicationData = CFSTR("application-specific"); +const CFStringRef kSecCodeSignerDetached = CFSTR("detached"); +const CFStringRef kSecCodeSignerDigestAlgorithm = CFSTR("digest-algorithm"); +const CFStringRef kSecCodeSignerDryRun = CFSTR("dryrun"); +const CFStringRef kSecCodeSignerEntitlements = CFSTR("entitlements"); +const CFStringRef kSecCodeSignerFlags = CFSTR("flags"); +const CFStringRef kSecCodeSignerIdentifier = CFSTR("identifier"); +const CFStringRef kSecCodeSignerIdentifierPrefix = CFSTR("identifier-prefix"); +const CFStringRef kSecCodeSignerIdentity = CFSTR("signer"); +const CFStringRef kSecCodeSignerPageSize = CFSTR("pagesize"); +const CFStringRef kSecCodeSignerRequirements = CFSTR("requirements"); +const CFStringRef kSecCodeSignerResourceRules = CFSTR("resource-rules"); +const CFStringRef kSecCodeSignerSDKRoot = CFSTR("sdkroot"); +const CFStringRef kSecCodeSignerSigningTime = CFSTR("signing-time"); +const CFStringRef kSecCodeSignerRequireTimestamp = CFSTR("timestamp-required"); +const CFStringRef kSecCodeSignerTimestampServer = CFSTR("timestamp-url"); +const CFStringRef kSecCodeSignerTimestampAuthentication = CFSTR("timestamp-authentication"); +const CFStringRef kSecCodeSignerTimestampOmitCertificates = CFSTR("timestamp-omit-certificates"); + +// temporary add-back to bridge B&I build dependencies -- remove soon +const CFStringRef kSecCodeSignerTSAUse = CFSTR("timestamp-required"); +const CFStringRef kSecCodeSignerTSAURL = CFSTR("timestamp-url"); +const CFStringRef kSecCodeSignerTSAClientAuth = CFSTR("timestamp-authentication"); +const CFStringRef kSecCodeSignerTSANoCerts = CFSTR("timestamp-omit-certificates"); + + +// +// CF-standard type code functions +// +CFTypeID SecCodeSignerGetTypeID(void) +{ + BEGIN_CSAPI + return gCFObjects().CodeSigner.typeID; + END_CSAPI1(_kCFRuntimeNotATypeID) +} + + +// +// Create a signer object +// +OSStatus SecCodeSignerCreate(CFDictionaryRef parameters, SecCSFlags flags, + SecCodeSignerRef *signerRef) +{ + BEGIN_CSAPI + + checkFlags(flags, kSecCSRemoveSignature); + SecPointer signer = new SecCodeSigner(flags); + signer->parameters(parameters); + CodeSigning::Required(signerRef) = signer->handle(); + + END_CSAPI +} + + +// +// Generate a signature +// +OSStatus SecCodeSignerAddSignature(SecCodeSignerRef signerRef, + SecStaticCodeRef codeRef, SecCSFlags flags) +{ + return SecCodeSignerAddSignatureWithErrors(signerRef, codeRef, flags, NULL); +} + +OSStatus SecCodeSignerAddSignatureWithErrors(SecCodeSignerRef signerRef, + SecStaticCodeRef codeRef, SecCSFlags flags, CFErrorRef *errors) +{ + BEGIN_CSAPI + SecCodeSigner::required(signerRef)->sign(SecStaticCode::required(codeRef), flags); + END_CSAPI_ERRORS +} diff --git a/libsecurity_codesigning/lib/SecCodeSigner.h b/libsecurity_codesigning/lib/SecCodeSigner.h new file mode 100644 index 00000000..42ad0899 --- /dev/null +++ b/libsecurity_codesigning/lib/SecCodeSigner.h @@ -0,0 +1,218 @@ +/* + * 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 SecCodeSigner + SecCodeSigner represents an object that can sign code. +*/ +#ifndef _H_SECCODESIGNER +#define _H_SECCODESIGNER + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/*! + @typedef SecCodeSignerRef + This is the type of a reference to a code requirement. +*/ +typedef struct __SecCodeSigner *SecCodeSignerRef; /* code signing object */ + + +/*! + @function SecCodeGetTypeID + Returns the type identifier of all SecCodeSigner instances. +*/ +CFTypeID SecCodeSignerGetTypeID(void); + + +/*! + The following CFString constants can be used as keys in the parameters argument + of SecCodeSignerCreate to specify various modes and options of the signing operation. + Passing any keys not specified here may lead to undefined behavior and is not supported. + The same applies to passing objects of types not explicitly allowed here. + + @constant kSecCodeSignerDetached Determines where the signature is written. + If this key is absent, the code being signed is modified to contain the signature, + replacing any signature already embedded there. + If the value is kCFNull, the signature is written to the system-wide detached + signature database. (You must have root privileges to write there.) + If the value of this key is a CFURL, the signature is written to a file at that location, + replacing any data there. + If the value is a CFMutableData, the signature is appended to that data. + @constant kSecCodeSignerDryRun A boolean value. If present and true, the actual writing + of the signature is inhibited, and the code is not modified, but all operations + leading up to this are performed normally, including the cryptographic access to + the signing identity (if any). + @constant kSecCodeSignerFlags A CFNumber specifying which flags to set in the code signature. + Note that depending on circumstances, this value may be augmented or modified + as part of the signing operation. + @constant kSecCodeSignerIdentifier If present, a CFString that explicitly specifies + the unique identifier string sealed into the code signature. If absent, the identifier + is derived implicitly from the code being signed. + @constant kSecCodeSignerIdentifierPrefix If the unique identifier string of the code signature + is implicitly generated, and the resulting string does not contain any "." (dot) + characters, then the (string) value of this parameter is prepended to the identifier. + By convention, the prefix is usually of the form "com.yourcompany.", but any value + is acceptable. If the kSecCodeSignerIdentifier parameter is specified, this parameter + is ineffective (but still allowed). + @constant kSecCodeSignerIdentity A SecIdentityRef describing the signing identity + to use for signing code. This is a mandatory parameter for signing operations. + Its value must be either a SecIdentityRef specifying a cryptographic identity + valid for Code Signing, or the special value kCFNull to indicate ad-hoc signing. + @constant kSecCodeSignerOperation The type of operation to be performed. Valid values + are kSecCodeSignerOperationSign to sign code, and kSecCodeSignerOperationRemove + to remove any existing signature from code. The default operation is to sign code. + @constant kSecCodeSignerPageSize An integer value explicitly specifying the page size + used to sign the main executable. This must be a power of two. A value of zero indicates + infinite size (no paging). + Only certain page sizes are allowed in most circumstances, and specifying an inappropriate + size will lead to spurious verification failures. This is for expert use only. + @constant kSecCodeSignerRequirements Specifies the internal requirements to be sealed into + the code signature. Must be either a CFData containing the binary (compiled) form of + a requirements set (SuperBlob), or a CFString containing a valid text form to be + compiled into binary form. Default requirements are automatically generated if this + parameter is omitted, and defaults may be applied to particular requirement types + that are not specified; but any requirement type you specify is sealed exactly as + specified. + @constant kSecCodeSignerResourceRules A CFDictionary containing resource scanning rules + determining what resource files are sealed into the signature (and in what way). + A situation-dependent default is applied if this parameter is not specified. + @constant kSecCodeSignerSDKRoot A CFURLRef indicating an alterate directory root + where signing operations should find subcomponents (libraries, frameworks, modules, etc.). + The default is the host system root "/". + @constant kSecCodeSignerSigningTime Specifies what date and time is sealed into the + code signature's CMS data. Can be either a CFDate object specifying a date, or + the value kCFNull indicating that no date should be included in the signature. + If not specified, the current date is chosen and sealed. + Since an ad-hoc signature has no CMS data, this argument is ineffective + for ad-hoc signing operations. + @constant kSecCodeSignerRequireTimestamp A CFBoolean indicating (if kCFBooleanTrue) that + the code signature should be certified by a timestamp authority service. This option + requires access to a timestamp server (usually over the Internet). If requested and + the timestamp server cannot be contacted or refuses service, the signing operation fails. + The timestamp value is not under the caller's control. + If the value is kCFBooleanFalse, no timestamp service is contacted and the resulting signature + has no certified timestamp. + If this key is omitted, a default is used that may vary from release to release. + Note that when signing multi-architectural ("fat") programs, each architecture will + be signed separately, and thus each architecture will have a slightly different timestamp. + @constant kSecCodeSignerTimestampServer A CFURL specifying which timestamp authority service + to contact for timestamping if requested by the kSecCodeSignerRequireTimestamp argument. + If omitted (and timestamping is performed), a system-defined default value is used, referring + to an Apple-operated timestamp service. Note that this service may not freely serve all requests. + @constant kSecCodeSignerTimestampAuthentication A SecIdentityRef describing the identity + used to authenticate to the timestamp authority server, if the server requires client-side + (SSL/TLS) authentication. This will not generally be the identity used to sign the actual + code, depending on the requirements of the timestamp authority service used. + If omitted, the timestamp server is contacted using unauthenticated HTTP requests. + @constant kSecCodeSignerTimestampOmitCertificates A CFBoolean indicating (if kCFBooleanTrue) + that the timestamp embedded in the signature, if requested, not contain the full certificate chain + of the timestamp service used. This will make for a marginally smaller signature, but may not + verify correctly unless all such certificates are available (through the keychain system) + on the verifying system. + The default is to embed enough certificates to ensure proper verification of Apple-generated + timestamp signatures. + */ +extern const CFStringRef kSecCodeSignerApplicationData; +extern const CFStringRef kSecCodeSignerDetached; +extern const CFStringRef kSecCodeSignerDigestAlgorithm; +extern const CFStringRef kSecCodeSignerDryRun; +extern const CFStringRef kSecCodeSignerEntitlements; +extern const CFStringRef kSecCodeSignerFlags; +extern const CFStringRef kSecCodeSignerIdentifier; +extern const CFStringRef kSecCodeSignerIdentifierPrefix; +extern const CFStringRef kSecCodeSignerIdentity; +extern const CFStringRef kSecCodeSignerPageSize; +extern const CFStringRef kSecCodeSignerRequirements; +extern const CFStringRef kSecCodeSignerResourceRules; +extern const CFStringRef kSecCodeSignerSDKRoot; +extern const CFStringRef kSecCodeSignerSigningTime; +extern const CFStringRef kSecCodeSignerTimestampAuthentication; +extern const CFStringRef kSecCodeSignerRequireTimestamp; +extern const CFStringRef kSecCodeSignerTimestampServer; +extern const CFStringRef kSecCodeSignerTimestampOmitCertificates; + +// temporary add-back to bridge B&I build dependencies -- remove soon +extern const CFStringRef kSecCodeSignerTSAUse; +extern const CFStringRef kSecCodeSignerTSAURL; +extern const CFStringRef kSecCodeSignerTSAClientAuth; +extern const CFStringRef kSecCodeSignerTSANoCerts; + + +/*! + @function SecCodeSignerCreate + Create a (new) SecCodeSigner object to be used for signing code. + + @param parameters An optional CFDictionary containing parameters that influence + signing operations with the newly created SecCodeSigner. If NULL, defaults + are applied to all parameters; note however that some parameters do not have + useful defaults, and will need to be set before signing is attempted. + @param flags Optional flags. Pass kSecCSDefaultFlags for standard behavior. + The kSecCSRemoveSignature flag requests that any existing signature be stripped + from the target code instead of signing. + @param staticCode On successful return, a SecStaticCode object reference representing + the file system origin of the given SecCode. On error, unchanged. + @result Upon success, noErr. Upon error, an OSStatus value documented in + CSCommon.h or certain other Security framework headers. +*/ +enum { + kSecCSRemoveSignature = 1 << 0, // strip existing signature +}; + + +OSStatus SecCodeSignerCreate(CFDictionaryRef parameters, SecCSFlags flags, + SecCodeSignerRef *signer); + + +/*! + @function SecCodeSignerAddSignature + Create a code signature and add it to the StaticCode object being signed. + + @param signer A SecCodeSigner object containing all the information required + to sign code. + @param code A valid SecStaticCode object reference representing code files + on disk. This code will be signed, and will ordinarily be modified to contain + the resulting signature data. + @param flags Optional flags. Pass kSecCSDefaultFlags for standard behavior. + @param errors An optional pointer to a CFErrorRef variable. If the call fails + (and something other than noErr is returned), and this argument is non-NULL, + a CFErrorRef is stored there further describing the nature and circumstances + of the failure. The caller must CFRelease() this error object when done with it. + @result Upon success, noErr. Upon error, an OSStatus value documented in + CSCommon.h or certain other Security framework headers. +*/ +OSStatus SecCodeSignerAddSignature(SecCodeSignerRef signer, + SecStaticCodeRef code, SecCSFlags flags); + +OSStatus SecCodeSignerAddSignatureWithErrors(SecCodeSignerRef signer, + SecStaticCodeRef code, SecCSFlags flags, CFErrorRef *errors); + + +#ifdef __cplusplus +} +#endif + +#endif //_H_SECCODESIGNER diff --git a/libsecurity_codesigning/lib/SecIntegrity.cpp b/libsecurity_codesigning/lib/SecIntegrity.cpp new file mode 100644 index 00000000..5bbb6035 --- /dev/null +++ b/libsecurity_codesigning/lib/SecIntegrity.cpp @@ -0,0 +1,26 @@ +/* + * 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@ + */ +#include +#include "SecIntegrity.h" + + diff --git a/libsecurity_codesigning/lib/SecIntegrity.h b/libsecurity_codesigning/lib/SecIntegrity.h new file mode 100644 index 00000000..c8fb0699 --- /dev/null +++ b/libsecurity_codesigning/lib/SecIntegrity.h @@ -0,0 +1,49 @@ +/* + * 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 SecIntegrity + This header provides functionality that allows a program to use its own + code signature to extend trust to parts of its bundle that it covers. + + This file does not help you verify code signatures themselves; use SecCode.h + for that. It is reasonable to use SecCode.h and SecIntegrity.h together. +*/ +#ifndef _H_SECINTEGRITY +#define _H_SECINTEGRITY + +#include + +#ifdef __cplusplus +extern "C" { +#endif + + + + + +#ifdef __cplusplus +} +#endif + +#endif //_H_SECINTEGRITY diff --git a/libsecurity_codesigning/lib/SecIntegrityLib.c b/libsecurity_codesigning/lib/SecIntegrityLib.c new file mode 100644 index 00000000..a6ffb626 --- /dev/null +++ b/libsecurity_codesigning/lib/SecIntegrityLib.c @@ -0,0 +1,23 @@ +/* + * 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@ + */ +#include "SecIntegrityLib.h" diff --git a/libsecurity_codesigning/lib/SecIntegrityLib.h b/libsecurity_codesigning/lib/SecIntegrityLib.h new file mode 100644 index 00000000..b0960c65 --- /dev/null +++ b/libsecurity_codesigning/lib/SecIntegrityLib.h @@ -0,0 +1,55 @@ +/* + * 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 SecIntegrityLib + This header provides a subset of the code-integrity API for Code Signing. + This subset functionality is implemented as a static library written + entirely in C, and depends on nothing except the system library and the + C runtime. It is thus suitable to be used by low-level libraries and + other such system facilities. On the other hand, it does not provide the + full functionality of . + + This file is documented as a delta to , which + you should consult as a baseline. +*/ +#ifndef _H_SECINTEGRITYLIB +#define _H_SECINTEGRITYLIB + +#include "SecIntegrity.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/* + This file is not yet published. + */ + + +#ifdef __cplusplus +} +#endif + +#endif //_H_SECINTEGRITYLIB diff --git a/libsecurity_codesigning/lib/SecRequirement.cpp b/libsecurity_codesigning/lib/SecRequirement.cpp new file mode 100644 index 00000000..68d95e45 --- /dev/null +++ b/libsecurity_codesigning/lib/SecRequirement.cpp @@ -0,0 +1,307 @@ +/* + * 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@ + */ + +// +// SecRequirement - API frame for SecRequirement objects +// +#include "cs.h" +#include "Requirements.h" +#include "reqparser.h" +#include "reqmaker.h" +#include "reqdumper.h" +#include +#include + +using namespace CodeSigning; + + +// +// CF-standard type code function +// +CFTypeID SecRequirementGetTypeID(void) +{ + BEGIN_CSAPI + return gCFObjects().Requirement.typeID; + END_CSAPI1(_kCFRuntimeNotATypeID) +} + + +// +// Create a Requirement from data +// +OSStatus SecRequirementCreateWithData(CFDataRef data, SecCSFlags flags, + SecRequirementRef *requirementRef) +{ + BEGIN_CSAPI + + checkFlags(flags); + CodeSigning::Required(requirementRef) = (new SecRequirement(CFDataGetBytePtr(data), CFDataGetLength(data)))->handle(); + + END_CSAPI +} + + +// +// Create a Requirement from data in a file +// +OSStatus SecRequirementCreateWithResource(CFURLRef resource, SecCSFlags flags, + SecRequirementRef *requirementRef) +{ + BEGIN_CSAPI + + checkFlags(flags); + CFRef data = cfLoadFile(resource); + CodeSigning::Required(requirementRef) = + (new SecRequirement(CFDataGetBytePtr(data), CFDataGetLength(data)))->handle(); + + END_CSAPI +} + + +// +// Create a Requirement from source text (compiling it) +// +OSStatus SecRequirementCreateWithString(CFStringRef text, SecCSFlags flags, + SecRequirementRef *requirementRef) +{ + return SecRequirementCreateWithStringAndErrors(text, flags, NULL, requirementRef); +} + +OSStatus SecRequirementCreateWithStringAndErrors(CFStringRef text, SecCSFlags flags, + CFErrorRef *errors, SecRequirementRef *requirementRef) +{ + BEGIN_CSAPI + + checkFlags(flags); + CodeSigning::Required(requirementRef) = (new SecRequirement(parseRequirement(cfString(text)), true))->handle(); + + END_CSAPI_ERRORS +} + + +// +// Create a Requirement group. +// This is the canonical point where "application group" is defined. +// +OSStatus SecRequirementCreateGroup(CFStringRef groupName, SecCertificateRef anchorRef, + SecCSFlags flags, SecRequirementRef *requirementRef) +{ + BEGIN_CSAPI + + checkFlags(flags); + Requirement::Maker maker; + maker.put(opAnd); // both of... + maker.infoKey("Application-Group", cfString(groupName)); + if (anchorRef) { + CSSM_DATA certData; + MacOSError::check(SecCertificateGetData(anchorRef, &certData)); + maker.anchor(0, certData.Data, certData.Length); + } else { + maker.anchor(); // canonical Apple anchor + } + CodeSigning::Required(requirementRef) = (new SecRequirement(maker.make(), true))->handle(); + + END_CSAPI +} + + +// +// Extract the stable binary from from a SecRequirementRef +// +OSStatus SecRequirementCopyData(SecRequirementRef requirementRef, SecCSFlags flags, + CFDataRef *data) +{ + BEGIN_CSAPI + + const Requirement *req = SecRequirement::required(requirementRef)->requirement(); + checkFlags(flags); + CodeSigning::Required(data); + *data = makeCFData(*req); + + END_CSAPI +} + + +// +// Generate source form for a SecRequirement (decompile/disassemble) +// +OSStatus SecRequirementCopyString(SecRequirementRef requirementRef, SecCSFlags flags, + CFStringRef *text) +{ + BEGIN_CSAPI + + const Requirement *req = SecRequirement::required(requirementRef)->requirement(); + checkFlags(flags); + CodeSigning::Required(text); + *text = makeCFString(Dumper::dump(req)); + + END_CSAPI +} + + +// +CFStringRef kSecRequirementKeyInfoPlist = CFSTR("requirement:eval:info"); +CFStringRef kSecRequirementKeyEntitlements = CFSTR("requirement:eval:entitlements"); +CFStringRef kSecRequirementKeyIdentifier = CFSTR("requirement:eval:identifier"); + +OSStatus SecRequirementEvaluate(SecRequirementRef requirementRef, + CFArrayRef certificateChain, CFDictionaryRef context, + SecCSFlags flags) +{ + BEGIN_CSAPI + + const Requirement *req = SecRequirement::required(requirementRef)->requirement(); + checkFlags(flags); + CodeSigning::Required(certificateChain); + + Requirement::Context ctx(certificateChain, // mandatory + context ? CFDictionaryRef(CFDictionaryGetValue(context, kSecRequirementKeyInfoPlist)) : NULL, + context ? CFDictionaryRef(CFDictionaryGetValue(context, kSecRequirementKeyEntitlements)) : NULL, + (context && CFDictionaryGetValue(context, kSecRequirementKeyIdentifier)) ? + cfString(CFStringRef(CFDictionaryGetValue(context, kSecRequirementKeyIdentifier))) : "", + NULL // can't specify a CodeDirectory here + ); + req->validate(ctx); + + END_CSAPI +} + + +// +// Assemble a requirement set (as a CFData) from a dictionary of requirement objects. +// An empty set is allowed. +// +OSStatus SecRequirementsCreateFromRequirements(CFDictionaryRef requirements, SecCSFlags flags, + CFDataRef *requirementSet) +{ + BEGIN_CSAPI + + checkFlags(flags); + if (requirements == NULL) + return errSecCSObjectRequired; + CFIndex count = CFDictionaryGetCount(requirements); + CFNumberRef keys[count]; + SecRequirementRef reqs[count]; + CFDictionaryGetKeysAndValues(requirements, (const void **)keys, (const void **)reqs); + Requirements::Maker maker; + for (CFIndex n = 0; n < count; n++) { + const Requirement *req = SecRequirement::required(reqs[n])->requirement(); + maker.add(cfNumber(keys[n]), req->clone()); + } + Requirements *reqset = maker.make(); // malloc'ed + CodeSigning::Required(requirementSet) = makeCFDataMalloc(*reqset); // takes ownership of reqs + + END_CSAPI +} + + +// +// Break a requirement set (given as a CFData) into its constituent requirements +// and return it as a CFDictionary. +// +OSStatus SecRequirementsCopyRequirements(CFDataRef requirementSet, SecCSFlags flags, + CFDictionaryRef *requirements) +{ + BEGIN_CSAPI + + checkFlags(flags); + if (requirementSet == NULL) + return errSecCSObjectRequired; + const Requirements *reqs = (const Requirements *)CFDataGetBytePtr(requirementSet); + CFRef dict = makeCFMutableDictionary(); + unsigned count = reqs->count(); + for (unsigned n = 0; n < count; n++) { + CFRef req = (new SecRequirement(reqs->blob(n)))->handle(); + CFDictionaryAddValue(dict, CFTempNumber(reqs->type(n)), req); + } + CodeSigning::Required(requirements) = dict.yield(); + + END_CSAPI +} + + +// +// Generically parse a string as some kind of requirement-related source form. +// If properly recognized, return the result as a CF object: +// SecRequirementRef for a single requirement +// CFDataRef for a requirement set +// +OSStatus SecRequirementsCreateWithString(CFStringRef text, SecCSFlags flags, + CFTypeRef *result, CFErrorRef *errors) +{ + BEGIN_CSAPI + + checkFlags(flags, kSecCSParseRequirement | kSecCSParseRequirementSet); + if (text == NULL || result == NULL) + return errSecCSObjectRequired; + std::string s = cfString(text); + switch (flags & (kSecCSParseRequirement | kSecCSParseRequirementSet)) { + case kSecCSParseRequirement: // single only + *result = (new SecRequirement(parseRequirement(s), true))->handle(); + break; + case kSecCSParseRequirementSet: // single only + { + const Requirements *reqs = parseRequirements(s); + *result = makeCFDataMalloc(*reqs); + break; + } + case 0: + case kSecCSParseRequirement | kSecCSParseRequirementSet: + { + const BlobCore *any = parseGeneric(s); + if (any->is()) + *result = (new SecRequirement(Requirement::specific(any), true))->handle(); + else + *result = makeCFDataMalloc(*any); + break; + } + } + + END_CSAPI_ERRORS +} + + +// +// Convert a SecRequirementRef or a CFDataRef containing a requirement set to text. +// Requirement sets will be formatted as multiple lines (one per requirement). They can be empty. +// A single requirement will return a single line that is NOT newline-terminated. +// +OSStatus SecRequirementsCopyString(CFTypeRef input, SecCSFlags flags, CFStringRef *text) +{ + BEGIN_CSAPI + + checkFlags(flags); + if (input == NULL) + return errSecCSObjectRequired; + if (CFGetTypeID(input) == SecRequirementGetTypeID()) { + return SecRequirementCopyString(SecRequirementRef(input), flags, text); + } else if (CFGetTypeID(input) == CFDataGetTypeID()) { + const Requirements *reqs = (const Requirements *)CFDataGetBytePtr(CFDataRef(input)); + if (!reqs->validateBlob(CFDataGetLength(CFDataRef(input)))) + return errSecCSReqInvalid; + CodeSigning::Required(text) = makeCFString(Dumper::dump(reqs, false)); + } else + return errSecCSInvalidObjectRef; + + END_CSAPI +} diff --git a/libsecurity_codesigning/lib/SecRequirement.h b/libsecurity_codesigning/lib/SecRequirement.h new file mode 100644 index 00000000..9a11c6f9 --- /dev/null +++ b/libsecurity_codesigning/lib/SecRequirement.h @@ -0,0 +1,140 @@ +/* + * 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@ + */ + +/*! + @header SecRequirement + SecRequirement represents a condition or constraint (a "Code Requirement") + that code must satisfy to be considered valid for some purpose. + SecRequirement itself does not understand or care WHY such a constraint + is appropriate or useful; it is purely a tool for formulating, recording, + and evaluating it. + + Code Requirements are usually stored and retrieved in the form of a variable-length + binary Blob that can be encapsulated as a CFDataRef and safely stored in various + data structures. They can be formulated in a text form that can be compiled + into binary form and decompiled back into text form without loss of functionality + (though comments and formatting are not preserved). +*/ +#ifndef _H_SECREQUIREMENT +#define _H_SECREQUIREMENT + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +/*! + @function SecRequirementGetTypeID + Returns the type identifier of all SecRequirement instances. +*/ +CFTypeID SecRequirementGetTypeID(void); + + +/*! + @function SecRequirementCreateWithData + Create a SecRequirement object from binary form. + This is the effective inverse of SecRequirementCopyData. + + @param data A binary blob obtained earlier from a valid SecRequirement object + using the SecRequirementCopyData call. This is the only publicly supported + way to get such a data blob. + @param flags Optional flags. Pass kSecCSDefaultFlags for standard behavior. + @param requirement On successful return, contains a reference to a SecRequirement + object that behaves identically to the one the data blob was obtained from. + @result Upon success, noErr. Upon error, an OSStatus value documented in + CSCommon.h or certain other Security framework headers. +*/ +OSStatus SecRequirementCreateWithData(CFDataRef data, SecCSFlags flags, + SecRequirementRef *requirement); + + +/*! + @function SecRequirementCreateWithString + Create a SecRequirement object by compiling a valid text representation + of a requirement. + + @param text A CFString containing the text form of a (single) Code Requirement. + @param flags Optional flags. Pass kSecCSDefaultFlags for standard behavior. + @param requirement On successful return, contains a reference to a SecRequirement + object that implements the conditions described in text. + @param errors An optional pointer to a CFErrorRef variable. If the call fails + (and something other than noErr is returned), and this argument is non-NULL, + a CFErrorRef is stored there further describing the nature and circumstances + of the failure. The caller must CFRelease() this error object when done with it. + @result Upon success, noErr. Upon error, an OSStatus value documented in + CSCommon.h or certain other Security framework headers. +*/ +OSStatus SecRequirementCreateWithString(CFStringRef text, SecCSFlags flags, + SecRequirementRef *requirement); + +OSStatus SecRequirementCreateWithStringAndErrors(CFStringRef text, SecCSFlags flags, + CFErrorRef *errors, SecRequirementRef *requirement); + + +/*! + @function SecRequirementCopyData + Extracts a stable, persistent binary form of a SecRequirement. + This is the effective inverse of SecRequirementCreateWithData. + + @param requirement A valid SecRequirement object. + @param flags Optional flags. Pass kSecCSDefaultFlags for standard behavior. + @param data On successful return, contains a reference to a CFData object + containing a binary blob that can be fed to SecRequirementCreateWithData + to recreate a SecRequirement object with identical behavior. + @result Upon success, noErr. Upon error, an OSStatus value documented in + CSCommon.h or certain other Security framework headers. +*/ +OSStatus SecRequirementCopyData(SecRequirementRef requirement, SecCSFlags flags, + CFDataRef *data); + + +/*! + @function SecRequirementCopyString + Converts a SecRequirement object into text form. + This is the effective inverse of SecRequirementCreateWithString. + + Repeated application of this function may produce text that differs in + formatting, may contain different source comments, and may perform its + validation functions in different order. However, it is guaranteed that + recompiling the text using SecRequirementCreateWithString will produce a + SecRequirement object that behaves identically to the one you start with. + + @param requirement A valid SecRequirement object. + @param flags Optional flags. Pass kSecCSDefaultFlags for standard behavior. + @param text On successful return, contains a reference to a CFString object + containing a text representation of the requirement. + @result Upon success, noErr. Upon error, an OSStatus value documented in + CSCommon.h or certain other Security framework headers. +*/ +OSStatus SecRequirementCopyString(SecRequirementRef requirement, SecCSFlags flags, + CFStringRef *text); + + +#ifdef __cplusplus +} +#endif + +#endif //_H_SECREQUIREMENT diff --git a/libsecurity_codesigning/lib/SecRequirementPriv.h b/libsecurity_codesigning/lib/SecRequirementPriv.h new file mode 100644 index 00000000..44055769 --- /dev/null +++ b/libsecurity_codesigning/lib/SecRequirementPriv.h @@ -0,0 +1,197 @@ +/* + * 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@ + */ + +/*! + @header SecRequirement + SecRequirementPriv is the private counter-part to SecRequirement. Its contents are not + official API, and are subject to change without notice. +*/ +#ifndef _H_SECREQUIREMENTPRIV +#define _H_SECREQUIREMENTPRIV + +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +/*! + @function SecRequirementsCreateFromRequirements + Take a dictionary of requirement objects and package them up as a requirement set. + + @param requirements A dictionary of requirements to combine into a set. + Dictionary keys are CFNumbers representing the index keys. Values are SecRequirementRefs. + NULL requirements are not allowed in the dictionary. + @param flags Optional flags. Pass kSecCSDefaultFlags for standard behavior. + @param requirementSet Upon success, receives a CFData object + @result Upon success, noErr. Upon error, an OSStatus value documented in + CSCommon.h or certain other Security framework headers. +*/ +OSStatus SecRequirementsCreateFromRequirements(CFDictionaryRef requirements, SecCSFlags flags, + CFDataRef *requirementSet); + + +/*! + @function SecRequirementsCopyRequirements + Create a SecRequirement object from binary form obtained from a file. + This call is functionally equivalent to reading the entire contents of a file + into a CFDataRef and then calling SecRequirementCreateWithData with that. + + @param requirementSet A CFData containing a requirement set. + @param flags Optional flags. Pass kSecCSDefaultFlags for standard behavior. + @param requirements Upon success, a dictionary containing each requirement contained + in requirementSet. The keys are CFNumbers indicating the requirement type. + @result Upon success, noErr. Upon error, an OSStatus value documented in + CSCommon.h or certain other Security framework headers. +*/ +OSStatus SecRequirementsCopyRequirements(CFDataRef requirementSet, SecCSFlags flags, + CFDictionaryRef *requirements); + + +/*! + @function SecRequirementsCreateWithString + Create a SecRequirement object or requirement set based on the string provided. + + @param text A CFString containing the text form of a (single) Code Requirement. + @param flags Optional flags. Pass kSecCSDefaultFlags to accept any supported input form. + Pass a combination of individual flags to select what forms to accept; other forms will result + in an error. + @param result Upon success, a CoreFoundation object of some kind representing + the result of parsing text. Depending on the input string and flags, the result + can be a SecRequirementRef (for a single requirement) or a CFDataRef for a requirement set. + @param errors An optional pointer to a CFErrorRef variable. If the call fails + (and something other than noErr is returned), and this argument is non-NULL, + a CFErrorRef is stored there further describing the nature and circumstances + of the failure. The caller must CFRelease() this error object when done with it. + @result Upon success, noErr. Upon error, an OSStatus value documented in + CSCommon.h or certain other Security framework headers. +*/ +enum { + kSecCSParseRequirement = 0x0001, // accept single requirements + kSecCSParseRequirementSet = 0x0002, // accept requirement sets +}; + +OSStatus SecRequirementsCreateWithString(CFStringRef text, SecCSFlags flags, + CFTypeRef *result, CFErrorRef *errors); + + +/*! + @function SecRequirementsCopyString + Converts a requirement object of some kind into text form. + This is the effective inverse of SecRequirementsCreateWithString. + + This function can process individual requirements (SecRequirementRefs) + and requirement sets (represented as CFDataRefs). + + Repeated application of this function may produce text that differs in + formatting, may contain different source comments, and may perform its + validation functions in different order. However, it is guaranteed that + recompiling the text using SecRequirementCreateWithString will produce a + SecRequirement object that behaves identically to the one you start with. + + @param requirements A SecRequirementRef, or a CFDataRef containing a valid requirement set. + @param flags Optional flags. Pass kSecCSDefaultFlags for standard behavior. + @param text On successful return, contains a reference to a CFString object + containing a text representation of the requirement. + @result Upon success, noErr. Upon error, an OSStatus value documented in + CSCommon.h or certain other Security framework headers. +*/ +OSStatus SecRequirementsCopyString(CFTypeRef input, SecCSFlags flags, CFStringRef *text); + + +/*! + @function SecRequirementCreateWithResource + Create a SecRequirement object from binary form obtained from a file. + This call is functionally equivalent to reading the entire contents of a file + into a CFDataRef and then calling SecRequirementCreateWithData with that. + + @param resource A CFURL identifying a file containing a (binary) requirement blob. + @param flags Optional flags. Pass kSecCSDefaultFlags for standard behavior. + @param requirement On successful return, contains a reference to a SecRequirement + object that behaves identically to the one the data blob was obtained from. + @result Upon success, noErr. Upon error, an OSStatus value documented in + CSCommon.h or certain other Security framework headers. +*/ +OSStatus SecRequirementCreateWithResource(CFURLRef resource, SecCSFlags flags, + SecRequirementRef *requirement); + + +/*! + @function SecRequirementCreateGroup + Create a SecRequirement object that represents membership in a developer-defined + application group. Group membership is defined by an entry in the code's + Info.plist, and sealed to a particular signing authority. + + This is not an API-track function. Don't call it if you don't already do. + + @param groupName A CFString containing the name of the desired application group. + @param anchor A reference to a digital certificate representing the signing + authority that asserts group membership. If NULL, indicates Apple's authority. + @param flags Optional flags. Pass kSecCSDefaultFlags for standard behavior. + @param requirement On successful return, contains a reference to a SecRequirement + object that requires group membership to pass validation. + @result Upon success, noErr. Upon error, an OSStatus value documented in + CSCommon.h or certain other Security framework headers. +*/ +OSStatus SecRequirementCreateGroup(CFStringRef groupName, SecCertificateRef anchor, + SecCSFlags flags, SecRequirementRef *requirement); + + + +/*! + @function SecRequirementEvaluate + Explicitly evaluate a SecRequirementRef against context provided in the call. + This allows evaluation of a code requirement outside the context of a code signature. + + @param requirement A valid SecRequirement object. + @param certificateChain A CFArray of SecCertificate objects describing the certificate + chain of the object being validated. This must be a full chain terminating in an anchor + certificate that is cryptographically valid. + @param context An optional CFDictionary containing additional context made available + to the requirement program's evaluation. NULL is equivalent to an empty dictionary. + @param flags Optional flags. Pass kSecCSDefaultFlags for standard behavior. + @result Upon success, noErr. Failure to pass the check returns errSecCSReqFailed. + All other returns indicate errors as documented in CSCommon.h or certain other + Security framework headers. + + @constant kSecRequirementKeyInfoPlist A context key providing an CFDictionary denoting + an Info.plist. If this key is missing, all references to Info.plist contents will fail. + @constant kSecRequirementKeyEntitlements A context key providing an CFDictionary describing + an entitlement dictionary. If this key is missing, all references to entitlements will fail. + @constant kSecRequirementKeyIdentifier A context key providing the signing identifier as a CFString. +*/ +extern CFStringRef kSecRequirementKeyInfoPlist; +extern CFStringRef kSecRequirementKeyEntitlements; +extern CFStringRef kSecRequirementKeyIdentifier; + +OSStatus SecRequirementEvaluate(SecRequirementRef requirement, + CFArrayRef certificateChain, CFDictionaryRef context, + SecCSFlags flags); + + +#ifdef __cplusplus +} +#endif + +#endif //_H_SECREQUIREMENTPRIV diff --git a/libsecurity_codesigning/lib/SecStaticCode.cpp b/libsecurity_codesigning/lib/SecStaticCode.cpp new file mode 100644 index 00000000..7cb5a17e --- /dev/null +++ b/libsecurity_codesigning/lib/SecStaticCode.cpp @@ -0,0 +1,301 @@ +/* + * Copyright (c) 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@ + */ + +// +// SecStaticCode - API frame for SecStaticCode objects +// +#include "cs.h" +#include "StaticCode.h" +#include +#include +#include + +using namespace CodeSigning; + + +// +// CF-standard type code function +// +CFTypeID SecStaticCodeGetTypeID(void) +{ + BEGIN_CSAPI + return gCFObjects().StaticCode.typeID; + END_CSAPI1(_kCFRuntimeNotATypeID) +} + + +// +// Create an StaticCode directly from disk path. +// +OSStatus SecStaticCodeCreateWithPath(CFURLRef path, SecCSFlags flags, SecStaticCodeRef *staticCodeRef) +{ + BEGIN_CSAPI + + checkFlags(flags); + CodeSigning::Required(staticCodeRef) = (new SecStaticCode(DiskRep::bestGuess(cfString(path).c_str())))->handle(); + + END_CSAPI +} + +const CFStringRef kSecCodeAttributeArchitecture = CFSTR("architecture"); +const CFStringRef kSecCodeAttributeSubarchitecture =CFSTR("subarchitecture"); +const CFStringRef kSecCodeAttributeBundleVersion = CFSTR("bundleversion"); + +OSStatus SecStaticCodeCreateWithPathAndAttributes(CFURLRef path, SecCSFlags flags, CFDictionaryRef attributes, + SecStaticCodeRef *staticCodeRef) +{ + BEGIN_CSAPI + + checkFlags(flags); + DiskRep::Context ctx; + std::string version; // holds memory placed into ctx + if (attributes) { + std::string archName; + int archNumber, subarchNumber; + if (cfscan(attributes, "{%O=%s}", kSecCodeAttributeArchitecture, &archName)) { + ctx.arch = Architecture(archName.c_str()); + } else if (cfscan(attributes, "{%O=%d,%O=%d}", + kSecCodeAttributeArchitecture, &archNumber, kSecCodeAttributeSubarchitecture, &subarchNumber)) + ctx.arch = Architecture(archNumber, subarchNumber); + else if (cfscan(attributes, "{%O=%d}", kSecCodeAttributeArchitecture, &archNumber)) + ctx.arch = Architecture(archNumber); + 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 +} + + +// +// Check static validity of a StaticCode +// +static void validate(SecStaticCode *code, const SecRequirement *req, SecCSFlags flags); +static void validateNested(string location, const SecRequirement *req, SecCSFlags flags, string exclude = "/"); + +static void validate(SecStaticCode *code, const SecRequirement *req, SecCSFlags flags) +{ + try { + code->validateNonResourceComponents(); // also validates the CodeDirectory + if (!(flags & kSecCSDoNotValidateExecutable)) + code->validateExecutable(); + if (!(flags & kSecCSDoNotValidateResources)) + code->validateResources(); + if (req) + code->validateRequirement(req->requirement(), errSecCSReqFailed); + if (flags & kSecCSCheckNestedCode) + if (CFURLRef baseUrl = code->resourceBase()) { + // CFBundle has no orderly enumerator of these things, so this is somewhat ad-hoc. + // (It should be augmented by information in ResourceDirectory.) + string base = cfString(baseUrl) + "/"; + validateNested(base + "Frameworks", req, flags); + validateNested(base + "SharedFrameworks", req, flags); + validateNested(base + "PlugIns", req, flags); + validateNested(base + "Plug-ins", req, flags); + validateNested(base + "XPCServices", req, flags); + validateNested(base + "MacOS", req, flags, code->mainExecutablePath()); // helpers + } + } catch (CSError &err) { + if (Universal *fat = code->diskRep()->mainExecutableImage()) // Mach-O + if (MachO *mach = fat->architecture()) { + err.augment(kSecCFErrorArchitecture, CFTempString(mach->architecture().displayName())); + delete mach; + } + throw; + } catch (const MacOSError &err) { + // add architecture information if we can get it + if (Universal *fat = code->diskRep()->mainExecutableImage()) + if (MachO *mach = fat->architecture()) { + CFTempString arch(mach->architecture().displayName()); + delete mach; + CSError::throwMe(err.error, kSecCFErrorArchitecture, arch); + } + // else just pass it on + throw; + } +} + +static void validateNested(string location, const SecRequirement *req, SecCSFlags flags, string exclude) +{ + DIR *dir = opendir(location.c_str()); + if (dir == 0) { + if (errno == ENOENT) // nothing there (okay) + return; + UnixError::throwMe(); + } + while (struct dirent *dp = readdir(dir)) { + switch (dp->d_type) { + case DT_REG: + case DT_LNK: + case DT_DIR: + break; + default: + continue; + } + if (dp->d_name[0] == '.') + continue; + string path = location + "/" + dp->d_name; + if (path == exclude) // main executable; skip + continue; + try { + SecPointer code = new SecStaticCode(DiskRep::bestGuess(path)); + validate(code, req, flags); + } catch (CSError &err) { + err.augment(kSecCFErrorPath, CFTempURL(path)); + throw; + } + } + closedir(dir); +} + + +OSStatus SecStaticCodeCheckValidity(SecStaticCodeRef staticCodeRef, SecCSFlags flags, + SecRequirementRef requirementRef) +{ + return SecStaticCodeCheckValidityWithErrors(staticCodeRef, flags, requirementRef, NULL); +} + +OSStatus SecStaticCodeCheckValidityWithErrors(SecStaticCodeRef staticCodeRef, SecCSFlags flags, + SecRequirementRef requirementRef, CFErrorRef *errors) +{ + BEGIN_CSAPI + + checkFlags(flags, + kSecCSCheckAllArchitectures + | kSecCSDoNotValidateExecutable + | kSecCSDoNotValidateResources + | kSecCSConsiderExpiration + | kSecCSEnforceRevocationChecks + | kSecCSCheckNestedCode); + + SecPointer code = SecStaticCode::requiredStatic(staticCodeRef); + const SecRequirement *req = SecRequirement::optional(requirementRef); + DTRACK(CODESIGN_EVAL_STATIC, code, (char*)code->mainExecutablePath().c_str()); + if (flags & kSecCSCheckAllArchitectures) { + SecStaticCode::AllArchitectures archs(code); + while (SecPointer scode = archs()) + validate(scode, req, flags); + } else + validate(code, req, flags); + + END_CSAPI_ERRORS +} + + +// +// ==================================================================================== +// +// The following API functions are called SecCode* but accept both SecCodeRef and +// SecStaticCodeRef arguments, operating on the implied SecStaticCodeRef as appropriate. +// Hence they're here, rather than in SecCode.cpp. +// + + +// +// Retrieve location information for an StaticCode. +// +OSStatus SecCodeCopyPath(SecStaticCodeRef staticCodeRef, SecCSFlags flags, CFURLRef *path) +{ + BEGIN_CSAPI + + checkFlags(flags); + SecPointer staticCode = SecStaticCode::requiredStatic(staticCodeRef); + CodeSigning::Required(path) = staticCode->canonicalPath(); + + END_CSAPI +} + + +// +// Fetch or make up a designated requirement +// +OSStatus SecCodeCopyDesignatedRequirement(SecStaticCodeRef staticCodeRef, SecCSFlags flags, + SecRequirementRef *requirementRef) +{ + BEGIN_CSAPI + + checkFlags(flags); + const Requirement *req = + SecStaticCode::requiredStatic(staticCodeRef)->designatedRequirement(); + CodeSigning::Required(requirementRef) = (new SecRequirement(req))->handle(); + + END_CSAPI +} + + +// +// Fetch a particular internal requirement, if present +// +OSStatus SecCodeCopyInternalRequirement(SecStaticCodeRef staticCodeRef, SecRequirementType type, + SecCSFlags flags, SecRequirementRef *requirementRef) +{ + BEGIN_CSAPI + + checkFlags(flags); + const Requirement *req = + SecStaticCode::requiredStatic(staticCodeRef)->internalRequirement(type); + CodeSigning::Required(requirementRef) = req ? (new SecRequirement(req))->handle() : NULL; + + END_CSAPI +} + + +// +// Record for future use a detached code signature. +// +OSStatus SecCodeSetDetachedSignature(SecStaticCodeRef codeRef, CFDataRef signature, + SecCSFlags flags) +{ + BEGIN_CSAPI + + checkFlags(flags); + SecPointer code = SecStaticCode::requiredStatic(codeRef); + + if (signature) + CFRetain(signature); // own a reference... + code->detachedSignature(signature); // ... and pass it to the code + code->resetValidity(); + + END_CSAPI +} + + +// +// Attach a code signature to a kernel memory mapping for page-in validation. +// +OSStatus SecCodeMapMemory(SecStaticCodeRef codeRef, SecCSFlags flags) +{ + BEGIN_CSAPI + + checkFlags(flags); + SecPointer code = SecStaticCode::requiredStatic(codeRef); + if (const CodeDirectory *cd = code->codeDirectory(false)) { + fsignatures args = { code->diskRep()->signingBase(), (void *)cd, cd->length() }; + UnixError::check(::fcntl(code->diskRep()->fd(), F_ADDSIGS, &args)); + } else + MacOSError::throwMe(errSecCSUnsigned); + + END_CSAPI +} diff --git a/libsecurity_codesigning/lib/SecStaticCode.h b/libsecurity_codesigning/lib/SecStaticCode.h new file mode 100644 index 00000000..8d0f68a9 --- /dev/null +++ b/libsecurity_codesigning/lib/SecStaticCode.h @@ -0,0 +1,156 @@ +/* + * 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@ + */ + +/*! + @header SecStaticCode + SecStaticCode represents the Code Signing identity of code in the file system. + This includes applications, tools, frameworks, plugins, scripts, and so on. + Note that arbitrary files will be considered scripts of unknown provenance; + and thus it is possible to handle most files as if they were code, though that is + not necessarily a good idea. + + Normally, each SecCode has a specific SecStaticCode that holds its static signing + data. Informally, that is the SecStaticCode the SecCode "was made from" (by its host). + There is however no viable link in the other direction - given a SecStaticCode, + it is not possible to find, enumerate, or control any SecCode that originated from it. + There might not be any at a given point in time; or there might be many. +*/ +#ifndef _H_SECSTATICCODE +#define _H_SECSTATICCODE + +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +/*! + @function SecStaticCodeGetTypeID + Returns the type identifier of all SecStaticCode instances. +*/ +CFTypeID SecStaticCodeGetTypeID(void); + + +/*! + @function SecStaticCodeCreateWithPath + Given a path to a file system object, create a SecStaticCode object representing + the code at that location, if possible. Such a SecStaticCode is not inherently + linked to running code in the system. + + It is possible to create a SecStaticCode object from an unsigned code object. + Most uses of such an object will return the errSecCSUnsigned error. However, + SecCodeCopyPath and SecCodeCopySigningInformation can be safely applied to such objects. + + @param path A path to a location in the file system. Only file:// URLs are + currently supported. For bundles, pass a URL to the root directory of the + bundle. For single files, pass a URL to the file. If you pass a URL to the + main executable of a bundle, the bundle as a whole will be generally recognized. + Caution: Paths containing embedded // or /../ within a bundle's directory + may cause the bundle to be misconstrued. If you expect to submit such paths, + first clean them with realpath(3) or equivalent. + @param flags Optional flags. Pass kSecCSDefaultFlags for standard behavior. + @param attributes A CFDictionary containing additional attributes of the code sought. + @param staticCode On successful return, contains a reference to the StaticCode object + representing the code at path. Unchanged on error. + @result Upon success, noErr. Upon error, an OSStatus value documented in + CSCommon.h or certain other Security framework headers. + + @constant kSecCodeAttributeArchitecture Specifies the Mach-O architecture of code desired. + This can be a CFString containing a canonical architecture name ("i386" etc.), or a CFNumber + specifying an architecture numerically (see mach/machine.h). This key is ignored if the code + is not in Mach-O binary form. If the code is Mach-O but not universal ("thin"), the architecture + specified must agree with the actual file contents. + @constant kSecCodeAttributeSubarchitecture If the architecture is specified numerically + (using the kSecCodeAttributeArchitecture key), specifies any sub-architecture by number. + This key is ignored if no main architecture is specified; if it is specified by name; or + if the code is not in Mach-O form. +*/ +extern const CFStringRef kSecCodeAttributeArchitecture; +extern const CFStringRef kSecCodeAttributeSubarchitecture; +extern const CFStringRef kSecCodeAttributeBundleVersion; + +OSStatus SecStaticCodeCreateWithPath(CFURLRef path, SecCSFlags flags, SecStaticCodeRef *staticCode); + +OSStatus SecStaticCodeCreateWithPathAndAttributes(CFURLRef path, SecCSFlags flags, CFDictionaryRef attributes, + SecStaticCodeRef *staticCode); + + +/*! + @function SecStaticCodeCheckValidity + Performs static validation on the given SecStaticCode object. The call obtains and + verifies the signature on the code object. It checks the validity of all + sealed components (including resources, if any). It validates the code against + a SecRequirement if one is given. The call succeeds if all these conditions + are satisfactory. It fails otherwise. + + This call is only secure if the code is not subject to concurrent modification, + and the outcome is only valid as long as the code is unmodified thereafter. + Consider this carefully if the underlying file system has dynamic characteristics, + such as a network file system, union mount, FUSE, etc. + + @param staticCode The code object to be validated. + @param flags Optional flags. Pass kSecCSDefaultFlags for standard behavior. + + @constant kSecCSCheckAllArchitectures + For multi-architecture (universal) Mach-O programs, validate all architectures + included. By default, only the native architecture is validated. + @constant kSecCSNoDnotValidateExecutable + Do not validate the contents of the main executable. This is normally done. + @constant kSecCSNoNotValidateResources + Do not validate the presence and contents of all bundle resources (if any). + By default, a mismatch in any bundle resource causes validation to fail. + @constant kSecCSCheckNestedCode + For code in bundle form, locate and recursively check embedded code. Only code + in standard locations is considered. + + @param requirement On optional code requirement specifying additional conditions + the staticCode object must satisfy to be considered valid. If NULL, no additional + requirements are imposed. + @param errors An optional pointer to a CFErrorRef variable. If the call fails + (something other than noErr is returned), and this argument is non-NULL, + a CFErrorRef is stored there further describing the nature and circumstances + of the failure. The caller must CFRelease() this error object when done with it. + @result If validation succeeds, noErr. If validation fails, an OSStatus value + documented in CSCommon.h or certain other Security framework headers. +*/ +enum { + kSecCSCheckAllArchitectures = 1 << 0, + kSecCSDoNotValidateExecutable = 1 << 1, + kSecCSDoNotValidateResources = 1 << 2, + kSecCSBasicValidateOnly = kSecCSDoNotValidateExecutable | kSecCSDoNotValidateResources, + kSecCSCheckNestedCode = 1 << 3, +}; + +OSStatus SecStaticCodeCheckValidity(SecStaticCodeRef staticCode, SecCSFlags flags, + SecRequirementRef requirement); + +OSStatus SecStaticCodeCheckValidityWithErrors(SecStaticCodeRef staticCode, SecCSFlags flags, + SecRequirementRef requirement, CFErrorRef *errors); + + +#ifdef __cplusplus +} +#endif + +#endif //_H_SECSTATICCODE diff --git a/libsecurity_codesigning/lib/SecStaticCodePriv.h b/libsecurity_codesigning/lib/SecStaticCodePriv.h new file mode 100644 index 00000000..1f0d74c5 --- /dev/null +++ b/libsecurity_codesigning/lib/SecStaticCodePriv.h @@ -0,0 +1,48 @@ +/* + * 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@ + */ + +/*! + @header SecStaticCode + SecStaticCodePriv is the private counter-part to SecStaticCode. Its contents are not + official API, and are subject to change without notice. +*/ +#ifndef _H_SECSTATICCODEPRIV +#define _H_SECSTATICCODEPRIV + +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +/* + * Currently empty + */ + + +#ifdef __cplusplus +} +#endif + +#endif //_H_SECSTATICCODEPRIV diff --git a/libsecurity_codesigning/lib/SecTask.c b/libsecurity_codesigning/lib/SecTask.c new file mode 100644 index 00000000..cb01bbb4 --- /dev/null +++ b/libsecurity_codesigning/lib/SecTask.c @@ -0,0 +1,235 @@ +/* + * Copyright (c) 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@ + */ + +#include +#include +#include + +#include +#include + +#include + +#include + +#include + +#include "SecTask.h" + +struct __SecTask { + CFRuntimeBase base; + + pid_t pid; + + /* 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; + } +} + +static CFStringRef SecTaskCopyDebugDescription(CFTypeRef cfTask) +{ + SecTaskRef task = (SecTaskRef) cfTask; + + return CFStringCreateWithFormat(CFGetAllocator(task), NULL, CFSTR(""), task); +} + +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) +{ + pid_t pid; + + audit_token_to_au32(token, + /* auidp */ NULL, + /* euidp */ NULL, + /* egidp */ NULL, + /* ruidp */ NULL, + /* rgidp */ NULL, + /* pidp */ &pid, + /* asidp */ NULL, + /* tidp */ NULL); + return SecTaskCreateWithPID(allocator, pid); +} + +SecTaskRef SecTaskCreateFromSelf(CFAllocatorRef allocator) +{ + return SecTaskCreateWithPID(allocator, getpid()); +} + +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 SecTaskLoadEntitlements(SecTaskRef task, CFErrorRef *error) +{ + CFMutableDataRef data = NULL; + struct csheader header; + uint32_t bufferlen; + int ret; + + ret = csops(task->pid, 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->pid, 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 new file mode 100644 index 00000000..7563b661 --- /dev/null +++ b/libsecurity_codesigning/lib/SecTask.h @@ -0,0 +1,103 @@ +/* + * 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/StaticCode.cpp b/libsecurity_codesigning/lib/StaticCode.cpp new file mode 100644 index 00000000..9a124458 --- /dev/null +++ b/libsecurity_codesigning/lib/StaticCode.cpp @@ -0,0 +1,1192 @@ +/* + * 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@ + */ + +// +// StaticCode - SecStaticCode API objects +// +#include "StaticCode.h" +#include "Code.h" +#include "reqmaker.h" +#include "drmaker.h" +#include "reqdumper.h" +#include "sigblob.h" +#include "resources.h" +#include "renum.h" +#include "detachedrep.h" +#include "csdatabase.h" +#include "csutilities.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace Security { +namespace CodeSigning { + +using namespace UnixPlusPlus; + + +// +// Construct a SecStaticCode object given a disk representation object +// +SecStaticCode::SecStaticCode(DiskRep *rep) + : mRep(rep), + mValidated(false), mExecutableValidated(false), mResourcesValidated(false), mResourcesValidContext(NULL), + mDesignatedReq(NULL), mGotResourceBase(false), mEvalDetails(NULL) +{ + CODESIGN_STATIC_CREATE(this, rep); + checkForSystemSignature(); +} + + +// +// Clean up a SecStaticCode object +// +SecStaticCode::~SecStaticCode() throw() +try { + ::free(const_cast(mDesignatedReq)); + if (mResourcesValidContext) + delete mResourcesValidContext; +} catch (...) { + return; +} + + +// +// CF-level comparison of SecStaticCode objects compares CodeDirectory hashes if signed, +// and falls back on comparing canonical paths if (both are) not. +// +bool SecStaticCode::equal(SecCFObject &secOther) +{ + SecStaticCode *other = static_cast(&secOther); + CFDataRef mine = this->cdHash(); + CFDataRef his = other->cdHash(); + if (mine || his) + return mine && his && CFEqual(mine, his); + else + return CFEqual(this->canonicalPath(), other->canonicalPath()); +} + +CFHashCode SecStaticCode::hash() +{ + if (CFDataRef h = this->cdHash()) + return CFHash(h); + else + return CFHash(this->canonicalPath()); +} + + +// +// Attach a detached signature. +// +void SecStaticCode::detachedSignature(CFDataRef sigData) +{ + if (sigData) { + mRep = new DetachedRep(sigData, mRep->base(), "explicit detached"); + CODESIGN_STATIC_ATTACH_EXPLICIT(this, mRep); + } else { + mRep = mRep->base(); + CODESIGN_STATIC_ATTACH_EXPLICIT(this, NULL); + } +} + + +// +// Consult the system detached signature database to see if it contains +// a detached signature for this StaticCode. If it does, fetch and attach it. +// We do this only if the code has no signature already attached. +// +void SecStaticCode::checkForSystemSignature() +{ + if (!this->isSigned()) + try { + if (RefPointer dsig = signatureDatabase().findCode(mRep)) { + CODESIGN_STATIC_ATTACH_SYSTEM(this, dsig); + mRep = dsig; + } + } catch (...) { + } +} + + +// +// Return a descriptive string identifying the source of the code signature +// +string SecStaticCode::signatureSource() +{ + if (!isSigned()) + return "unsigned"; + if (DetachedRep *rep = dynamic_cast(mRep.get())) + return rep->source(); + return "embedded"; +} + + +// +// Do ::required, but convert incoming SecCodeRefs to their SecStaticCodeRefs +// (if possible). +// +SecStaticCode *SecStaticCode::requiredStatic(SecStaticCodeRef ref) +{ + SecCFObject *object = SecCFObject::required(ref, errSecCSInvalidObjectRef); + if (SecStaticCode *scode = dynamic_cast(object)) + return scode; + else if (SecCode *code = dynamic_cast(object)) + return code->staticCode(); + else // neither (a SecSomethingElse) + MacOSError::throwMe(errSecCSInvalidObjectRef); +} + +SecCode *SecStaticCode::optionalDynamic(SecStaticCodeRef ref) +{ + SecCFObject *object = SecCFObject::required(ref, errSecCSInvalidObjectRef); + if (dynamic_cast(object)) + return NULL; + else if (SecCode *code = dynamic_cast(object)) + return code; + else // neither (a SecSomethingElse) + MacOSError::throwMe(errSecCSInvalidObjectRef); +} + + +// +// Void all cached validity data. +// +// We also throw out cached components, because the new signature data may have +// a different idea of what components should be present. We could reconcile the +// cached data instead, if performance seems to be impacted. +// +void SecStaticCode::resetValidity() +{ + CODESIGN_EVAL_STATIC_RESET(this); + mValidated = false; + mExecutableValidated = false; + mResourcesValidated = false; + if (mResourcesValidContext) { + delete mResourcesValidContext; + mResourcesValidContext = NULL; + } + mDir = NULL; + mSignature = NULL; + for (unsigned n = 0; n < cdSlotCount; n++) + mCache[n] = NULL; + mInfoDict = NULL; + mEntitlements = NULL; + mResourceDict = NULL; + mDesignatedReq = NULL; + mGotResourceBase = false; + mTrust = NULL; + mCertChain = NULL; + mEvalDetails = NULL; + mRep->flush(); + + // we may just have updated the system database, so check again + checkForSystemSignature(); +} + + +// +// Retrieve a sealed component by special slot index. +// If the CodeDirectory has already been validated, validate against that. +// Otherwise, retrieve the component without validation (but cache it). Validation +// will go through the cache and validate all cached components. +// +CFDataRef SecStaticCode::component(CodeDirectory::SpecialSlot slot, OSStatus fail /* = errSecCSSignatureFailed */) +{ + assert(slot <= cdSlotMax); + + CFRef &cache = mCache[slot]; + if (!cache) { + if (CFRef data = mRep->component(slot)) { + if (validated()) // if the directory has been validated... + if (!codeDirectory()->validateSlot(CFDataGetBytePtr(data), // ... and it's no good + CFDataGetLength(data), -slot)) + MacOSError::throwMe(fail); // ... then bail + cache = data; // it's okay, cache it + } else { // absent, mark so + if (validated()) // if directory has been validated... + if (codeDirectory()->slotIsPresent(-slot)) // ... and the slot is NOT missing + MacOSError::throwMe(fail); // was supposed to be there + cache = CFDataRef(kCFNull); // white lie + } + } + return (cache == CFDataRef(kCFNull)) ? NULL : cache.get(); +} + + +// +// Get the CodeDirectory. +// Throws (if check==true) or returns NULL (check==false) if there is none. +// Always throws if the CodeDirectory exists but is invalid. +// NEVER validates against the signature. +// +const CodeDirectory *SecStaticCode::codeDirectory(bool check /* = true */) +{ + if (!mDir) { + if (mDir.take(mRep->codeDirectory())) { + const CodeDirectory *dir = reinterpret_cast(CFDataGetBytePtr(mDir)); + dir->checkIntegrity(); + } + } + if (mDir) + return reinterpret_cast(CFDataGetBytePtr(mDir)); + if (check) + MacOSError::throwMe(errSecCSUnsigned); + return NULL; +} + + +// +// Get the hash of the CodeDirectory. +// Returns NULL if there is none. +// +CFDataRef SecStaticCode::cdHash() +{ + if (!mCDHash) { + if (const CodeDirectory *cd = codeDirectory(false)) { + SHA1 hash; + hash(cd, cd->length()); + SHA1::Digest digest; + hash.finish(digest); + mCDHash.take(makeCFData(digest, sizeof(digest))); + CODESIGN_STATIC_CDHASH(this, digest, sizeof(digest)); + } + } + return mCDHash; +} + + +// +// Return the CMS signature blob; NULL if none found. +// +CFDataRef SecStaticCode::signature() +{ + if (!mSignature) + mSignature.take(mRep->signature()); + if (mSignature) + return mSignature; + MacOSError::throwMe(errSecCSUnsigned); +} + + +// +// Verify the signature on the CodeDirectory. +// If this succeeds (doesn't throw), the CodeDirectory is statically trustworthy. +// Any outcome (successful or not) is cached for the lifetime of the StaticCode. +// +void SecStaticCode::validateDirectory() +{ + // echo previous outcome, if any + if (!validated()) + try { + // perform validation (or die trying) + CODESIGN_EVAL_STATIC_DIRECTORY(this); + mValidationExpired = verifySignature(); + component(cdInfoSlot, errSecCSInfoPlistFailed); // force load of Info Dictionary (if any) + for (CodeDirectory::SpecialSlot slot = codeDirectory()->maxSpecialSlot(); slot >= 1; --slot) + if (mCache[slot]) // if we already loaded that resource... + validateComponent(slot); // ... then check it now + mValidated = true; // we've done the deed... + mValidationResult = noErr; // ... and it was good + } catch (const CommonError &err) { + mValidated = true; + mValidationResult = err.osStatus(); + throw; + } catch (...) { + secdebug("staticCode", "%p validation threw non-common exception", this); + mValidated = true; + mValidationResult = errSecCSInternalError; + throw; + } + assert(validated()); + if (mValidationResult == noErr) { + if (mValidationExpired) + if ((apiFlags() & kSecCSConsiderExpiration) + || (codeDirectory()->flags & kSecCodeSignatureForceExpiration)) + MacOSError::throwMe(CSSMERR_TP_CERT_EXPIRED); + } else + MacOSError::throwMe(mValidationResult); +} + + +// +// Load and validate the CodeDirectory and all components *except* those related to the resource envelope. +// Those latter components are checked by validateResources(). +// +void SecStaticCode::validateNonResourceComponents() +{ + this->validateDirectory(); + for (CodeDirectory::SpecialSlot slot = codeDirectory()->maxSpecialSlot(); slot >= 1; --slot) + switch (slot) { + case cdResourceDirSlot: // validated by validateResources + break; + default: + this->component(slot); // loads and validates + break; + } +} + + +// +// Get the (signed) signing date from the code signature. +// Sadly, we need to validate the signature to get the date (as a side benefit). +// This means that you can't get the signing time for invalidly signed code. +// +// We could run the decoder "almost to" verification to avoid this, but there seems +// little practical point to such a duplication of effort. +// +CFAbsoluteTime SecStaticCode::signingTime() +{ + validateDirectory(); + return mSigningTime; +} + +CFAbsoluteTime SecStaticCode::signingTimestamp() +{ + validateDirectory(); + return mSigningTimestamp; +} + + +// +// Verify the CMS signature on the CodeDirectory. +// This performs the cryptographic tango. It returns if the signature is valid, +// or throws if it is not. As a side effect, a successful return sets up the +// cached certificate chain for future use. +// Returns true if the signature is expired (the X.509 sense), false if it's not. +// +bool SecStaticCode::verifySignature() +{ + // ad-hoc signed code is considered validly signed by definition + if (flag(kSecCodeSignatureAdhoc)) { + 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 + CFRef cms; + MacOSError::check(CMSDecoderCreate(&cms.aref())); // create decoder + CFDataRef sig = this->signature(); + MacOSError::check(CMSDecoderUpdateMessage(cms, CFDataGetBytePtr(sig), CFDataGetLength(sig))); + this->codeDirectory(); // load CodeDirectory (sets mDir) + MacOSError::check(CMSDecoderSetDetachedContent(cms, mDir)); + MacOSError::check(CMSDecoderFinalizeMessage(cms)); + MacOSError::check(CMSDecoderSetSearchKeychain(cms, cfEmptyArray())); + CFRef policy = verificationPolicy(apiFlags()); + CMSSignerStatus status; + MacOSError::check(CMSDecoderCopySignerStatus(cms, 0, policy, + 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)) { + case noErr: + case errSecSigningTimeMissing: + break; + default: + MacOSError::throwMe(rc); + } + + // certified signing time (as specified by a TSA; optional) + mSigningTimestamp = 0; + switch (OSStatus rc = CMSDecoderCopySignerTimestamp(cms, 0, &mSigningTimestamp)) { + case noErr: + case errSecTimestampMissing: + break; + default: + MacOSError::throwMe(rc); + } + + // set up the environment for SecTrust + MacOSError::check(SecTrustSetAnchorCertificates(mTrust, cfEmptyArray())); // no anchors + MacOSError::check(SecTrustSetKeychains(mTrust, cfEmptyArray())); // no keychains + CSSM_APPLE_TP_ACTION_DATA actionData = { + CSSM_APPLE_TP_ACTION_VERSION, // version of data structure + CSSM_TP_ACTION_IMPLICIT_ANCHORS // action flags + }; + + for (;;) { // at most twice + MacOSError::check(SecTrustSetParameters(mTrust, + CSSM_TP_ACTION_DEFAULT, CFTempData(&actionData, sizeof(actionData)))); + + // evaluate trust and extract results + SecTrustResultType trustResult; + MacOSError::check(SecTrustEvaluate(mTrust, &trustResult)); + MacOSError::check(SecTrustGetResult(mTrust, &trustResult, &mCertChain.aref(), &mEvalDetails)); + CODESIGN_EVAL_STATIC_SIGNATURE_RESULT(this, trustResult, mCertChain ? CFArrayGetCount(mCertChain) : 0); + switch (trustResult) { + case kSecTrustResultProceed: + case kSecTrustResultUnspecified: + break; // success + case kSecTrustResultDeny: + MacOSError::throwMe(CSSMERR_APPLETP_TRUST_SETTING_DENY); // user reject + case kSecTrustResultInvalid: + assert(false); // should never happen + MacOSError::throwMe(CSSMERR_TP_NOT_TRUSTED); + default: + { + OSStatus result; + MacOSError::check(SecTrustGetCssmResultCode(mTrust, &result)); + // if we have a valid timestamp, CMS validates against (that) signing time and all is well. + // If we don't have one, may validate against *now*, and must be able to tolerate expiration. + if (mSigningTimestamp == 0) // no timestamp available + if (((result == CSSMERR_TP_CERT_EXPIRED) || (result == CSSMERR_TP_CERT_NOT_VALID_YET)) + && !(actionData.ActionFlags & CSSM_TP_ACTION_ALLOW_EXPIRED)) { + CODESIGN_EVAL_STATIC_SIGNATURE_EXPIRED(this); + actionData.ActionFlags |= CSSM_TP_ACTION_ALLOW_EXPIRED; // (this also allows postdated certs) + continue; // retry validation while tolerating expiration + } + MacOSError::throwMe(result); + } + } + return actionData.ActionFlags & CSSM_TP_ACTION_ALLOW_EXPIRED; + } +} + + +// +// Return the TP policy used for signature verification. +// This may be a simple SecPolicyRef or a CFArray of policies. +// The caller owns the return value. +// +static SecPolicyRef makeCRLPolicy() +{ + CFRef policy; + MacOSError::check(SecPolicyCopy(CSSM_CERT_X_509v3, &CSSMOID_APPLE_TP_REVOCATION_CRL, &policy.aref())); + CSSM_APPLE_TP_CRL_OPTIONS options; + memset(&options, 0, sizeof(options)); + options.Version = CSSM_APPLE_TP_CRL_OPTS_VERSION; + options.CrlFlags = CSSM_TP_ACTION_FETCH_CRL_FROM_NET | CSSM_TP_ACTION_CRL_SUFFICIENT; + CSSM_DATA optData = { sizeof(options), (uint8 *)&options }; + MacOSError::check(SecPolicySetValue(policy, &optData)); + return policy.yield(); +} + +static SecPolicyRef makeOCSPPolicy() +{ + CFRef policy; + MacOSError::check(SecPolicyCopy(CSSM_CERT_X_509v3, &CSSMOID_APPLE_TP_REVOCATION_OCSP, &policy.aref())); + CSSM_APPLE_TP_OCSP_OPTIONS options; + memset(&options, 0, sizeof(options)); + options.Version = CSSM_APPLE_TP_OCSP_OPTS_VERSION; + options.Flags = CSSM_TP_ACTION_OCSP_SUFFICIENT; + CSSM_DATA optData = { sizeof(options), (uint8 *)&options }; + MacOSError::check(SecPolicySetValue(policy, &optData)); + return policy.yield(); +} + +CFTypeRef SecStaticCode::verificationPolicy(SecCSFlags flags) +{ + CFRef core; + MacOSError::check(SecPolicyCopy(CSSM_CERT_X_509v3, + &CSSMOID_APPLE_TP_CODE_SIGNING, &core.aref())); + if (flags & kSecCSEnforceRevocationChecks) { + CFRef crl = makeCRLPolicy(); + CFRef ocsp = makeOCSPPolicy(); + return makeCFArray(3, core.get(), crl.get(), ocsp.get()); + } else { + return core.yield(); + } +} + + +// +// Validate a particular sealed, cached resource against its (special) CodeDirectory slot. +// The resource must already have been placed in the cache. +// This does NOT perform basic validation. +// +void SecStaticCode::validateComponent(CodeDirectory::SpecialSlot slot, OSStatus fail /* = errSecCSSignatureFailed */) +{ + assert(slot <= cdSlotMax); + CFDataRef data = mCache[slot]; + assert(data); // must be cached + if (data == CFDataRef(kCFNull)) { + if (codeDirectory()->slotIsPresent(-slot)) // was supposed to be there... + MacOSError::throwMe(fail); // ... and is missing + } else { + if (!codeDirectory()->validateSlot(CFDataGetBytePtr(data), CFDataGetLength(data), -slot)) + MacOSError::throwMe(fail); + } +} + + +// +// Perform static validation of the main executable. +// This reads the main executable from disk and validates it against the +// CodeDirectory code slot array. +// Note that this is NOT an in-memory validation, and is thus potentially +// subject to timing attacks. +// +void SecStaticCode::validateExecutable() +{ + if (!validatedExecutable()) { + try { + DTRACK(CODESIGN_EVAL_STATIC_EXECUTABLE, this, + (char*)this->mainExecutablePath().c_str(), codeDirectory()->nCodeSlots); + const CodeDirectory *cd = this->codeDirectory(); + if (!cd) + MacOSError::throwMe(errSecCSUnsigned); + AutoFileDesc fd(mainExecutablePath(), O_RDONLY); + fd.fcntl(F_NOCACHE, true); // turn off page caching (one-pass) + if (Universal *fat = mRep->mainExecutableImage()) + fd.seek(fat->archOffset()); + size_t pageSize = cd->pageSize ? (1 << cd->pageSize) : 0; + size_t remaining = cd->codeLimit; + for (size_t slot = 0; slot < cd->nCodeSlots; ++slot) { + size_t size = min(remaining, pageSize); + if (!cd->validateSlot(fd, size, slot)) { + CODESIGN_EVAL_STATIC_EXECUTABLE_FAIL(this, slot); + MacOSError::throwMe(errSecCSSignatureFailed); + } + remaining -= size; + } + mExecutableValidated = true; + mExecutableValidResult = noErr; + } catch (const CommonError &err) { + mExecutableValidated = true; + mExecutableValidResult = err.osStatus(); + throw; + } catch (...) { + secdebug("staticCode", "%p executable validation threw non-common exception", this); + mExecutableValidated = true; + mExecutableValidResult = errSecCSInternalError; + throw; + } + } + assert(validatedExecutable()); + if (mExecutableValidResult != noErr) + MacOSError::throwMe(mExecutableValidResult); +} + + +// +// Perform static validation of sealed resources. +// +// This performs a whole-code static resource scan and effectively +// computes a concordance between what's on disk and what's in the ResourceDirectory. +// Any unsanctioned difference causes an error. +// +void SecStaticCode::validateResources() +{ + if (!validatedResources()) { + try { + // sanity first + CFDictionaryRef sealedResources = resourceDictionary(); + if (this->resourceBase()) // disk has resources + if (sealedResources) + /* go to work below */; + else + MacOSError::throwMe(errSecCSResourcesNotFound); + else // disk has no resources + if (sealedResources) + MacOSError::throwMe(errSecCSResourcesNotFound); + else + return; // no resources, not sealed - fine (no work) + + // found resources, and they are sealed + CFDictionaryRef rules = cfget(sealedResources, "rules"); + CFDictionaryRef files = cfget(sealedResources, "files"); + DTRACK(CODESIGN_EVAL_STATIC_RESOURCES, this, + (char*)this->mainExecutablePath().c_str(), int(CFDictionaryGetCount(files))); + + // make a shallow copy of the ResourceDirectory so we can "check off" what we find + CFRef resourceMap = makeCFMutableDictionary(files); + + // scan through the resources on disk, checking each against the resourceDirectory + mResourcesValidContext = new CollectingContext(*this); // collect all failures in here + ResourceBuilder resources(cfString(this->resourceBase()), rules, codeDirectory()->hashType); + mRep->adjustResources(resources); + string path; + ResourceBuilder::Rule *rule; + + while (resources.next(path, rule)) { + validateResource(path, *mResourcesValidContext); + CFDictionaryRemoveValue(resourceMap, CFTempString(path)); + } + + if (CFDictionaryGetCount(resourceMap) > 0) { + secdebug("staticCode", "%p sealed resource(s) not found in code", this); + CFDictionaryApplyFunction(resourceMap, SecStaticCode::checkOptionalResource, mResourcesValidContext); + } + + // now check for any errors found in the reporting context + mResourcesValidated = true; + if (mResourcesValidContext->osStatus() != noErr) + mResourcesValidContext->throwMe(); + + } catch (const CommonError &err) { + mResourcesValidated = true; + mResourcesValidResult = err.osStatus(); + throw; + } catch (...) { + secdebug("staticCode", "%p executable validation threw non-common exception", this); + mResourcesValidated = true; + mResourcesValidResult = errSecCSInternalError; + throw; + } + } + assert(validatedResources()); + if (mResourcesValidResult) + MacOSError::throwMe(mResourcesValidResult); + if (mResourcesValidContext->osStatus() != noErr) + mResourcesValidContext->throwMe(); +} + + +void SecStaticCode::checkOptionalResource(CFTypeRef key, CFTypeRef value, void *context) +{ + CollectingContext *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())); + } else { + ctx->reportProblem(errSecCSBadResource, kSecCFErrorResourceSeal, key); + } + } +} + + +// +// Load, validate, cache, and return CFDictionary forms of sealed resources. +// +CFDictionaryRef SecStaticCode::infoDictionary() +{ + if (!mInfoDict) { + mInfoDict.take(getDictionary(cdInfoSlot, errSecCSInfoPlistFailed)); + secdebug("staticCode", "%p loaded InfoDict %p", this, mInfoDict.get()); + } + return mInfoDict; +} + +CFDictionaryRef SecStaticCode::entitlements() +{ + if (!mEntitlements) { + validateDirectory(); + if (CFDataRef entitlementData = component(cdEntitlementSlot)) { + validateComponent(cdEntitlementSlot); + const EntitlementBlob *blob = reinterpret_cast(CFDataGetBytePtr(entitlementData)); + if (blob->validateBlob()) { + mEntitlements.take(blob->entitlements()); + secdebug("staticCode", "%p loaded Entitlements %p", this, mEntitlements.get()); + } + // we do not consider a different blob type to be an error. We think it's a new format we don't understand + } + } + return mEntitlements; +} + +CFDictionaryRef SecStaticCode::resourceDictionary() +{ + if (mResourceDict) // cached + return mResourceDict; + if (CFRef dict = getDictionary(cdResourceDirSlot, errSecCSSignatureFailed)) + if (cfscan(dict, "{rules=%Dn,files=%Dn}")) { + secdebug("staticCode", "%p loaded ResourceDict %p", + this, mResourceDict.get()); + return mResourceDict = dict; + } + // bad format + return NULL; +} + + +// +// Load and cache the resource directory base. +// Note that the base is optional for each DiskRep. +// +CFURLRef SecStaticCode::resourceBase() +{ + if (!mGotResourceBase) { + string base = mRep->resourcesRootPath(); + if (!base.empty()) + mResourceBase.take(makeCFURL(base, true)); + mGotResourceBase = true; + } + return mResourceBase; +} + + +// +// Load a component, validate it, convert it to a CFDictionary, and return that. +// This will force load and validation, which means that it will perform basic +// validation if it hasn't been done yet. +// +CFDictionaryRef SecStaticCode::getDictionary(CodeDirectory::SpecialSlot slot, OSStatus fail /* = errSecCSSignatureFailed */) +{ + validateDirectory(); + if (CFDataRef infoData = component(slot, fail)) { + validateComponent(slot, fail); + if (CFDictionaryRef dict = makeCFDictionaryFrom(infoData)) + return dict; + else + MacOSError::throwMe(errSecCSBadDictionaryFormat); + } + return NULL; +} + + +// +// Load, validate, and return a sealed resource. +// The resource data (loaded in to memory as a blob) is returned and becomes +// the responsibility of the caller; it is NOT cached by SecStaticCode. +// +// A resource that is not sealed will not be returned, and an error will be thrown. +// A missing resource will cause an error unless it's marked optional in the Directory. +// Under no circumstances will a corrupt resource be returned. +// NULL will only be returned for a resource that is neither sealed nor present +// (or that is sealed, absent, and marked optional). +// If the ResourceDictionary itself is not sealed, this function will always fail. +// +// There is currently no interface for partial retrieval of the resource data. +// (Since the ResourceDirectory does not currently support segmentation, all the +// data would have to be read anyway, but it could be read into a reusable buffer.) +// +CFDataRef SecStaticCode::resource(string path, ValidationContext &ctx) +{ + if (CFDictionaryRef rdict = resourceDictionary()) { + if (CFTypeRef file = cfget(rdict, "files.%s", path.c_str())) { + ResourceSeal seal = file; + if (!resourceBase()) // no resources in DiskRep + MacOSError::throwMe(errSecCSResourcesNotFound); + CFRef fullpath = makeCFURL(path, false, resourceBase()); + if (CFRef data = cfLoadFile(fullpath)) { + MakeHash hasher(this->codeDirectory()); + hasher->update(CFDataGetBytePtr(data), CFDataGetLength(data)); + if (hasher->verify(seal.hash())) + return data.yield(); // good + else + ctx.reportProblem(errSecCSBadResource, kSecCFErrorResourceAltered, fullpath); // altered + } else { + if (!seal.optional()) + ctx.reportProblem(errSecCSBadResource, kSecCFErrorResourceMissing, fullpath); // was sealed but is now missing + else + return NULL; // validly missing + } + } else + ctx.reportProblem(errSecCSBadResource, kSecCFErrorResourceAdded, CFTempURL(path, false, resourceBase())); + return NULL; + } else + MacOSError::throwMe(errSecCSResourcesNotSealed); +} + +CFDataRef SecStaticCode::resource(string path) +{ + ValidationContext ctx; + return resource(path, ctx); +} + + +void SecStaticCode::validateResource(string path, ValidationContext &ctx) +{ + if (CFDictionaryRef rdict = resourceDictionary()) { + if (CFTypeRef file = cfget(rdict, "files.%s", path.c_str())) { + ResourceSeal seal = file; + if (!resourceBase()) // no resources in DiskRep + MacOSError::throwMe(errSecCSResourcesNotFound); + CFRef fullpath = makeCFURL(path, false, resourceBase()); + AutoFileDesc fd(cfString(fullpath), O_RDONLY, FileDesc::modeMissingOk); // open optional filee + if (fd) { + MakeHash hasher(this->codeDirectory()); + hashFileData(fd, hasher.get()); + if (hasher->verify(seal.hash())) + return; // verify good + else + ctx.reportProblem(errSecCSBadResource, kSecCFErrorResourceAltered, fullpath); // altered + } else { + if (!seal.optional()) + ctx.reportProblem(errSecCSBadResource, kSecCFErrorResourceMissing, fullpath); // was sealed but is now missing + else + return; // validly missing + } + } else + ctx.reportProblem(errSecCSBadResource, kSecCFErrorResourceAdded, CFTempURL(path, false, resourceBase())); + } else + MacOSError::throwMe(errSecCSResourcesNotSealed); +} + + +// +// Test a CodeDirectory flag. +// Returns false if there is no CodeDirectory. +// May throw if the CodeDirectory is present but somehow invalid. +// +bool SecStaticCode::flag(uint32_t tested) +{ + if (const CodeDirectory *cd = this->codeDirectory(false)) + return cd->flags & tested; + else + return false; +} + + +// +// Retrieve the full SuperBlob containing all internal requirements. +// +const Requirements *SecStaticCode::internalRequirements() +{ + if (CFDataRef req = component(cdRequirementsSlot)) + return (const Requirements *)CFDataGetBytePtr(req); + else + return NULL; +} + + +// +// Retrieve a particular internal requirement by type. +// +const Requirement *SecStaticCode::internalRequirement(SecRequirementType type) +{ + if (const Requirements *reqs = internalRequirements()) + return reqs->find(type); + else + return NULL; +} + + +// +// Return the Designated Requirement (DR). This can be either explicit in the +// Internal Requirements component, or implicitly generated on demand here. +// Note that an explicit DR may have been implicitly generated at signing time; +// we don't distinguish this case. +// +const Requirement *SecStaticCode::designatedRequirement() +{ + if (const Requirement *req = internalRequirement(kSecDesignatedRequirementType)) { + return req; // explicit in signing data + } else { + if (!mDesignatedReq) + mDesignatedReq = defaultDesignatedRequirement(); + return mDesignatedReq; + } +} + + +// +// Generate the default Designated Requirement (DR) for this StaticCode. +// Ignore any explicit DR it may contain. +// +const Requirement *SecStaticCode::defaultDesignatedRequirement() +{ + if (flag(kSecCodeSignatureAdhoc)) { + // adhoc signature: return a plain cdhash requirement + Requirement::Maker maker; + SHA1 hash; + hash(codeDirectory(), codeDirectory()->length()); + SHA1::Digest digest; + hash.finish(digest); + maker.cdhash(digest); + return maker.make(); + } else { + // full signature: Gin up full context and let DRMaker do its thing + validateDirectory(); // need the cert chain + Requirement::Context context(this->certificates(), + this->infoDictionary(), + this->entitlements(), + this->identifier(), + this->codeDirectory() + ); + return DRMaker(context).make(); + } +} + + +// +// Validate a SecStaticCode against the internal requirement of a particular type. +// +void SecStaticCode::validateRequirements(SecRequirementType type, SecStaticCode *target, + OSStatus nullError /* = noErr */) +{ + DTRACK(CODESIGN_EVAL_STATIC_INTREQ, this, type, target, nullError); + if (const Requirement *req = internalRequirement(type)) + target->validateRequirement(req, nullError ? nullError : errSecCSReqFailed); + else if (nullError) + MacOSError::throwMe(nullError); + else + /* accept it */; +} + + +// +// Validate this StaticCode against an external Requirement +// +bool SecStaticCode::satisfiesRequirement(const Requirement *req, OSStatus failure) +{ + assert(req); + validateDirectory(); + return req->validates(Requirement::Context(mCertChain, infoDictionary(), entitlements(), codeDirectory()->identifier(), codeDirectory()), failure); +} + +void SecStaticCode::validateRequirement(const Requirement *req, OSStatus failure) +{ + if (!this->satisfiesRequirement(req, failure)) + MacOSError::throwMe(failure); +} + + +// +// Retrieve one certificate from the cert chain. +// Positive and negative indices can be used: +// [ leaf, intermed-1, ..., intermed-n, anchor ] +// 0 1 ... -2 -1 +// Returns NULL if unavailable for any reason. +// +SecCertificateRef SecStaticCode::cert(int ix) +{ + validateDirectory(); // need cert chain + if (mCertChain) { + CFIndex length = CFArrayGetCount(mCertChain); + if (ix < 0) + ix += length; + if (ix >= 0 && ix < length) + return SecCertificateRef(CFArrayGetValueAtIndex(mCertChain, ix)); + } + return NULL; +} + +CFArrayRef SecStaticCode::certificates() +{ + validateDirectory(); // need cert chain + return mCertChain; +} + + +// +// Gather (mostly) API-official information about this StaticCode. +// +// This method lives in the twilight between the API and internal layers, +// since it generates API objects (Sec*Refs) for return. +// +CFDictionaryRef SecStaticCode::signingInformation(SecCSFlags flags) +{ + // + // Start with the pieces that we return even for unsigned code. + // This makes Sec[Static]CodeRefs useful as API-level replacements + // of our internal OSXCode objects. + // + CFRef dict = makeCFMutableDictionary(1, + kSecCodeInfoMainExecutable, CFTempURL(this->mainExecutablePath()).get() + ); + + // + // If we're not signed, this is all you get + // + if (!this->isSigned()) + return dict.yield(); + + // + // Add the generic attributes that we always include + // + CFDictionaryAddValue(dict, kSecCodeInfoIdentifier, CFTempString(this->identifier())); + CFDictionaryAddValue(dict, kSecCodeInfoFormat, CFTempString(this->format())); + CFDictionaryAddValue(dict, kSecCodeInfoSource, CFTempString(this->signatureSource())); + CFDictionaryAddValue(dict, kSecCodeInfoUnique, this->cdHash()); + CFDictionaryAddValue(dict, kSecCodeInfoDigestAlgorithm, CFTempNumber(this->codeDirectory(false)->hashType)); + + // + // Deliver any Info.plist only if it looks intact + // + try { + if (CFDictionaryRef info = this->infoDictionary()) + CFDictionaryAddValue(dict, kSecCodeInfoPList, info); + } catch (...) { } // don't deliver Info.plist if questionable + + // + // kSecCSSigningInformation adds information about signing certificates and chains + // + if (flags & kSecCSSigningInformation) { + if (CFArrayRef certs = this->certificates()) + CFDictionaryAddValue(dict, kSecCodeInfoCertificates, certs); + if (CFDataRef sig = this->signature()) + CFDictionaryAddValue(dict, kSecCodeInfoCMS, sig); + if (mTrust) + CFDictionaryAddValue(dict, kSecCodeInfoTrust, mTrust); + if (CFAbsoluteTime time = this->signingTime()) + if (CFRef date = CFDateCreate(NULL, time)) + CFDictionaryAddValue(dict, kSecCodeInfoTime, date); + if (CFAbsoluteTime time = this->signingTimestamp()) + if (CFRef date = CFDateCreate(NULL, time)) + CFDictionaryAddValue(dict, kSecCodeInfoTimestamp, date); + } + + // + // kSecCSRequirementInformation adds information on requirements + // + if (flags & kSecCSRequirementInformation) { + if (const Requirements *reqs = this->internalRequirements()) { + CFDictionaryAddValue(dict, kSecCodeInfoRequirements, + CFTempString(Dumper::dump(reqs))); + CFDictionaryAddValue(dict, kSecCodeInfoRequirementData, CFTempData(*reqs)); + } + + const Requirement *dreq = this->designatedRequirement(); + CFRef dreqRef = (new SecRequirement(dreq))->handle(); + CFDictionaryAddValue(dict, kSecCodeInfoDesignatedRequirement, dreqRef); + if (this->internalRequirement(kSecDesignatedRequirementType)) { // explicit + CFRef ddreqRef = (new SecRequirement(this->defaultDesignatedRequirement(), true))->handle(); + CFDictionaryAddValue(dict, kSecCodeInfoImplicitDesignatedRequirement, ddreqRef); + } else { // implicit + CFDictionaryAddValue(dict, kSecCodeInfoImplicitDesignatedRequirement, dreqRef); + } + + if (CFDataRef ent = this->component(cdEntitlementSlot)) { + CFDictionaryAddValue(dict, kSecCodeInfoEntitlements, ent); + if (CFDictionaryRef entdict = this->entitlements()) + CFDictionaryAddValue(dict, kSecCodeInfoEntitlementsDict, entdict); + } + } + + // + // kSecCSInternalInformation adds internal information meant to be for Apple internal + // use (SPI), and not guaranteed to be stable. Primarily, this is data we want + // to reliably transmit through the API wall so that code outside the Security.framework + // can use it without having to play nasty tricks to get it. + // + if (flags & kSecCSInternalInformation) { + if (mDir) + CFDictionaryAddValue(dict, kSecCodeInfoCodeDirectory, mDir); + CFDictionaryAddValue(dict, kSecCodeInfoCodeOffset, CFTempNumber(mRep->signingBase())); + if (CFDictionaryRef resources = resourceDictionary()) + CFDictionaryAddValue(dict, kSecCodeInfoResourceDirectory, resources); + } + + + // + // kSecCSContentInformation adds more information about the physical layout + // of the signed code. This is (only) useful for packaging or patching-oriented + // applications. + // + if (flags & kSecCSContentInformation) + if (CFRef files = mRep->modifiedFiles()) + CFDictionaryAddValue(dict, kSecCodeInfoChangedFiles, files); + + return dict.yield(); +} + + +// +// Resource validation contexts. +// The default context simply throws a CSError, rudely terminating the operation. +// +SecStaticCode::ValidationContext::~ValidationContext() +{ /* virtual */ } + +void SecStaticCode::ValidationContext::reportProblem(OSStatus rc, CFStringRef type, CFTypeRef value) +{ + CSError::throwMe(rc, type, value); +} + +void SecStaticCode::CollectingContext::reportProblem(OSStatus rc, CFStringRef type, CFTypeRef value) +{ + if (mStatus == noErr) + mStatus = rc; // record first failure for eventual error return + if (type) { + if (!mCollection) + mCollection.take(makeCFMutableDictionary()); + CFMutableArrayRef element = CFMutableArrayRef(CFDictionaryGetValue(mCollection, type)); + if (!element) { + element = makeCFMutableArray(0); + if (!element) + CFError::throwMe(); + CFDictionaryAddValue(mCollection, type, element); + CFRelease(element); + } + CFArrayAppendValue(element, value); + } +} + +void SecStaticCode::CollectingContext::throwMe() +{ + assert(mStatus != noErr); + throw CSError(mStatus, mCollection.retain()); +} + + +// +// SecStaticCode::AllArchitectures produces SecStaticCode objects separately +// for each architecture represented by a base object. +// +// Performance note: This is a simple, straight-forward implementation that +// does not heroically try to share resources between the code objects produced. +// In practice, this means we'll re-open files and re-read resource files. +// In exchange, we enter all the code paths in the normal way, and do not have +// special sharing paths to worry about. +// If a performance tool brings you here because you have *proof* of a performance +// problem, consider digging up MachO and Universal (for sharing file descriptors), +// and SecStaticCode (for sharing resource iterators). That ought to cover most of +// the big chunks. If you're just offended by the simplicity of this implementation, +// go play somewhere else. +// +SecStaticCode::AllArchitectures::AllArchitectures(SecStaticCode *code) + : mBase(code) +{ + if (Universal *fat = code->diskRep()->mainExecutableImage()) { + fat->architectures(mArchitectures); + mCurrent = mArchitectures.begin(); + mState = fatBinary; + } else { + mState = firstNonFat; + } +} + +SecStaticCode *SecStaticCode::AllArchitectures::operator () () +{ + switch (mState) { + case firstNonFat: + mState = atEnd; + return mBase; + case fatBinary: + { + if (mCurrent == mArchitectures.end()) + return NULL; + Architecture arch = *mCurrent++; + if (arch == mBase->diskRep()->mainExecutableImage()->bestNativeArch()) { + return mBase; + } else { + DiskRep::Context ctx; + ctx.arch = arch; + return new SecStaticCode(DiskRep::bestGuess(mBase->mainExecutablePath(), &ctx)); + } + } + default: + return NULL; + } +} + + +} // end namespace CodeSigning +} // end namespace Security diff --git a/libsecurity_codesigning/lib/StaticCode.h b/libsecurity_codesigning/lib/StaticCode.h new file mode 100644 index 00000000..af255bad --- /dev/null +++ b/libsecurity_codesigning/lib/StaticCode.h @@ -0,0 +1,237 @@ +/* + * 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@ + */ + +// +// StaticCode - SecStaticCode API objects +// +#ifndef _H_STATICCODE +#define _H_STATICCODE + +#include "cs.h" +#include "Requirements.h" +#include "requirement.h" +#include "diskrep.h" +#include "codedirectory.h" +#include +#include + +namespace Security { +namespace CodeSigning { + + +class SecCode; + + +// +// A SecStaticCode object represents the file system version of some code. +// There's a lot of pieces to this, and we'll bring them all into +// memory here (lazily) and let you fondle them with ease. +// +// Note that concrete knowledge of where stuff is stored resides in the DiskRep +// object we hold. DiskReps allocate, retrieve, and return data to us. We are +// responsible for interpreting, caching, and validating them. (In other words, +// DiskReps know where stuff is and how it is stored, but we know what it means.) +// +// Data accessors (returning CFDataRef, CFDictionaryRef, various pointers, etc.) +// cache those values internally and return unretained(!) references ("Get" style) +// that are valid as long as the SecStaticCode object's lifetime, or until +// resetValidity() is called, whichever is sooner. If you need to keep them, +// retain or copy them as needed. +// +class SecStaticCode : public SecCFObject { + NOCOPY(SecStaticCode) + +protected: + // + // A context for resource validation operations, to tailor error response. + // The base class throws an exception immediately and ignores detail data. + // + class ValidationContext { + public: + virtual ~ValidationContext(); + virtual void reportProblem(OSStatus rc, CFStringRef type, CFTypeRef value); + }; + + // + // A CollectingContext collects all error details and throws an annotated final error. + // + class CollectingContext : public ValidationContext { + public: + CollectingContext(SecStaticCode &c) : code(c), mStatus(noErr) { } + 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; + OSStatus mStatus; + }; + +public: + SECCFFUNCTIONS(SecStaticCode, SecStaticCodeRef, + errSecCSInvalidObjectRef, gCFObjects().StaticCode) + + // implicitly convert SecCodeRefs to their SecStaticCodeRefs + static SecStaticCode *requiredStatic(SecStaticCodeRef ref); // convert SecCodeRef + static SecCode *optionalDynamic(SecStaticCodeRef ref); // extract SecCodeRef or NULL + + SecStaticCode(DiskRep *rep); + virtual ~SecStaticCode() throw(); + + bool equal(SecCFObject &other); + CFHashCode hash(); + + void detachedSignature(CFDataRef sig); // attach an explicitly given detached signature + void checkForSystemSignature(); // check for and attach system-supplied detached signature + + const CodeDirectory *codeDirectory(bool check = true); + CFDataRef cdHash(); + CFDataRef signature(); + CFAbsoluteTime signingTime(); + CFAbsoluteTime signingTimestamp(); + bool isSigned() { return codeDirectory(false) != NULL; } + DiskRep *diskRep() { return mRep; } + std::string mainExecutablePath() { return mRep->mainExecutablePath(); } + CFURLRef canonicalPath() const { return mRep->canonicalPath(); } + std::string identifier() { return codeDirectory()->identifier(); } + std::string format() const { return mRep->format(); } + std::string signatureSource(); + CFDataRef component(CodeDirectory::SpecialSlot slot, OSStatus fail = errSecCSSignatureFailed); + CFDictionaryRef infoDictionary(); + CFDictionaryRef entitlements(); + + CFDictionaryRef resourceDictionary(); + CFURLRef resourceBase(); + CFDataRef resource(std::string path); + CFDataRef resource(std::string path, ValidationContext &ctx); + void validateResource(std::string path, ValidationContext &ctx); + + bool flag(uint32_t tested); + + void resetValidity(); // clear validation caches (if something may have changed) + + bool validated() const { return mValidated; } + bool valid() const + { assert(validated()); return mValidated && (mValidationResult == noErr); } + bool validatedExecutable() const { return mExecutableValidated; } + bool validatedResources() const { return mResourcesValidated; } + + void validateDirectory(); + void validateComponent(CodeDirectory::SpecialSlot slot, OSStatus fail = errSecCSSignatureFailed); + void validateNonResourceComponents(); + void validateResources(); + void validateExecutable(); + + const Requirements *internalRequirements(); + const Requirement *internalRequirement(SecRequirementType type); + const Requirement *designatedRequirement(); + const Requirement *defaultDesignatedRequirement(); // newly allocated (caller owns) + + void validateRequirements(SecRequirementType type, SecStaticCode *target, + OSStatus nullError = noErr); // target against my [type], throws + void validateRequirement(const Requirement *req, OSStatus failure); // me against [req], throws + bool satisfiesRequirement(const Requirement *req, OSStatus failure); // me against [req], returns on clean miss + + // certificates are available after signature validation (they are stored in the CMS signature) + SecCertificateRef cert(int ix); // get a cert from the cert chain + CFArrayRef certificates(); // get the entire certificate chain + + CFDictionaryRef signingInformation(SecCSFlags flags); // omnibus information-gathering API (creates new dictionary) + +public: + class AllArchitectures; + +protected: + CFDictionaryRef getDictionary(CodeDirectory::SpecialSlot slot, OSStatus fail); // component value as a dictionary + bool verifySignature(); + CFTypeRef verificationPolicy(SecCSFlags flags); + + static void checkOptionalResource(CFTypeRef key, CFTypeRef value, void *context); + +private: + RefPointer mRep; // on-disk representation + + // master validation state + bool mValidated; // core validation was attempted + OSStatus mValidationResult; // outcome of core validation + bool mValidationExpired; // outcome had expired certificates + + // static executable validation state (nested within mValidated/mValid) + bool mExecutableValidated; // tried to validate executable file + OSStatus mExecutableValidResult; // outcome if mExecutableValidated + + // static resource validation state (nested within mValidated/mValid) + bool mResourcesValidated; // tried to validate resources + OSStatus mResourcesValidResult; // outcome if mResourceValidated or.. + CollectingContext *mResourcesValidContext; // other outcome + + // cached contents + CFRef mDir; // code directory data + CFRef mSignature; // CMS signature data + CFAbsoluteTime mSigningTime; // (signed) signing time + CFAbsoluteTime mSigningTimestamp; // Timestamp time (from timestamping authority) + CFRef mCache[cdSlotCount]; // NULL => not tried, kCFNull => absent, other => present + + // alternative cache forms (storage may depend on cached contents above) + CFRef mInfoDict; // derived from mCache slot + CFRef mEntitlements; // derived from mCache slot + CFRef mResourceDict; // derived from mCache slot + const Requirement *mDesignatedReq; // cached designated req if we made one up + CFRef mCDHash; // hash of CodeDirectory + + bool mGotResourceBase; // asked mRep for resourceBasePath + CFRef mResourceBase; // URL form of resource base directory + + // signature verification outcome (mTrust == NULL => not done yet) + CFRef mTrust; // outcome of crypto validation (valid or not) + CFRef mCertChain; + CSSM_TP_APPLE_EVIDENCE_INFO *mEvalDetails; +}; + + +// +// Given a SecStaticCode, create an iterator that produces SecStaticCodes +// for all architectures encompassed by this static code reference. +// +class SecStaticCode::AllArchitectures : public SecPointer { +public: + AllArchitectures(SecStaticCode *code); + + SecStaticCode *operator () (); + +private: + SecPointer mBase; + enum { fatBinary, firstNonFat, atEnd } mState; + Universal::Architectures mArchitectures; + Universal::Architectures::const_iterator mCurrent; +}; + + +} // end namespace CodeSigning +} // end namespace Security + +#endif // !_H_STATICCODE diff --git a/libsecurity_codesigning/lib/antlrplugin.cpp b/libsecurity_codesigning/lib/antlrplugin.cpp new file mode 100644 index 00000000..fc38e53c --- /dev/null +++ b/libsecurity_codesigning/lib/antlrplugin.cpp @@ -0,0 +1,124 @@ +/* + * 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@ + */ + +#include "antlrplugin.h" +#include "cserror.h" +#include "RequirementLexer.hpp" +#include "RequirementParser.hpp" +#include + + +namespace Security { +namespace CodeSigning { + +namespace Parser = Security_CodeSigning; + + +// +// Lexer input adapters +// +class StdioInputStream : public antlr::InputBuffer { +public: + StdioInputStream(FILE *fp) : mFile(fp) { } + int getChar() { return fgetc(mFile); } + +private: + FILE *mFile; +}; + +class StringInputStream : public antlr::InputBuffer { +public: + StringInputStream(const string &s) : mInput(s), mPos(mInput.begin()) { } + int getChar() { return (mPos == mInput.end()) ? EOF : *mPos++; } + +private: + string mInput; + string::const_iterator mPos; +}; + + +// +// Generic parser driver +// +template +const Result *parse(Source source, Result *(Parser::RequirementParser::*rule)(), std::string &errors) +{ + Input input(source); + Parser::RequirementLexer lexer(input); + Parser::RequirementParser parser(lexer); + try { + const Result *result = (parser.*rule)(); + errors = parser.errors; + if (errors.empty()) + return result; + else + ::free((void *)result); + } catch (const antlr::TokenStreamException &ex) { + errors = ex.toString() + "\n"; + } + return NULL; // signal failure +} + + +// +// Hook up each supported parsing action to the plugin interface +// +const Requirement *fileRequirement(FILE *source, string &errors) +{ return parse(source, &Parser::RequirementParser::requirement, errors); } + +const Requirement *stringRequirement(string source, string &errors) +{ return parse(source, &Parser::RequirementParser::requirement, errors); } + +const Requirements *fileRequirements(FILE *source, string &errors) +{ return parse(source, &Parser::RequirementParser::requirementSet, errors); } + +const Requirements *stringRequirements(string source, string &errors) +{ return parse(source, &Parser::RequirementParser::requirementSet, errors); } + +const BlobCore *fileGeneric(FILE *source, string &errors) +{ return parse(source, &Parser::RequirementParser::autosense, errors); } + +const BlobCore *stringGeneric(string source, string &errors) +{ return parse(source, &Parser::RequirementParser::autosense, errors); } + + +// +// Basic plugin hookup +// +static AntlrPlugin plugin = { + fileRequirement, + fileRequirements, + fileGeneric, + stringRequirement, + stringRequirements, + stringGeneric +}; + +AntlrPlugin *findAntlrPlugin() +{ + return &plugin; +} + + +} // end namespace CodeSigning +} // end namespace Security diff --git a/libsecurity_codesigning/lib/antlrplugin.h b/libsecurity_codesigning/lib/antlrplugin.h new file mode 100644 index 00000000..2d111399 --- /dev/null +++ b/libsecurity_codesigning/lib/antlrplugin.h @@ -0,0 +1,74 @@ +/* + * 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@ + */ + +// +// Plugin interface for internal Security plug-ins +// +#ifndef _H_ANTLRPLUGIN +#define _H_ANTLRPLUGIN + +#include +#include "requirement.h" +#include +#include + +namespace Security { +namespace CodeSigning { + + +// +// The plugin proxy. +// +// During loading, one instance of this object will be created by the plugin +// and returned through the (one and only) dynamically-linked method of the plugin. +// All further interaction then proceeds through methods of this object. +// +// +class AntlrPlugin { +public: + typedef const Requirement *FileRequirement(std::FILE *source, std::string &errors); + FileRequirement *fileRequirement; + typedef const Requirements *FileRequirements(std::FILE *source, std::string &errors); + FileRequirements *fileRequirements; + typedef const BlobCore *FileGeneric(std::FILE *source, std::string &errors); + FileGeneric *fileGeneric; + typedef const Requirement *StringRequirement(std::string source, std::string &errors); + StringRequirement *stringRequirement; + typedef const Requirements *StringRequirements(std::string source, std::string &errors); + StringRequirements *stringRequirements; + typedef const BlobCore *StringGeneric(std::string source, std::string &errors); + StringGeneric *stringGeneric; +}; + +extern "C" { + AntlrPlugin *findAntlrPlugin(); + typedef AntlrPlugin *FindAntlrPlugin(); +} + +#define FINDANTLRPLUGIN "findAntlrPlugin" + + +} // end namespace CodeSigning +} // end namespace Security + +#endif // !_H_ANTLRPLUGIN diff --git a/libsecurity_codesigning/lib/bundlediskrep.cpp b/libsecurity_codesigning/lib/bundlediskrep.cpp new file mode 100644 index 00000000..fa5a8574 --- /dev/null +++ b/libsecurity_codesigning/lib/bundlediskrep.cpp @@ -0,0 +1,480 @@ +/* + * Copyright (c) 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@ + */ +#include "bundlediskrep.h" +#include "filediskrep.h" +#include +#include +#include +#include +#include + + +namespace Security { +namespace CodeSigning { + +using namespace UnixPlusPlus; + + +// +// Local helpers +// +static std::string findDistFile(const std::string &directory); + + +// +// We make a CFBundleRef immediately, but everything else is lazy +// +BundleDiskRep::BundleDiskRep(const char *path, const Context *ctx) + : mBundle(CFBundleCreate(NULL, CFTempURL(path))) +{ + if (!mBundle) + MacOSError::throwMe(errSecCSBadBundleFormat); + setup(ctx); + CODESIGN_DISKREP_CREATE_BUNDLE_PATH(this, (char*)path, (void*)ctx, mExecRep); +} + +BundleDiskRep::BundleDiskRep(CFBundleRef ref, const Context *ctx) +{ + mBundle = ref; // retains + setup(ctx); + CODESIGN_DISKREP_CREATE_BUNDLE_REF(this, ref, (void*)ctx, mExecRep); +} + +// common construction code +void BundleDiskRep::setup(const Context *ctx) +{ + mInstallerPackage = false; // default + + // deal with versioned bundles (aka Frameworks) + string version = resourcesRootPath() + + "/Versions/" + + ((ctx && ctx->version) ? ctx->version : "Current") + + "/."; + if (::access(version.c_str(), F_OK) == 0) { // versioned bundle + if (CFBundleRef versionBundle = CFBundleCreate(NULL, CFTempURL(version))) + mBundle.take(versionBundle); // replace top bundle ref + else + MacOSError::throwMe(errSecCSStaticCodeNotFound); + } else { + if (ctx && ctx->version) // explicitly specified + MacOSError::throwMe(errSecCSStaticCodeNotFound); + } + + CFDictionaryRef infoDict = CFBundleGetInfoDictionary(mBundle); + assert(infoDict); // CFBundle will always make one up for us + CFTypeRef mainHTML = CFDictionaryGetValue(infoDict, CFSTR("MainHTML")); + CFTypeRef packageVersion = CFDictionaryGetValue(infoDict, CFSTR("IFMajorVersion")); + + // conventional executable bundle: CFBundle identifies an executable for us + if (CFRef mainExec = CFBundleCopyExecutableURL(mBundle)) // if CFBundle claims an executable... + if (mainHTML == NULL) { // ... and it's not a widget + mMainExecutableURL = mainExec; + mExecRep = DiskRep::bestFileGuess(this->mainExecutablePath(), ctx); + mFormat = "bundle with " + mExecRep->format(); + return; + } + + // widget + if (mainHTML) { + if (CFGetTypeID(mainHTML) != CFStringGetTypeID()) + MacOSError::throwMe(errSecCSBadBundleFormat); + mMainExecutableURL.take(makeCFURL(cfString(CFStringRef(mainHTML)), false, + CFRef(CFBundleCopySupportFilesDirectoryURL(mBundle)))); + if (!mMainExecutableURL) + MacOSError::throwMe(errSecCSBadBundleFormat); + mExecRep = new FileDiskRep(this->mainExecutablePath().c_str()); + mFormat = "widget bundle"; + return; + } + + // do we have a real Info.plist here? + if (CFRef infoURL = _CFBundleCopyInfoPlistURL(mBundle)) { + // focus on the Info.plist (which we know exists) as the nominal "main executable" file + if ((mMainExecutableURL = _CFBundleCopyInfoPlistURL(mBundle))) { + mExecRep = new FileDiskRep(this->mainExecutablePath().c_str()); + if (packageVersion) { + mInstallerPackage = true; + mFormat = "installer package bundle"; + } else { + mFormat = "bundle"; + } + return; + } + } + + // we're getting desperate here. Perhaps an oldish-style installer package? Look for a *.dist file + std::string distFile = findDistFile(this->resourcesRootPath()); + if (!distFile.empty()) { + mMainExecutableURL = makeCFURL(distFile); + mExecRep = new FileDiskRep(this->mainExecutablePath().c_str()); + mInstallerPackage = true; + mFormat = "installer package bundle"; + return; + } + + // this bundle cannot be signed + MacOSError::throwMe(errSecCSBadBundleFormat); +} + + +// +// Return the full path to the one-and-only file named something.dist in a directory. +// Return empty string if none; throw an exception if multiple. Do not descend into subdirectories. +// +static std::string findDistFile(const std::string &directory) +{ + std::string found; + char *paths[] = {(char *)directory.c_str(), NULL}; + FTS *fts = fts_open(paths, FTS_PHYSICAL | FTS_NOCHDIR | FTS_NOSTAT, NULL); + bool root = true; + while (FTSENT *ent = fts_read(fts)) { + switch (ent->fts_info) { + case FTS_F: + case FTS_NSOK: + if (!strcmp(ent->fts_path + ent->fts_pathlen - 5, ".dist")) { // found plain file foo.dist + if (found.empty()) // first found + found = ent->fts_path; + else // multiple *.dist files (bad) + MacOSError::throwMe(errSecCSBadBundleFormat); + } + break; + case FTS_D: + if (!root) + fts_set(fts, ent, FTS_SKIP); // don't descend + root = false; + break; + default: + break; + } + } + fts_close(fts); + return found; +} + + +// +// Create a path to a bundle signing resource, by name. +// If the BUNDLEDISKREP_DIRECTORY directory exists in the bundle's support directory, files +// will be read and written there. Otherwise, they go directly into the support directory. +// +string BundleDiskRep::metaPath(const char *name) +{ + if (mMetaPath.empty()) { + string support = cfStringRelease(CFBundleCopySupportFilesDirectoryURL(mBundle)); + mMetaPath = support + "/" BUNDLEDISKREP_DIRECTORY; + if (::access(mMetaPath.c_str(), F_OK) == 0) { + mMetaExists = true; + } else { + mMetaPath = support; + mMetaExists = false; + } + } + return mMetaPath + "/" + name; +} + + +// +// Try to create the meta-file directory in our bundle. +// Does nothing if the directory already exists. +// Throws if an error occurs. +// +void BundleDiskRep::createMeta() +{ + string meta = metaPath(BUNDLEDISKREP_DIRECTORY); + if (!mMetaExists) { + if (::mkdir(meta.c_str(), 0755) == 0) { + copyfile(cfString(canonicalPath(), true).c_str(), meta.c_str(), NULL, COPYFILE_SECURITY); + mMetaPath = meta; + mMetaExists = true; + } else if (errno != EEXIST) + UnixError::throwMe(); + } +} + + +// +// Load and return a component, by slot number. +// Info.plist components come from the bundle, always (we don't look +// for Mach-O embedded versions). +// Everything else comes from the embedded blobs of a Mach-O image, or from +// files located in the Contents directory of the bundle. +// +CFDataRef BundleDiskRep::component(CodeDirectory::SpecialSlot slot) +{ + switch (slot) { + // the Info.plist comes from the magic CFBundle-indicated place and ONLY from there + case cdInfoSlot: + if (CFRef info = _CFBundleCopyInfoPlistURL(mBundle)) + return cfLoadFile(info); + else + return NULL; + // by default, we take components from the executable image or files + default: + if (CFDataRef data = mExecRep->component(slot)) + return data; + // falling through + // but the following always come from files + case cdResourceDirSlot: + if (const char *name = CodeDirectory::canonicalSlotName(slot)) + return metaData(name); + else + return NULL; + } +} + + +// +// The binary identifier is taken directly from the main executable. +// +CFDataRef BundleDiskRep::identification() +{ + return mExecRep->identification(); +} + + +// +// Various aspects of our DiskRep personality. +// +CFURLRef BundleDiskRep::canonicalPath() +{ + return CFBundleCopyBundleURL(mBundle); +} + +string BundleDiskRep::mainExecutablePath() +{ + return cfString(mMainExecutableURL); +} + +string BundleDiskRep::resourcesRootPath() +{ + return cfStringRelease(CFBundleCopySupportFilesDirectoryURL(mBundle)); +} + +void BundleDiskRep::adjustResources(ResourceBuilder &builder) +{ + // exclude entire contents of meta directory + builder.addExclusion("^" BUNDLEDISKREP_DIRECTORY "/"); + + // exclude the store manifest directory + builder.addExclusion("^" STORE_RECEIPT_DIRECTORY "/"); + + // exclude the main executable file + string resources = resourcesRootPath(); + string executable = mainExecutablePath(); + if (!executable.compare(0, resources.length(), resources, 0, resources.length())) // is prefix + builder.addExclusion(string("^") + + ResourceBuilder::escapeRE(executable.substr(resources.length() + 1)) + "$"); +} + + + +Universal *BundleDiskRep::mainExecutableImage() +{ + return mExecRep->mainExecutableImage(); +} + +size_t BundleDiskRep::signingBase() +{ + return mExecRep->signingBase(); +} + +size_t BundleDiskRep::signingLimit() +{ + return mExecRep->signingLimit(); +} + +string BundleDiskRep::format() +{ + return mFormat; +} + +CFArrayRef BundleDiskRep::modifiedFiles() +{ + CFMutableArrayRef files = CFArrayCreateMutableCopy(NULL, 0, mExecRep->modifiedFiles()); + checkModifiedFile(files, cdCodeDirectorySlot); + checkModifiedFile(files, cdSignatureSlot); + checkModifiedFile(files, cdResourceDirSlot); + checkModifiedFile(files, cdEntitlementSlot); + return files; +} + +void BundleDiskRep::checkModifiedFile(CFMutableArrayRef files, CodeDirectory::SpecialSlot slot) +{ + if (CFDataRef data = mExecRep->component(slot)) // provided by executable file + CFRelease(data); + else if (const char *resourceName = CodeDirectory::canonicalSlotName(slot)) { + string file = metaPath(resourceName); + if (::access(file.c_str(), F_OK) == 0) + CFArrayAppendValue(files, CFTempURL(file)); + } +} + +FileDesc &BundleDiskRep::fd() +{ + return mExecRep->fd(); +} + +void BundleDiskRep::flush() +{ + mExecRep->flush(); +} + + +// +// Defaults for signing operations +// +string BundleDiskRep::recommendedIdentifier(const SigningContext &) +{ + if (CFStringRef identifier = CFBundleGetIdentifier(mBundle)) + return cfString(identifier); + if (CFDictionaryRef infoDict = CFBundleGetInfoDictionary(mBundle)) + if (CFStringRef identifier = CFStringRef(CFDictionaryGetValue(infoDict, kCFBundleNameKey))) + return cfString(identifier); + + // fall back to using the canonical path + return canonicalIdentifier(cfString(this->canonicalPath())); +} + +CFDictionaryRef BundleDiskRep::defaultResourceRules(const SigningContext &) +{ + // consider the bundle's structure + string rbase = this->resourcesRootPath(); + if (rbase.substr(rbase.length()-2, 2) == "/.") // produced by versioned bundle implicit "Current" case + rbase = rbase.substr(0, rbase.length()-2); // ... so take it off for this + string resources = cfStringRelease(CFBundleCopyResourcesDirectoryURL(mBundle)); + if (resources == rbase) + resources = ""; + else if (resources.compare(0, rbase.length(), rbase, 0, rbase.length()) != 0) // Resources not in resource root + MacOSError::throwMe(errSecCSBadBundleFormat); + else + resources = resources.substr(rbase.length() + 1) + "/"; // differential path segment + + // installer package rules + if (mInstallerPackage) + return cfmake("{rules={" + "'^.*' = #T" // include everything, but... + "%s = {optional=#T, weight=1000}" // make localizations optional + "'^.*/.*\\.pkg/' = {omit=#T, weight=10000}" // and exclude all nested packages (by name) + "}}", + (string("^") + resources + ".*\\.lproj/").c_str() + ); + + // executable bundle rules + return cfmake("{rules={" + "'^version.plist$' = #T" // include version.plist + "%s = #T" // include Resources + "%s = {optional=#T, weight=1000}" // make localizations optional + "%s = {omit=#T, weight=1100}" // exclude all locversion.plist files + "}}", + (string("^") + resources).c_str(), + (string("^") + resources + ".*\\.lproj/").c_str(), + (string("^") + resources + ".*\\.lproj/locversion.plist$").c_str() + ); +} + +const Requirements *BundleDiskRep::defaultRequirements(const Architecture *arch, const SigningContext &ctx) +{ + return mExecRep->defaultRequirements(arch, ctx); +} + +size_t BundleDiskRep::pageSize(const SigningContext &ctx) +{ + return mExecRep->pageSize(ctx); +} + + +// +// Writers +// +DiskRep::Writer *BundleDiskRep::writer() +{ + return new Writer(this); +} + +BundleDiskRep::Writer::Writer(BundleDiskRep *r) + : rep(r), mMadeMetaDirectory(false) +{ + execWriter = rep->mExecRep->writer(); +} + + +// +// 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, we write to a file in the Bundle's meta directory. +// +void BundleDiskRep::Writer::component(CodeDirectory::SpecialSlot slot, CFDataRef data) +{ + switch (slot) { + default: + if (!execWriter->attribute(writerLastResort)) // willing to take the data... + return execWriter->component(slot, data); // ... so hand it through + // execWriter doesn't want the data; store it as a resource file (below) + case cdResourceDirSlot: + // the resource directory always goes into a bundle file + if (const char *name = CodeDirectory::canonicalSlotName(slot)) { + rep->createMeta(); + string path = rep->metaPath(name); + AutoFileDesc fd(path, O_WRONLY | O_CREAT | O_TRUNC, 0644); + fd.writeAll(CFDataGetBytePtr(data), CFDataGetLength(data)); + } else + MacOSError::throwMe(errSecCSBadBundleFormat); + } +} + + +// +// Remove all signature data +// +void BundleDiskRep::Writer::remove() +{ + // remove signature from the executable + execWriter->remove(); + + // remove signature files from bundle + for (CodeDirectory::SpecialSlot slot = 0; slot < cdSlotCount; slot++) + remove(slot); + remove(cdSignatureSlot); +} + +void BundleDiskRep::Writer::remove(CodeDirectory::SpecialSlot slot) +{ + if (const char *name = CodeDirectory::canonicalSlotName(slot)) + if (::unlink(rep->metaPath(name).c_str())) + switch (errno) { + case ENOENT: // not found - that's okay + break; + default: + UnixError::throwMe(); + } +} + + +void BundleDiskRep::Writer::flush() +{ + execWriter->flush(); +} + + +} // end namespace CodeSigning +} // end namespace Security diff --git a/libsecurity_codesigning/lib/bundlediskrep.h b/libsecurity_codesigning/lib/bundlediskrep.h new file mode 100644 index 00000000..bef1861b --- /dev/null +++ b/libsecurity_codesigning/lib/bundlediskrep.h @@ -0,0 +1,127 @@ +/* + * Copyright (c) 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@ + */ + +// +// bundlediskrep - bundle directory disk representation +// +#ifndef _H_BUNDLEDISKREP +#define _H_BUNDLEDISKREP + +#include "diskrep.h" +#include "machorep.h" + +namespace Security { +namespace CodeSigning { + + +#define BUNDLEDISKREP_DIRECTORY "_CodeSignature" +#define STORE_RECEIPT_DIRECTORY "_MASReceipt" + + +// +// A BundleDiskRep represents a standard Mac OS X bundle on disk. +// The bundle is expected to have an Info.plist, and a "main executable file" +// of some sort (as indicated therein). +// The BundleDiskRep stores the necessary components in the main executable +// if it is in Mach-O format, or in files in a _CodeSignature directory if not. +// This DiskRep supports resource sealing. +// +class BundleDiskRep : public DiskRep { +public: + BundleDiskRep(const char *path, const Context *ctx = NULL); + BundleDiskRep(CFBundleRef ref, const Context *ctx = NULL); + + CFDataRef component(CodeDirectory::SpecialSlot slot); + CFDataRef identification(); + std::string mainExecutablePath(); + CFURLRef canonicalPath(); + std::string resourcesRootPath(); + void adjustResources(ResourceBuilder &builder); + Universal *mainExecutableImage(); + size_t signingBase(); + size_t signingLimit(); + std::string format(); + CFArrayRef modifiedFiles(); + UnixPlusPlus::FileDesc &fd(); + void flush(); + + std::string recommendedIdentifier(const SigningContext &ctx); + CFDictionaryRef defaultResourceRules(const SigningContext &ctx); + const Requirements *defaultRequirements(const Architecture *arch, const SigningContext &ctx); + size_t pageSize(const SigningContext &ctx); + + CFBundleRef bundle() const { return mBundle; } + +public: + Writer *writer(); + class Writer; + friend class Writer; + +protected: + std::string metaPath(const char *name); + CFDataRef metaData(const char *name) { return cfLoadFile(CFTempURL(metaPath(name))); } + void createMeta(); // (try to) create the meta-file directory + +private: + void setup(const Context *ctx); // shared init + void checkModifiedFile(CFMutableArrayRef files, CodeDirectory::SpecialSlot slot); + +private: + CFRef mBundle; + std::string mMetaPath; // path to directory containing signing files + bool mMetaExists; // separate meta-file directory exists + CFRef mMainExecutableURL; // chosen main executable URL + bool mInstallerPackage; // is an installer (not executable) bundle + string mFormat; // format description string + RefPointer mExecRep; // DiskRep for main executable file +}; + + +// +// Writers +// +// +class BundleDiskRep::Writer : public DiskRep::Writer { + friend class BundleDiskRep; +public: + Writer(BundleDiskRep *r); + + void component(CodeDirectory::SpecialSlot slot, CFDataRef data); + void remove(); + void flush(); + +protected: + DiskRep *execRep() { return rep->mExecRep; } + void remove(CodeDirectory::SpecialSlot slot); + +protected: + RefPointer rep; + RefPointer execWriter; + bool mMadeMetaDirectory; +}; + + +} // end namespace CodeSigning +} // end namespace Security + +#endif // !_H_BUNDLEDISKREP diff --git a/libsecurity_codesigning/lib/cdbuilder.cpp b/libsecurity_codesigning/lib/cdbuilder.cpp new file mode 100644 index 00000000..ac17edbc --- /dev/null +++ b/libsecurity_codesigning/lib/cdbuilder.cpp @@ -0,0 +1,217 @@ +/* + * 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@ + */ + +// +// cdbuilder - constructor for CodeDirectories +// +#include "cdbuilder.h" +#include +#include + +using namespace UnixPlusPlus; +using LowLevelMemoryUtilities::alignUp; + + +namespace Security { +namespace CodeSigning { + + +// +// Create an (empty) builder +// +CodeDirectory::Builder::Builder(HashAlgorithm digestAlgorithm) + : mFlags(0), + mHashType(digestAlgorithm), + mSpecialSlots(0), + mCodeSlots(0), + mScatter(NULL), + mScatterSize(0), + mDir(NULL) +{ + mDigestLength = MakeHash(this)->digestLength(); + mSpecial = (unsigned char *)calloc(cdSlotMax, mDigestLength); +} + +CodeDirectory::Builder::~Builder() +{ + ::free(mSpecial); + ::free(mScatter); +} + + +// +// Set the source of the main executable (i.e. the code pages) +// +void CodeDirectory::Builder::executable(string path, + size_t pagesize, size_t offset, size_t length) +{ + mExec.close(); // any previously opened one + mExec.open(path); + mPageSize = pagesize; + mExecOffset = offset; + mExecLength = length; +} + +void CodeDirectory::Builder::reopen(string path, size_t offset, size_t length) +{ + assert(mExec); // already called executable() + mExec.close(); + mExec.open(path); + mExecOffset = offset; + mExecLength = length; +} + + +// +// Set the source for one special slot +// +void CodeDirectory::Builder::specialSlot(SpecialSlot slot, CFDataRef data) +{ + assert(slot <= cdSlotMax); + MakeHash hash(this); + hash->update(CFDataGetBytePtr(data), CFDataGetLength(data)); + hash->finish(specialSlot(slot)); + if (slot >= mSpecialSlots) + mSpecialSlots = slot; +} + + +// +// Allocate a Scatter vector +// +CodeDirectory::Scatter *CodeDirectory::Builder::scatter(unsigned count) +{ + mScatterSize = (count + 1) * sizeof(Scatter); + if (!(mScatter = (Scatter *)::realloc(mScatter, mScatterSize))) + UnixError::throwMe(ENOMEM); + ::memset(mScatter, 0, mScatterSize); + return mScatter; +} + + +// +// Calculate the size we'll need for the CodeDirectory as described so far +// +size_t CodeDirectory::Builder::size() +{ + assert(mExec); // must have called executable() + if (mExecLength == 0) + mExecLength = mExec.fileSize() - mExecOffset; + + // how many code pages? + if (mPageSize == 0) { // indefinite - one page + mCodeSlots = (mExecLength > 0); + } else { // finite - calculate from file size + mCodeSlots = (mExecLength + mPageSize - 1) / mPageSize; // round up + } + + size_t offset = sizeof(CodeDirectory); + offset += mScatterSize; // scatter vector + offset += mIdentifier.size() + 1; // size of identifier (with null byte) + offset += (mCodeSlots + mSpecialSlots) * mDigestLength; // hash vector + return offset; +} + + +// +// Take everything added to date and wrap it up in a shiny new CodeDirectory. +// +// Note that this only constructs a CodeDirectory; it does not touch any subsidiary +// structures (resource tables, etc.), nor does it create any signature to secure +// the CodeDirectory. +// The returned CodeDirectory object is yours, and you may modify it as desired. +// But the memory layout is set here, so the various sizes and counts should be good +// when you call build(). +// It's up to us to order the dynamic fields as we wish; but note that we currently +// don't pad them, and so they should be allocated in non-increasing order of required +// alignment. Make sure to keep the code here in sync with the size-calculating code above. +// +CodeDirectory *CodeDirectory::Builder::build() +{ + assert(mExec); // must have (successfully) called executable() + + // size and allocate + size_t identLength = mIdentifier.size() + 1; + size_t total = size(); + if (!(mDir = (CodeDirectory *)calloc(1, total))) // initialize to zero + UnixError::throwMe(ENOMEM); + + // fill header + mDir->initialize(total); + mDir->version = currentVersion; + mDir->flags = mFlags; + mDir->nSpecialSlots = mSpecialSlots; + mDir->nCodeSlots = mCodeSlots; + mDir->codeLimit = mExecLength; + mDir->hashType = mHashType; + mDir->hashSize = mDigestLength; + if (mPageSize) { + int pglog; + assert(frexp(mPageSize, &pglog) == 0.5); // must be power of 2 + frexp(mPageSize, &pglog); + assert(pglog < 256); + mDir->pageSize = pglog - 1; + } else + mDir->pageSize = 0; // means infinite page size + + // locate and fill flex fields + size_t offset = sizeof(CodeDirectory); + + if (mScatter) { + mDir->scatterOffset = offset; + memcpy(mDir->scatterVector(), mScatter, mScatterSize); + offset += mScatterSize; + } + + mDir->identOffset = offset; + memcpy(mDir->identifier(), mIdentifier.c_str(), identLength); + offset += identLength; + + // (add new flexibly-allocated fields here) + + mDir->hashOffset = offset + mSpecialSlots * mDigestLength; + offset += (mSpecialSlots + mCodeSlots) * mDigestLength; + assert(offset == total); // matches allocated size + + // fill special slots + memset((*mDir)[-mSpecialSlots], 0, mDigestLength * mSpecialSlots); + for (size_t slot = 1; slot <= mSpecialSlots; ++slot) + memcpy((*mDir)[-slot], specialSlot(slot), mDigestLength); + + // fill code slots + mExec.seek(mExecOffset); + size_t remaining = mExecLength; + for (unsigned int slot = 0; slot < mCodeSlots; ++slot) { + size_t thisPage = min(mPageSize, remaining); + MakeHash hasher(this); + generateHash(hasher, mExec, (*mDir)[slot], thisPage); + remaining -= thisPage; + } + + // all done. Pass ownership to caller + return mDir; +} + + +} // CodeSigning +} // Security diff --git a/libsecurity_codesigning/lib/cdbuilder.h b/libsecurity_codesigning/lib/cdbuilder.h new file mode 100644 index 00000000..3a050bbf --- /dev/null +++ b/libsecurity_codesigning/lib/cdbuilder.h @@ -0,0 +1,95 @@ +/* + * 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@ + */ + +// +// cdbuilder - constructor for CodeDirectories +// +#ifndef _H_CDBUILDER +#define _H_CDBUILDER + +#include "codedirectory.h" + + +namespace Security { +namespace CodeSigning { + + +// +// Builder can construct CodeDirectories from pieces: +// Builder builder(...); +// builder.variousSetters(withSuitableData); +// CodeDirectory *result = builder.build(); +// Builder is not reusable. +// +class CodeDirectory::Builder { +public: + Builder(HashAlgorithm digestAlgorithm); + ~Builder(); + + void executable(string path, size_t pagesize, size_t offset, size_t length); + void reopen(string path, size_t offset, size_t length); + + void specialSlot(SpecialSlot slot, CFDataRef data); + void identifier(const std::string &code) { mIdentifier = code; } + void flags(uint32_t f) { mFlags = f; } + + Scatter *scatter(unsigned count); // allocate that many scatter elements (w/o sentinel) + Scatter *scatter() { return mScatter; } // return already allocated scatter vector + + size_t size(); // calculate size + CodeDirectory *build(); // build CodeDirectory and return it + +private: + DynamicHash *getHash() const { return CodeDirectory::hashFor(this->mHashType); } + + Hashing::Byte *specialSlot(SpecialSlot slot) + { assert(slot > 0 && slot <= cdSlotMax); return mSpecial + (slot - 1) * mDigestLength; } + Hashing::Byte *specialSlot(SpecialSlot slot) const + { assert(slot > 0 && slot <= cdSlotMax); return mSpecial + (slot - 1) * mDigestLength; } + +private: + Hashing::Byte *mSpecial; // array of special slot hashes + UnixPlusPlus::AutoFileDesc mExec; // main executable file + size_t mExecOffset; // starting offset in mExec + size_t mExecLength; // total bytes of file to sign + size_t mPageSize; // page size of executable (bytes) + uint32_t mFlags; // CodeDirectory flags + uint32_t mHashType; // digest algorithm code + uint32_t mDigestLength; // number of bytes in a single glue digest + std::string mIdentifier; // canonical identifier + + size_t mSpecialSlots; // highest special slot set + size_t mCodeSlots; // number of code pages (slots) + + Scatter *mScatter; // scatter vector + size_t mScatterSize; // number of scatter elements allocated (incl. sentinel) + + CodeDirectory *mDir; // what we're building +}; + + +} // CodeSigning +} // Security + + +#endif //_H_CDBUILDER diff --git a/libsecurity_codesigning/lib/cfmdiskrep.cpp b/libsecurity_codesigning/lib/cfmdiskrep.cpp new file mode 100644 index 00000000..6ba10f26 --- /dev/null +++ b/libsecurity_codesigning/lib/cfmdiskrep.cpp @@ -0,0 +1,224 @@ +/* + * 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 = 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 new file mode 100644 index 00000000..3ea17ab8 --- /dev/null +++ b/libsecurity_codesigning/lib/cfmdiskrep.h @@ -0,0 +1,112 @@ +/* + * 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/codedirectory.cpp b/libsecurity_codesigning/lib/codedirectory.cpp new file mode 100644 index 00000000..0bcb9801 --- /dev/null +++ b/libsecurity_codesigning/lib/codedirectory.cpp @@ -0,0 +1,270 @@ +/* + * 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@ + */ + +// +// codedirectory - format and operations for code signing "code directory" structures +// +#include "codedirectory.h" +#include "csutilities.h" +#include "CSCommonPriv.h" + +using namespace UnixPlusPlus; + + +namespace Security { +namespace CodeSigning { + + +// +// Highest understood special slot in this CodeDirectory. +// +CodeDirectory::SpecialSlot CodeDirectory::maxSpecialSlot() const +{ + SpecialSlot slot = this->nSpecialSlots; + if (slot > cdSlotMax) + slot = cdSlotMax; + return slot; +} + + +// +// Canonical filesystem names for select slot numbers. +// These are variously used for filenames, extended attribute names, etc. +// to get some consistency in naming. These are for storing signing-related +// data; they have no bearing on the actual hash slots in the CodeDirectory. +// +const char *CodeDirectory::canonicalSlotName(SpecialSlot slot) +{ + switch (slot) { + case cdRequirementsSlot: + return kSecCS_REQUIREMENTSFILE; + case cdResourceDirSlot: + return kSecCS_RESOURCEDIRFILE; + case cdCodeDirectorySlot: + return kSecCS_CODEDIRECTORYFILE; + case cdSignatureSlot: + return kSecCS_SIGNATUREFILE; + case cdApplicationSlot: + return kSecCS_APPLICATIONFILE; + case cdEntitlementSlot: + return kSecCS_ENTITLEMENTFILE; + default: + return NULL; + } +} + + +// +// Canonical attributes of SpecialSlots. +// +unsigned CodeDirectory::slotAttributes(SpecialSlot slot) +{ + switch (slot) { + case cdRequirementsSlot: + return cdComponentIsBlob; // global + case cdCodeDirectorySlot: + return cdComponentPerArchitecture | cdComponentIsBlob; + case cdSignatureSlot: + return cdComponentPerArchitecture; // raw + case cdEntitlementSlot: + return cdComponentIsBlob; // global + case cdIdentificationSlot: + return cdComponentPerArchitecture; // raw + default: + return 0; // global, raw + } +} + + +// +// Symbolic names for code directory special slots. +// These are only used for debug output. They are not API-official. +// Needs to be coordinated with the cd*Slot enumeration in codedirectory.h. +// +#if !defined(NDEBUG) +const char * const CodeDirectory::debugSlotName[] = { + "codedirectory", + "info", + "requirements", + "resources", + "application", + "entitlement" +}; +#endif //NDEBUG + + +// +// Check a CodeDirectory for basic integrity. This should ensure that the +// version is understood by our code, and that the internal structure +// (offsets etc.) is intact. In particular, it must make sure that no offsets +// point outside the CodeDirectory. +// Throws if the directory is corrupted or out of versioning bounds. +// Returns if the version is usable (perhaps with degraded features due to +// compatibility hacks). +// +// Note: There are some things we don't bother checking because they won't +// cause crashes, and will just be flagged as nonsense later. For example, +// a Bad Guy could overlap the identifier and hash fields, which is nonsense +// but not dangerous. +// +void CodeDirectory::checkIntegrity() const +{ + // check version for support + if (!this->validateBlob()) + MacOSError::throwMe(errSecCSSignatureInvalid); // busted + if (version > compatibilityLimit) + MacOSError::throwMe(errSecCSSignatureUnsupported); // too new - no clue + if (version < earliestVersion) + MacOSError::throwMe(errSecCSSignatureUnsupported); // too old - can't support + if (version > currentVersion) + secdebug("codedir", "%p version 0x%x newer than current 0x%x", + this, uint32_t(version), currentVersion); + + // now check interior offsets for validity + if (!stringAt(identOffset)) + MacOSError::throwMe(errSecCSSignatureFailed); // identifier out of blob range + if (!contains(hashOffset - uint64_t(hashSize) * nSpecialSlots, hashSize * (uint64_t(nSpecialSlots) + nCodeSlots))) + MacOSError::throwMe(errSecCSSignatureFailed); // hash array out of blob range + if (const Scatter *scatter = this->scatterVector()) { + // the optional scatter vector is terminated with an element having (count == 0) + unsigned int pagesConsumed = 0; + while (scatter->count) { + if (!contains(scatter, sizeof(Scatter))) + MacOSError::throwMe(errSecCSSignatureFailed); + pagesConsumed += scatter->count; + scatter++; + } + if (!contains(scatter, sizeof(Scatter))) // (even sentinel must be in range) + MacOSError::throwMe(errSecCSSignatureFailed); + if (!contains((*this)[pagesConsumed-1], hashSize)) // referenced too many main hash slots + MacOSError::throwMe(errSecCSSignatureFailed); + } +} + + +// +// Validate a slot against data in memory. +// +bool CodeDirectory::validateSlot(const void *data, size_t length, Slot slot) const +{ + secdebug("codedir", "%p validating slot %d", this, int(slot)); + MakeHash hasher(this); + Hashing::Byte digest[hasher->digestLength()]; + generateHash(hasher, data, length, digest); + return memcmp(digest, (*this)[slot], hasher->digestLength()) == 0; +} + + +// +// Validate a slot against the contents of an open file. At most 'length' bytes +// will be read from the file. +// +bool CodeDirectory::validateSlot(FileDesc fd, size_t length, Slot slot) const +{ + MakeHash hasher(this); + Hashing::Byte digest[hasher->digestLength()]; + generateHash(hasher, fd, digest, length); + return memcmp(digest, (*this)[slot], hasher->digestLength()) == 0; +} + + +// +// Check whether a particular slot is present. +// Absense is indicated by either a zero hash, or by lying outside +// the slot range. +// +bool CodeDirectory::slotIsPresent(Slot slot) const +{ + if (slot >= -Slot(nSpecialSlots) && slot < Slot(nCodeSlots)) { + const Hashing::Byte *digest = (*this)[slot]; + for (unsigned n = 0; n < hashSize; n++) + if (digest[n]) + return true; // non-zero digest => present + } + return false; // absent +} + + +// +// Given a hash type code, create an appropriate subclass of DynamicHash +// and return it. The caller owns the object and must delete it when done. +// This function never returns NULL. It throws if the hashType is unsuupported, +// or if there's an error creating the hasher. +// +DynamicHash *CodeDirectory::hashFor(HashAlgorithm hashType) +{ + CCDigestAlg alg; + switch (hashType) { + case kSecCodeSignatureHashSHA1: alg = kCCDigestSHA1; break; + case kSecCodeSignatureHashSHA256: alg = kCCDigestSHA256; break; + case kSecCodeSignatureHashPrestandardSkein160x256: alg = kCCDigestSkein160; break; + case kSecCodeSignatureHashPrestandardSkein256x512: alg = kCCDigestSkein256; break; + default: + MacOSError::throwMe(errSecCSSignatureUnsupported); + } + return new CCHashInstance(alg); +} + + +// +// Hash the next limit bytes of a file and return the digest. +// If the file is shorter, hash as much as you can. +// Limit==0 means unlimited (to end of file). +// Return how many bytes were actually hashed. +// Throw on any errors. +// +size_t CodeDirectory::generateHash(DynamicHash *hasher, FileDesc fd, Hashing::Byte *digest, size_t limit) +{ + size_t size = hashFileData(fd, hasher, limit); + hasher->finish(digest); + return size; +} + + +// +// Ditto, but hash a memory buffer instead. +// +size_t CodeDirectory::generateHash(DynamicHash *hasher, const void *data, size_t length, Hashing::Byte *digest) +{ + hasher->update(data, length); + hasher->finish(digest); + return length; +} + + +} // CodeSigning +} // Security + + +// +// Canonical text form for user-settable code directory flags. +// Note: This table is actually exported from Security.framework. +// +const SecCodeDirectoryFlagTable kSecCodeDirectoryFlagTable[] = { + { "host", kSecCodeSignatureHost, true }, + { "adhoc", kSecCodeSignatureAdhoc, false }, + { "hard", kSecCodeSignatureForceHard, true }, + { "kill", kSecCodeSignatureForceKill, true }, + { "expires", kSecCodeSignatureForceExpiration, true }, + { NULL } +}; diff --git a/libsecurity_codesigning/lib/codedirectory.h b/libsecurity_codesigning/lib/codedirectory.h new file mode 100644 index 00000000..1028fd7f --- /dev/null +++ b/libsecurity_codesigning/lib/codedirectory.h @@ -0,0 +1,265 @@ +/* + * 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@ + */ + +// +// codedirectory - format and operations for code signing "code directory" structures +// +// A CodeDirectory is the top level object describing a particular instance +// of (static) code. It contains hashes of other objects that further describe +// parts of that code; these hashes hold the various pieces together. +// +// This means that if you reliably ascertain the contents of a CodeDirectory, +// you can verify the integrity of the entire code object it represents - the +// CodeDirectory can stand as a proxy for that code. +// +// Code signatures usually use CMS to sign the CodeDirectory to form full +// signature blobs; ad-hoc signatures simply record the SHA-1 hash of the +// CodeDirectory directly. The SHA-1 of the CodeDirectory is also widely +// used as concordance for a particular code instance - in essence, for +// different processes (or a process and the kernel) to "compare notes" +// to make sure they refer to the same code. +// +#ifndef _H_CODEDIRECTORY +#define _H_CODEDIRECTORY + +#include +#include +#include +#include +#include + + +namespace Security { +namespace CodeSigning { + + +// +// Conventional string names for various code signature components. +// Depending on storage, these may end up as filenames, extended attribute names, etc. +// +#define kSecCS_CODEDIRECTORYFILE "CodeDirectory" // CodeDirectory +#define kSecCS_SIGNATUREFILE "CodeSignature" // CMS Signature +#define kSecCS_REQUIREMENTSFILE "CodeRequirements" // internal requirements +#define kSecCS_RESOURCEDIRFILE "CodeResources" // resource directory +#define kSecCS_APPLICATIONFILE "CodeApplication" // application-specific resource +#define kSecCS_ENTITLEMENTFILE "CodeEntitlements" // entitlement configuration + + +// +// Special hash slot values. In a CodeDirectory, these show up at negative slot +// indices. This enumeration is also used widely in various internal APIs, and as +// type values in embedded SuperBlobs. +// +// How to add a new special slot type: +// 1. Add the new name at the end of the primary or virtual slot array (below). +// 2a. For slots representing existing code pieces, follow the ball for cdInfoSlot. +// 2b. For slots representing global signature components, follow the ball for cdResourceDirSlot. +// 2c. For slots representing per-architecture signature components, follow the ball for cdEntitlementSlot. +// ("Follow the ball" -> Global search for that name and do likewise.) +// +enum { + // + // Primary slot numbers. + // These values are potentially present in the CodeDirectory hash array + // under their negative values. They are also used in APIs and SuperBlobs. + // Note that zero must not be used for these (it's page 0 of the main code array), + // and it is important to assign contiguous (very) small values for them. + // + cdInfoSlot = 1, // Info.plist + cdRequirementsSlot = 2, // internal requirements + cdResourceDirSlot = 3, // resource directory + cdApplicationSlot = 4, // Application specific slot + cdEntitlementSlot = 5, // embedded entitlement configuration + // (add further primary slot numbers here) + + cdSlotCount, // total number of special slots (+1 for slot 0) + cdSlotMax = cdSlotCount - 1, // highest special slot number (as a positive number) + + // + // Virtual slot numbers. + // These values are NOT used in the CodeDirectory hash array. They are used as + // internal API identifiers and as types in SuperBlobs. + // Zero is okay to use here; and we assign that to the CodeDirectory itself so + // it shows up first in (properly sorted) SuperBlob indices. The rest of the + // numbers is set Far Away so the primary slot set can expand safely. + // It's okay to have large gaps in these assignments. + // + cdCodeDirectorySlot = 0, // CodeDirectory + cdSignatureSlot = 0x10000, // CMS signature + cdIdentificationSlot, // identification blob + // (add further virtual slot numbers here) +}; + + +// +// Special hash slot attributes. +// This is a central description of attributes of each slot. +// Various places in Code Signing pick up those attributes and act accordingly. +// +enum { + cdComponentPerArchitecture = 1, // slot value differs for each Mach-O architecture + cdComponentIsBlob = 2, // slot value is a Blob (need not be BlobWrapped) +}; + + +// +// A CodeDirectory is a typed Blob describing the secured pieces of a program. +// This structure describes the common header and provides access to the variable-size +// elements packed after it. For help in constructing a CodeDirectory, use the nested +// Builder class. +// +// At the heart of a CodeDirectory lies a packed array of hash digests. +// The array's zero-index element is at offset hashOffset, and the array covers +// elements in the range [-nSpecialSlots .. nCodeSlots-1]. Non-negative indices +// denote pages of the main executable. Negative indices indicate "special" hashes, +// each of a different thing (see cd*Slot constants above). +// Special slots that are in range but not present are zeroed out. Unallocated special +// slots are also presumed absent; this is not an error. (Thus the range of special +// slots can be extended at will.) +// +// HOW TO MANAGE COMPATIBILITY: +// Each CodeDirectory has a format (compatibility) version. Two constants control +// versioning: +// * currentVersion is the version used for newly created CodeDirectories. +// * compatibilityLimit is the highest version the code will accept as compatible. +// Test for version < currentVersion to detect old formats that may need special +// handling; this is done in checkIntegrity(). The current code rejects versions +// below earliestVersion. +// Break backward compatibility by rejecting versions that are unsuitable. +// Accept currentVersion < version <= compatibilityLimit as versions newer than +// those understood by this code but engineered (by newer code) to be backward +// compatible. Reject version > compatibilityLimit as incomprehensible gibberish. +// +// When creating a new version, increment currentVersion. When adding new fixed fields, +// just append them; the flex fields will shift to make room. To add new flex fields, +// add a fixed field containing the new field's offset and add suitable computations +// to the Builder to place the new data (right) before the hash array. Remember to check +// for offset in-range in checkIntegrity(). Older code will then simply ignore your +// new fields on load/read. +// Add flag bits to the existing flags field to add features that step outside +// of the linear versioning stream. Leave the 'spare' fields alone unless you need +// something extraordinarily weird - they're meant to be the final escape when everything +// else fails. +// As you create new versions, consider moving the compatibilityLimit out to open up +// new room for backward compatibility. +// To break backward compatibility intentionally, move currentVersion beyond the +// old compatibilityLimit (and move compatibilityLimit further out). +// +class CodeDirectory: public Blob { +public: + Endian version; // compatibility version + Endian flags; // setup and mode flags + Endian hashOffset; // offset of hash slot element at index zero + Endian identOffset; // offset of identifier string + Endian nSpecialSlots; // number of special hash slots + Endian nCodeSlots; // number of ordinary (code) hash slots + Endian codeLimit; // limit to main image signature range + uint8_t hashSize; // size of each hash digest (bytes) + uint8_t hashType; // type of hash (kSecCodeSignatureHash* constants) + uint8_t spare1; // unused (must be zero) + uint8_t pageSize; // log2(page size in bytes); 0 => infinite + Endian spare2; // unused (must be zero) + Endian scatterOffset; // offset of optional scatter vector (zero if absent) + + // works with the version field; see comments above + static const uint32_t currentVersion = 0x20100; // "version 2.1" + static const uint32_t compatibilityLimit = 0x2F000; // "version 3 with wiggle room" + + static const uint32_t earliestVersion = 0x20001; // earliest supported version + static const uint32_t supportsScatter = 0x20100; // first version to support scatter option + + void checkIntegrity() const; // throws if inconsistent or unsupported version + + typedef uint32_t HashAlgorithm; // types of internal glue hashes + typedef int Slot; // slot index (negative for special slots) + typedef unsigned int SpecialSlot; // positive special slot index (not for code slots) + + const char *identifier() const { return at(identOffset); } + char *identifier() { return at(identOffset); } + + // main hash array access + SpecialSlot maxSpecialSlot() const; + + unsigned char *operator [] (Slot slot) + { + assert(slot >= int(-nSpecialSlots) && slot < int(nCodeSlots)); + return at(hashOffset) + hashSize * slot; + } + + const unsigned char *operator [] (Slot slot) const + { + assert(slot >= int(-nSpecialSlots) && slot < int(nCodeSlots)); + return at(hashOffset) + hashSize * slot; + } + + // + // The main page hash array can be "scattered" across the code file + // by specifying an array of Scatter elements, terminated with an + // element whose count field is zero. + // The scatter vector is optional; if absent, the hash array covers + // a single contiguous range of pages. CodeDirectory versions below + // supportsScatter never have scatter vectors (they lack the scatterOffset field). + // + struct Scatter { + Endian count; // number of pages; zero for sentinel (only) + Endian base; // first page number + Endian targetOffset; // byte offset in target + Endian spare; // reserved (must be zero) + }; + Scatter *scatterVector() // first scatter vector element (NULL if none) + { return (version >= supportsScatter && scatterOffset) ? at(scatterOffset) : NULL; } + const Scatter *scatterVector() const + { return (version >= supportsScatter && scatterOffset) ? at(scatterOffset) : NULL; } + +public: + bool validateSlot(const void *data, size_t size, Slot slot) const; // validate memory buffer against page slot + bool validateSlot(UnixPlusPlus::FileDesc fd, size_t size, Slot slot) const; // read and validate file + bool slotIsPresent(Slot slot) const; + + class Builder; + +public: + static DynamicHash *hashFor(HashAlgorithm hashType); // create a DynamicHash subclass for (hashType) digests + DynamicHash *getHash() const { return hashFor(this->hashType); } // make one for me + +protected: + static size_t generateHash(DynamicHash *hash, UnixPlusPlus::FileDesc fd, Hashing::Byte *digest, size_t limit = 0); // hash to count or end of file + static size_t generateHash(DynamicHash *hash, const void *data, size_t length, Hashing::Byte *digest); // hash data buffer + +public: + // + // Information about SpecialSlots. + // This specifies meta-data about slots themselves; + // it does not work with the contents of hash slots. + // + static const char *canonicalSlotName(SpecialSlot slot); + static unsigned slotAttributes(SpecialSlot slot); + IFDEBUG(static const char * const debugSlotName[]); +}; + + +} // CodeSigning +} // Security + + +#endif //_H_CODEDIRECTORY diff --git a/libsecurity_codesigning/lib/cs.cpp b/libsecurity_codesigning/lib/cs.cpp new file mode 100644 index 00000000..825e3356 --- /dev/null +++ b/libsecurity_codesigning/lib/cs.cpp @@ -0,0 +1,63 @@ +/* + * 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@ + */ + +// +// cs.h - code signing core header +// +#include "cs.h" +#include + +namespace Security { +namespace CodeSigning { + + +ModuleNexus gCFObjects; + +CFObjects::CFObjects() + : Code("SecCode"), + StaticCode("SecStaticCode"), + Requirement("SecRequirements"), + CodeSigner("SecCodeSigner") +{ +} + + +OSStatus dbError(const SQLite3::Error &err) +{ + switch (err.error) { + case SQLITE_PERM: + case SQLITE_READONLY: + case SQLITE_AUTH: + return errSecCSSigDBDenied; + case SQLITE_CANTOPEN: + case SQLITE_EMPTY: + case SQLITE_NOTADB: + return errSecCSSigDBAccess; + default: + return SecKeychainErrFromOSStatus(err.osStatus()); + } +} + + +} // CodeSigning +} // Security diff --git a/libsecurity_codesigning/lib/cs.h b/libsecurity_codesigning/lib/cs.h new file mode 100644 index 00000000..1cd9306b --- /dev/null +++ b/libsecurity_codesigning/lib/cs.h @@ -0,0 +1,184 @@ +/* + * 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@ + */ + +// +// cs.h - code signing core header +// +#ifndef _H_CS +#define _H_CS + +#include "cserror.h" +#include "codesigning_dtrace.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace Security { +namespace CodeSigning { + + +// +// API per-thread globals +// +struct PerThread { + SecCSFlags flags; // flags of pending API call +}; + + +// +// API globals +// +struct CFObjects { + CFObjects(); + CFClass Code; + CFClass StaticCode; + CFClass Requirement; + CFClass CodeSigner; + + ThreadNexus perThread; + + SecCSFlags &flags() { return perThread().flags; } +}; + +extern ModuleNexus gCFObjects; + +static inline SecCSFlags apiFlags() { return gCFObjects().flags(); } + +OSStatus dbError(const SQLite3::Error &err); + + +// +// Code Signing API brackets +// +#define BEGIN_CSAPI \ + try { + +#define END_CSAPI \ + } \ + catch (const UnixError &err) { \ + switch (err.error) { \ + case ENOEXEC: return errSecCSBadObjectFormat; \ + default: return err.osStatus(); \ + }} \ + catch (const MacOSError &err) { return err.osStatus(); } \ + catch (const SQLite3::Error &err) { return dbError(err); } \ + catch (const CommonError &err) { return SecKeychainErrFromOSStatus(err.osStatus()); } \ + catch (const std::bad_alloc &) { return memFullErr; } \ + catch (...) { return errSecCSInternalError; } \ + return noErr; + +#define END_CSAPI_ERRORS \ + } \ + catch (const CSError &err) { return err.cfError(errors); } \ + catch (const UnixError &err) { \ + switch (err.error) { \ + case ENOEXEC: return CSError::cfError(errors, errSecCSBadObjectFormat); \ + default: return CSError::cfError(errors, err.osStatus()); \ + }} \ + catch (const MacOSError &err) { return CSError::cfError(errors, err.osStatus()); } \ + catch (const SQLite3::Error &err) { return CSError::cfError(errors, dbError(err)); } \ + catch (const CommonError &err) { return CSError::cfError(errors, SecKeychainErrFromOSStatus(err.osStatus())); } \ + catch (const std::bad_alloc &) { return CSError::cfError(errors, memFullErr); } \ + catch (...) { return CSError::cfError(errors, errSecCSInternalError); } \ + return noErr; + +#define END_CSAPI1(bad) } catch (...) { return bad; } + + +#define END_CSAPI_ERRORS1(bad) \ + } \ + catch (const CSError &err) { err.cfError(errors); } \ + catch (const UnixError &err) { \ + switch (err.error) { \ + case ENOEXEC: CSError::cfError(errors, errSecCSBadObjectFormat); \ + default: CSError::cfError(errors, err.osStatus()); \ + }} \ + catch (const MacOSError &err) { CSError::cfError(errors, err.osStatus()); } \ + catch (const SQLite3::Error &err) { CSError::cfError(errors, dbError(err)); } \ + catch (const CommonError &err) { CSError::cfError(errors, SecKeychainErrFromOSStatus(err.osStatus())); } \ + catch (const std::bad_alloc &) { CSError::cfError(errors, memFullErr); } \ + catch (...) { CSError::cfError(errors, errSecCSInternalError); } \ + return bad; + + +// +// A version of CodeSigning::Required +// +template +static inline T &Required(T *ptr) +{ + if (ptr == NULL) + MacOSError::throwMe(errSecCSObjectRequired); + return *ptr; +} + +static inline void Required(const void *ptr) +{ + if (ptr == NULL) + MacOSError::throwMe(errSecCSObjectRequired); +} + + +// +// Check flags against a validity mask +// +static inline void checkFlags(SecCSFlags flags, SecCSFlags acceptable = 0) +{ + if (flags & ~acceptable) + MacOSError::throwMe(errSecCSInvalidFlags); + gCFObjects().flags() = flags; +} + + +// +// DTrace USDT function bracket. +// Use like this: +// DTRACK(PROVIDER_PROBE_PREFIX, arguments-after-this); +// which will call +// PROVIDER_PROBE_PREFIX_START(this, arguments-after-this) +// and +// PROVIDER_PROBE_PREFIX_END(this) +// +#define DTRACK(_prefix, _obj, _args...) \ + if (_prefix ## _START_ENABLED()) _prefix ## _START((_obj), ## _args); \ + struct _DTFrame ## _prefix { void *me; \ + _DTFrame ## _prefix(void *m) : me(m) { } \ + ~_DTFrame ## _prefix() { _prefix ## _END(me); } \ + } _dtframe##_prefix((_obj)); + + +} // CodeSigning +} // Security + +#endif //_H_CS diff --git a/libsecurity_codesigning/lib/cscdefs.c b/libsecurity_codesigning/lib/cscdefs.c new file mode 100644 index 00000000..401c1a6c --- /dev/null +++ b/libsecurity_codesigning/lib/cscdefs.c @@ -0,0 +1,4 @@ +#include +#include +#include +#include "cscdefs.h" diff --git a/libsecurity_codesigning/lib/cscdefs.h b/libsecurity_codesigning/lib/cscdefs.h new file mode 100644 index 00000000..4c3b9985 --- /dev/null +++ b/libsecurity_codesigning/lib/cscdefs.h @@ -0,0 +1,89 @@ +/* + * 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; + + +/* + * Sample code to locate the CodeDirectory from an embedded signature blob + */ +static inline const CS_CodeDirectory *findCodeDirectory(const CS_SuperBlob *embedded) +{ + if (embedded && ntohl(embedded->magic) == CSMAGIC_EMBEDDED_SIGNATURE) { + const CS_BlobIndex *limit = &embedded->index[ntohl(embedded->count)]; + const CS_BlobIndex *p; + for (p = embedded->index; p < limit; ++p) + if (ntohl(p->type) == CSSLOT_CODEDIRECTORY) { + const unsigned char *base = (const unsigned char *)embedded; + const CS_CodeDirectory *cd = (const CS_CodeDirectory *)(base + ntohl(p->offset)); + if (cd->magic == CSMAGIC_CODEDIRECTORY) + return cd; + else + break; + } + } + // not found + return NULL; +} + + +/* + * Locating a page hash + */ +static inline const unsigned char *hashes(const CS_CodeDirectory *cd, unsigned page) +{ + const unsigned char *base = (const unsigned char *)cd; + assert(page < ntohl(cd->nCodeSlots)); + + // "20" below is the size of a SHA-1 hash. There's got to be a constant for that + // where you get your SHA-1 functions from. This can also be had as cd->hashSize + // (but the constant is marginally faster, I suppose) + return base + ntohl(cd->hashOffset) + page * 20; +} diff --git a/libsecurity_codesigning/lib/csdatabase.cpp b/libsecurity_codesigning/lib/csdatabase.cpp new file mode 100644 index 00000000..5772ee6e --- /dev/null +++ b/libsecurity_codesigning/lib/csdatabase.cpp @@ -0,0 +1,175 @@ +/* + * Copyright (c) 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@ + */ + +// +// csdb - system-supported Code Signing related database interfaces +// +#include "csdatabase.h" +#include "detachedrep.h" + +namespace Security { +namespace CodeSigning { + +using namespace SQLite; + + +// +// The one and only SignatureDatabase object. +// It auto-adapts to readonly vs. writable use. +// +ModuleNexus signatureDatabase; +ModuleNexus signatureDatabaseWriter; + + +// +// Default path to the signature database. +// +const char SignatureDatabase::defaultPath[] = "/var/db/DetachedSignatures"; + + +// +// Creation commands to initialize the system database. +// +const char schema[] = "\ + create table if not exists code ( \n\ + id integer primary key on conflict replace autoincrement not null, \n\ + global integer null references global (id), \n\ + identifier text not null, \n\ + architecture integer, \n\ + identification blob not null unique on conflict replace, \n\ + signature blob not null, \n\ + created text default current_timestamp \n\ + ); \n\ + create index if not exists identifier_index on code (identifier); \n\ + create index if not exists architecture_index on code (architecture); \n\ + create index if not exists id_index on code (identification); \n\ + \n\ + create table if not exists global ( \n\ + id integer primary key on conflict replace autoincrement not null, \n\ + sign_location text not null, \n\ + signature blob null \n\ + ); \n\ + create index if not exists location_index on global (sign_location); \n\ +"; + + + +// +// Open the database (creating it if necessary and possible). +// Note that this isn't creating the schema; we do that on first write. +// +SignatureDatabase::SignatureDatabase(const char *path, int flags) + : SQLite::Database(path, flags) +{ +} + +SignatureDatabase::~SignatureDatabase() +{ /* virtual */ } + + +// +// Consult the database to find code by identification blob. +// Return the signature and (optional) global data blobs. +// +FilterRep *SignatureDatabase::findCode(DiskRep *rep) +{ + if (CFRef identification = rep->identification()) + if (!this->empty()) { + SQLite::Statement query(*this, + "select code.signature, global.signature from code, global \ + where code.identification = ?1 and code.global = global.id;"); + query.bind(1) = identification.get(); + if (query.nextRow()) + return new DetachedRep(query[0].data(), query[1].data(), rep, "system"); + } + + // no joy + return NULL; +} + + +// +// Given a unified detached signature blob, store its data in the database. +// This writes exactly one Global record, plus one Code record per architecture +// (where non-architectural code is treated as single-architecture). +// +void SignatureDatabaseWriter::storeCode(const BlobCore *sig, const char *location) +{ + Transaction xa(*this, Transaction::exclusive); // lock out everyone + if (this->empty()) + this->execute(schema); // initialize schema + if (const EmbeddedSignatureBlob *esig = EmbeddedSignatureBlob::specific(sig)) { // architecture-less + int64 globid = insertGlobal(location, NULL); + insertCode(globid, 0, esig); + xa.commit(); + return; + } else if (const DetachedSignatureBlob *dsblob = DetachedSignatureBlob::specific(sig)) { + int64 globid = insertGlobal(location, dsblob->find(0)); + unsigned count = dsblob->count(); + for (unsigned n = 0; n < count; n++) + if (uint32_t arch = dsblob->type(n)) + insertCode(globid, arch, EmbeddedSignatureBlob::specific(dsblob->blob(n))); + xa.commit(); + return; + } + + MacOSError::throwMe(errSecCSSignatureInvalid); + +} + +int64 SignatureDatabaseWriter::insertGlobal(const char *location, const BlobCore *blob) +{ + Statement insert(*this, "insert into global (sign_location, signature) values (?1, ?2);"); + insert.bind(1) = location; + if (blob) + insert.bind(2).blob(blob, blob->length(), true); + insert(); + return lastInsert(); +} + +void SignatureDatabaseWriter::insertCode(int64 globid, int arch, const EmbeddedSignatureBlob *sig) +{ + // retrieve binary identifier (was added by signer) + const BlobWrapper *ident = BlobWrapper::specific(sig->find(cdIdentificationSlot)); + assert(ident); + + // extract CodeDirectory to get some information from it + const CodeDirectory *cd = CodeDirectory::specific(sig->find(cdCodeDirectorySlot)); + assert(cd); + + // write the record + Statement insert(*this, + "insert into code (global, identifier, architecture, identification, signature) values (?1, ?2, ?3, ?4, ?5);"); + insert.bind(1) = globid; + insert.bind(2) = cd->identifier(); + if (arch) + insert.bind(3) = arch; + insert.bind(4).blob(ident->data(), ident->length(), true); + insert.bind(5).blob(sig, sig->length(), true); + insert(); +} + + + +} // end namespace CodeSigning +} // end namespace Security diff --git a/libsecurity_codesigning/lib/csdatabase.h b/libsecurity_codesigning/lib/csdatabase.h new file mode 100644 index 00000000..95f8e1b1 --- /dev/null +++ b/libsecurity_codesigning/lib/csdatabase.h @@ -0,0 +1,78 @@ +/* + * 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@ + */ + +// +// csdb - system-supported Code Signing related database interfaces +// +#ifndef _H_CSDATABASE +#define _H_CSDATABASE + +#include "diskrep.h" +#include "sigblob.h" +#include +#include +#include +#include + + +namespace Security { +namespace CodeSigning { + +namespace SQLite = SQLite3; + + +class SignatureDatabase : public SQLite::Database { +public: + SignatureDatabase(const char *path = defaultPath, + int flags = SQLITE_OPEN_READONLY); + virtual ~SignatureDatabase(); + + FilterRep *findCode(DiskRep *rep); + +public: + static const char defaultPath[]; +}; + + +class SignatureDatabaseWriter : public SignatureDatabase { +public: + SignatureDatabaseWriter(const char *path = defaultPath, + int flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE) + : SignatureDatabase(path, flags) { } + + void storeCode(const BlobCore *sig, const char *location); + +private: + SQLite::int64 insertGlobal(const char *location, const BlobCore *blob); + void insertCode(SQLite::int64 globid, int arch, const EmbeddedSignatureBlob *sig); +}; + + +extern ModuleNexus signatureDatabase; +extern ModuleNexus signatureDatabaseWriter; + + +} // end namespace CodeSigning +} // end namespace Security + +#endif // !_H_CSDATABASE diff --git a/libsecurity_codesigning/lib/cserror.cpp b/libsecurity_codesigning/lib/cserror.cpp new file mode 100644 index 00000000..16732056 --- /dev/null +++ b/libsecurity_codesigning/lib/cserror.cpp @@ -0,0 +1,88 @@ +/* + * 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@ + */ + +// +// cserror.h - extended-diagnostics Code Signing errors +// +#include "cs.h" +#include + +namespace Security { +namespace CodeSigning { + + +// +// We need a nothrow destructor +// +CSError::~CSError() throw () +{ } + + +// +// Create and throw various forms of CSError +// +void CSError::throwMe(OSStatus rc) +{ + throw CSError(rc); +} + +void CSError::throwMe(OSStatus rc, CFDictionaryRef dict) +{ + throw CSError(rc, dict); +} + +void CSError::throwMe(OSStatus rc, CFStringRef key, CFTypeRef value) +{ + throw CSError(rc, cfmake("{%O=%O}", key, value)); +} + + +// +// Add a key/value pair to the dictionary +// +void CSError::augment(CFStringRef key, CFTypeRef value) +{ + mInfoDict.take(cfmake("{+%O,%O=%O}", mInfoDict.get(), key, value)); +} + + +// +// Convert exception-carried error information to CFError form +// +OSStatus CSError::cfError(CFErrorRef *errors) const +{ + if (errors) // errors argument was specified + *errors = CFErrorCreate(NULL, kCFErrorDomainOSStatus, this->osStatus(), this->infoDict()); + return this->osStatus(); +} + +OSStatus CSError::cfError(CFErrorRef *errors, OSStatus rc) +{ + if (errors) + *errors = CFErrorCreate(NULL, kCFErrorDomainOSStatus, rc, NULL); + return rc; +} + + +} // CodeSigning +} // Security diff --git a/libsecurity_codesigning/lib/cserror.h b/libsecurity_codesigning/lib/cserror.h new file mode 100644 index 00000000..d737f0f9 --- /dev/null +++ b/libsecurity_codesigning/lib/cserror.h @@ -0,0 +1,67 @@ +/* + * 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@ + */ + +// +// cserror.h - extended-diagnostics Code Signing errors +// +#ifndef _H_CSERRORS +#define _H_CSERRORS + +#include +#include + + +namespace Security { +namespace CodeSigning { + + +// +// Special tailored exceptions to transmit additional error information +// +class CSError : public MacOSError { +public: + CSError(OSStatus rc) : MacOSError(rc) { } + CSError(OSStatus rc, CFDictionaryRef dict) : MacOSError(rc), mInfoDict(dict) { } // takes dict + ~CSError() throw (); + + static void throwMe(OSStatus rc) __attribute__((noreturn)); + static void throwMe(OSStatus rc, CFDictionaryRef info) __attribute__ ((noreturn)); // takes dict + static void throwMe(OSStatus rc, CFStringRef key, CFTypeRef value) __attribute__((noreturn)); + + void augment(CFStringRef key, CFTypeRef value); + + CFDictionaryRef infoDict() const { return mInfoDict; } + +public: + OSStatus cfError(CFErrorRef *errors) const; + static OSStatus cfError(CFErrorRef *errors, OSStatus rc); + +private: + CFRef mInfoDict; +}; + + +} // CodeSigning +} // Security + +#endif //_H_CSERRORS diff --git a/libsecurity_codesigning/lib/csgeneric.cpp b/libsecurity_codesigning/lib/csgeneric.cpp new file mode 100644 index 00000000..c67d9467 --- /dev/null +++ b/libsecurity_codesigning/lib/csgeneric.cpp @@ -0,0 +1,218 @@ +/* + * Copyright (c) 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@ + */ + +// +// csgeneric - generic Code representative +// +#include "csgeneric.h" +#include "cs.h" +#include "StaticCode.h" +#include +#include + +namespace Security { +namespace CodeSigning { + +using MachPlusPlus::Port; + + +// +// Common call-out code for cshosting RPC service +// +#define CALL(host, name, args...) \ + OSStatus result; \ + if (cshosting_client_ ## name (host, mig_get_reply_port(), &result, args)) \ + MacOSError::throwMe(errSecCSNotAHost); \ + MacOSError::check(result); + + +// +// Construct a running process representation +// +GenericCode::GenericCode(SecCode *host, SecGuestRef guestRef) + : SecCode(host), mGuestRef(guestRef) +{ +} + + +// +// Identify a guest by attribute set, and return a new GenericCode representing it. +// This uses cshosting RPCs to ask the host (or its proxy). +// +SecCode *GenericCode::locateGuest(CFDictionaryRef attributes) +{ + if (Port host = hostingPort()) { + CFRef attrData; + void *attrPtr = NULL; size_t attrLength = 0; + if (attributes) { + attrData.take(CFPropertyListCreateXMLData(NULL, attributes)); + attrPtr = (void *)CFDataGetBytePtr(attrData); + attrLength = CFDataGetLength(attrData); + } + GuestChain guestPath; + mach_msg_type_number_t guestPathLength; + mach_port_t subport; + CALL(host, findGuest, guestRef(), attrPtr, attrLength, + &guestPath, &guestPathLength, &subport); + CODESIGN_GUEST_LOCATE_GENERIC(this, guestPath, guestPathLength, subport); + SecPointer code = this; + for (unsigned n = 0; n < guestPathLength; n++) + code = new GenericCode(code, guestPath[n]); + return code.yield(); + } else + return NULL; // not found, no error +} + + +// +// Identify a guest by returning its StaticCode and running CodeDirectory hash. +// This uses cshosting RPCs to ask the host (or its proxy). +// +SecStaticCode *GenericCode::identifyGuest(SecCode *guest, CFDataRef *cdhashOut) +{ + if (GenericCode *iguest = dynamic_cast(guest)) { + FilePathOut path; + CFRef cdhash; + CFDictionary attributes(errSecCSHostProtocolInvalidAttribute); + identifyGuest(iguest->guestRef(), path, cdhash.aref(), attributes.aref()); + DiskRep::Context ctx; + if (CFNumberRef architecture = attributes.get(kSecGuestAttributeArchitecture)) { + cpu_type_t cpu = cfNumber(architecture); + if (CFNumberRef subarchitecture = attributes.get(kSecGuestAttributeSubarchitecture)) + ctx.arch = Architecture(cpu, cfNumber(subarchitecture)); + else + ctx.arch = Architecture(cpu); + } + SecPointer code = new GenericStaticCode(DiskRep::bestGuess(path, &ctx)); + CODESIGN_GUEST_IDENTIFY_GENERIC(iguest, iguest->guestRef(), code); + if (cdhash) { + CODESIGN_GUEST_CDHASH_GENERIC(iguest, (void *)CFDataGetBytePtr(cdhash), CFDataGetLength(cdhash)); + *cdhashOut = cdhash.yield(); + } + return code.yield(); + } else + MacOSError::throwMe(errSecCSNotAHost); +} + +// helper to drive the identifyGuest hosting IPC and return results as CF objects +void GenericCode::identifyGuest(SecGuestRef guest, char *path, CFDataRef &cdhash, CFDictionaryRef &attributes) +{ + if (Port host = hostingPort()) { + HashDataOut hash; + uint32_t hashLength; + XMLBlobOut attr; + uint32_t attrLength; + CALL(host, identifyGuest, guest, path, hash, &hashLength, &attr, &attrLength); + if (hashLength) + cdhash = makeCFData(hash, hashLength); + if (attrLength) { + CFRef attrData = makeCFData(attr, attrLength); + attributes = makeCFDictionaryFrom(attrData); +#if ROSETTA_TEST_HACK + CFMutableDictionaryRef hattr = makeCFMutableDictionary(attributes); + CFDictionaryAddValue(hattr, kSecGuestAttributeArchitecture, CFTempNumber(CPU_TYPE_POWERPC)); + CFRelease(attributes); + attributes = hattr; +#endif + } + } else + MacOSError::throwMe(errSecCSNotAHost); +} + + +// +// Get the Code Signing Status Word for a Code. +// This uses cshosting RPCs to ask the host (or its proxy). +// +SecCodeStatus GenericCode::getGuestStatus(SecCode *guest) +{ + if (Port host = hostingPort()) { + uint32_t status; + CALL(host, guestStatus, safe_cast(guest)->guestRef(), &status); + return status; + } else + MacOSError::throwMe(errSecCSNotAHost); +} + + +// +// Status changes are transmitted through the cshosting RPCs. +// +void GenericCode::changeGuestStatus(SecCode *iguest, SecCodeStatusOperation operation, CFDictionaryRef arguments) +{ + if (/* GenericCode *guest = */dynamic_cast(iguest)) + switch (operation) { + case kSecCodeOperationNull: + break; + case kSecCodeOperationInvalidate: + case kSecCodeOperationSetHard: + case kSecCodeOperationSetKill: + MacOSError::throwMe(errSecCSUnimplemented); + break; + default: + MacOSError::throwMe(errSecCSUnimplemented); + } + else + MacOSError::throwMe(errSecCSNoSuchCode); +} + + +// +// Return the Hosting Port for this Code. +// May return MACH_PORT_NULL if the code is not a code host. +// Throws if we can't get the hosting port for some reason (and can't positively +// determine that there is none). +// +// Note that we do NOT cache negative outcomes. Being a host is a dynamic property, +// and this Code may not have commenced hosting operations yet. For non- (or not-yet-)hosts +// we simply return NULL. +// +Port GenericCode::hostingPort() +{ + if (!mHostingPort) { + if (staticCode()->codeDirectory()->flags & kSecCodeSignatureHost) { + mHostingPort = getHostingPort(); + CODESIGN_GUEST_HOSTINGPORT(this, mHostingPort); + } + } + return mHostingPort; +} + + +// +// A pure GenericHost has no idea where to get a hosting port from. +// This method must be overridden to get one. +// However, we do handle a contiguous chain of GenericCodes by deferring +// to our next-higher host for it. +// +mach_port_t GenericCode::getHostingPort() +{ + if (GenericCode *genericHost = dynamic_cast(host())) + return genericHost->getHostingPort(); + else + MacOSError::throwMe(errSecCSNotAHost); +} + + +} // CodeSigning +} // Security diff --git a/libsecurity_codesigning/lib/csgeneric.h b/libsecurity_codesigning/lib/csgeneric.h new file mode 100644 index 00000000..5b953a1c --- /dev/null +++ b/libsecurity_codesigning/lib/csgeneric.h @@ -0,0 +1,82 @@ +/* + * 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@ + */ + +// +// csgeneric - generic Code representative +// +#ifndef _H_CSGENERIC +#define _H_CSGENERIC + +#include "Code.h" +#include +#include +#include + +namespace Security { +namespace CodeSigning { + + +// +// A SecCode that represents "generic" code. +// Generic code is, well, generic. It doesn't have any real resources that define it, +// and so it's defined, de facto, by its host. The Code Signing subsystem has no special +// knowledge as to its nature, and so it just asks the host about everything. The asking +// is done via the cshosting Mach RPC protocol, which can be implemented by hosts in whichever +// way they find reasonable. This code doesn't care, as long as someone is answering. +// +// It is all right to subclass GenericCode to inherit access to the cshosting protocol. +// +class GenericCode : public SecCode { +public: + GenericCode(SecCode *host, SecGuestRef guestRef = kSecNoGuest); + + SecCode *locateGuest(CFDictionaryRef attributes); + SecStaticCode *identifyGuest(SecCode *guest, CFDataRef *cdhash); + SecCodeStatus getGuestStatus(SecCode *guest); + void changeGuestStatus(SecCode *guest, SecCodeStatusOperation operation, CFDictionaryRef arguments); + + SecGuestRef guestRef() const { return mGuestRef; } + +protected: + MachPlusPlus::Port hostingPort(); + virtual mach_port_t getHostingPort(); + +private: + void identifyGuest(SecGuestRef guest, char *path, CFDataRef &cdhash, CFDictionaryRef &attributes); + +private: + MachPlusPlus::Port mHostingPort; // cached hosting port for this Code + SecGuestRef mGuestRef; // guest reference +}; + + +// +// We don't need a GenericCode variant of SecStaticCode +// +typedef SecStaticCode GenericStaticCode; + + +} // end namespace CodeSigning +} // end namespace Security + +#endif // !_H_CSGENERIC diff --git a/libsecurity_codesigning/lib/cskernel.cpp b/libsecurity_codesigning/lib/cskernel.cpp new file mode 100644 index 00000000..9821465d --- /dev/null +++ b/libsecurity_codesigning/lib/cskernel.cpp @@ -0,0 +1,195 @@ +/* + * Copyright (c) 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@ + */ + +// +// cskernel - Kernel implementation of the Code Signing Host Interface. +// +// The kernel host currently supports only UNIX processes as guests. +// It tracks then by their pid. Perhaps one day we'll get a more stable +// means of tracking processes that doesn't involve reusing identifiers. +// +// The kernel host could represent non-process guests one day. One candidate +// are Kernel Extensions. +// +#include "cskernel.h" +#include "csprocess.h" +#include "kerneldiskrep.h" +#include "machorep.h" +#include +#include +#include // MAXPATHLEN + +namespace Security { +namespace CodeSigning { + + +// +// The running-kernel singletons +// +ModuleNexus KernelCode::globals; + +KernelCode::Globals::Globals() +{ + code = new KernelCode; + staticCode = new KernelStaticCode; +} + +KernelCode::KernelCode() + : SecCode(NULL) +{ +} + +KernelStaticCode::KernelStaticCode() + : SecStaticCode(new KernelDiskRep()) +{ +} + + +// +// Identify our guests (UNIX processes) by attribute. +// The only supported lookup attribute is currently the pid. (We could support +// task ports, but those can easily be mapped to pids.) +// Note that we don't actually validate the pid here; if it's invalid, we'll notice +// when we try to ask the kernel about it later. +// +SecCode *KernelCode::locateGuest(CFDictionaryRef attributes) +{ + if (CFTypeRef attr = CFDictionaryGetValue(attributes, kSecGuestAttributePid)) { + if (CFDictionaryGetCount(attributes) != 1) + MacOSError::throwMe(errSecCSUnsupportedGuestAttributes); // had more + if (CFGetTypeID(attr) == CFNumberGetTypeID()) + return (new ProcessCode(cfNumber(CFNumberRef(attr))))->retain(); + MacOSError::throwMe(errSecCSInvalidAttributeValues); + } else + MacOSError::throwMe(errSecCSUnsupportedGuestAttributes); +} + + +// +// We map guests to disk by calling a kernel service. +// It is here that we verify that our user-space concept of the code identity +// matches the kernel's idea (to defeat just-in-time switching attacks). +// +SecStaticCode *KernelCode::identifyGuest(SecCode *iguest, CFDataRef *cdhash) +{ + if (ProcessCode *guest = dynamic_cast(iguest)) { + char path[2 * MAXPATHLEN]; // reasonable upper limit + if (::proc_pidpath(guest->pid(), path, sizeof(path))) { + off_t offset; + csops(guest, CS_OPS_PIDOFFSET, &offset, sizeof(offset)); + SecPointer code = new ProcessStaticCode(DiskRep::bestGuess(path, offset)); + CODESIGN_GUEST_IDENTIFY_PROCESS(guest, guest->pid(), code); + if (cdhash) { + SHA1::Digest kernelHash; + if (::csops(guest->pid(), CS_OPS_CDHASH, kernelHash, sizeof(kernelHash)) == -1) + switch (errno) { + case EBADEXEC: // means "no CodeDirectory hash for this program" + *cdhash = NULL; + break; + case ESRCH: + MacOSError::throwMe(errSecCSNoSuchCode); + default: + UnixError::throwMe(); + } + else // succeeded + *cdhash = makeCFData(kernelHash, sizeof(kernelHash)); + CODESIGN_GUEST_CDHASH_PROCESS(guest, kernelHash, sizeof(kernelHash)); + } + return code.yield(); + } else + UnixError::throwMe(); + } + MacOSError::throwMe(errSecCSNoSuchCode); +} + + +// +// We obtain the guest's status by asking the kernel +// +SecCodeStatus KernelCode::getGuestStatus(SecCode *iguest) +{ + if (ProcessCode *guest = dynamic_cast(iguest)) { + uint32_t pFlags; + csops(guest, CS_OPS_STATUS, &pFlags); + secdebug("kcode", "guest %p(%d) kernel status 0x%x", guest, guest->pid(), pFlags); + return pFlags; + } else + MacOSError::throwMe(errSecCSNoSuchCode); +} + + +// +// We tell the kernel to make status changes +// +void KernelCode::changeGuestStatus(SecCode *iguest, SecCodeStatusOperation operation, CFDictionaryRef arguments) +{ + if (ProcessCode *guest = dynamic_cast(iguest)) + switch (operation) { + case kSecCodeOperationNull: + break; + case kSecCodeOperationInvalidate: + csops(guest, CS_OPS_MARKINVALID); + break; + case kSecCodeOperationSetHard: + csops(guest, CS_OPS_MARKHARD); + break; + case kSecCodeOperationSetKill: + csops(guest, CS_OPS_MARKKILL); + break; + default: + MacOSError::throwMe(errSecCSUnimplemented); + } + else + MacOSError::throwMe(errSecCSNoSuchCode); +} + + +// +// The StaticCode for the running kernel is explicit. +// We can't ask our own host for it, naturally. +// +void KernelCode::identify() +{ + mStaticCode.take(globals().staticCode->retain()); + // the kernel isn't currently signed, so we don't get a cdHash for it +} + + +// +// Interface to kernel csops() system call. +// +void KernelCode::csops(ProcessCode *proc, unsigned int op, void *addr, size_t length) +{ + if (::csops(proc->pid(), op, addr, length) == -1) { + switch (errno) { + case ESRCH: + MacOSError::throwMe(errSecCSNoSuchCode); + default: + UnixError::throwMe(); + } + } +} + + +} // CodeSigning +} // Security diff --git a/libsecurity_codesigning/lib/cskernel.h b/libsecurity_codesigning/lib/cskernel.h new file mode 100644 index 00000000..c50598ee --- /dev/null +++ b/libsecurity_codesigning/lib/cskernel.h @@ -0,0 +1,86 @@ +/* + * 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@ + */ + +// +// cskernel - Kernel implementation of the Code Signing Host Interface +// +#ifndef _H_CSKERNEL +#define _H_CSKERNEL + +#include "Code.h" +#include "StaticCode.h" +#include + +namespace Security { +namespace CodeSigning { + + +class ProcessCode; + + +// +// The nominal StaticCode representing the kernel on disk. +// This is barely used, since we don't validate the kernel (it's the root of trust) +// and we don't activate new kernels at runtime. +// +class KernelStaticCode : public SecStaticCode { +public: + KernelStaticCode(); + +private: +}; + + +// +// A SecCode that represents the system's running kernel. +// We usually only have one of those in the system at one time. :-) +// +class KernelCode : public SecCode { +public: + KernelCode(); + + SecCode *locateGuest(CFDictionaryRef attributes); + SecStaticCode *identifyGuest(SecCode *guest, CFDataRef *cdhash); + SecCodeStatus getGuestStatus(SecCode *guest); + void changeGuestStatus(SecCode *guest, SecCodeStatusOperation operation, CFDictionaryRef arguments); + + static KernelCode *active() { return globals().code; } + +public: + struct Globals { + Globals(); + SecPointer code; + SecPointer staticCode; + }; + static ModuleNexus globals; + +protected: + void identify(); + void csops(ProcessCode *proc, unsigned int op, void *addr = NULL, size_t length = 0); +}; + + +} // end namespace CodeSigning +} // end namespace Security + +#endif // !_H_CSKERNEL diff --git a/libsecurity_codesigning/lib/csprocess.cpp b/libsecurity_codesigning/lib/csprocess.cpp new file mode 100644 index 00000000..0d14392a --- /dev/null +++ b/libsecurity_codesigning/lib/csprocess.cpp @@ -0,0 +1,51 @@ +/* + * 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@ + */ + +// +// csprocess - UNIX process implementation of the Code Signing Host Interface +// +#include "csprocess.h" +#include "cskernel.h" +#include + +namespace Security { +namespace CodeSigning { + + +// +// Construct a running process representation +// +ProcessCode::ProcessCode(pid_t pid) + : GenericCode(KernelCode::active()), mPid(pid) +{ +} + + +mach_port_t ProcessCode::getHostingPort() +{ + return SecurityServer::ClientSession().hostingPort(pid()); +} + + +} // CodeSigning +} // Security diff --git a/libsecurity_codesigning/lib/csprocess.h b/libsecurity_codesigning/lib/csprocess.h new file mode 100644 index 00000000..7fd6efc7 --- /dev/null +++ b/libsecurity_codesigning/lib/csprocess.h @@ -0,0 +1,66 @@ +/* + * 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@ + */ + +// +// csprocess - UNIX process implementation of the Code Signing Host Interface +// +#ifndef _H_CSPROCESS +#define _H_CSPROCESS + +#include "csgeneric.h" +#include + +namespace Security { +namespace CodeSigning { + + +// +// A SecCode that represents a running UNIX process. +// Processes are identified by pid. +// +// ProcessCode inherits GenericCode's access to the cshosting Mach protocol to +// deal with guests. +// +class ProcessCode : public GenericCode { +public: + ProcessCode(pid_t pid); + + pid_t pid() const { return mPid; } + + mach_port_t getHostingPort(); + +private: + pid_t mPid; +}; + + +// +// We don't need a GenericCode variant of ProcessCode +// +typedef SecStaticCode ProcessStaticCode; + + +} // end namespace CodeSigning +} // end namespace Security + +#endif // !_H_CSPROCESS diff --git a/libsecurity_codesigning/lib/csutilities.cpp b/libsecurity_codesigning/lib/csutilities.cpp new file mode 100644 index 00000000..6ac5db8f --- /dev/null +++ b/libsecurity_codesigning/lib/csutilities.cpp @@ -0,0 +1,188 @@ +/* + * 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@ + */ + +// +// csutilities - miscellaneous utilities for the code signing implementation +// +#include "csutilities.h" +#include +#include +#include +#include + +namespace Security { +namespace CodeSigning { + + +// +// Calculate the canonical hash of a certificate, given its raw (DER) data. +// +void hashOfCertificate(const void *certData, size_t certLength, SHA1::Digest digest) +{ + SHA1 hasher; + hasher(certData, certLength); + hasher.finish(digest); +} + + +// +// Ditto, given a SecCertificateRef +// +void hashOfCertificate(SecCertificateRef cert, SHA1::Digest digest) +{ + assert(cert); + CSSM_DATA certData; + MacOSError::check(SecCertificateGetData(cert, &certData)); + hashOfCertificate(certData.Data, certData.Length, digest); +} + + +// +// Check to see if a certificate contains a particular field, by OID. This works for extensions, +// even ones not recognized by the local CL. It does not return any value, only presence. +// +bool certificateHasField(SecCertificateRef cert, const CSSM_OID &oid) +{ + assert(cert); + CSSM_DATA *value; + switch (OSStatus rc = SecCertificateCopyFirstFieldValue(cert, &oid, &value)) { + case noErr: + MacOSError::check(SecCertificateReleaseFirstFieldValue(cert, &oid, value)); + return true; // extension found by oid + case errSecUnknownTag: + break; // oid not recognized by CL - continue below + default: + MacOSError::throwMe(rc); // error: fail + } + + // check the CL's bag of unrecognized extensions + CSSM_DATA **values; + bool found = false; + if (SecCertificateCopyFieldValues(cert, &CSSMOID_X509V3CertificateExtensionCStruct, &values)) + return false; // no unrecognized extensions - no match + if (values) + for (CSSM_DATA **p = values; *p; p++) { + const CSSM_X509_EXTENSION *ext = (const CSSM_X509_EXTENSION *)(*p)->Data; + if (oid == ext->extnId) { + found = true; + break; + } + } + MacOSError::check(SecCertificateReleaseFieldValues(cert, &CSSMOID_X509V3CertificateExtensionCStruct, values)); + return found; +} + + +// +// Retrieve X.509 policy extension OIDs, if any. +// This currently ignores policy qualifiers. +// +bool certificateHasPolicy(SecCertificateRef cert, const CSSM_OID &policyOid) +{ + bool matched = false; + assert(cert); + CSSM_DATA *data; + if (OSStatus rc = SecCertificateCopyFirstFieldValue(cert, &CSSMOID_CertificatePolicies, &data)) + MacOSError::throwMe(rc); + if (data && data->Data && data->Length == sizeof(CSSM_X509_EXTENSION)) { + const CSSM_X509_EXTENSION *ext = (const CSSM_X509_EXTENSION *)data->Data; + assert(ext->format == CSSM_X509_DATAFORMAT_PARSED); + const CE_CertPolicies *policies = (const CE_CertPolicies *)ext->value.parsedValue; + if (policies) + for (unsigned int n = 0; n < policies->numPolicies; n++) { + const CE_PolicyInformation &cp = policies->policies[n]; + if (cp.certPolicyId == policyOid) { + matched = true; + break; + } + } + } + SecCertificateReleaseFirstFieldValue(cert, &CSSMOID_PolicyConstraints, data); + return matched; +} + + +// +// Copyfile +// +Copyfile::Copyfile() +{ + if (!(mState = copyfile_state_alloc())) + UnixError::throwMe(); +} + +void Copyfile::set(uint32_t flag, const void *value) +{ + check(::copyfile_state_set(mState, flag, value)); +} + +void Copyfile::get(uint32_t flag, void *value) +{ + check(::copyfile_state_set(mState, flag, value)); +} + +void Copyfile::operator () (const char *src, const char *dst, copyfile_flags_t flags) +{ + check(::copyfile(src, dst, mState, flags)); +} + +void Copyfile::check(int rc) +{ + if (rc < 0) + UnixError::throwMe(); +} + + +// +// MessageTracer support +// +MessageTrace::MessageTrace(const char *domain, const char *signature) +{ + mAsl = asl_new(ASL_TYPE_MSG); + if (domain) + asl_set(mAsl, "com.apple.message.domain", domain); + if (signature) + asl_set(mAsl, "com.apple.message.signature", signature); +} + +void MessageTrace::add(const char *key, const char *format, ...) +{ + va_list args; + va_start(args, format); + char value[200]; + vsnprintf(value, sizeof(value), format, args); + va_end(args); + asl_set(mAsl, (string("com.apple.message.") + key).c_str(), value); +} + +void MessageTrace::send(const char *format, ...) +{ + va_list args; + va_start(args, format); + asl_vlog(NULL, mAsl, ASL_LEVEL_NOTICE, format, args); + va_end(args); +} + + +} // end namespace CodeSigning +} // end namespace Security diff --git a/libsecurity_codesigning/lib/csutilities.h b/libsecurity_codesigning/lib/csutilities.h new file mode 100644 index 00000000..10b33f80 --- /dev/null +++ b/libsecurity_codesigning/lib/csutilities.h @@ -0,0 +1,167 @@ +/* + * 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@ + */ + +// +// csutilities - miscellaneous utilities for the code signing implementation +// +// This is a collection of odds and ends that wouldn't fit anywhere else. +// The common theme is that the contents are otherwise naturally homeless. +// +#ifndef _H_CSUTILITIES +#define _H_CSUTILITIES + +#include +#include +#include +#include +#include +#include +#include + +namespace Security { +namespace CodeSigning { + + +// +// Calculate canonical hashes of certificate. +// This is simply defined as (always) the SHA1 hash of the DER. +// +void hashOfCertificate(const void *certData, size_t certLength, SHA1::Digest digest); +void hashOfCertificate(SecCertificateRef cert, SHA1::Digest digest); + + +// +// Calculate hashes of (a section of) a file. +// Starts at the current file position. +// Extends to end of file, or (if limit > 0) at most limit bytes. +// Returns number of bytes digested. +// +template +size_t hashFileData(const char *path, _Hash *hasher) +{ + UnixPlusPlus::AutoFileDesc fd(path); + return hashFileData(fd, hasher); +} + +template +size_t hashFileData(UnixPlusPlus::FileDesc fd, _Hash *hasher, size_t limit = 0) +{ + unsigned char buffer[4096]; + size_t total = 0; + for (;;) { + size_t size = sizeof(buffer); + if (limit && limit < size) + size = limit; + size_t got = fd.read(buffer, size); + total += got; + if (fd.atEnd()) + break; + hasher->update(buffer, got); + if (limit && (limit -= got) == 0) + break; + } + return total; +} + + +// +// Check to see if a certificate contains a particular field, by OID. This works for extensions, +// even ones not recognized by the local CL. It does not return any value, only presence. +// +bool certificateHasField(SecCertificateRef cert, const CSSM_OID &oid); +bool certificateHasPolicy(SecCertificateRef cert, const CSSM_OID &policyOid); + + +// +// Encapsulation of the copyfile(3) API. +// This is slated to go into utilities once stable. +// +class Copyfile { +public: + Copyfile(); + ~Copyfile() { copyfile_state_free(mState); } + + operator copyfile_state_t () const { return mState; } + + void set(uint32_t flag, const void *value); + void get(uint32_t flag, void *value); + + void operator () (const char *src, const char *dst, copyfile_flags_t flags); + +private: + void check(int rc); + +private: + copyfile_state_t mState; +}; + + +// +// MessageTracer support +// +class MessageTrace { +public: + MessageTrace(const char *domain, const char *signature); + void add(const char *key, const char *format, ...); + void send(const char *format, ...); + +private: + aslmsg mAsl; +}; + + +// +// A reliable uid set/reset bracket +// +class UidGuard { +public: + UidGuard() : mPrevious(-1) { } + UidGuard(uid_t uid) : mPrevious(-1) { seteuid(uid); } + ~UidGuard() + { + if (active()) + UnixError::check(::seteuid(mPrevious)); + } + + bool seteuid(uid_t uid) + { + if (uid == geteuid()) + return true; // no change, don't bother the kernel + if (!active()) + mPrevious = ::geteuid(); + return ::seteuid(uid) == 0; + } + + bool active() const { return mPrevious != uid_t(-1); } + operator bool () const { return active(); } + uid_t saved() const { assert(active()); return mPrevious; } + +private: + uid_t mPrevious; +}; + + +} // end namespace CodeSigning +} // end namespace Security + +#endif // !_H_CSUTILITIES diff --git a/libsecurity_codesigning/lib/detachedrep.cpp b/libsecurity_codesigning/lib/detachedrep.cpp new file mode 100644 index 00000000..348a8ed0 --- /dev/null +++ b/libsecurity_codesigning/lib/detachedrep.cpp @@ -0,0 +1,103 @@ +/* + * Copyright (c) 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@ + */ + +// +// detachedrep - prefix diskrep representing a detached signature stored in a file +// +#include "detachedrep.h" + + +namespace Security { +namespace CodeSigning { + + +// +// We construct a DetachedRep from the data blob of the detached signature +// and a reference of the original DiskRep we chain to. +// We accept an EmbeddedSignatureBlob (for a non-architected signature) +// or a DetachedSignatureBlob (for architected signatures) that is a SuperBlob +// of EmbeddedSignatureBlobs. +// +DetachedRep::DetachedRep(CFDataRef sig, DiskRep *orig, const std::string &source) + : FilterRep(orig), mSig(sig), mSource(source) +{ + const BlobCore *sigBlob = reinterpret_cast(CFDataGetBytePtr(sig)); + if (sigBlob->is()) { // architecture-less + if ((mArch = EmbeddedSignatureBlob::specific(sigBlob))) { + mGlobal = NULL; + CODESIGN_DISKREP_CREATE_DETACHED(this, orig, (char*)source.c_str(), NULL); + return; + } + } else if (sigBlob->is()) // architecture collection + if (const DetachedSignatureBlob *dsblob = DetachedSignatureBlob::specific(sigBlob)) + if (Universal *fat = orig->mainExecutableImage()) + if (const BlobCore *blob = dsblob->find(fat->bestNativeArch().cpuType())) + if ((mArch = EmbeddedSignatureBlob::specific(blob))) + if ((mGlobal = EmbeddedSignatureBlob::specific(dsblob->find(0)))) { + CODESIGN_DISKREP_CREATE_DETACHED(this, orig, (char*)source.c_str(), (void*)mGlobal); + return; + } + MacOSError::throwMe(errSecCSSignatureInvalid); +} + + +// +// Here's a version to construct a DetachedRep if we already have the right architecture +// and (optional) associated global blob. Just take them. +// +DetachedRep::DetachedRep(CFDataRef sig, CFDataRef gsig, DiskRep *orig, const std::string &source) + : FilterRep(orig), mSig(sig), mGSig(gsig), mSource(source) +{ + const BlobCore *sigBlob = reinterpret_cast(CFDataGetBytePtr(sig)); + mArch = EmbeddedSignatureBlob::specific(sigBlob); + if (!mArch) + MacOSError::throwMe(errSecCSSignatureInvalid); + if (gsig) { + const BlobCore *gsigBlob = reinterpret_cast(CFDataGetBytePtr(gsig)); + mGlobal = EmbeddedSignatureBlob::specific(gsigBlob); + if (!mGlobal) + MacOSError::throwMe(errSecCSSignatureInvalid); + } else + mGlobal = NULL; + CODESIGN_DISKREP_CREATE_DETACHED(this, orig, (char*)source.c_str(), (void*)mGlobal); +} + + +// +// We look up components by first checking for a per-architecture item, +// then for a global item in the detached signature, and finally falling +// back on the original DiskRep (for static components). +// +CFDataRef DetachedRep::component(CodeDirectory::SpecialSlot slot) +{ + if (CFDataRef result = mArch->component(slot)) + return result; + if (mGlobal) + if (CFDataRef result = mGlobal->component(slot)) + return result; + return this->base()->component(slot); +} + + +} // end namespace CodeSigning +} // end namespace Security diff --git a/libsecurity_codesigning/lib/detachedrep.h b/libsecurity_codesigning/lib/detachedrep.h new file mode 100644 index 00000000..9802b2e8 --- /dev/null +++ b/libsecurity_codesigning/lib/detachedrep.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 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@ + */ + +// +// detachedrep - prefix diskrep representing a detached signature stored in a file +// +#ifndef _H_DETACHEDREP +#define _H_DETACHEDREP + +#include "diskrep.h" +#include "sigblob.h" + +namespace Security { +namespace CodeSigning { + + +// +// We use a DetachedRep to interpose (filter) the genuine DiskRep representing +// the code on disk, *if* a detached signature was set on this object. In this +// situation, mRep will point to a (2 element) chain of DiskReps. +// +// This is a neat way of dealing with the (unusual) detached-signature case +// without disturbing things unduly. Consider DetachedDiskRep to be closely +// married to SecStaticCode; it's unlikely to work right if you use it elsewhere. +// +// Note that there's no *writing* code here. Writing detached signatures is handled +// specially in the signing code. +// +class DetachedRep : public FilterRep { +public: + DetachedRep(CFDataRef sig, DiskRep *orig, const std::string &source); // SuperBlob of all architectures + DetachedRep(CFDataRef sig, CFDataRef gsig, DiskRep *orig, const std::string &source); // one architecture + globals + + CFDataRef component(CodeDirectory::SpecialSlot slot); + + const std::string &source() const { return mSource; } + +private: + CFRef mSig, mGSig; + const EmbeddedSignatureBlob *mArch; // current architecture; points into mSignature + const EmbeddedSignatureBlob *mGlobal; // shared elements; points into mSignature + std::string mSource; // source description (readable) +}; + + +} // end namespace CodeSigning +} // end namespace Security + +#endif // !_H_DETACHEDREP diff --git a/libsecurity_codesigning/lib/diskrep.cpp b/libsecurity_codesigning/lib/diskrep.cpp new file mode 100644 index 00000000..395402c6 --- /dev/null +++ b/libsecurity_codesigning/lib/diskrep.cpp @@ -0,0 +1,298 @@ +/* + * Copyright (c) 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@ + */ + +// +// diskrep - disk representations of code +// +#include "diskrep.h" +#include +#include + +// specific disk representations created by the bestGuess() function +#include "filediskrep.h" +#include "bundlediskrep.h" +#include "cfmdiskrep.h" +#include "slcrep.h" + + +namespace Security { +namespace CodeSigning { + +using namespace UnixPlusPlus; + + +// +// Abstract features +// +DiskRep::DiskRep() +{ +} + +DiskRep::~DiskRep() +{ + CODESIGN_DISKREP_DESTROY(this); +} + + +// +// Normal DiskReps are their own base. +// +DiskRep *DiskRep::base() +{ + return this; +} + + +// +// By default, DiskReps are read-only. +// +DiskRep::Writer *DiskRep::writer() +{ + MacOSError::throwMe(errSecCSUnimplemented); +} + + +void DiskRep::Writer::addDiscretionary(CodeDirectory::Builder &) +{ + // do nothing +} + + +// +// Given a file system path, come up with the most likely correct +// disk representation for what's there. +// This is, strictly speaking, a heuristic that could be fooled - there's +// no fool-proof rule for figuring this out. But we'd expect this to work +// fine in ordinary use. If you happen to know what you're looking at +// (say, a bundle), then just create the suitable subclass of DiskRep directly. +// That's quite legal. +// The optional context argument can provide additional information that guides the guess. +// +DiskRep *DiskRep::bestGuess(const char *path, const Context *ctx) +{ + try { + if (!(ctx && ctx->fileOnly)) { + struct stat st; + if (::stat(path, &st)) + UnixError::throwMe(); + + // if it's a directory, assume it's a bundle + if ((st.st_mode & S_IFMT) == S_IFDIR) // directory - assume bundle + return new BundleDiskRep(path, ctx); + + // see if it's the main executable of a recognized bundle + if (CFRef pathURL = makeCFURL(path)) + if (CFRef bundle = _CFBundleCreateWithExecutableURLIfMightBeBundle(NULL, pathURL)) + return new BundleDiskRep(bundle, ctx); + } + + // try the various single-file representations + 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); + + // ultimate fallback - the generic file representation + return new FileDiskRep(path); + + } catch (const CommonError &error) { + switch (error.unixError()) { + case ENOENT: + MacOSError::throwMe(errSecCSStaticCodeNotFound); + default: + throw; + } + } +} + + +DiskRep *DiskRep::bestFileGuess(const char *path, const Context *ctx) +{ + Context dctx; + if (ctx) + dctx = *ctx; + dctx.fileOnly = true; + return bestGuess(path, &dctx); +} + + +// +// Given a main executable known to be a Mach-O binary, and an offset into +// the file of the actual architecture desired (of a Universal file), +// produce a suitable MachORep. +// This function does not consider non-MachO binaries. It does however handle +// bundles with Mach-O main executables correctly. +// +DiskRep *DiskRep::bestGuess(const char *path, size_t archOffset) +{ + try { + // is it the main executable of a bundle? + if (CFRef pathURL = makeCFURL(path)) + if (CFRef bundle = _CFBundleCreateWithExecutableURLIfMightBeBundle(NULL, pathURL)) { + Context ctx; ctx.offset = archOffset; + return new BundleDiskRep(bundle, &ctx); // ask bundle to make bundle-with-MachO-at-offset + } + // else, must be a Mach-O binary + Context ctx; ctx.offset = archOffset; + return new MachORep(path, &ctx); + } catch (const CommonError &error) { + switch (error.unixError()) { + case ENOENT: + MacOSError::throwMe(errSecCSStaticCodeNotFound); + default: + throw; + } + } +} + + +// +// Default behaviors of DiskRep +// +string DiskRep::resourcesRootPath() +{ + return ""; // has no resources directory +} + +void DiskRep::adjustResources(ResourceBuilder &builder) +{ + // do nothing +} + +Universal *DiskRep::mainExecutableImage() +{ + return NULL; // no Mach-O executable +} + +size_t DiskRep::signingBase() +{ + return 0; // whole file (start at beginning) +} + +CFArrayRef DiskRep::modifiedFiles() +{ + // by default, claim (just) the main executable modified + CFRef mainURL = makeCFURL(mainExecutablePath()); + return makeCFArray(1, mainURL.get()); +} + +void DiskRep::flush() +{ + // nothing cached +} + + +CFDictionaryRef DiskRep::defaultResourceRules(const SigningContext &) +{ + return NULL; // none +} + +const Requirements *DiskRep::defaultRequirements(const Architecture *, const SigningContext &) +{ + return NULL; // none +} + +size_t DiskRep::pageSize(const SigningContext &) +{ + return monolithicPageSize; // unpaged (monolithic) +} + + +// +// Given some string (usually a pathname), derive a suggested signing identifier +// in a canonical way (so there's some consistency). +// +// This is a heuristic. First we lop off any leading directories and final (non-numeric) +// extension. Then we walk backwards, eliminating numeric extensions except the first one. +// Thus, libfrotz7.3.5.dylib becomes libfrotz7, mumble.77.plugin becomes mumble.77, +// and rumble.rb becomes rumble. This isn't perfect, but it ought to handle 98%+ of +// the common varieties out there. Specify an explicit identifier for the oddballs. +// +// This is called by the various recommendedIdentifier() methods, who are +// free to modify or override it. +// +// Note: We use strchr("...") instead of is*() here because we do not +// wish to be influenced by locale settings. +// +std::string DiskRep::canonicalIdentifier(const std::string &name) +{ + string s = name; + string::size_type p; + + // lop off any directory prefixes + if ((p = s.rfind('/')) != string::npos) + s = s.substr(p+1); + + // remove any final extension (last dot) unless it's numeric + if ((p = s.rfind('.')) != string::npos && !strchr("0123456789", s[p+1])) + s = s.substr(0, p); + + // eat numeric suffixes except the first one; roughly: + // foo.2.3.4 => foo.2, foo2.3 => foo2, foo.9 => foo.9, foo => foo + if (strchr("0123456789.", s[0])) // starts with digit or . + return s; // ... so don't mess with it + p = s.size()-1; + // foo3.5^, foo.3.5^, foo3^, foo.3^, foo^ + while (strchr("0123456789.", s[p])) + p--; + // fo^o3.5, fo^o.3.5, fo^o3, fo^o.3, fo^o + p++; + // foo^3.5, foo^.3.5, foo^3, foo^.3, foo^ + if (s[p] == '.') + p++; + // foo^3.5, foo.^3.5, foo^3, foo.^3, foo^ + while (p < s.size() && strchr("0123456789", s[p])) + p++; + // foo3^.5, foo.3^.5, foo3^, foo.3^, foo^ + return s.substr(0, p); +} + + +// +// Writers +// +DiskRep::Writer::Writer(uint32_t attrs) + : mArch(CPU_TYPE_ANY), mAttributes(attrs) +{ +} + +DiskRep::Writer::~Writer() +{ /* virtual */ } + +uint32_t DiskRep::Writer::attributes() const +{ return mAttributes; } + +void DiskRep::Writer::flush() +{ /* do nothing */ } + +void DiskRep::Writer::remove() +{ + MacOSError::throwMe(errSecCSNotSupported); +} + + +} // end namespace CodeSigning +} // end namespace Security diff --git a/libsecurity_codesigning/lib/diskrep.h b/libsecurity_codesigning/lib/diskrep.h new file mode 100644 index 00000000..4a6beb5d --- /dev/null +++ b/libsecurity_codesigning/lib/diskrep.h @@ -0,0 +1,219 @@ +/* + * Copyright (c) 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@ + */ + +// +// diskrep - disk representations of code +// +#ifndef _H_DISKREP +#define _H_DISKREP + +#include "cs.h" +#include "codedirectory.h" +#include "cdbuilder.h" +#include "requirement.h" +#include "resources.h" +#include // for class Architecture +#include +#include +#include + +namespace Security { +namespace CodeSigning { + + +// +// DiskRep is an abstract interface to code somewhere located by +// a file system path. It presents the ability to read and write +// Code Signing-related information about such code without exposing +// the details of the storage locations or formats. +// +class DiskRep : public RefCount { +public: + class SigningContext; + +public: + DiskRep(); + virtual ~DiskRep(); + virtual DiskRep *base(); + virtual CFDataRef component(CodeDirectory::SpecialSlot slot) = 0; // fetch component + virtual CFDataRef identification() = 0; // binary lookup identifier + virtual std::string mainExecutablePath() = 0; // path to main executable + virtual CFURLRef canonicalPath() = 0; // path to whole code + virtual std::string resourcesRootPath(); // resource directory if any [none] + virtual void adjustResources(ResourceBuilder &builder); // adjust resource rule set [no change] + virtual Universal *mainExecutableImage(); // Mach-O image if Mach-O based [null] + virtual size_t signingBase(); // start offset of signed area in main executable [zero] + virtual size_t signingLimit() = 0; // size of signed area in main executable + virtual std::string format() = 0; // human-readable type string + virtual CFArrayRef modifiedFiles(); // list of files modified by signing [main execcutable only] + virtual UnixPlusPlus::FileDesc &fd() = 0; // a cached file descriptor for main executable file + virtual void flush(); // flush caches (refetch as needed) + + // default values for signing operations + virtual std::string recommendedIdentifier(const SigningContext &ctx) = 0; // default identifier + virtual CFDictionaryRef defaultResourceRules(const SigningContext &ctx); // default resource rules [none] + virtual const Requirements *defaultRequirements(const Architecture *arch, + const SigningContext &ctx); // default internal requirements [none] + virtual size_t pageSize(const SigningContext &ctx); // default main executable page size [infinite, i.e. no paging] + + bool mainExecutableIsMachO() { return mainExecutableImage() != NULL; } + + // shorthands + CFDataRef codeDirectory() { return component(cdCodeDirectorySlot); } + CFDataRef signature() { return component(cdSignatureSlot); } + +public: + class Writer; + virtual Writer *writer(); // Writer factory + +public: + // optional information that might be used to create a suitable DiskRep. All optional + struct Context { + Context() : arch(Architecture::none), version(NULL), offset(0), fileOnly(false), inMemory(NULL) { } + Architecture arch; // explicit architecture (choose amongst universal variants) + const char *version; // bundle version (string) + off_t offset; // explicit file offset + bool fileOnly; // only consider single-file representations (no bundles etc.) + const void *inMemory; // consider using in-memory copy at this address + }; + + static DiskRep *bestGuess(const char *path, const Context *ctx = NULL); // canonical heuristic, any path + static DiskRep *bestFileGuess(const char *path, const Context *ctx = NULL); // ctx (if any) + fileOnly + static DiskRep *bestGuess(const char *path, size_t archOffset); // Mach-O at given file offset only + + // versions using std::string paths (merely a convenience) + static DiskRep *bestGuess(const std::string &path, const Context *ctx = NULL) + { return bestGuess(path.c_str(), ctx); } + static DiskRep *bestGuess(const std::string &path, size_t archOffset) { return bestGuess(path.c_str(), archOffset); } + static DiskRep *bestFileGuess(const std::string &path, const Context *ctx = NULL) { return bestFileGuess(path.c_str(), ctx); } + +public: + // see DiskRep::Writer docs for why this is here + class SigningContext { + protected: + SigningContext() { } + + public: + virtual std::string sdkPath(const std::string &path) const = 0; + virtual bool isAdhoc() const = 0; + }; + +protected: + // canonically derive a suggested signing identifier from some string + static std::string canonicalIdentifier(const std::string &name); + +public: + static const size_t segmentedPageSize = 4096; // default page size for system-paged signatures + static const size_t monolithicPageSize = 0; // default page size for non-Mach-O executables +}; + + +// +// Write-access objects. +// At this layer they are quite abstract, carrying just the functionality needed +// for the signing machinery to place data wherever it should go. Each DiskRep subclass +// that supports writing signing data to a place inside the code needs to implement +// a subclass of Writer and return an instance in the DiskRep::writer() method when asked. +// +// The Writer class is subclassed interestingly by the Mach-O multi-architecture signing code, +// which is handled as a special case. This means that not all Writer subclass objects were made +// by DiskRep::writer, and it is unwise to assume so. +// +// Note that the methods that provide defaults for signing operations are in DiskRep rather +// than here. That's because writers abstract data *sending*, and are virtual on management +// of stored data, while DiskRep is virtual on the existing code object, which is where +// we get our defaults from. +// +class DiskRep::Writer : public RefCount { +public: + Writer(uint32_t attrs = 0); + virtual ~Writer(); + virtual void component(CodeDirectory::SpecialSlot slot, CFDataRef data) = 0; + virtual uint32_t attributes() const; + virtual void addDiscretionary(CodeDirectory::Builder &builder); + virtual void remove(); + virtual void flush(); + + bool attribute(uint32_t attr) const { return mAttributes & attr; } + + void signature(CFDataRef data) { component(cdSignatureSlot, data); } + void codeDirectory(const CodeDirectory *cd) + { component(cdCodeDirectorySlot, CFTempData(cd->data(), cd->length())); } + +private: + Architecture mArch; + uint32_t mAttributes; +}; + +// +// Writer attributes. Defaults should be off-bits. +// +enum { + writerLastResort = 0x0001, // prefers not to store attributes itself + writerNoGlobal = 0x0002, // has only per-architecture storage +}; + + +// +// A prefix DiskRep that filters (only) signature-dependent behavior and passes +// all code-dependent behavior off to an underlying (different) DiskRep. +// FilterRep subclasses are typically "stacked" on top of their base DiskRep, and +// then used in their place. +// +class FilterRep : public DiskRep { +public: + FilterRep(DiskRep *orig) : mOriginal(orig) { } + + DiskRep *base() { return mOriginal; } + + // things that look at signature components are filtered + CFDataRef component(CodeDirectory::SpecialSlot slot) = 0; + + // the rest of the virtual behavior devolves on the original DiskRep + CFDataRef identification() { return mOriginal->identification(); } + std::string mainExecutablePath() { return mOriginal->mainExecutablePath(); } + CFURLRef canonicalPath() { return mOriginal->canonicalPath(); } + std::string resourcesRootPath() { return mOriginal->resourcesRootPath(); } + void adjustResources(ResourceBuilder &builder) { return mOriginal->adjustResources(builder); } + Universal *mainExecutableImage() { return mOriginal->mainExecutableImage(); } + size_t signingBase() { return mOriginal->signingBase(); } + size_t signingLimit() { return mOriginal->signingLimit(); } + std::string format() { return mOriginal->format(); } + CFArrayRef modifiedFiles() { return mOriginal->modifiedFiles(); } + UnixPlusPlus::FileDesc &fd() { return mOriginal->fd(); } + void flush() { return mOriginal->flush(); } + + std::string recommendedIdentifier(const SigningContext &ctx) + { return mOriginal->recommendedIdentifier(ctx); } + CFDictionaryRef defaultResourceRules(const SigningContext &ctx) + { return mOriginal->defaultResourceRules(ctx); } + +private: + RefPointer mOriginal; // underlying representation +}; + + +} // end namespace CodeSigning +} // end namespace Security + +#endif // !_H_DISKREP diff --git a/libsecurity_codesigning/lib/drmaker.cpp b/libsecurity_codesigning/lib/drmaker.cpp new file mode 100644 index 00000000..98f887d8 --- /dev/null +++ b/libsecurity_codesigning/lib/drmaker.cpp @@ -0,0 +1,197 @@ +/* + * 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@ + */ + +// +// drmaker - create automatic Designated Requirements +// +#include "drmaker.h" +#include "csutilities.h" +#include +#include +//#include + +namespace Security { +namespace CodeSigning { + + +static const uint8_t adcSdkMarker[] = { APPLE_EXTENSION_OID, 2, 1 }; // iOS intermediate marker +const CSSM_DATA adcSdkMarkerOID = { sizeof(adcSdkMarker), (uint8_t *)adcSdkMarker }; + +static const uint8_t caspianSdkMarker[] = { APPLE_EXTENSION_OID, 2, 6 }; // Caspian intermediate marker +const CSSM_DATA devIdSdkMarkerOID = { sizeof(caspianSdkMarker), (uint8_t *)caspianSdkMarker }; +static const uint8_t caspianLeafMarker[] = { APPLE_EXTENSION_OID, 1, 13 }; // Caspian leaf certificate marker +const CSSM_DATA devIdLeafMarkerOID = { sizeof(caspianLeafMarker), (uint8_t *)caspianLeafMarker }; + + + +DRMaker::DRMaker(const Requirement::Context &context) + : ctx(context) +{ +} + +DRMaker::~DRMaker() +{ +} + + +// +// Generate the default (implicit) Designated Requirement for this StaticCode. +// This is a heuristic of sorts, and may change over time (for the better, we hope). +// +Requirement *DRMaker::make() +{ + // we can't make an explicit DR for a (proposed) ad-hoc signing because that requires the CodeDirectory (which we ain't got yet) + if (ctx.certCount() == 0) + return NULL; + + // always require the identifier + this->put(opAnd); + this->ident(ctx.identifier); + + SHA1::Digest anchorHash; + hashOfCertificate(ctx.cert(Requirement::anchorCert), anchorHash); + if (!memcmp(anchorHash, Requirement::appleAnchorHash(), SHA1::digestLength) +#if defined(TEST_APPLE_ANCHOR) + || !memcmp(anchorHash, Requirement::testAppleAnchorHash(), SHA1::digestLength) +#endif + ) + appleAnchor(); + else + nonAppleAnchor(); + + return Maker::make(); +} + + +void DRMaker::nonAppleAnchor() +{ + // get the Organization DN element for the leaf + CFRef leafOrganization; + MacOSError::check(SecCertificateCopySubjectComponent(ctx.cert(Requirement::leafCert), + &CSSMOID_OrganizationName, &leafOrganization.aref())); + + // now step up the cert chain looking for the first cert with a different one + int slot = Requirement::leafCert; // start at leaf + if (leafOrganization) { + while (SecCertificateRef ca = ctx.cert(slot+1)) { // NULL if you over-run the anchor slot + CFRef caOrganization; + MacOSError::check(SecCertificateCopySubjectComponent(ca, &CSSMOID_OrganizationName, &caOrganization.aref())); + if (!caOrganization || CFStringCompare(leafOrganization, caOrganization, 0) != kCFCompareEqualTo) + break; + slot++; + } + if (slot == ctx.certCount() - 1) // went all the way to the anchor... + slot = Requirement::anchorCert; // ... so say that + } + + // nail the last cert with the leaf's Organization value + SHA1::Digest authorityHash; + hashOfCertificate(ctx.cert(slot), authorityHash); + this->anchor(slot, authorityHash); +} + + +void DRMaker::appleAnchor() +{ + if (isIOSSignature()) { + // get the Common Name DN element for the leaf + CFRef leafCN; + MacOSError::check(SecCertificateCopySubjectComponent(ctx.cert(Requirement::leafCert), + &CSSMOID_CommonName, &leafCN.aref())); + + // apple anchor generic and ... + this->put(opAnd); + this->anchorGeneric(); // apple generic anchor and... + // ... leaf[subject.CN] = and ... + this->put(opAnd); + this->put(opCertField); // certificate + this->put(0); // leaf + this->put("subject.CN"); // [subject.CN] + this->put(matchEqual); // = + this->putData(leafCN); // + // ... cert 1[field.] exists + this->put(opCertGeneric); // certificate + this->put(1); // 1 + this->putData(adcSdkMarkerOID.Data, adcSdkMarkerOID.Length); // [field.] + this->put(matchExists); // exists + return; + } + + if (isDeveloperIDSignature()) { + // get the Organizational Unit DN element for the leaf (it contains the TEAMID) + CFRef teamID; + MacOSError::check(SecCertificateCopySubjectComponent(ctx.cert(Requirement::leafCert), + &CSSMOID_OrganizationalUnitName, &teamID.aref())); + + // apple anchor generic and ... + this->put(opAnd); + this->anchorGeneric(); // apple generic anchor and... + + // ... certificate 1[intermediate marker oid] exists and ... + this->put(opAnd); + this->put(opCertGeneric); // certificate + this->put(1); // 1 + this->putData(caspianSdkMarker, sizeof(caspianSdkMarker)); + this->put(matchExists); // exists + + // ... certificate leaf[Caspian cert oid] exists and ... + this->put(opAnd); + this->put(opCertGeneric); // certificate + this->put(0); // leaf + this->putData(caspianLeafMarker, sizeof(caspianLeafMarker)); + this->put(matchExists); // exists + + // ... leaf[subject.OU] = + this->put(opCertField); // certificate + this->put(0); // leaf + this->put("subject.OU"); // [subject.OU] + this->put(matchEqual); // = + this->putData(teamID); // TEAMID + return; + } + + // otherwise, claim this program for Apple Proper + this->anchor(); +} + +bool DRMaker::isIOSSignature() +{ + if (ctx.certCount() == 3) // leaf, one intermediate, anchor + if (SecCertificateRef intermediate = ctx.cert(1)) // get intermediate + if (certificateHasField(intermediate, CssmOid::overlay(adcSdkMarkerOID))) + return true; + return false; +} + +bool DRMaker::isDeveloperIDSignature() +{ + if (ctx.certCount() == 3) // leaf, one intermediate, anchor + if (SecCertificateRef intermediate = ctx.cert(1)) // get intermediate + if (certificateHasField(intermediate, CssmOid::overlay(devIdSdkMarkerOID))) + return true; + return false; +} + + +} // end namespace CodeSigning +} // end namespace Security diff --git a/libsecurity_codesigning/lib/drmaker.h b/libsecurity_codesigning/lib/drmaker.h new file mode 100644 index 00000000..704c3611 --- /dev/null +++ b/libsecurity_codesigning/lib/drmaker.h @@ -0,0 +1,69 @@ +/* + * 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@ + */ + +// +// drmaker - create Designated Requirements +// +#ifndef _H_DRMAKER +#define _H_DRMAKER + +#include "reqmaker.h" + +namespace Security { +namespace CodeSigning { + + +// +// Some useful certificate OID markers +// +extern const CSSM_DATA adcSdkMarkerOID; +extern const CSSM_DATA devIdSdkMarkerOID; +extern const CSSM_DATA devIdLeafMarkerOID; + + + +// +// A Maker of Designated Requirements +// +class DRMaker : public Requirement::Maker { +public: + DRMaker(const Requirement::Context &context); + virtual ~DRMaker(); + + const Requirement::Context &ctx; + +public: + Requirement *make(); + +private: + void appleAnchor(); + void nonAppleAnchor(); + bool isIOSSignature(); + bool isDeveloperIDSignature(); +}; + + +} // end namespace CodeSigning +} // end namespace Security + +#endif // !_H_DRMAKER diff --git a/libsecurity_codesigning/lib/filediskrep.cpp b/libsecurity_codesigning/lib/filediskrep.cpp new file mode 100644 index 00000000..7a098c22 --- /dev/null +++ b/libsecurity_codesigning/lib/filediskrep.cpp @@ -0,0 +1,191 @@ +/* + * Copyright (c) 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@ + */ +#include "filediskrep.h" +#include "StaticCode.h" +#include +#include + + +namespace Security { +namespace CodeSigning { + +using namespace UnixPlusPlus; + + +// +// Everything's lazy in here +// +FileDiskRep::FileDiskRep(const char *path) + : SingleDiskRep(path) +{ + CODESIGN_DISKREP_CREATE_FILE(this, (char*)path); +} + + +// +// Produce an extended attribute name from a canonical slot name +// +string FileDiskRep::attrName(const char *name) +{ + static const char prefix[] = "com.apple.cs."; + return string(prefix) + name; +} + + +// +// Retrieve an extended attribute by name +// +CFDataRef FileDiskRep::getAttribute(const char *name) +{ + string aname = attrName(name); + try { + ssize_t length = fd().getAttrLength(aname); + if (length < 0) + return NULL; // no such attribute + CFMallocData buffer(length); + fd().getAttr(aname, buffer, length); + return buffer; + } catch (const UnixError &err) { + // recover some errors that happen in (relatively) benign circumstances + switch (err.error) { + case ENOTSUP: // no extended attributes on this filesystem + case EPERM: // filesystem objects to name(?) + return NULL; + default: + throw; + } + } +} + + +// +// 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 FileDiskRep::component(CodeDirectory::SpecialSlot slot) +{ + if (const char *name = CodeDirectory::canonicalSlotName(slot)) + return getAttribute(name); + else + return NULL; +} + + +// +// Generate a suggested set of internal requirements. +// We don't really have to say much. However, if we encounter a file that +// starts with the magic "#!" script marker, we do suggest that this should +// be a valid host if we can reasonably make out what that is. +// +const Requirements *FileDiskRep::defaultRequirements(const Architecture *, const SigningContext &ctx) +{ + // read start of file + char buffer[256]; + size_t length = fd().read(buffer, sizeof(buffer), 0); + if (length > 3 && buffer[0] == '#' && buffer[1] == '!' && buffer[2] == '/') { + // isolate (full) path element in #!/full/path -some -other -stuff + if (length == sizeof(buffer)) + length--; + buffer[length] = '\0'; + char *cmd = buffer + 2; + cmd[strcspn(cmd, " \t\n\r\f")] = '\0'; + secdebug("filediskrep", "looks like a script for %s", cmd); + if (cmd[1]) + try { + // find path on disk, get designated requirement (if signed) + string path = ctx.sdkPath(cmd); + if (RefPointer rep = DiskRep::bestFileGuess(path)) + if (SecPointer code = new SecStaticCode(rep)) + if (const Requirement *req = code->designatedRequirement()) { + CODESIGN_SIGN_DEP_INTERP(this, (char*)cmd, (void*)req); + // package up as host requirement and return that + Requirements::Maker maker; + maker.add(kSecHostRequirementType, req->clone()); + return maker.make(); + } + } catch (...) { + secdebug("filediskrep", "exception getting host requirement (ignored)"); + } + } + return NULL; +} + + +string FileDiskRep::format() +{ + return "generic"; +} + + +// +// FileDiskRep::Writers +// +DiskRep::Writer *FileDiskRep::writer() +{ + return new Writer(this); +} + + +// +// 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 FileDiskRep::Writer::component(CodeDirectory::SpecialSlot slot, CFDataRef data) +{ + try { + fd().setAttr(attrName(CodeDirectory::canonicalSlotName(slot)), + CFDataGetBytePtr(data), CFDataGetLength(data)); + } catch (const UnixError &error) { + if (error.error == ERANGE) + MacOSError::throwMe(errSecCSCMSTooLarge); + throw; + } +} + + +// +// Clear all signing data +// +void FileDiskRep::Writer::remove() +{ + for (CodeDirectory::SpecialSlot slot = 0; slot < cdSlotCount; slot++) + if (const char *name = CodeDirectory::canonicalSlotName(slot)) + fd().removeAttr(attrName(name)); + fd().removeAttr(attrName(kSecCS_SIGNATUREFILE)); +} + + +// +// We are NOT the preferred store for components because our approach +// (extended attributes) suffers from some serious limitations. +// +bool FileDiskRep::Writer::preferredStore() +{ + return false; +} + + +} // end namespace CodeSigning +} // end namespace Security diff --git a/libsecurity_codesigning/lib/filediskrep.h b/libsecurity_codesigning/lib/filediskrep.h new file mode 100644 index 00000000..70410eea --- /dev/null +++ b/libsecurity_codesigning/lib/filediskrep.h @@ -0,0 +1,93 @@ +/* + * Copyright (c) 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@ + */ + +// +// filediskrep - single-file executable disk representation +// +#ifndef _H_FILEDISKREP +#define _H_FILEDISKREP + +#include "singlediskrep.h" +#include "machorep.h" +#include + +namespace Security { +namespace CodeSigning { + + +// +// A FileDiskRep represents a single code file on disk. We assume nothing about +// the format or contents of the file and impose no structure on it, other than +// assuming that all relevant code is contained in the file's data bytes. +// By default, we seal the entire file data as a single page. +// +// This is the ultimate fallback disk format. It is used if no other pattern +// applies. As such it is important that we do not introduce any assumptions +// here. Know that you do not know what any of the file means. +// +// FileDiskrep stores components in extended file attributes, one attribute +// per component. Note that this imposes size limitations on component size +// that may well be prohibitive in some applications. +// +// This DiskRep does not support resource sealing. +// +class FileDiskRep : public SingleDiskRep { +public: + FileDiskRep(const char *path); + + CFDataRef component(CodeDirectory::SpecialSlot slot); + std::string format(); + + const Requirements *defaultRequirements(const Architecture *arch, const SigningContext &ctx); + +public: + DiskRep::Writer *writer(); + class Writer; + friend class Writer; + +protected: + CFDataRef getAttribute(const char *name); + static std::string attrName(const char *name); +}; + + +// +// The write side of a FileDiskRep +// +class FileDiskRep::Writer : public SingleDiskRep::Writer { + friend class FileDiskRep; +public: + void component(CodeDirectory::SpecialSlot slot, CFDataRef data); + void remove(); + bool preferredStore(); + +protected: + Writer(FileDiskRep *r) : SingleDiskRep::Writer(r, writerLastResort) { } + RefPointer rep; +}; + + +} // end namespace CodeSigning +} // end namespace Security + +#endif // !_H_FILEDISKREP diff --git a/libsecurity_codesigning/lib/kerneldiskrep.cpp b/libsecurity_codesigning/lib/kerneldiskrep.cpp new file mode 100644 index 00000000..f39cc511 --- /dev/null +++ b/libsecurity_codesigning/lib/kerneldiskrep.cpp @@ -0,0 +1,91 @@ +/* + * 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 "kerneldiskrep.h" +#include + +namespace Security { +namespace CodeSigning { + +using namespace UnixPlusPlus; + + +// +// Everything about the kernel is pretty much fixed, so there's +// no state to maintain. +// +KernelDiskRep::KernelDiskRep() +{ + CODESIGN_DISKREP_CREATE_KERNEL(this); +} + + +// +// We can't pull any resources from the kernel. +// And we know where it all is. +// +CFDataRef KernelDiskRep::component(CodeDirectory::SpecialSlot slot) +{ + return NULL; +} + +CFDataRef KernelDiskRep::identification() +{ + return NULL; +} + + +CFURLRef KernelDiskRep::canonicalPath() +{ + return makeCFURL("/mach_kernel"); +} + +string KernelDiskRep::recommendedIdentifier(const SigningContext &) +{ + utsname names; + UnixError::check(::uname(&names)); + return string("kernel.") + names.sysname; +} + +size_t KernelDiskRep::signingLimit() +{ + return 0; // don't bother +} + +string KernelDiskRep::format() +{ + return "system kernel"; +} + +UnixPlusPlus::FileDesc &KernelDiskRep::fd() +{ + UnixError::throwMe(EINVAL); // don't have one +} + +string KernelDiskRep::mainExecutablePath() +{ + return "/mach_kernel"; +} + + +} // end namespace CodeSigning +} // end namespace Security diff --git a/libsecurity_codesigning/lib/kerneldiskrep.h b/libsecurity_codesigning/lib/kerneldiskrep.h new file mode 100644 index 00000000..997462f6 --- /dev/null +++ b/libsecurity_codesigning/lib/kerneldiskrep.h @@ -0,0 +1,64 @@ +/* + * 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@ + */ + +// +// kerneldiskrep - the kernel's own disk representation. +// +// This is a very special case. +// It's here primarily so we don't have to add special cases for the kernel +// all over the higher layers. +// +#ifndef _H_KERNELDISKREP +#define _H_KERNELDISKREP + +#include "diskrep.h" + +namespace Security { +namespace CodeSigning { + + +// +// A KernelDiskRep represents a (the) kernel on disk. +// It has no write support, so we can't sign the kernel, +// which is fine since we unconditionally trust it anyway. +// +class KernelDiskRep : public DiskRep { +public: + KernelDiskRep(); + + CFDataRef component(CodeDirectory::SpecialSlot slot); + CFDataRef identification(); + std::string mainExecutablePath(); + CFURLRef canonicalPath(); + size_t signingLimit(); + std::string format(); + UnixPlusPlus::FileDesc &fd(); + + std::string recommendedIdentifier(const SigningContext &ctx); +}; + + +} // end namespace CodeSigning +} // end namespace Security + +#endif // !_H_KERNELDISKREP diff --git a/libsecurity_codesigning/lib/machorep.cpp b/libsecurity_codesigning/lib/machorep.cpp new file mode 100644 index 00000000..180a400e --- /dev/null +++ b/libsecurity_codesigning/lib/machorep.cpp @@ -0,0 +1,383 @@ +/* + * 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@ + */ + +// +// machorep - DiskRep mix-in for handling Mach-O main executables +// +#include "machorep.h" +#include "StaticCode.h" +#include "reqmaker.h" + + +namespace Security { +namespace CodeSigning { + +using namespace UnixPlusPlus; + + +// +// Object management. +// We open the main executable lazily, so nothing much happens on construction. +// If the context specifies a file offset, we directly pick that Mach-O binary (only). +// if it specifies an architecture, we try to pick that. Otherwise, we deliver the whole +// Universal object (which will usually deliver the "native" architecture later). +// +MachORep::MachORep(const char *path, const Context *ctx) + : SingleDiskRep(path), mSigningData(NULL) +{ + if (ctx) + if (ctx->offset) + mExecutable = new Universal(fd(), ctx->offset); + else if (ctx->arch) { + auto_ptr full(new Universal(fd())); + mExecutable = new Universal(fd(), full->archOffset(ctx->arch)); + } else + mExecutable = new Universal(fd()); + else + mExecutable = new Universal(fd()); + assert(mExecutable); + CODESIGN_DISKREP_CREATE_MACHO(this, (char*)path, (void*)ctx); +} + +MachORep::~MachORep() +{ + delete mExecutable; + ::free(mSigningData); +} + + +// +// Sniffer function for "plausible Mach-O binary" +// +bool MachORep::candidate(FileDesc &fd) +{ + switch (Universal::typeOf(fd)) { + case MH_EXECUTE: + case MH_DYLIB: + case MH_DYLINKER: + case MH_BUNDLE: + case MH_PRELOAD: + return true; // dynamic image; supported + case MH_OBJECT: + return false; // maybe later... + default: + return false; // not Mach-O (or too exotic) + } +} + + + +// +// Nowadays, the main executable object is created upon construction. +// +Universal *MachORep::mainExecutableImage() +{ + return mExecutable; +} + + +// +// Signing base is the start of the Mach-O architecture we're using +// +size_t MachORep::signingBase() +{ + return mainExecutableImage()->archOffset(); +} + + +// +// We choose the binary identifier for a Mach-O binary as follows: +// - If the Mach-O headers have a UUID command, use the UUID. +// - Otherwise, use the SHA-1 hash of the (entire) load commands. +// +CFDataRef MachORep::identification() +{ + std::auto_ptr macho(mainExecutableImage()->architecture()); + return identificationFor(macho.get()); +} + +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); + char result[4 + sizeof(uuidc->uuid)]; + memcpy(result, "UUID", 4); + memcpy(result+4, uuidc->uuid, sizeof(uuidc->uuid)); + return makeCFData(result, sizeof(result)); + } + + // otherwise, use the SHA-1 hash of the entire load command area + SHA1 hash; + hash(&macho->header(), sizeof(mach_header)); + hash(macho->loadCommands(), macho->commandLength()); + SHA1::Digest digest; + hash.finish(digest); + return makeCFData(digest, sizeof(digest)); +} + + +// +// Retrieve a component from the executable. +// This reads the entire signing SuperBlob when first called for an executable, +// and then caches it for further use. +// Note that we could read individual components directly off disk and only cache +// the SuperBlob Index directory. Our caller (usually SecStaticCode) is expected +// to cache the pieces anyway. +// +CFDataRef MachORep::component(CodeDirectory::SpecialSlot slot) +{ + switch (slot) { + case cdInfoSlot: + return infoPlist(); + default: + return embeddedComponent(slot); + } +} + + +// Retrieve a component from the embedded signature SuperBlob (if present). +// This reads the entire signing SuperBlob when first called for an executable, +// and then caches it for further use. +// Note that we could read individual components directly off disk and only cache +// the SuperBlob Index directory. Our caller (usually SecStaticCode) is expected +// to cache the pieces anyway. But it's not clear that the resulting multiple I/O +// calls wouldn't be slower in the end. +// +CFDataRef MachORep::embeddedComponent(CodeDirectory::SpecialSlot slot) +{ + if (!mSigningData) { // fetch and cache + auto_ptr macho(mainExecutableImage()->architecture()); + if (macho.get()) + if (const linkedit_data_command *cs = macho->findCodeSignature()) { + size_t offset = macho->flip(cs->dataoff); + size_t length = macho->flip(cs->datasize); + if ((mSigningData = EmbeddedSignatureBlob::readBlob(macho->fd(), macho->offset() + offset, length))) { + secdebug("machorep", "%zd signing bytes in %d blob(s) from %s(%s)", + mSigningData->length(), mSigningData->count(), + mainExecutablePath().c_str(), macho->architecture().name()); + } else { + secdebug("machorep", "failed to read signing bytes from %s(%s)", + mainExecutablePath().c_str(), macho->architecture().name()); + MacOSError::throwMe(errSecCSSignatureInvalid); + } + } + } + if (mSigningData) + return mSigningData->component(slot); + + // not found + return NULL; +} + + +// +// Extract an embedded Info.plist from the file. +// Returns NULL if none is found. +// +CFDataRef MachORep::infoPlist() +{ + CFRef info; + try { + auto_ptr macho(mainExecutableImage()->architecture()); + if (const section *sect = macho->findSection("__TEXT", "__info_plist")) { + if (macho->is64()) { + const section_64 *sect64 = reinterpret_cast(sect); + info.take(macho->dataAt(macho->flip(sect64->offset), macho->flip(sect64->size))); + } else { + info.take(macho->dataAt(macho->flip(sect->offset), macho->flip(sect->size))); + } + } + } catch (...) { + secdebug("machorep", "exception reading embedded Info.plist"); + } + return info.yield(); +} + + +// +// Provide a (vaguely) human readable characterization of this code +// +string MachORep::format() +{ + if (Universal *fat = mainExecutableImage()) { + Universal::Architectures archs; + fat->architectures(archs); + if (fat->isUniversal()) { + string s = "Mach-O universal ("; + for (Universal::Architectures::const_iterator it = archs.begin(); + it != archs.end(); ++it) { + if (it != archs.begin()) + s += " "; + s += it->displayName(); + } + return s + ")"; + } else { + assert(archs.size() == 1); + return string("Mach-O thin (") + archs.begin()->displayName() + ")"; + } + } else + return "Mach-O (unrecognized format)"; +} + + +// +// Flush cached data +// +void MachORep::flush() +{ + delete mExecutable; + mExecutable = NULL; + ::free(mSigningData); + mSigningData = NULL; + SingleDiskRep::flush(); + mExecutable = new Universal(fd()); +} + + +// +// Return a recommended unique identifier. +// If our file has an embedded Info.plist, use the CFBundleIdentifier from that. +// Otherwise, use the default. +// +string MachORep::recommendedIdentifier(const SigningContext &ctx) +{ + if (CFDataRef info = infoPlist()) { + if (CFRef dict = makeCFDictionaryFrom(info)) { + CFStringRef code = CFStringRef(CFDictionaryGetValue(dict, kCFBundleIdentifierKey)); + if (code && CFGetTypeID(code) != CFStringGetTypeID()) + MacOSError::throwMe(errSecCSBadDictionaryFormat); + if (code) + return cfString(code); + } else + MacOSError::throwMe(errSecCSBadDictionaryFormat); + } + + // ah well. Use the default + return SingleDiskRep::recommendedIdentifier(ctx); +} + + +// +// The default suggested requirements for Mach-O binaries are as follows: +// Library requirement: Composed from dynamic load commands. +// +const Requirements *MachORep::defaultRequirements(const Architecture *arch, const SigningContext &ctx) +{ + assert(arch); // enforced by signing infrastructure + Requirements::Maker maker; + + // add library requirements from DYLIB commands (if any) + if (Requirement *libreq = libraryRequirements(arch, ctx)) + maker.add(kSecLibraryRequirementType, libreq); // takes ownership + + // that's all + return maker.make(); +} + +Requirement *MachORep::libraryRequirements(const Architecture *arch, const SigningContext &ctx) +{ + auto_ptr macho(mainExecutableImage()->architecture(*arch)); + Requirement::Maker maker; + Requirement::Maker::Chain chain(maker, opOr); + + if (macho.get()) + if (const linkedit_data_command *ldep = macho->findLibraryDependencies()) { + size_t offset = macho->flip(ldep->dataoff); + size_t length = macho->flip(ldep->datasize); + if (LibraryDependencyBlob *deplist = LibraryDependencyBlob::readBlob(macho->fd(), macho->offset() + offset, length)) { + try { + secdebug("machorep", "%zd library dependency bytes in %d blob(s) from %s(%s)", + deplist->length(), deplist->count(), + mainExecutablePath().c_str(), macho->architecture().name()); + unsigned count = deplist->count(); + // we could walk through DYLIB load commands in parallel. We just don't need anything from them so far + for (unsigned n = 0; n < count; n++) { + const Requirement *req = NULL; + if (const BlobCore *dep = deplist->blob(n)) { + if ((req = Requirement::specific(dep))) { + // binary code requirement; good to go + } else if (const BlobWrapper *wrap = BlobWrapper::specific(dep)) { + // blob-wrapped text form - convert to binary requirement + std::string reqString = std::string((const char *)wrap->data(), wrap->length()); + CFRef areq; + MacOSError::check(SecRequirementCreateWithString(CFTempString(reqString), kSecCSDefaultFlags, &areq.aref())); + CFRef reqData; + MacOSError::check(SecRequirementCopyData(areq, kSecCSDefaultFlags, &reqData.aref())); + req = Requirement::specific((const BlobCore *)CFDataGetBytePtr(reqData)); + } else { + secdebug("machorep", "unexpected blob type 0x%x in slot %d of binary dependencies", dep->magic(), n); + continue; + } + chain.add(); + maker.copy(req); + } else + secdebug("machorep", "missing DR info for library index %d", n); + } + ::free(deplist); + } catch (...) { + ::free(deplist); + throw; + } + } + } + if (chain.empty()) + return NULL; + else + return maker.make(); +} + + +// +// Default to system page size for segmented (paged) signatures +// +size_t MachORep::pageSize(const SigningContext &) +{ + return segmentedPageSize; +} + + +// +// FileDiskRep::Writers +// +DiskRep::Writer *MachORep::writer() +{ + return new Writer(this); +} + + +// +// Write a component. +// MachORep::Writers don't write to components directly; the signing code uses special +// knowledge of the Mach-O format to build embedded signatures and blasts them directly +// to disk. Thus this implementation will never be called (and, if called, will simply fail). +// +void MachORep::Writer::component(CodeDirectory::SpecialSlot slot, CFDataRef data) +{ + assert(false); + MacOSError::throwMe(errSecCSInternalError); +} + + +} // end namespace CodeSigning +} // end namespace Security diff --git a/libsecurity_codesigning/lib/machorep.h b/libsecurity_codesigning/lib/machorep.h new file mode 100644 index 00000000..24861395 --- /dev/null +++ b/libsecurity_codesigning/lib/machorep.h @@ -0,0 +1,102 @@ +/* + * 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@ + */ + +// +// machorep - DiskRep mix-in for handling Mach-O main executables +// +#ifndef _H_MACHOREP +#define _H_MACHOREP + +#include "singlediskrep.h" +#include "sigblob.h" +#include +#include + +namespace Security { +namespace CodeSigning { + + +// +// MachORep is a DiskRep class that supports code signatures +// directly embedded in Mach-O binary files. +// +// It does not have write support (for writing signatures); +// writing multi-architecture binaries is complicated enough +// that it's driven directly from the signing code, with no +// abstractions to get in the way. +// +class MachORep : public SingleDiskRep { +public: + MachORep(const char *path, const Context *ctx = NULL); + virtual ~MachORep(); + + CFDataRef component(CodeDirectory::SpecialSlot slot); + CFDataRef identification(); + Universal *mainExecutableImage(); + size_t signingBase(); + std::string format(); + + std::string recommendedIdentifier(const SigningContext &ctx); + const Requirements *defaultRequirements(const Architecture *arch, const SigningContext &ctx); + size_t pageSize(const SigningContext &ctx); + + void flush(); // flush cache + + static bool candidate(UnixPlusPlus::FileDesc &fd); + +public: + static CFDataRef identificationFor(MachO *macho); + +public: + DiskRep::Writer *writer(); + class Writer; + friend class Writer; + +protected: + CFDataRef embeddedComponent(CodeDirectory::SpecialSlot slot); + CFDataRef infoPlist(); + Requirement *libraryRequirements(const Architecture *arch, const SigningContext &ctx); + +private: + Universal *mExecutable; // cached Mach-O/Universal reference to mainExecutablePath() + EmbeddedSignatureBlob *mSigningData; // cached signing data from current architecture +}; + + +// +// The write side of a MachORep. +// This is purposely dysfunctional; Mach-O signatures are written +// by code in signerutils, not by DiskRep::Writers. +// +class MachORep::Writer : public SingleDiskRep::Writer { + friend class FileDiskRep; +public: + Writer(MachORep *r) : SingleDiskRep::Writer(r, writerNoGlobal) { } + void component(CodeDirectory::SpecialSlot slot, CFDataRef data); +}; + + +} // end namespace CodeSigning +} // end namespace Security + +#endif // !_H_MACHOREP diff --git a/libsecurity_codesigning/lib/policydb.cpp b/libsecurity_codesigning/lib/policydb.cpp new file mode 100644 index 00000000..63b3c934 --- /dev/null +++ b/libsecurity_codesigning/lib/policydb.cpp @@ -0,0 +1,410 @@ +/* + * Copyright (c) 2011-2012 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +#include "cs.h" +#include "policydb.h" +#include "policyengine.h" +#include +#include +#include +#include +#include +#include +#include +#include "csdatabase.h" + +#include +#include +#include +#include + +namespace Security { +namespace CodeSigning { + + +using namespace SQLite; + + +// +// Determine the database path +// +static const char *dbPath() +{ + if (const char *s = getenv("SYSPOLICYDATABASE")) + return s; + return defaultDatabase; +} + + +// +// Help mapping API-ish CFString keys to more convenient internal enumerations +// +typedef struct { + const CFStringRef &cstring; + uint enumeration; +} StringMap; + +static uint mapEnum(CFDictionaryRef context, CFStringRef attr, const StringMap *map, uint value = 0) +{ + if (context) + if (CFTypeRef value = CFDictionaryGetValue(context, attr)) + for (const StringMap *mp = map; mp->cstring; ++mp) + if (CFEqual(mp->cstring, value)) + return mp->enumeration; + return value; +} + +static const StringMap mapType[] = { + { kSecAssessmentOperationTypeExecute, kAuthorityExecute }, + { kSecAssessmentOperationTypeInstall, kAuthorityInstall }, + { kSecAssessmentOperationTypeOpenDocument, kAuthorityOpenDoc }, + { NULL } +}; + +AuthorityType typeFor(CFDictionaryRef context, AuthorityType type /* = kAuthorityInvalid */) +{ + return mapEnum(context, kSecAssessmentContextKeyOperation, mapType, type); +} + +CFStringRef typeNameFor(AuthorityType type) +{ + for (const StringMap *mp = mapType; mp->cstring; ++mp) + if (type == mp->enumeration) + return mp->cstring; + return CFStringCreateWithFormat(NULL, NULL, CFSTR("type %d"), type); +} + + +// +// Open the database +// +PolicyDatabase::PolicyDatabase(const char *path, int flags) + : SQLite::Database(path ? path : dbPath(), flags), + mLastExplicitCheck(0) +{ + // sqlite3 doesn't do foreign key support by default, have to turn this on per connection + SQLite::Statement foreign(*this, "PRAGMA foreign_keys = true"); + foreign.execute(); + + // Try upgrade processing if we may be open for write. + // Ignore any errors (we may have been downgraded to read-only) + // and try again later. + if (openFlags() & SQLITE_OPEN_READWRITE) + try { + upgradeDatabase(); + installExplicitSet(gkeAuthFile, gkeSigsFile); + } catch(...) { + } +} + +PolicyDatabase::~PolicyDatabase() +{ /* virtual */ } + + +// +// Quick-check the cache for a match. +// Return true on a cache hit, false on failure to confirm a hit for any reason. +// +bool PolicyDatabase::checkCache(CFURLRef path, AuthorityType type, CFMutableDictionaryRef result) +{ + // we currently don't use the cache for anything but execution rules + if (type != kAuthorityExecute) + return false; + + CFRef code; + MacOSError::check(SecStaticCodeCreateWithPath(path, kSecCSDefaultFlags, &code.aref())); + if (SecStaticCodeCheckValidity(code, kSecCSBasicValidateOnly, NULL) != noErr) + return false; // quick pass - any error is a cache miss + CFRef info; + MacOSError::check(SecCodeCopySigningInformation(code, kSecCSDefaultFlags, &info.aref())); + CFDataRef cdHash = CFDataRef(CFDictionaryGetValue(info, kSecCodeInfoUnique)); + + // check the cache table for a fast match + SQLite::Statement cached(*this, "SELECT object.allow, authority.label, authority FROM object, authority" + " WHERE object.authority = authority.id AND object.type = :type AND object.hash = :hash AND authority.disabled = 0" + " AND JULIANDAY('now') < object.expires;"); + cached.bind(":type").integer(type); + cached.bind(":hash") = cdHash; + if (cached.nextRow()) { + bool allow = int(cached[0]); + const char *label = cached[1]; + SQLite::int64 auth = cached[2]; + SYSPOLICY_ASSESS_CACHE_HIT(); + + // If its allowed, lets do a full validation unless if + // we are overriding the assessement, since that force + // the verdict to 'pass' at the end + + if (allow && !overrideAssessment()) + MacOSError::check(SecStaticCodeCheckValidity(code, kSecCSDefaultFlags, NULL)); + + cfadd(result, "{%O=%B}", kSecAssessmentAssessmentVerdict, allow); + PolicyEngine::addAuthority(result, label, auth, kCFBooleanTrue); + return true; + } + return false; +} + + +// +// Purge the object cache of all expired entries. +// These are meant to run within the caller's transaction. +// +void PolicyDatabase::purgeAuthority() +{ + SQLite::Statement cleaner(*this, + "DELETE FROM authority WHERE expires <= JULIANDAY('now');"); + cleaner.execute(); +} + +void PolicyDatabase::purgeObjects() +{ + SQLite::Statement cleaner(*this, + "DELETE FROM object WHERE expires <= JULIANDAY('now');"); + cleaner.execute(); +} + +void PolicyDatabase::purgeObjects(double priority) +{ + SQLite::Statement cleaner(*this, + "DELETE FROM object WHERE expires <= JULIANDAY('now') OR (SELECT priority FROM authority WHERE id = object.authority) <= :priority;"); + cleaner.bind(":priority") = priority; + cleaner.execute(); +} + + +// +// Database migration +// +std::string PolicyDatabase::featureLevel(const char *name) +{ + SQLite::Statement feature(*this, "SELECT value FROM feature WHERE name=:name"); + feature.bind(":name") = name; + if (feature.nextRow()) + return feature[0].string(); + else + return ""; // new feature (no level) +} + +void PolicyDatabase::addFeature(const char *name, const char *value, const char *remarks) +{ + SQLite::Statement feature(*this, "INSERT OR REPLACE INTO feature (name,value,remarks) VALUES(:name, :value, :remarks)"); + feature.bind(":name") = name; + feature.bind(":value") = value; + feature.bind(":remarks") = remarks; + feature.execute(); +} + +void PolicyDatabase::simpleFeature(const char *feature, void (^perform)()) +{ + if (!hasFeature(feature)) { + addFeature(feature, "upgraded", "upgraded"); + SQLite::Transaction update(*this); + perform(); + update.commit(); + } +} + +void PolicyDatabase::simpleFeature(const char *feature, const char *sql) +{ + simpleFeature(feature, ^{ + SQLite::Statement perform(*this, sql); + addFeature(feature, "upgraded", "upgraded"); + perform.execute(); + }); +} + + +void PolicyDatabase::upgradeDatabase() +{ + simpleFeature("bookmarkhints", + "CREATE TABLE bookmarkhints (" + " id INTEGER PRIMARY KEY AUTOINCREMENT, " + " bookmark BLOB," + " authority INTEGER NOT NULL" + " REFERENCES authority(id) ON DELETE CASCADE" + ")"); + + simpleFeature("codesignedpackages", ^{ + SQLite::Statement update(*this, + "UPDATE authority" + " SET requirement = '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.14] or certificate leaf[field.1.2.840.113635.100.6.1.13])'" + " WHERE type = 2 and label = 'Developer ID' and flags & :flag"); + update.bind(":flag") = kAuthorityFlagDefault; + update.execute(); + }); +} + + +// +// Install Gatekeeper override (GKE) data. +// The arguments are paths to the authority and signature files. +// +void PolicyDatabase::installExplicitSet(const char *authfile, const char *sigfile) +{ + // only try this every gkeCheckInterval seconds + time_t now = time(NULL); + if (mLastExplicitCheck + gkeCheckInterval > now) + return; + mLastExplicitCheck = now; + + try { + if (CFRef authData = cfLoadFile(authfile)) { + CFDictionary auth(CFRef(makeCFDictionaryFrom(authData)), errSecCSDbCorrupt); + CFDictionaryRef content = auth.get(CFSTR("authority")); + std::string authUUID = cfString(auth.get(CFSTR("uuid"))); + if (authUUID.empty()) { + secdebug("gkupgrade", "no uuid in auth file; ignoring gke.auth"); + return; + } + std::string dbUUID; + SQLite::Statement uuidQuery(*this, "SELECT value FROM feature WHERE name='gke'"); + if (uuidQuery.nextRow()) + dbUUID = (const char *)uuidQuery[0]; + if (dbUUID == authUUID) { + secdebug("gkupgrade", "gke.auth already present, ignoring"); + return; + } + Syslog::notice("loading GKE %s (replacing %s)", authUUID.c_str(), dbUUID.empty() ? "nothing" : dbUUID.c_str()); + + // first, load code signatures. This is pretty much idempotent + if (sigfile) + if (FILE *sigs = fopen(sigfile, "r")) { + unsigned count = 0; + while (const BlobCore *blob = BlobCore::readBlob(sigs)) { + signatureDatabaseWriter().storeCode(blob, ""); + count++; + } + secdebug("gkupgrade", "%d detached signature(s) loaded from override data", count); + fclose(sigs); + } + + // start transaction (atomic from here on out) + SQLite::Transaction loadAuth(*this, SQLite::Transaction::exclusive, "GKE_Upgrade"); + + // purge prior authority data + SQLite::Statement purge(*this, "DELETE FROM authority WHERE flags & :flag"); + purge.bind(":flag") = kAuthorityFlagWhitelist; + purge(); + + // load new data + CFIndex count = CFDictionaryGetCount(content); + CFStringRef keys[count]; + CFDictionaryRef values[count]; + CFDictionaryGetKeysAndValues(content, (const void **)keys, (const void **)values); + + SQLite::Statement insert(*this, "INSERT INTO authority (type, allow, requirement, label, flags, remarks)" + " VALUES (:type, 1, :requirement, 'GKE', :flags, :path)"); + for (CFIndex n = 0; n < count; n++) { + CFDictionary info(values[n], errSecCSDbCorrupt); + insert.reset(); + insert.bind(":type") = cfString(info.get(CFSTR("type"))); + insert.bind(":path") = cfString(info.get(CFSTR("path"))); + insert.bind(":requirement") = "cdhash H\"" + cfString(info.get(CFSTR("cdhash"))) + "\""; + insert.bind(":flags") = kAuthorityFlagWhitelist; + insert(); + } + + // update version and commit + addFeature("gke", authUUID.c_str(), "gke loaded"); + loadAuth.commit(); + } + } catch (...) { + secdebug("gkupgrade", "exception during GKE upgrade"); + } +} + + +// +// Check the override-enable master flag +// +#define SP_ENABLE_KEY CFSTR("enabled") +#define SP_ENABLED CFSTR("yes") +#define SP_DISABLED CFSTR("no") + +bool overrideAssessment() +{ + static bool enabled = true; + static dispatch_once_t once; + static int token = -1; + static int have_token = 0; + static dispatch_queue_t queue; + int check; + + if (have_token && notify_check(token, &check) == NOTIFY_STATUS_OK && !check) + return !enabled; + + dispatch_once(&once, ^{ + if (notify_register_check(kNotifySecAssessmentMasterSwitch, &token) == NOTIFY_STATUS_OK) + have_token = 1; + queue = dispatch_queue_create("com.apple.SecAssessment.assessment", NULL); + }); + + dispatch_sync(queue, ^{ + /* upgrade configuration from emir, ignore all error since we might not be able to write to */ + if (::access(visibleSecurityFlagFile, F_OK) == 0) { + try { + setAssessment(true); + ::unlink(visibleSecurityFlagFile); + } catch (...) { + } + enabled = true; + return; + } + + try { + Dictionary * prefsDict = Dictionary::CreateDictionary(prefsFile); + if (prefsDict == NULL) + return; + + CFStringRef value = prefsDict->getStringValue(SP_ENABLE_KEY); + if (value && CFStringCompare(value, SP_DISABLED, 0) == 0) + enabled = false; + else + enabled = true; + delete prefsDict; + } catch(...) { + } + }); + + return !enabled; +} + +void setAssessment(bool masterSwitch) +{ + MutableDictionary *prefsDict = MutableDictionary::CreateMutableDictionary(prefsFile); + if (prefsDict == NULL) + prefsDict = new MutableDictionary::MutableDictionary(); + prefsDict->setValue(SP_ENABLE_KEY, masterSwitch ? SP_ENABLED : SP_DISABLED); + prefsDict->writePlistToFile(prefsFile); + delete prefsDict; + + /* make sure permissions is right */ + ::chmod(prefsFile, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + + notify_post(kNotifySecAssessmentMasterSwitch); +} + + +} // end namespace CodeSigning +} // end namespace Security diff --git a/libsecurity_codesigning/lib/policydb.h b/libsecurity_codesigning/lib/policydb.h new file mode 100644 index 00000000..643b4fe4 --- /dev/null +++ b/libsecurity_codesigning/lib/policydb.h @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2011-2012 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, 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_POLICYDB +#define _H_POLICYDB + +#include +#include +#include +#include + +namespace Security { +namespace CodeSigning { + + +namespace SQLite = SQLite3; + + +static const char defaultDatabase[] = "/var/db/SystemPolicy"; +static const char visibleSecurityFlagFile[] = "/var/db/.sp_visible"; /* old duchess/emir style configration */ +static const char prefsFile[] = "/var/db/SystemPolicy-prefs.plist"; + +static const char gkeAuthFile[] = "/var/db/gke.auth"; +static const char gkeSigsFile[] = "/var/db/gke.sigs"; +static const unsigned int gkeCheckInterval = 60; // seconds + + +// +// We use Julian dates in the database, because SQLite understands them well and they convert easily to/from CFAbsoluteTime +// +static const double never = 5000000; // canonical "never" julian date (an arbitrary point in the year 8977) +static const double julianBase = 2451910.5; // julian date of CFAbsoluteTime epoch + +static inline double dateToJulian(CFDateRef time) +{ return CFDateGetAbsoluteTime(time) / 86400.0 + julianBase; } + +static inline CFDateRef julianToDate(double julian) +{ return CFDateCreate(NULL, (julian - julianBase) * 86400); } + + +typedef SHA1::SDigest ObjectHash; + + +typedef uint AuthorityType; +enum { + kAuthorityInvalid = 0, // not a valid authority type + kAuthorityExecute = 1, // authorizes launch and execution + kAuthorityInstall = 2, // authorizes installation + kAuthorityOpenDoc = 3, // authorizes opening of documents +}; + + +// +// Defined flags for authority flags column +// +enum { + kAuthorityFlagVirtual = 0x0001, // virtual rule (anchoring object records) + kAuthorityFlagDefault = 0x0002, // rule is part of the original default set + kAuthorityFlagInhibitCache = 0x0004, // never cache outcome of this rule + kAuthorityFlagWhitelist = 0x1000, // whitelist override +}; + + +// +// Mapping/translation to/from API space +// +AuthorityType typeFor(CFDictionaryRef context, AuthorityType type = kAuthorityInvalid); +CFStringRef typeNameFor(AuthorityType type) + CF_RETURNS_RETAINED; + + +// +// An open policy database. +// Usually read-only, but can be opened for write by privileged callers. +// This is a translucent wrapper around SQLite::Database; the caller +// is expected to work with statement rows. +// +class PolicyDatabase : public SQLite::Database { +public: + PolicyDatabase(const char *path = NULL, int flags = SQLITE_OPEN_READONLY); + virtual ~PolicyDatabase(); + +public: + bool checkCache(CFURLRef path, AuthorityType type, CFMutableDictionaryRef result); + +public: + void purgeAuthority(); + void purgeObjects(); + void purgeObjects(double priority);// + + void upgradeDatabase(); + std::string featureLevel(const char *feature); + bool hasFeature(const char *feature) { return !featureLevel(feature).empty(); } + void addFeature(const char *feature, const char *value, const char *remarks); + void simpleFeature(const char *feature, const char *sql); + void simpleFeature(const char *feature, void (^perform)()); + + void installExplicitSet(const char *auth, const char *sigs); + +private: + time_t mLastExplicitCheck; +}; + + +// +// Check the system-wide overriding flag file +// +bool overrideAssessment(); +void setAssessment(bool masterSwitch); + +} // end namespace CodeSigning +} // end namespace Security + +#endif //_H_POLICYDB diff --git a/libsecurity_codesigning/lib/policyengine.cpp b/libsecurity_codesigning/lib/policyengine.cpp new file mode 100644 index 00000000..4cae2d96 --- /dev/null +++ b/libsecurity_codesigning/lib/policyengine.cpp @@ -0,0 +1,886 @@ +/* + * Copyright (c) 2011-2012 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +#include "policyengine.h" +#include "xar++.h" +#include "quarantine++.h" +#include "codesigning_dtrace.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "SecCodePriv.h" +#undef check // Macro! Yech. + +extern "C" { +#include +} + + +namespace Security { +namespace CodeSigning { + +static const double NEGATIVE_HOLD = 60.0/86400; // 60 seconds to cache negative outcomes + +static const char RECORDER_DIR[] = "/tmp/gke-"; // recorder mode destination for detached signatures +enum { + recorder_code_untrusted = 0, // signed but untrusted + recorder_code_adhoc = 1, // unsigned; signature recorded + recorder_code_unable = 2, // unsigned; unable to record signature +}; + + +static void authorizeUpdate(SecAssessmentFlags flags, CFDictionaryRef context); +static void normalizeTarget(CFRef &target, CFDictionary &context, bool signUnsigned = false); +static bool codeInvalidityExceptions(SecStaticCodeRef code, CFMutableDictionaryRef result); +static CFTypeRef installerPolicy() CF_RETURNS_RETAINED; + + +// +// Core structure +// +PolicyEngine::PolicyEngine() + : PolicyDatabase(NULL, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE) +{ +} + +PolicyEngine::~PolicyEngine() +{ } + + +// +// Top-level evaluation driver +// +void PolicyEngine::evaluate(CFURLRef path, AuthorityType type, SecAssessmentFlags flags, CFDictionaryRef context, CFMutableDictionaryRef result) +{ + switch (type) { + case kAuthorityExecute: + evaluateCode(path, kAuthorityExecute, flags, context, result); + break; + case kAuthorityInstall: + evaluateInstall(path, flags, context, result); + break; + case kAuthorityOpenDoc: + evaluateDocOpen(path, flags, context, result); + break; + default: + MacOSError::throwMe(errSecCSInvalidAttributeValues); + break; + } +} + + +// +// Executable code. +// Read from disk, evaluate properly, cache as indicated. The whole thing, so far. +// +void PolicyEngine::evaluateCode(CFURLRef path, AuthorityType type, SecAssessmentFlags flags, CFDictionaryRef context, CFMutableDictionaryRef result) +{ + FileQuarantine qtn(cfString(path).c_str()); + if (qtn.flag(QTN_FLAG_HARD)) + MacOSError::throwMe(errSecCSFileHardQuarantined); + + CFRef code; + MacOSError::check(SecStaticCodeCreateWithPath(path, kSecCSDefaultFlags, &code.aref())); + + const SecCSFlags validationFlags = kSecCSEnforceRevocationChecks; + + SQLite::Statement query(*this, + "SELECT allow, requirement, id, label, expires, flags, disabled FROM scan_authority" + " WHERE type = :type" + " ORDER BY priority DESC;"); + query.bind(":type").integer(type); + SQLite3::int64 latentID = 0; // first (highest priority) disabled matching ID + std::string latentLabel; // ... and associated label, if any + while (query.nextRow()) { + bool allow = int(query[0]); + const char *reqString = query[1]; + SQLite3::int64 id = query[2]; + const char *label = query[3]; + double expires = query[4]; + sqlite3_int64 ruleFlags = query[5]; + SQLite3::int64 disabled = query[6]; + + CFRef requirement; + MacOSError::check(SecRequirementCreateWithString(CFTempString(reqString), kSecCSDefaultFlags, &requirement.aref())); + OSStatus rc = SecStaticCodeCheckValidity(code, validationFlags, requirement); + + if (rc == errSecCSUnsigned) { + try { + // ad-hoc sign the code and attach the signature + CFRef signature = CFDataCreateMutable(NULL, 0); + CFTemp arguments("{%O=%O, %O=#N}", kSecCodeSignerDetached, signature.get(), kSecCodeSignerIdentity); + CFRef signer; + MacOSError::check(SecCodeSignerCreate(arguments, kSecCSDefaultFlags, &signer.aref())); + MacOSError::check(SecCodeSignerAddSignature(signer, code, kSecCSDefaultFlags)); + MacOSError::check(SecCodeSetDetachedSignature(code, signature, kSecCSDefaultFlags)); + + // if we're in GKE recording mode, save that signature and report its location + if (SYSPOLICY_RECORDER_MODE_ENABLED()) { + int status = recorder_code_unable; // ephemeral signature (not recorded) + if (geteuid() == 0) { + CFRef uuid = CFUUIDCreate(NULL); + std::string sigfile = RECORDER_DIR + cfStringRelease(CFUUIDCreateString(NULL, uuid)) + ".tsig"; + try { + UnixPlusPlus::AutoFileDesc fd(sigfile, O_WRONLY | O_CREAT); + fd.write(CFDataGetBytePtr(signature), CFDataGetLength(signature)); + status = recorder_code_adhoc; // recorded signature + SYSPOLICY_RECORDER_MODE_ADHOC_PATH(cfString(path).c_str(), type, sigfile.c_str()); + } catch (...) { } + } + + // now report the D probe itself + CFRef info; + MacOSError::check(SecCodeCopySigningInformation(code, kSecCSDefaultFlags, &info.aref())); + CFDataRef cdhash = CFDataRef(CFDictionaryGetValue(info, kSecCodeInfoUnique)); + SYSPOLICY_RECORDER_MODE(cfString(path).c_str(), type, "", + cdhash ? CFDataGetBytePtr(cdhash) : NULL, status); + } + + // rerun the validation to update state + rc = SecStaticCodeCheckValidity(code, validationFlags | kSecCSBasicValidateOnly, requirement); + } catch (...) { } + } + + switch (rc) { + case noErr: // well signed and satisfies requirement... + break; // ... continue below + case errSecCSSignatureFailed: + if (!codeInvalidityExceptions(code, result)) { + if (SYSPOLICY_ASSESS_OUTCOME_BROKEN_ENABLED()) + SYSPOLICY_ASSESS_OUTCOME_BROKEN(cfString(path).c_str(), type, false); + MacOSError::throwMe(rc); + } + if (SYSPOLICY_ASSESS_OUTCOME_BROKEN_ENABLED()) + SYSPOLICY_ASSESS_OUTCOME_BROKEN(cfString(path).c_str(), type, true); + // treat as unsigned to fix problems in the field + case errSecCSUnsigned: + cfadd(result, "{%O=#F}", kSecAssessmentAssessmentVerdict); + addAuthority(result, "no usable signature"); + return; + case errSecCSReqFailed: // requirement missed, but otherwise okay + continue; + default: // broken in some way; all tests will fail like this so bail out + MacOSError::throwMe(rc); + } + if (disabled) { + if (latentID == 0) { + latentID = id; + if (label) + latentLabel = label; + } + continue; // the loop + } + + CFRef info; // as needed + if (flags & kSecAssessmentFlagRequestOrigin) { + if (!info) + MacOSError::check(SecCodeCopySigningInformation(code, kSecCSSigningInformation, &info.aref())); + if (CFArrayRef chain = CFArrayRef(CFDictionaryGetValue(info, kSecCodeInfoCertificates))) + setOrigin(chain, result); + } + if (!(ruleFlags & kAuthorityFlagInhibitCache) && !(flags & kSecAssessmentFlagNoCache)) { // cache inhibit + if (!info) + MacOSError::check(SecCodeCopySigningInformation(code, kSecCSSigningInformation, &info.aref())); + if (SecTrustRef trust = SecTrustRef(CFDictionaryGetValue(info, kSecCodeInfoTrust))) { + CFRef xinfo; + MacOSError::check(SecTrustCopyExtendedResult(trust, &xinfo.aref())); + if (CFDateRef limit = CFDateRef(CFDictionaryGetValue(xinfo, kSecTrustExpirationDate))) { + this->recordOutcome(code, allow, type, min(expires, dateToJulian(limit)), id); + } + } + } + if (allow) { + if (SYSPOLICY_ASSESS_OUTCOME_ACCEPT_ENABLED()) { + if (!info) + MacOSError::check(SecCodeCopySigningInformation(code, kSecCSSigningInformation, &info.aref())); + CFDataRef cdhash = CFDataRef(CFDictionaryGetValue(info, kSecCodeInfoUnique)); + SYSPOLICY_ASSESS_OUTCOME_ACCEPT(cfString(path).c_str(), type, label, cdhash ? CFDataGetBytePtr(cdhash) : NULL); + } + } else { + if (SYSPOLICY_ASSESS_OUTCOME_DENY_ENABLED() || SYSPOLICY_RECORDER_MODE_ENABLED()) { + if (!info) + MacOSError::check(SecCodeCopySigningInformation(code, kSecCSSigningInformation, &info.aref())); + CFDataRef cdhash = CFDataRef(CFDictionaryGetValue(info, kSecCodeInfoUnique)); + std::string cpath = cfString(path); + const void *hashp = cdhash ? CFDataGetBytePtr(cdhash) : NULL; + SYSPOLICY_ASSESS_OUTCOME_DENY(cpath.c_str(), type, label, hashp); + SYSPOLICY_RECORDER_MODE(cpath.c_str(), type, label, hashp, recorder_code_untrusted); + } + } + cfadd(result, "{%O=%B}", kSecAssessmentAssessmentVerdict, allow); + addAuthority(result, label, id); + return; + } + + // no applicable authority. Deny by default + CFRef info; + MacOSError::check(SecCodeCopySigningInformation(code, kSecCSSigningInformation, &info.aref())); + if (flags & kSecAssessmentFlagRequestOrigin) { + if (CFArrayRef chain = CFArrayRef(CFDictionaryGetValue(info, kSecCodeInfoCertificates))) + setOrigin(chain, result); + } + if (SYSPOLICY_ASSESS_OUTCOME_DEFAULT_ENABLED() || SYSPOLICY_RECORDER_MODE_ENABLED()) { + CFDataRef cdhash = CFDataRef(CFDictionaryGetValue(info, kSecCodeInfoUnique)); + const void *hashp = cdhash ? CFDataGetBytePtr(cdhash) : NULL; + std::string cpath = cfString(path); + SYSPOLICY_ASSESS_OUTCOME_DEFAULT(cpath.c_str(), type, latentLabel.c_str(), hashp); + SYSPOLICY_RECORDER_MODE(cpath.c_str(), type, latentLabel.c_str(), hashp, 0); + } + if (!(flags & kSecAssessmentFlagNoCache)) + this->recordOutcome(code, false, type, this->julianNow() + NEGATIVE_HOLD, latentID); + cfadd(result, "{%O=%B}", kSecAssessmentAssessmentVerdict, false); + addAuthority(result, latentLabel.c_str(), latentID); +} + + +// +// Installer archive. +// Hybrid policy: If we detect an installer signature, use and validate that. +// If we don't, check for a code signature instead. +// +void PolicyEngine::evaluateInstall(CFURLRef path, SecAssessmentFlags flags, CFDictionaryRef context, CFMutableDictionaryRef result) +{ + const AuthorityType type = kAuthorityInstall; + + Xar xar(cfString(path).c_str()); + if (!xar) { + // follow the code signing path + evaluateCode(path, type, flags, context, result); + return; + } + + SQLite3::int64 latentID = 0; // first (highest priority) disabled matching ID + std::string latentLabel; // ... and associated label, if any + if (!xar.isSigned()) { + // unsigned xar + if (SYSPOLICY_ASSESS_OUTCOME_UNSIGNED_ENABLED()) + SYSPOLICY_ASSESS_OUTCOME_UNSIGNED(cfString(path).c_str(), type); + cfadd(result, "{%O=%B}", kSecAssessmentAssessmentVerdict, false); + addAuthority(result, "no usable signature"); + return; + } + if (CFRef certs = xar.copyCertChain()) { + CFRef policy = installerPolicy(); + CFRef trust; + MacOSError::check(SecTrustCreateWithCertificates(certs, policy, &trust.aref())); +// MacOSError::check(SecTrustSetAnchorCertificates(trust, cfEmptyArray())); // no anchors + MacOSError::check(SecTrustSetOptions(trust, kSecTrustOptionAllowExpired | kSecTrustOptionImplicitAnchors)); + + SecTrustResultType trustResult; + MacOSError::check(SecTrustEvaluate(trust, &trustResult)); + CFRef chain; + CSSM_TP_APPLE_EVIDENCE_INFO *info; + MacOSError::check(SecTrustGetResult(trust, &trustResult, &chain.aref(), &info)); + + if (flags & kSecAssessmentFlagRequestOrigin) + setOrigin(chain, result); + + switch (trustResult) { + case kSecTrustResultProceed: + case kSecTrustResultUnspecified: + break; + default: + { + OSStatus rc; + MacOSError::check(SecTrustGetCssmResultCode(trust, &rc)); + MacOSError::throwMe(rc); + } + } + + SQLite::Statement query(*this, + "SELECT allow, requirement, id, label, flags, disabled FROM scan_authority" + " WHERE type = :type" + " ORDER BY priority DESC;"); + query.bind(":type").integer(type); + while (query.nextRow()) { + bool allow = int(query[0]); + const char *reqString = query[1]; + SQLite3::int64 id = query[2]; + const char *label = query[3]; + //sqlite_uint64 ruleFlags = query[4]; + SQLite3::int64 disabled = query[5]; + + CFRef requirement; + MacOSError::check(SecRequirementCreateWithString(CFTempString(reqString), kSecCSDefaultFlags, &requirement.aref())); + switch (OSStatus rc = SecRequirementEvaluate(requirement, chain, NULL, kSecCSDefaultFlags)) { + case noErr: // success + break; + case errSecCSReqFailed: // requirement missed, but otherwise okay + continue; + default: // broken in some way; all tests will fail like this so bail out + MacOSError::throwMe(rc); + } + if (disabled) { + if (latentID == 0) { + latentID = id; + if (label) + latentLabel = label; + } + continue; // the loop + } + + if (SYSPOLICY_ASSESS_OUTCOME_ACCEPT_ENABLED() || SYSPOLICY_ASSESS_OUTCOME_DENY_ENABLED()) { + if (allow) + SYSPOLICY_ASSESS_OUTCOME_ACCEPT(cfString(path).c_str(), type, label, NULL); + else + SYSPOLICY_ASSESS_OUTCOME_DENY(cfString(path).c_str(), type, label, NULL); + } + + // not adding to the object cache - we could, but it's not likely to be worth it + cfadd(result, "{%O=%B}", kSecAssessmentAssessmentVerdict, allow); + addAuthority(result, label, id); + return; + } + } + if (SYSPOLICY_ASSESS_OUTCOME_DEFAULT_ENABLED()) + SYSPOLICY_ASSESS_OUTCOME_DEFAULT(cfString(path).c_str(), type, latentLabel.c_str(), NULL); + + // no applicable authority. Deny by default + cfadd(result, "{%O=#F}", kSecAssessmentAssessmentVerdict); + addAuthority(result, latentLabel.c_str(), latentID); +} + + +// +// Create a suitable policy array for verification of installer signatures. +// +static SecPolicyRef makeCRLPolicy() +{ + CFRef policy; + MacOSError::check(SecPolicyCopy(CSSM_CERT_X_509v3, &CSSMOID_APPLE_TP_REVOCATION_CRL, &policy.aref())); + CSSM_APPLE_TP_CRL_OPTIONS options; + memset(&options, 0, sizeof(options)); + options.Version = CSSM_APPLE_TP_CRL_OPTS_VERSION; + options.CrlFlags = CSSM_TP_ACTION_FETCH_CRL_FROM_NET | CSSM_TP_ACTION_CRL_SUFFICIENT; + CSSM_DATA optData = { sizeof(options), (uint8 *)&options }; + MacOSError::check(SecPolicySetValue(policy, &optData)); + return policy.yield(); +} + +static SecPolicyRef makeOCSPPolicy() +{ + CFRef policy; + MacOSError::check(SecPolicyCopy(CSSM_CERT_X_509v3, &CSSMOID_APPLE_TP_REVOCATION_OCSP, &policy.aref())); + CSSM_APPLE_TP_OCSP_OPTIONS options; + memset(&options, 0, sizeof(options)); + options.Version = CSSM_APPLE_TP_OCSP_OPTS_VERSION; + options.Flags = CSSM_TP_ACTION_OCSP_SUFFICIENT; + CSSM_DATA optData = { sizeof(options), (uint8 *)&options }; + MacOSError::check(SecPolicySetValue(policy, &optData)); + return policy.yield(); +} + +static CFTypeRef installerPolicy() +{ + CFRef base = SecPolicyCreateBasicX509(); + CFRef crl = makeCRLPolicy(); + CFRef ocsp = makeOCSPPolicy(); + return makeCFArray(3, base.get(), crl.get(), ocsp.get()); +} + + +// +// LaunchServices-layer document open. +// We don't cache those at present. If we ever do, we need to authenticate CoreServicesUIAgent as the source of its risk assessment. +// +void PolicyEngine::evaluateDocOpen(CFURLRef path, SecAssessmentFlags flags, CFDictionaryRef context, CFMutableDictionaryRef result) +{ + if (context) { + if (CFStringRef riskCategory = CFStringRef(CFDictionaryGetValue(context, kLSDownloadRiskCategoryKey))) { + FileQuarantine qtn(cfString(path).c_str()); + + if (CFEqual(riskCategory, kLSRiskCategorySafe) + || CFEqual(riskCategory, kLSRiskCategoryNeutral) + || CFEqual(riskCategory, kLSRiskCategoryUnknown) + || CFEqual(riskCategory, kLSRiskCategoryMayContainUnsafeExecutable)) { + cfadd(result, "{%O=#T}", kSecAssessmentAssessmentVerdict); + addAuthority(result, "_XProtect"); + } else if (qtn.flag(QTN_FLAG_HARD)) { + MacOSError::throwMe(errSecCSFileHardQuarantined); + } else if (qtn.flag(QTN_FLAG_ASSESSMENT_OK)) { + cfadd(result, "{%O=#T}", kSecAssessmentAssessmentVerdict); + addAuthority(result, "Prior Assessment"); + } else { + cfadd(result, "{%O=#F}", kSecAssessmentAssessmentVerdict); + addAuthority(result, "_XProtect"); + } + addToAuthority(result, kLSDownloadRiskCategoryKey, riskCategory); + return; + } + } + // insufficient information from LS - deny by default + cfadd(result, "{%O=#F}", kSecAssessmentAssessmentVerdict); + addAuthority(result, "Insufficient Context"); +} + + +// +// Result-creation helpers +// +void PolicyEngine::addAuthority(CFMutableDictionaryRef parent, const char *label, SQLite::int64 row, CFTypeRef cacheInfo) +{ + CFRef auth = makeCFMutableDictionary(); + if (label && label[0]) + cfadd(auth, "{%O=%s}", kSecAssessmentAssessmentSource, label); + if (row) + CFDictionaryAddValue(auth, kSecAssessmentAssessmentAuthorityRow, CFTempNumber(row)); + if (overrideAssessment()) + CFDictionaryAddValue(auth, kSecAssessmentAssessmentAuthorityOverride, kDisabledOverride); + if (cacheInfo) + CFDictionaryAddValue(auth, kSecAssessmentAssessmentFromCache, cacheInfo); + CFDictionaryAddValue(parent, kSecAssessmentAssessmentAuthority, auth); +} + +void PolicyEngine::addToAuthority(CFMutableDictionaryRef parent, CFStringRef key, CFTypeRef value) +{ + CFMutableDictionaryRef authority = CFMutableDictionaryRef(CFDictionaryGetValue(parent, kSecAssessmentAssessmentAuthority)); + assert(authority); + CFDictionaryAddValue(authority, key, value); +} + + +// +// Add a rule to the policy database +// +CFDictionaryRef PolicyEngine::add(CFTypeRef inTarget, AuthorityType type, SecAssessmentFlags flags, CFDictionaryRef context) +{ + // default type to execution + if (type == kAuthorityInvalid) + type = kAuthorityExecute; + + authorizeUpdate(flags, context); + CFDictionary ctx(context, errSecCSInvalidAttributeValues); + CFCopyRef target = inTarget; + CFRef bookmark = NULL; + + switch (type) { + case kAuthorityExecute: + normalizeTarget(target, ctx, true); + // bookmarks are untrusted and just a hint to callers + bookmark = ctx.get(kSecAssessmentRuleKeyBookmark); + break; + case kAuthorityInstall: + if (inTarget && CFGetTypeID(inTarget) == CFURLGetTypeID()) { + // no good way to turn an installer file into a requirement. Pretend to succeeed so caller proceeds + return cfmake("{%O=%O}", kSecAssessmentAssessmentAuthorityOverride, CFSTR("virtual install")); + } + break; + case kAuthorityOpenDoc: + // handle document-open differently: use quarantine flags for whitelisting + if (!target || CFGetTypeID(target) != CFURLGetTypeID()) // can only "add" file paths + MacOSError::throwMe(errSecCSInvalidObjectRef); + try { + std::string spath = cfString(target.as()); + FileQuarantine qtn(spath.c_str()); + qtn.setFlag(QTN_FLAG_ASSESSMENT_OK); + qtn.applyTo(spath.c_str()); + } catch (const CommonError &error) { + // could not set quarantine flag - report qualified success + return cfmake("{%O=%O,'assessment:error'=%d}", + kSecAssessmentAssessmentAuthorityOverride, CFSTR("error setting quarantine"), error.osStatus()); + } catch (...) { + return cfmake("{%O=%O}", kSecAssessmentAssessmentAuthorityOverride, CFSTR("unable to set quarantine")); + } + return NULL; + } + + // if we now have anything else, we're busted + if (!target || CFGetTypeID(target) != SecRequirementGetTypeID()) + MacOSError::throwMe(errSecCSInvalidObjectRef); + + double priority = 0; + string label; + bool allow = true; + double expires = never; + string remarks; + + if (CFNumberRef pri = ctx.get(kSecAssessmentUpdateKeyPriority)) + CFNumberGetValue(pri, kCFNumberDoubleType, &priority); + if (CFStringRef lab = ctx.get(kSecAssessmentUpdateKeyLabel)) + label = cfString(lab); + if (CFDateRef time = ctx.get(kSecAssessmentUpdateKeyExpires)) + // we're using Julian dates here; convert from CFDate + expires = dateToJulian(time); + if (CFBooleanRef allowing = ctx.get(kSecAssessmentUpdateKeyAllow)) + allow = allowing == kCFBooleanTrue; + if (CFStringRef rem = ctx.get(kSecAssessmentUpdateKeyRemarks)) + remarks = cfString(rem); + + CFRef requirementText; + MacOSError::check(SecRequirementCopyString(target.as(), kSecCSDefaultFlags, &requirementText.aref())); + SQLite::Transaction xact(*this, SQLite3::Transaction::deferred, "add_rule"); + SQLite::Statement insert(*this, + "INSERT INTO authority (type, allow, requirement, priority, label, expires, remarks)" + " VALUES (:type, :allow, :requirement, :priority, :label, :expires, :remarks);"); + insert.bind(":type").integer(type); + insert.bind(":allow").integer(allow); + insert.bind(":requirement") = requirementText.get(); + insert.bind(":priority") = priority; + if (!label.empty()) + insert.bind(":label") = label; + insert.bind(":expires") = expires; + if (!remarks.empty()) + insert.bind(":remarks") = remarks; + insert.execute(); + SQLite::int64 newRow = this->lastInsert(); + if (bookmark) { + SQLite::Statement bi(*this, "INSERT INTO bookmarkhints (bookmark, authority) VALUES (:bookmark, :authority)"); + bi.bind(":bookmark") = CFDataRef(bookmark); + bi.bind(":authority").integer(newRow); + bi.execute(); + } + this->purgeObjects(priority); + xact.commit(); + notify_post(kNotifySecAssessmentUpdate); + return cfmake("{%O=%d}", kSecAssessmentUpdateKeyRow, newRow); +} + + +CFDictionaryRef PolicyEngine::remove(CFTypeRef target, AuthorityType type, SecAssessmentFlags flags, CFDictionaryRef context) +{ + if (type == kAuthorityOpenDoc) { + // handle document-open differently: use quarantine flags for whitelisting + authorizeUpdate(flags, context); + if (!target || CFGetTypeID(target) != CFURLGetTypeID()) + MacOSError::throwMe(errSecCSInvalidObjectRef); + std::string spath = cfString(CFURLRef(target)).c_str(); + FileQuarantine qtn(spath.c_str()); + qtn.clearFlag(QTN_FLAG_ASSESSMENT_OK); + qtn.applyTo(spath.c_str()); + return NULL; + } + return manipulateRules("DELETE FROM authority", target, type, flags, context); +} + +CFDictionaryRef PolicyEngine::enable(CFTypeRef target, AuthorityType type, SecAssessmentFlags flags, CFDictionaryRef context) +{ + return manipulateRules("UPDATE authority SET disabled = 0", target, type, flags, context); +} + +CFDictionaryRef PolicyEngine::disable(CFTypeRef target, AuthorityType type, SecAssessmentFlags flags, CFDictionaryRef context) +{ + return manipulateRules("UPDATE authority SET disabled = 1", target, type, flags, context); +} + +CFDictionaryRef PolicyEngine::find(CFTypeRef target, AuthorityType type, SecAssessmentFlags flags, CFDictionaryRef context) +{ + SQLite::Statement query(*this); + selectRules(query, "SELECT scan_authority.id, scan_authority.type, scan_authority.requirement, scan_authority.allow, scan_authority.label, scan_authority.priority, scan_authority.remarks, scan_authority.expires, scan_authority.disabled, bookmarkhints.bookmark FROM scan_authority LEFT OUTER JOIN bookmarkhints ON scan_authority.id = bookmarkhints.authority", + "scan_authority", target, type, flags, context, + " ORDER BY priority DESC"); + CFRef found = makeCFMutableArray(0); + while (query.nextRow()) { + SQLite::int64 id = query[0]; + int type = int(query[1]); + const char *requirement = query[2]; + int allow = int(query[3]); + const char *label = query[4]; + double priority = query[5]; + const char *remarks = query[6]; + double expires = query[7]; + int disabled = int(query[8]); + CFRef bookmark = query[9].data(); + CFRef rule = makeCFMutableDictionary(5, + kSecAssessmentRuleKeyID, CFTempNumber(id).get(), + kSecAssessmentRuleKeyType, CFRef(typeNameFor(type)).get(), + kSecAssessmentRuleKeyRequirement, CFTempString(requirement).get(), + kSecAssessmentRuleKeyAllow, allow ? kCFBooleanTrue : kCFBooleanFalse, + kSecAssessmentRuleKeyPriority, CFTempNumber(priority).get() + ); + if (label) + CFDictionaryAddValue(rule, kSecAssessmentRuleKeyLabel, CFTempString(label)); + if (remarks) + CFDictionaryAddValue(rule, kSecAssessmentRuleKeyRemarks, CFTempString(remarks)); + if (expires != never) + CFDictionaryAddValue(rule, kSecAssessmentRuleKeyExpires, CFRef(julianToDate(expires))); + if (disabled) + CFDictionaryAddValue(rule, kSecAssessmentRuleKeyDisabled, CFTempNumber(disabled)); + if (bookmark) + CFDictionaryAddValue(rule, kSecAssessmentRuleKeyBookmark, bookmark); + CFArrayAppendValue(found, rule); + } + if (CFArrayGetCount(found) == 0) + MacOSError::throwMe(errSecCSNoMatches); + return cfmake("{%O=%O}", kSecAssessmentUpdateKeyFound, found.get()); +} + + +CFDictionaryRef PolicyEngine::update(CFTypeRef target, SecAssessmentFlags flags, CFDictionaryRef context) +{ + AuthorityType type = typeFor(context, kAuthorityInvalid); + CFStringRef edit = CFStringRef(CFDictionaryGetValue(context, kSecAssessmentContextKeyUpdate)); + CFDictionaryRef result; + if (CFEqual(edit, kSecAssessmentUpdateOperationAdd)) + result = this->add(target, type, flags, context); + else if (CFEqual(edit, kSecAssessmentUpdateOperationRemove)) + result = this->remove(target, type, flags, context); + else if (CFEqual(edit, kSecAssessmentUpdateOperationEnable)) + result = this->enable(target, type, flags, context); + else if (CFEqual(edit, kSecAssessmentUpdateOperationDisable)) + result = this->disable(target, type, flags, context); + else if (CFEqual(edit, kSecAssessmentUpdateOperationFind)) + result = this->find(target, type, flags, context); + else + MacOSError::throwMe(errSecCSInvalidAttributeValues); + if (result == NULL) + result = makeCFDictionary(0); // success, no details + return result; +} + + +// +// Construct and prepare an SQL query on the authority table, operating on some set of existing authority records. +// In essence, this appends a suitable WHERE clause to the stanza passed and prepares it on the statement given. +// +void PolicyEngine::selectRules(SQLite::Statement &action, std::string phrase, std::string table, + CFTypeRef inTarget, AuthorityType type, SecAssessmentFlags flags, CFDictionaryRef context, std::string suffix /* = "" */) +{ + CFDictionary ctx(context, errSecCSInvalidAttributeValues); + CFCopyRef target = inTarget; + normalizeTarget(target, ctx); + + string label; + if (CFStringRef lab = ctx.get(kSecAssessmentUpdateKeyLabel)) + label = cfString(CFStringRef(lab)); + + if (!target) { + if (label.empty()) { + if (type == kAuthorityInvalid) { + action.query(phrase + suffix); + } else { + action.query(phrase + " WHERE " + table + ".type = :type" + suffix); + action.bind(":type").integer(type); + } + } else { // have label + if (type == kAuthorityInvalid) { + action.query(phrase + " WHERE " + table + ".label = :label" + suffix); + } else { + action.query(phrase + " WHERE " + table + ".type = :type AND " + table + ".label = :label" + suffix); + action.bind(":type").integer(type); + } + action.bind(":label") = label; + } + } else if (CFGetTypeID(target) == CFNumberGetTypeID()) { + action.query(phrase + " WHERE " + table + ".id = :id" + suffix); + action.bind(":id").integer(cfNumber(target.as())); + } else if (CFGetTypeID(target) == SecRequirementGetTypeID()) { + if (type == kAuthorityInvalid) + type = kAuthorityExecute; + CFRef requirementText; + MacOSError::check(SecRequirementCopyString(target.as(), kSecCSDefaultFlags, &requirementText.aref())); + action.query(phrase + " WHERE " + table + ".type = :type AND " + table + ".requirement = :requirement" + suffix); + action.bind(":type").integer(type); + action.bind(":requirement") = requirementText.get(); + } else + MacOSError::throwMe(errSecCSInvalidObjectRef); +} + + +// +// Execute an atomic change to existing records in the authority table. +// +CFDictionaryRef PolicyEngine::manipulateRules(const std::string &stanza, + CFTypeRef inTarget, AuthorityType type, SecAssessmentFlags flags, CFDictionaryRef context) +{ + SQLite::Transaction xact(*this, SQLite3::Transaction::deferred, "rule_change"); + SQLite::Statement action(*this); + authorizeUpdate(flags, context); + selectRules(action, stanza, "authority", inTarget, type, flags, context); + action.execute(); + unsigned int changes = this->changes(); // latch change count + // We MUST purge objects with priority <= MAX(priority of any changed rules); + // but for now we just get lazy and purge them ALL. + if (changes) { + this->purgeObjects(1.0E100); + xact.commit(); + notify_post(kNotifySecAssessmentUpdate); + return cfmake("{%O=%d}", kSecAssessmentUpdateKeyCount, changes); + } + // no change; return an error + MacOSError::throwMe(errSecCSNoMatches); +} + + +// +// Fill in extra information about the originator of cryptographic credentials found - if any +// +void PolicyEngine::setOrigin(CFArrayRef chain, CFMutableDictionaryRef result) +{ + if (chain) + if (CFArrayGetCount(chain) > 0) + if (SecCertificateRef leaf = SecCertificateRef(CFArrayGetValueAtIndex(chain, 0))) + if (CFStringRef summary = SecCertificateCopyLongDescription(NULL, leaf, NULL)) { + CFDictionarySetValue(result, kSecAssessmentAssessmentOriginator, summary); + CFRelease(summary); + } +} + + +// +// Take an assessment outcome and record it in the object cache +// +void PolicyEngine::recordOutcome(SecStaticCodeRef code, bool allow, AuthorityType type, double expires, SQLite::int64 authority) +{ + CFRef info; + MacOSError::check(SecCodeCopySigningInformation(code, kSecCSDefaultFlags, &info.aref())); + CFDataRef cdHash = CFDataRef(CFDictionaryGetValue(info, kSecCodeInfoUnique)); + assert(cdHash); // was signed + CFRef path; + MacOSError::check(SecCodeCopyPath(code, kSecCSDefaultFlags, &path.aref())); + assert(expires); + SQLite::Transaction xact(*this, SQLite3::Transaction::deferred, "caching"); + SQLite::Statement insert(*this, + "INSERT OR REPLACE INTO object (type, allow, hash, expires, path, authority)" + " VALUES (:type, :allow, :hash, :expires, :path," + " CASE :authority WHEN 0 THEN (SELECT id FROM authority WHERE label = 'No Matching Rule') ELSE :authority END" + " );"); + insert.bind(":type").integer(type); + insert.bind(":allow").integer(allow); + insert.bind(":hash") = cdHash; + insert.bind(":expires") = expires; + insert.bind(":path") = cfString(path); + insert.bind(":authority").integer(authority); + insert.execute(); + xact.commit(); +} + + +// +// Perform update authorization processing. +// Throws an exception if authorization is denied. +// +static void authorizeUpdate(SecAssessmentFlags flags, CFDictionaryRef context) +{ + AuthorizationRef authorization = NULL; + + if (context) + if (CFTypeRef authkey = CFDictionaryGetValue(context, kSecAssessmentUpdateKeyAuthorization)) + if (CFGetTypeID(authkey) == CFDataGetTypeID()) { + CFDataRef authdata = CFDataRef(authkey); + MacOSError::check(AuthorizationCreateFromExternalForm((AuthorizationExternalForm *)CFDataGetBytePtr(authdata), &authorization)); + } + if (authorization == NULL) + MacOSError::check(AuthorizationCreate(NULL, NULL, kAuthorizationFlagDefaults, &authorization)); + + AuthorizationItem right[] = { + { "com.apple.security.assessment.update", 0, NULL, 0 } + }; + AuthorizationRights rights = { sizeof(right) / sizeof(right[0]), right }; + MacOSError::check(AuthorizationCopyRights(authorization, &rights, NULL, + kAuthorizationFlagExtendRights | kAuthorizationFlagInteractionAllowed, NULL)); + + MacOSError::check(AuthorizationFree(authorization, kAuthorizationFlagDefaults)); +} + + +// +// Perform common argument normalizations for update operations +// +static void normalizeTarget(CFRef &target, CFDictionary &context, bool signUnsigned) +{ + // turn CFURLs into (designated) SecRequirements + if (target && CFGetTypeID(target) == CFURLGetTypeID()) { + CFRef code; + MacOSError::check(SecStaticCodeCreateWithPath(target.as(), kSecCSDefaultFlags, &code.aref())); + switch (OSStatus rc = SecCodeCopyDesignatedRequirement(code, kSecCSDefaultFlags, (SecRequirementRef *)&target.aref())) { + case noErr: { + // use the *default* DR to avoid unreasonably wide DRs opening up Gatekeeper to attack + CFRef info; + MacOSError::check(SecCodeCopySigningInformation(code, kSecCSRequirementInformation, &info.aref())); + target = CFDictionaryGetValue(info, kSecCodeInfoImplicitDesignatedRequirement); + } + break; + case errSecCSUnsigned: + if (signUnsigned) { + // Ad-hoc sign the code temporarily so we can get its code requirement + CFRef signature = CFDataCreateMutable(NULL, 0); + CFRef signer; + CFTemp arguments("{%O=%O, %O=#N}", kSecCodeSignerDetached, signature.get(), kSecCodeSignerIdentity); + MacOSError::check(SecCodeSignerCreate(arguments, kSecCSDefaultFlags, &signer.aref())); + MacOSError::check(SecCodeSignerAddSignature(signer, code, kSecCSDefaultFlags)); + MacOSError::check(SecCodeSetDetachedSignature(code, signature, kSecCSDefaultFlags)); + MacOSError::check(SecCodeCopyDesignatedRequirement(code, kSecCSDefaultFlags, (SecRequirementRef *)&target.aref())); + break; + } + MacOSError::check(rc); + case errSecCSSignatureFailed: + // recover certain cases of broken signatures (well, try) + if (codeInvalidityExceptions(code, NULL)) { + // Ad-hoc sign the code in place (requiring a writable subject). This requires root privileges. + CFRef signer; + CFTemp arguments("{%O=#N}", kSecCodeSignerIdentity); + MacOSError::check(SecCodeSignerCreate(arguments, kSecCSDefaultFlags, &signer.aref())); + MacOSError::check(SecCodeSignerAddSignature(signer, code, kSecCSDefaultFlags)); + MacOSError::check(SecCodeCopyDesignatedRequirement(code, kSecCSDefaultFlags, (SecRequirementRef *)&target.aref())); + break; + } + MacOSError::check(rc); + default: + MacOSError::check(rc); + } + if (context.get(kSecAssessmentUpdateKeyRemarks) == NULL) { + // no explicit remarks; add one with the path + CFRef path; + MacOSError::check(SecCodeCopyPath(code, kSecCSDefaultFlags, &path.aref())); + CFMutableDictionaryRef dict = makeCFMutableDictionary(context.get()); + CFDictionaryAddValue(dict, kSecAssessmentUpdateKeyRemarks, CFTempString(cfString(path))); + context.take(dict); + } + } +} + + +// +// Process special overrides for invalidly signed code. +// This is the (hopefully minimal) concessions we make to keep hurting our customers +// for our own prior mistakes... +// +static bool codeInvalidityExceptions(SecStaticCodeRef code, CFMutableDictionaryRef result) +{ + if (OSAIsRecognizedExecutableURL) { + CFRef info; + MacOSError::check(SecCodeCopySigningInformation(code, kSecCSDefaultFlags, &info.aref())); + if (CFURLRef executable = CFURLRef(CFDictionaryGetValue(info, kSecCodeInfoMainExecutable))) { + SInt32 error; + if (OSAIsRecognizedExecutableURL(executable, &error)) { + if (result) + CFDictionaryAddValue(result, + kSecAssessmentAssessmentAuthorityOverride, CFSTR("ignoring known invalid applet signature")); + return true; + } + } + } + return false; +} + + +} // end namespace CodeSigning +} // end namespace Security diff --git a/libsecurity_codesigning/lib/policyengine.h b/libsecurity_codesigning/lib/policyengine.h new file mode 100644 index 00000000..7ae9bfc7 --- /dev/null +++ b/libsecurity_codesigning/lib/policyengine.h @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2011-2012 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, 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_POLICYENGINE +#define _H_POLICYENGINE + +#include "SecAssessment.h" +#include "policydb.h" +#include +#include +#include +#include +#include +#include + +namespace Security { +namespace CodeSigning { + + +typedef uint EngineOperation; +enum { + opInvalid = 0, + opEvaluate, + opAddAuthority, + opRemoveAuthority, +}; + + +class PolicyEngine : public PolicyDatabase { +public: + PolicyEngine(); + virtual ~PolicyEngine(); + +public: + void evaluate(CFURLRef path, AuthorityType type, SecAssessmentFlags flags, CFDictionaryRef context, CFMutableDictionaryRef result); + + CFDictionaryRef update(CFTypeRef target, SecAssessmentFlags flags, CFDictionaryRef context); + CFDictionaryRef add(CFTypeRef target, AuthorityType type, SecAssessmentFlags flags, CFDictionaryRef context); + CFDictionaryRef remove(CFTypeRef target, AuthorityType type, SecAssessmentFlags flags, CFDictionaryRef context); + CFDictionaryRef enable(CFTypeRef target, AuthorityType type, SecAssessmentFlags flags, CFDictionaryRef context); + CFDictionaryRef disable(CFTypeRef target, AuthorityType type, SecAssessmentFlags flags, CFDictionaryRef context); + CFDictionaryRef find(CFTypeRef target, AuthorityType type, SecAssessmentFlags flags, CFDictionaryRef context); + +public: + static void addAuthority(CFMutableDictionaryRef parent, const char *label, SQLite::int64 row = 0, CFTypeRef cacheInfo = NULL); + static void addToAuthority(CFMutableDictionaryRef parent, CFStringRef key, CFTypeRef value); + +private: + void evaluateCode(CFURLRef path, AuthorityType type, SecAssessmentFlags flags, CFDictionaryRef context, CFMutableDictionaryRef result); + void evaluateInstall(CFURLRef path, SecAssessmentFlags flags, CFDictionaryRef context, CFMutableDictionaryRef result); + void evaluateDocOpen(CFURLRef path, SecAssessmentFlags flags, CFDictionaryRef context, CFMutableDictionaryRef result); + + void selectRules(SQLite::Statement &action, std::string stanza, std::string table, + CFTypeRef inTarget, AuthorityType type, SecAssessmentFlags flags, CFDictionaryRef context, std::string suffix = ""); + CFDictionaryRef manipulateRules(const std::string &stanza, + CFTypeRef target, AuthorityType type, SecAssessmentFlags flags, CFDictionaryRef context); + + void setOrigin(CFArrayRef chain, CFMutableDictionaryRef result); + + void recordOutcome(SecStaticCodeRef code, bool allow, AuthorityType type, double expires, SQLite::int64 authority); +}; + + +} // end namespace CodeSigning +} // end namespace Security + +#endif //_H_POLICYENGINE diff --git a/libsecurity_codesigning/lib/quarantine++.cpp b/libsecurity_codesigning/lib/quarantine++.cpp new file mode 100644 index 00000000..866627d9 --- /dev/null +++ b/libsecurity_codesigning/lib/quarantine++.cpp @@ -0,0 +1,107 @@ +/* + * 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@ + */ + +// +// xar++ - interface to XAR-format archive files +// +#include "quarantine++.h" + + +namespace Security { +namespace CodeSigning { + + +// +// Check the int result of a qtn API call. +// If the error is "not quarantined," note in the object (no error). +// Other qtn-specific errors are arbitrarily mapped to ENOSYS (this isn't +// important enough to subclass CommonError). +// +void FileQuarantine::check(int err) +{ + switch (err) { + case 0: + mQuarantined = true; + break; + case QTN_NOT_QUARANTINED: + mQuarantined = false; + return; + default: // some flavor of quarantine-not-available + UnixError::throwMe(err); + } +} + + +FileQuarantine::~FileQuarantine() +{ + if (mQtn) + qtn_file_free(mQtn); +} + + +FileQuarantine::FileQuarantine(const char *path) +{ + if (!(mQtn = qtn_file_alloc())) + UnixError::throwMe(); + check(qtn_file_init_with_path(mQtn, path)); +} + +FileQuarantine::FileQuarantine(int fd) +{ + if (!(mQtn = qtn_file_alloc())) + UnixError::throwMe(); + check(qtn_file_init_with_fd(mQtn, fd)); +} + + +void FileQuarantine::setFlags(uint32_t flags) +{ + if (mQuarantined) + check(qtn_file_set_flags(mQtn, flags)); +} + +void FileQuarantine::setFlag(uint32_t flag) +{ + if (mQuarantined) + setFlags(flags() | flag); +} + +void FileQuarantine::clearFlag(uint32_t flag) +{ + if (mQuarantined) + setFlags(flags() & ~flag); +} + +void FileQuarantine::applyTo(const char *path) +{ + check(qtn_file_apply_to_path(mQtn, path)); +} + +void FileQuarantine::applyTo(int fd) +{ + check(qtn_file_apply_to_fd(mQtn, fd)); +} + + +} // end namespace CodeSigning +} // end namespace Security diff --git a/libsecurity_codesigning/lib/quarantine++.h b/libsecurity_codesigning/lib/quarantine++.h new file mode 100644 index 00000000..53c56091 --- /dev/null +++ b/libsecurity_codesigning/lib/quarantine++.h @@ -0,0 +1,77 @@ +/* + * 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@ + */ + +// +// quarantine++ - interface to XAR-format archive files +// +#ifndef _H_QUARANTINEPLUSPLUS +#define _H_QUARANTINEPLUSPLUS + +#include +#include + +extern "C" { +#include +} + +namespace Security { +namespace CodeSigning { + + +// +// A file quarantine object +// +class FileQuarantine { +public: + FileQuarantine(const char *path); + FileQuarantine(int fd); + virtual ~FileQuarantine(); + + uint32_t flags() const + { return qtn_file_get_flags(mQtn); } + bool flag(uint32_t f) const + { return this->flags() & f; } + + void setFlags(uint32_t flags); + void setFlag(uint32_t flag); + void clearFlag(uint32_t flag); + + void applyTo(const char *path); + void applyTo(int fd); + + operator bool() const { return mQtn != 0; } + bool quarantined() const { return mQuarantined; } + +private: + void check(int err); + +private: + qtn_file_t mQtn; // qtn handle + bool mQuarantined; // has quarantine information +}; + + +} // end namespace CodeSigning +} // end namespace Security + +#endif // !_H_QUARANTINEPLUSPLUS diff --git a/libsecurity_codesigning/lib/renum.cpp b/libsecurity_codesigning/lib/renum.cpp new file mode 100644 index 00000000..a5b8e78f --- /dev/null +++ b/libsecurity_codesigning/lib/renum.cpp @@ -0,0 +1,80 @@ +/* + * 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@ + */ + +// +// renum - enumerator for code (usually bundle) resources +// +#include "renum.h" +#include +#include + +namespace Security { +namespace CodeSigning { + +using namespace UnixPlusPlus; + + +ResourceEnumerator::ResourceEnumerator(string path) + : mPath(path) +{ + assert(!mPath.empty()); + const char * paths[2] = { path.c_str(), NULL }; + mFTS = fts_open((char * const *)paths, FTS_PHYSICAL | FTS_COMFOLLOW | FTS_NOCHDIR, NULL); + if (!mFTS) + UnixError::throwMe(); +} + +ResourceEnumerator::~ResourceEnumerator() +{ + checkError(fts_close(mFTS)); +} + + +FTSENT *ResourceEnumerator::next(string &path) +{ + while (FTSENT *ent = fts_read(mFTS)) { + switch (ent->fts_info) { + case FTS_F: + path = ent->fts_path + mPath.size() + 1; // skip prefix + "/" + return ent; + case FTS_D: + secdebug("rdirenum", "entering %s", ent->fts_path); + break; + case FTS_DP: + secdebug("rdirenum", "leaving %s", ent->fts_path); + break; + case FTS_SL: + secdebug("rdirenum", "symlink ignored: %s", ent->fts_path); + break; + default: + secdebug("rdirenum", "type %d (errno %d): %s", + ent->fts_info, ent->fts_errno, ent->fts_path); + break; + } + } + return NULL; +} + + +} // end namespace CodeSigning +} // end namespace Security diff --git a/libsecurity_codesigning/lib/renum.h b/libsecurity_codesigning/lib/renum.h new file mode 100644 index 00000000..1d40983c --- /dev/null +++ b/libsecurity_codesigning/lib/renum.h @@ -0,0 +1,58 @@ +/* + * 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@ + */ + +// +// renum - enumerator for code (usually bundle) resources +// +#ifndef _H_RENUM +#define _H_RENUM + +#include +#include + +namespace Security { +namespace CodeSigning { + + +// +// A ResourceEnumerator front-ends FTS to scan out relevant resource +// directory entries (ignoring irrelevant ones). +// It also returns canonical resource paths (relative to the resource directory). +// +class ResourceEnumerator { +public: + ResourceEnumerator(std::string path); + ~ResourceEnumerator(); + + FTSENT *next(std::string &path); + +private: + std::string mPath; + FTS *mFTS; +}; + + +} // end namespace CodeSigning +} // end namespace Security + +#endif // !_H_RENUM diff --git a/libsecurity_codesigning/lib/reqdumper.cpp b/libsecurity_codesigning/lib/reqdumper.cpp new file mode 100644 index 00000000..ceca1501 --- /dev/null +++ b/libsecurity_codesigning/lib/reqdumper.cpp @@ -0,0 +1,353 @@ +/* + * Copyright (c) 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@ + */ + +// +// reqdumper - Requirement un-parsing (disassembly) +// +#include "reqdumper.h" +#include // OID encoder +#include + +namespace Security { +namespace CodeSigning { + +using namespace UnixPlusPlus; + + +// +// Table of reserved words (keywords), generated by ANTLR +// +static const char * const keywords[] = { +#include "RequirementKeywords.h" + "", + NULL +}; + + +// +// Printf to established output channel +// +void Dumper::print(const char *format, ...) +{ + char buffer[256]; + va_list args; + va_start(args, format); + vsnprintf(buffer, sizeof(buffer), format, args); + va_end(args); + mOutput += buffer; +} + + +// +// Dump the underlying Requirement program +// +void Dumper::dump() +{ + this->expr(); + + // remove any initial space + if (mOutput[0] == ' ') + mOutput = mOutput.substr(1); +} + + +// +// Dump an entire Requirements set, using temporary Dumper objects. +// +// This detects single Requirement inputs and dumps them successfully (using +// single-requirement syntax). No indication of error is returned in this case. +// +string Dumper::dump(const Requirements *reqs, bool debug /* = false */) +{ + if (!reqs) { + return "# no requirement(s)"; + } else if (reqs->magic() == Requirement::typeMagic) { // single requirement + return dump((const Requirement *)reqs) + "\n"; + } else { + string result; + for (unsigned n = 0; n < reqs->count(); n++) { + char prefix[200]; + if (reqs->type(n) < kSecRequirementTypeCount) + snprintf(prefix, sizeof(prefix), + "%s => ", Requirement::typeNames[reqs->type(n)]); + else + snprintf(prefix, sizeof(prefix), "/*unknown type*/ %d => ", reqs->type(n)); + Dumper dumper(reqs->blob(n), debug); + dumper.expr(); + result += prefix + dumper.value() + "\n"; + } + return result; + } +} + +string Dumper::dump(const Requirement *req, bool debug /* = false */) +{ + Dumper dumper(req, debug); + try { + dumper.dump(); + return dumper; + } catch (const CommonError &err) { + if (debug) { + char errstr[80]; + snprintf(errstr, sizeof(errstr), " !! error %ld !!", (unsigned long)err.osStatus()); + return dumper.value() + errstr; + } + throw; + } +} + +string Dumper::dump(const BlobCore *req, bool debug /* = false */) +{ + switch (req->magic()) { + case Requirement::typeMagic: + return dump(static_cast(req), debug); + break; + case Requirements::typeMagic: + return dump(static_cast(req), debug); + break; + default: + return "invalid data type"; + } +} + + +// +// Element dumpers. Output accumulates in internal buffer. +// +void Dumper::expr(SyntaxLevel level) +{ + if (mDebug) + print("/*@0x%x*/", pc()); + ExprOp op = ExprOp(get()); + switch (op & ~opFlagMask) { + case opFalse: + print("never"); + break; + case opTrue: + print("always"); + break; + case opIdent: + print("identifier "); + data(); + break; + case opAppleAnchor: + print("anchor apple"); + break; + case opAppleGenericAnchor: + print("anchor apple generic"); + break; + case opAnchorHash: + print("certificate"); certSlot(); print(" = "); hashData(); + break; + case opInfoKeyValue: + if (mDebug) + print("/*legacy*/"); + print("info["); dotString(); print("] = "); data(); + break; + case opAnd: + if (level < slAnd) + print("("); + expr(slAnd); + print(" and "); + expr(slAnd); + if (level < slAnd) + print(")"); + break; + case opOr: + if (level < slOr) + print("("); + expr(slOr); + print(" or "); + expr(slOr); + if (level < slOr) + print(")"); + break; + case opNot: + print("! "); + expr(slPrimary); + break; + case opCDHash: + print(" cdhash "); + hashData(); + break; + case opInfoKeyField: + print("info["); dotString(); print("]"); match(); + break; + case opEntitlementField: + print("entitlement["); dotString(); print("]"); match(); + break; + case opCertField: + print("certificate"); certSlot(); print("["); dotString(); print("]"); match(); + break; + case opCertGeneric: + print("certificate"); certSlot(); print("["); + { + const unsigned char *data; size_t length; + getData(data, length); + print("field.%s", CssmOid((unsigned char *)data, length).toOid().c_str()); + } + print("]"); match(); + break; + case opCertPolicy: + print("certificate"); certSlot(); print("["); + { + const unsigned char *data; size_t length; + getData(data, length); + print("policy.%s", CssmOid((unsigned char *)data, length).toOid().c_str()); + } + print("]"); match(); + break; + case opTrustedCert: + print("certificate"); certSlot(); print("trusted"); + break; + case opTrustedCerts: + print("anchor trusted"); + break; + case opNamedAnchor: + print("anchor apple "); data(); + break; + case opNamedCode: + print("("); data(); print(")"); + break; + default: + if (op & opGenericFalse) { + print(" false /* opcode %d */", op & ~opFlagMask); + break; + } else if (op & opGenericSkip) { + print(" /* opcode %d */", op & ~opFlagMask); + break; + } else { + print("OPCODE %d NOT UNDERSTOOD (ending print)", op); + return; + } + } +} + +void Dumper::certSlot() +{ + switch (int32_t slot = get()) { + case Requirement::anchorCert: + print(" root"); + break; + case Requirement::leafCert: + print(" leaf"); + break; + default: + print(" %d", slot); + break; + } +} + +void Dumper::match() +{ + switch (MatchOperation op = MatchOperation(get())) { + case matchExists: + print(" /* exists */"); + break; + case matchEqual: + print(" = "); data(); + break; + case matchContains: + print(" ~ "); data(); + break; + case matchBeginsWith: + print(" = "); data(); print("*"); + break; + case matchEndsWith: + print(" = *"); data(); + break; + case matchLessThan: + print(" < "); data(); + break; + case matchGreaterEqual: + print(" >= "); data(); + break; + case matchLessEqual: + print(" <= "); data(); + break; + case matchGreaterThan: + print(" > "); data(); + break; + default: + print("MATCH OPCODE %d NOT UNDERSTOOD", op); + break; + } +} + +void Dumper::hashData() +{ + print("H\""); + const unsigned char *data; size_t length; + getData(data, length); + printBytes(data, length); + print("\""); +} + +void Dumper::data(PrintMode bestMode /* = isSimple */, bool dotOkay /* = false */) +{ + const unsigned char *data; size_t length; + getData(data, length); + for (unsigned n = 0; n < length; n++) + if ((isalnum(data[n]) || (data[n] == '.' && dotOkay))) { // simple + if (n == 0 && isdigit(data[n])) // unquoted idents can't start with a digit + bestMode = isPrintable; + } else if (isgraph(data[n]) || isspace(data[n])) { + if (bestMode == isSimple) + bestMode = isPrintable; + } else { + bestMode = isBinary; + break; // pessimal + } + + if (bestMode == isSimple) { + string s((const char *)data, length); + for (const char * const * k = keywords; *k; k++) + if (s == *k) { + bestMode = isPrintable; // reserved word; need quotes + break; + } + } + + switch (bestMode) { + case isSimple: + print("%.*s", length, data); + break; + case isPrintable: + print("\"%.*s\"", length, data); + break; + default: + print("0x"); + printBytes(data, length); + break; + } +} + +void Dumper::printBytes(const Byte *data, size_t length) +{ + for (unsigned n = 0; n < length; n++) + print("%02.2x", data[n]); +} + + +} // CodeSigning +} // Security diff --git a/libsecurity_codesigning/lib/reqdumper.h b/libsecurity_codesigning/lib/reqdumper.h new file mode 100644 index 00000000..70c881f0 --- /dev/null +++ b/libsecurity_codesigning/lib/reqdumper.h @@ -0,0 +1,100 @@ +/* + * Copyright (c) 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@ + */ + +// +// reqdumper - Requirement un-parsing (disassembly) +// +#ifndef _H_REQDUMPER +#define _H_REQDUMPER + +#include "reqreader.h" +#include + + +namespace Security { +namespace CodeSigning { + + +// +// A decompiler for (compiled) requirements programs. +// This is intended to produce compiler-ready source, and the +// (decompile . compile) cycle is meant to be loss-less. +// +// Note that a Dumper is a type of Interpreter, so it can use the program stream +// accessors of the Interpreter. However, the evaluaton Context is absent, so +// actual validation functions must not be called. +// +class Dumper : public Requirement::Reader { +public: + explicit Dumper(const Requirement *req, bool debug = false) + : Reader(req), mDebug(debug) { } + + enum SyntaxLevel { + slPrimary, // syntax primary + slAnd, // conjunctive + slOr, // disjunctive + slTop // where we start + }; + + void dump(); // decompile this (entire) requirement + void expr(SyntaxLevel level = slTop); // decompile one requirement expression + + std::string value() const { return mOutput; } + operator std::string () const { return value(); } + + typedef unsigned char Byte; + +public: + // all-in-one dumping + static string dump(const Requirements *reqs, bool debug = false); + static string dump(const Requirement *req, bool debug = false); + static string dump(const BlobCore *req, bool debug = false); // dumps either + +protected: + enum PrintMode { + isSimple, // printable and does not require quotes + isPrintable, // can be quoted safely + isBinary // contains binary bytes (use 0xnnn form) + }; + void data(PrintMode bestMode = isSimple, bool dotOkay = false); + void dotString() { data(isSimple, true); } + void quotedString() { data(isPrintable); } + void hashData(); // H"bytes" + void certSlot(); // symbolic certificate slot indicator (explicit) + void match(); // a match suffix (op + value) + + void print(const char *format, ...); + +private: + void printBytes(const Byte *data, size_t length); // just write hex bytes + +private: + std::string mOutput; // output accumulator + bool mDebug; // include debug output in mOutput +}; + + +} // CodeSigning +} // Security + +#endif //_H_REQDUMPER diff --git a/libsecurity_codesigning/lib/reqinterp.cpp b/libsecurity_codesigning/lib/reqinterp.cpp new file mode 100644 index 00000000..e3e82338 --- /dev/null +++ b/libsecurity_codesigning/lib/reqinterp.cpp @@ -0,0 +1,573 @@ +/* + * 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@ + */ + +// +// reqinterp - Requirement language (exprOp) interpreter +// +#include "reqinterp.h" +#include "codesigning_dtrace.h" +#include +#include +#include +#include +#include "csutilities.h" + +namespace Security { +namespace CodeSigning { + + +// +// Fragment fetching, caching, and evaluation. +// +// Several language elements allow "calling" of separate requirement programs +// stored on disk as (binary) requirement blobs. The Fragments class takes care +// of finding, loading, caching, and evaluating them. +// +// This is a singleton for (process global) caching. It works fine as multiple instances, +// at a loss of caching effectiveness. +// +class Fragments { +public: + Fragments(); + + bool named(const std::string &name, const Requirement::Context &ctx) + { return evalNamed("subreq", name, ctx); } + bool namedAnchor(const std::string &name, const Requirement::Context &ctx) + { return evalNamed("anchorreq", name, ctx); } + +private: + bool evalNamed(const char *type, const std::string &name, const Requirement::Context &ctx); + CFDataRef fragment(const char *type, const std::string &name); + + typedef std::map > FragMap; + +private: + CFBundleRef mMyBundle; // Security.framework bundle + Mutex mLock; // lock for all of the below... + FragMap mFragments; // cached fragments +}; + +static ModuleNexus fragments; + + +// +// Magic certificate features +// +static CFStringRef appleIntermediateCN = CFSTR("Apple Code Signing Certification Authority"); +static CFStringRef appleIntermediateO = CFSTR("Apple Inc."); + + +// +// Main interpreter function. +// +// ExprOp code is in Polish Notation (operator followed by operands), +// and this engine uses opportunistic evaluation. +// +bool Requirement::Interpreter::evaluate() +{ + ExprOp op = ExprOp(get()); + CODESIGN_EVAL_REQINT_OP(op, this->pc() - sizeof(uint32_t)); + switch (op & ~opFlagMask) { + case opFalse: + return false; + case opTrue: + return true; + case opIdent: + return mContext->directory && getString() == mContext->directory->identifier(); + case opAppleAnchor: + return appleSigned(); + case opAppleGenericAnchor: + return appleAnchored(); + case opAnchorHash: + { + SecCertificateRef cert = mContext->cert(get()); + return verifyAnchor(cert, getSHA1()); + } + case opInfoKeyValue: // [legacy; use opInfoKeyField] + { + string key = getString(); + return infoKeyValue(key, Match(CFTempString(getString()), matchEqual)); + } + case opAnd: + return evaluate() & evaluate(); + case opOr: + return evaluate() | evaluate(); + case opCDHash: + if (mContext->directory) { + SHA1 hash; + hash(mContext->directory, mContext->directory->length()); + return hash.verify(getHash()); + } else + return false; + case opNot: + return !evaluate(); + case opInfoKeyField: + { + string key = getString(); + Match match(*this); + return infoKeyValue(key, match); + } + case opEntitlementField: + { + string key = getString(); + Match match(*this); + return entitlementValue(key, match); + } + case opCertField: + { + SecCertificateRef cert = mContext->cert(get()); + string key = getString(); + Match match(*this); + return certFieldValue(key, match, cert); + } + case opCertGeneric: + { + SecCertificateRef cert = mContext->cert(get()); + string key = getString(); + Match match(*this); + return certFieldGeneric(key, match, cert); + } + case opCertPolicy: + { + SecCertificateRef cert = mContext->cert(get()); + string key = getString(); + Match match(*this); + return certFieldPolicy(key, match, cert); + } + case opTrustedCert: + return trustedCert(get()); + case opTrustedCerts: + return trustedCerts(); + case opNamedAnchor: + return fragments().namedAnchor(getString(), *mContext); + case opNamedCode: + return fragments().named(getString(), *mContext); + default: + // opcode not recognized - handle generically if possible, fail otherwise + if (op & (opGenericFalse | opGenericSkip)) { + // unknown opcode, but it has a size field and can be safely bypassed + skip(get()); + if (op & opGenericFalse) { + CODESIGN_EVAL_REQINT_UNKNOWN_FALSE(op); + return false; + } else { + CODESIGN_EVAL_REQINT_UNKNOWN_SKIPPED(op); + return evaluate(); + } + } + // unrecognized opcode and no way to interpret it + secdebug("csinterp", "opcode 0x%x cannot be handled; aborting", op); + MacOSError::throwMe(errSecCSUnimplemented); + } +} + + +// +// Evaluate an Info.plist key condition +// +bool Requirement::Interpreter::infoKeyValue(const string &key, const Match &match) +{ + if (mContext->info) // we have an Info.plist + if (CFTypeRef value = CFDictionaryGetValue(mContext->info, CFTempString(key))) + return match(value); + return false; +} + + +// +// Evaluate an entitlement condition +// +bool Requirement::Interpreter::entitlementValue(const string &key, const Match &match) +{ + if (mContext->entitlements) // we have an Info.plist + if (CFTypeRef value = CFDictionaryGetValue(mContext->entitlements, CFTempString(key))) + return match(value); + return false; +} + + +bool Requirement::Interpreter::certFieldValue(const string &key, const Match &match, SecCertificateRef cert) +{ + // no cert, no chance + if (cert == NULL) + return false; + + // a table of recognized keys for the "certificate[foo]" syntax + static const struct CertField { + const char *name; + const CSSM_OID *oid; + } certFields[] = { + { "subject.C", &CSSMOID_CountryName }, + { "subject.CN", &CSSMOID_CommonName }, + { "subject.D", &CSSMOID_Description }, + { "subject.L", &CSSMOID_LocalityName }, +// { "subject.C-L", &CSSMOID_CollectiveLocalityName }, // missing from Security.framework headers + { "subject.O", &CSSMOID_OrganizationName }, + { "subject.C-O", &CSSMOID_CollectiveOrganizationName }, + { "subject.OU", &CSSMOID_OrganizationalUnitName }, + { "subject.C-OU", &CSSMOID_CollectiveOrganizationalUnitName }, + { "subject.ST", &CSSMOID_StateProvinceName }, + { "subject.C-ST", &CSSMOID_CollectiveStateProvinceName }, + { "subject.STREET", &CSSMOID_StreetAddress }, + { "subject.C-STREET", &CSSMOID_CollectiveStreetAddress }, + { "subject.UID", &CSSMOID_UserID }, + { NULL, NULL } + }; + + // DN-component single-value match + for (const CertField *cf = certFields; cf->name; cf++) + if (cf->name == key) { + CFRef value; + if (OSStatus rc = SecCertificateCopySubjectComponent(cert, cf->oid, &value.aref())) { + secdebug("csinterp", "cert %p lookup for DN.%s failed rc=%d", cert, key.c_str(), (int)rc); + return false; + } + return match(value); + } + + // email multi-valued match (any of...) + if (key == "email") { + CFRef value; + if (OSStatus rc = SecCertificateCopyEmailAddresses(cert, &value.aref())) { + secdebug("csinterp", "cert %p lookup for email failed rc=%d", cert, (int)rc); + return false; + } + return match(value); + } + + // unrecognized key. Fail but do not abort to promote backward compatibility down the road + secdebug("csinterp", "cert field notation \"%s\" not understood", key.c_str()); + return false; +} + + +bool Requirement::Interpreter::certFieldGeneric(const string &key, const Match &match, SecCertificateRef cert) +{ + // the key is actually a (binary) OID value + CssmOid oid((char *)key.data(), key.length()); + return certFieldGeneric(oid, match, cert); +} + +bool Requirement::Interpreter::certFieldGeneric(const CssmOid &oid, const Match &match, SecCertificateRef cert) +{ + return cert && certificateHasField(cert, oid) && match(kCFBooleanTrue); +} + +bool Requirement::Interpreter::certFieldPolicy(const string &key, const Match &match, SecCertificateRef cert) +{ + // the key is actually a (binary) OID value + CssmOid oid((char *)key.data(), key.length()); + return certFieldPolicy(oid, match, cert); +} + +bool Requirement::Interpreter::certFieldPolicy(const CssmOid &oid, const Match &match, SecCertificateRef cert) +{ + return cert && certificateHasPolicy(cert, oid) && match(kCFBooleanTrue); +} + + +// +// Check the Apple-signed condition +// +bool Requirement::Interpreter::appleAnchored() +{ + if (SecCertificateRef cert = mContext->cert(anchorCert)) + if (verifyAnchor(cert, appleAnchorHash()) +#if defined(TEST_APPLE_ANCHOR) + || verifyAnchor(cert, testAppleAnchorHash()) +#endif + ) + return true; + return false; +} + +bool Requirement::Interpreter::appleSigned() +{ + if (appleAnchored()) + if (SecCertificateRef intermed = mContext->cert(-2)) // first intermediate + // first intermediate common name match (exact) + if (certFieldValue("subject.CN", Match(appleIntermediateCN, matchEqual), intermed) + && certFieldValue("subject.O", Match(appleIntermediateO, matchEqual), intermed)) + return true; + return false; +} + + +// +// Verify an anchor requirement against the context +// +bool Requirement::Interpreter::verifyAnchor(SecCertificateRef cert, const unsigned char *digest) +{ + // get certificate bytes + if (cert) { + CSSM_DATA certData; + MacOSError::check(SecCertificateGetData(cert, &certData)); + + // verify hash + //@@@ should get SHA1(cert(-1).data) precalculated during chain verification + SHA1 hasher; + hasher(certData.Data, certData.Length); + return hasher.verify(digest); + } + return false; +} + + +// +// Check one or all certificate(s) in the cert chain against the Trust Settings database. +// +bool Requirement::Interpreter::trustedCerts() +{ + int anchor = mContext->certCount() - 1; + for (int slot = 0; slot <= anchor; slot++) + if (SecCertificateRef cert = mContext->cert(slot)) + switch (trustSetting(cert, slot == anchor)) { + case kSecTrustSettingsResultTrustRoot: + case kSecTrustSettingsResultTrustAsRoot: + return true; + case kSecTrustSettingsResultDeny: + return false; + case kSecTrustSettingsResultUnspecified: + break; + default: + assert(false); + return false; + } + else + return false; + return false; +} + +bool Requirement::Interpreter::trustedCert(int slot) +{ + if (SecCertificateRef cert = mContext->cert(slot)) { + int anchorSlot = mContext->certCount() - 1; + switch (trustSetting(cert, slot == anchorCert || slot == anchorSlot)) { + case kSecTrustSettingsResultTrustRoot: + case kSecTrustSettingsResultTrustAsRoot: + return true; + case kSecTrustSettingsResultDeny: + case kSecTrustSettingsResultUnspecified: + return false; + default: + assert(false); + return false; + } + } else + return false; +} + + +// +// Explicitly check one certificate against the Trust Settings database and report +// the findings. This is a helper for the various Trust Settings evaluators. +// +SecTrustSettingsResult Requirement::Interpreter::trustSetting(SecCertificateRef cert, bool isAnchor) +{ + // the SPI input is the uppercase hex form of the SHA-1 of the certificate... + assert(cert); + SHA1::Digest digest; + hashOfCertificate(cert, digest); + string Certhex = CssmData(digest, sizeof(digest)).toHex(); + for (string::iterator it = Certhex.begin(); it != Certhex.end(); ++it) + if (islower(*it)) + *it = toupper(*it); + + // call Trust Settings and see what it finds + SecTrustSettingsDomain domain; + SecTrustSettingsResult result; + CSSM_RETURN *errors = NULL; + uint32 errorCount = 0; + bool foundMatch, foundAny; + switch (OSStatus rc = SecTrustSettingsEvaluateCert( + CFTempString(Certhex), // settings index + &CSSMOID_APPLE_TP_CODE_SIGNING, // standard code signing policy + NULL, 0, // policy string (unused) + kSecTrustSettingsKeyUseAny, // no restriction on key usage @@@ + isAnchor, // consult system default anchor set + + &domain, // domain of found setting + &errors, &errorCount, // error set and maximum count + &result, // the actual setting + &foundMatch, &foundAny // optimization hints (not used) + )) { + case noErr: + ::free(errors); + if (foundMatch) + return result; + else + return kSecTrustSettingsResultUnspecified; + default: + ::free(errors); + MacOSError::throwMe(rc); + } +} + + +// +// Create a Match object from the interpreter stream +// +Requirement::Interpreter::Match::Match(Interpreter &interp) +{ + switch (mOp = interp.get()) { + case matchExists: + break; + case matchEqual: + case matchContains: + case matchBeginsWith: + case matchEndsWith: + case matchLessThan: + case matchGreaterThan: + case matchLessEqual: + case matchGreaterEqual: + mValue.take(makeCFString(interp.getString())); + break; + default: + // Assume this (unknown) match type has a single data argument. + // This gives us a chance to keep the instruction stream aligned. + interp.getString(); // discard + break; + } +} + + +// +// Execute a match against a candidate value +// +bool Requirement::Interpreter::Match::operator () (CFTypeRef candidate) const +{ + // null candidates always fail + if (!candidate) + return false; + + // interpret an array as matching alternatives (any one succeeds) + if (CFGetTypeID(candidate) == CFArrayGetTypeID()) { + CFArrayRef array = CFArrayRef(candidate); + CFIndex count = CFArrayGetCount(array); + for (CFIndex n = 0; n < count; n++) + if ((*this)(CFArrayGetValueAtIndex(array, n))) // yes, it's recursive + return true; + } + + switch (mOp) { + case matchExists: // anything but NULL and boolean false "exists" + return !CFEqual(candidate, kCFBooleanFalse); + case matchEqual: // equality works for all CF types + return CFEqual(candidate, mValue); + case matchContains: + if (CFGetTypeID(candidate) == CFStringGetTypeID()) { + CFStringRef value = CFStringRef(candidate); + if (CFStringFindWithOptions(value, mValue, CFRangeMake(0, CFStringGetLength(value)), 0, NULL)) + return true; + } + return false; + case matchBeginsWith: + if (CFGetTypeID(candidate) == CFStringGetTypeID()) { + CFStringRef value = CFStringRef(candidate); + if (CFStringFindWithOptions(value, mValue, CFRangeMake(0, CFStringGetLength(mValue)), 0, NULL)) + return true; + } + return false; + case matchEndsWith: + if (CFGetTypeID(candidate) == CFStringGetTypeID()) { + CFStringRef value = CFStringRef(candidate); + CFIndex matchLength = CFStringGetLength(mValue); + CFIndex start = CFStringGetLength(value) - matchLength; + if (start >= 0) + if (CFStringFindWithOptions(value, mValue, CFRangeMake(start, matchLength), 0, NULL)) + return true; + } + return false; + case matchLessThan: + return inequality(candidate, kCFCompareNumerically, kCFCompareLessThan, true); + case matchGreaterThan: + return inequality(candidate, kCFCompareNumerically, kCFCompareGreaterThan, true); + case matchLessEqual: + return inequality(candidate, kCFCompareNumerically, kCFCompareGreaterThan, false); + case matchGreaterEqual: + return inequality(candidate, kCFCompareNumerically, kCFCompareLessThan, false); + default: + // unrecognized match types can never match + return false; + } +} + + +bool Requirement::Interpreter::Match::inequality(CFTypeRef candidate, CFStringCompareFlags flags, + CFComparisonResult outcome, bool negate) const +{ + if (CFGetTypeID(candidate) == CFStringGetTypeID()) { + CFStringRef value = CFStringRef(candidate); + if ((CFStringCompare(value, mValue, flags) == outcome) == negate) + return true; + } + return false; +} + + +// +// External fragments +// +Fragments::Fragments() +{ + mMyBundle = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.security")); +} + + +bool Fragments::evalNamed(const char *type, const std::string &name, const Requirement::Context &ctx) +{ + if (CFDataRef fragData = fragment(type, name)) { + const Requirement *req = (const Requirement *)CFDataGetBytePtr(fragData); // was prevalidated as Requirement + return req->validates(ctx); + } + return false; +} + + +CFDataRef Fragments::fragment(const char *type, const std::string &name) +{ + string key = name + "!!" + type; // compound key + StLock _(mLock); // lock for cache access + FragMap::const_iterator it = mFragments.find(key); + if (it == mFragments.end()) { + CFRef fragData; // will always be set (NULL on any errors) + if (CFRef fragURL = CFBundleCopyResourceURL(mMyBundle, CFTempString(name), CFSTR("csreq"), CFTempString(type))) + if (CFRef data = cfLoadFile(fragURL)) { // got data + const Requirement *req = (const Requirement *)CFDataGetBytePtr(data); + if (req->validateBlob(CFDataGetLength(data))) // looks like a Requirement... + fragData = data; // ... so accept it + else + Syslog::warning("Invalid sub-requirement at %s", cfString(fragURL).c_str()); + } + if (CODESIGN_EVAL_REQINT_FRAGMENT_LOAD_ENABLED()) + CODESIGN_EVAL_REQINT_FRAGMENT_LOAD(type, name.c_str(), fragData ? CFDataGetBytePtr(fragData) : NULL); + mFragments[key] = fragData; // cache it, success or failure + return fragData; + } + CODESIGN_EVAL_REQINT_FRAGMENT_HIT(type, name.c_str()); + return it->second; +} + + +} // CodeSigning +} // Security diff --git a/libsecurity_codesigning/lib/reqinterp.h b/libsecurity_codesigning/lib/reqinterp.h new file mode 100644 index 00000000..ad1ddb84 --- /dev/null +++ b/libsecurity_codesigning/lib/reqinterp.h @@ -0,0 +1,88 @@ +/* + * Copyright (c) 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@ + */ + +// +// reqinterp - Requirement language (exprOp) interpreter +// +#ifndef _H_REQINTERP +#define _H_REQINTERP + +#include +#include +#include // CssmOid + +namespace Security { +namespace CodeSigning { + + +// +// An interpreter for exprForm-type requirements. +// This is a simple Polish Notation stack evaluator. +// +class Requirement::Interpreter : public Requirement::Reader { +public: + Interpreter(const Requirement *req, const Context *ctx) : Reader(req), mContext(ctx) { } + + bool evaluate(); + +protected: + class Match { + public: + Match(Interpreter &interp); // reads match postfix from interp + Match(CFStringRef value, MatchOperation op) : mValue(value), mOp(op) { } // explicit + Match() : mValue(NULL), mOp(matchExists) { } // explict test for presence + bool operator () (CFTypeRef candidate) const; // match to candidate + + protected: + bool inequality(CFTypeRef candidate, CFStringCompareFlags flags, CFComparisonResult outcome, bool negate) const; + + private: + CFCopyRef mValue; // match value + MatchOperation mOp; // type of match + }; + +protected: + bool infoKeyValue(const std::string &key, const Match &match); + bool entitlementValue(const std::string &key, const Match &match); + bool certFieldValue(const string &key, const Match &match, SecCertificateRef cert); + bool certFieldGeneric(const string &key, const Match &match, SecCertificateRef cert); + bool certFieldGeneric(const CssmOid &oid, const Match &match, SecCertificateRef cert); + bool certFieldPolicy(const string &key, const Match &match, SecCertificateRef cert); + bool certFieldPolicy(const CssmOid &oid, const Match &match, SecCertificateRef cert); + bool verifyAnchor(SecCertificateRef cert, const unsigned char *digest); + bool appleSigned(); + bool appleAnchored(); + bool trustedCerts(); + bool trustedCert(int slot); + + static SecTrustSettingsResult trustSetting(SecCertificateRef cert, bool isAnchor); + +private: + const Context * const mContext; +}; + + +} // CodeSigning +} // Security + +#endif //_H_REQINTERP diff --git a/libsecurity_codesigning/lib/reqmaker.cpp b/libsecurity_codesigning/lib/reqmaker.cpp new file mode 100644 index 00000000..31642a94 --- /dev/null +++ b/libsecurity_codesigning/lib/reqmaker.cpp @@ -0,0 +1,169 @@ +/* + * 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@ + */ + +// +// reqmaker - Requirement assembler +// +#include "reqmaker.h" + +namespace Security { +namespace CodeSigning { + + +// +// Requirement::Makers +// +Requirement::Maker::Maker(Kind k) + : mSize(1024) +{ + mBuffer = (Requirement *)malloc(mSize); + mBuffer->initialize(); + mBuffer->kind(k); + mPC = sizeof(Requirement); +} + +// need at least (size) bytes in the creation buffer +void Requirement::Maker::require(size_t size) +{ + if (mPC + size > mSize) { + mSize *= 2; + if (mPC + size > mSize) + mSize = mPC + size; + if (!(mBuffer = (Requirement *)realloc(mBuffer, mSize))) + UnixError::throwMe(ENOMEM); + } +} + +// allocate (size) bytes at end of buffer and return pointer to that +void *Requirement::Maker::alloc(size_t size) +{ + // round size up to preserve alignment + size_t usedSize = LowLevelMemoryUtilities::alignUp(size, baseAlignment); + require(usedSize); + void *data = mBuffer->at(mPC); + mPC += usedSize; + + // clear any padding (avoid random bytes in code image) + const uint32_t zero = 0; + memcpy(mBuffer->at(mPC - usedSize + size), &zero, usedSize - size); + + // all done + return data; +} + +// put contiguous data blob +void Requirement::Maker::putData(const void *data, size_t length) +{ + put(uint32_t(length)); + memcpy(alloc(length), data, length); +} + +// Specialized Maker put operations +void Requirement::Maker::anchor() +{ + put(opAppleAnchor); +} + +void Requirement::Maker::anchorGeneric() +{ + put(opAppleGenericAnchor); +} + +void Requirement::Maker::anchor(int slot, SHA1::Digest digest) +{ + put(opAnchorHash); + put(slot); + putData(digest, SHA1::digestLength); +} + +void Requirement::Maker::anchor(int slot, const void *cert, size_t length) +{ + SHA1 hasher; + hasher(cert, length); + SHA1::Digest digest; + hasher.finish(digest); + anchor(slot, digest); +} + +void Requirement::Maker::trustedAnchor() +{ + put(opTrustedCerts); +} + +void Requirement::Maker::trustedAnchor(int slot) +{ + put(opTrustedCert); + put(slot); +} + +void Requirement::Maker::infoKey(const string &key, const string &value) +{ + put(opInfoKeyValue); + put(key); + put(value); +} + +void Requirement::Maker::ident(const string &identifier) +{ + put(opIdent); + put(identifier); +} + +void Requirement::Maker::cdhash(SHA1::Digest digest) +{ + put(opCDHash); + putData(digest, SHA1::digestLength); +} + + + +void Requirement::Maker::copy(const Requirement *req) +{ + assert(req); + if (req->kind() != exprForm) // don't know how to embed this + MacOSError::throwMe(errSecCSReqUnsupported); + this->copy(req->at(sizeof(Requirement)), req->length() - sizeof(Requirement)); +} + + +void *Requirement::Maker::insert(const Label &label, size_t length) +{ + require(length); + memmove(mBuffer->at(label.pos + length), + mBuffer->at(label.pos), mPC - label.pos); + mPC += length; + return mBuffer->at(label.pos); +} + + +Requirement *Requirement::Maker::make() +{ + mBuffer->length(mPC); + Requirement *result = mBuffer; + mBuffer = NULL; + return result; +} + + +} // CodeSigning +} // Security diff --git a/libsecurity_codesigning/lib/reqmaker.h b/libsecurity_codesigning/lib/reqmaker.h new file mode 100644 index 00000000..ee1da109 --- /dev/null +++ b/libsecurity_codesigning/lib/reqmaker.h @@ -0,0 +1,134 @@ +/* + * 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@ + */ + +// +// reqmaker - Requirement assembler +// +#ifndef _H_REQMAKER +#define _H_REQMAKER + +#include + +namespace Security { +namespace CodeSigning { + + +// +// A Requirement::Maker is a tool for creating a Requirement blob. +// It's primarily an assember for the binary requirements (exprOp) language. +// Initialize it, call put() methods to generate the exprOp program, then +// call make() to get the assembled Requirement blob, malloc'ed for you. +// The Maker is not reusable. +// +class Requirement::Maker { +public: + Maker(Kind k = exprForm); + ~Maker() { free(mBuffer); } + + template + T *alloc(size_t size) { return reinterpret_cast(alloc(size)); } + + template + void put(const T &value) { *alloc >(sizeof(T)) = value; } + void put(ExprOp op) { put(uint32_t(op)); } + void put(MatchOperation op) { put(uint32_t(op)); } + void put(const std::string &s) { putData(s.data(), s.size()); } + void put(const char *s) { putData(s, strlen(s)); } + void putData(const void *data, size_t length); + void putData(CFStringRef s) { put(cfString(s)); } + + void anchor(int slot, SHA1::Digest digest); // given slot/digest + void anchor(int slot, const void *cert, size_t length); // given slot/cert + void anchor(); // made-by-Apple + void anchorGeneric(); // anything drawn from the Apple anchor + + void trustedAnchor(); + void trustedAnchor(int slot); + + void infoKey(const std::string &key, const std::string &value); + void ident(const std::string &identHash); + void cdhash(SHA1::Digest digest); + + void copy(const void *data, size_t length) + { memcpy(this->alloc(length), data, length); } + void copy(const Requirement *req); // inline expand + + // + // Keep labels into exprOp code, and allow for "shifting in" + // prefix code as needed (exprOp is a prefix-code language). + // + struct Label { + const Offset pos; + Label(const Maker &maker) : pos(maker.length()) { } + }; + void *insert(const Label &label, size_t length = sizeof(uint32_t)); + + template + Endian &insert(const Label &label, size_t length = sizeof(T)) + { return *reinterpret_cast*>(insert(label, length)); } + + // + // Help with making operator chains (foo AND bar AND baz...). + // Note that the empty case (no elements at all) must be resolved by the caller. + // + class Chain : public Label { + public: + Chain(Maker &myMaker, ExprOp op) + : Label(myMaker), maker(myMaker), mJoiner(op), mCount(0) { } + + void add() + { if (mCount++) maker.insert(*this) = mJoiner; } + + Maker &maker; + bool empty() const { return mCount == 0; } + unsigned count() const { return mCount; } + + private: + ExprOp mJoiner; + unsigned mCount; + }; + + + // + // Over-all construction management + // + void kind(Kind k) { mBuffer->kind(k); } + size_t length() const { return mPC; } + Requirement *make(); + Requirement *operator () () { return make(); } + +protected: + void require(size_t size); + void *alloc(size_t size); + +private: + Requirement *mBuffer; + Offset mSize; + Offset mPC; +}; + + +} // CodeSigning +} // Security + +#endif //_H_REQMAKER diff --git a/libsecurity_codesigning/lib/reqparser.cpp b/libsecurity_codesigning/lib/reqparser.cpp new file mode 100644 index 00000000..5a8e94e1 --- /dev/null +++ b/libsecurity_codesigning/lib/reqparser.cpp @@ -0,0 +1,125 @@ +/* + * Copyright (c) 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@ + */ + +// +// reqparser - interface to Requirement language parser/compiler +// +#include "reqparser.h" +#include "antlrplugin.h" +#include "cserror.h" +#include "codesigning_dtrace.h" +#include +#include + +namespace Security { +namespace CodeSigning { + + +struct PluginHost { + PluginHost(); + RefPointer plugin; + AntlrPlugin *antlr; +}; + +ModuleNexus plugin; + + +// +// The PluginHost constructor runs under the protection of ModuleNexus's constructor, +// so it doesn't have to worry about thread safety and such. +// +PluginHost::PluginHost() +{ + if (CFBundleRef securityFramework = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.security"))) + if (CFRef plugins = CFBundleCopyBuiltInPlugInsURL(securityFramework)) + if (CFRef pluginURL = makeCFURL("csparser.bundle", true, plugins)) { + plugin = new LoadableBundle(cfString(pluginURL).c_str()); + plugin->load(); + CODESIGN_LOAD_ANTLR(); + antlr = reinterpret_cast(plugin->lookupSymbol(FINDANTLRPLUGIN))(); + return; + } + + // can't load plugin - fail + MacOSError::throwMe(errSecCSInternalError); +} + + +// +// Drive a parsing function through the plugin harness and translate any errors +// into a CFError exception. +// +template +const Result *parse(Source source, const Result *(*AntlrPlugin::*func)(Source, string &)) +{ + string errors; + if (const Result *result = (plugin().antlr->*func)(source, errors)) + return result; + else + CSError::throwMe(errSecCSReqInvalid, kSecCFErrorRequirementSyntax, CFTempString(errors)); +} + + +// +// Implement the template instances by passing them through the plugin's eye-of-the-needle. +// Any other combination of input and output types will cause linker errors. +// +template <> +const Requirement *RequirementParser::operator () (std::FILE *source) +{ + return parse(source, &AntlrPlugin::fileRequirement); +} + +template <> +const Requirement *RequirementParser::operator () (const std::string &source) +{ + return parse(source, &AntlrPlugin::stringRequirement); +} + +template <> +const Requirements *RequirementParser::operator () (std::FILE *source) +{ + return parse(source, &AntlrPlugin::fileRequirements); +} + +template <> +const Requirements *RequirementParser::operator () (const std::string &source) +{ + return parse(source, &AntlrPlugin::stringRequirements); +} + +template <> +const BlobCore *RequirementParser::operator () (std::FILE *source) +{ + return parse(source, &AntlrPlugin::fileGeneric); +} + +template <> +const BlobCore *RequirementParser::operator () (const std::string &source) +{ + return parse(source, &AntlrPlugin::stringGeneric); +} + + +} // CodeSigning +} // Security diff --git a/libsecurity_codesigning/lib/reqparser.h b/libsecurity_codesigning/lib/reqparser.h new file mode 100644 index 00000000..21e1baac --- /dev/null +++ b/libsecurity_codesigning/lib/reqparser.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 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@ + */ + +// +// reqparser - interface to Requirement language parser/compiler +// +#ifndef _H_REQPARSER +#define _H_REQPARSER + +#include "requirement.h" + +namespace Security { +namespace CodeSigning { + + +// +// Generic parser interface +// +template +class RequirementParser { +public: + const ReqType *operator () (std::FILE *file); + const ReqType *operator () (const std::string &text); +}; + + +// +// Specifics for easier readability +// +template +inline const Requirement *parseRequirement(const Input &source) +{ return RequirementParser()(source); } + +template +inline const Requirements *parseRequirements(const Input &source) +{ return RequirementParser()(source); } + +template +inline const BlobCore *parseGeneric(const Input &source) +{ return RequirementParser()(source); } + + +} // CodeSigning +} // Security + +#endif //_H_REQPARSER diff --git a/libsecurity_codesigning/lib/reqreader.cpp b/libsecurity_codesigning/lib/reqreader.cpp new file mode 100644 index 00000000..8c79912b --- /dev/null +++ b/libsecurity_codesigning/lib/reqreader.cpp @@ -0,0 +1,93 @@ +/* + * 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@ + */ + +// +// reqreader - Requirement language (exprOp) reader/scanner +// +#include "reqreader.h" +#include +#include +#include // for hex encoding +#include "csutilities.h" + +namespace Security { +namespace CodeSigning { + + +// +// Requirement::Reader +// +Requirement::Reader::Reader(const Requirement *req) + : mReq(req), mPC(sizeof(Requirement)) +{ + assert(req); + if (req->kind() != exprForm) + MacOSError::throwMe(errSecCSReqUnsupported); +} + + +// +// Access helpers to retrieve various data types from the data stream +// +void Requirement::Reader::getData(const void *&data, size_t &length) +{ + length = get(); + checkSize(length); + data = (mReq->at(mPC)); + mPC += LowLevelMemoryUtilities::alignUp(length, baseAlignment); +} + +string Requirement::Reader::getString() +{ + const char *s; size_t length; + getData(s, length); + return string(s, length); +} + +const unsigned char *Requirement::Reader::getHash() +{ + const unsigned char *s; size_t length; + getData(s, length); + if (length != SHA1::digestLength) + MacOSError::throwMe(errSecCSReqInvalid); + return s; +} + +const unsigned char *Requirement::Reader::getSHA1() +{ + const unsigned char *digest; size_t length; + getData(digest, length); + if (length != CC_SHA1_DIGEST_LENGTH) + MacOSError::throwMe(errSecCSReqInvalid); + return digest; +} + +void Requirement::Reader::skip(size_t length) +{ + checkSize(length); + mPC += length; +} + + +} // CodeSigning +} // Security diff --git a/libsecurity_codesigning/lib/reqreader.h b/libsecurity_codesigning/lib/reqreader.h new file mode 100644 index 00000000..2db501b4 --- /dev/null +++ b/libsecurity_codesigning/lib/reqreader.h @@ -0,0 +1,86 @@ +/* + * 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@ + */ + +// +// reqreader - Requirement language (exprOp) reader/scanner +// +#ifndef _H_REQREADER +#define _H_REQREADER + +#include +#include + +namespace Security { +namespace CodeSigning { + + +// +// The Reader class provides structured access to a opExpr-type code requirement. +// +class Requirement::Reader { +public: + Reader(const Requirement *req); + + const Requirement *requirement() const { return mReq; } + + template T get(); + void getData(const void *&data, size_t &length); + + std::string getString(); + const unsigned char *getHash(); + const unsigned char *getSHA1(); + + template void getData(T *&data, size_t &length) + { return getData(reinterpret_cast(data), length); } + +protected: + void checkSize(size_t length) + { + if (mPC + length > mReq->length()) + MacOSError::throwMe(errSecCSReqInvalid); + } + + void skip(size_t length); + + Offset pc() const { return mPC; } + bool atEnd() const { return mPC >= mReq->length(); } + +private: + const Requirement * const mReq; + Offset mPC; +}; + +template +T Requirement::Reader::get() +{ + checkSize(sizeof(T)); + const Endian *value = mReq->at >(mPC); + mPC += sizeof(T); + return *value; +} + + +} // CodeSigning +} // Security + +#endif //_H_REQREADER diff --git a/libsecurity_codesigning/lib/requirement.cpp b/libsecurity_codesigning/lib/requirement.cpp new file mode 100644 index 00000000..cc527291 --- /dev/null +++ b/libsecurity_codesigning/lib/requirement.cpp @@ -0,0 +1,173 @@ +/* + * 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@ + */ + +// +// requirement - Code Requirement Blob description +// +#include "requirement.h" +#include "reqinterp.h" +#include "codesigning_dtrace.h" +#include +#include +#include +#include +#include + +#ifdef DEBUGDUMP +#include +#endif + +namespace Security { +namespace CodeSigning { + + +// +// The (SHA-1) hash of the canonical Apple certificate root anchor +// +static const SHA1::Digest gAppleAnchorHash = + { 0x61, 0x1e, 0x5b, 0x66, 0x2c, 0x59, 0x3a, 0x08, 0xff, 0x58, + 0xd1, 0x4a, 0xe2, 0x24, 0x52, 0xd1, 0x98, 0xdf, 0x6c, 0x60 }; + + +// +// Canonical names for requirement types +// +const char *const Requirement::typeNames[] = { + "invalid", + "host", + "guest", + "designated", + "library", + "plugin", +}; + + +// +// validate a requirement against a code context +// +void Requirement::validate(const Requirement::Context &ctx, OSStatus failure /* = errSecCSReqFailed */) const +{ + if (!this->validates(ctx, failure)) + MacOSError::throwMe(failure); +} + +bool Requirement::validates(const Requirement::Context &ctx, OSStatus failure /* = errSecCSReqFailed */) const +{ + CODESIGN_EVAL_REQINT_START((void*)this, this->length()); + switch (kind()) { + case exprForm: + if (Requirement::Interpreter(this, &ctx).evaluate()) { + CODESIGN_EVAL_REQINT_END(this, 0); + return true; + } else { + CODESIGN_EVAL_REQINT_END(this, failure); + return false; + } + default: + CODESIGN_EVAL_REQINT_END(this, errSecCSReqUnsupported); + MacOSError::throwMe(errSecCSReqUnsupported); + } +} + + +// +// Retrieve one certificate from the cert chain. +// Positive and negative indices can be used: +// [ leaf, intermed-1, ..., intermed-n, anchor ] +// 0 1 ... -2 -1 +// Returns NULL if unavailable for any reason. +// +SecCertificateRef Requirement::Context::cert(int ix) const +{ + if (certs) { + if (ix < 0) + ix += certCount(); + if (ix >= CFArrayGetCount(certs)) + return NULL; + if (CFTypeRef element = CFArrayGetValueAtIndex(certs, ix)) + return SecCertificateRef(element); + } + return NULL; +} + +unsigned int Requirement::Context::certCount() const +{ + if (certs) + return CFArrayGetCount(certs); + else + return 0; +} + + +// +// Return the hash of the canonical Apple certificate root (anchor). +// In a special test mode, also return an alternate root hash for testing. +// +const SHA1::Digest &Requirement::appleAnchorHash() +{ + return gAppleAnchorHash; +} + +#if defined(TEST_APPLE_ANCHOR) + +const char Requirement::testAppleAnchorEnv[] = "TEST_APPLE_ANCHOR"; + +const SHA1::Digest &Requirement::testAppleAnchorHash() +{ + static bool tried = false; + static SHA1::Digest testHash; + if (!tried) { + // see if we have one configured + if (const char *path = getenv(testAppleAnchorEnv)) + try { + UnixPlusPlus::FileDesc fd(path); + char buffer[2048]; // arbitrary limit + size_t size = fd.read(buffer, sizeof(buffer)); + SHA1 hash; + hash(buffer, size); + hash.finish(testHash); + Syslog::alert("ACCEPTING TEST AUTHORITY %s FOR APPLE CODE IDENTITY", path); + } catch (...) { } + tried = true; + } + return testHash; // will be zeroes (no match) if not configured +} + +#endif //TEST_APPLE_ANCHOR + + +// +// Debug dump support +// +#ifdef DEBUGDUMP + +void Requirement::dump() const +{ + Debug::dump("%s\n", Dumper::dump(this).c_str()); +} + +#endif //DEBUGDUMP + + +} // CodeSigning +} // Security diff --git a/libsecurity_codesigning/lib/requirement.h b/libsecurity_codesigning/lib/requirement.h new file mode 100644 index 00000000..dc59fa10 --- /dev/null +++ b/libsecurity_codesigning/lib/requirement.h @@ -0,0 +1,217 @@ +/* + * 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@ + */ + +// +// requirement - Code Requirement Blob description +// +#ifndef _H_REQUIREMENT +#define _H_REQUIREMENT + +#include +#include +#include +#include +#include "codedirectory.h" +#include + +namespace Security { +namespace CodeSigning { + + +// +// Single requirement. +// This is a contiguous binary blob, starting with this header +// and followed by binary expr-code. All links within the blob +// are offset-relative to the start of the header. +// This is designed to be a binary stable format. Note that we restrict +// outselves to 4GB maximum size (4 byte size/offset), and we expect real +// Requirement blobs to be fairly small (a few kilobytes at most). +// +// The "kind" field allows for adding different kinds of Requirements altogether +// in the future. We expect to stay within the framework of "opExpr" requirements, +// but it never hurts to have a way out. +// +class Requirement: public Blob { +public: + class Maker; // makes Requirement blobs + class Context; // evaluation context + class Reader; // structured reader + class Interpreter; // evaluation engine + + // different forms of Requirements. Right now, we only support exprForm ("opExprs") + enum Kind { + exprForm = 1 // prefix expr form + }; + + void kind(Kind k) { mKind = k; } + Kind kind() const { return Kind(uint32_t(mKind)); } + + // validate this requirement against a code context + void validate(const Context &ctx, OSStatus failure = errSecCSReqFailed) const; // throws on all failures + bool validates(const Context &ctx, OSStatus failure = errSecCSReqFailed) const; // returns on clean miss + + // certificate positions (within a standard certificate chain) + static const int leafCert = 0; // index for leaf (first in chain) + static const int anchorCert = -1; // index for anchor (last in chain) + + // the SHA1 hash of the canonical "Apple Anchor", i.e. the X509 Anchor + // that is considered "Apple's anchor certificate", as defined by hashOfCertificate(). + static const SHA1::Digest &appleAnchorHash(); +#if defined(TEST_APPLE_ANCHOR) + static const char testAppleAnchorEnv[]; + static const SHA1::Digest &testAppleAnchorHash(); +#endif //TEST_APPLE_ANCHOR + + // common alignment rule for all requirement forms + static const size_t baseAlignment = sizeof(uint32_t); // (we might as well say "four") + + // canonical (source) names of Requirement types (matched to SecRequirementType in CSCommon.h) + static const char *const typeNames[]; + + IFDUMP(void dump() const); + +private: + Endian mKind; // expression kind +}; + + +// +// An interpretation context +// +class Requirement::Context { +protected: + Context() + : certs(NULL), info(NULL), entitlements(NULL), identifier(""), directory(NULL) { } + +public: + Context(CFArrayRef certChain, CFDictionaryRef infoDict, CFDictionaryRef entitlementDict, + const std::string &ident, const CodeDirectory *dir) + : certs(certChain), info(infoDict), entitlements(entitlementDict), identifier(ident), directory(dir) { } + + CFArrayRef certs; // certificate chain + CFDictionaryRef info; // Info.plist + CFDictionaryRef entitlements; // entitlement plist + std::string identifier; // signing identifier + const CodeDirectory *directory; // CodeDirectory + + SecCertificateRef cert(int ix) const; // get a cert from the cert chain (NULL if not found) + unsigned int certCount() const; // length of cert chain (including root) +}; + + +// +// exprForm opcodes. +// +// Opcodes are broken into flags in the (HBO) high byte, and an opcode value +// in the remaining 24 bits. Note that opcodes will remain fairly small +// (almost certainly <60000), so we have the third byte to play around with +// in the future, if needed. For now, small opcodes effective reserve this byte +// as zero. +// The flag byte allows for limited understanding of unknown opcodes. It allows +// the interpreter to use the known opcode parts of the program while semi-creatively +// disregarding the parts it doesn't know about. An unrecognized opcode with zero +// flag byte causes evaluation to categorically fail, since the semantics of such +// an opcode cannot safely be predicted. +// +enum { + // semantic bits or'ed into the opcode + opFlagMask = 0xFF000000, // high bit flags + opGenericFalse = 0x80000000, // has size field; okay to default to false + opGenericSkip = 0x40000000, // has size field; skip and continue +}; + +enum ExprOp { + opFalse, // unconditionally false + opTrue, // unconditionally true + opIdent, // match canonical code [string] + opAppleAnchor, // signed by Apple as Apple's product + opAnchorHash, // match anchor [cert hash] + opInfoKeyValue, // *legacy* - use opInfoKeyField [key; value] + opAnd, // binary prefix expr AND expr [expr; expr] + opOr, // binary prefix expr OR expr [expr; expr] + opCDHash, // match hash of CodeDirectory directly [cd hash] + opNot, // logical inverse [expr] + opInfoKeyField, // Info.plist key field [string; match suffix] + opCertField, // Certificate field [cert index; field name; match suffix] + opTrustedCert, // require trust settings to approve one particular cert [cert index] + opTrustedCerts, // require trust settings to approve the cert chain + opCertGeneric, // Certificate component by OID [cert index; oid; match suffix] + opAppleGenericAnchor, // signed by Apple in any capacity + opEntitlementField, // entitlement dictionary field [string; match suffix] + opCertPolicy, // Certificate policy by OID [cert index; oid; match suffix] + opNamedAnchor, // named anchor type + opNamedCode, // named subroutine + exprOpCount // (total opcode count in use) +}; + +// match suffix opcodes +enum MatchOperation { + matchExists, // anything but explicit "false" - no value stored + matchEqual, // equal (CFEqual) + matchContains, // partial match (substring) + matchBeginsWith, // partial match (initial substring) + matchEndsWith, // partial match (terminal substring) + matchLessThan, // less than (string with numeric comparison) + matchGreaterThan, // greater than (string with numeric comparison) + matchLessEqual, // less or equal (string with numeric comparison) + matchGreaterEqual, // greater or equal (string with numeric comparison) +}; + + +// +// We keep Requirement groups in SuperBlobs, indexed by SecRequirementType +// +typedef SuperBlob<0xfade0c01> Requirements; + + +// +// Byte order flippers +// +inline CodeSigning::ExprOp h2n(CodeSigning::ExprOp op) +{ + uint32_t intOp = (uint32_t) op; + return (CodeSigning::ExprOp) ::h2n(intOp); +} + +inline CodeSigning::ExprOp n2h(CodeSigning::ExprOp op) +{ + uint32_t intOp = (uint32_t) op; + return (CodeSigning::ExprOp) ::n2h(intOp); +} + + +inline CodeSigning::MatchOperation h2n(CodeSigning::MatchOperation op) +{ + return CodeSigning::MatchOperation(::h2n((uint32_t) op)); +} + +inline CodeSigning::MatchOperation n2h(CodeSigning::MatchOperation op) +{ + return CodeSigning::MatchOperation(::n2h((uint32_t) op)); +} + + +} // CodeSigning +} // Security + +#endif //_H_REQUIREMENT diff --git a/libsecurity_codesigning/lib/resources.cpp b/libsecurity_codesigning/lib/resources.cpp new file mode 100644 index 00000000..785eb0a7 --- /dev/null +++ b/libsecurity_codesigning/lib/resources.cpp @@ -0,0 +1,216 @@ +/* + * 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@ + */ + +// +// resource directory construction and verification +// +#include "resources.h" +#include "csutilities.h" +#include +#include +#include + +namespace Security { +namespace CodeSigning { + + +// +// Construction and maintainance +// +ResourceBuilder::ResourceBuilder(const std::string &root, CFDictionaryRef rulesDict, CodeDirectory::HashAlgorithm hashType) + : ResourceEnumerator(root), mHashType(hashType) +{ + CFDictionary rules(rulesDict, errSecCSResourceRulesInvalid); + rules.apply(this, &ResourceBuilder::addRule); + mRawRules = rules; +} + +ResourceBuilder::~ResourceBuilder() +{ + for (Rules::iterator it = mRules.begin(); it != mRules.end(); ++it) + delete *it; +} + + +// +// Parse and add one matching rule +// +void ResourceBuilder::addRule(CFTypeRef key, CFTypeRef value) +{ + string pattern = cfString(key, errSecCSResourceRulesInvalid); + unsigned weight = 1; + uint32_t flags = 0; + if (CFGetTypeID(value) == CFBooleanGetTypeID()) { + if (value == kCFBooleanFalse) + flags |= omitted; + } else { + CFDictionary rule(value, errSecCSResourceRulesInvalid); + if (CFNumberRef weightRef = rule.get("weight")) + weight = cfNumber(weightRef); + if (CFBooleanRef omitRef = rule.get("omit")) + if (omitRef == kCFBooleanTrue) + flags |= omitted; + if (CFBooleanRef optRef = rule.get("optional")) + if (optRef == kCFBooleanTrue) + flags |= optional; + } + addRule(new Rule(pattern, weight, flags)); +} + + +// +// Locate the next non-ignored file, look up its rule, and return it. +// Returns NULL when we're out of files. +// +FTSENT *ResourceBuilder::next(string &path, Rule * &rule) +{ + while (FTSENT *ent = ResourceEnumerator::next(path)) { + // find best matching rule + Rule *bestRule = NULL; + for (Rules::const_iterator it = mRules.begin(); it != mRules.end(); ++it) { + Rule *rule = *it; + if (rule->match(path.c_str())) { + if (rule->flags & exclusion) { + bestRule = NULL; + break; + } + if (!bestRule || rule->weight > bestRule->weight) + bestRule = rule; + } + } + if (!bestRule || (bestRule->flags & omitted)) + continue; + rule = bestRule; + return ent; + } + return NULL; +} + + +// +// Build the ResourceDirectory given the currently established rule set. +// +CFDictionaryRef ResourceBuilder::build() +{ + secdebug("codesign", "start building resource directory"); + CFRef files = makeCFMutableDictionary(); + + string path; + Rule *rule; + while (FTSENT *ent = next(path, rule)) { + assert(rule); + CFRef hash = hashFile(ent->fts_accpath); + if (rule->flags == 0) { // default case - plain hash + cfadd(files, "{%s=%O}", path.c_str(), hash.get()); + secdebug("csresource", "%s added simple (rule %p)", path.c_str(), rule); + } else { // more complicated - use a sub-dictionary + cfadd(files, "{%s={hash=%O,optional=%B}}", + path.c_str(), hash.get(), rule->flags & optional); + secdebug("csresource", "%s added complex (rule %p)", path.c_str(), rule); + } + } + secdebug("codesign", "finished code directory with %d entries", + int(CFDictionaryGetCount(files))); + + return cfmake("{rules=%O,files=%O}", mRawRules.get(), files.get()); +} + + +// +// Hash a file and return a CFDataRef with the hash +// +CFDataRef ResourceBuilder::hashFile(const char *path) +{ + UnixPlusPlus::AutoFileDesc fd(path); + fd.fcntl(F_NOCACHE, true); // turn off page caching (one-pass) + MakeHash hasher(this); + hashFileData(fd, hasher.get()); + Hashing::Byte digest[hasher->digestLength()]; + hasher->finish(digest); + return CFDataCreate(NULL, digest, sizeof(digest)); +} + + +// +// Regex matching objects +// +ResourceBuilder::Rule::Rule(const std::string &pattern, unsigned w, uint32_t f) + : weight(w), flags(f) +{ + if (::regcomp(this, pattern.c_str(), REG_EXTENDED | REG_NOSUB)) //@@@ REG_ICASE? + MacOSError::throwMe(errSecCSResourceRulesInvalid); + secdebug("csresource", "%p rule %s added (weight %d, flags 0x%x)", + this, pattern.c_str(), w, f); +} + +ResourceBuilder::Rule::~Rule() +{ + ::regfree(this); +} + +bool ResourceBuilder::Rule::match(const char *s) const +{ + switch (::regexec(this, s, 0, NULL, 0)) { + case 0: + return true; + case REG_NOMATCH: + return false; + default: + MacOSError::throwMe(errSecCSResourceRulesInvalid); + } +} + + +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)) + r.push_back('\\'); + r.push_back(c); + } + return r; +} + + +// +// Resource Seals +// +ResourceSeal::ResourceSeal(CFTypeRef it) +{ + if (it == NULL) + MacOSError::throwMe(errSecCSResourcesInvalid); + if (CFGetTypeID(it) == CFDataGetTypeID()) { + mHash = CFDataRef(it); + mOptional = false; + } else { + mOptional = false; + if (!cfscan(it, "{hash=%XO,?optional=%B}", &mHash, &mOptional)) + MacOSError::throwMe(errSecCSResourcesInvalid); + } +} + + +} // end namespace CodeSigning +} // end namespace Security diff --git a/libsecurity_codesigning/lib/resources.h b/libsecurity_codesigning/lib/resources.h new file mode 100644 index 00000000..69c5851b --- /dev/null +++ b/libsecurity_codesigning/lib/resources.h @@ -0,0 +1,118 @@ +/* + * 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@ + */ + +// +// resource directory construction and verification +// +#ifndef _H_RSIGN +#define _H_RSIGN + +#include "renum.h" +#include "codedirectory.h" +#include +#include +#include +#include "regex.h" +#include +#include + +namespace Security { +namespace CodeSigning { + + +// +// The builder of ResourceDirectories. +// +// Note that this *is* a ResourceEnumerate, which can enumerate +// its source directory once (only). +// +class ResourceBuilder : public ResourceEnumerator { +public: + ResourceBuilder(const std::string &root, CFDictionaryRef rules, CodeDirectory::HashAlgorithm hashType); + ~ResourceBuilder(); + + CFDictionaryRef build(); + + enum Action { + optional = 0x01, // may be absent at runtime + omitted = 0x02, // do not seal even if present + exclusion = 0x04, // overriding exclusion (stop looking) + }; + + typedef unsigned int Weight; + +public: + class Rule : private regex_t { + public: + Rule(const std::string &pattern, Weight weight, uint32_t flags); + ~Rule(); + + bool match(const char *s) const; + + const Weight weight; + const uint32_t flags; + }; + void addRule(Rule *rule) { mRules.push_back(rule); } + void addExclusion(const std::string &pattern) { mRules.insert(mRules.begin(), new Rule(pattern, 0, exclusion)); } + + static std::string escapeRE(const std::string &s); + + FTSENT *next(std::string &path, Rule * &rule); // enumerate next file and match rule + +protected: + void addRule(CFTypeRef key, CFTypeRef value); + CFDataRef hashFile(const char *path); + DynamicHash *getHash() const { return CodeDirectory::hashFor(this->mHashType); } + +private: + CFCopyRef mRawRules; + typedef std::vector Rules; + Rules mRules; + CodeDirectory::HashAlgorithm mHashType; +}; + + +// +// The "seal" on a single resource. +// +class ResourceSeal { +public: + ResourceSeal(CFTypeRef ref); + +public: + operator bool () const { return mHash; } + bool operator ! () const { return mHash == NULL; } + + const SHA1::Byte *hash() const { return CFDataGetBytePtr(mHash); } + bool optional() const { return mOptional; } + +private: + CFDataRef mHash; + int mOptional; +}; + + +} // end namespace CodeSigning +} // end namespace Security + +#endif // !_H_RSIGN diff --git a/libsecurity_codesigning/lib/security_codesigning.d b/libsecurity_codesigning/lib/security_codesigning.d new file mode 100644 index 00000000..c4849d97 --- /dev/null +++ b/libsecurity_codesigning/lib/security_codesigning.d @@ -0,0 +1,96 @@ +/* + * DTrace static providers at the Code Signing layer + */ +#define int32_t int +#define uint32_t unsigned +#define mach_port_t uint32_t + + +/* + * Basic semantic events of the code signing subsystem + */ +provider codesign { + probe diskrep__create__macho(void *me, const char *path, const void *ctx); + probe diskrep__create__bundle__path(void *me, const char *path, void *ctx, void *exec); + probe diskrep__create__bundle__ref(void *me, void *cfbundle, void *ctx, void *exec); + probe diskrep__create__file(void *me, const char *path); + probe diskrep__create__cfm(void *me, const char *path); + probe diskrep__create__slc(void *me, const char *path); + probe diskrep__create__detached(void *me, void *orig, const char *source, void *glob); + probe diskrep__create__kernel(void *me); + probe diskrep__destroy(void *me); + + probe static__create(void *me, void *host); + probe dynamic__create(void *me, void *rep); + + probe static__cdhash(void *me, const void *cdhash, uint32_t length); + probe static__attach__explicit(void *me, void *rep); + probe static__attach__system(void *me, void *rep); + + probe eval__dynamic__start(void *me, const char *path); + probe eval__dynamic__end(void *me); + probe eval__dynamic__root(void *me); + + probe eval__static__start(void *me, const char *path); + probe eval__static__end(void *me); + probe eval__static__reset(void *me); + + probe eval__static__executable__start(void *me, const char *path, uint32_t pages); + probe eval__static__executable__fail(void *me, uint32_t badPage); + probe eval__static__executable__end(void *me); + probe eval__static__resources__start(void *me, const char *path, int count); + probe eval__static__resources__end(void *me); + + probe eval__static__directory(void *me); + probe eval__static__intreq__start(void *me, uint32_t reqType, void *target, int32_t nullError); + probe eval__static__intreq__end(void *me); + + probe eval__static__signature__start(void *me, const char *path); + probe eval__static__signature__adhoc(void *me); + probe eval__static__signature__result(void *me, uint32_t result, uint32_t chainLength); + probe eval__static__signature__expired(void *me); + probe eval__static__signature__end(void *me); + + probe eval__reqint__start(const void *reqdata, uint32_t reqlength); + probe eval__reqint__end(const void *reqdata, uint32_t result); + probe eval__reqint__op(uint32_t opcode, uint32_t offset); + probe eval__reqint__unknown_false(uint32_t opcode); + probe eval__reqint__unknown_skipped(uint32_t opcode); + probe eval__reqint__fragment__load(const char *type, const char *name, const void *req); + probe eval__reqint__fragment__hit(const char *type, const char *name); + + probe guest__hostingport(void *host, mach_port_t hostingPort); + probe guest__locate__generic(void *host, uint32_t *guestPath, uint32_t guestPathLength, mach_port_t subport); + probe guest__identify__process(void *guest, uint32_t guestPid, void *code); + probe guest__cdhash__process(void *code, const void *cdhash, uint32_t length); + probe guest__identify__generic(void *guest, uint32_t guestRef, void *code); + probe guest__cdhash__generic(void *code, const void *cdhash, uint32_t length); + + probe allocate__validate(const char *path, uint32_t pid); + probe allocate__arch(const char *arch, uint32_t size); + probe allocate__archn(uint32_t cputype, uint32_t cpusubtype, uint32_t size); + probe allocate__write(const char *arch, off_t offset, uint32_t length, uint32_t available); + + probe sign__dep__macho(void *me, const char *name, const void *requirement); + probe sign__dep__interp(void *me, const char *name, const void *requirement); + + probe load__antlr(); +}; + + +provider syspolicy { + probe assess_api(const char *path, int type, uint64_t flags); + + probe assess__outcome__accept(const char *path, int type, const char *label, const void *cdhash); + probe assess__outcome__deny(const char *path, int type, const char *label, const void *cdhash); + probe assess__outcome__default(const char *path, int type, const char *label, const void *cdhash); + probe assess__outcome__unsigned(const char *path, int type); + probe assess__outcome__broken(const char *path, int type, bool exception_made); + + probe recorder_mode(const char *path, int type, const char *label, const void *cdhash, int flags); + probe recorder_mode_adhoc_path(const char *path, int type, const char *sig_path); // path containing adhoc signature recorded + + probe assess_cache_hit(); + probe assess_local(); + probe assess_remote(); +}; diff --git a/libsecurity_codesigning/lib/security_codesigning.exp b/libsecurity_codesigning/lib/security_codesigning.exp new file mode 100644 index 00000000..00c9147d --- /dev/null +++ b/libsecurity_codesigning/lib/security_codesigning.exp @@ -0,0 +1,161 @@ +# +# 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@ +# +_SecCodeGetTypeID +_SecCodeCopySelf +_SecCodeCopyInternalRequirement +_SecCodeGetStatus +_SecCodeSetStatus +_SecCodeCopyStaticCode +_SecCodeCopyHost +_SecCodeCopyGuestWithAttributes +_SecCodeCreateWithPID +_SecCodeCheckValidity +_SecCodeCheckValidityWithErrors +_SecCodeCopyPath +_SecCodeCopyDesignatedRequirement +_SecCodeCopySigningInformation +_SecCodeMapMemory +_SecCodeSetDetachedSignature +_kSecCodeAttributeArchitecture +_kSecCodeAttributeBundleVersion +_kSecCodeAttributeSubarchitecture +_SecStaticCodeGetTypeID +_SecStaticCodeCreateWithPath +_SecStaticCodeCreateWithPathAndAttributes +_SecStaticCodeCheckValidity +_SecStaticCodeCheckValidityWithErrors +_SecRequirementGetTypeID +_SecRequirementCreateWithData +_SecRequirementCreateWithResource +_SecRequirementCreateWithString +_SecRequirementCreateWithStringAndErrors +_SecRequirementCreateGroup +_SecRequirementCopyData +_SecRequirementCopyString +_SecRequirementEvaluate +_SecRequirementsCreateFromRequirements +_SecRequirementsCopyRequirements +_SecRequirementsCreateWithString +_SecRequirementsCopyString +_SecCodeSignerGetTypeID +_SecCodeSignerCreate +_SecCodeSignerAddSignature +_SecCodeSignerAddSignatureWithErrors +_SecHostCreateGuest +_SecHostRemoveGuest +_SecHostSetGuestStatus +_SecHostSelectGuest +_SecHostSelectedGuest +_SecHostSetHostingPort +_kSecCodeDirectoryFlagTable +_kSecCodeSignerApplicationData +_kSecCodeSignerDetached +_kSecCodeSignerDigestAlgorithm +_kSecCodeSignerDryRun +_kSecCodeSignerEntitlements +_kSecCodeSignerFlags +_kSecCodeSignerIdentifier +_kSecCodeSignerIdentifierPrefix +_kSecCodeSignerIdentity +_kSecCodeSignerTimestampAuthentication +_kSecCodeSignerRequireTimestamp +_kSecCodeSignerTimestampServer +_kSecCodeSignerTimestampOmitCertificates +_kSecCodeSignerPageSize +_kSecCodeSignerRequirements +_kSecCodeSignerResourceRules +_kSecCodeSignerSDKRoot +_kSecCodeSignerSigningTime +_kSecCodeInfoCertificates +_kSecCodeInfoChangedFiles +_kSecCodeInfoCMS +_kSecCodeInfoTime +_kSecCodeInfoDesignatedRequirement +_kSecCodeInfoEntitlements +_kSecCodeInfoEntitlementsDict +_kSecCodeInfoFormat +_kSecCodeInfoDigestAlgorithm +_kSecCodeInfoIdentifier +_kSecCodeInfoImplicitDesignatedRequirement +_kSecCodeInfoMainExecutable +_kSecCodeInfoPList +_kSecCodeInfoRequirements +_kSecCodeInfoRequirementData +_kSecCodeInfoSource +_kSecCodeInfoStatus +_kSecCodeInfoTrust +_kSecCodeInfoUnique +_kSecCodeInfoCodeDirectory +_kSecCodeInfoCodeOffset +_kSecCodeInfoResourceDirectory +_kSecGuestAttributeCanonical +_kSecGuestAttributeHash +_kSecGuestAttributeMachPort +_kSecGuestAttributePid +_kSecRequirementKeyInfoPlist +_kSecRequirementKeyEntitlements +_kSecCFErrorArchitecture +_kSecCFErrorPattern +_kSecCFErrorResourceSeal +_kSecCFErrorResourceAdded +_kSecCFErrorResourceAltered +_kSecCFErrorResourceMissing +_kSecCFErrorInfoPlist +_kSecCFErrorGuestAttributes +_kSecCFErrorRequirementSyntax +_kSecCFErrorPath + +# Entitlements +_SecTaskGetTypeID +_SecTaskCreateWithAuditToken +_SecTaskCreateFromSelf +_SecTaskCopyValueForEntitlement +_SecTaskCopyValuesForEntitlements + +# Assessments +_SecAssessmentCreate +_SecAssessmentCopyResult +_SecAssessmentUpdate +_SecAssessmentControl +_kSecAssessmentContextKeyOperation +_kSecAssessmentOperationTypeExecute +_kSecAssessmentOperationTypeInstall +_kSecAssessmentOperationTypeOpenDocument +_kSecAssessmentContextKeyUpdate +_kSecAssessmentUpdateOperationAddFile +_kSecAssessmentUpdateOperationRemoveFile +_kSecAssessmentUpdateOperationAdd +_kSecAssessmentUpdateOperationRemove +_kSecAssessmentUpdateKeyAllow +_kSecAssessmentUpdateKeyExpires +_kSecAssessmentUpdateKeyLabel +_kSecAssessmentUpdateKeyPriority +_kSecAssessmentUpdateKeyRemarks +_kSecAssessmentAssessmentAuthority +_kSecAssessmentAssessmentAuthorityRow +_kSecAssessmentAssessmentFromCache +_kSecAssessmentAssessmentOriginator +_kSecAssessmentAssessmentAuthorityOverride +_kSecAssessmentAssessmentSource +_kSecAssessmentAssessmentVerdict +_kSecAssessmentContextKeyCertificates diff --git a/libsecurity_codesigning/lib/sigblob.cpp b/libsecurity_codesigning/lib/sigblob.cpp new file mode 100644 index 00000000..95ad32dc --- /dev/null +++ b/libsecurity_codesigning/lib/sigblob.cpp @@ -0,0 +1,65 @@ +/* + * 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@ + */ + +// +// sigblob - signature (Super)Blob types +// +#include "sigblob.h" +#include "CSCommon.h" + + +namespace Security { +namespace CodeSigning { + + +CFDataRef EmbeddedSignatureBlob::component(CodeDirectory::SpecialSlot slot) const +{ + if (const BlobCore *blob = this->find(slot)) + if (CodeDirectory::slotAttributes(slot) & cdComponentIsBlob) + return makeCFData(*blob); // is a native Blob + else if (const BlobWrapper *wrap = BlobWrapper::specific(blob)) + return makeCFData(*wrap); + else + MacOSError::throwMe(errSecCSSignatureInvalid); + return NULL; +} + + +void EmbeddedSignatureBlob::Maker::component(CodeDirectory::SpecialSlot slot, CFDataRef data) +{ + if (CodeDirectory::slotAttributes(slot) & cdComponentIsBlob) + add(slot, reinterpret_cast(CFDataGetBytePtr(data))->clone()); + else + add(slot, BlobWrapper::alloc(CFDataGetBytePtr(data), CFDataGetLength(data))); +} + + +CFDictionaryRef EntitlementBlob::entitlements() const +{ + return makeCFDictionaryFrom(this->at(sizeof(EntitlementBlob)), + this->length() - sizeof(EntitlementBlob)); +} + + +} // end namespace CodeSigning +} // end namespace Security diff --git a/libsecurity_codesigning/lib/sigblob.h b/libsecurity_codesigning/lib/sigblob.h new file mode 100644 index 00000000..c90f5e8e --- /dev/null +++ b/libsecurity_codesigning/lib/sigblob.h @@ -0,0 +1,81 @@ +/* + * 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@ + */ + +// +// sigblob - signature (Super)Blob types +// +#ifndef _H_SIGBLOB +#define _H_SIGBLOB + +#include "codedirectory.h" +#include +#include + +namespace Security { +namespace CodeSigning { + + +// +// An EmbeddedSignatureBlob is a SuperBlob indexed by component slot number. +// This is what we embed in Mach-O images. It is also what we use for detached +// signatures for non-Mach-O binaries. +// +class EmbeddedSignatureBlob : public SuperBlobCore { + typedef SuperBlobCore _Core; +public: + CFDataRef component(CodeDirectory::SpecialSlot slot) const; + + class Maker : public _Core::Maker { + public: + void component(CodeDirectory::SpecialSlot type, CFDataRef data); + }; +}; + + +// +// A DetachedSignatureBlob collects multiple architectures' worth of +// EmbeddedSignatureBlobs into one, well, Super-SuperBlob. +// This is what we use for Mach-O detached signatures. +// +typedef SuperBlob<0xfade0cc1> DetachedSignatureBlob; // indexed by main architecture + + +// +// The linkers produces a superblob of dependency records from its dylib inputs +// +typedef SuperBlob<0xfade0c05> LibraryDependencyBlob; // indexed sequentially from 0 + + +// +// An entitlement blob is used for embedding entitlement configuration data +// +class EntitlementBlob : public Blob { +public: + CFDictionaryRef entitlements() const; +}; + + +} // end namespace CodeSigning +} // end namespace Security + +#endif // !_H_SIGBLOB diff --git a/libsecurity_codesigning/lib/signer.cpp b/libsecurity_codesigning/lib/signer.cpp new file mode 100644 index 00000000..fc0c58f5 --- /dev/null +++ b/libsecurity_codesigning/lib/signer.cpp @@ -0,0 +1,426 @@ +/* + * 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@ + */ + +// +// signer - Signing operation supervisor and controller +// +#include "signer.h" +#include "resources.h" +#include "signerutils.h" +#include "SecCodeSigner.h" +#include +#include +#include +#include +#include +#include "renum.h" +#include "machorep.h" +#include "csutilities.h" +#include +#include +#include + +namespace Security { +namespace CodeSigning { + + +// +// Sign some code. +// +void SecCodeSigner::Signer::sign(SecCSFlags flags) +{ + rep = code->diskRep()->base(); + this->prepare(flags); + PreSigningContext context(*this); + if (Universal *fat = state.mNoMachO ? NULL : rep->mainExecutableImage()) { + signMachO(fat, context); + } else { + signArchitectureAgnostic(context); + } +} + + +// +// Remove any existing code signature from code +// +void SecCodeSigner::Signer::remove(SecCSFlags flags) +{ + // can't remove a detached signature + if (state.mDetached) + MacOSError::throwMe(errSecCSNotSupported); + + rep = code->diskRep(); + if (Universal *fat = state.mNoMachO ? NULL : rep->mainExecutableImage()) { + // architecture-sensitive removal + MachOEditor editor(rep->writer(), *fat, kSecCodeSignatureNoHash, rep->mainExecutablePath()); + editor.allocate(); // create copy + editor.commit(); // commit change + } else { + // architecture-agnostic removal + RefPointer writer = rep->writer(); + writer->remove(); + writer->flush(); + } +} + + +// +// Contemplate the object-to-be-signed and set up the Signer state accordingly. +// +void SecCodeSigner::Signer::prepare(SecCSFlags flags) +{ + // get the Info.plist out of the rep for some creative defaulting + CFRef infoDict; + if (CFRef infoData = rep->component(cdInfoSlot)) + infoDict.take(makeCFDictionaryFrom(infoData)); + + // work out the canonical identifier + identifier = state.mIdentifier; + if (identifier.empty()) { + identifier = rep->recommendedIdentifier(state); + if (identifier.find('.') == string::npos) + identifier = state.mIdentifierPrefix + identifier; + if (identifier.find('.') == string::npos && state.isAdhoc()) + identifier = identifier + "-" + uniqueName(); + secdebug("signer", "using default identifier=%s", identifier.c_str()); + } else + secdebug("signer", "using explicit identifier=%s", identifier.c_str()); + + // work out the CodeDirectory flags word + if (state.mCdFlagsGiven) { + cdFlags = state.mCdFlags; + secdebug("signer", "using explicit cdFlags=0x%x", cdFlags); + } else { + cdFlags = 0; + if (infoDict) + if (CFTypeRef csflags = CFDictionaryGetValue(infoDict, CFSTR("CSFlags"))) { + if (CFGetTypeID(csflags) == CFNumberGetTypeID()) { + cdFlags = cfNumber(CFNumberRef(csflags)); + secdebug("signer", "using numeric cdFlags=0x%x from Info.plist", cdFlags); + } else if (CFGetTypeID(csflags) == CFStringGetTypeID()) { + cdFlags = cdTextFlags(cfString(CFStringRef(csflags))); + secdebug("signer", "using text cdFlags=0x%x from Info.plist", cdFlags); + } else + MacOSError::throwMe(errSecCSBadDictionaryFormat); + } + } + if (state.mSigner == SecIdentityRef(kCFNull)) // ad-hoc signing requested... + cdFlags |= kSecCodeSignatureAdhoc; // ... so note that + + // prepare the resource directory, if any + string rpath = rep->resourcesRootPath(); + if (!rpath.empty()) { + // explicitly given resource rules always win + CFCopyRef resourceRules = state.mResourceRules; + + // embedded resource rules come next + if (!resourceRules && infoDict) + if (CFTypeRef spec = CFDictionaryGetValue(infoDict, _kCFBundleResourceSpecificationKey)) { + if (CFGetTypeID(spec) == CFStringGetTypeID()) + if (CFRef data = cfLoadFile(rpath + "/" + cfString(CFStringRef(spec)))) + if (CFDictionaryRef dict = makeCFDictionaryFrom(data)) + resourceRules.take(dict); + if (!resourceRules) // embedded rules present but unacceptable + MacOSError::throwMe(errSecCSResourceRulesInvalid); + } + + // finally, ask the DiskRep for its default + if (!resourceRules) + resourceRules.take(rep->defaultResourceRules(state)); + + // build the resource directory + ResourceBuilder resources(rpath, cfget(resourceRules, "rules"), digestAlgorithm()); + rep->adjustResources(resources); // DiskRep-specific adjustments + CFRef rdir = resources.build(); + resourceDirectory.take(CFPropertyListCreateXMLData(NULL, rdir)); + } + + // screen and set the signing time + CFAbsoluteTime now = CFAbsoluteTimeGetCurrent(); + if (state.mSigningTime == CFDateRef(kCFNull)) { + signingTime = 0; // no time at all + } else if (!state.mSigningTime) { + signingTime = now; // default + } else { + CFAbsoluteTime time = CFDateGetAbsoluteTime(state.mSigningTime); + if (time > now) // not allowed to post-date a signature + MacOSError::throwMe(errSecCSBadDictionaryFormat); + signingTime = time; + } + + pagesize = state.mPageSize ? cfNumber(state.mPageSize) : rep->pageSize(state); + + // Timestamping setup + CFRef mTSAuth; // identity for client-side authentication to the Timestamp server +} + + +// +// Sign a Mach-O binary, using liberal dollops of that special Mach-O magic sauce. +// Note that this will deal just fine with non-fat Mach-O binaries, but it will +// treat them as architectural binaries containing (only) one architecture - that +// interpretation is courtesy of the Universal/MachO support classes. +// +void SecCodeSigner::Signer::signMachO(Universal *fat, const Requirement::Context &context) +{ + // Mach-O executable at the core - perform multi-architecture signing + auto_ptr editor(state.mDetached + ? static_cast(new BlobEditor(*fat, *this)) + : new MachOEditor(rep->writer(), *fat, this->digestAlgorithm(), rep->mainExecutablePath())); + assert(editor->count() > 0); + if (!editor->attribute(writerNoGlobal)) // can store architecture-common components + populate(*editor); + + // pass 1: prepare signature blobs and calculate sizes + for (MachOEditor::Iterator it = editor->begin(); it != editor->end(); ++it) { + MachOEditor::Arch &arch = *it->second; + arch.source.reset(fat->architecture(it->first)); + arch.ireqs(state.mRequirements, rep->defaultRequirements(&arch.architecture, state), context); + if (editor->attribute(writerNoGlobal)) // can't store globally, add per-arch + populate(arch); + populate(arch.cdbuilder, arch, arch.ireqs, + arch.source->offset(), arch.source->signingExtent()); + + // add identification blob (made from this architecture) only if we're making a detached signature + if (state.mDetached) { + CFRef identification = MachORep::identificationFor(arch.source.get()); + arch.add(cdIdentificationSlot, BlobWrapper::alloc( + CFDataGetBytePtr(identification), CFDataGetLength(identification))); + } + + // prepare SuperBlob size estimate + size_t cdSize = arch.cdbuilder.size(); + arch.blobSize = arch.size(cdSize, state.mCMSSize, 0); + } + + editor->allocate(); + + // pass 2: Finish and generate signatures, and write them + for (MachOEditor::Iterator it = editor->begin(); it != editor->end(); ++it) { + MachOEditor::Arch &arch = *it->second; + editor->reset(arch); + + // finish CodeDirectory (off new binary) and sign it + CodeDirectory *cd = arch.cdbuilder.build(); + CFRef signature = signCodeDirectory(cd); + + // complete the SuperBlob + arch.add(cdCodeDirectorySlot, cd); // takes ownership + arch.add(cdSignatureSlot, BlobWrapper::alloc( + CFDataGetBytePtr(signature), CFDataGetLength(signature))); + if (!state.mDryRun) { + EmbeddedSignatureBlob *blob = arch.make(); + editor->write(arch, blob); // takes ownership of blob + } + } + + // done: write edit copy back over the original + if (!state.mDryRun) + editor->commit(); +} + + +// +// Sign a binary that has no notion of architecture. +// That currently means anything that isn't Mach-O format. +// +void SecCodeSigner::Signer::signArchitectureAgnostic(const Requirement::Context &context) +{ + // non-Mach-O executable - single-instance signing + RefPointer writer = state.mDetached ? + (new DetachedBlobWriter(*this)) : rep->writer(); + CodeDirectory::Builder builder(state.mDigestAlgorithm); + InternalRequirements ireqs; + ireqs(state.mRequirements, rep->defaultRequirements(NULL, state), context); + populate(*writer); + populate(builder, *writer, ireqs, rep->signingBase(), rep->signingLimit()); + + // add identification blob (made from this architecture) only if we're making a detached signature + if (state.mDetached) { + CFRef identification = rep->identification(); + writer->component(cdIdentificationSlot, identification); + } + + CodeDirectory *cd = builder.build(); + CFRef signature = signCodeDirectory(cd); + if (!state.mDryRun) { + writer->codeDirectory(cd); + writer->signature(signature); + writer->flush(); + } + ::free(cd); +} + + +// +// Global populate - send components to destination buffers ONCE +// +void SecCodeSigner::Signer::populate(DiskRep::Writer &writer) +{ + if (resourceDirectory) + writer.component(cdResourceDirSlot, resourceDirectory); +} + + +// +// Per-architecture populate - send components to per-architecture buffers +// and populate the CodeDirectory for an architecture. In architecture-agnostic +// signing operations, the non-architectural binary is considered one (arbitrary) architecture +// for the purposes of this call. +// +void SecCodeSigner::Signer::populate(CodeDirectory::Builder &builder, DiskRep::Writer &writer, + InternalRequirements &ireqs, size_t offset /* = 0 */, size_t length /* = 0 */) +{ + // fill the CodeDirectory + builder.executable(rep->mainExecutablePath(), pagesize, offset, length); + builder.flags(cdFlags); + builder.identifier(identifier); + + if (CFRef data = rep->component(cdInfoSlot)) + builder.specialSlot(cdInfoSlot, data); + if (ireqs) { + CFRef data = makeCFData(*ireqs); + writer.component(cdRequirementsSlot, data); + builder.specialSlot(cdRequirementsSlot, data); + } + if (resourceDirectory) + builder.specialSlot(cdResourceDirSlot, resourceDirectory); +#if NOT_YET + if (state.mApplicationData) + builder.specialSlot(cdApplicationSlot, state.mApplicationData); +#endif + if (state.mEntitlementData) { + writer.component(cdEntitlementSlot, state.mEntitlementData); + builder.specialSlot(cdEntitlementSlot, state.mEntitlementData); + } + + writer.addDiscretionary(builder); +} + +#include + +// +// Generate the CMS signature for a (finished) CodeDirectory. +// +CFDataRef SecCodeSigner::Signer::signCodeDirectory(const CodeDirectory *cd) +{ + assert(state.mSigner); + CFRef defaultTSContext = NULL; + + // a null signer generates a null signature blob + if (state.mSigner == SecIdentityRef(kCFNull)) + return CFDataCreate(NULL, NULL, 0); + + // generate CMS signature + CFRef cms; + MacOSError::check(CMSEncoderCreate(&cms.aref())); + MacOSError::check(CMSEncoderSetCertificateChainMode(cms, kCMSCertificateChainWithRoot)); + CMSEncoderAddSigners(cms, state.mSigner); + MacOSError::check(CMSEncoderSetHasDetachedContent(cms, true)); + + if (signingTime) { + MacOSError::check(CMSEncoderAddSignedAttributes(cms, kCMSAttrSigningTime)); + MacOSError::check(CMSEncoderSetSigningTime(cms, signingTime)); + } + + MacOSError::check(CMSEncoderUpdateContent(cms, cd, cd->length())); + + // Set up to call Timestamp server if requested + + if (state.mWantTimeStamp) + { + CFRef error = NULL; + defaultTSContext = SecCmsTSAGetDefaultContext(&error.aref()); + if (error) + MacOSError::throwMe(errSecDataNotAvailable); + + if (state.mNoTimeStampCerts || state.mTimestampService) { + if (state.mTimestampService) + CFDictionarySetValue(defaultTSContext, kTSAContextKeyURL, state.mTimestampService); + if (state.mNoTimeStampCerts) + CFDictionarySetValue(defaultTSContext, kTSAContextKeyNoCerts, kCFBooleanTrue); + } + + CmsMessageSetTSAContext(cms, defaultTSContext); + } + + CFDataRef signature; + MacOSError::check(CMSEncoderCopyEncodedContent(cms, &signature)); + + return signature; +} + + +// +// Parse a text of the form +// flag,...,flag +// where each flag is the canonical name of a signable CodeDirectory flag. +// No abbreviations are allowed, and internally set flags are not accepted. +// +uint32_t SecCodeSigner::Signer::cdTextFlags(std::string text) +{ + uint32_t flags = 0; + for (string::size_type comma = text.find(','); ; text = text.substr(comma+1), comma = text.find(',')) { + string word = (comma == string::npos) ? text : text.substr(0, comma); + const SecCodeDirectoryFlagTable *item; + for (item = kSecCodeDirectoryFlagTable; item->name; item++) + if (item->signable && word == item->name) { + flags |= item->value; + break; + } + if (!item->name) // not found + MacOSError::throwMe(errSecCSInvalidFlags); + if (comma == string::npos) // last word + break; + } + return flags; +} + + +// +// Generate a unique string from our underlying DiskRep. +// We could get 90%+ of the uniquing benefit by just generating +// a random string here. Instead, we pick the (hex string encoding of) +// the source rep's unique identifier blob. For universal binaries, +// this is the canonical local architecture, which is a bit arbitrary. +// This provides us with a consistent unique string for all architectures +// of a fat binary, *and* (unlike a random string) is reproducible +// for identical inputs, even upon resigning. +// +std::string SecCodeSigner::Signer::uniqueName() const +{ + CFRef identification = rep->identification(); + const UInt8 *ident = CFDataGetBytePtr(identification); + const unsigned int length = CFDataGetLength(identification); + string result; + for (unsigned int n = 0; n < length; n++) { + char hex[3]; + snprintf(hex, sizeof(hex), "%02x", ident[n]); + result += hex; + } + return result; +} + + +} // end namespace CodeSigning +} // end namespace Security diff --git a/libsecurity_codesigning/lib/signer.h b/libsecurity_codesigning/lib/signer.h new file mode 100644 index 00000000..101f222f --- /dev/null +++ b/libsecurity_codesigning/lib/signer.h @@ -0,0 +1,87 @@ +/* + * 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@ + */ + +// +// signer - Signing operation supervisor and controller +// +#ifndef _H_SIGNER +#define _H_SIGNER + +#include "CodeSigner.h" +#include "cdbuilder.h" +#include "signerutils.h" +#include "StaticCode.h" +#include + +namespace Security { +namespace CodeSigning { + + +// +// The signer driver class. +// This is a workflow object, containing all the data needed for the various +// signing stages to cooperate. It is not meant to be API visible; that is +// SecCodeSigner's job. +// +class SecCodeSigner::Signer { +public: + Signer(SecCodeSigner &s, SecStaticCode *c) : state(s), code(c) { } + void sign(SecCSFlags flags); + void remove(SecCSFlags flags); + + SecCodeSigner &state; + SecStaticCode * const code; + + CodeDirectory::HashAlgorithm digestAlgorithm() const { return state.mDigestAlgorithm; } + + std::string path() const { return cfString(rep->canonicalPath()); } + SecIdentityRef signingIdentity() const { return state.mSigner; } + std::string signingIdentifier() const { return identifier; } + +protected: + void prepare(SecCSFlags flags); // set up signing parameters + void signMachO(Universal *fat, const Requirement::Context &context); // sign a Mach-O binary + void signArchitectureAgnostic(const Requirement::Context &context); // sign anything else + + void populate(DiskRep::Writer &writer); // global + void populate(CodeDirectory::Builder &builder, DiskRep::Writer &writer, + InternalRequirements &ireqs, size_t offset = 0, size_t length = 0); // per-architecture + CFDataRef signCodeDirectory(const CodeDirectory *cd); + + uint32_t cdTextFlags(std::string text); // convert text CodeDirectory flags + std::string uniqueName() const; // derive unique string from rep + +private: + RefPointer rep; // DiskRep of Code being signed + CFRef resourceDirectory; // resource directory + std::string identifier; // signing identifier + uint32_t cdFlags; // CodeDirectory flags + size_t pagesize; // size of main executable pages + CFAbsoluteTime signingTime; // signing time for CMS signature (0 => none) +}; + + +} // end namespace CodeSigning +} // end namespace Security + +#endif // !_H_CODESIGNER diff --git a/libsecurity_codesigning/lib/signerutils.cpp b/libsecurity_codesigning/lib/signerutils.cpp new file mode 100644 index 00000000..d03d884e --- /dev/null +++ b/libsecurity_codesigning/lib/signerutils.cpp @@ -0,0 +1,363 @@ +/* + * 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@ + */ + +// +// signerutils - utilities for signature generation +// +#include "signerutils.h" +#include "signer.h" +#include "SecCodeSigner.h" +#include +#include +#include "renum.h" +#include "csutilities.h" +#include "drmaker.h" +#include +#include +#include + +// for helper validation +#include "Code.h" +#include +#include + + +namespace Security { +namespace CodeSigning { + + +// +// About the Mach-O allocation helper +// +static const char helperName[] = "codesign_allocate"; +static const char helperPath[] = "/usr/bin/codesign_allocate"; +static const char helperOverride[] = "CODESIGN_ALLOCATE"; +static const size_t csAlign = 16; + + +// +// BlobWriters +// +void BlobWriter::component(CodeDirectory::SpecialSlot slot, CFDataRef data) +{ + return EmbeddedSignatureBlob::Maker::component(slot, data); +} + + +void DetachedBlobWriter::flush() +{ + EmbeddedSignatureBlob *blob = this->make(); + signer.code->detachedSignature(makeCFData(*blob)); + signer.state.returnDetachedSignature(blob, signer); + ::free(blob); +} + + +// +// ArchEditor +// +ArchEditor::ArchEditor(Universal &code, CodeDirectory::HashAlgorithm hashType, uint32_t attrs) + : DiskRep::Writer(attrs) +{ + Universal::Architectures archList; + code.architectures(archList); + for (Universal::Architectures::const_iterator it = archList.begin(); + it != archList.end(); ++it) + architecture[*it] = new Arch(*it, hashType); +} + + +ArchEditor::~ArchEditor() +{ + for (ArchMap::iterator it = begin(); it != end(); ++it) + delete it->second; +} + + +// +// BlobEditor +// +BlobEditor::BlobEditor(Universal &fat, SecCodeSigner::Signer &s) + : ArchEditor(fat, s.digestAlgorithm(), 0), signer(s) +{ } + + +void BlobEditor::component(CodeDirectory::SpecialSlot slot, CFDataRef data) +{ + mGlobal.component(slot, data); +} + +void BlobEditor::write(Arch &arch, EmbeddedSignatureBlob *blob) +{ + mMaker.add(arch.architecture.cpuType(), blob); +} + + +void BlobEditor::commit() +{ + // create the architecture-global blob and store it into the superblob + mMaker.add(0, mGlobal.make()); // takes ownership of blob + + // finish up the superblob and deliver it + DetachedSignatureBlob *blob = mMaker.make(); + signer.state.returnDetachedSignature(blob, signer); + ::free(blob); +} + + +// +// MachOEditor's allocate() method spawns the codesign_allocate helper tool to +// "drill up" the Mach-O binary for insertion of Code Signing signature data. +// After the tool succeeds, we open the new file and are ready to write it. +// +MachOEditor::MachOEditor(DiskRep::Writer *w, Universal &code, CodeDirectory::HashAlgorithm hashType, std::string srcPath) + : ArchEditor(code, hashType, w->attributes()), + writer(w), + sourcePath(srcPath), + tempPath(srcPath + ".cstemp"), + mNewCode(NULL), + mTempMayExist(false) +{ + if (const char *path = getenv(helperOverride)) { + mHelperPath = path; + mHelperOverridden = true; + } else { + mHelperPath = helperPath; + mHelperOverridden = false; + } +} + +MachOEditor::~MachOEditor() +{ + delete mNewCode; + if (mTempMayExist) + ::remove(tempPath.c_str()); // ignore error (can't do anything about it) + this->kill(); +} + + +void MachOEditor::component(CodeDirectory::SpecialSlot slot, CFDataRef data) +{ + writer->component(slot, data); +} + + +void MachOEditor::allocate() +{ + // note that we may have a temporary file from now on (for cleanup in the error case) + mTempMayExist = true; + + // run codesign_allocate to make room in the executable file + fork(); + wait(); + if (!Child::succeeded()) + UnixError::throwMe(ENOEXEC); //@@@ how to signal "it din' work"? + + // open the new (temporary) Universal file + { + UidGuard guard(0); + mFd.open(tempPath, O_RDWR); + } + mNewCode = new Universal(mFd); +} + +static const unsigned char appleReq[] = { + // anchor apple and info["Application-Group"] = "com.apple.tool.codesign_allocate" + 0xfa, 0xde, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x11, 0x41, 0x70, 0x70, 0x6c, + 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x63, 0x6f, 0x6d, 0x2e, 0x61, 0x70, 0x70, 0x6c, + 0x65, 0x2e, 0x74, 0x6f, 0x6f, 0x6c, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x73, 0x69, 0x67, 0x6e, 0x5f, + 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x65, +}; + +void MachOEditor::parentAction() +{ + if (mHelperOverridden) { + CODESIGN_ALLOCATE_VALIDATE((char*)mHelperPath, this->pid()); + // check code identity of an overridden allocation helper + SecPointer code = new SecStaticCode(DiskRep::bestGuess(mHelperPath)); + code->validateDirectory(); + code->validateExecutable(); + code->validateResources(); + code->validateRequirement((const Requirement *)appleReq, errSecCSReqFailed); + } +} + +void MachOEditor::childAction() +{ + vector arguments; + arguments.push_back(helperName); + arguments.push_back("-i"); + arguments.push_back(sourcePath.c_str()); + arguments.push_back("-o"); + arguments.push_back(tempPath.c_str()); + + for (Iterator it = architecture.begin(); it != architecture.end(); ++it) { + size_t size = LowLevelMemoryUtilities::alignUp(it->second->blobSize, csAlign); + char *ssize; // we'll leak this (execv is coming soon) + asprintf(&ssize, "%zd", size); + + if (const char *arch = it->first.name()) { + CODESIGN_ALLOCATE_ARCH((char*)arch, size); + arguments.push_back("-a"); + arguments.push_back(arch); + } else { + CODESIGN_ALLOCATE_ARCHN(it->first.cpuType(), it->first.cpuSubtype(), size); + arguments.push_back("-A"); + char *anum; + asprintf(&anum, "%d", it->first.cpuType()); + arguments.push_back(anum); + asprintf(&anum, "%d", it->first.cpuSubtype()); + arguments.push_back(anum); + } + arguments.push_back(ssize); + } + arguments.push_back(NULL); + + if (mHelperOverridden) + ::csops(0, CS_EXEC_SET_KILL, NULL, 0); // force code integrity + ::seteuid(0); // activate privilege if caller has it; ignore error if not + execv(mHelperPath, (char * const *)&arguments[0]); +} + +void MachOEditor::reset(Arch &arch) +{ + arch.source.reset(mNewCode->architecture(arch.architecture)); + arch.cdbuilder.reopen(tempPath, + arch.source->offset(), arch.source->signingOffset()); +} + + +// +// MachOEditor's write() method actually writes the blob into the CODESIGNING section +// of the executable image file. +// +void MachOEditor::write(Arch &arch, EmbeddedSignatureBlob *blob) +{ + if (size_t offset = arch.source->signingOffset()) { + size_t signingLength = arch.source->signingLength(); + CODESIGN_ALLOCATE_WRITE((char*)arch.architecture.name(), offset, blob->length(), signingLength); + if (signingLength < blob->length()) + MacOSError::throwMe(errSecCSCMSTooLarge); + arch.source->seek(offset); + arch.source->writeAll(*blob); + ::free(blob); // done with it + } else { + secdebug("signer", "%p cannot find CODESIGNING section", this); + MacOSError::throwMe(errSecCSInternalError); + } +} + + +// +// Commit the edit. +// This moves the temporary editor copy over the source image file. +// Note that the Universal object returned by allocate() is still open +// and valid; the caller owns it. +// +void MachOEditor::commit() +{ + // if the file's owned by someone else *and* we can become root... + struct stat st; + UnixError::check(::stat(sourcePath.c_str(), &st)); + + // copy over all the *other* stuff + Copyfile copy; + int fd = mFd; + copy.set(COPYFILE_STATE_DST_FD, &fd); + { + // perform copy under root or file-owner privileges if available + UidGuard guard; + if (!guard.seteuid(0)) + guard.seteuid(st.st_uid); + + // copy metadata from original file... + copy(sourcePath.c_str(), NULL, COPYFILE_SECURITY | COPYFILE_METADATA); + + // ... but explicitly update the timestamps since we did change the file + char buf; + mFd.read(&buf, sizeof(buf), 0); + mFd.write(&buf, sizeof(buf), 0); + + // move the new file into place + UnixError::check(::rename(tempPath.c_str(), sourcePath.c_str())); + mTempMayExist = false; // we renamed it away + } +} + + +// +// InternalRequirements +// +void InternalRequirements::operator () (const Requirements *given, const Requirements *defaulted, const Requirement::Context &context) +{ + // first add the default internal requirements + if (defaulted) { + this->add(defaulted); + ::free((void *)defaulted); // was malloc(3)ed by DiskRep + } + + // now override them with any requirements explicitly given by the signer + if (given) + this->add(given); + + // now add the Designated Requirement, if we can make it and it's not been provided + if (!this->contains(kSecDesignatedRequirementType)) { + DRMaker maker(context); + if (Requirement *dr = maker.make()) { + this->add(kSecDesignatedRequirementType, dr); // takes ownership of dr + } + } + + // return the result + mReqs = this->make(); +} + + +// +// Pre-Signing contexts +// +PreSigningContext::PreSigningContext(const SecCodeSigner::Signer &signer) +{ + // construct a cert chain + if (signer.signingIdentity() != SecIdentityRef(kCFNull)) { + CFRef signingCert; + MacOSError::check(SecIdentityCopyCertificate(signer.signingIdentity(), &signingCert.aref())); + CFRef policy = SecPolicyCreateWithOID(kSecPolicyAppleCodeSigning); + CFRef trust; + MacOSError::check(SecTrustCreateWithCertificates(CFArrayRef(signingCert.get()), policy, &trust.aref())); + SecTrustResultType result; + MacOSError::check(SecTrustEvaluate(trust, &result)); + CSSM_TP_APPLE_EVIDENCE_INFO *info; + MacOSError::check(SecTrustGetResult(trust, &result, &mCerts.aref(), &info)); + this->certs = mCerts; + } + + // other stuff + this->identifier = signer.signingIdentifier(); +} + + +} // end namespace CodeSigning +} // end namespace Security diff --git a/libsecurity_codesigning/lib/signerutils.h b/libsecurity_codesigning/lib/signerutils.h new file mode 100644 index 00000000..3fdb0815 --- /dev/null +++ b/libsecurity_codesigning/lib/signerutils.h @@ -0,0 +1,201 @@ +/* + * 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@ + */ + +// +// signerutils - utilities for signature generation +// +#ifndef _H_SIGNERUTILS +#define _H_SIGNERUTILS + +#include "CodeSigner.h" +#include "sigblob.h" +#include "cdbuilder.h" +#include +#include +#include +#include + +namespace Security { +namespace CodeSigning { + + +// +// A helper to deal with the magic merger logic of internal requirements +// +class InternalRequirements : public Requirements::Maker { +public: + InternalRequirements() : mReqs(NULL) { } + ~InternalRequirements() { ::free((void *)mReqs); } + void operator () (const Requirements *given, const Requirements *defaulted, const Requirement::Context &context); + operator const Requirements * () const { return mReqs; } + +private: + const Requirements *mReqs; +}; + + +// +// A DiskRep::Writer that assembles data in a SuperBlob (in memory) +// +class BlobWriter : public DiskRep::Writer, public EmbeddedSignatureBlob::Maker { +public: + void component(CodeDirectory::SpecialSlot slot, CFDataRef data); +}; + + +class DetachedBlobWriter : public BlobWriter { +public: + DetachedBlobWriter(SecCodeSigner::Signer &s) : signer(s) { } + + SecCodeSigner::Signer &signer; + + void flush(); +}; + + +// +// A multi-architecture editing assistant. +// ArchEditor collects (Mach-O) architectures in use, and maintains per-archtitecture +// data structures. It must be subclassed to express a particular way to handle the signing +// data. +// +class ArchEditor : public DiskRep::Writer { +public: + ArchEditor(Universal &fat, CodeDirectory::HashAlgorithm hashType, uint32_t attrs); + virtual ~ArchEditor(); + +public: + // + // One architecture's signing construction element. + // This also implements DispRep::Writer so generic writing code + // can work with both Mach-O and other files. + // + struct Arch : public BlobWriter { + Architecture architecture; // our architecture + auto_ptr source; // Mach-O object to be signed + CodeDirectory::Builder cdbuilder; // builder for CodeDirectory + InternalRequirements ireqs; // consolidated internal requirements + size_t blobSize; // calculated SuperBlob size + + Arch(const Architecture &arch, CodeDirectory::HashAlgorithm hashType) + : architecture(arch), cdbuilder(hashType) { } + }; + + // + // Our callers access the architectural universe through a map + // from Architectures to Arch objects. + // + typedef std::map ArchMap; + typedef ArchMap::iterator Iterator; + ArchMap::iterator begin() { return architecture.begin(); } + ArchMap::iterator end() { return architecture.end(); } + unsigned count() const { return architecture.size(); } + + // methods needed for an actual implementation + virtual void allocate() = 0; // interpass allocations + virtual void reset(Arch &arch) = 0; // pass 2 prep + virtual void write(Arch &arch, EmbeddedSignatureBlob *blob) = 0; // takes ownership of blob + virtual void commit() = 0; // write/flush result + +protected: + ArchMap architecture; +}; + + +// +// An ArchEditor that collects all architectures into a single SuperBlob, +// usually for writing a detached multi-architecture signature. +// +class BlobEditor : public ArchEditor { +public: + BlobEditor(Universal &fat, SecCodeSigner::Signer &s); + + SecCodeSigner::Signer &signer; + + void component(CodeDirectory::SpecialSlot slot, CFDataRef data); + void allocate() { } + void reset(Arch &arch) { } + void write(Arch &arch, EmbeddedSignatureBlob *blob); + void commit(); + +private: + DetachedSignatureBlob::Maker mMaker; + EmbeddedSignatureBlob::Maker mGlobal; +}; + + +// +// An ArchEditor that writes its signatures into a (fat) binary file. +// We do this by forking a helper tool (codesign_allocate) and asking +// it to make a copy with suitable space "opened up" in the right spots. +// +class MachOEditor : public ArchEditor, private UnixPlusPlus::Child { +public: + MachOEditor(DiskRep::Writer *w, Universal &code, CodeDirectory::HashAlgorithm hashType, std::string srcPath); + ~MachOEditor(); + + const RefPointer writer; + const std::string sourcePath; + const std::string tempPath; + + void component(CodeDirectory::SpecialSlot slot, CFDataRef data); + void allocate(); + void reset(Arch &arch); + void write(Arch &arch, EmbeddedSignatureBlob *blob); + void commit(); + +private: + // fork operation + void childAction(); + void parentAction(); + + // controlling the temporary file copy + Universal *mNewCode; + UnixPlusPlus::AutoFileDesc mFd; + bool mTempMayExist; + + // finding and managing the helper tool + const char *mHelperPath; + bool mHelperOverridden; +}; + + +// +// A Requirement::Context populated from a signing request. +// We use this to help generate the explicit Designated Requirement +// during signing ops, and thus this must be constructed BEFORE we +// actually have a signed object. +// +class PreSigningContext : public Requirement::Context { +public: + PreSigningContext(const SecCodeSigner::Signer &signer); + +private: + CFRef mCerts; // hold cert chain +}; + + +} // end namespace CodeSigning +} // end namespace Security + +#endif // !_H_SIGNERUTILS diff --git a/libsecurity_codesigning/lib/singlediskrep.cpp b/libsecurity_codesigning/lib/singlediskrep.cpp new file mode 100644 index 00000000..154ed2e9 --- /dev/null +++ b/libsecurity_codesigning/lib/singlediskrep.cpp @@ -0,0 +1,127 @@ +/* + * 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@ + */ + +// +// singlediskrep - semi-abstract diskrep for a single file of some kind +// +#include "singlediskrep.h" +#include "csutilities.h" +#include + +namespace Security { +namespace CodeSigning { + +using namespace UnixPlusPlus; + + +// +// Construct a SingleDiskRep +// +SingleDiskRep::SingleDiskRep(const std::string &path) + : mPath(path) +{ +} + + +// +// The default binary identification of a SingleDiskRep is the (SHA-1) hash +// of the entire file itself. +// +CFDataRef SingleDiskRep::identification() +{ + SHA1 hash; + this->fd().seek(0); + hashFileData(this->fd(), &hash); + SHA1::Digest digest; + hash.finish(digest); + return makeCFData(digest, sizeof(digest)); +} + + +// +// Both the canonical and main executable path of a SingleDiskRep is, well, its path. +// +CFURLRef SingleDiskRep::canonicalPath() +{ + return makeCFURL(mPath); +} + +string SingleDiskRep::mainExecutablePath() +{ + return mPath; +} + + +// +// The default signing limit is the size of the file. +// This will do unless the signing data gets creatively stuck in there somewhere. +// +size_t SingleDiskRep::signingLimit() +{ + return fd().fileSize(); +} + + +// +// A lazily opened read-only file descriptor for the path. +// +FileDesc &SingleDiskRep::fd() +{ + if (!mFd) + mFd.open(mPath, O_RDONLY); + return mFd; +} + + +// +// Flush cached state +// +void SingleDiskRep::flush() +{ + mFd.close(); +} + + +// +// The recommended identifier of a SingleDiskRep is, absent any better clue, +// the basename of its path. +// +string SingleDiskRep::recommendedIdentifier(const SigningContext &) +{ + return canonicalIdentifier(mPath); +} + + +// +// Prototype Writers +// +FileDesc &SingleDiskRep::Writer::fd() +{ + if (!mFd) + mFd.open(rep->path(), O_RDWR); + return mFd; +} + + +} // end namespace CodeSigning +} // end namespace Security diff --git a/libsecurity_codesigning/lib/singlediskrep.h b/libsecurity_codesigning/lib/singlediskrep.h new file mode 100644 index 00000000..2ff73e10 --- /dev/null +++ b/libsecurity_codesigning/lib/singlediskrep.h @@ -0,0 +1,89 @@ +/* + * 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@ + */ + +// +// singlediskrep - semi-abstract diskrep for a single file of some kind +// +#ifndef _H_SINGLEDISKREP +#define _H_SINGLEDISKREP + +#include "diskrep.h" +#include + +namespace Security { +namespace CodeSigning { + + +// +// A slight specialization of DiskRep that knows that it's working with a single +// file at a path that is both the canonical and main executable path. This is a common +// pattern. +// +// A SingleDiskRep is not a fully formed DiskRep in its own right. It must be further +// subclassed. +// +class SingleDiskRep : public DiskRep { +public: + SingleDiskRep(const std::string &path); + + CFDataRef identification(); // partial file hash + std::string mainExecutablePath(); // base path + CFURLRef canonicalPath(); // base path + size_t signingLimit(); // size of file + UnixPlusPlus::FileDesc &fd(); // readable fd for this file + void flush(); // close cached fd + + std::string recommendedIdentifier(const SigningContext &ctx); // basename(path) + +public: + class Writer; + +protected: + std::string path() const { return mPath; } + +private: + std::string mPath; + UnixPlusPlus::AutoFileDesc mFd; // open file (cached) +}; + + +// +// A Writer for a SingleDiskRep +// +class SingleDiskRep::Writer : public DiskRep::Writer { +public: + Writer(SingleDiskRep *r, uint32_t attrs = 0) : DiskRep::Writer(attrs), rep(r) { } + + UnixPlusPlus::FileDesc &fd(); + +private: + RefPointer rep; // underlying SingleDiskRep + UnixPlusPlus::AutoFileDesc mFd; // cached writable fd +}; + + + +} // end namespace CodeSigning +} // end namespace Security + +#endif // !_H_SINGLEDISKREP diff --git a/libsecurity_codesigning/lib/slcrep.cpp b/libsecurity_codesigning/lib/slcrep.cpp new file mode 100644 index 00000000..254d651e --- /dev/null +++ b/libsecurity_codesigning/lib/slcrep.cpp @@ -0,0 +1,162 @@ +/* + * Copyright (c) 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@ + */ + +// +// slcrep - DiskRep representing the Mac OS Shared Library Cache +// +#include "slcrep.h" + + +namespace Security { +namespace CodeSigning { + +using namespace UnixPlusPlus; + + +// +// Object management. +// We open the file lazily, so nothing much happens on constructions. +// We can construct directly from a file path, or from an architecture +// (represented by Context), which will find the file in its usual +// location on disk. +// +DYLDCacheRep::DYLDCacheRep(const char *path) + : SingleDiskRep(path), mCache(path) +{ + this->setup(); +} + +DYLDCacheRep::DYLDCacheRep(const Context *ctx) + : SingleDiskRep(DYLDCache::pathFor(((ctx && ctx->arch) ? ctx->arch : Architecture::local()))), + mCache(this->path()) +{ + this->setup(); +} + +void DYLDCacheRep::setup() +{ + mSigningData = NULL; + if (mCache.totalSize() >= mCache.mapSize() + sizeof(BlobCore)) { + const EmbeddedSignatureBlob *blob = mCache.at(mCache.mapSize()); + if (mCache.totalSize() >= mCache.mapSize() + blob->length()) // entire blob fits in file + mSigningData = blob; + } + CODESIGN_DISKREP_CREATE_SLC(this, (char*)this->mainExecutablePath().c_str()); +} + + +// +// Sniffer function for "plausible shared library cache file". +// +bool DYLDCacheRep::candidate(FileDesc &fd) +{ + return DYLDCache::validate(fd); +} + + +// +// Default to system page size for segmented (paged) signatures +// +size_t DYLDCacheRep::pageSize(const SigningContext &) +{ + return segmentedPageSize; +} + + +// +// Retrieve a component from the executable. +// Our mCache has mapped the entire file, so we just fish the contents out of +// the mapped area as needed. +// +CFDataRef DYLDCacheRep::component(CodeDirectory::SpecialSlot slot) +{ + return mSigningData ? mSigningData->component(slot) : NULL; +} + + +// +// Provide a (vaguely) human readable characterization of this code +// +string DYLDCacheRep::format() +{ + if (const char *name = mCache.architecture().name()) { + char result[100]; + snprintf(result, sizeof(result), "OS X Shared Library Cache (%s @ 0x%llx)", + name, mCache.baseAddress()); + return result; + } else + return "OS X Shared Library Cache (unknown type)"; +} + + +// +// DYLDCacheRep::Writers +// +DiskRep::Writer *DYLDCacheRep::writer() +{ + return new Writer(this); +} + + +// +// Write a component. +// +void DYLDCacheRep::Writer::component(CodeDirectory::SpecialSlot slot, CFDataRef data) +{ + EmbeddedSignatureBlob::Maker::component(slot, data); +} + + +// +// Append the superblob we built to the cache file. +// +void DYLDCacheRep::Writer::flush() +{ + delete mSigningData; // ditch previous blob just in case + mSigningData = Maker::make(); // assemble new signature SuperBlob + fd().seek(rep->mCache.mapSize()); // end of impage proper + fd().writeAll(*mSigningData); +} + + +// +// The discretionary additions insert a Scatter vector describing the file's mapping table. +// +void DYLDCacheRep::Writer::addDiscretionary(CodeDirectory::Builder &builder) +{ + unsigned count = rep->mCache.mappingCount(); + builder.scatter(count); + for (unsigned n = 0; n < count; n++) { + const DYLDCache::Mapping dmap = rep->mCache.mapping(n); + CodeDirectory::Scatter *scatter = builder.scatter() + n; + scatter->targetOffset = dmap.address(); + scatter->base = dmap.offset() / segmentedPageSize; + assert(dmap.offset() % segmentedPageSize == 0); + scatter->count = dmap.size() / segmentedPageSize; + assert(dmap.size() % segmentedPageSize == 0); + } +} + + +} // end namespace CodeSigning +} // end namespace Security diff --git a/libsecurity_codesigning/lib/slcrep.h b/libsecurity_codesigning/lib/slcrep.h new file mode 100644 index 00000000..4e044ae3 --- /dev/null +++ b/libsecurity_codesigning/lib/slcrep.h @@ -0,0 +1,93 @@ +/* + * Copyright (c) 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@ + */ + +// +// slcrep - DiskRep representing the Mac OS Shared Library Cache +// +#ifndef _H_SLCREP +#define _H_SLCREP + +#include "singlediskrep.h" +#include "sigblob.h" +#include +#include +#include + +namespace Security { +namespace CodeSigning { + + +// +// DYLDCacheRep implements the on-disk format for the Mac OS X +// Shared Library Cache, which coalesces a set of system libraries +// and frameworks into one big (mappable) code blob in the sky. +// +class DYLDCacheRep : public SingleDiskRep { +public: + DYLDCacheRep(const Context *ctx = NULL); + DYLDCacheRep(const char *path); + + CFDataRef component(CodeDirectory::SpecialSlot slot); + size_t pageSize(const SigningContext &ctx); + std::string format(); + + static bool candidate(UnixPlusPlus::FileDesc &fd); + +public: + static CFDataRef identificationFor(MachO *macho); + +public: + DiskRep::Writer *writer(); + class Writer; + friend class Writer; + +private: + void setup(); + +private: + DYLDCache mCache; + const EmbeddedSignatureBlob *mSigningData; // pointer to signature SuperBlob (in mapped memory) +}; + + +// +// The write side of a FileDiskRep +// +class DYLDCacheRep::Writer : public SingleDiskRep::Writer, private EmbeddedSignatureBlob::Maker { + friend class FileDiskRep; +public: + Writer(DYLDCacheRep *r) : SingleDiskRep::Writer(r, writerNoGlobal), rep(r), mSigningData(NULL) { } + void component(CodeDirectory::SpecialSlot slot, CFDataRef data); + void flush(); + void addDiscretionary(CodeDirectory::Builder &builder); + +private: + DYLDCacheRep *rep; + EmbeddedSignatureBlob *mSigningData; +}; + + +} // end namespace CodeSigning +} // end namespace Security + +#endif // !_H_SLCREP diff --git a/libsecurity_codesigning/lib/syspolicy.sql b/libsecurity_codesigning/lib/syspolicy.sql new file mode 100644 index 00000000..9e3eecee --- /dev/null +++ b/libsecurity_codesigning/lib/syspolicy.sql @@ -0,0 +1,197 @@ +-- +-- Copyright (c) 2011-2012 Apple Inc. All Rights Reserved. +-- +-- @APPLE_LICENSE_HEADER_START@ +-- +-- This file contains Original Code and/or Modifications of Original Code +-- as defined in and that are subject to the Apple Public Source License +-- Version 2.0 (the 'License'). You may not use this file except in +-- compliance with the License. Please obtain a copy of the License at +-- http://www.opensource.apple.com/apsl/ and read it before using this +-- file. +-- +-- The Original Code and all software distributed under the License are +-- distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER +-- EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, +-- INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, +-- FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. +-- Please see the License for the specific language governing rights and +-- limitations under the License. +-- +-- @APPLE_LICENSE_HEADER_END@ +-- +-- +-- System Policy master database - file format and initial contents +-- +-- This is currently for sqlite3 +-- +-- NOTES: +-- Dates are uniformly in julian form. We use 5000000 as the canonical "never" expiration +-- value; that's a day in the year 8977. +-- +PRAGMA user_version = 1; +PRAGMA foreign_keys = true; +PRAGMA legacy_file_format = false; +PRAGMA recursive_triggers = true; + + +-- +-- The feature table hold configuration features and options +-- +CREATE TABLE feature ( + id INTEGER PRIMARY KEY, -- canononical + name TEXT NOT NULL UNIQUE, -- name of option + value TEXT NULL, -- value of option, if any + remarks TEXT NULL -- optional remarks string +); + + +-- +-- The primary authority. This table is conceptually scanned +-- in priority order, with the highest-priority matching enabled record +-- determining the outcome. +-- +CREATE TABLE authority ( + id INTEGER PRIMARY KEY AUTOINCREMENT, -- canonical + version INTEGER NOT NULL DEFAULT (1) -- semantic version of this rule + CHECK (version > 0), + type INTEGER NOT NULL, -- operation type + requirement TEXT NULL -- code requirement + CHECK ((requirement IS NULL) = ((flags & 1) != 0)), + allow INTEGER NOT NULL DEFAULT (1) -- allow (1) or deny (0) + CHECK (allow = 0 OR allow = 1), + disabled INTEGER NOT NULL DEFAULT (0) -- disable count (stacks; enabled if zero) + CHECK (disabled >= 0), + expires FLOAT NOT NULL DEFAULT (5000000), -- expiration of rule authority (Julian date) + priority REAL NOT NULL DEFAULT (0), -- rule priority (full float) + label TEXT NULL, -- text label for authority rule + flags INTEGER NOT NULL DEFAULT (0), -- amalgamated binary flags + -- following fields are for documentation only + ctime FLOAT NOT NULL DEFAULT (JULIANDAY('now')), -- rule creation time (Julian) + mtime FLOAT NOT NULL DEFAULT (JULIANDAY('now')), -- time rule was last changed (Julian) + user TEXT NULL, -- user requesting this rule (NULL if unknown) + remarks TEXT NULL -- optional remarks string +); + +-- index +CREATE INDEX authority_type ON authority (type); +CREATE INDEX authority_priority ON authority (priority); +CREATE INDEX authority_expires ON authority (expires); + +-- update mtime if a record is changed +CREATE TRIGGER authority_update AFTER UPDATE ON authority +BEGIN + UPDATE authority SET mtime = JULIANDAY('now') WHERE id = old.id; +END; + +-- rules that are actively considered +CREATE VIEW active_authority AS +SELECT * from authority +WHERE disabled = 0 AND JULIANDAY('now') < expires AND (flags & 1) = 0; + +-- rules subject to priority scan: active_authority but including disabled rules +CREATE VIEW scan_authority AS +SELECT * from authority +WHERE JULIANDAY('now') < expires AND (flags & 1) = 0; + + +-- +-- A table to carry (potentially large-ish) filesystem data stored as a bookmark blob. +-- +CREATE TABLE bookmarkhints ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + bookmark BLOB NOT NULL, + authority INTEGER NOT NULL + REFERENCES authority(id) ON DELETE CASCADE +); + + +-- +-- Upgradable features already contained in this baseline. +-- See policydatabase.cpp for upgrade code. +-- +INSERT INTO feature (name, value, remarks) + VALUES ('bookmarkhints', 'value', 'builtin'); +INSERT INTO feature (name, value, remarks) + VALUES ('codesignedpackages', 'value', 'builtin'); + + +-- +-- Initial canonical contents of a fresh database +-- + +-- virtual rule anchoring negative cache entries (no rule found) +insert into authority (type, allow, priority, flags, label) + values (1, 0, -1.0E100, 1, 'No Matching Rule'); + +-- any Apple-signed installers except Developer ID +insert into authority (type, allow, priority, flags, label, requirement) + values (2, 1, -1, 2, 'Apple Installer', 'anchor apple generic and ! certificate 1[field.1.2.840.113635.100.6.2.6]'); + +-- Apple code signing +insert into authority (type, allow, flags, label, requirement) + values (1, 1, 2, 'Apple System', 'anchor apple'); + +-- Mac App Store signing +insert into authority (type, allow, flags, label, requirement) + values (1, 1, 2, 'Mac App Store', 'anchor apple generic and certificate leaf[field.1.2.840.113635.100.6.1.9] exists'); + +-- Caspian code and archive signing +insert into authority (type, allow, flags, label, requirement) + values (1, 1, 2, 'Developer ID', 'anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] exists and certificate leaf[field.1.2.840.113635.100.6.1.13] exists'); +insert into authority (type, allow, flags, label, requirement) + values (2, 1, 2, 'Developer ID', 'anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] exists and (certificate leaf[field.1.2.840.113635.100.6.1.14] or certificate leaf[field.1.2.840.113635.100.6.1.13])'); + + +-- +-- The cache table lists previously determined outcomes +-- for individual objects (by object hash). Entries come from +-- full evaluations of authority records, or by explicitly inserting +-- override rules that preempt the normal authority. +-- EACH object record must have a parent authority record from which it is derived; +-- this may be a normal authority rule or an override rule. If the parent rule is deleted, +-- all objects created from it are automatically removed (by sqlite itself). +-- +CREATE TABLE object ( + id INTEGER PRIMARY KEY, -- canonical + type INTEGER NOT NULL, -- operation type + hash CDHASH NOT NULL, -- canonical hash of object + allow INTEGER NOT NULL, -- allow (1) or deny (0) + expires FLOAT NOT NULL DEFAULT (5000000), -- expiration of object entry + authority INTEGER NOT NULL -- governing authority rule + REFERENCES authority(id) ON DELETE CASCADE, + -- following fields are for documentation only + path TEXT NULL, -- path of object at record creation time + ctime FLOAT NOT NULL DEFAULT (JULIANDAY('now')), -- record creation time + mtime FLOAT NOT NULL DEFAULT (JULIANDAY('now')), -- record modification time + remarks TEXT NULL -- optional remarks string +); + +-- index +CREATE INDEX object_type ON object (type); +CREATE INDEX object_expires ON object (expires); +CREATE UNIQUE INDEX object_hash ON object (hash); + +-- update mtime if a record is changed +CREATE TRIGGER object_update AFTER UPDATE ON object +BEGIN + UPDATE object SET mtime = JULIANDAY('now') WHERE id = old.id; +END; + + +-- +-- Some useful views on objects. These are for administration; they are not used by the assessor. +-- +CREATE VIEW object_state AS +SELECT object.id, object.type, object.allow, + CASE object.expires WHEN 5000000 THEN NULL ELSE STRFTIME('%Y-%m-%d %H:%M:%f', object.expires, 'localtime') END AS expiration, + (object.expires - JULIANDAY('now')) * 86400 as remaining, + authority.label, + object.authority, + object.path, + object.ctime, + authority.requirement, + authority.disabled, + object.remarks +FROM object, authority +WHERE object.authority = authority.id; diff --git a/libsecurity_codesigning/lib/xar++.cpp b/libsecurity_codesigning/lib/xar++.cpp new file mode 100644 index 00000000..30e9665e --- /dev/null +++ b/libsecurity_codesigning/lib/xar++.cpp @@ -0,0 +1,96 @@ +/* + * 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@ + */ + +// +// xar++ - interface to XAR-format archive files +// +#include "xar++.h" +#include +#include + + +namespace Security { +namespace CodeSigning { + + +Xar::Xar(const char *path) +{ + mXar = 0; + mSigCMS = 0; + mSigClassic = 0; + if (path) + open(path); +} + +void Xar::open(const char *path) +{ + if ((mXar = ::xar_open(path, READ)) == NULL) + return; + + xar_signature_t sig = ::xar_signature_first(mXar); + // read signatures until we find a CMS signature + while (sig && mSigCMS == NULL) { + const char *type = ::xar_signature_type(sig); + if (strcmp(type, "CMS") == 0) { + mSigCMS = sig; + } else if (strcmp(type, "RSA") == 0) { + mSigClassic = sig; + } + sig = ::xar_signature_next(sig); + } +} + +Xar::~Xar() +{ + if (mXar) + ::xar_close(mXar); +} + +static CFArrayRef copyCertChainFromSignature(xar_signature_t sig) +{ + unsigned count = xar_signature_get_x509certificate_count(sig); + CFRef certs = makeCFMutableArray(0); + for (unsigned ix = 0; ix < count; ix++) { + const uint8_t *data; + uint32_t length; + if (xar_signature_get_x509certificate_data(sig, ix, &data, &length) == 0) { + CFTempData cdata(data, length); + CFRef cert = SecCertificateCreateWithData(NULL, cdata); + CFArrayAppendValue(certs, cert.get()); + } + } + return certs.yield(); +} + +CFArrayRef Xar::copyCertChain() +{ + if (mSigCMS) + return copyCertChainFromSignature(mSigCMS); + else if (mSigClassic) + return copyCertChainFromSignature(mSigClassic); + return NULL; +} + + +} // end namespace CodeSigning +} // end namespace Security diff --git a/libsecurity_codesigning/lib/xar++.h b/libsecurity_codesigning/lib/xar++.h new file mode 100644 index 00000000..11f4f7e4 --- /dev/null +++ b/libsecurity_codesigning/lib/xar++.h @@ -0,0 +1,66 @@ +/* + * 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@ + */ + +// +// xar++ - interface to XAR-format archive files +// +#ifndef _H_XARPLUSPLUS +#define _H_XARPLUSPLUS + +#include +#include + +extern "C" { +#include +} + +namespace Security { +namespace CodeSigning { + + +// +// A XAR-format file on disk +// +class Xar { +public: + Xar(const char *path = NULL); + virtual ~Xar(); + void open(const char *path); + + operator bool() const { return mXar != 0; } + bool isSigned() const { return mSigClassic != 0 || mSigCMS != 0; } + + CFArrayRef copyCertChain(); + +private: + xar_t mXar; + xar_signature_t mSigClassic; + xar_signature_t mSigCMS; +}; + + + +} // end namespace CodeSigning +} // end namespace Security + +#endif // !_H_XARPLUSPLUS diff --git a/libsecurity_codesigning/lib/xpcengine.cpp b/libsecurity_codesigning/lib/xpcengine.cpp new file mode 100644 index 00000000..f779db56 --- /dev/null +++ b/libsecurity_codesigning/lib/xpcengine.cpp @@ -0,0 +1,191 @@ +/* + * 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@ + */ +#include "xpcengine.h" +#include +#include +#include +#include + + +namespace Security { +namespace CodeSigning { + +static const char serviceName[] = "com.apple.security.syspolicy"; + + +static dispatch_once_t dispatchInit; // one-time init marker +static xpc_connection_t service; // connection to spd +static dispatch_queue_t queue; // dispatch queue for service + +static void init() +{ + dispatch_once(&dispatchInit, ^void(void) { + const char *name = serviceName; + if (const char *env = getenv("SYSPOLICYNAME")) + 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_resume(service); + }); +} + + +// +// Your standard XPC client-side machinery +// +class Message { +public: + xpc_object_t obj; + + Message(const char *function) + { + init(); + obj = xpc_dictionary_create(NULL, NULL, 0); + xpc_dictionary_set_string(obj, "function", function); + } + ~Message() + { + if (obj) + xpc_release(obj); + } + operator xpc_object_t () { return obj; } + + void send() + { + xpc_object_t reply = xpc_connection_send_message_with_reply_sync(service, obj); + xpc_release(obj); + obj = NULL; + xpc_type_t type = xpc_get_type(reply); + if (type == XPC_TYPE_DICTIONARY) { + obj = reply; + if (int64_t error = xpc_dictionary_get_int64(obj, "error")) + MacOSError::throwMe(error); + } else if (type == XPC_TYPE_ERROR) { + const char *s = xpc_copy_description(reply); + printf("Error returned: %s\n", s); + free((char*)s); + MacOSError::throwMe(errSecCSInternalError); + } else { + const char *s = xpc_copy_description(reply); + printf("Unexpected type of return object: %s\n", s); + free((char*)s); + } + } +}; + + + +static void copyCFDictionary(const void *key, const void *value, void *ctx) +{ + CFMutableDictionaryRef target = CFMutableDictionaryRef(ctx); + if (CFEqual(key, kSecAssessmentContextKeyCertificates)) // obsolete + return; + if (CFGetTypeID(value) == CFURLGetTypeID()) { + CFRef path = CFURLCopyFileSystemPath(CFURLRef(value), kCFURLPOSIXPathStyle); + CFDictionaryAddValue(target, key, path); + } else { + CFDictionaryAddValue(target, key, value); + } +} + +void xpcEngineAssess(CFURLRef path, uint flags, CFDictionaryRef context, CFMutableDictionaryRef result) +{ + Message msg("assess"); + xpc_dictionary_set_string(msg, "path", cfString(path).c_str()); + xpc_dictionary_set_int64(msg, "flags", flags); + CFRef ctx = makeCFMutableDictionary(); + if (context) + CFDictionaryApplyFunction(context, copyCFDictionary, ctx); + CFRef contextData = makeCFData(CFDictionaryRef(ctx)); + xpc_dictionary_set_data(msg, "context", CFDataGetBytePtr(contextData), CFDataGetLength(contextData)); + + msg.send(); + + if (int64_t error = xpc_dictionary_get_int64(msg, "error")) + MacOSError::throwMe(error); + + size_t resultLength; + const void *resultData = xpc_dictionary_get_data(msg, "result", &resultLength); + CFRef resultDict = makeCFDictionaryFrom(resultData, resultLength); + CFDictionaryApplyFunction(resultDict, copyCFDictionary, result); + CFDictionaryAddValue(result, CFSTR("assessment:remote"), kCFBooleanTrue); +} + + +CFDictionaryRef xpcEngineUpdate(CFTypeRef target, uint flags, CFDictionaryRef context) +{ + Message msg("update"); + // target can be NULL, a CFURLRef, a SecRequirementRef, or a CFNumberRef + if (target) { + if (CFGetTypeID(target) == CFNumberGetTypeID()) + xpc_dictionary_set_uint64(msg, "rule", cfNumber(CFNumberRef(target))); + else if (CFGetTypeID(target) == CFURLGetTypeID()) + xpc_dictionary_set_string(msg, "url", cfString(CFURLRef(target)).c_str()); + else if (CFGetTypeID(target) == SecRequirementGetTypeID()) { + CFRef data; + MacOSError::check(SecRequirementCopyData(SecRequirementRef(target), kSecCSDefaultFlags, &data.aref())); + xpc_dictionary_set_data(msg, "requirement", CFDataGetBytePtr(data), CFDataGetLength(data)); + } else + MacOSError::throwMe(errSecCSInvalidObjectRef); + } + xpc_dictionary_set_int64(msg, "flags", flags); + CFRef ctx = makeCFMutableDictionary(); + if (context) + CFDictionaryApplyFunction(context, copyCFDictionary, ctx); + AuthorizationRef localAuthorization = NULL; + if (CFDictionaryGetValue(ctx, kSecAssessmentUpdateKeyAuthorization) == NULL) { // no caller-provided authorization + MacOSError::check(AuthorizationCreate(NULL, NULL, kAuthorizationFlagDefaults, &localAuthorization)); + AuthorizationExternalForm extForm; + MacOSError::check(AuthorizationMakeExternalForm(localAuthorization, &extForm)); + CFDictionaryAddValue(ctx, kSecAssessmentUpdateKeyAuthorization, CFTempData(&extForm, sizeof(extForm))); + } + CFRef contextData = makeCFData(CFDictionaryRef(ctx)); + xpc_dictionary_set_data(msg, "context", CFDataGetBytePtr(contextData), CFDataGetLength(contextData)); + + msg.send(); + + if (localAuthorization) + AuthorizationFree(localAuthorization, kAuthorizationFlagDefaults); + + if (int64_t error = xpc_dictionary_get_int64(msg, "error")) + MacOSError::throwMe(error); + + size_t resultLength; + const void *resultData = xpc_dictionary_get_data(msg, "result", &resultLength); + return makeCFDictionaryFrom(resultData, resultLength); +} + + +bool xpcEngineControl(const char *control) +{ + Message msg("control"); + xpc_dictionary_set_string(msg, "control", control); + msg.send(); + return true; +} + + +} // end namespace CodeSigning +} // end namespace Security diff --git a/libsecurity_codesigning/lib/xpcengine.h b/libsecurity_codesigning/lib/xpcengine.h new file mode 100644 index 00000000..e2edd01b --- /dev/null +++ b/libsecurity_codesigning/lib/xpcengine.h @@ -0,0 +1,44 @@ +/* + * 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@ + */ +#ifndef _H_XPCENGINE +#define _H_XPCENGINE + +#include "SecAssessment.h" +#include "policydb.h" +#include +#include + +namespace Security { +namespace CodeSigning { + + +void xpcEngineAssess(CFURLRef path, uint flags, CFDictionaryRef context, CFMutableDictionaryRef result); +CFDictionaryRef xpcEngineUpdate(CFTypeRef target, uint flags, CFDictionaryRef context) + CF_RETURNS_RETAINED; +bool xpcEngineControl(const char *name); + + +} // end namespace CodeSigning +} // end namespace Security + +#endif //_H_XPCENGINE diff --git a/libsecurity_codesigning/libsecurity_codesigning.xcodeproj/project.pbxproj b/libsecurity_codesigning/libsecurity_codesigning.xcodeproj/project.pbxproj new file mode 100644 index 00000000..e1a82958 --- /dev/null +++ b/libsecurity_codesigning/libsecurity_codesigning.xcodeproj/project.pbxproj @@ -0,0 +1,1326 @@ +// !$*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 */, + ); + 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 */, + ); + 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, ); }; }; + 18B965941472FE27005A4D2E /* renum.h in Headers */ = {isa = PBXBuildFile; fileRef = C2EF100F0A49BD89005A44BB /* renum.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18B965951472FE30005A4D2E /* cdbuilder.h in Headers */ = {isa = PBXBuildFile; fileRef = C2D383150A237F47005C63A2 /* cdbuilder.h */; settings = {ATTRIBUTES = (Public, ); }; }; + C2093AA80BB0948000EB8599 /* reqreader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2093AA60BB0948000EB8599 /* reqreader.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 */; }; + 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 */; }; + C2EF10100A49BD89005A44BB /* renum.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2EF100E0A49BD89005A44BB /* renum.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 */; }; + 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; + }; + 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; + }; + C26AC0F4143BD1C4001C98CE /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = private/var/db; + dstSubfolderSpec = 0; + files = ( + C26AC0F5143BD1C8001C98CE /* SystemPolicy in CopyFiles */, + ); + 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; }; + 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 = ""; }; + C2110704158BF5C8001D7F76 /* gkmerge */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.python; name = gkmerge; path = gke/gkmerge; sourceTree = SOURCE_ROOT; }; + 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; name = gkclear; path = gke/gkclear; sourceTree = SOURCE_ROOT; }; + C2578CC315798D0F00D4FE48 /* gkgenerate */ = {isa = PBXFileReference; lastKnownFileType = text.script.python; name = gkgenerate; path = gke/gkgenerate; sourceTree = SOURCE_ROOT; }; + C2578CC415798D0F00D4FE48 /* gkrecord */ = {isa = PBXFileReference; lastKnownFileType = text.script.python; name = gkrecord; path = gke/gkrecord; sourceTree = SOURCE_ROOT; }; + 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 = ""; }; + 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 = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; + C273606C1433F09000A9A5FF /* SecAssessment.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = SecAssessment.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; + C273606D1433F09000A9A5FF /* SecAssessment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = SecAssessment.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; + C27360D41436866C00A9A5FF /* xpcengine.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = xpcengine.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; + C27360D71436868600A9A5FF /* xpcengine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = xpcengine.h; sourceTree = ""; }; + C278A19B158AB2C300FA6767 /* gkhandmake */ = {isa = PBXFileReference; lastKnownFileType = text.script.python; name = gkhandmake; path = gke/gkhandmake; sourceTree = SOURCE_ROOT; }; + C278A19C158AB2C300FA6767 /* gklist */ = {isa = PBXFileReference; lastKnownFileType = text.script.python; name = gklist; path = gke/gklist; sourceTree = SOURCE_ROOT; }; + 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 = ""; }; + C2EF100E0A49BD89005A44BB /* renum.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = renum.cpp; sourceTree = ""; }; + C2EF100F0A49BD89005A44BB /* renum.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = renum.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 = ""; }; + 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; + }; + C2BC1F240B580D3A003EC9DC /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + C2BC1F2D0B580D4B003EC9DC /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + C26B45C10B8A9C0A003C0ACA /* ucspc 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 = ( + 182BB4FC146F2823000BF1F3 /* libsecurityd.xcodeproj */, + 4C308388053237100028A8C6 /* lib */, + 1844619E146E9AD100B12992 /* config */, + C2D383F90A23A9D9005C63A2 /* cstemp */, + C2CC30EF0B8519CF005FA59D /* Frameworks */, + 4CA1FEBF052A3C8100F22E42 /* Products */, + ); + sourceTree = ""; + }; + 4CA1FEBF052A3C8100F22E42 /* Products */ = { + isa = PBXGroup; + children = ( + 4CA1FEBE052A3C8100F22E42 /* libsecurity_codesigning.a */, + C2BC1F260B580D3A003EC9DC /* libintegrity.a */, + C2BC1F2F0B580D4B003EC9DC /* libcodehost.a */, + ); + 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 */, + 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 */, + ); + name = gke; + path = whitelist; + 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 */, + ); + 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 = ( + C2CC30A00B8519CC005FA59D /* CoreFoundation.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 */, + C2EF100F0A49BD89005A44BB /* renum.h */, + C2EF100E0A49BD89005A44BB /* renum.cpp */, + C2A976A90B8A2E36008B4EA0 /* csutilities.h */, + C2A976A80B8A2E36008B4EA0 /* csutilities.cpp */, + C235340E145F1B050073F964 /* xar++.h */, + C2353410145F1B110073F964 /* xar++.cpp */, + C2F4439914C626D4000A01E6 /* quarantine++.h */, + C2F4439814C626D4000A01E6 /* quarantine++.cpp */, + ); + name = "Local Utilities"; + sourceTree = ""; + }; + C2D383F90A23A9D9005C63A2 /* cstemp */ = { + isa = PBXGroup; + children = ( + C2C4F4EE0E0980C700137848 /* codesigning_dtrace.h */, + C26AC0F3143BD1B3001C98CE /* SystemPolicy */, + C26B45C00B8A9C00003C0ACA /* ucspc */, + ); + path = cstemp; + sourceTree = BUILT_PRODUCTS_DIR; + }; + FEB30C9110DAC6C400557BA2 /* Entitlements */ = { + isa = PBXGroup; + children = ( + FEB30C9410DAC8A500557BA2 /* SecTask.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 */, + 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 */, + 18B965941472FE27005A4D2E /* renum.h in Headers */, + EB68B133150DB04400B4013D /* RequirementKeywords.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 */, + C26763D814FD9EBE00A46EDF /* drmaker.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 */, + ); + 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"; + }; + 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"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 4CA1FEAB052A3C3800F22E42 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0420; + }; + buildConfigurationList = C263E67909A2971B000043F1 /* Build configuration list for PBXProject "libsecurity_codesigning" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 1; + knownRegions = ( + English, + Japanese, + French, + German, + ); + 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 */, + ); + }; +/* 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 = ( + 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 */, + C2EF10100A49BD89005A44BB /* renum.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 */, + 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 */, + ); + 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; + }; +/* 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 */; + }; + 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 */ + C263E67609A2971B000043F1 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 184461A0146E9AD100B12992 /* debug.xcconfig */; + buildSettings = { + HEADER_SEARCH_PATHS = ( + "$(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 = { + HEADER_SEARCH_PATHS = ( + "$(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 = { + TEMPDIR = "$(BUILT_PRODUCTS_DIR)/cstemp"; + }; + name = Debug; + }; + C263E67C09A2971B000043F1 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 184461A1146E9AD100B12992 /* lib.xcconfig */; + buildSettings = { + TEMPDIR = "$(BUILT_PRODUCTS_DIR)/cstemp"; + }; + name = Release; + }; + C26AC0ED143BCF01001C98CE /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + }; + name = Debug; + }; + C26AC0EF143BCF01001C98CE /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + }; + name = Release; + }; + C26AC70A0DAEB3A8005BFB40 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + }; + name = Debug; + }; + C26AC70C0DAEB3A8005BFB40 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + }; + name = Release; + }; + C2BC1F280B580D3F003EC9DC /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 184461A0146E9AD100B12992 /* debug.xcconfig */; + buildSettings = { + SKIP_INSTALL = NO; + }; + name = Debug; + }; + C2BC1F2A0B580D3F003EC9DC /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 184461A2146E9AD100B12992 /* release.xcconfig */; + buildSettings = { + SKIP_INSTALL = NO; + }; + name = Release; + }; + C2BC1F310B580D69003EC9DC /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 184461A0146E9AD100B12992 /* debug.xcconfig */; + buildSettings = { + SKIP_INSTALL = NO; + }; + name = Debug; + }; + C2BC1F330B580D69003EC9DC /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 184461A2146E9AD100B12992 /* release.xcconfig */; + buildSettings = { + SKIP_INSTALL = NO; + }; + name = Release; + }; + C2D383C10A23A8E3005C63A2 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + }; + name = Debug; + }; + C2D383C30A23A8E3005C63A2 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + }; + name = Release; + }; + C2E287480B5D8FD8009336A0 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + }; + name = Debug; + }; + C2E2874A0B5D8FD8009336A0 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 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; + }; +/* End XCConfigurationList section */ + }; + rootObject = 4CA1FEAB052A3C3800F22E42 /* Project object */; +} diff --git a/libsecurity_codesigning/req/cfm.ireqs b/libsecurity_codesigning/req/cfm.ireqs new file mode 100644 index 00000000..02d53dc1 --- /dev/null +++ b/libsecurity_codesigning/req/cfm.ireqs @@ -0,0 +1,4 @@ +# +# Suggested internal requirements for CFM code +# +host => anchor apple and identifier com.apple.LaunchCFMApp // CFM runner tool diff --git a/libsecurity_codesigning/req/ppc-host.ireq b/libsecurity_codesigning/req/ppc-host.ireq new file mode 100644 index 00000000..a43b31ad --- /dev/null +++ b/libsecurity_codesigning/req/ppc-host.ireq @@ -0,0 +1,4 @@ +# +# Suggested internal host requirement for (only) ppc Mach-O code +# +anchor apple and identifier com.apple.translate // Rosetta diff --git a/libsecurity_codesigning/requirements.grammar b/libsecurity_codesigning/requirements.grammar new file mode 100644 index 00000000..6b83f053 --- /dev/null +++ b/libsecurity_codesigning/requirements.grammar @@ -0,0 +1,488 @@ +/* + * Copyright (c) 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@ + */ + +// +// Requirements Language Grammar +// +// This file describes two distinct (related) grammars: +// Requirement => single requirement (Requirement *) +// RequirementSet => set of labeled requirements (Requirements *) +// The grammar can "autosense" - i.e. recognize which one it's fed and +// return appropriate semantic data. +// +// The semantic data compiled is a malloc'ed BlobCore * - a Requirement +// object or a SuperBlob containing multiple Requirements. +// +// Errors are indicated to the caller by accumulating error message strings +// in the errors member variable. Any non-empty error value indicates failure. +// Presence of semantic data is not a reliable indication of success. +// +header "post_include_hpp" { +#include "requirement.h" +using namespace CodeSigning; +typedef Requirement::Maker Maker; +} + +header "post_include_cpp" { +#include "requirement.h" +#include "reqmaker.h" +#include "csutilities.h" +#include +#include +#include // OID coding +using namespace CodeSigning; +typedef Requirement::Maker Maker; +} + +options { + language="Cpp"; + namespace="Security_CodeSigning"; + namespaceStd="std"; + namespaceAntlr="antlr"; + genHashLines=false; +} + + +{ + // + // Collect error messages. + // Note that the immediate caller takes the absence of collected error messages + // to indicate compilation success. + // + void RequirementParser::reportError(const antlr::RecognitionException &ex) + { + errors += ex.toString() + "\n"; + } + + void RequirementParser::reportError(const std::string &s) + { + errors += s + "\n"; + } + + + // + // Parser helper functions + // + string RequirementParser::hexString(const string &s) + { + if (s.size() % 2) + throw antlr::SemanticException("odd number of digits"); + const char *p = s.data(); + string result; + for (unsigned n = 0; n < s.length(); n += 2) { + char c; + sscanf(p+n, "%2hhx", &c); + result.push_back(c); + } + return result; + } + + void RequirementParser::hashString(const string &s, SHA1::Digest hash) + { + if (s.size() != 2 * SHA1::digestLength) + throw antlr::SemanticException("invalid hash length"); + memcpy(hash, hexString(s).data(), SHA1::digestLength); + } + + static const char *matchPrefix(const string &key, const char *prefix) + { + unsigned pLength = strlen(prefix); + if (!key.compare(0, pLength, prefix, 0, pLength)) + return key.c_str() + pLength; + else + return NULL; + } + + void RequirementParser::certMatchOperation(Maker &maker, int32_t slot, string key) + { + if (matchPrefix(key, "subject.")) { + maker.put(opCertField); + maker.put(slot); + maker.put(key); + } else if (const char *oids = matchPrefix(key, "field.")) { + maker.put(opCertGeneric); + maker.put(slot); + CssmAutoData oid(Allocator::standard()); oid.fromOid(oids); + maker.putData(oid.data(), oid.length()); + } else if (const char *oids = matchPrefix(key, "extension.")) { + maker.put(opCertGeneric); + maker.put(slot); + CssmAutoData oid(Allocator::standard()); oid.fromOid(oids); + maker.putData(oid.data(), oid.length()); + } else if (const char *oids = matchPrefix(key, "policy.")) { + maker.put(opCertPolicy); + maker.put(slot); + CssmAutoData oid(Allocator::standard()); oid.fromOid(oids); + maker.putData(oid.data(), oid.length()); + } else { + throw antlr::SemanticException(key + ": unrecognized certificate field"); + } + } +} + + +class RequirementParser extends Parser; + +options { + k=2; +} + +{ +public: + std::string errors; + void reportError(const antlr::RecognitionException &ex); + void reportError(const std::string &s); + +private: + static string hexString(const string &s); + static void hashString(const string &s, SHA1::Digest hash); + void certMatchOperation(Maker &maker, int32_t slot, string key); +} + + +// +// Compound target; compiles single requirements or requirement sets +// and returns them as a BlobCore. +// +autosense returns [BlobCore *result = NULL] + : result=requirement + | result=requirementSet + ; + + +// +// A Requirements Set. +// +requirementSet returns [Requirements *result = NULL] + { Requirements::Maker maker; } + : ( { uint32_t t; Requirement *req; } + t=requirementType ARROW req=requirementElement + { maker.add(t, req); } + )+ + { result = errors.empty() ? maker() : NULL; } + EOF + ; + +requirementType returns [uint32_t type = kSecInvalidRequirementType] + : "guest" + { type = kSecGuestRequirementType; } + | "host" + { type = kSecHostRequirementType; } + | "designated" + { type = kSecDesignatedRequirementType; } + | "library" + { type = kSecLibraryRequirementType; } + | "plugin" + { type = kSecPluginRequirementType; } + | stype:INTEGER + { type = atol(stype->getText().c_str()); } + ; + + +// +// A single Requirement (untyped) +// +requirement returns [Requirement *result = NULL] + : result = requirementElement + EOF + ; + +requirementElement returns [Requirement *result = NULL] + { Requirement::Maker maker; } + : expr[maker] + { result = maker(); } + ( fluff )* + ; + + +// +// Classic recursive expressions +// +expr[Maker &maker] + { Maker::Label label(maker); } + : term[maker] ( "or" { maker.insert(label) = opOr; } term[maker] )* + ; + +term[Maker &maker] + { Maker::Label label(maker); } + : primary[maker] ( "and" { maker.insert(label) = opAnd; } primary[maker] )* + ; + +primary[Maker &maker] + : LPAREN expr[maker] RPAREN + | NOT { maker.put(opNot); } primary[maker] + | ( "always" | "true" ) + { maker.put(opTrue); } + | ( "never" | "false" ) + { maker.put(opFalse); } + | certspec[maker] + | infospec[maker] + | entitlementspec[maker] + | "identifier" { string code; } eql code=identifierString + { maker.ident(code); } + | "cdhash" { SHA1::Digest digest; } eql hash[digest] + { maker.cdhash(digest); } + | LPAREN { string name; } name=identifierString RPAREN + { maker.put(opNamedCode); maker.put(name); } + ; + + +// +// Certificate specifications restrict certificates in the signing chain +// +certspec[Maker &maker] + : "anchor" "apple" appleanchor[maker] + | "anchor" "generic" "apple" // alternate form + { maker.put(opAppleGenericAnchor); } + | ( "certificate" | "cert" | "anchor" ) "trusted" + { maker.trustedAnchor(); } + | ( "certificate" | "cert" ) { int32_t slot; } slot=certSlot + ( certslotspec[maker, slot] | "trusted" { maker.trustedAnchor(slot); } ) + | "anchor" certslotspec[maker, Requirement::anchorCert] + ; + +appleanchor[Maker &maker] + : empty + { maker.put(opAppleAnchor); } + | "generic" + { maker.put(opAppleGenericAnchor); } + | { string name; } name=identifierString + { maker.put(opNamedAnchor); maker.put(name); } + ; + +certslotspec[Maker &maker, int32_t slot] { string key; } + : eql { SHA1::Digest digest; } certificateDigest[digest] + { maker.anchor(slot, digest); } + | key=bracketKey + { certMatchOperation(maker, slot, key); } + match_suffix[maker] + ; + + +// +// Info specifications place conditions on entries in the Info.plist +// +infospec[Maker &maker] { string key; } + : "info" key=bracketKey + { maker.put(opInfoKeyField); maker.put(key); } + match_suffix[maker] + ; + + +// +// Entitlement specifications place conditions on embedded entitlement entries +// +entitlementspec[Maker &maker] { string key; } + : "entitlement" key=bracketKey + { maker.put(opEntitlementField); maker.put(key); } + match_suffix[maker] + ; + + +// +// Common match operations, written as a syntactic suffix (the operand precedes this) +// +match_suffix[Maker &maker] + : empty ( "exists" ) ? + { maker.put(matchExists); } + | ( EQL | EQQL ) + { MatchOperation mop = matchEqual; string value; } + ( STAR { mop = matchEndsWith; } ) ? + value=datavalue + ( STAR { mop = (mop == matchEndsWith) ? matchContains : matchBeginsWith; } ) ? + { maker.put(mop); maker.put(value); } + | SUBS { string value; } value=datavalue + { maker.put(matchContains); maker.put(value); } + | LESS { string value; } value=datavalue + { maker.put(matchLessThan); maker.put(value); } + | GT { string value; } value=datavalue + { maker.put(matchGreaterThan); maker.put(value); } + | LE { string value; } value=datavalue + { maker.put(matchLessEqual); maker.put(value); } + | GE { string value; } value=datavalue + { maker.put(matchGreaterEqual); maker.put(value); } + ; + +bracketKey returns [string key] + : LBRACK key=stringvalue RBRACK + ; + +// +// A certSlot identifies one certificate from the certificate chain +// +certSlot returns [int32_t slot = 0] + : s:INTEGER // counting from the anchor up + { slot = atol(s->getText().c_str()); } + | NEG ss:INTEGER // counting from the leaf down + { slot = -atol(ss->getText().c_str()); } + | "leaf" // the leaf ( == -1) + { slot = Requirement::leafCert; } + | "root" // the root ( == 0) + { slot = Requirement::anchorCert; } + ; + +// an arbitrary digest value +hash[SHA1::Digest digest] + : hash:HASHCONSTANT + { hashString(hash->getText(), digest); } + ; + +// various forms to specify a certificate hash +certificateDigest[SHA1::Digest digest] + : hash[digest] + | { string path; } path=pathstring + { if (CFRef certData = cfLoadFile(path)) + hashOfCertificate(CFDataGetBytePtr(certData), CFDataGetLength(certData), digest); + else + throw antlr::SemanticException(path + ": not found"); + } + ; + +// generic data - can be simple string, quoted string, or 0x-style hex +datavalue returns [string result] + : result=stringvalue + | hex:HEXCONSTANT { result = hexString(hex->getText()); } + ; + +// strings can always be quoted, but DOTKEYs don't need to be +stringvalue returns [string result] + : dk:DOTKEY { result = dk->getText(); } + | s:STRING { result = s->getText(); } + ; + +// pathstrings are like strings, but PATHNAMEs don't need to be quoted either +pathstring returns [string result] + : dk:DOTKEY { result = dk->getText(); } + | s:STRING { result = s->getText(); } + | pn:PATHNAME { result = pn->getText(); } + ; + +// unique identifier value +identifierString returns [string result] + : dk:DOTKEY { result = dk->getText(); } + | s:STRING { result = s->getText(); } + ; + +// syntactic cavity generators +fluff + : SEMI + ; + +eql + : EQL + | EQQL + | empty + ; + +empty : ; + + +// +// The lexer for the Requirement language. +// Really straightforward and conventional. +// A subset of strings don't need to be quoted (DOTKEYs). Neither do some simple +// pathnames starting with "/". +// Hash values have a special syntax H"abcd" (abcd in straight hex). +// Hex constants of the form 0xabcd can have any length; they are carried +// around as strings (which are in turn stored as data in the language binary). +// +class RequirementLexer extends Lexer; + +options { + k=2; + testLiterals=false; +} + +protected +IDENT options { testLiterals=true; } + : ( 'A' .. 'Z' | 'a' .. 'z' ) ( 'A' .. 'Z' | 'a' .. 'z' | '0' .. '9' )* + ; + +DOTKEY options { testLiterals=true; } + : IDENT ( "." ( IDENT | INTEGER ) )* + ; + +PATHNAME + : "/" IDENT ( "/" IDENT )+ + ; + +HASHCONSTANT + : 'H'! '"'! ( HEX )+ '"'! + ; + +HEXCONSTANT + : '0'! 'x'! ( HEX )+ + ; + +STRING + : '"'! ( ( '\\'! '"' ) | ( ~ ( '"' | '\\' ) ) )* '"'! + ; + +INTEGER + : ( '0' .. '9' ) + + ; + +protected +HEX : '0' .. '9' | 'a' .. 'f' | 'A' .. 'F' ; + +// operator tokens +ARROW : "=>" ; +SEMI : ';' ; +LPAREN : '(' ; +RPAREN : ')' ; +LBRACK : '[' ; +RBRACK : ']' ; +LESS : '<' ; +GT : '>' ; +LE : "<=" ; +GE : ">=" ; +COMMA : ',' ; +EQL : '=' ; +EQQL : "==" ; +SUBS : '~' ; +NEG : '-' ; +NOT : '!' ; +STAR : '*' ; + + +// +// White spaces +// +WS : ( ' ' | '\n' { newline(); } | '\t' )+ + { $setType(antlr::Token::SKIP); } + ; + +SHELLCOMMENT + : '#' ( ~ '\n' )* + { $setType(antlr::Token::SKIP); } + ; + +C_COMMENT + : "/*" ( (~'*')|('*'(~'/')) )* "*/" + { $setType(antlr::Token::SKIP); } + ; + +CPP_COMMENT + : "//" ( ~ '\n' )* + { $setType(antlr::Token::SKIP); } + ; diff --git a/libsecurity_comcryption/Info-security_comcryption.plist b/libsecurity_comcryption/Info-security_comcryption.plist new file mode 100644 index 00000000..7685bd64 --- /dev/null +++ b/libsecurity_comcryption/Info-security_comcryption.plist @@ -0,0 +1,5 @@ + + + + + diff --git a/libsecurity_comcryption/lib/comDebug.h b/libsecurity_comcryption/lib/comDebug.h new file mode 100644 index 00000000..aee978f6 --- /dev/null +++ b/libsecurity_comcryption/lib/comDebug.h @@ -0,0 +1,212 @@ +/* Copyright (c) 1997 Apple Computer, Inc. + * + * comDebug.h + */ + +#ifndef _COM_DEBUG_H_ +#define _COM_DEBUG_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * enable general debugging printfs and error checking. + */ +#define COM_DEBUG 0 +#if COM_DEBUG +#include + +#define ddprintf(x) printf x +#else +#define ddprintf(x) +#endif + +/* + * block parsing debug + */ +#define COM_SCAN_DEBUG 0 +#if COM_SCAN_DEBUG +#define scprintf(x) printf x +#else +#define scprintf(x) +#endif + +/* + * 2nd-level comcrypt debug + */ +#define LEVEL2_DEBUG 0 +#if LEVEL2_DEBUG +#include + +#define l2printf(x) printf x +#else +#define l2printf(x) +#endif + +/* + * lookahead queue debug + */ +#define COM_LA_DEBUG 0 +#define COM_LA_PRINTF 0 +#if COM_LA_PRINTF +#define laprintf(x) printf x +#else +#define laprintf(x) +#endif + +/* + * Statistics measurements. This is a private API. + */ +#if COM_DEBUG +#define COM_STATS 0 +#else +#define COM_STATS 0 +#endif + +#if COM_STATS + +/* + * Info obtained via a call to getComStats() + */ +typedef struct { + unsigned level1blocks; + unsigned plaintextBytes; + unsigned ciphertextBytes; + unsigned oneByteFrags; // 1st level only + unsigned twoByteFrags; // ditto + unsigned level2oneByteFrags; // second level only + unsigned level2twoByteFrags; // ditto + unsigned level2byteCode; // bytes, pre-encrypted + unsigned level2cipherText; // bytes, post-encrypt + unsigned level2blocks; // 2nd-level blocks + unsigned level2jmatch; // total jmatch (at first level) of + // 2nd level blocks +} comStats; + +extern comStats _comStats; +#define incrComStat(stat, num) _comStats.stat += num; + +#define incr1byteFrags(recursLevel) { \ + if(recursLevel == 1) { \ + incrComStat(level2oneByteFrags, 1); \ + } \ + else { \ + incrComStat(oneByteFrags, 1); \ + } \ +} +#define incr2byteFrags(recursLevel) { \ + if(recursLevel == 1) { \ + incrComStat(level2twoByteFrags, 1); \ + } \ + else { \ + incrComStat(twoByteFrags, 1); \ + } \ +} + +extern void resetComStats(); +extern void getComStats(comStats *stats); + +#else +#define incrComStat(stat, num) +#define incr1byteFrags(recursLevel) +#define incr2byteFrags(recursLevel) +#endif + +/* + * Profiling measurement. A private API when enabled. + */ +#if COM_DEBUG +#define COM_PROFILE 0 +#else +#define COM_PROFILE 0 +#endif + +#if COM_PROFILE + +#include + +/* + * Global profiling enable. It turns out the the cost of doing the + * kern_timestamp() call twice per codeword is way more expensive + * than the actual comcryption code. Setting this variable to zero + * avoids the cost of all the timestamps for reference without + * rebuilding. Also, the cmcPerWordOhead calibrates the actual + * cost of the two kern_timestamp() calls per word. + */ +extern unsigned comProfEnable; + +/* + * Profiling accumulators. + */ +typedef unsigned comprof_t; + +extern comprof_t cmcTotal; +extern comprof_t cmcQueSearch; +extern comprof_t cmcQueMatchMove; +extern comprof_t cmcQueMissMove; +extern comprof_t cmcPerWordOhead; +extern comprof_t cmcLevel2; + + +/* + * Place one of these in the local variable declaration list of each routine + * which will do profiling. + */ +#define COMPROF_LOCALS \ + struct tsval _profStartTime; \ + struct tsval _profEndTime; + +/* + * Start the clock. + */ +#define COMPROF_START \ + if(comProfEnable) { \ + kern_timestamp(&_profStartTime); \ + } + +/* + * Stop the clock and gather elapsed time to specified accumulator. + */ +#define COMPROF_END(accum) \ + if(comProfEnable) { \ + kern_timestamp(&_profEndTime); \ + accum += (_profEndTime.low_val - _profStartTime.low_val); \ + } + + +#else + +#define COMPROF_LOCALS +#define COMPROF_START +#define COMPROF_END(accum) + +#endif /* COM_PROFILE */ + +/* + * Get/set parameter API, private, for debug only. + */ +#if COM_DEBUG +#define COM_PARAM_ENABLE 1 +#else +#define COM_PARAM_ENABLE 0 +#endif /*COM_DEBUG*/ + +#if COM_PARAM_ENABLE + +extern unsigned getF1(comcryptObj cobj); +extern void setF1(comcryptObj cobj, unsigned f1); +extern unsigned getF2(comcryptObj cobj); +extern void setF2(comcryptObj cobj, unsigned f2); +extern unsigned getJmatchThresh(comcryptObj cobj); +extern void setJmatchThresh(comcryptObj cobj, unsigned jmatchThresh); +extern unsigned getMinByteCode(comcryptObj cobj); +extern void setMinByteCode(comcryptObj cobj, unsigned minByteCode); + +#endif /*COM_PARAM_ENABLE*/ + +#ifdef __cplusplus +} +#endif + +#endif /*_COM_DEBUG_H_*/ diff --git a/libsecurity_comcryption/lib/comcryptPriv.c b/libsecurity_comcryption/lib/comcryptPriv.c new file mode 100644 index 00000000..56e9b5ac --- /dev/null +++ b/libsecurity_comcryption/lib/comcryptPriv.c @@ -0,0 +1,537 @@ +/* + 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 + + To Do: +*/ + +#include "comcryptPriv.h" +#include +#include +#include +#ifdef macintosh +#include +#endif + +/* if NULL, use our own */ +comMallocExternFcn *comMallocExt = NULL; +comFreeExternFcn *comFreeExt = NULL; + +#if COM_STATS +comStats _comStats; + +void resetComStats() +{ + memset(&_comStats, 0, sizeof(comStats)); +} + +void getComStats(comStats *stats) +{ + *stats = _comStats; +} + +#else /*COM_STATS*/ + +#define incrComStat(stat, num) + +#endif /*COM_STATS*/ + +/* + * Generate a symbol permutation from the key. + */ +void key_perm( + const unsigned char *key, + int keybytes, + unsigned char *map, + unsigned char *invmap) +{ + int i, j, tmp, sum; + + for(sum = 0, j = 0; j < keybytes; j++) { + sum += key[j]; + } + for(j=0; j < 256; j++) { + map[j] = j; + } + for(j=0; j < 255; j++) { + i = (key[j % keybytes] + j*sum) & 0xff; + tmp = map[i]; + map[i] = map[j]; + map[j] = tmp; + } + for(j=0; j<256; j++) { + invmap[map[j]] = j; + } +} + +int keybyte( + const unsigned char *key, + int keybytes, + int index) +{ + return((int) key[index % keybytes]); +} + +int keynybble( + const unsigned char *key, + int keybytes, + int index) +{ + int i = index % (2*keybytes); + int j; + + j = key[i>>1]; /* Which byte. */ + if(i & 1) j >>= 4; /* Which nybble. */ + return(j & 0xf); +} + +/* + * Hash a key array. + */ + +#define HASH_SEED 3 +#define HASH_REDUCE 1023 + +static unsigned keyHash(const unsigned char *key, unsigned keylen) +{ + unsigned x = HASH_SEED; /* Any seed in [1,p-1]. Like SEED = 3. */ + unsigned ctr; + + for(ctr=0; ctrcodeBufSize = comcryptMaxOutBufSize(NULL, + CC_BLOCK_SIZE, + CCOP_COMCRYPT, + 1); + cbuf->codeBuf = (unsigned char *)ascMalloc(cbuf->codeBufSize); + + /* + * max size needed for level2Buf is the MaxOutBufSize of comcrypting + * a whole block of byte code. Note we assume that MaxOutBufSize(n) >= n. + */ + cbuf->level2BufSize = comcryptMaxOutBufSize(NULL, + MAX_TOKENS, // one byte per token + CCOP_COMCRYPT, + 1); + cbuf->level2Buf = (unsigned char *)ascMalloc(cbuf->level2BufSize); + + cbuf->queue = (queueElt *)ascMalloc(sizeof(queueElt) * QLEN); + + #if QUEUE_LOOKAHEAD + /* + * Might want to do this dynamically, though that requires the malloc + * of the lookAhead buffer to be done in initCodeBufs(), not here (at + * comcryptAlloc() time). + * + * FIXME : should do the malloc of lookAhead buffer lazily for + * non-Mac platforms. + */ + cbuf->lookAhead = (unsigned char *)ascMalloc(LOOKAHEAD_SIZE); + #else /* QUEUE_LOOKAHEAD */ + cbuf->lookAhead = NULL; + #endif /* QUEUE_LOOKAHEAD */ + + /* + * This maybe should also be done dynamically, lazily... + */ + cbuf->sigArray = (unsigned *)ascMalloc((MAX_TOKENS + 1) * sizeof(unsigned)); +} + +void initCodeBufs( + comcryptBuf *cbuf, + const unsigned char *key, + unsigned keyLen, + unsigned char laEnable, + unsigned char sigSeqEnable) +{ + unsigned ct; + unsigned qval; + unsigned char khash = (unsigned char)keyHash(key, keyLen); + + cbuf->nybbleDex = khash; + + if(laEnable) { + memset(cbuf->lookAhead, 0, LOOKAHEAD_SIZE); + } + + laprintf(("initing queue and lookahead\n")); + + for(ct=0; ctqueue[ct] = qval; + if(laEnable) { + markInQueue(cbuf, qval, 1); + } + } + // note cbuf->nybbleDex = khash on return... + + cbuf->f1 = F1_DEFAULT; + cbuf->f2 = F2_DEFAULT; + cbuf->jmatchThresh = THRESH_2LEVEL_JMATCH_DEF; + cbuf->minByteCode = THRESH_2LEVEL_NUMBYTECODES_DEF; + if(sigSeqEnable) { + initSigSequence(cbuf, key, keyLen); + } +} + +void freeCodeBufs(comcryptBuf *cbuf) +{ + if(cbuf->queue != NULL) { + ascFree(cbuf->queue); + } + if(cbuf->codeBuf != NULL) { + ascFree(cbuf->codeBuf); + } + if(cbuf->level2Buf != NULL) { + ascFree(cbuf->level2Buf); + } + if(cbuf->nextBuf != NULL) { + freeCodeBufs(cbuf->nextBuf); + ascFree(cbuf->nextBuf); + cbuf->nextBuf = NULL; + } + if(cbuf->lookAhead != NULL) { + ascFree(cbuf->lookAhead); + } + if(cbuf->sigArray != NULL) { + ascFree(cbuf->sigArray); + } +} + +void serializeInt( + unsigned i, + unsigned char *buf) +{ + buf[0] = (unsigned char)(i >> 24); + buf[1] = (unsigned char)(i >> 16); + buf[2] = (unsigned char)(i >> 8); + buf[3] = (unsigned char)(i & 0xff); +} + +unsigned deserializeInt(unsigned char *buf) +{ + unsigned i; + + i = ((unsigned)buf[0]) << 24; + i |= ((unsigned)buf[1]) << 16; + i |= ((unsigned)buf[2]) << 8; + i |= buf[3]; + return i; +} + +#if COM_PARAM_ENABLE + +unsigned getF1(comcryptObj cobj) +{ + comcryptPriv *cpriv = (comcryptPriv *)cobj; + + return cpriv->cbuf.f1; +} + +void setF1(comcryptObj cobj, unsigned f1) +{ + comcryptPriv *cpriv = (comcryptPriv *)cobj; + + cpriv->cbuf.f1 = f1; + if(cpriv->cbuf.nextBuf != NULL) { + cpriv->cbuf.nextBuf->f1 = f1; + } +} + +unsigned getF2(comcryptObj cobj) +{ + comcryptPriv *cpriv = (comcryptPriv *)cobj; + + return cpriv->cbuf.f2; +} + +void setF2(comcryptObj cobj, unsigned f2) +{ + comcryptPriv *cpriv = (comcryptPriv *)cobj; + + cpriv->cbuf.f2 = f2; + if(cpriv->cbuf.nextBuf != NULL) { + cpriv->cbuf.nextBuf->f2 = f2; + } +} + +unsigned getJmatchThresh(comcryptObj cobj) +{ + comcryptPriv *cpriv = (comcryptPriv *)cobj; + + return cpriv->cbuf.jmatchThresh; +} + +void setJmatchThresh(comcryptObj cobj, unsigned jmatchThresh) +{ + comcryptPriv *cpriv = (comcryptPriv *)cobj; + + cpriv->cbuf.jmatchThresh = jmatchThresh; + if(cpriv->cbuf.nextBuf != NULL) { + cpriv->cbuf.nextBuf->jmatchThresh = jmatchThresh; + } +} + +unsigned getMinByteCode(comcryptObj cobj) +{ + comcryptPriv *cpriv = (comcryptPriv *)cobj; + + return cpriv->cbuf.minByteCode; +} + +void setMinByteCode(comcryptObj cobj, unsigned minByteCode) +{ + comcryptPriv *cpriv = (comcryptPriv *)cobj; + + cpriv->cbuf.minByteCode = minByteCode; + if(cpriv->cbuf.nextBuf != NULL) { + cpriv->cbuf.nextBuf->minByteCode = minByteCode; + } +} + +#endif /*COM_PARAM_ENABLE*/ + + +#if COM_LA_DEBUG + +/* + * Verify integrity of lookahead w.r.t. queue. + */ +int testLookAhead(comcryptBuf *cbuf, int i1, int i2) +{ + unsigned i; + + if(!cbuf->laEnable) { + return 0; + } + for(i=0; iqueue[i])) { + printf("aaagh, corrupted lookahead - in queue[], !inQueue()\n"); + printf("i=0x%x i1=0x%x i2=0x%x\n", + i, i1, i2); + printf("\n"); + exit(1); + } + } + //return initTestLookAhead(cbuf); + return 0; +} + +int initTestLookAhead(comcryptBuf *cbuf) +{ + #if QUEUE_LOOKAHEAD_BIT + + unsigned codeWord = 0; + unsigned char bit; + unsigned short byte; + unsigned char *la = cbuf->lookAhead; + + for(byte=0; bytequeue[i] == codeWord) { + found = 1; + break; + } + } + if(!found) { + printf("***corrupted init lookahead - in l.a., " + "not in queue[]\n"); + printf("codeWord 0x%x\n", codeWord); + printf("\n"); + exit(1); + } + } + codeWord++; + } + } + + #endif /* QUEUE_LOOKAHEAD_BIT */ + return 0; +} + +#endif /* COM_LA_DEBUG */ + +void initSigSequence(comcryptBuf *cbuf, + const unsigned char *key, + unsigned keyLen) +{ + unsigned seed = IN_OFFSET; + unsigned j; + + for(j=0; jsigArray[0] = (unsigned short)seed; +} + +#if 0 +/* + * Called once per token bit, after processing the token. + */ +void nextSigWord(comcryptBuf *cbuf, + unsigned sigDex, // same as tokenDex + unsigned match, + unsigned above) // jabove, keyabove +{ + unsigned offset; + unsigned short *sigArray = cbuf->sigArray; + + #if COM_DEBUG + if(sigDex == 0) { + printf("nextSigWord underflow\n"); + exit(1); + } + if(sigDex > MAX_TOKENS) { + printf("nextSigWord overflow\n"); + exit(1); + } + #endif + + if(match) { + offset = IN_OFFSET; + } + else { + offset = OUT_OFFSET; + } +#if 1 + sigArray[sigDex] = (sigArray[sigDex-1] * (above + offset)) % HASH_PRIME; +#endif +} +#endif + +/* + * Obfuscate a block of ciphertext. + */ +void sigMunge(comcryptBuf *cbuf, + const unsigned char *tokenPtr, + unsigned numTokens, + unsigned char *byteCodePtr, + unsigned char *longCodePtr) +{ + unsigned char tokenBit = 0x01; + unsigned token; + unsigned short sig; + + for(token=0; tokensigArray[token]; + if(*tokenPtr & tokenBit) { + /* no match - munge longCode - written MSB first */ + *longCodePtr++ ^= (unsigned char)(sig >> 8); + *longCodePtr++ ^= (unsigned char)sig; + } + else { + /* match - munge byteCode */ + *byteCodePtr++ ^= (unsigned char)sig; + } + tokenBit <<= 1; + if(tokenBit == 0) { + tokenBit = 0x01; + tokenPtr++; + } + } +} + + +/* + * All this can be optimized and tailored to specific platforms, of course... + */ + +void *ascMalloc(unsigned size) +{ + #ifdef macintosh + + Handle h; + OSErr err; + Ptr p; + + #endif /* mac */ + + if(comMallocExt != NULL) { + return (comMallocExt)(size); + } + + #ifdef macintosh + + h = nil; + err = noErr; + + h = NewHandleSys(size); // system heap is not paged + do{ + HLockHi(h); // will move low in system heap + err = MemError(); + if( err != noErr ) break; + p = *h; + }while(0); + if( err != noErr ){ + return NULL; + } + return p; + + #else /* others...*/ + return malloc(size); + #endif +} + +void ascFree(void *data) +{ + #ifdef macintosh + Handle h; + #endif + + if(comFreeExt != NULL) { + (comFreeExt)(data); + return; + } + + #ifdef macintosh + if( data != nil ){ + h = RecoverHandle((Ptr) data); + DisposeHandle(h); + } + + #else /* others */ + free(data); + #endif +} diff --git a/libsecurity_comcryption/lib/comcryptPriv.h b/libsecurity_comcryption/lib/comcryptPriv.h new file mode 100644 index 00000000..be167f6c --- /dev/null +++ b/libsecurity_comcryption/lib/comcryptPriv.h @@ -0,0 +1,487 @@ +/* + 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 + + To Do: +*/ + +#ifndef _COMCRYPT_PRIV_H_ +#define _COMCRYPT_PRIV_H_ + +#include "comcryption.h" +#include "comDebug.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern comMallocExternFcn *comMallocExt; +extern comFreeExternFcn *comFreeExt; + +/* + * type of element in comcryptBuf.queue[]. Making this an unsigned int gives + * a slight performance improvement on the i486 platform, but it does use up + * more memory. + */ +typedef unsigned queueElt; + +/* + * Enable queue lookahead via comcryptBuf.lookAhead[]. This is currently + * just the default value for comcryptBuf.laEnable. + */ +#define QUEUE_LOOKAHEAD 1 + +/* + * lookahead queue is bit array if 1, else byte array. + * FIXME - this will most likely be a hard-coded 1 for Mac and + * dynamically configurable for other platforms. + */ +#define QUEUE_LOOKAHEAD_BIT 1 + +/* + * Size of lookAhead buffer in bytes. + */ +#if QUEUE_LOOKAHEAD_BIT +/* + * 1 bit per potential queueElt value. + */ +#define LOOKAHEAD_SIZE (1 << ((2 * 8) - 3)) +#else /* QUEUE_LOOKAHEAD_BIT */ +/* + * One byte per queueElt value; avoids shifts and masks in accessing + * array elements at the cost of additional memory. + */ +#define LOOKAHEAD_SIZE (1 << (2 * 8)) +#endif /* QUEUE_LOOKAHEAD_BIT */ + +/* + * When true, optimize away the cost of the keynybble() call on a hit + * on queue[0]. + */ +#define SKIP_NIBBLE_ON_QUEUE_0 1 + +/* + * pre-malloc'd buffers, one per level of comcryption. This allows each level + * to maintain its own queue state machine as well as its own comcryption + * parameters. + */ +typedef struct _comcryptBuf { + queueElt *queue; // mallocd, QLEN elements + unsigned nybbleDex; // index for keynybble() + struct _comcryptBuf *nextBuf; // for recursion + + /* + * Used to temporarily store bytecode fragments during comcryption and + * partial blocks during decomcryption. + */ + unsigned char *codeBuf; + unsigned codeBufSize; // malloc'd size of codeBuf + unsigned codeBufLength; // valid bytes in codeBuf + + /* + * Buffer for two-level comcryption. During comcryption, 2nd level + * comcrypted bytecode is placed here. During decomcryption, the result + * of decomcrytping the 2nd level bytecode is placed here. + */ + unsigned char *level2Buf; + unsigned level2BufSize; // malloc'd size of level2Buf + + /* + * comcryption parameters, may (eventually) be different for different + * levels. Tweakable, for now, only via private API in comDebug.h. + */ + unsigned f1; + unsigned f2; + unsigned jmatchThresh; // max avg jmatch for 2 level + unsigned minByteCode; // min numByteCodes for 2 level + + /* + * Bit map, one bit per potential value in queue[]; 1 means "this value + * is somewhere in queue[]" + */ + unsigned char *lookAhead; + + /* + * Signature Sequence array - to be Xord with ciphertext + * size = MAX_TOKENS + */ + unsigned *sigArray; +} comcryptBuf; + + +/* + * Private struct associated with client's comcryptObj. + */ +typedef struct { + unsigned char *key; + unsigned keybytes; // valid bytes in *key + comcryptOptimize optimize; // CCO_SIZE, etc. + unsigned char *map; + unsigned char *invmap; + unsigned version; // from ciphertext + unsigned versionBytes; // valid bytes in version; + // also nonzero on comcrypt + // means version has been + // written + unsigned spareBytes; // # ciphertext header spare + // bytes skipped + comcryptBuf cbuf; + + /* + * To save a tiny bit of memory, these could/should be bits, but + * we examine some of them on every code word, so we'll expand them into + * bytes... + */ + unsigned char laEnable; // lookahead enable + unsigned char sigSeqEnable; // signature sequence enable + unsigned char level2enable; // 2-level comcryption + +} comcryptPriv; + + +/* + * Block and buffer sizes. Subject to tweaking... + */ +#define CC_BLOCK_SIZE 256 /* bytes of plaintext */ + +/* + * For comcryptMaxInBufSize(CCOP_COMCRYPT), if outBufSize exceeds this + * threshhold, truncate the max inBufSize so that + * inBufSize = 0 mod CC_BLOCK_SIZE. + */ +#define INBUF_TRUNC_THRESH (16 * 1024) + +/* + * Macros to calculate number of token bits and bytes associated with + * a quantity of plaintext (in bytes) + */ +#define TOKEN_BITS_FROM_PTEXT(pt) ((pt + 1) >> 1) +#define TOKEN_BYTES_FROM_PTEXT(pt) ((pt + 15) >> 4) +#define TOKEN_BYTES_FROM_TOKEN_BITS(tb) ((tb + 7) >> 3) + +/* + * Max number of token bits or code fragments in a block + */ +#define MAX_TOKENS (CC_BLOCK_SIZE / 2) + +/* + * Size of comcryptBuf.queue[]. + */ +#define QLEN 256 + +/* + * FIXME - some info on these constants? + */ +#define F1_DEFAULT 12 +#define F2_DEFAULT 12 +#define ABOVE(F2) ((F2 * QLEN) >> 4) + +/* + * Constants for obfuscation via signature sequence. + */ +#define HASH_Q 19 +#define HASH_PRIME ((1< HASH_PRIME) { \ + x = (x >> HASH_Q) + (x & HASH_PRIME); \ + } \ +} + +/* + * Haven't gotten this to work for the Mac yet... + */ +#ifdef NeXT +#define SIG_WORD_INLINE 1 +#else /*NeXT*/ +#define SIG_WORD_INLINE 0 +#endif + +#if SIG_WORD_INLINE + +static inline void nextSigWord(comcryptBuf *cbuf, + unsigned sigDex, // same as tokenDex + unsigned match, + unsigned above) // (jabove, keyabove) + nibbleDex +{ + unsigned offset; + unsigned *sigArray = cbuf->sigArray; + + #if COM_DEBUG + if(sigDex == 0) { + printf("nextSigWord underflow\n"); + exit(1); + } + if(sigDex > MAX_TOKENS) { + printf("nextSigWord overflow\n"); + exit(1); + } + #endif + + if(match) { + offset = IN_OFFSET; + } + else { + offset = OUT_OFFSET; + } + sigArray[sigDex] = sigArray[sigDex-1] * (above + offset); + MOD_HASH(sigArray[sigDex]); +} + +#else /*SIG_WORD_INLINE*/ + +#define nextSigWord(cbuf, sigDex, match, above) { \ + unsigned offset = (match ? IN_OFFSET : OUT_OFFSET); \ + unsigned *sigArray = cbuf->sigArray; \ + unsigned result = (sigArray[sigDex-1] * (above + offset)); \ + MOD_HASH(result); \ + sigArray[sigDex] = result; \ +} + +#endif /*SIG_WORD_INLINE*/ + +/* + * Inline serializeShort(), deserializeShort() + */ +#define serializeShort(s, buf) \ + buf[0] = (unsigned char)(s >> 8); \ + buf[1] = (unsigned char)(s); \ + +#define deserializeShort(s, buf) \ + s = ((unsigned short)buf[0]) << 8; \ + s |= buf[1]; \ + + +/* + * General purpose macros for accessing bit arrays. Used for accessing + * token bits and lookahead array bits if QUEUE_LOOKAHEAD_BIT = 1. + */ +#define MARK_BIT_ARRAY(cp, index, val) { \ + unsigned char bit = 1 << (index & 7); \ + unsigned char *bytePtr = &cp[index>>3]; \ + if(val) { \ + *bytePtr |= bit; \ + } \ + else { \ + *bytePtr &= ~bit; \ + } \ +} +#define GET_BIT_ARRAY(cp, index) \ + (cp[index >> 3] & (1 << (index & 7))) + +#define getToken(tokenPtr, tokenDex) \ + GET_BIT_ARRAY(tokenPtr, tokenDex) + +#define updateToken(tokenPtr, tokenDex, tokenBit) \ + MARK_BIT_ARRAY(tokenPtr, tokenDex, tokenBit) + +/* + * Macros for accessing lookahead array elements + */ + +#if QUEUE_LOOKAHEAD_BIT +/* + * This way saves memory + */ +#define markInQueue(cbuf, codeWord, val) \ + MARK_BIT_ARRAY(cbuf->lookAhead, codeWord, val) + +#define inQueue(cbuf, codeWord) \ + GET_BIT_ARRAY(cbuf->lookAhead, codeWord) + +#else /* QUEUE_LOOKAHEAD_BIT */ + +/* + * This way saves time + */ +#define markInQueue(cbuf, codeWord, val) { \ + cbuf->lookAhead[codeWord] = val; \ +} +#define inQueue(cbuf, codeWord) (cbuf->lookAhead[codeWord]) + +#endif /* QUEUE_LOOKAHEAD_BIT */ + +void *ascMalloc(unsigned size); +void ascFree(void *data); + +#ifdef __cplusplus +} +#endif + +#endif /*_COMCRYPT_PRIV_H_*/ diff --git a/libsecurity_comcryption/lib/comcryption.c b/libsecurity_comcryption/lib/comcryption.c new file mode 100644 index 00000000..23ae85af --- /dev/null +++ b/libsecurity_comcryption/lib/comcryption.c @@ -0,0 +1,1444 @@ +/* + 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. + +*/ + +#include +#include +#include +#include "comcryption.h" +#include "comDebug.h" +#include "comcryptPriv.h" + +#if COM_PROFILE + +unsigned comProfEnable; +comprof_t cmcTotal; +comprof_t cmcQueSearch; +comprof_t cmcQueMatchMove; +comprof_t cmcQueMissMove; +comprof_t cmcLevel2; +comprof_t cmcPerWordOhead; + +#endif /*COM_PROFILE*/ + +void comMallocRegister(comMallocExternFcn *mallocExtern, + comFreeExternFcn *freeExtern) +{ + comMallocExt = mallocExtern; + comFreeExt = freeExtern; +} + +/* + * Call once at startup. The resulting comcryptObj can be reused multiple + * times. + */ +comcryptObj comcryptAlloc() +{ + comcryptPriv *cpriv = (comcryptPriv *) ascMalloc(sizeof(comcryptPriv)); + + if(cpriv == NULL) { + return NULL; + } + memset(cpriv, 0, sizeof(comcryptPriv)); + +#if COMCRYPT_EXPORT_ONLY + cpriv->key = (unsigned char *)ascMalloc(EXPORT_KEY_SIZE); +#else /*COMCRYPT_EXPORT_ONLY*/ + cpriv->key = (unsigned char *)ascMalloc(COMCRYPT_MAX_KEYLENGTH); +#endif /*COMCRYPT_EXPORT_ONLY*/ + + if(cpriv->key == NULL) { + return NULL; + } + cpriv->map = (unsigned char *)ascMalloc(256); + cpriv->invmap = (unsigned char *)ascMalloc(256); + if((cpriv->map == NULL) || (cpriv->invmap == NULL)) { + return NULL; + } + mallocCodeBufs(&cpriv->cbuf); + if((cpriv->cbuf.codeBuf == NULL) || + (cpriv->cbuf.level2Buf == NULL)) { + return NULL; + } + #if QUEUE_LOOKAHEAD + if(cpriv->cbuf.lookAhead == NULL) { + return NULL; + } + #endif + + /* + * Hard coded limit of two levels of comcryption + */ + cpriv->cbuf.nextBuf = (comcryptBuf *)ascMalloc(sizeof(comcryptBuf)); + if(cpriv->cbuf.nextBuf == NULL) { + return NULL; + } + mallocCodeBufs(cpriv->cbuf.nextBuf); + if((cpriv->cbuf.nextBuf->codeBuf == NULL) || + (cpriv->cbuf.nextBuf->level2Buf == NULL)) { + return NULL; + } + #if QUEUE_LOOKAHEAD + if(cpriv->cbuf.nextBuf->lookAhead == NULL) { + return NULL; + } + #endif + + cpriv->cbuf.nextBuf->nextBuf = NULL; + return cpriv; +} + +/* + * Call this before starting every stream process + */ +comcryptReturn comcryptInit( + comcryptObj cobj, + const unsigned char *key, + unsigned keyLen, + comcryptOptimize optimize) // CCO_SIZE, etc. +{ + comcryptPriv *cpriv = (comcryptPriv *)cobj; + unsigned maxKeySize; + +#if COMCRYPT_EXPORT_ONLY + /* + * FIXME - NSA might not be satisfied with this, may have to enforce + * elsewhere + */ + maxKeySize = EXPORT_KEY_SIZE; +#else /*COMCRYPT_EXPORT_ONLY*/ + maxKeySize = COMCRYPT_MAX_KEYLENGTH; +#endif /*COMCRYPT_EXPORT_ONLY*/ + + if(keyLen > maxKeySize) { + keyLen = maxKeySize; + } + memmove(cpriv->key, key, keyLen); + cpriv->keybytes = keyLen; + cpriv->cbuf.codeBufLength = 0; + cpriv->cbuf.nextBuf->codeBufLength = 0; + cpriv->version = 0; + cpriv->versionBytes = 0; + cpriv->spareBytes = 0; + cpriv->optimize = optimize; + + /* + * Derive feature enable bits from optimize arg. This is highly likely + * to change.... + */ + cpriv->level2enable = 1; + cpriv->sigSeqEnable = 1; + switch(optimize) { + case CCO_TIME: + cpriv->level2enable = 0; + break; + case CCO_TIME_SIZE: + cpriv->sigSeqEnable = 0; + break; + default: + break; + } +#if QUEUE_LOOKAHEAD + cpriv->laEnable = 1; +#else /* QUEUE_LOOKAHEAD */ + cpriv->laEnable = 0; +#endif /* QUEUE_LOOKAHEAD */ + + /* + * init queue and maps + */ + initCodeBufs(&cpriv->cbuf, key, keyLen, cpriv->laEnable, + cpriv->sigSeqEnable); + initCodeBufs(cpriv->cbuf.nextBuf, key, keyLen, cpriv->laEnable, + cpriv->sigSeqEnable); + key_perm(key, keyLen, cpriv->map, cpriv->invmap); + return CCR_SUCCESS; +} + +/* + * Free a comcryptObj object obtained via comcryptAlloc() + */ +void comcryptObjFree(comcryptObj cobj) +{ + comcryptPriv *cpriv = (comcryptPriv *)cobj; + + if(cpriv->key != NULL) { + ascFree(cpriv->key); + } + if(cpriv->map != NULL) { + ascFree(cpriv->map); + } + if(cpriv->invmap != NULL) { + ascFree(cpriv->invmap); + } + freeCodeBufs(&cpriv->cbuf); + ascFree(cpriv); +} + +/* + * Return the maximum input buffer size allowed for for specified + * output buffer size. Note that for both comcrypt and decomcrypt, + * to cover the worst case, the output buffer always has to be + * larger than the input buffer. + */ +unsigned comcryptMaxInBufSize(comcryptObj cobj, + unsigned outBufSize, + comcryptOp op) +{ + unsigned fullBlocks; + unsigned minCblockSize; + unsigned resid; + unsigned rtn; + unsigned tokenBytes; + comcryptPriv *cpriv = (comcryptPriv *)cobj; + unsigned ptextFromCodeBuf; + + switch(op) { + case CCOP_COMCRYPT: + /* + * Worst case: no compression. Also, establish a minimum + * ciphertext size to accomodate header and one block. + */ + minCblockSize = MIN_CBLOCK_SIZE; + if(cpriv->versionBytes == 0) { + minCblockSize += CTEXT_HDR_SIZE; + } + if(outBufSize < (minCblockSize)) { + return 0; + } + if(cpriv->versionBytes == 0) { + outBufSize -= CTEXT_HDR_SIZE; + } + fullBlocks = outBufSize / MAX_CBLOCK_SIZE; + rtn = (fullBlocks * CC_BLOCK_SIZE); // bytes of ptext + + /* + * code must be even aligned, then chop off one for odd ptext + */ + rtn &= 0xfffffffe; + rtn--; + if(rtn <= 0) { + return 0; + } + resid = outBufSize % MAX_CBLOCK_SIZE; + if(resid) { + rtn += resid; + + /* + * Account for resid block overhead + */ + if(rtn < MIN_CBLOCK_SIZE) { + return 0; + } + rtn -= MIN_CBLOCK_SIZE; + + tokenBytes = TOKEN_BYTES_FROM_PTEXT(resid); + if(rtn <= tokenBytes) { + return 0; + } + rtn -= tokenBytes; + } + if(rtn > INBUF_TRUNC_THRESH) { + /* + * Truncate to even block size to minimize partial cipherblocks + */ + rtn &= ~(CC_BLOCK_SIZE - 1); + } + return rtn; + + case CCOP_DECOMCRYPT: + /* + * Worst case - 4:1 compression and an almost full block in + * codeBuf. Note 4:1 is a super-conservative, easy arithmetic + * version of (9/16) squared... + */ + ptextFromCodeBuf = cpriv->cbuf.codeBufLength * 4; + if(outBufSize < ptextFromCodeBuf) { + /* decrypting codeBuf might overflow output (plaintext) + * buffer - won't be able to move anything */ + rtn = 0; + } + else { + /* can decrypt (this much plainText - ptextFromCodeBuf) / 4 */ + rtn = (outBufSize - ptextFromCodeBuf) / 4; + } + + /* may be able to handle a bit extra for initial decrypt... */ + if(cpriv->versionBytes < VERSION_BYTES) { + rtn += (VERSION_BYTES - cpriv->versionBytes); + } + if(cpriv->spareBytes < SPARE_BYTES) { + rtn += (SPARE_BYTES - cpriv->spareBytes); + } + return rtn; + + default: + ddprintf(("bogus op (%d) in comcryptMaxInBufSize()\n", op)); + return 0; + } +} + +/* + * Return the maximum output buffer size for specified input buffer size. + * Output buffer size will always be larger than input buffer size. + */ +unsigned comcryptMaxOutBufSize(comcryptObj cobj, + unsigned inBufSize, + comcryptOp op, + char final) +{ + unsigned fullBlocks; + unsigned resid; + unsigned rtn; + comcryptPriv *cpriv = (comcryptPriv *)cobj; + + switch(op) { + case CCOP_COMCRYPT: + fullBlocks = inBufSize / CC_BLOCK_SIZE; + rtn = fullBlocks * MAX_CBLOCK_SIZE; + resid = inBufSize % CC_BLOCK_SIZE; + if(resid != 0) { + /* + * partial block + */ + unsigned tokenBytes = TOKEN_BYTES_FROM_PTEXT(resid); + + rtn += MIN_CBLOCK_SIZE; + rtn += tokenBytes; + rtn += resid; // no compression + if(resid & 1) { + rtn++; // oddByte uses extra + } + } + if((cpriv == NULL) || // i.e., we're being called from mallocCodeBufs + (cpriv->versionBytes == 0)) { + rtn += CTEXT_HDR_SIZE; // first of a stream + } + return rtn; + + case CCOP_DECOMCRYPT: + /* + * Here assume max compression, including resid block in codeBuf + */ + inBufSize += cpriv->cbuf.codeBufLength; + if(inBufSize) { + /* may be able to handle a bit extra for initial decrypt... */ + unsigned delta; + if(cpriv->versionBytes < VERSION_BYTES) { + delta = VERSION_BYTES - cpriv->versionBytes; + if(inBufSize > delta) { + inBufSize -= delta; + } + else { + inBufSize = 0; + } + } + if(cpriv->spareBytes < SPARE_BYTES) { + delta = SPARE_BYTES - cpriv->spareBytes; + if(inBufSize > delta) { + inBufSize -= delta; + } + else { + inBufSize = 0; + } + } + } + rtn = 4 * inBufSize; + return rtn; + + default: + ddprintf(("bogus op (%d) in comcryptMaxOutBufSize()\n", op)); + return 0; + } +} + +/* + * Threshold for using memmove() rather than hard-coded loop for + * moving queue segment. This was derived empirically on a Pentium; + * we should do similar measurements on PPC. + */ +#define QUEUE_MEMMOVE_THRESH 3 + +/* + * peek at queue[0] before search. This appears to only be a win for + * constant plaintext, i.e., the codeword is almost always at queue[0]. + */ +#define QUEUE_PEEK 0 + +/* + * Comcrypt one block. + */ +static comcryptReturn comcryptBlock( + comcryptPriv *cpriv, + comcryptBuf *cbuf, // not necessarily cpriv->cbuf + const unsigned char *plainText, + unsigned plainTextLen, + unsigned char *cipherText, + unsigned *cipherTextLen, // IN/OUT + unsigned recursLevel) +{ + unsigned char *byteCodePtr; + unsigned char *destByteCodePtr; + unsigned char *longCodePtr; + unsigned char *startLongCodePtr; + unsigned char *tokenPtr; + unsigned char *startTokenPtr; + unsigned char *startCtextPtr = cipherText; + unsigned numTokenBytes; // in bytes, constant + unsigned short codeWord; + unsigned oddByte = 0; + unsigned match; + unsigned jmatch=0; + unsigned tokenDex = 0; // index into array of token bits + unsigned j; + unsigned numLongCodes = 0; + unsigned numByteCodes = 0; + unsigned totalCipherTextLen; + unsigned above; + unsigned jmatchTotal = 0; + unsigned jmatchAvg; + comcryptReturn crtn; + unsigned char blockDesc = CBD_MAGIC; + unsigned fullBlock = 0; + int len; + queueElt *src; + queueElt *dst; + queueElt *cbufq = &cbuf->queue[0]; + + /* + * 'nibble' is added to 'above' in the call to nextSigWord() for + * additional security. + * + * Normal case : nibble = keynybble() + * last word on odd byte : nibble = nibbleDex + * hit on queue q : nibble = nibbleDex (optimize to avoid keynybble() + * call) + */ + unsigned char nibble; + + COMPROF_LOCALS; + + #if COM_LA_DEBUG + if(testLookAhead(cbuf, 0, 0)) { + return CCR_INTERNAL; + } + #endif + + laprintf(("comcryptBlock recurs level %d\n", recursLevel)); + + /* + * Set up ptrs for the three arrays we'll be writing + */ + tokenPtr = cipherText + CTBO_NUM_TOKENS + 1; + if(plainTextLen >= (CC_BLOCK_SIZE - 1)) { + /* + * Optimized for full block - no token count in block. Note + * that plainTextLen == (CC_BLOCK_SIZE - 1) is also a full block + * in that it uses up a full block's worth of tokens! + */ + numTokenBytes = CC_BLOCK_SIZE >> 4; + tokenPtr--; + blockDesc |= CBD_FULL_BLOCK; + fullBlock = 1; + } + else { + numTokenBytes = (plainTextLen + 15) >> 4; + } + longCodePtr = tokenPtr + numTokenBytes; + startLongCodePtr = longCodePtr; + byteCodePtr = cbuf->codeBuf; + startTokenPtr = tokenPtr; + + if((unsigned)(longCodePtr - cipherText) > *cipherTextLen) { + ddprintf(("comcryptBlock: short block (1)\n")); + return CCR_OUTBUFFER_TOO_SMALL; + } + memset(tokenPtr, 0, numTokenBytes); + + /* + * Entering time-critical region. This loop executes once for every + * 2 bytes of plaintext. Make every attempt to streamline the code + * here; avoid function calls in favor of macros; etc. + */ + while(plainTextLen != 0) { + + /* + * assemble a 16-bit word from two bytes if possible + */ + if(plainTextLen == 1) { + /* + * Odd byte case + */ + codeWord = ((unsigned short)(cpriv->map[*plainText]) << 8) | + cpriv->map[0]; // a bit of obfuscation - mapped zero + oddByte = 1; + blockDesc |= CBD_ODD; + plainTextLen--; + } + else { + codeWord = ((unsigned short)(cpriv->map[*plainText]) << 8) | + (unsigned short)(cpriv->map[plainText[1]]); + plainText += 2; + plainTextLen -= 2; + } + + /* + * Calibrate how much profiling is costing us. + */ + COMPROF_START; + COMPROF_END(cmcPerWordOhead); + + /* + * See if this word is in queue[]. Skip if oddByte; we'll force + * a 16-bit word in that case. Also skip the search if we know + * via lookahead that a search would be fruitless. + */ + COMPROF_START; /* cmcQueSearch */ + match = 0; + do { /* while 0 - for easy breaks w/o goto */ + + /* + * First handle some optimizations and special cases + */ + if(oddByte) { + break; // force longcode + } + +#if QUEUE_PEEK + if(cbufq[0] == codeWord) { + match = 1; + jmatch = 0; + break; + + } +#endif /*QUEUE_PEEK*/ + + if(cpriv->laEnable && !inQueue(cbuf, codeWord)) { + break; + } + + /* + * OK, do the gruntwork search + */ + for(j=0; j < QLEN; j++) { + if(cbufq[j] == codeWord) { + match = 1; + jmatch = j; + break; + } + } + +#if COM_LA_DEBUG + if(cpriv->laEnable && !match) { + printf("inQueue, not found in queue!\n"); + return CCR_INTERNAL; + } + + /* + * Search for duplicates. + */ + if(match) { + for(j=jmatch+1; jkey, cpriv->keybytes, + (cbuf->nybbleDex)++); +#endif /*SKIP_NIBBLE_ON_QUEUE_0*/ + + COMPROF_START; + if(match) { + /* + * 16-bit symbol is in queue. 8 bits of ciphertext, token bit is 0. + */ + if(jmatch == 0) { + /* + * Optimization: jmatch = 0. Keep state machine in sync, + * but skip queue update. + */ + above = 0; + laprintf(("...queue hit at queue[0]\n")); +#if SKIP_NIBBLE_ON_QUEUE_0 + nibble = (cbuf->nybbleDex)++; +#endif /*SKIP_NIBBLE_ON_QUEUE_0*/ + } + else { +#if SKIP_NIBBLE_ON_QUEUE_0 + nibble = keynybble(cpriv->key, cpriv->keybytes, + (cbuf->nybbleDex)++); +#endif /*SKIP_NIBBLE_ON_QUEUE_0*/ + + above = (cbuf->f1 * jmatch * (16 + nibble)) >> 9; + + /* + * queue[above..(jmatch-1)] move one element towards end + * queue[above] = this codeWord + */ + laprintf(("...queue hit, moving 0x%x from 0x%x to 0x%x\n", + codeWord, jmatch, above)); + + len = (int)jmatch - (int)above; + if(len > QUEUE_MEMMOVE_THRESH) { + src = &cbufq[above]; + dst = src + 1; + len *= sizeof(queueElt); + memmove(dst, src, len); + } + else { + for(j = jmatch; j>above; j--) { + cbufq[j] = cbufq[j-1]; + } + } + + cbufq[above] = codeWord; +#if COM_LA_DEBUG + if(testLookAhead(cbuf, above, jmatch)) { + return CCR_INTERNAL; + } +#endif /*COM_LA_DEBUG*/ + } + COMPROF_END(cmcQueMatchMove); + + codeWord = jmatch; + incr1byteFrags(recursLevel); + jmatchTotal += jmatch; + } + else if(oddByte == 0) { + /* + * 16-bit symbol is not in queue. 16 bits of ciphertext. + * Token bit is 1. + * + * queue[above...QLEN-1] move one element toward end + * queue[QLEN-1] discarded + * queue[above] = new codeword + * + * Note we skip this queue manipulation in the oddbyte case, since + * we don't really know (or care) if the current code word is in + * the queue or not. + */ +#if SKIP_NIBBLE_ON_QUEUE_0 + nibble = keynybble(cpriv->key, cpriv->keybytes, + (cbuf->nybbleDex)++); +#endif /*SKIP_NIBBLE_ON_QUEUE_0*/ + + above = ABOVE(cbuf->f2) + nibble; + +#if COM_DEBUG + if(above > QLEN) { + printf("Hey Doug! above %d QLEN %d\n", above, QLEN); + return CCR_INTERNAL; + } +#endif + + laprintf(("...queue miss, adding 0x%x at 0x%x, deleting 0x%x\n", + codeWord, above, cbufq[QLEN-1])); + + if(cpriv->laEnable) { + markInQueue(cbuf, codeWord, 1); // new entry + markInQueue(cbuf, cbufq[QLEN-1], 0); // bumped out + } + + len = QLEN - 1 - (int)above; + if(len > QUEUE_MEMMOVE_THRESH) { + src = &cbufq[above]; + dst = src + 1; + len *= sizeof(queueElt); + memmove(dst, src, len); + } + else { + for(j=QLEN-1; j > above; j--) { + cbufq[j] = cbufq[j-1]; + } + } + + cbufq[above] = codeWord; + +#if COM_LA_DEBUG + if(testLookAhead(cbuf, above, 0)) { + return CCR_INTERNAL; + } +#endif /*COM_LA_DEBUG*/ + + COMPROF_END(cmcQueMissMove); + incr2byteFrags(recursLevel); + } + else { + /* + * Odd byte case, at least gather stats. + */ + incr2byteFrags(recursLevel); + + /* + * ...and keep this in sync for signature sequence + */ + above = 0; +#if SKIP_NIBBLE_ON_QUEUE_0 + nibble = (cbuf->nybbleDex)++; +#endif /*SKIP_NIBBLE_ON_QUEUE_0*/ + } + + updateToken(tokenPtr, tokenDex, !match); + tokenDex++; + + if(match) { + *byteCodePtr++ = codeWord & 0xff; + numByteCodes++; + } + else { + serializeShort(codeWord, longCodePtr); + longCodePtr += 2; + numLongCodes++; + } + if(cpriv->sigSeqEnable) { + nextSigWord(cbuf, tokenDex, match, (above + nibble)); + } + } + +#if COM_DEBUG + if(numTokenBytes != ((tokenDex + 7) >> 3)) { + ddprintf(("comcryptBlock: numTokenBytes (%d), tokenDex (%d)\n", + numTokenBytes, tokenDex)); + } +#endif /*COM_DEBUG*/ + + /* + * We already wrote tokens and longcode to cipherText; verify we + * didn't overrun + */ + totalCipherTextLen = (longCodePtr - startCtextPtr); + if(*cipherTextLen < totalCipherTextLen) { + ddprintf(("comcryptBlock: short block (2)\n")); + return CCR_OUTBUFFER_TOO_SMALL; + } + if(!fullBlock) { + cipherText[CTBO_NUM_TOKENS] = tokenDex; + } + cipherText[CTBO_NUM_LONG_CODES] = numLongCodes; + +#if COM_DEBUG + if(tokenDex > MAX_TOKENS) { + ddprintf(("comcryptBlock: counter overflow!\n")); + return CCR_INTERNAL; + } + if((numByteCodes + numLongCodes) != tokenDex) { + ddprintf(("comcryptBlock: counter mismatch!\n")); + return CCR_INTERNAL; + } +#endif /*COM_DEBUG*/ + + /* + * See if doing a second level comcryption makes sense. + */ + destByteCodePtr = startLongCodePtr + (numLongCodes * 2); + if(numByteCodes > 0) { + jmatchAvg = jmatchTotal / numByteCodes; + } + else { + jmatchAvg = cbuf->jmatchThresh + 1; + } + if((recursLevel == 0) && // hard coded recursion limit + (cpriv->level2enable) && // enabled by caller + (numByteCodes >= cbuf->minByteCode) && // meaningful # of bytecodes + (jmatchAvg <= cbuf->jmatchThresh)) { // reasonable compression + // already achieved + + unsigned thisCtext = cbuf->level2BufSize; + + COMPROF_START; + crtn = comcryptBlock(cpriv, + cbuf->nextBuf, + cbuf->codeBuf, + numByteCodes, + cbuf->level2Buf, + &thisCtext, + recursLevel + 1); + if(crtn) { + return crtn; + } + + /* + * Write level2Buf to cipherText (as byteCodeArray). + * Size of 2nd level comcrypted byte code follows longcode array, + * then the bytecode itself. + * First bump totalCipherTextLen by the size of the comcrypted array + * plus one (for the size byte itself), and verify no overflow + */ + totalCipherTextLen += (thisCtext + 1); + if(*cipherTextLen < totalCipherTextLen) { + ddprintf(("comcryptBlock: short block (3)\n")); + return CCR_OUTBUFFER_TOO_SMALL; + } + *destByteCodePtr++ = thisCtext; + COMPROF_END(cmcLevel2); + memmove(destByteCodePtr, cbuf->level2Buf, thisCtext); + blockDesc |= CBD_DOUBLE; + + l2printf(("***2nd-level comcrypt: numByteCodes %d encrypted " + "size %d\n", numByteCodes, thisCtext)); + incrComStat(level2byteCode, numByteCodes); + incrComStat(level2cipherText, thisCtext); + incrComStat(level2jmatch, jmatchTotal); + incrComStat(level2blocks, 1); + } + else { + /* + * Normal one-level comcryption. Write byteCodes to ciphertext. + * numByteCodes is inferred. + */ + totalCipherTextLen += numByteCodes; + if(*cipherTextLen < totalCipherTextLen) { + ddprintf(("comcryptBlock: short block (3)\n")); + return CCR_OUTBUFFER_TOO_SMALL; + } + memmove(destByteCodePtr, cbuf->codeBuf, numByteCodes); + blockDesc |= CBD_SINGLE; + if(recursLevel == 0) { + incrComStat(level1blocks, 1); + } + /* else this is a 2nd-level, our caller will count */ + + /* + * obfuscate via sigArray (only when we're NOT doing 2nd level + * comcrypt) + */ + if(cpriv->sigSeqEnable) { + sigMunge(cbuf, startTokenPtr, tokenDex, + destByteCodePtr, startLongCodePtr); + + /* + * Prime sigArray state machine for next block. Note in the case + * of 2nd level, we skip this step, so the next block starts from + * the same state as this one did. + */ + cbuf->sigArray[0] = cbuf->sigArray[tokenDex]; + } + } + cipherText[CTBO_BLOCK_DESC] = blockDesc; + *cipherTextLen = totalCipherTextLen; + return CCR_SUCCESS; +} + +/* + * Main public encrypt function. + */ +comcryptReturn comcryptData( + comcryptObj cobj, + unsigned char *plainText, + unsigned plainTextLen, + unsigned char *cipherText, // malloc'd by caller + unsigned *cipherTextLen, // IN/OUT + comcryptEos endOfStream) // CCE_END_OF_STREAM, etc. +{ + comcryptPriv *cpriv = (comcryptPriv *)cobj; + unsigned ctextLen = *cipherTextLen; + comcryptReturn crtn; + unsigned thisPtext; + unsigned thisCtext; + COMPROF_LOCALS; + + COMPROF_START; + incrComStat(plaintextBytes, plainTextLen); + if(cpriv->versionBytes == 0) { + /* + * First, put header (version, spare) into head of ciphertext. + */ + if(ctextLen < CTEXT_HDR_SIZE) { + ddprintf(("comcryptData: overflow (0)\n")); + return CCR_OUTBUFFER_TOO_SMALL; + } + serializeInt(VERSION_3_Dec_97, cipherText); + cipherText += VERSION_BYTES; + cpriv->versionBytes = VERSION_BYTES; + serializeInt(0, cipherText); // spares + cipherText += SPARE_BYTES; + ctextLen -= CTEXT_HDR_SIZE; + } + + /* + * OK, grind it out, one block at a time. + */ + while (plainTextLen != 0) { + thisPtext = CC_BLOCK_SIZE; + if(thisPtext > plainTextLen) { + thisPtext = plainTextLen; + } + thisCtext = ctextLen; + crtn = comcryptBlock(cpriv, + &cpriv->cbuf, + plainText, + thisPtext, + cipherText, + &thisCtext, + 0); // recurs level + if(crtn) { + return crtn; + } + plainText += thisPtext; + plainTextLen -= thisPtext; + if(thisCtext > ctextLen) { + ddprintf(("comcryptData: undetected ciphertext overlow\n")); + return CCR_OUTBUFFER_TOO_SMALL; + } + cipherText += thisCtext; + ctextLen -= thisCtext; + } + *cipherTextLen = *cipherTextLen - ctextLen; + incrComStat(ciphertextBytes, *cipherTextLen); + COMPROF_END(cmcTotal); + return CCR_SUCCESS; +} + +/* + * Return values from deComcryptBlock(). + */ +typedef enum { + DCB_SUCCESS, // OK + DCB_SHORT, // incomplete block, try again with more ciphertext + DCB_PARSE_ERROR, // bad block + DCB_OUTBUFFER_TOO_SMALL +} dcbReturn; + +/* + * Assumes exactly one block of ciphertext, error otherwise. + */ +static dcbReturn deComcryptBlock( + comcryptPriv *cpriv, + comcryptBuf *cbuf, // not necessarily cpriv->cbuf + unsigned char *cipherText, + unsigned cipherTextLen, + unsigned char *plainText, + unsigned *plainTextLen, // IN/OUT + comcryptEos endOfStream, // CCE_END_OF_STREAM, etc. + unsigned *blockSize) // RETURNED on DCB_SUCCESS +{ + unsigned char *tokenPtr; + unsigned numTokenBits; // constant, from ciphertext + unsigned numTokenBytes; + unsigned char *longCodePtr; + unsigned numLongCodes; + unsigned char *byteCodePtr; + unsigned numByteCodes; + unsigned tokenDex; + unsigned oddByte = 0; + unsigned short codeWord; + unsigned char codeByte; + unsigned ptextLen = *plainTextLen; // bytes REMAINING + unsigned above; + unsigned j; + unsigned char blockDesc; + dcbReturn drtn; + int len; + queueElt *src; + queueElt *dst; + int lastWord = 0; + queueElt *cbufq = &cbuf->queue[0]; + int level2 = 0; // 2nd level comcrypted block + unsigned match; + unsigned char sigSeq; // signature sequence enable + unsigned char nibble; + + blockDesc = cipherText[CTBO_BLOCK_DESC]; + if((blockDesc & CBD_MAGIC_MASK) != CBD_MAGIC) { + ddprintf(("deComcryptBlock: bad CBD_MAGIC\n")); + return DCB_PARSE_ERROR; + } + + /* + * Min block size - blockDesc, numLongCodes, numTokens, one token byte, + * one bytecode + */ + if(cipherTextLen < 5) { + return DCB_SHORT; + } + if((blockDesc & CBD_FULL_BLOCK_MASK) == CBD_FULL_BLOCK) { + /* + * # of token bits implied for full block + */ + numTokenBits = TOKEN_BITS_FROM_PTEXT(CC_BLOCK_SIZE); + numTokenBytes = TOKEN_BYTES_FROM_PTEXT(CC_BLOCK_SIZE); + tokenPtr = cipherText + CTBO_NUM_TOKENS; + } + else { + numTokenBits = cipherText[CTBO_NUM_TOKENS]; + numTokenBytes = TOKEN_BYTES_FROM_TOKEN_BITS(numTokenBits); + tokenPtr = cipherText + CTBO_NUM_TOKENS + 1; + } + longCodePtr = tokenPtr + numTokenBytes; + numLongCodes = cipherText[CTBO_NUM_LONG_CODES]; + + byteCodePtr = longCodePtr + (numLongCodes * 2); // may increment... + if((blockDesc & CBD_BLOCK_TYPE_MASK) == CBD_SINGLE) { + /* + * # of bytecodes implied from numTokenBits and numLongCodes + */ + numByteCodes = numTokenBits - numLongCodes; + } + else { + /* + * size of 2nd level comcrypted bytecode specified after longCode + * array (and before the bytecode itself). + * Careful, verify that we can read numByteCodes first... + */ + if((unsigned)(byteCodePtr - cipherText) > cipherTextLen) { + return DCB_SHORT; + } + numByteCodes = *byteCodePtr++; + level2 = 1; + } + *blockSize = (byteCodePtr - cipherText) + numByteCodes; + if(*blockSize > cipherTextLen) { + return DCB_SHORT; + } + + /* + * We now know that we have a complete cipherblock. Go for it. + */ + if(level2) { + /* + * this block's bytecode array contains 2nd level comcrypted bytecodes. + */ + unsigned thisPtext = cbuf->level2BufSize; + unsigned level1CodeSize; + + if(cbuf->nextBuf == NULL) { + ddprintf(("2-level comcypt, no nextBuf available!\n")); + return DCB_PARSE_ERROR; + } + drtn = deComcryptBlock(cpriv, + cbuf->nextBuf, + byteCodePtr, + numByteCodes, + cbuf->level2Buf, + &thisPtext, + CCE_END_OF_STREAM, + &level1CodeSize); + switch(drtn) { + case DCB_SHORT: + ddprintf(("CBT_DOUBLE block, incomplete cipherblock in " + "2nd level code\n")); + return DCB_PARSE_ERROR; + + case DCB_OUTBUFFER_TOO_SMALL: // not our fault! + case DCB_PARSE_ERROR: + default: + ddprintf(("2nd-level decomcrypt error (%d)\n", drtn)); + return drtn; + + case DCB_SUCCESS: + /* + * Supposedly we passed in exactly one cipherblock... + */ + if(numByteCodes != level1CodeSize) { + ddprintf(("2nd-level decomcrypt: " + "numByteCodes != level1CodeSize\n")); + return DCB_PARSE_ERROR; + } + l2printf(("2nd-level decomcrypt: ciphertext %d " + "numByteCodes %d\n", numByteCodes, thisPtext)); + break; + } + byteCodePtr = cbuf->level2Buf; + numByteCodes = thisPtext; + } + + if((blockDesc & CBD_ODD_MASK) == CBD_ODD) { + oddByte = 1; + } + + /* + * Skip signature sequence if this was a 2nd level comcrypted block + */ + sigSeq = cpriv->sigSeqEnable && !level2; + + for(tokenDex=0; tokenDexkey, cpriv->keybytes, + (cbuf->nybbleDex)++); + + if(match) { + codeByte = *byteCodePtr++; + + if(sigSeq) { + codeByte ^= (unsigned char)(cbuf->sigArray[tokenDex]); + } + + /* + * dynamically process the queue for match - 8 bits + * of ciphercode, 16 bits of plaintext + */ + codeWord = cbufq[codeByte]; + above = (cbuf->f1 * codeByte * (16 + nibble)) >> 9; + +#if SKIP_NIBBLE_ON_QUEUE_0 + if(codeByte == 0) { + /* + * Special case for top of queue optimization during + * comcrypt + */ + nibble = cbuf->nybbleDex - 1; + } +#endif /*SKIP_NIBBLE_ON_QUEUE_0*/ + + /* + * queue[above..codeByte] move one element towards end + * queue[above] = this codeWord + */ + len = (int)codeByte - (int)above; + if(len > QUEUE_MEMMOVE_THRESH) { + src = &cbufq[above]; + dst = src + 1; + len *= sizeof(queueElt); + memmove(dst, src, len); + } + else { + for(j = codeByte; j > above; j--) { + cbufq[j] = cbufq[j-1]; + } + } + cbufq[above] = codeWord; + } + else { + /* + * !match, 16 bits of code + */ + deserializeShort(codeWord, longCodePtr); + if(sigSeq) { + codeWord ^= cbuf->sigArray[tokenDex]; + } + + if(oddByte && (tokenDex == (numTokenBits - 1))) { + lastWord = 1; + above = 0; +#if SKIP_NIBBLE_ON_QUEUE_0 + nibble = cbuf->nybbleDex - 1; +#endif /*SKIP_NIBBLE_ON_QUEUE_0*/ + } + else { + longCodePtr += 2; + + /* + * dynamically process the queue for unmatch; skip if this + * is an oddByte codeword. + * queue[above...QLEN-1] move one element toward end + * queue[above] = new codeWord + */ + above = ABOVE(cbuf->f2) + nibble; + len = QLEN - 1 - (int)above; + if(len > QUEUE_MEMMOVE_THRESH) { + src = &cbufq[above]; + dst = src + 1; + len *= sizeof(queueElt); + memmove(dst, src, len); + } + else { + for(j=QLEN-1; j > above; j--) { + cbufq[j] = cbufq[j-1]; + } + } + cbufq[above] = codeWord; + } + } + + if(sigSeq) { + /* + * Advance signature sequence state machine. + */ + nextSigWord(cbuf, tokenDex+1, match, (above + nibble)); + } + + /* + * cook up a byte or two of plainText from code word and invmap[] + */ + if(ptextLen < 1) { + ddprintf(("decryptBlock: ptext overflow (1)\n")); + return DCB_OUTBUFFER_TOO_SMALL; + } + *plainText++ = cpriv->invmap[(codeWord >> 8) & 0xff]; + ptextLen--; + if(lastWord) { + /* + * end of oddByte block. + */ + tokenDex++; // for sigArray maintenance + break; // out of main loop + } + else { + if(ptextLen < 1) { + ddprintf(("decryptBlock: ptext overflow (2)\n")); + return DCB_OUTBUFFER_TOO_SMALL; + } + *plainText++ = cpriv->invmap[(codeWord) & 0xff]; + ptextLen--; + } + } + + /* + * Prime sigArray state machine for next block. + */ + if(sigSeq) { + cbuf->sigArray[0] = cbuf->sigArray[tokenDex]; + } + *plainTextLen = *plainTextLen - ptextLen; + return DCB_SUCCESS; +} + +comcryptReturn deComcryptData( + comcryptObj cobj, + unsigned char *cipherText, + unsigned cipherTextLen, + unsigned char *plainText, + unsigned *plainTextLen, // IN/OUT + comcryptEos endOfStream) // CCE_END_OF_STREAM, etc. + +{ + comcryptPriv *cpriv = (comcryptPriv *)cobj; + unsigned char *outorigin = plainText; + unsigned ptextLen = *plainTextLen; + unsigned thisPtext; // per block + unsigned blockSize; + dcbReturn drtn; + unsigned ctextUsed; + + /* + * Snag version from ciphertext, or as much as we can get + */ + while((cpriv->versionBytes < VERSION_BYTES) && cipherTextLen) { + cpriv->version <<= 8; + cpriv->version |= *cipherText; + cpriv->versionBytes++; + cipherText++; + cipherTextLen--; + } + + /* + * Then skip over the remainder of the header (currently spares) + */ + if((cpriv->spareBytes < SPARE_BYTES) && cipherTextLen) { + unsigned toSkip = SPARE_BYTES - cpriv->spareBytes; + + if(toSkip > cipherTextLen) { + toSkip = cipherTextLen; + } + cpriv->spareBytes += toSkip; + cipherText += toSkip; + cipherTextLen -= toSkip; + } + + if(cipherTextLen == 0) { + *plainTextLen = 0; + return CCR_SUCCESS; + } + + if(cpriv->version != VERSION_3_Dec_97) { + ddprintf(("Incompatible version.\n")); + return CCR_BAD_CIPHERTEXT; + } + + while(cipherTextLen != 0) { + + /* + * Main loop. First deal with possible existing partial block. + */ + if(cpriv->cbuf.codeBufLength != 0) { + unsigned toCopy = + cpriv->cbuf.codeBufSize - cpriv->cbuf.codeBufLength; + unsigned origBufSize = cpriv->cbuf.codeBufLength; + + if(toCopy > cipherTextLen) { + toCopy = cipherTextLen; + } + memmove(cpriv->cbuf.codeBuf + cpriv->cbuf.codeBufLength, + cipherText, toCopy); + cpriv->cbuf.codeBufLength += toCopy; + + thisPtext = ptextLen; + drtn = deComcryptBlock(cpriv, + &cpriv->cbuf, + cpriv->cbuf.codeBuf, + cpriv->cbuf.codeBufLength, + plainText, + &thisPtext, + endOfStream, + &blockSize); + switch(drtn) { + case DCB_SHORT: + /* + * Incomplete block in codeBuf + */ + if(endOfStream == CCE_END_OF_STREAM) { + /* + * Caller thinks this is the end, but we need more + */ + ddprintf(("deComcryptData(): CCE_END_OF_STREAM, " + "not end of block\n")); + return CCR_BAD_CIPHERTEXT; + } + cipherTextLen -= toCopy; + if(cipherTextLen != 0) { + /* + * i.e., codeBuf overflow - could be s/w error? Do + * we need a bigger buffer? + */ + ddprintf(("deComcryptData: full codeBuf, incomplete " + "block\n")); + return CCR_BAD_CIPHERTEXT; + } + else { + /* + * OK, stash it and try again + */ + scprintf(("====incomplete codeBuf, codeBufLength %d, " + "cipherTextLen %d\n", + cpriv->cbuf.codeBufLength, toCopy)); + break; // out of main loop (after this switch) + } + + case DCB_OUTBUFFER_TOO_SMALL: + ddprintf(("codeBuf decomcrypt error short buf\n")); + return CCR_OUTBUFFER_TOO_SMALL; + + case DCB_PARSE_ERROR: + default: + ddprintf(("codeBuf decomcrypt error (%d)\n", drtn)); + return CCR_BAD_CIPHERTEXT; + + case DCB_SUCCESS: + /* + * ctextUsed is how much of caller's ciphertext we used + * in this buffered block + */ + ctextUsed = blockSize - origBufSize; + scprintf(("====decrypted block in codeBuf, blockSize %d, " + "ctextUsed %d, thisPtext %d\n", + blockSize, ctextUsed, thisPtext)); + cipherText += ctextUsed; + cipherTextLen -= ctextUsed; + plainText += thisPtext; + ptextLen -= thisPtext; + cpriv->cbuf.codeBufLength = 0; + break; + } + + /* + * We might have used up all of caller's cipherText processing + * codeBuf... + */ + if(cipherTextLen == 0) { + break; // out of main loop + } + + } /* buffered ciphertext in codeBuf */ + + /* + * Snarf ciphertext, one block at a time. + */ + + thisPtext = ptextLen; + drtn = deComcryptBlock(cpriv, + &cpriv->cbuf, + cipherText, + cipherTextLen, + plainText, + &thisPtext, + endOfStream, + &blockSize); + switch(drtn) { + case DCB_SHORT: + /* + * Incomplete block + */ + if(endOfStream == CCE_END_OF_STREAM) { + ddprintf(("deComcryptData(): CCE_END_OF_STREAM, not end of " + "block (2)\n")); + return CCR_BAD_CIPHERTEXT; + } + if(cipherTextLen > + (cpriv->cbuf.codeBufSize - cpriv->cbuf.codeBufLength)) { + ddprintf(("deComcryptData(): codeBuf overflow!\n")); + return CCR_BAD_CIPHERTEXT; + } + memmove(cpriv->cbuf.codeBuf + cpriv->cbuf.codeBufLength, + cipherText, cipherTextLen); + cpriv->cbuf.codeBufLength += cipherTextLen; + cipherTextLen = 0; + scprintf(("====Incomplete block, cipherTextLen %d " + "codeBufLength %d\n", cipherTextLen, + cpriv->cbuf.codeBufLength)); + break; // actually out of main loop + + case DCB_PARSE_ERROR: + case DCB_OUTBUFFER_TOO_SMALL: + default: + return CCR_BAD_CIPHERTEXT; + + case DCB_SUCCESS: + if(ptextLen < thisPtext) { + /* + * Software error + */ + ddprintf(("deComcryptData: undetected ptext " + "overflow (2)\n")); + return CCR_BAD_CIPHERTEXT; + } + plainText += thisPtext; + ptextLen -= thisPtext; + cipherText += blockSize; + cipherTextLen -= blockSize; + scprintf(("====decrypted one block, blockSize %d " + "thisPtext %d\n", blockSize, thisPtext)); + break; + } + } /* main loop */ + + *plainTextLen = plainText - outorigin; + return CCR_SUCCESS; +} diff --git a/libsecurity_comcryption/lib/comcryption.h b/libsecurity_comcryption/lib/comcryption.h new file mode 100644 index 00000000..18dd6465 --- /dev/null +++ b/libsecurity_comcryption/lib/comcryption.h @@ -0,0 +1,169 @@ +/* + 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: + +*/ +#ifndef _COMCRYPTION_H_ +#define _COMCRYPTION_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Return values. + */ +typedef enum { + CCR_SUCCESS = 0, // normal result + CCR_OUTBUFFER_TOO_SMALL, // caller needs to alloc more out buffer + CCR_MEMORY_ERROR, // internal error + CCR_WRONG_VERSION, // compatibility error + CCR_BAD_CIPHERTEXT, // can't decrypt ciphertext stream + CCR_INTERNAL // internal library error +} comcryptReturn; + +/* + * Used to specify optimization in ComcryptInit(). May be ignored in + * early implementation. + */ +typedef enum { + CCO_DEFAULT, // let the low-level code decide + CCO_SIZE, // optimize for max compression + CCO_SECURITY, // optimize for max crypto security + CCO_TIME, // optimize for minimum runtime; implies no + // second-level comcryption; security not + // compromised + CCO_TIME_SIZE, // minimum runtime with second-level + // comcryption enabled; implies loss of + // security + CCO_ASCII, // optimize for max compression for ASCII + // plaintext + CCO_OTHER // TBD +} comcryptOptimize; + +/* + * Used to specify operation type. + */ +typedef enum { + CCOP_COMCRYPT, + CCOP_DECOMCRYPT +} comcryptOp; + +/* + * Used to specify End of stream. + */ +typedef enum { + CCE_MORE_TO_COME, // more ops to follow + CCE_END_OF_STREAM // end of stream, close output strem +} comcryptEos; + +/* + * Maximum key length in bytes. + */ +#define COMCRYPT_MAX_KEYLENGTH 64 + +/* + * Clients can *optionally* register external memory alloc/free functions here. + */ +typedef void *(comMallocExternFcn)(unsigned size); +typedef void (comFreeExternFcn)(void *data); +void comMallocRegister(comMallocExternFcn *mallocExtern, + comFreeExternFcn *freeExtern); + +/* + * Opaque data type for ComCryptData() and DeComCryptData() + */ +typedef void *comcryptObj; + +/* + * Call once at startup. The resulting comcryptObj can be reused multiple + * times. + */ +comcryptObj comcryptAlloc(); + +/* + * Use this before starting every stream process + */ +comcryptReturn comcryptInit( + comcryptObj cobj, + const unsigned char *key, + unsigned keyLen, + comcryptOptimize optimize); // CCO_SIZE, etc. + +/* + * Free a comcryptObj object obtained via comcryptAlloc() + */ +void comcryptObjFree(comcryptObj cobj); + +/* + * Return the maximum input buffer size allowed for for specified + * output buffer size. Note that for both comcrypt and decomcrypt, + * to cover the worst case, the output buffer always has to be + * larger that the input buffer. + */ +unsigned comcryptMaxInBufSize(comcryptObj cobj, + unsigned outBufSize, + comcryptOp op); // CCOP_COMCRYPT, etc. + +/* + * Return the maximum output buffer size for specified input buffer size. + * Output buffer size will always be larger than input buffer size. + */ +unsigned comcryptMaxOutBufSize(comcryptObj cobj, + unsigned inBufSize, + comcryptOp op, // CCOP_COMCRYPT, etc. + char final); // nonzero for last op + // only used for CCOP_DECOMCRYPT + +/* + * the one-function-fits-all comcrypt routine - + * call it multiple times for one ComcryptObj if + * you want, or just once to do a whole stream + * in one shot. + * + * NOTE: in the current implementation, the endOfStream is not used; + * no "final" call is necessary on comcryption. + */ +comcryptReturn comcryptData( + comcryptObj cobj, + unsigned char *plainText, + unsigned plainTextLen, + unsigned char *cipherText, // malloc'd by caller + unsigned *cipherTextLen, // IN/OUT + comcryptEos endOfStream); // CCE_END_OF_STREAM, etc. + +/* + * decomcrypt routine - call it multiple times for + * one comcryptObj, or just once to do a whole stream + * in one shot. Boundaries of ciphertext segments - + * across calls to this function - are arbitrary. + * + * NOTE: in the current implementation, the final call to this (when + * endOfStrem == CCE_END_OF_STREAM) must contain a nonzero amount of + * ciphertext. + */ +comcryptReturn deComcryptData( + comcryptObj cobj, + unsigned char *cipherText, + unsigned cipherTextLen, + unsigned char *plainText, + unsigned *plainTextLen, // IN/OUT + comcryptEos endOfStream); // CCE_END_OF_STREAM, etc. + +#ifdef __cplusplus +} +#endif + +#endif /*_COMCRYPTION_H_*/ diff --git a/libsecurity_comcryption/libsecurity_comcryption.xcodeproj/project.pbxproj b/libsecurity_comcryption/libsecurity_comcryption.xcodeproj/project.pbxproj new file mode 100644 index 00000000..142f4c3e --- /dev/null +++ b/libsecurity_comcryption/libsecurity_comcryption.xcodeproj/project.pbxproj @@ -0,0 +1,200 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 7264323500A8AD987F000001 /* comcryption.c in Sources */ = {isa = PBXBuildFile; fileRef = 7264322D00A8AD987F000001 /* comcryption.c */; }; + 7264323600A8AD987F000001 /* comcryptPriv.c in Sources */ = {isa = PBXBuildFile; fileRef = 7264322E00A8AD987F000001 /* comcryptPriv.c */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 182BB1F2146EF7C1000BF1F3 /* base.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = base.xcconfig; sourceTree = ""; }; + 182BB1F3146EF7C1000BF1F3 /* debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = debug.xcconfig; sourceTree = ""; }; + 182BB1F4146EF7C1000BF1F3 /* lib.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = lib.xcconfig; sourceTree = ""; }; + 182BB1F5146EF7C1000BF1F3 /* release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = release.xcconfig; sourceTree = ""; }; + 7264321400A8AD0A7F000001 /* libsecurity_comcryption.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libsecurity_comcryption.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 7264322D00A8AD987F000001 /* comcryption.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = comcryption.c; sourceTree = ""; }; + 7264322E00A8AD987F000001 /* comcryptPriv.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = comcryptPriv.c; sourceTree = ""; }; + 7264322F00A8AD987F000001 /* comcryption.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = comcryption.h; sourceTree = ""; }; + 7264323000A8AD987F000001 /* comcryptPriv.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = comcryptPriv.h; sourceTree = ""; }; + 7264323100A8AD987F000001 /* comDebug.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = comDebug.h; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 7264322000A8AD0A7F000001 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 0FD07C9EFE8A174411CD283A = { + isa = PBXGroup; + children = ( + 7264321200A8ACCB7F000001 /* lib */, + 182BB1F1146EF7C1000BF1F3 /* config */, + 31DBE9B3FEEEE8F611CD283A /* Products */, + ); + sourceTree = ""; + }; + 182BB1F1146EF7C1000BF1F3 /* config */ = { + isa = PBXGroup; + children = ( + 182BB1F2146EF7C1000BF1F3 /* base.xcconfig */, + 182BB1F3146EF7C1000BF1F3 /* debug.xcconfig */, + 182BB1F4146EF7C1000BF1F3 /* lib.xcconfig */, + 182BB1F5146EF7C1000BF1F3 /* release.xcconfig */, + ); + name = config; + path = ../config; + sourceTree = ""; + }; + 31DBE9B3FEEEE8F611CD283A /* Products */ = { + isa = PBXGroup; + children = ( + 7264321400A8AD0A7F000001 /* libsecurity_comcryption.a */, + ); + name = Products; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 7264321200A8ACCB7F000001 /* lib */ = { + isa = PBXGroup; + children = ( + 7264322D00A8AD987F000001 /* comcryption.c */, + 7264322F00A8AD987F000001 /* comcryption.h */, + 7264322E00A8AD987F000001 /* comcryptPriv.c */, + 7264323000A8AD987F000001 /* comcryptPriv.h */, + 7264323100A8AD987F000001 /* comDebug.h */, + ); + path = lib; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 7264321E00A8AD0A7F000001 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 7264321D00A8AD0A7F000001 /* libsecurity_comcryption */ = { + isa = PBXNativeTarget; + buildConfigurationList = C27AD3200987FCDE001272E0 /* Build configuration list for PBXNativeTarget "libsecurity_comcryption" */; + buildPhases = ( + 7264321E00A8AD0A7F000001 /* Headers */, + 7264321F00A8AD0A7F000001 /* Sources */, + 7264322000A8AD0A7F000001 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = libsecurity_comcryption; + productInstallPath = /usr/local/lib; + productName = ComCryption; + productReference = 7264321400A8AD0A7F000001 /* libsecurity_comcryption.a */; + productType = "com.apple.product-type.library.static"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 0FD07C9DFE8A174411CD283A /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0420; + }; + buildConfigurationList = C27AD3240987FCDE001272E0 /* Build configuration list for PBXProject "libsecurity_comcryption" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 1; + knownRegions = ( + en, + ); + mainGroup = 0FD07C9EFE8A174411CD283A; + productRefGroup = 0FD07C9EFE8A174411CD283A; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 7264321D00A8AD0A7F000001 /* libsecurity_comcryption */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXSourcesBuildPhase section */ + 7264321F00A8AD0A7F000001 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 7264323500A8AD987F000001 /* comcryption.c in Sources */, + 7264323600A8AD987F000001 /* comcryptPriv.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + C27AD3210987FCDE001272E0 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 182BB1F3146EF7C1000BF1F3 /* debug.xcconfig */; + buildSettings = { + }; + name = Debug; + }; + C27AD3230987FCDE001272E0 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 182BB1F5146EF7C1000BF1F3 /* release.xcconfig */; + buildSettings = { + }; + name = Release; + }; + C27AD3250987FCDE001272E0 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 182BB1F4146EF7C1000BF1F3 /* lib.xcconfig */; + buildSettings = { + }; + name = Debug; + }; + C27AD3270987FCDE001272E0 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 182BB1F4146EF7C1000BF1F3 /* lib.xcconfig */; + buildSettings = { + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + C27AD3200987FCDE001272E0 /* Build configuration list for PBXNativeTarget "libsecurity_comcryption" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C27AD3210987FCDE001272E0 /* Debug */, + C27AD3230987FCDE001272E0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C27AD3240987FCDE001272E0 /* Build configuration list for PBXProject "libsecurity_comcryption" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C27AD3250987FCDE001272E0 /* Debug */, + C27AD3270987FCDE001272E0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 0FD07C9DFE8A174411CD283A /* Project object */; +} diff --git a/libsecurity_cryptkit/Info-security_cryptkit.plist b/libsecurity_cryptkit/Info-security_cryptkit.plist new file mode 100644 index 00000000..0c67376e --- /dev/null +++ b/libsecurity_cryptkit/Info-security_cryptkit.plist @@ -0,0 +1,5 @@ + + + + + diff --git a/libsecurity_cryptkit/ckutils/Makefile b/libsecurity_cryptkit/ckutils/Makefile new file mode 100644 index 00000000..e0a50cb5 --- /dev/null +++ b/libsecurity_cryptkit/ckutils/Makefile @@ -0,0 +1,21 @@ +# +# Top-level Makefile for ckutils. Allows build or clean +# of all directories in one swoop. +# +SHELL := /bin/zsh + +SUBDIRS= atomTime badsig blobtest cfileTest giantAsmBench giantBench giantDvt + +first: + @foreach i in $(SUBDIRS); \ + echo "=== Making $$i ==="; \ + cd $$i; \ + make || exit; \ + cd ..; \ + end + +clean: + @foreach i in $(SUBDIRS); \ + echo "=== Cleaning $$i ==="; \ + (cd $$i; make clean;) \ + end diff --git a/libsecurity_cryptkit/ckutils/Makefile.common b/libsecurity_cryptkit/ckutils/Makefile.common new file mode 100644 index 00000000..3f83691e --- /dev/null +++ b/libsecurity_cryptkit/ckutils/Makefile.common @@ -0,0 +1,88 @@ +# +# Common makefile fragment for ckutils. +# This is -included from project-specific Makefiles, assumed +# to be one directory down from this file. +# +# Standard binary locations. Assume LOCAL_BUILD_DIR in environment. +# + +LOCAL_BUILD ?= $(shell echo $(LOCAL_BUILD_DIR)) +ifeq "" "$(LOCAL_BUILD)" + LOCAL_BUILD = . +endif + +CRYPTKIT_SRC= ../../lib + +OFILES= $(CSOURCE:%.c=%.o) $(CPPSOURCE:%.cpp=%.o) +ALL_OFILES= $(OFILES) $(CRYPTKIT_LIB_BIN) + +# +# override with recursive make for e.g. debug build +# +VARIANT_SUFFIX= + +# +# override this with a recursive make to test minimal signature build +# +CRYPTKIT_CONFIG=-DCK_STANDALONE_BUILD + +# +# override with recursive make to link against other binary +# +CRYPTKIT_BINARY=CryptKit + +# +# Assume final load with cc, not ld +# +STD_LIBS= -l$(CRYPTKIT_BINARY)$(VARIANT_SUFFIX) +STD_LIBPATH=-L$(LOCAL_BUILD) +ALL_LIBS= $(STD_LIBS) $(PROJ_LIBS) +ALL_LIBPATHS= $(STD_LIBPATH) $(PROJ_LIBPATH) + +# +# Override this from the make command line to add e.g. -lMallocDebug +# +CMDLINE_LDFLAGS= + +STD_FRAMEWORKS= +STD_FRAME_PATH= -F$(LOCAL_BUILD) -F/usr/local/SecurityPieces/Frameworks + +# +ALL_LDFLAGS= $(CMDLINE_LDFLAGS) $(ALL_LIBS) $(ALL_LIBPATHS) $(STD_FRAME_PATH) $(PROJ_LDFLAGS) + +CC= /usr/bin/gcc + +ALL_FRAMEWORKS= $(STD_FRAMEWORKS) $(PROJ_FRAMEWORKS) + +# CryptKit headers accessed via +STD_INCLUDES= -I$(CRYPTKIT_SRC) -I.. +ALL_INCLUDES= $(STD_INCLUDES) $(PROJ_INCLUDES) +CINCLUDES= $(ALL_INCLUDES) + +WFLAGS= -Wno-four-char-constants -Wall -Werror -Wno-format -Wno-deprecated-declarations +STD_CFLAGS= -g $(VERBOSE) $(CRYPTKIT_CONFIG) + +ALL_CFLAGS= $(CINCLUDES) $(STD_CFLAGS) $(PROJ_CFLAGS) $(WFLAGS) $(STD_FRAME_PATH) + +BUILT_TARGET= $(EXECUTABLE) + +first: $(BUILT_TARGET) + +debug: + echo making debug + make "VARIANT_SUFFIX=_debug" + +smallsig: + make "CRYPTKIT_CONFIG=-DCK_MINIMUM_SIG_BUILD" "CRYPTKIT_BINARY=CryptKitSignature" + +clean: + rm -f $(OFILES) $(EXECUTABLE) $(OTHER_TO_CLEAN) + +$(BUILT_TARGET): $(ALL_OFILES) $(PROJ_DEPENDS) + cc -o $(BUILT_TARGET) $(ALL_OFILES) $(ALL_FRAMEWORKS) $(ALL_LDFLAGS) + +.c.o: + $(CC) $(ALL_CFLAGS) -c -o $*.o $< + +.cpp.o: + $(CC) $(ALL_CFLAGS) -c -o $*.o $< diff --git a/libsecurity_cryptkit/ckutils/atomTime/Makefile b/libsecurity_cryptkit/ckutils/atomTime/Makefile new file mode 100644 index 00000000..cef23232 --- /dev/null +++ b/libsecurity_cryptkit/ckutils/atomTime/Makefile @@ -0,0 +1,53 @@ +# name of executable to build +EXECUTABLE=atomTime +# C source (.c extension) +CSOURCE= atomTime.c + +SHELL := /bin/zsh + +# 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 + +# +# 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=-O3 + +# +# Optional link flags (using cc, not ld) +# +PROJ_LDFLAGS= + +# +# Optional dependencies +# +PROJ_DEPENDS= + +include ../Makefile.common diff --git a/libsecurity_cryptkit/ckutils/atomTime/atomTime.c b/libsecurity_cryptkit/ckutils/atomTime/atomTime.c new file mode 100644 index 00000000..d4eec127 --- /dev/null +++ b/libsecurity_cryptkit/ckutils/atomTime/atomTime.c @@ -0,0 +1,662 @@ +/* + * atomTime.c - measure performance of mulg, gsquare, feemod, + * gshift{left,right}, elliptic, ellMulProj + */ + +#include "ckconfig.h" +#include "ckutilsPlatform.h" +#include "CryptKitSA.h" +#include "ckutilities.h" /* needs private headers */ +#include "curveParams.h" /* ditto */ +#include "falloc.h" /* ditto */ +#include "elliptic.h" +#include "ellipticProj.h" +#include +#include +#include + +/* default loops for "fast" and "slow" ops respecitively */ +#define LOOPS_DEF_FAST 10000 +#define LOOPS_DEF_SLOW 100 + +#define NUM_BORROW 100 + +/* individual enables - normally all on, disable to zero in on one test */ +#define MULG_ENABLE 1 +#define GSQUARE_ENABLE 1 +#define FEEMOD_ENABLE 1 +#define BORROW_ENABLE 1 +#define SHIFT_ENABLE 1 +#define BINVAUX_ENABLE 1 +#define MAKE_RECIP_ENABLE 1 +#define MODGRECIP_ENABLE 1 +#define KEYGEN_ENABLE 1 +#define ELLIPTIC_ENABLE 1 +#define ELL_SIMPLE_ENABLE 1 + +static void usage(char **argv) +{ + printf("Usage: %s [l=loops_fast] [L=loops_slow] [q(uick)] [D=depth]\n", argv[0]); + exit(1); +} + +/* + * Fill numGiants with random data of length bits. + */ +static void genRandGiants(giant *giants, + unsigned numGiants, + unsigned bits, + feeRand rand) +{ + int i; + giant g; + unsigned char *rdata; + unsigned bytes = (bits + 7) / 8; + giantDigit mask = 0; + unsigned giantMsd = 0; // index of MSD + unsigned log2BitsPerDigit; + unsigned bitsPerDigit; + + /* just to satisfy compiler - make sure it's always called */ + if(giants == NULL) { + return; + } + + log2BitsPerDigit = GIANT_LOG2_BITS_PER_DIGIT; + bitsPerDigit = GIANT_BITS_PER_DIGIT; + + if((bits & 7) != 0) { + /* + * deserializeGiant() has a resolution of one byte. We + * need more resolution - that is, we'll be creating + * giants a little larger than we need, and we'll mask off + * some bits in the giants' m.s. digit. + * This assumes that data fills the giantDigits such + * that if bytes mod GIANT_BYTES_PER_DIGIT != 0, the + * empty byte(s) in the MSD are in the m.s. byte(s). + */ + giantMsd = bits >> log2BitsPerDigit; + mask = (1 << (bits & (bitsPerDigit - 1))) - 1; + } + rdata = fmalloc(bytes); + for(i=0; in[giantMsd] &= mask; + + /* + * We've zeroed out some bits; we might have to + * adjust the sign of the giant as well. Note that + * deserializeGiant always yields positive + * giants.... + */ + for(j=(g->sign - 1); j!=0; j--) { + if(g->n[j] == 0) { + (g->sign)--; + } + else { + break; + } + } + } + } + ffree(rdata); + return; +} + +#if CRYPTKIT_ELL_PROJ_ENABLE +/* + * Assumes the presence of numEllPoints items in *points, and that the + * x coordinate in each point is init'd to a random giant. Uses the x + * coords as seeds to make normalized points of the entire *points array. + */ +static void makePoints(pointProjStruct *points, + unsigned numEllPoints, + curveParams *cp) +{ + int i; + giant seed = newGiant(cp->maxDigits); + + for(i=0; i maxLoops) { + maxLoops = loopsSlow; + } + + /* + * Alloc array of giants big enough for squaring at the largest + * key size, enough of them for 'loops' mulgs + */ + cp = curveParamsForDepth(FEE_DEPTH_LARGEST); + numGiants = maxLoops * 2; // 2 giants per loop + if(loopsSlow > (maxLoops / 4)) { + /* findPointProj needs 4 giants per loop */ + numGiants *= 4; + } + #if CRYPTKIT_ELL_PROJ_ENABLE + numEllGiants = loopsSlow * 2; + numEllPoints = loopsSlow * 2; + #endif + giants = fmalloc(numGiants * sizeof(giant)); + if(giants == NULL) { + printf("malloc failure\n"); + exit(1); + } + for(i=0; imaxDigits); + if(giants[i] == NULL) { + printf("malloc failure\n"); + exit(1); + } + } + freeCurveParams(cp); + + #if CRYPTKIT_ELL_PROJ_ENABLE + /* + * Projective points - two per ellLoop. The giants come from + * giants[]. We reserve an extra giant per point. + * We're assuming that numEllPoints < (4 * numGiants). + */ + points = fmalloc(numEllPoints * sizeof(pointProjStruct)); + if(points == NULL) { + printf("malloc failure\n"); + exit(1); + } + j=0; + for(i=0; icurveType) { + case FCT_Montgomery: + curveType = "FCT_Montgomery"; + break; + case FCT_Weierstrass: + curveType = "FCT_Weierstrass"; + break; + case FCT_General: + curveType = "FCT_General"; + break; + default: + printf("***Unknown curveType!\n"); + exit(1); + } + + switch(cp->primeType) { + case FPT_General: + printf("depth=%d; FPT_General, %s; keysize=%d;\n", + depth, curveType, bitlen(cp->basePrime)); + break; + case FPT_Mersenne: + printf("depth=%d; FPT_Mersenne, %s; q=%d\n", + depth, curveType, cp->q); + break; + default: + printf("depth=%d; FPT_FEE, %s; q=%d k=%d\n", + depth, curveType, cp->q, cp->k); + break; + } + basePrimeLen = bitlen(cp->basePrime); + + /* + * mulg test + * bitlen(giant) <= bitlen(basePrime); + * giants[n+1] *= giants[n] + */ + #if MULG_ENABLE + genRandGiants(giants, numGiants, basePrimeLen, rand); + PLAT_GET_TIME(startTime); + for(i=0; imaxDigits); + } + for(j=0; jbasePrime, giants[i]); + } + PLAT_GET_TIME(endTime); + elapsed = PLAT_GET_US(startTime, endTime); + printf(" binvaux: %12.2f us per op\n", + elapsed / loopsSlow); + #endif /* BINVAUX_ENABLE */ + + /* + * make_recip test + * bitlen(giant) <= bitlen(basePrime); + * make_recip(giants[n], giants[n+1] + */ + #if MAKE_RECIP_ENABLE + genRandGiants(giants, numGiants, basePrimeLen, rand); + PLAT_GET_TIME(startTime); + for(i=0; imaxDigits); + recip = borrowGiant(cp->maxDigits); + genRandGiants(&modGiant, 1, basePrimeLen, rand); + make_recip(modGiant, recip); + + PLAT_GET_TIME(startTime); + for(i=0; imaxDigits); + PLAT_GET_TIME(startTime); + for(i=0; in[0] = 1; + z->sign = 1; + elliptic(giants[i], z, giants[i+1], cp); + } + PLAT_GET_TIME(endTime); + elapsed = PLAT_GET_US(startTime, endTime); + printf(" elliptic: %12.2f us per op\n", + elapsed / (loopsSlow / 2)); + #endif /* ELLIPTIC_ENABLE*/ + + /* + * elliptic_simple test + * bitlen(giant) <= bitlen(basePrime); + * giants[n] *= giants[n+1] (elliptic mult) + */ + #if ELL_SIMPLE_ENABLE + genRandGiants(giants, numGiants, basePrimeLen, rand); + PLAT_GET_TIME(startTime); + for(i=0; icurveType != FCT_Weierstrass) { + goto loopEnd; + } + + #if CRYPTKIT_ELL_PROJ_ENABLE + /* + * ellMulProj test + * bitlen(giant) <= bitlen(basePrime); + * point[n+1] = point[n] * giants[4n+3] + * + * note we're cooking up way more giants than we have to; + * we really only need the x's and k's. But what the heck. + */ + genRandGiants(giants, 4 * numEllPoints, basePrimeLen, rand); + makePoints(points, numEllPoints, cp); + PLAT_GET_TIME(startTime); + for(i=0; i +#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/libsecurity_cryptkit/ckutils/blobtest/Makefile new file mode 100644 index 00000000..c4c789ad --- /dev/null +++ b/libsecurity_cryptkit/ckutils/blobtest/Makefile @@ -0,0 +1,51 @@ +# name of executable to build +EXECUTABLE=blobtest +# C source (.c extension) +CSOURCE= blobtest.c + +# 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= + +# +# 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= + +# +# Optional link flags (using cc, not ld) +# +PROJ_LDFLAGS= + +# +# Optional dependencies +# +PROJ_DEPENDS= + +include ../Makefile.common diff --git a/libsecurity_cryptkit/ckutils/blobtest/blobtest.c b/libsecurity_cryptkit/ckutils/blobtest/blobtest.c new file mode 100644 index 00000000..c76c0a47 --- /dev/null +++ b/libsecurity_cryptkit/ckutils/blobtest/blobtest.c @@ -0,0 +1,344 @@ +/* Copyright 1998 Apple Computer, Inc. + * + * blobtest.c - test key blob functions + * + * Revision History + * ---------------- + * 23 Mar 1998 Doug Mitchell + * Created. + */ + +#include "Crypt.h" +#include "falloc.h" +#include +#include +#include +#include "ckutilsPlatform.h" + +#define MIN_PASSWD_LENGTH 4 +#define MAX_PASSWD_LENGTH 20 +#define DEPTH_DEFAULT FEE_DEPTH_DEFAULT + +#undef BOOL +#undef YES +#undef NO +#define BOOL int +#define YES 1 +#define NO 0 + +static unsigned char *passwdPool; + +static unsigned doBlobTest(unsigned minPasswdLen, + unsigned maxPasswdLen, + BOOL verbose, + unsigned depth); +static void usage(char **argv); + +int main(int argc, char **argv) +{ + BOOL seedSpec = NO; // YES ==> user specified + unsigned loopNum; + int arg; + char *argp; + + /* + * User-spec'd variables + */ + unsigned minPasswordLen = MIN_PASSWD_LENGTH; + unsigned maxPasswordLen = MAX_PASSWD_LENGTH; + int seed = 0; + unsigned loops = 1; + BOOL quiet = NO; + BOOL verbose = NO; + unsigned depth = DEPTH_DEFAULT; + + #if macintosh + argc = ccommand(&argv); + #endif + for(arg=1; arg +#include +#include + +static unsigned char *dataPool; /* plaintext comes from here */ + +#undef BOOL +#undef YES +#undef NO +#define BOOL int +#define YES 1 +#define NO 0 + +#define LOOPS_DEF 100 +#define MIN_EXP 2 /* for data size 10**exp */ +#define MAX_EXP 3 /* FEED is very slow with ptext larger than this... */ +#define DEPTH_DEFAULT FEE_DEPTH_DEFAULT +#define MIN_OFFSET 0 +#define MAX_OFFSET 99 + +#define PASSWD_LENGTH 10 + +static void usage(char **argv) +{ + printf("usage: %s [options]\n", argv[0]); + printf("Options:\n"); + printf(" l==loops (default=%d)\n", LOOPS_DEF); + printf(" n=minExp (default=%d)\n", MIN_EXP); + printf(" x=maxExp (default=max=%d)\n", MAX_EXP); + printf(" D=depth (default=%d)\n", DEPTH_DEFAULT); + printf(" N=minOffset (default=%d)\n", MIN_OFFSET); + printf(" q(uiet) v(erbose)\n"); + printf(" h(elp) I(ncrementing offset)\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 + (RAND() % (max-min+1))); +} + +/* end of feeLib routines */ + +#define MIN_ASCII ' ' +#define MAX_ASCII '~' + +static void genPasswd(unsigned char *passwd, + unsigned passwdLen, BOOL ascii) +{ + unsigned *ip = (unsigned *)passwd; + unsigned intCount = passwdLen / 4; + int i; + unsigned char *cp; + unsigned residue = passwdLen & 0x3; + char ac; + + if(ascii) { + cp = passwd; + ac = MIN_ASCII; + for(i=0; i MAX_ASCII) { + ac = MIN_ASCII; + } + } + } + else { + for (i=0; i MAX_ASCII) { + ac = MIN_ASCII; + } + } + break; + case DT_Random: + #ifdef __LITTLE_ENDIAN__ + intCount = size >> 2; + ip = (unsigned *)dataPool; + for(i=0; i MAX_OFFSET) { + minOffset = MIN_OFFSET; + } + sizeOffset = minOffset; + break; + case 'x': + maxExp = atoi(&argp[2]); + if(maxExp > MAX_EXP) { + usage(argv); + } + break; + case 's': + seed = atoi(&argp[2]); + seedSpec = YES; + break; + case 'I': + incrOffset = YES; + break; + case 'q': + quiet = YES; + break; + case 'v': + verbose = YES; + break; + case 'h': + default: + usage(argv); + } + } + + if(seedSpec == NO) { + time((unsigned long *)(&seed)); + } + SRAND(seed); + maxSize = dataSizeFromExp(maxExp) + MAX_OFFSET + 8; + dataPool = fmalloc(maxSize); + + printf("Starting cfileTest: loops %d seed %d depth %d\n", + loops, seed, depth); + + for(loop=1; ; loop++) { + + ptext = genData(minExp, maxExp, DT_Random, incrOffset, + minOffset, &ptextLen); + if(!quiet) { + printf("..loop %d plaintext size %d\n", loop, ptextLen); + } + + /* + * Generate a whole bunch of keys + */ + genPasswd(passwd1, PASSWD_LENGTH, NO); // not ascii! + genPasswd(passwd2, PASSWD_LENGTH, NO); + myPrivKey = genPrivKey(passwd1, PASSWD_LENGTH, depth); + theirPrivKey = genPrivKey(passwd2, PASSWD_LENGTH, depth); + myPubKey = genPubKey(myPrivKey); + theirPubKey = genPubKey(theirPrivKey); + + for(encrType=CFE_PublicDES; + encrType<=CFE_FEEDExp; + encrType++) { + + if(verbose) { + printf(" ..%s\n", stringFromEncrType(encrType)); + } + for(doEnc64=0; doEnc64<2; doEnc64++) { + if(verbose) { + printf(" ..doEnc64 %d\n", doEnc64); + } + + if(verbose) { + printf(" ..no sig\n"); + } + doTest(ptext, ptextLen, myPrivKey, myPubKey, + theirPrivKey, theirPubKey, + encrType, doEnc64, SIG_NO, EXPLICIT_NO); + + if(verbose) { + printf(" ..sig, implicit sendPubKey\n"); + } + doTest(ptext, ptextLen, myPrivKey, myPubKey, + theirPrivKey, theirPubKey, + encrType, doEnc64, SIG_YES, EXPLICIT_NO); + + if(verbose) { + printf(" ..sig, explicit sendPubKey\n"); + } + doTest(ptext, ptextLen, myPrivKey, myPubKey, + theirPrivKey, theirPubKey, + encrType, doEnc64, SIG_YES, EXPLICIT_YES); + + if(verbose) { + printf(" ..sig, force error\n"); + } + doTest(ptext, ptextLen, myPrivKey, myPubKey, + theirPrivKey, theirPubKey, + encrType, doEnc64, SIG_YES, EXPLICIT_ERR); + + } /* for doEnc64 */ + } /* for encrType */ + + feePubKeyFree(myPrivKey); + feePubKeyFree(myPubKey); + feePubKeyFree(theirPrivKey); + feePubKeyFree(theirPubKey); + if(loops) { + if(loop == loops) { + break; + } + } + } /* main loop */ + + if(!quiet) { + printf("cfile test complete\n"); + } + return 0; +} diff --git a/libsecurity_cryptkit/ckutils/ckutilsPlatform.h b/libsecurity_cryptkit/ckutils/ckutilsPlatform.h new file mode 100644 index 00000000..66ee7bcb --- /dev/null +++ b/libsecurity_cryptkit/ckutils/ckutilsPlatform.h @@ -0,0 +1,106 @@ +/* + * Platform-dependent stuff for ckutils + */ + +#ifndef _CKU_PLATFORM_H_ +#define _CKU_PLATFORM_H_ + +#include +#include + +/* use this for linux compatibility testing */ +//#define linux 1 +/* end linux test */ + +/* + * Make sure endianness is defined... + */ +#if !defined(__BIG_ENDIAN__) && !defined(__LITTLE_ENDIAN__) + #if macintosh + #define __BIG_ENDIAN__ 1 + #elif defined(i386) || defined(i486) || defined(__i386__) || defined(__i486__) + #define __LITTLE_ENDIAN__ 1 + #else + #error Platform dependent work needed + #endif +#endif /* endian */ + +#ifdef NeXT + #import + #define SRAND(x) srandom(x) + #define RAND() random() +#else NeXT + /* + * Use stdlib only + */ + #define SRAND(x) srand(x) + #define RAND() rand() + #define bcopy(s, d, l) memmove(d, s, l) + #define bzero(s, l) memset(s, 0, l) + #define bcmp(s, d, l) memcmp(s, d, l) +#endif + +#ifdef CK_NT_C_ONLY + +/* + * Standard I/O redirects for WINNT. + */ +#define open(f, b, c) _open(f, b, c) +#define close(f) _close(f) +#define read(f, b, c) _read(f, b, c) +#define write(f, b, c) _write(f, b, c) +#define fstat(f, b) _fstat(f, b) + +#define O_RDONLY _O_RDONLY +#define O_WRONLY _O_WRONLY +#define O_CREAT _O_CREAT +#define O_TRUNC _O_TRUNC + +#endif CK_NT_C_ONLY + +/* + * Platform-dependent timestamp stuff. For now we assume that each platform + * has some kind of struct which maintains a high-resolution clock and + * a function which fills that struct with the current time. + */ +#if macintosh + + #include + + #define PLAT_TIME UnsignedWide + #define PLAT_GET_TIME(pt) Microseconds(&pt) + #define PLAT_GET_US(start,end) (end.lo - start.lo) + +#elif linux + + #include + + #define PLAT_TIME struct timeval + #define PLAT_GET_TIME(pt) gettimeofday(&pt, NULL) + #define PLAT_GET_US(start,end) \ + ( ( ( (end.tv_sec & 0xff) * 1000000) + end.tv_usec) - \ + ( ( (start.tv_sec & 0xff) * 1000000) + start.tv_usec) ) + +#elif NeXT + + #include + + #define PLAT_TIME struct tsval + #define PLAT_GET_TIME(pt) kern_timestamp(&pt) + #define PLAT_GET_US(start,end) (end.low_val - start.low_val) + + +#elif defined(__MACH__) && defined(__APPLE__) + #include + /* time as a double */ + #define PLAT_TIME CFAbsoluteTime + #define PLAT_GET_TIME(pt) pt = CFAbsoluteTimeGetCurrent() + #define PLAT_GET_US(start,end) \ + ((end - start) * 1000000.0) + #define PLAT_GET_NS(start,end) \ + ((end - start) * 1000000000.0) +#else + #error Platform dependent work needed +#endif + +#endif /* _CKU_PLATFORM_H_ */ diff --git a/libsecurity_cryptkit/ckutils/giantAsmBench/Makefile b/libsecurity_cryptkit/ckutils/giantAsmBench/Makefile new file mode 100644 index 00000000..e44b24a0 --- /dev/null +++ b/libsecurity_cryptkit/ckutils/giantAsmBench/Makefile @@ -0,0 +1,51 @@ +# name of executable to build +EXECUTABLE=giantAsmBench +# C source (.c extension) +CSOURCE= giantAsmBench.c + +# 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 + +# +# 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= -Os + +# +# Optional link flags (using cc, not ld) +# +PROJ_LDFLAGS= + +# +# Optional dependencies +# +PROJ_DEPENDS= + +include ../Makefile.common diff --git a/libsecurity_cryptkit/ckutils/giantAsmBench/giantAsmBench.c b/libsecurity_cryptkit/ckutils/giantAsmBench/giantAsmBench.c new file mode 100644 index 00000000..0760c292 --- /dev/null +++ b/libsecurity_cryptkit/ckutils/giantAsmBench/giantAsmBench.c @@ -0,0 +1,215 @@ +/* Copyright (c) 1998 Apple Computer, Inc. All rights reserved. + * + * giantAsmBench.c - Benchmark of platform-specific giantInteger primitives. + * + * Revision History + * ---------------- + * 18 Apr 98 Doug Mitchell at Apple + * Created. + */ + +#include +#include +#include +#include +#include "ckutilsPlatform.h" +#include +#include + +#define LOOPS_DEF 10000 +#define MIN_SIZE_DEF 1 /* mix digits for vectorMultiply test */ +#define MAX_SIZE_DEF 8 /* max digits */ + + +static void usage(char **argv) +{ + printf("usage: %s [options]\n", argv[0]); + printf(" Options:\n"); + printf(" l=loops (default = %d)\n", LOOPS_DEF); + printf(" n=maxDigits (default = %d)\n", MIN_SIZE_DEF); + printf(" x=maxDigits (default = %d)\n", MAX_SIZE_DEF); + printf(" s=seed\n"); + printf(" h(elp)\n"); + exit(1); +} + +/* + * Fill buffer with random data. Assumes giantDigits is native int size. + */ +static void randDigits(unsigned numDigits, + giantDigit *digits) +{ + int i; + + for(i=0; i +#include "ckutilsPlatform.h" +#include +#include + +#define LOOPS_DEF 100 +#define MIN_SIZE_DEF 4 /* min giant size in bytes */ +#define MAX_SIZE_DEF 32 /* max in bytes */ +#define LOOP_NOTIFY 100 + + +static void usage(char **argv) +{ + printf("usage: %s [options]\n", argv[0]); + printf(" Options:\n"); + printf(" l=loops (default = %d)\n", LOOPS_DEF); + printf(" n=maxBytes (default = %d\n", MIN_SIZE_DEF); + printf(" x=maxBytes (default = %d\n", MAX_SIZE_DEF); + printf(" o (use old 16-bit CryptKit\n"); + printf(" s=seed\n"); + printf(" h(elp)\n"); + exit(1); +} + +/* + * Fill buffer with random data. + */ +static void fillData(unsigned bufSize, + unsigned char *buf) +{ + unsigned *ip; + unsigned intCount; + unsigned residue; + unsigned char *cp; + int i; + + intCount = bufSize >> 2; + ip = (unsigned *)buf; + for(i=0; isign = -g->sign; + } + + /* avoid zero data - too many pitfalls with mod and div */ + while(isZero(g)) { + g->sign = 1; + g->n[0] = RAND(); + } +} + +/* + * Init giant arrays with random data. + */ +static void initRandGiants(unsigned numBytes, + unsigned char *buf, + unsigned numGiants, + giant *g1, + giant *g2) +{ + int i; + + for(i=0; i +#include "ckutilsPlatform.h" +#include +#include + +#define LOOPS_DEF 100 +#define MAX_SIZE_DEF 32 +#define LOOP_NOTIFY 100 + +/* quick test to show modg(1,g) broken */ +#define MODG1_TEST_ENABLE 1 + +static void usage(char **argv) +{ + printf("usage: %s [options]\n", argv[0]); + printf(" Options:\n"); + printf(" l=loops (default = %d)\n", LOOPS_DEF); + printf(" x=maxBytes (default = %d)\n", MAX_SIZE_DEF); + printf(" s=seed\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 + (RAND() % (max-min+1))); +} + +/* + * Fill buffer with random data, random size from 1 to maxSize. + * Returns size of random data generated. + */ +static unsigned fillData(unsigned maxSize, + unsigned char *data, + int evenOnly) +{ + unsigned *ip; + unsigned intCount; + unsigned residue; + unsigned char *cp; + int i; + unsigned size; + + size = genRand(1, maxSize); + if(evenOnly) { + size &= ~1; + if(size == 1) { + size = 2; + } + } + intCount = size >> 2; + ip = (unsigned *)data; + for(i=0; isign = -g->sign; + } + + /* avoid zero data - too many pitfalls with mod and div */ + if(isZero(g)) { + g->sign = 1; + g->n[0] = 0x77; + } + return g; +} + +static int testError() +{ + char resp[100]; + + printf("Attach via debugger for more info.\n"); + printf("a to abort, c to continue: "); + gets(resp); + return (resp[0] != 'c'); +} + +/* g := |g1| */ +static void gabs(giant g) +{ + if(g->sign < 0) { + g->sign = -g->sign; + } +} + +/* + * Individual tests. API is identical for all tests. + * + * g1, g2 : giants with random data, size, and sign. Tests do not modify + * these. + * scr1, scr2 : scratch giants, big enough for all conceivable ops. Can + * be modified at will. + * Return : 0 for sucess, 1 on error. + */ + +static int compTest(giant g1, giant g2, giant scr1, giant scr2) +{ + gtog(g1, scr1); // scr1 := g1 + gtog(scr1, scr2); + if(gcompg(g1, scr2)) { + printf("gtog/gcompg error\n"); + return testError(); + } + return 0; +} + +static int addSubTest(giant g1, giant g2, giant scr1, giant scr2) +{ + gtog(g1, scr1); // scr1 := g1 + addg(g2, scr1); // scr1 := g1 + g2 + subg(g1, scr1); // scr1 := g1 + g2 - g1 =? g2 + if(gcompg(g2, scr1)) { + printf("addg/subg error\n"); + return testError(); + } + return 0; +} + +#define LARGEST_MUL 0xffff + +static int mulTest(giant g1, giant g2, giant scr1, giant scr2) +{ + int randInt = genRand(1, LARGEST_MUL); + int i; + int rtn = 0; + + int_to_giant(randInt, scr1); // scr1 := randInt + gtog(g1, scr2); // scr2 := g1 + mulg(scr1, scr2); // scr2 := g1 * randInt + + /* now do the same thing with multiple adds */ + int_to_giant(0, scr1); // scr1 := 0 + for(i=0; icapacity - abs(g1->sign) - 1) * + GIANT_BITS_PER_DIGIT; + int shiftCnt = genRand(1, maxShift); + giant scr3 = borrowGiant(scr1->capacity); + int rtn = 0; + + gtog(g1, scr1); // scr1 := g1 + gshiftleft(shiftCnt, scr1); // scr1 := (g1 << shiftCnt) + + gtog(g1, scr2); // scr2 := g1 + if(shiftCnt <= 30) { + int multInt = (1 << shiftCnt); + int_to_giant(multInt, scr3); // scr3 := (1 << shiftCnt) + } + else { + int_to_giant(1, scr3); // scr3 := 1; + gshiftleft(shiftCnt, scr3); // scr3 := (1 << shiftCnt) + } + mulg(scr3, scr2); // scr2 := g1 * (1 << shiftCnt); + if(gcompg(scr1, scr2)) { + printf("shiftCnt %d 0x%x\n", shiftCnt, shiftCnt); + printf("g1 : "); printGiantHex(g1); + printf("scr1 : "); printGiantHex(scr1); + printf("scr2 : "); printGiantHex(scr2); + printf("gshiftleft error\n"); + rtn = testError(); + } + returnGiant(scr3); + return rtn; +} + +static int rshiftTest(giant g1, giant g2, giant scr1, giant scr2) +{ + int maxShift = bitlen(g1) - 1; + int shiftCnt; + giant scr3 = borrowGiant(scr1->capacity); + int rtn = 0; + + /* special case, can't have g1 = 1 */ + if(maxShift == 0) { + #if FEE_DEBUG + printf("...rshiftTest: tweaking g1 = 1\n"); + #endif + g1->n[0] = 2; + shiftCnt = 1; + } + else { + shiftCnt = genRand(1, maxShift); + } + gtog(g1, scr1); // scr1 := g1 + gabs(scr1); // scr1 := |g1| + gtog(scr1, scr2); // scr2 := |g1| + gshiftright(shiftCnt, scr1); // scr1 := (|g1| >> shiftCnt) + + if(shiftCnt <= 30) { + int multInt = (1 << shiftCnt); + int_to_giant(multInt, scr3); // scr3 := (1 << shiftCnt) + } + else { + int_to_giant(1, scr3); // scr3 := 1; + gshiftleft(shiftCnt, scr3); // scr3 := (1 << shiftCnt) + } + divg(scr3, scr2); // scr2 := g1 / (1 << shiftCnt); + if(gcompg(scr1, scr2)) { + printf("shiftCnt %d 0x%x\n", shiftCnt, shiftCnt); + printf("g1 : "); printGiantHex(g1); + printf("scr1 : "); printGiantHex(scr1); + printf("scr2 : "); printGiantHex(scr2); + printf("gshiftright error\n"); + rtn = testError(); + } + returnGiant(scr3); + return rtn; +} + +static int divTest(giant g1, giant g2, giant scr1, giant scr2) +{ + gtog(g1, scr1); // scr1 := g1 + mulg(g2, scr1); // scr1 := g1 * g2 + gtog(g2, scr2); // scr2 := g2 + gabs(scr2); // scr2 := |g2| + divg(scr2, scr1); // scr1 := (g1 * g2) / |g2| + + /* weird case - if g2 is negative, this result is -g1! */ + if(g2->sign < 0) { + scr1->sign = -scr1->sign; + } + if(gcompg(scr1, g1)) { + printf("g1 : "); printGiantHex(g1); + printf("g2 : "); printGiantHex(g1); + printf("scr1 : "); printGiantHex(scr1); + printf("divTest error\n"); + return testError(); + } + return 0; +} + +#define LARGEST_MOD_MUL 0x40 + +static int modTest(giant g1, giant g2, giant scr1, giant scr2) +{ + int randInt = genRand(1, LARGEST_MOD_MUL); + giant scr3 = borrowGiant(scr1->capacity); + /* debug only */ + giant scr4 = borrowGiant(scr1->capacity); + /* end debug */ + int rtn = 0; + + int_to_giant(randInt, scr1); // scr1 := rand + gtog(g1, scr2); + gabs(scr2); // scr2 := |g1| + + /* current modg can't deal with g mod 1 ! */ + if((scr2->sign == 1) && (scr2->n[0] == 1)) { + #if MODG1_TEST_ENABLE + /* assume that this is legal... */ + #if FEE_DEBUG + printf("..modTest: g1 = 1, no tweak\n"); + #endif + #else + printf("..modTest: tweaking g1 = 1\n"); + scr2->n[0] = 0x54; + #endif MODG1_TEST_ENABLE + } + /* end modg workaround */ + + gtog(g2, scr3); + gabs(scr3); // scr3 := |g2| + + /* this will only work if randInt < |g1| */ + if(gcompg(scr1, scr2) >= 0) { + #if FEE_DEBUG + printf("..modTest: tweaking rand, > g1 = "); printGiantHex(g1); + printf(" g2 = "); printGiantHex(g2); + printf(" rand = "); printGiantHex(scr1); + #endif + modg(scr2, scr1); // scr1 := rand mod g1 + if(gcompg(scr1, scr2) >= 0) { + printf("simple modg error\n"); + return testError(); + } + } + + mulg(scr2, scr3); // scr3 := |g1 * g2| + addg(scr1, scr3); // scr3 := (|g1 * g2|) + rand + gtog(scr3, scr4); + modg(scr2, scr3); // scr3 := scr3 mod |g1| =? rand + if(gcompg(scr1, scr3)) { + printf("g1 : "); printGiantHex(g1); + printf("g2 : "); printGiantHex(g2); + printf("rand : 0x%x\n", randInt); + printf("randG : "); printGiantHex(scr1); + printf("scr4 : "); printGiantHex(scr4); + printf("mod : "); printGiantHex(scr3); + printf("modTest error\n"); + rtn = testError(); + } + returnGiant(scr3); + returnGiant(scr4); + return rtn; + + +} + +#if MODG1_TEST_ENABLE +/* quickie test to demonstrate failure of modg(1, g). Known failure + * as of 10 Apr 1998. + * modg(1,g) fixed on 13 Apr 1998, so this should now work. + */ +static int modg1Test(giant g1, giant scr1, giant scr2) +{ + /* test mod(x, 1) */ + scr1->n[0] = 1; + scr1->sign = 1; + gtog(g1, scr2); + modg(scr1, scr2); + if(!isZero(scr2)) { + printf("g1 : "); printGiantHex(g1); + printf("g1 mod 1 : "); printGiantHex(scr2); + return testError(); + } + return 0; +} +#endif MODG1_TEST_ENABLE + +static int mulOnesTest(giant g1, giant g2, giant scr1, giant scr2) +{ + int i; + int rtn = 0; + giant gOnes = borrowGiant(scr1->capacity); + + /* set up a giant with all ones data */ + gOnes->sign = abs(g1->sign); + for(i=0; isign; i++) { + gOnes->n[i] = (giantDigit)(-1); + } + + gtog(gOnes, scr1); // scr1 := gOnes + mulg(g1, scr1); // scr1 := gOnes * g1 + + gtog(g1, scr2); + mulg(gOnes, scr2); + + if(gcompg(scr1, scr2)) { + printf("good prod : "); printGiantHex(scr1); + printf("bad prod : "); printGiantHex(scr2); + printf("mulOnesTest error\n"); + rtn = testError(); + } + return rtn; + +} + +int main(int argc, char **argv) +{ + int arg; + char *argp; + giant g1; // init'd randomly + giant g2; // ditto + giant scr1; // scratch + giant scr2; // ditto + unsigned char *buf; + int loop; + + int loops = LOOPS_DEF; + int seedSpec = 0; + unsigned seed = 0; + unsigned maxSize = MAX_SIZE_DEF; + + initCryptKit(); + + #ifdef macintosh + seedSpec = 1; + seed = 0; + argc = 1; + maxSize = 8; + #endif + + for(arg=1; arg +#include +#include + +#define SIGN_LOOPS_DEF 100 +#define VFY_LOOPS_DEF 100 +#define PRIV_KEY_SIZE_BYTES 32 +#define DIGEST_SIZE_BYTES 20 /* e.g., SHA1 */ +#define NUM_KEYS 10 + +static void usage(char **argv) +{ + printf("Usage: %s [option...]\n", argv[0]); + printf("Options:\n"); + printf(" s=signLoops -- default %d\n", SIGN_LOOPS_DEF); + printf(" v=verifyLoops -- default %d\n", VFY_LOOPS_DEF); + printf(" D=depth -- default is ALL\n"); + exit(1); +} + +typedef struct { + unsigned char *data; + unsigned length; +} FeeData; + +/* + * Fill numDatas with random data of length bits. Caller has mallocd referents. + */ +static void genRandData(FeeData *datas, + unsigned numDatas, + unsigned numBytes, + feeRand rand) +{ + unsigned i; + FeeData *fd; + for(i=0; ilength = numBytes; + feeRandBytes(rand, fd->data, numBytes); + } + return; +} + +static void mallocData( + FeeData *fd, + unsigned numBytes) +{ + fd->data = (unsigned char *)fmalloc(numBytes); + fd->length = numBytes; +} + +/* common random callback */ +feeReturn randCallback( + void *ref, + unsigned char *bytes, + unsigned numBytes) +{ + feeRand frand = (feeRand)ref; + feeRandBytes(frand, bytes, numBytes); + return FR_Success; +} + +int main(int argc, char **argv) +{ + int arg; + char *argp; + unsigned sigLoops = SIGN_LOOPS_DEF; + unsigned vfyLoops = VFY_LOOPS_DEF; + unsigned numKeys = NUM_KEYS; // might be less for very small loops + unsigned depth; + feeRand rand; + + feePubKey keys[NUM_KEYS]; + /* sigLoops copies of each of {digestData, sigData} */ + FeeData *digestData; + FeeData *sigData; + + unsigned seed; + unsigned i; + PLAT_TIME startTime; + PLAT_TIME endTime; + double elapsed; + curveParams *cp; + unsigned minDepth = 0; + unsigned maxDepth = FEE_DEPTH_MAX; + unsigned basePrimeLen; + char *curveType; + feeReturn frtn; + + for(arg=1; arg sigLoops) { + numKeys = sigLoops; + } + digestData = (FeeData *)fmalloc(sizeof(FeeData) * sigLoops); + sigData = (FeeData *)fmalloc(sizeof(FeeData) * sigLoops); + + /* alloc the data, once, for largest private key or "digest" we'll use */ + for(i=0; icurveType) { + case FCT_Montgomery: + curveType = "FCT_Montgomery"; + break; + case FCT_Weierstrass: + curveType = "FCT_Weierstrass"; + break; + case FCT_General: + curveType = "FCT_General"; + break; + default: + printf("***Unknown curveType!\n"); + exit(1); + } + + switch(cp->primeType) { + case FPT_General: + printf("depth=%d; FPT_General, %s; keysize=%d;\n", + depth, curveType, bitlen(cp->basePrime)); + break; + case FPT_Mersenne: + printf("depth=%d; FPT_Mersenne, %s; q=%d\n", + depth, curveType, cp->q); + break; + default: + printf("depth=%d; FPT_FEE, %s; q=%d k=%d\n", + depth, curveType, cp->q, cp->k); + break; + } + basePrimeLen = bitlen(cp->basePrime); + + /* one set of random data as private keys */ + unsigned privSize = (basePrimeLen + 8) / 8; + genRandData(digestData, numKeys, privSize, rand); + + /* generate the keys (no hash - we've got that covered) */ + for(i=0; idata, digst->length, fkey); + if(frtn) { + printf("***Error %d on feeSigSign\n", (int)frtn); + break; + } + frtn = feeSigData(fs, &sig->data, &sig->length); + if(frtn) { + printf("***Error %d on feeSigData\n", (int)frtn); + break; + } + feeSigFree(fs); + } + PLAT_GET_TIME(endTime); + elapsed = PLAT_GET_US(startTime, endTime); + printf(" sign: %12.2f us per op\n", + elapsed / sigLoops); + + /* + * verify - might be doing more of these than we have + * valid signatures..... + */ + unsigned dex=0; + PLAT_GET_TIME(startTime); + for(i=0; idata, sig->length, &fs); + if(frtn) { + printf("***Error %d on feeSigParse\n", (int)frtn); + break; + } + frtn = feeSigVerify(fs, digst->data, digst->length, fkey); + if(frtn) { + printf("***Error %d on feeSigVerify\n", (int)frtn); + break; + } + feeSigFree(fs); + dex++; + if(dex == sigLoops) { + /* that's all the data we have, recycle */ + dex = 0; + } + } + PLAT_GET_TIME(endTime); + elapsed = PLAT_GET_US(startTime, endTime); + printf(" verify: %12.2f us per op\n", + elapsed / vfyLoops); + + freeCurveParams(cp); + /* possibly limited number of signatures.... */ + for(i=0; i minus + 1 ==> plus + bit 1 : 's' arg to elliptic_add() diff --git a/libsecurity_cryptkit/lib/CipherFileDES.c b/libsecurity_cryptkit/lib/CipherFileDES.c new file mode 100644 index 00000000..28593507 --- /dev/null +++ b/libsecurity_cryptkit/lib/CipherFileDES.c @@ -0,0 +1,586 @@ +/* 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. + *************************************************************************** + * + * CipherFileDES.c - DES-related cipherfile support + * + * Revision History + * ---------------- + * 24 Jun 97 Doug Mitchell at Apple + * Fixed memory leaks via sigData + * 18 Feb 97 Doug Mitchell at Apple + * Split off from feeCipherFile.c + */ + +#include "ckconfig.h" + +#if CRYPTKIT_CIPHERFILE_ENABLE + +#include "Crypt.h" +#include "CipherFileDES.h" +#include "falloc.h" +#include "feeDebug.h" +#include + +/* + * These functions are only called from feeCipherFile.c. + */ +feeReturn createRandDES(feePubKey sendPrivKey, // for sig only + feePubKey recvPubKey, + const unsigned char *plainText, + unsigned plainTextLen, + int genSig, // 1 ==> generate signature + unsigned userData, // for caller's convenience + feeCipherFile *cipherFile) // RETURNED if successful +{ + feeRand frand = NULL; + feeReturn frtn; + unsigned char desKey[FEE_DES_MIN_STATE_SIZE]; + unsigned char *encrDesKey = NULL; // FEED encrypted desKey + unsigned encrDesKeyLen; + feeDES des = NULL; + feeFEEDExp feed = NULL; + unsigned char *cipherText = NULL; + unsigned cipherTextLen; + unsigned char *sigData = NULL; + unsigned sigDataLen = 0; + feeCipherFile cfile = NULL; + unsigned char *pubKeyString = NULL; // of sendPrivKey + unsigned pubKeyStringLen = 0; + + if(recvPubKey == NULL) { + return FR_BadPubKey; + } + + /* + * Cons up random DES key and a feeDES object with it + */ + frand = feeRandAlloc(); + if(frand == NULL) { + frtn = FR_Internal; + goto out; + } + feeRandBytes(frand, desKey, FEE_DES_MIN_STATE_SIZE); + des = feeDESNewWithState(desKey, FEE_DES_MIN_STATE_SIZE); + if(des == NULL) { + frtn = FR_Internal; + goto out; + } + + /* + * Encrypt the DES key via FEEDExp + */ + feed = feeFEEDExpNewWithPubKey(recvPubKey, NULL, NULL); + if(feed == NULL) { + frtn = FR_BadPubKey; + goto out; + } + frtn = feeFEEDExpEncrypt(feed, + desKey, + FEE_DES_MIN_STATE_SIZE, + &encrDesKey, + &encrDesKeyLen); + if(frtn) { + goto out; + } + + /* + * Encrypt the plaintext via DES + */ + frtn = feeDESEncrypt(des, + plainText, + plainTextLen, + &cipherText, + &cipherTextLen); + if(frtn) { + goto out; + } + + if(genSig) { + /* + * We generate signature on ciphertext by convention. + */ + if(sendPrivKey == NULL) { + frtn = FR_BadPubKey; + goto out; + } + frtn = feePubKeyCreateSignature(sendPrivKey, + cipherText, + cipherTextLen, + &sigData, + &sigDataLen); + if(frtn) { + goto out; + } + /* + * Sender's public key string + */ + frtn = feePubKeyCreateKeyString(sendPrivKey, + (char **)&pubKeyString, + &pubKeyStringLen); + if(frtn) { + /* + * Huh? + */ + frtn = FR_BadPubKey; + goto out; + } + } + + /* + * Cons up a cipherfile + */ + cfile = feeCFileNewFromCipherText(CFE_RandDES, + cipherText, + cipherTextLen, + pubKeyString, + pubKeyStringLen, + encrDesKey, + encrDesKeyLen, + sigData, + sigDataLen, + userData); + if(cfile == NULL) { + frtn = FR_Internal; + goto out; + } + +out: + /* free alloc'd stuff */ + + if(cipherText) { + ffree(cipherText); + } + if(feed) { + feeFEEDExpFree(feed); + } + if(frand) { + feeRandFree(frand); + } + if(des) { + feeDESFree(des); + } + if(sigData) { + ffree(sigData); + } + if(encrDesKey) { + ffree(encrDesKey); + } + if(pubKeyString) { + ffree(pubKeyString); + } + memset(desKey, 0, FEE_DES_MIN_STATE_SIZE); + *cipherFile = cfile; + return frtn; + +} + +feeReturn decryptRandDES(feeCipherFile cipherFile, + feePubKey recvPrivKey, + feePubKey sendPubKey, // optional + unsigned char **plainText, // RETURNED + unsigned *plainTextLen, // RETURNED + feeSigStatus *sigStatus) // RETURNED +{ + feeReturn frtn = FR_Success; + unsigned char *cipherText = NULL; + unsigned cipherTextLen; + feeFEEDExp feed = NULL; // to decrypt desKey + feeDES des = NULL; // to decrypt cipherText + unsigned char *desKey; + unsigned desKeyLen; + unsigned char *encrDesKey = NULL; // FEED encrypted desKey + unsigned encrDesKeyLen; + unsigned char *sigData = NULL; + unsigned sigDataLen; + unsigned char *sendPubKeyStr = NULL; + unsigned sendPubKeyStrLen = 0; + feePubKey parsedSendPubKey = NULL; + + if(feeCFileEncrType(cipherFile) != CFE_RandDES) { + frtn = FR_Internal; + goto out; + } + + /* + * Get ciphertext and encrypted DES key from cipherFile + */ + cipherText = feeCFileCipherText(cipherFile, &cipherTextLen); + if(cipherText == NULL) { + frtn = FR_BadCipherFile; + goto out; + } + encrDesKey = feeCFileOtherKeyData(cipherFile, &encrDesKeyLen); + if(encrDesKey == NULL) { + frtn = FR_BadCipherFile; + goto out; + } + + /* + * FEED decrypt to get DES key + */ + feed = feeFEEDExpNewWithPubKey(recvPrivKey, NULL, NULL); + if(feed == NULL) { + frtn = FR_BadPubKey; + goto out; + } + frtn = feeFEEDExpDecrypt(feed, + encrDesKey, + encrDesKeyLen, + &desKey, + &desKeyLen); + if(frtn) { + goto out; + } + + /* + * Now DES decrypt the ciphertext + */ + if(desKeyLen != FEE_DES_MIN_STATE_SIZE) { + frtn = FR_BadCipherFile; + goto out; + } + des = feeDESNewWithState(desKey, desKeyLen); + if(des == NULL) { + frtn = FR_Internal; + goto out; + } + frtn = feeDESDecrypt(des, + cipherText, + cipherTextLen, + plainText, + plainTextLen); + if(frtn) { + goto out; + } + + sigData = feeCFileSigData(cipherFile, &sigDataLen); + if(sigData) { + feeReturn sigFrtn; + + if(sendPubKey == NULL) { + /* + * Obtain sender's public key from cipherfile + */ + sendPubKeyStr = feeCFileSendPubKeyData(cipherFile, + &sendPubKeyStrLen); + if(sendPubKeyStr == NULL) { + /* + * Hmm..shouldn't really happen, but let's + * press on. + */ + *sigStatus = SS_PresentNoKey; + goto out; + } + parsedSendPubKey = feePubKeyAlloc(); + frtn = feePubKeyInitFromKeyString(parsedSendPubKey, + (char *)sendPubKeyStr, sendPubKeyStrLen); + if(frtn) { + dbgLog(("parseRandDES: bad sendPubKeyStr\n")); + *sigStatus = SS_PresentNoKey; + goto out; + } + sendPubKey = parsedSendPubKey; + } + sigFrtn = feePubKeyVerifySignature(sendPubKey, + cipherText, + cipherTextLen, + sigData, + sigDataLen); + switch(sigFrtn) { + case FR_Success: + *sigStatus = SS_PresentValid; + break; + default: + *sigStatus = SS_PresentInvalid; + break; + } + } + else { + *sigStatus = SS_NotPresent; + } +out: + if(cipherText) { + ffree(cipherText); + } + if(feed) { + feeFEEDExpFree(feed); + } + if(des) { + feeDESFree(des); + } + if(desKey) { + memset(desKey, 0, desKeyLen); + ffree(desKey); + } + if(encrDesKey) { + ffree(encrDesKey); + } + if(sigData) { + ffree(sigData); + } + if(parsedSendPubKey) { + feePubKeyFree(parsedSendPubKey); + } + if(sendPubKeyStr) { + ffree(sendPubKeyStr); + } + return frtn; +} + +feeReturn createPubDES(feePubKey sendPrivKey, // required + feePubKey recvPubKey, + const unsigned char *plainText, + unsigned plainTextLen, + int genSig, // 1 ==> generate signature + unsigned userData, // for caller's convenience + feeCipherFile *cipherFile) // RETURNED if successful +{ + feeRand frand = NULL; + feeReturn frtn; + unsigned char *desKey; + unsigned desKeyLen; + feeDES des = NULL; + unsigned char *cipherText = NULL; + unsigned cipherTextLen; + unsigned char *sigData = NULL; + unsigned sigDataLen = 0; + feeCipherFile cfile = NULL; + unsigned char *pubKeyString = NULL; + unsigned pubKeyStringLen; + + if((sendPrivKey == NULL) || (recvPubKey == NULL)) { + return FR_BadPubKey; + } + + /* + * Get the public string version of sendPrivKey for embedding in + * cipherfile + */ + frtn = feePubKeyCreateKeyString(sendPrivKey, + (char **)&pubKeyString, + &pubKeyStringLen); + if(frtn) { + goto out; + } + + /* + * Obtain DES key via key exchange and get a feeDES object with it + */ + frtn = feePubKeyCreatePad(sendPrivKey, + recvPubKey, + &desKey, + &desKeyLen); + if(frtn) { + goto out; + } + des = feeDESNewWithState(desKey, desKeyLen); + if(des == NULL) { + frtn = FR_Internal; + goto out; + } + + /* + * Encrypt the plaintext via DES + */ + frtn = feeDESEncrypt(des, + plainText, + plainTextLen, + &cipherText, + &cipherTextLen); + if(frtn) { + goto out; + } + + if(genSig) { + /* + * We generate signature on ciphertext by convention. + */ + frtn = feePubKeyCreateSignature(sendPrivKey, + cipherText, + cipherTextLen, + &sigData, + &sigDataLen); + if(frtn) { + goto out; + } + } + + /* + * Cons up a cipherfile + */ + cfile = feeCFileNewFromCipherText(CFE_PublicDES, + cipherText, + cipherTextLen, + pubKeyString, + pubKeyStringLen, + NULL, // otherKey + 0, + sigData, + sigDataLen, + userData); + if(cfile == NULL) { + frtn = FR_Internal; + goto out; + } + +out: + /* free alloc'd stuff */ + + if(cipherText) { + ffree(cipherText); + } + if(frand) { + feeRandFree(frand); + } + if(des) { + feeDESFree(des); + } + if(desKey) { + ffree(desKey); + } + if(sigData) { + ffree(sigData); + } + if(pubKeyString) { + ffree(pubKeyString); + } + *cipherFile = cfile; + return frtn; + +} + +feeReturn decryptPubDES(feeCipherFile cipherFile, + feePubKey recvPrivKey, + feePubKey sendPubKey, + unsigned char **plainText, // RETURNED + unsigned *plainTextLen, // RETURNED + feeSigStatus *sigStatus) // RETURNED +{ + feeReturn frtn = FR_Success; + unsigned char *cipherText = NULL; + unsigned cipherTextLen; + feeDES des = NULL; // to decrypt cipherText + unsigned char *desKey; + unsigned desKeyLen; + unsigned char *sigData = NULL; + unsigned sigDataLen; + unsigned char *pubKeyString = NULL; + unsigned pubKeyStringLen; + feePubKey decryptPubKey = NULL; // from cipherfile + + if(feeCFileEncrType(cipherFile) != CFE_PublicDES) { + frtn = FR_Internal; + goto out; + } + + /* + * Get ciphertext and sender's public key from cipherFile + */ + cipherText = feeCFileCipherText(cipherFile, &cipherTextLen); + if(cipherText == NULL) { + frtn = FR_BadCipherFile; + goto out; + } + pubKeyString = feeCFileSendPubKeyData(cipherFile, &pubKeyStringLen); + if(pubKeyString == NULL) { + frtn = FR_BadCipherFile; + goto out; + } + decryptPubKey = feePubKeyAlloc(); + frtn = feePubKeyInitFromKeyString(decryptPubKey, + (char *)pubKeyString, + pubKeyStringLen); + if(frtn) { + goto out; + } + + /* + * key exchange to get DES key + */ + frtn = feePubKeyCreatePad(recvPrivKey, + decryptPubKey, + &desKey, + &desKeyLen); + if(frtn) { + goto out; + } + + /* + * Now DES decrypt the ciphertext + */ + if(desKeyLen < FEE_DES_MIN_STATE_SIZE) { + frtn = FR_BadCipherFile; + goto out; + } + des = feeDESNewWithState(desKey, desKeyLen); + if(des == NULL) { + frtn = FR_Internal; + goto out; + } + frtn = feeDESDecrypt(des, + cipherText, + cipherTextLen, + plainText, + plainTextLen); + if(frtn) { + goto out; + } + + sigData = feeCFileSigData(cipherFile, &sigDataLen); + if(sigData) { + feeReturn sigFrtn; + + if(sendPubKey == NULL) { + /* + * Use key embedded in cipherfile + */ + sendPubKey = decryptPubKey; + } + sigFrtn = feePubKeyVerifySignature(sendPubKey, + cipherText, + cipherTextLen, + sigData, + sigDataLen); + switch(sigFrtn) { + case FR_Success: + *sigStatus = SS_PresentValid; + break; + default: + *sigStatus = SS_PresentInvalid; + break; + } + } + else { + *sigStatus = SS_NotPresent; + } +out: + if(cipherText) { + ffree(cipherText); + } + if(des) { + feeDESFree(des); + } + if(desKey) { + ffree(desKey); + } + if(pubKeyString) { + ffree(pubKeyString); + } + if(sigData) { + ffree(sigData); + } + if(decryptPubKey) { + feePubKeyFree(decryptPubKey); + } + return frtn; +} + +#endif /* CRYPTKIT_CIPHERFILE_ENABLE */ + diff --git a/libsecurity_cryptkit/lib/CipherFileDES.h b/libsecurity_cryptkit/lib/CipherFileDES.h new file mode 100644 index 00000000..8f73474e --- /dev/null +++ b/libsecurity_cryptkit/lib/CipherFileDES.h @@ -0,0 +1,67 @@ +/* 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. + *************************************************************************** + * + * CipherFileDES.h - DES-related cipherfile support + * + * Revision History + * ---------------- + * 18 Feb 97 Doug Mitchell at Apple + * Created. + */ + +#ifndef _CK_CFILEDES_H_ +#define _CK_CFILEDES_H_ + +#include "ckconfig.h" + +#if CRYPTKIT_CIPHERFILE_ENABLE + +#include "Crypt.h" +#include "feeCipherFile.h" +#include "CipherFileTypes.h" + +#ifdef __cplusplus +extern "C" { +#endif + +feeReturn createRandDES(feePubKey sendPrivKey, + feePubKey recvPubKey, + const unsigned char *plainText, + unsigned plainTextLen, + int genSig, // 1 ==> generate signature + unsigned userData, // for caller's convenience + feeCipherFile *cipherFile); // RETURNED if successful +feeReturn decryptRandDES(feeCipherFile cipherFile, + feePubKey recvPrivKey, + feePubKey sendPubKey, + unsigned char **plainText, // RETURNED + unsigned *plainTextLen, // RETURNED + feeSigStatus *sigStatus); // RETURNED +feeReturn createPubDES(feePubKey sendPrivKey, // required + feePubKey recvPubKey, // required + const unsigned char *plainText, + unsigned plainTextLen, + int genSig, // 1 ==> generate signature + unsigned userData, // for caller's convenience + feeCipherFile *cipherFile); // RETURNED if successful +feeReturn decryptPubDES(feeCipherFile cipherFile, + feePubKey recvPrivKey, + feePubKey sendPubKey, // optional + unsigned char **plainText, // RETURNED + unsigned *plainTextLen, // RETURNED + feeSigStatus *sigStatus); // RETURNED + +#ifdef __cplusplus +} +#endif + +#endif /* CRYPTKIT_CIPHERFILE_ENABLE*/ + +#endif /*_CK_CFILEDES_H_*/ diff --git a/libsecurity_cryptkit/lib/CipherFileFEED.c b/libsecurity_cryptkit/lib/CipherFileFEED.c new file mode 100644 index 00000000..d11a2338 --- /dev/null +++ b/libsecurity_cryptkit/lib/CipherFileFEED.c @@ -0,0 +1,460 @@ +/* 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. + *************************************************************************** + * + * CipherFileFEED.c - FEED and FEEDExp related cipherfile support + * + * Revision History + * ---------------- + * 24 Jun 97 Doug Mitchell at Apple + * Fixed memory leaks via sigData + * 18 Feb 97 Doug Mitchell at Apple + * Split off from feeCipherFile.c + */ + +#include "ckconfig.h" + +#if CRYPTKIT_CIPHERFILE_ENABLE + +#include "Crypt.h" +#include "CipherFileFEED.h" +#include "falloc.h" +#include "feeDebug.h" + +feeReturn createFEED(feePubKey sendPrivKey, // required + feePubKey recvPubKey, + const unsigned char *plainText, + unsigned plainTextLen, + int genSig, // 1 ==> generate signature + unsigned userData, // for caller's convenience + feeCipherFile *cipherFile) // RETURNED if successful +{ + feeReturn frtn; + feeFEED feed = NULL; + unsigned char *cipherText = NULL; + unsigned cipherTextLen; + unsigned char *sigData = NULL; + unsigned sigDataLen = 0; + feeCipherFile cfile = NULL; + unsigned char *pubKeyString = NULL; // of sendPrivKey + unsigned pubKeyStringLen = 0; + + if((sendPrivKey == NULL) || (recvPubKey == NULL)) { + return FR_BadPubKey; + } + + /* + * FEED encrypt plaintext + */ + feed = feeFEEDNewWithPubKey(sendPrivKey, recvPubKey, FF_ENCRYPT, NULL, NULL); + if(feed == NULL) { + frtn = FR_BadPubKey; + goto out; + } + frtn = feeFEEDEncrypt(feed, + plainText, + plainTextLen, + &cipherText, + &cipherTextLen); + if(frtn) { + goto out; + } + + /* + * Sender's public key string + */ + frtn = feePubKeyCreateKeyString(sendPrivKey, + (char **)&pubKeyString, + &pubKeyStringLen); + if(frtn) { + /* + * Huh? + */ + frtn = FR_BadPubKey; + goto out; + } + + if(genSig) { + /* + * We generate signature on ciphertext by convention. + */ + frtn = feePubKeyCreateSignature(sendPrivKey, + cipherText, + cipherTextLen, + &sigData, + &sigDataLen); + if(frtn) { + goto out; + } + } + + /* + * Cons up a cipherfile + */ + cfile = feeCFileNewFromCipherText(CFE_FEED, + cipherText, + cipherTextLen, + pubKeyString, + pubKeyStringLen, + NULL, + 0, + sigData, + sigDataLen, + userData); + if(cfile == NULL) { + frtn = FR_Internal; + goto out; + } + +out: + /* free alloc'd stuff */ + + if(cipherText) { + ffree(cipherText); + } + if(feed) { + feeFEEDFree(feed); + } + if(pubKeyString) { + ffree(pubKeyString); + } + if(sigData) { + ffree(sigData); + } + *cipherFile = cfile; + return frtn; + +} + +feeReturn decryptFEED(feeCipherFile cipherFile, + feePubKey recvPrivKey, + feePubKey sendPubKey, // optional + unsigned char **plainText, // RETURNED + unsigned *plainTextLen, // RETURNED + feeSigStatus *sigStatus) // RETURNED +{ + feeReturn frtn = FR_Success; + unsigned char *cipherText = NULL; + unsigned cipherTextLen; + feeFEED feed = NULL; + unsigned char *sigData = NULL; + unsigned sigDataLen; + unsigned char *sendPubKeyStr = NULL; + unsigned sendPubKeyStrLen = 0; + feePubKey parsedSendPubKey = NULL; + + if(feeCFileEncrType(cipherFile) != CFE_FEED) { + frtn = FR_Internal; + goto out; + } +//printf("decryptFEED\n"); +//printf("privKey:\n"); printPubKey(recvPrivKey); +//printf("pubKey:\n"); printPubKey(sendPubKey); + /* + * Get ciphertext and sender's public key from cipherFile + */ + cipherText = feeCFileCipherText(cipherFile, &cipherTextLen); + if(cipherText == NULL) { + frtn = FR_BadCipherFile; + goto out; + } + sendPubKeyStr = feeCFileSendPubKeyData(cipherFile, &sendPubKeyStrLen); + if(sendPubKeyStr == NULL) { + frtn = FR_BadCipherFile; + goto out; + } + parsedSendPubKey = feePubKeyAlloc(); + frtn = feePubKeyInitFromKeyString(parsedSendPubKey, + (char *)sendPubKeyStr, + sendPubKeyStrLen); + if(frtn) { + frtn = FR_BadCipherFile; + goto out; + } +//printf("parsedSendPubKey:\n"); printPubKey(parsedSendPubKey); + + /* + * FEED decrypt + */ + feed = feeFEEDNewWithPubKey(recvPrivKey, parsedSendPubKey, FF_DECRYPT, NULL, NULL); + if(feed == NULL) { + frtn = FR_BadPubKey; + goto out; + } + frtn = feeFEEDDecrypt(feed, + cipherText, + cipherTextLen, + plainText, + plainTextLen); + if(frtn) { + goto out; + } + + sigData = feeCFileSigData(cipherFile, &sigDataLen); + if(sigData) { + feeReturn sigFrtn; + + if(sendPubKey == NULL) { + /* + * use embedded sender's public key + */ + sendPubKey = parsedSendPubKey; + } + sigFrtn = feePubKeyVerifySignature(sendPubKey, + cipherText, + cipherTextLen, + sigData, + sigDataLen); + switch(sigFrtn) { + case FR_Success: + *sigStatus = SS_PresentValid; + break; + default: + *sigStatus = SS_PresentInvalid; + break; + } + } + else { + *sigStatus = SS_NotPresent; + } +out: + if(cipherText) { + ffree(cipherText); + } + if(feed) { + feeFEEDFree(feed); + } + if(sigData) { + ffree(sigData); + } + if(parsedSendPubKey) { + feePubKeyFree(parsedSendPubKey); + } + if(sendPubKeyStr) { + ffree(sendPubKeyStr); + } + return frtn; +} + +feeReturn createFEEDExp(feePubKey sendPrivKey, // for sig only + feePubKey recvPubKey, + const unsigned char *plainText, + unsigned plainTextLen, + int genSig, // 1 ==> generate signature + unsigned userData, // for caller's convenience + feeCipherFile *cipherFile) // RETURNED if successful +{ + feeReturn frtn; + feeFEEDExp feed = NULL; + unsigned char *cipherText = NULL; + unsigned cipherTextLen; + unsigned char *sigData = NULL; + unsigned sigDataLen = 0; + feeCipherFile cfile = NULL; + unsigned char *pubKeyString = NULL; // of sendPrivKey, for sig + unsigned pubKeyStringLen = 0; + + if(recvPubKey == NULL) { + return FR_BadPubKey; + } + + /* + * FEEDExp encrypt plaintext + */ + feed = feeFEEDExpNewWithPubKey(recvPubKey, NULL, NULL); + if(feed == NULL) { + frtn = FR_BadPubKey; + goto out; + } + frtn = feeFEEDExpEncrypt(feed, + plainText, + plainTextLen, + &cipherText, + &cipherTextLen); + if(frtn) { + goto out; + } + + if(genSig) { + if(sendPrivKey == NULL) { + frtn = FR_IllegalArg; + goto out; + } + /* + * We generate signature on ciphertext by convention. + */ + frtn = feePubKeyCreateSignature(sendPrivKey, + cipherText, + cipherTextLen, + &sigData, + &sigDataLen); + if(frtn) { + goto out; + } + /* + * Sender's public key string + */ + frtn = feePubKeyCreateKeyString(sendPrivKey, + (char **)&pubKeyString, + &pubKeyStringLen); + if(frtn) { + /* + * Huh? + */ + frtn = FR_BadPubKey; + goto out; + } + } + + /* + * Cons up a cipherfile + */ + cfile = feeCFileNewFromCipherText(CFE_FEEDExp, + cipherText, + cipherTextLen, + pubKeyString, + pubKeyStringLen, + NULL, + 0, + sigData, + sigDataLen, + userData); + if(cfile == NULL) { + frtn = FR_Internal; + goto out; + } + +out: + /* free alloc'd stuff */ + + if(cipherText) { + ffree(cipherText); + } + if(feed) { + feeFEEDExpFree(feed); + } + if(sigData) { + ffree(sigData); + } + if(pubKeyString) { + ffree(pubKeyString); + } + *cipherFile = cfile; + return frtn; + +} + +feeReturn decryptFEEDExp(feeCipherFile cipherFile, + feePubKey recvPrivKey, + feePubKey sendPubKey, // optional + unsigned char **plainText, // RETURNED + unsigned *plainTextLen, // RETURNED + feeSigStatus *sigStatus) // RETURNED +{ + feeReturn frtn = FR_Success; + unsigned char *cipherText = NULL; + unsigned cipherTextLen; + feeFEEDExp feed = NULL; + unsigned char *sigData = NULL; + unsigned sigDataLen; + unsigned char *sendPubKeyStr = NULL; + unsigned sendPubKeyStrLen = 0; + feePubKey parsedSendPubKey = NULL; + + if(feeCFileEncrType(cipherFile) != CFE_FEEDExp) { + frtn = FR_Internal; + goto out; + } + + /* + * Get ciphertext from cipherFile + */ + cipherText = feeCFileCipherText(cipherFile, &cipherTextLen); + if(cipherText == NULL) { + frtn = FR_BadCipherFile; + goto out; + } + + /* + * FEEDExp decrypt + */ + feed = feeFEEDExpNewWithPubKey(recvPrivKey, NULL, NULL); + if(feed == NULL) { + frtn = FR_BadPubKey; + goto out; + } + frtn = feeFEEDExpDecrypt(feed, + cipherText, + cipherTextLen, + plainText, + plainTextLen); + if(frtn) { + goto out; + } + + sigData = feeCFileSigData(cipherFile, &sigDataLen); + if(sigData) { + feeReturn sigFrtn; + + if(sendPubKey == NULL) { + /* + * use embedded sender's public key + */ + sendPubKeyStr = feeCFileSendPubKeyData(cipherFile, + &sendPubKeyStrLen); + if(sendPubKeyStr == NULL) { + frtn = FR_BadCipherFile; + goto out; + } + parsedSendPubKey = feePubKeyAlloc(); + frtn = feePubKeyInitFromKeyString(parsedSendPubKey, + (char *)sendPubKeyStr, sendPubKeyStrLen); + if(frtn) { + frtn = FR_BadCipherFile; + goto out; + } + sendPubKey = parsedSendPubKey; + } + sigFrtn = feePubKeyVerifySignature(sendPubKey, + cipherText, + cipherTextLen, + sigData, + sigDataLen); + switch(sigFrtn) { + case FR_Success: + *sigStatus = SS_PresentValid; + break; + default: + *sigStatus = SS_PresentInvalid; + break; + } + } + else { + *sigStatus = SS_NotPresent; + } +out: + if(cipherText) { + ffree(cipherText); + } + if(feed) { + feeFEEDExpFree(feed); + } + if(sigData) { + ffree(sigData); + } + if(parsedSendPubKey) { + feePubKeyFree(parsedSendPubKey); + } + if(sendPubKeyStr) { + ffree(sendPubKeyStr); + } + return frtn; +} + +#endif /* CRYPTKIT_CIPHERFILE_ENABLE */ diff --git a/libsecurity_cryptkit/lib/CipherFileFEED.h b/libsecurity_cryptkit/lib/CipherFileFEED.h new file mode 100644 index 00000000..e6c165d0 --- /dev/null +++ b/libsecurity_cryptkit/lib/CipherFileFEED.h @@ -0,0 +1,69 @@ +/* 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. + *************************************************************************** + * + * CipherFileFEED.h - FEED and FEEDExp related cipherfile support + * + * Revision History + * ---------------- + * 18 Feb 97 Doug Mitchell at Apple + * Created. + */ + +#ifndef _CK_CFILEFEED_H_ +#define _CK_CFILEFEED_H_ + +#include "ckconfig.h" + +#if CRYPTKIT_CIPHERFILE_ENABLE + +#include "Crypt.h" +#include "feeCipherFile.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Private functions. + */ +feeReturn createFEED(feePubKey sendPrivKey, + feePubKey recvPubKey, + const unsigned char *plainText, + unsigned plainTextLen, + int genSig, // 1 ==> generate signature + unsigned userData, // for caller's convenience + feeCipherFile *cipherFile); // RETURNED if successful +feeReturn decryptFEED(feeCipherFile cipherFile, + feePubKey recvPrivKey, + feePubKey sendPubKey, + unsigned char **plainText, // RETURNED + unsigned *plainTextLen, // RETURNED + feeSigStatus *sigStatus); // RETURNED +feeReturn createFEEDExp(feePubKey sendPrivKey, + feePubKey recvPubKey, + const unsigned char *plainText, + unsigned plainTextLen, + int genSig, // 1 ==> generate signature + unsigned userData, // for caller's convenience + feeCipherFile *cipherFile); // RETURNED if successful +feeReturn decryptFEEDExp(feeCipherFile cipherFile, + feePubKey recvPrivKey, + feePubKey sendPubKey, // optional + unsigned char **plainText, // RETURNED + unsigned *plainTextLen, // RETURNED + feeSigStatus *sigStatus); // RETURNED + +#ifdef __cplusplus +} +#endif + +#endif /* CRYPTKIT_CIPHERFILE_ENABLE */ + +#endif /*_CK_CFILEFEED_H_*/ diff --git a/libsecurity_cryptkit/lib/CipherFileTypes.h b/libsecurity_cryptkit/lib/CipherFileTypes.h new file mode 100644 index 00000000..27b09bc1 --- /dev/null +++ b/libsecurity_cryptkit/lib/CipherFileTypes.h @@ -0,0 +1,83 @@ +/* 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. + *************************************************************************** + * + * CipherFileTypes.h + * + * Revision History + * ---------------- + * 8/24/98 ap + * Added tags around #endif comment. + * 19 Feb 97 Doug Mitchell at NeXT + * Created. + */ + +#ifndef _CK_CFILETYPES_H_ +#define _CK_CFILETYPES_H_ + +#include "ckconfig.h" + +#if CRYPTKIT_CIPHERFILE_ENABLE + +#include "feeCipherFile.h" + +/* + * Type of encryption used in a CipherFile. + */ +typedef enum { + + /* + * DES encryption using pad created via public key exchange; sender's + * public key is embedded. + */ + CFE_PublicDES = 1, + + /* + * Random DES key used for encryption. The DES key is encrypted via + * FEEDExp using recipient's public key; the result is embedded in the + * CipherFile. Sender's public key is embedded only if + * signature is generated. + */ + CFE_RandDES = 2, + + /* + * 1:1 FEED encryption. Sender's public key is embedded. + */ + CFE_FEED = 3, + + /* + * 2:1 FEED encryption. Sender's public key is embedded only if signature + * is generated. + */ + CFE_FEEDExp = 4, + + /* + * User-defined cipherfile. + */ + CFE_Other = 5 + +} cipherFileEncrType; + + +/* + * Signature status upon decryption of a CipherFile. + */ +typedef enum { + + SS_NotPresent = 0, // Signature not present. + SS_PresentValid = 1, // Signature present and valid. + SS_PresentNoKey = 2, // Signature present, but no public key + // available to validate it. + SS_PresentInvalid = 3 // Signature present and invalid. + +} feeSigStatus; + +#endif /* CRYPTKIT_CIPHERFILE_ENABLE */ + +#endif /* _CK_CFILETYPES_H_ */ diff --git a/libsecurity_cryptkit/lib/Crypt.h b/libsecurity_cryptkit/lib/Crypt.h new file mode 100644 index 00000000..4af8afa1 --- /dev/null +++ b/libsecurity_cryptkit/lib/Crypt.h @@ -0,0 +1,60 @@ +/* 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. + *************************************************************************** + * + * Crypt.h - top-level header for FEE library. + * + * Revision History + * ---------------- + * 8/24/98 ap + * Added tags around #endif comment. + * 28 May 1996 Doug Mitchell at Apple + * Added falloc.h, newly exported API. + * 27 Aug 1996 Doug Mitchell at NeXT + * Created. + */ + +#ifndef _CK_CRYPT_H_ +#define _CK_CRYPT_H_ + +#ifdef macintosh + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#else + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif + +#endif /* _CK_CRYPT_H_ */ diff --git a/libsecurity_cryptkit/lib/CryptKit.def b/libsecurity_cryptkit/lib/CryptKit.def new file mode 100644 index 00000000..b4a73bb4 --- /dev/null +++ b/libsecurity_cryptkit/lib/CryptKit.def @@ -0,0 +1,113 @@ +LIBRARY CryptKit.dll + +EXPORTS + + feePubKeyAlloc + feePubKeyFree + feePubKeyInitFromPrivData + feePubKeyInitFromKey + feePubKeyInitFromKeyString + feePubKeyCreateKeyString + feePubKeyIsEqual + feePubKeyCreatePad + feePubKeyCreateSignature + feePubKeyVerifySignature + feePubKeyUsageName + feePubKeyAlgorithmName + feePubKeyBitsize + feeDESNewWithState + feeDESFree + feeDESSetState + feeDESSetBlockMode + feeDESSetChainMode + feeDESPlainBlockSize + feeDESCipherBlockSize + feeDESCipherBufSize + + feeDESCipherTextSize + + feeDESEncryptBlock + feeDESDecryptBlock + feeDESEncrypt + feeDESDecrypt + feeSigNewWithKey + feeSigFree + feeSigPm + feeSigSign + feeSigData + feeSigParse + feeSigVerify + feeSigSigner + feeHashAlloc + feeHashReinit + feeHashFree + feeHashAddData + feeHashDigest + feeHashDigestLen + feeRandAllocWithSeed + feeRandAlloc + feeRandFree + feeRandNextNum + feeRandBytes + feeReturnString + feeFEEDNewWithPubKey + feeFEEDFree + feeFEEDPlainBlockSize + feeFEEDCipherBlockSize + feeFEEDCipherBufSize + + feeFEEDCipherTextSize + feeFEEDEncryptBlock + feeFEEDDecryptBlock + feeFEEDEncrypt + feeFEEDDecrypt + + feeFEEDExpNewWithPubKey + + feeFEEDExpFree + + feeFEEDExpPlainBlockSize + + feeFEEDExpCipherBlockSize + + feeFEEDExpCipherBufSize + + feeFEEDExpCipherTextSize + + feeFEEDExpEncryptBlock + + feeFEEDExpDecryptBlock + + feeFEEDExpEncrypt + + feeFEEDExpDecrypt + dec64 + enc64 + isValidEnc64 + feeCFileNewFromCipherText + feeCFileDataRepresentation + feeCFileNewFromDataRep + feeCFileFree + feeCFileEncrType + feeCFileCipherText + feeCFileSendPubKeyData + feeCFileOtherKeyData + feeCFileSigData + parseCipherFile + + createCipherFile + fmalloc + fmallocWithData + ffree + + .objc_class_name_NSFEEPublicKey CONSTANT + + .objc_category_name_NSFEEPublicKey_Private CONSTANT + + .objc_class_name_NSRandomNumberGenerator CONSTANT + + .objc_class_name_NSDESCryptor CONSTANT + + .objc_class_name_NSCipherFile CONSTANT + + diff --git a/libsecurity_cryptkit/lib/CryptKit.h b/libsecurity_cryptkit/lib/CryptKit.h new file mode 100644 index 00000000..c641a901 --- /dev/null +++ b/libsecurity_cryptkit/lib/CryptKit.h @@ -0,0 +1,28 @@ +/* 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. + *************************************************************************** + * + * CryptKit.h created by blaine on Thu 22-Feb-1996 + */ + +// Encryption related protocols and types +#include +#include + +// Classes +#include +#include +#include +#include +#include + +// Misc. Functions +#include +#include +#include diff --git a/libsecurity_cryptkit/lib/CryptKitAsn1.cpp b/libsecurity_cryptkit/lib/CryptKitAsn1.cpp new file mode 100644 index 00000000..d67478b2 --- /dev/null +++ b/libsecurity_cryptkit/lib/CryptKitAsn1.cpp @@ -0,0 +1,82 @@ +/* + * CryptKitAsn1.cpp - ASN1 templates for FEE keys and signatures + */ + +#include "CryptKitAsn1.h" +#include + +/* + * Unlike RSA, DSA, and Diffie-Hellman, the integers in these + * objects are indeed signed. + */ +#define SEC_ASN1_SIGNED (SEC_ASN1_SIGNED_INT | SEC_ASN1_INTEGER) + +/* FEECurveParametersASN1 */ +const SecAsn1Template FEECurveParametersASN1Template[] = { + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(FEECurveParametersASN1) }, + { SEC_ASN1_INTEGER, offsetof(FEECurveParametersASN1,primeType) }, + { SEC_ASN1_INTEGER, offsetof(FEECurveParametersASN1,curveType) }, + { SEC_ASN1_SIGNED, offsetof(FEECurveParametersASN1,q) }, + { SEC_ASN1_SIGNED, offsetof(FEECurveParametersASN1,k) }, + { SEC_ASN1_SIGNED, offsetof(FEECurveParametersASN1,m) }, + { SEC_ASN1_SIGNED, offsetof(FEECurveParametersASN1,a) }, + { SEC_ASN1_SIGNED, offsetof(FEECurveParametersASN1,b_) }, + { SEC_ASN1_SIGNED, offsetof(FEECurveParametersASN1,c) }, + { SEC_ASN1_SIGNED, offsetof(FEECurveParametersASN1,x1Plus) }, + { SEC_ASN1_SIGNED, offsetof(FEECurveParametersASN1,x1Minus) }, + { SEC_ASN1_SIGNED, offsetof(FEECurveParametersASN1,cOrderPlus) }, + { SEC_ASN1_SIGNED, offsetof(FEECurveParametersASN1,cOrderMinus) }, + { SEC_ASN1_SIGNED, offsetof(FEECurveParametersASN1,x1OrderPlus) }, + { SEC_ASN1_SIGNED, offsetof(FEECurveParametersASN1,x1OrderMinus) }, + { SEC_ASN1_SIGNED | SEC_ASN1_OPTIONAL, + offsetof(FEECurveParametersASN1,basePrime) }, + { 0, } +}; + +/* FEEElGamalSignatureASN1 */ +const SecAsn1Template FEEElGamalSignatureASN1Template[] = { + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(FEEElGamalSignatureASN1) }, + { SEC_ASN1_SIGNED, offsetof(FEEElGamalSignatureASN1,u) }, + { SEC_ASN1_SIGNED, offsetof(FEEElGamalSignatureASN1,pmX) }, + { 0, } +}; + +/* FEEECDSASignatureASN1 */ +const SecAsn1Template FEEECDSASignatureASN1Template[] = { + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(FEEECDSASignatureASN1) }, + { SEC_ASN1_SIGNED, offsetof(FEEECDSASignatureASN1,c) }, + { SEC_ASN1_SIGNED, offsetof(FEEECDSASignatureASN1,d) }, + { 0, } +}; + +/* FEEPublicKeyASN1 */ +const SecAsn1Template FEEPublicKeyASN1Template[] = { + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(FEEPublicKeyASN1) }, + { SEC_ASN1_SIGNED, offsetof(FEEPublicKeyASN1,version) }, + { SEC_ASN1_INLINE, + offsetof(FEEPublicKeyASN1,curveParams), + FEECurveParametersASN1Template }, + { SEC_ASN1_SIGNED, offsetof(FEEPublicKeyASN1,plusX) }, + { SEC_ASN1_SIGNED, offsetof(FEEPublicKeyASN1,minusX) }, + { SEC_ASN1_SIGNED | SEC_ASN1_OPTIONAL, + offsetof(FEEPublicKeyASN1,plusY) }, + { 0, } +}; + +/* FEEPrivateKeyASN1 */ +const SecAsn1Template FEEPrivateKeyASN1Template[] = { + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(FEEPrivateKeyASN1) }, + { SEC_ASN1_SIGNED, offsetof(FEEPrivateKeyASN1,version) }, + { SEC_ASN1_INLINE, + offsetof(FEEPrivateKeyASN1,curveParams), + FEECurveParametersASN1Template }, + { SEC_ASN1_SIGNED, offsetof(FEEPrivateKeyASN1,privData) }, + { 0, } +}; + + diff --git a/libsecurity_cryptkit/lib/CryptKitAsn1.h b/libsecurity_cryptkit/lib/CryptKitAsn1.h new file mode 100644 index 00000000..a4bfc299 --- /dev/null +++ b/libsecurity_cryptkit/lib/CryptKitAsn1.h @@ -0,0 +1,138 @@ +/* + * CryptKitAsn1.h - ASN1 templates for FEE objects + */ + +#ifndef _CRYPT_KIT_ASN1_H_ +#define _CRYPT_KIT_ASN1_H_ + +#include "ckconfig.h" + +#if CRYPTKIT_DER_ENABLE + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + -- FEE Curve parameters (defined in ) + FEEPrimeType ::= INTEGER { FPT_Mersenne(0), FPT_FEE(1), FPT_General(2) } + FEECurveType ::= INTEGER { FCT_Montgomery(0), FCT_Weierstrass(1), + FCT_General(2) } + */ + +/* + FEECurveParameters ::= SEQUENCE + { + primeType FEEPrimeType, + curveType FEECurveType, + q INTEGER, -- unsigned + k INTEGER, -- signed + m INTEGER, + a BigIntegerStr, + bb BigIntegerStr, -- can't use variable/field b + c BigIntegerStr, + x1Plus BigIntegerStr, + x1Minus BigIntegerStr, + cOrderPlus BigIntegerStr, + cOrderMinus BigIntegerStr, + x1OrderPlus BigIntegerStr, + x1OrderMinus BigIntegerStr, + basePrime BigIntegerStr OPTIONAL + -- iff FEEPrimeType == CT_GENERAL +} +*/ +typedef struct { + CSSM_DATA primeType; + CSSM_DATA curveType; + CSSM_DATA q; + CSSM_DATA k; + CSSM_DATA m; + CSSM_DATA a; + CSSM_DATA b_; // can't use variable/field b + CSSM_DATA c; + CSSM_DATA x1Plus; + CSSM_DATA x1Minus; + CSSM_DATA cOrderPlus; + CSSM_DATA cOrderMinus; + CSSM_DATA x1OrderPlus; + CSSM_DATA x1OrderMinus; + CSSM_DATA basePrime; // OPTIONAL +} FEECurveParametersASN1; + +extern const SecAsn1Template FEECurveParametersASN1Template[]; + +/* + -- FEE ElGamal-style signature + FEEElGamalSignature ::= SEQUENCE { + u BigIntegerStr, + pmX BigIntegerStr + } +*/ +typedef struct { + CSSM_DATA u; + CSSM_DATA pmX; +} FEEElGamalSignatureASN1; + +extern const SecAsn1Template FEEElGamalSignatureASN1Template[]; + +/* + -- FEE ECDSA-style signature + FEEECDSASignature ::= SEQUENCE { + c BigIntegerStr, + d BigIntegerStr + } +*/ +typedef struct { + CSSM_DATA c; + CSSM_DATA d; +} FEEECDSASignatureASN1; + +extern const SecAsn1Template FEEECDSASignatureASN1Template[]; + +/* + FEEPublicKey ::= SEQUENCE + { + version INTEGER, + curveParams FEECurveParameters, + plusX BigIntegerStr, + minusX BigIntegerStr, + plusY BigIntegerStr OPTIONAL + -- iff FEECurveType == ct-weierstrass +} +*/ +typedef struct { + CSSM_DATA version; + FEECurveParametersASN1 curveParams; + CSSM_DATA plusX; + CSSM_DATA minusX; + CSSM_DATA plusY; // OPTIONAL +} FEEPublicKeyASN1; + +extern const SecAsn1Template FEEPublicKeyASN1Template[]; + +/* + FEEPrivateKey ::= SEQUENCE + { + version INTEGER, + curveParams FEECurveParameters, + privData BigIntegerStr + } +*/ +typedef struct { + CSSM_DATA version; + FEECurveParametersASN1 curveParams; + CSSM_DATA privData; +} FEEPrivateKeyASN1; + +extern const SecAsn1Template FEEPrivateKeyASN1Template[]; + +#ifdef __cplusplus +} +#endif + +#endif /* CRYPTKIT_DER_ENABLE */ + +#endif /* _CRYPT_KIT_ASN1_H_ */ diff --git a/libsecurity_cryptkit/lib/CryptKitDER.cpp b/libsecurity_cryptkit/lib/CryptKitDER.cpp new file mode 100644 index 00000000..079de5b3 --- /dev/null +++ b/libsecurity_cryptkit/lib/CryptKitDER.cpp @@ -0,0 +1,1151 @@ +/* + * 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. + */ + + +/* + * CryptKitDER.h - snacc-based routines to create and parse DER-encoded FEE + * keys and signatures + * + * Created 3/12/2001 by dmitch. + */ + +#include "ckconfig.h" + +#if CRYPTKIT_DER_ENABLE + +#include +#include +#include +#include +#include "CryptKitAsn1.h" +#include +#include +#include +#include +#include + +#define PRINT_SIG_GIANTS 0 +#define PRINT_CURVE_PARAMS 0 +#define PRINT_SIZES 0 +#if PRINT_SIZES +#define szprint(s) printf s +#else +#define szprint(s) +#endif + +/* + * Trivial exception class associated with a feeReturn. + */ +class feeException +{ +protected: + feeException(feeReturn frtn, const char *op); +public: + ~feeException() throw() {} + feeReturn frtn() const throw() { return mFrtn; } + static void throwMe(feeReturn frtn, const char *op = NULL) __attribute__((noreturn)); +private: + feeReturn mFrtn; +}; + +feeException::feeException( + feeReturn frtn, + const char *op) + : mFrtn(frtn) +{ + if(op) { + dbgLog(("%s: %s\n", op, feeReturnString(frtn))); + } +} + +void feeException::throwMe(feeReturn frtn, const char *op /*= NULL*/) { throw feeException(frtn, op); } + +/* + * ASN1 encoding rules specify that an integer's sign is indicated by the MSB + * of the first (MS) content byte. For a non-negative number, if the MSB of + * the MS byte (of the unencoded number) is one, then the encoding starts with + * a byte of zeroes to indicate positive sign. For a negative number, the first + * nine bits can not be all 1 - if they are (in the undecoded number), leading + * bytes of 0xff are trimmed off until the first nine bits are something other + * than one. Also, the first nine bits of the encoded number can not all be + * zero. + * + * CryptKit giants express their sign as part of the giantstruct.sign field. + * The giantDigit array (giantstruct.n[]) is stored l.s. digit first. + * + * These routines are independent of platform, endianness, and giatn digit size. + */ + +/* routines to guess maximum size of DER-encoded objects */ +static unsigned feeSizeOfSnaccGiant( + giant g) +{ + unsigned rtn = abs(g->sign) * GIANT_BYTES_PER_DIGIT; + szprint(("feeSizeOfSnaccGiant: sign %d size %d\n", g->sign, rtn + 4)); + return rtn + 4; +} + +/* PUBLIC... */ +unsigned feeSizeOfDERSig( + giant g1, + giant g2) +{ + unsigned rtn = feeSizeOfSnaccGiant(g1); + rtn += feeSizeOfSnaccGiant(g2); + szprint(("feeSizeOfDERSig: size %d\n", rtn + 4)); + return rtn + 4; +} + +/* perform 2's complement of byte array, expressed MS byte first */ +static void twosComplement( + unsigned char *bytePtr, // points to MS byte + unsigned numBytes) +{ + unsigned char *outp = bytePtr + numBytes - 1; + unsigned char carry = 1; // first time thru, carry = 1 to add one to 1's comp + for(unsigned byteDex=0; byteDex unsigned int + */ +static unsigned cssmDataToInt( + const CSSM_DATA &cdata) +{ + if((cdata.Length == 0) || (cdata.Data == NULL)) { + return 0; + } + unsigned len = (unsigned)cdata.Length; + if(len > sizeof(int)) { + feeException::throwMe(FR_BadKeyBlob, "cssmDataToInt"); + } + + unsigned rtn = 0; + uint8 *cp = cdata.Data; + for(unsigned i=0; i CSSM_DATA, mallocing from an SecNssCoder + */ +static void intToCssmData( + unsigned num, + CSSM_DATA &cdata, + SecNssCoder &coder) +{ + unsigned len = 0; + + if(num < 0x100) { + len = 1; + } + else if(num < 0x10000) { + len = 2; + } + else if(num < 0x1000000) { + len = 3; + } + else { + len = 4; + } + cdata.Data = (uint8 *)coder.malloc(len); + cdata.Length = len; + uint8 *cp = &cdata.Data[len - 1]; + for(unsigned i=0; i>= 8; + } +} + +/* + * Convert a decoded ASN integer, as a CSSM_DATA, to a (mallocd) giant. + * Only known exception is a feeException. + */ +static giant cssmDataToGiant( + const CSSM_DATA &cdata) +{ + char *rawOcts = (char *)cdata.Data; + unsigned numBytes = cdata.Length; + unsigned numGiantDigits; + int sign = 1; + giant grtn; + feeReturn frtn = FR_Success; + unsigned char *inp = NULL; + unsigned digitDex; // index into g->giantDigit[] + + /* handle degenerate case (value of zero) */ + if((numBytes == 0) || ((numBytes == 1) && rawOcts[0] == 0)) { + grtn = newGiant(1); + if(grtn == NULL) { + feeException::throwMe(FR_Memory, "newGiant(1)"); + } + int_to_giant(0, grtn); + return grtn; + } + + /* make a copy of raw octets if we have to do two's complement */ + unsigned char *byteArray = NULL; + bool didMalloc = false; + if(rawOcts[0] & 0x80) { + sign = -1; + numBytes++; + byteArray = (unsigned char *)fmalloc(numBytes); + didMalloc = true; + byteArray[0] = 0xff; + memmove(byteArray + 1, rawOcts, numBytes-1); + twosComplement(byteArray, numBytes); + } + else { + /* no copy */ + char *foo = rawOcts; + byteArray = (unsigned char *)foo; + } + + /* cook up a new giant */ + numGiantDigits = (numBytes + GIANT_BYTES_PER_DIGIT - 1) / + GIANT_BYTES_PER_DIGIT; + grtn = newGiant(numGiantDigits); + if(grtn == NULL) { + frtn = FR_Memory; + goto abort; + } + + /* + * Convert byteArray to array of giantDigits + * inp - raw input bytes, LSB last + * grtn->n[] - output array of giantDigits, LSD first + * Start at LS byte and LD digit + */ + digitDex = 0; // index into g->giantDigit[] + giantDigit thisDigit; + inp = byteArray + numBytes - 1; + unsigned dex; // total byte counter + unsigned byteDex; // index into one giantDigit + unsigned shiftCount; + for(dex=0; dexn[digitDex++] = thisDigit; + } + grtn->sign = (int)numGiantDigits * sign; + + /* trim leading (MS) zeroes */ + gtrimSign(grtn); +abort: + if(didMalloc) { + ffree(byteArray); + } + if(frtn) { + feeException::throwMe(frtn, "bigIntStrToGiant"); + } + return grtn; +} + +/* + * Convert a giant to an CSSM_DATA, mallocing using specified coder. + * Only known exception is a feeException. + */ + static void giantToCssmData( + giant g, + CSSM_DATA &cdata, + SecNssCoder &coder) +{ + unsigned char doPrepend = 0; + unsigned numGiantDigits = abs(g->sign); + unsigned numBytes = numGiantDigits * GIANT_BYTES_PER_DIGIT; + giantDigit msGiantBit = 0; + if(isZero(g)) { + /* special degenerate case */ + intToCssmData(0, cdata, coder); + return; + } + else { + msGiantBit = g->n[numGiantDigits - 1] >> (GIANT_BITS_PER_DIGIT - 1); + } + + /* prepend a byte of zero if necessary */ + if((g->sign < 0) || // negative - to handle 2's complement + ((g->sign > 0) && msGiantBit)) { // ensure MS byte is zero + doPrepend = 1; + numBytes++; + } + + unsigned char *rawBytes = (unsigned char *)fmalloc(numBytes); + if(rawBytes == NULL) { + feeException::throwMe(FR_Memory, "giantToBigIntStr fmalloc(rawBytes)"); + } + unsigned char *outp = rawBytes; + if(doPrepend) { + *outp++ = 0; + } + + /* + * Convert array of giantDigits to bytes. + * outp point to MS output byte. + */ + int digitDex; // index into g->giantDigit[] + unsigned byteDex; // byte index into a giantDigit + for(digitDex=numGiantDigits-1; digitDex>=0; digitDex--) { + /* one loop per giantDigit, starting at MS end */ + giantDigit thisDigit = g->n[digitDex]; + unsigned char *bp = outp + GIANT_BYTES_PER_DIGIT - 1; + for(byteDex=0; byteDex>= 8; + } + outp += GIANT_BYTES_PER_DIGIT; + } + + /* do two's complement for negative giants */ + if(g->sign < 0) { + twosComplement(rawBytes, numBytes); + } + + /* strip off redundant leading bits (nine zeroes or nine ones) */ + outp = rawBytes; + unsigned char *endp = outp + numBytes - 1; + while((*outp == 0) && // m.s. byte zero + (outp < endp) && // more bytes exist + (!(outp[1] & 0x80))) { // 9th bit is 0 + outp++; + numBytes--; + } + while((*outp == 0xff) && // m.s. byte all ones + (outp < endp) && // more bytes exist + (outp[1] & 0x80)) { // 9th bit is 1 + outp++; + numBytes--; + } + cdata.Data = (uint8 *)coder.malloc(numBytes); + memmove(cdata.Data, outp, numBytes); + cdata.Length = numBytes; + ffree(rawBytes); + return; +} + +/* curveParams : CryptKit <--> FEECurveParametersASN1 */ +/* Only known exception is a feeException */ +static void feeCurveParamsToASN1( + const curveParams *cp, + FEECurveParametersASN1 &asnCp, + SecNssCoder &coder) +{ + #if PRINT_CURVE_PARAMS + printf("===encoding curveParams; cp:\n"); printCurveParams(cp); + #endif + memset(&asnCp, 0, sizeof(asnCp)); + try { + intToCssmData(cp->primeType, asnCp.primeType, coder); + intToCssmData(cp->curveType, asnCp.curveType, coder); + intToCssmData(cp->q, asnCp.q, coder); + intToCssmData(cp->k, asnCp.k, coder); + intToCssmData(cp->m, asnCp.m, coder); + giantToCssmData(cp->a, asnCp.a, coder); + giantToCssmData(cp->b, asnCp.b_, coder); + giantToCssmData(cp->c, asnCp.c, coder); + giantToCssmData(cp->x1Plus, asnCp.x1Plus, coder); + giantToCssmData(cp->x1Minus, asnCp.x1Minus, coder); + giantToCssmData(cp->cOrderPlus, asnCp.cOrderPlus, coder); + giantToCssmData(cp->cOrderMinus, asnCp.cOrderMinus, coder); + giantToCssmData(cp->x1OrderPlus, asnCp.x1OrderPlus, coder); + giantToCssmData(cp->x1OrderMinus, asnCp.x1OrderMinus, coder); + if(cp->primeType == FPT_General) { + giantToCssmData(cp->basePrime, asnCp.basePrime, coder); + } + } + catch(const feeException &ferr) { + throw; + } + catch(...) { + feeException::throwMe(FR_Memory, "feeCurveParamsToSnacc catchall"); // ??? + } +} + +static curveParams *feeCurveParamsFromAsn1( + const FEECurveParametersASN1 &asnCp) +{ + curveParams *cp = newCurveParams(); + if(cp == NULL) { + feeException::throwMe(FR_Memory, "feeCurveParamsFromSnacc alloc cp"); + } + cp->primeType = (feePrimeType)cssmDataToInt(asnCp.primeType); + cp->curveType = (feeCurveType)cssmDataToInt(asnCp.curveType); + cp->q = cssmDataToInt(asnCp.q); + cp->k = cssmDataToInt(asnCp.k); + cp->m = cssmDataToInt(asnCp.m); + cp->a = cssmDataToGiant(asnCp.a); + cp->b = cssmDataToGiant(asnCp.b_); + cp->c = cssmDataToGiant(asnCp.c); + cp->x1Plus = cssmDataToGiant(asnCp.x1Plus); + cp->x1Minus = cssmDataToGiant(asnCp.x1Minus); + cp->cOrderPlus = cssmDataToGiant(asnCp.cOrderPlus); + cp->cOrderMinus = cssmDataToGiant(asnCp.cOrderMinus); + cp->x1OrderPlus = cssmDataToGiant(asnCp.x1OrderPlus); + cp->x1OrderMinus = cssmDataToGiant(asnCp.x1OrderMinus); + if(asnCp.basePrime.Data != NULL) { + cp->basePrime = cssmDataToGiant(asnCp.basePrime); + } + + /* remaining fields inferred */ + curveParamsInferFields(cp); + allocRecipGiants(cp); + #if PRINT_CURVE_PARAMS + printf("===decoding curveParams; cp:\n"); printCurveParams(cp); + #endif + return cp; +} + +/*** + *** Public routines. These are usable from C code; they never throw. + ***/ + +/* + * Encode/decode the two FEE signature types. We malloc returned data via + * fmalloc(); caller must free via ffree(). + */ +feeReturn feeDEREncodeElGamalSignature( + giant u, + giant PmX, + unsigned char **encodedSig, // fmallocd and RETURNED + unsigned *encodedSigLen) // RETURNED +{ + /* convert to FEEElGamalSignatureASN1 */ + FEEElGamalSignatureASN1 asnSig; + SecNssCoder coder; + + try { + giantToCssmData(u, asnSig.u, coder); + giantToCssmData(PmX, asnSig.pmX, coder); + } + catch(const feeException &ferr) { + return ferr.frtn(); + } + + /* DER encode */ + PRErrorCode perr; + CSSM_DATA encBlob; // mallocd by coder + perr = coder.encodeItem(&asnSig, FEEElGamalSignatureASN1Template, encBlob); + if(perr) { + return FR_Memory; + } + + /* copy out to caller */ + *encodedSig = (unsigned char *)fmalloc(encBlob.Length); + *encodedSigLen = encBlob.Length; + memmove(*encodedSig, encBlob.Data, encBlob.Length); + + #if PRINT_SIG_GIANTS + printf("feeEncodeElGamalSignature:\n"); + printf(" u : "); printGiantHex(u); + printf(" PmX : "); printGiantHex(PmX); + #endif + + return FR_Success; +} + +feeReturn feeDEREncodeECDSASignature( + giant c, + giant d, + unsigned char **encodedSig, // fmallocd and RETURNED + unsigned *encodedSigLen) // RETURNED +{ + /* convert to FEEECDSASignatureASN1 */ + FEEECDSASignatureASN1 asnSig; + SecNssCoder coder; + + try { + giantToCssmData(c, asnSig.c, coder); + giantToCssmData(d, asnSig.d, coder); + } + catch(const feeException &ferr) { + return ferr.frtn(); + } + + /* DER encode */ + PRErrorCode perr; + CSSM_DATA encBlob; // mallocd by coder + perr = coder.encodeItem(&asnSig, FEEECDSASignatureASN1Template, encBlob); + if(perr) { + return FR_Memory; + } + + /* copy out to caller */ + *encodedSig = (unsigned char *)fmalloc(encBlob.Length); + *encodedSigLen = encBlob.Length; + memmove(*encodedSig, encBlob.Data, encBlob.Length); + + #if PRINT_SIG_GIANTS + printf("feeEncodeECDSASignature:\n"); + printf(" c : "); printGiantHex(*c); + printf(" d : "); printGiantHex(*d); + #endif + return FR_Success; + +} + +feeReturn feeDERDecodeElGamalSignature( + const unsigned char *encodedSig, + size_t encodedSigLen, + giant *u, // newGiant'd and RETURNED + giant *PmX) // newGiant'd and RETURNED +{ + FEEElGamalSignatureASN1 asnSig; + SecNssCoder coder; + + memset(&asnSig, 0, sizeof(asnSig)); + PRErrorCode perr = coder.decode(encodedSig, encodedSigLen, + FEEElGamalSignatureASN1Template, &asnSig); + if(perr) { + return FR_BadSignatureFormat; + } + + try { + *u = cssmDataToGiant(asnSig.u); + *PmX = cssmDataToGiant(asnSig.pmX); + } + catch(const feeException &ferr) { + return ferr.frtn(); + } + catch(...) { + /* FIXME - bad sig? memory? */ + return FR_Memory; + } + #if PRINT_SIG_GIANTS + printf("feeDecodeElGamalSignature:\n"); + printf(" u : "); printGiantHex(*u); + printf(" PmX : "); printGiantHex(*PmX); + #endif + return FR_Success; +} + +feeReturn feeDERDecodeECDSASignature( + const unsigned char *encodedSig, + size_t encodedSigLen, + giant *c, // newGiant'd and RETURNED + giant *d) // newGiant'd and RETURNED +{ + FEEECDSASignatureASN1 asnSig; + SecNssCoder coder; + + memset(&asnSig, 0, sizeof(asnSig)); + PRErrorCode perr = coder.decode(encodedSig, encodedSigLen, + FEEECDSASignatureASN1Template, &asnSig); + if(perr) { + return FR_BadSignatureFormat; + } + + try { + *c = cssmDataToGiant(asnSig.c); + *d = cssmDataToGiant(asnSig.d); + } + catch(const feeException &ferr) { + return ferr.frtn(); + } + catch(...) { + /* FIXME - bad sig? memory? */ + return FR_Memory; + } + #if PRINT_SIG_GIANTS + printf("feeDERDecodeECDSASignature:\n"); + printf(" u : "); printGiantHex(*u); + printf(" PmX : "); printGiantHex(*PmX); + #endif + return FR_Success; +} + +/* + * Encode/decode the FEE private and public keys. We malloc returned data via + * falloc(); caller must free via ffree(). Public C functions which never throw. + */ +feeReturn feeDEREncodePublicKey( + int version, + const curveParams *cp, + giant plusX, + giant minusX, + giant plusY, // may be NULL + unsigned char **keyBlob, // fmallocd and RETURNED + unsigned *keyBlobLen) // RETURNED +{ + FEEPublicKeyASN1 asnKey; + SecNssCoder coder; + + memset(&asnKey, 0, sizeof(asnKey)); + intToCssmData(version, asnKey.version, coder); + + try { + feeCurveParamsToASN1(cp, asnKey.curveParams, coder); + giantToCssmData(plusX, asnKey.plusX, coder); + giantToCssmData(minusX, asnKey.minusX, coder); + if(plusY != NULL) { + giantToCssmData(plusY, asnKey.plusY, coder); + } + } + catch(const feeException &ferr) { + return ferr.frtn(); + } + + /* DER encode */ + PRErrorCode perr; + CSSM_DATA encBlob; // mallocd by coder + perr = coder.encodeItem(&asnKey, FEEPublicKeyASN1Template, encBlob); + if(perr) { + return FR_Memory; + } + + /* copy out */ + *keyBlob = (unsigned char *)fmalloc(encBlob.Length); + *keyBlobLen = encBlob.Length; + memmove(*keyBlob, encBlob.Data, encBlob.Length); + return FR_Success; +} + +feeReturn feeDEREncodePrivateKey( + int version, + const curveParams *cp, + const giant privData, + unsigned char **keyBlob, // fmallocd and RETURNED + unsigned *keyBlobLen) // RETURNED +{ + FEEPrivateKeyASN1 asnKey; + SecNssCoder coder; + + memset(&asnKey, 0, sizeof(asnKey)); + intToCssmData(version, asnKey.version, coder); + + try { + feeCurveParamsToASN1(cp, asnKey.curveParams, coder); + giantToCssmData(privData, asnKey.privData, coder); + } + catch(const feeException &ferr) { + return ferr.frtn(); + } + + /* DER encode */ + PRErrorCode perr; + CSSM_DATA encBlob; // mallocd by coder + perr = coder.encodeItem(&asnKey, FEEPrivateKeyASN1Template, encBlob); + if(perr) { + return FR_Memory; + } + + /* copy out */ + *keyBlob = (unsigned char *)fmalloc(encBlob.Length); + *keyBlobLen = encBlob.Length; + memmove(*keyBlob, encBlob.Data, encBlob.Length); + return FR_Success; +} + +feeReturn feeDERDecodePublicKey( + const unsigned char *keyBlob, + unsigned keyBlobLen, + int *version, // this and remainder RETURNED + curveParams **cp, + giant *plusX, + giant *minusX, + giant *plusY) // may be NULL +{ + FEEPublicKeyASN1 asnKey; + SecNssCoder coder; + + memset(&asnKey, 0, sizeof(asnKey)); + PRErrorCode perr = coder.decode(keyBlob, keyBlobLen, + FEEPublicKeyASN1Template, &asnKey); + if(perr) { + return FR_BadKeyBlob; + } + + try { + *version = cssmDataToInt(asnKey.version); + *cp = feeCurveParamsFromAsn1(asnKey.curveParams); + *plusX = cssmDataToGiant(asnKey.plusX); + *minusX = cssmDataToGiant(asnKey.minusX); + if(asnKey.plusY.Data != NULL) { + /* optional */ + *plusY = cssmDataToGiant(asnKey.plusY); + } + else { + *plusY = newGiant(1); + int_to_giant(0, *plusY); + } + } + catch(const feeException &ferr) { + return ferr.frtn(); + } + catch(...) { + /* FIXME - bad sig? memory? */ + return FR_Memory; + } + return FR_Success; +} + +feeReturn feeDERDecodePrivateKey( + const unsigned char *keyBlob, + unsigned keyBlobLen, + int *version, // this and remainder RETURNED + curveParams **cp, + giant *privData) // RETURNED +{ + FEEPrivateKeyASN1 asnKey; + SecNssCoder coder; + + memset(&asnKey, 0, sizeof(asnKey)); + PRErrorCode perr = coder.decode(keyBlob, keyBlobLen, + FEEPrivateKeyASN1Template, &asnKey); + if(perr) { + return FR_BadKeyBlob; + } + + try { + *version = cssmDataToInt(asnKey.version); + *cp = feeCurveParamsFromAsn1(asnKey.curveParams); + *privData = cssmDataToGiant(asnKey.privData); + } + catch(const feeException &ferr) { + return ferr.frtn(); + } + catch(...) { + /* FIXME - bad sig? memory? */ + return FR_Memory; + } + return FR_Success; +} + +#pragma mark --- ECDSA support --- + +/* convert between feeDepth and curve OIDs */ +static const CSSM_OID *depthToOid( + feeDepth depth) +{ + switch(depth) { + case FEE_DEPTH_secp192r1: + return &CSSMOID_secp192r1; + case FEE_DEPTH_secp256r1: + return &CSSMOID_secp256r1; + case FEE_DEPTH_secp384r1: + return &CSSMOID_secp384r1; + case FEE_DEPTH_secp521r1: + return &CSSMOID_secp521r1; + default: + dbgLog(("depthToOid needs work\n")); + return NULL; + } +} + +static feeReturn curveOidToFeeDepth( + const CSSM_OID *curveOid, + feeDepth *depth) /* RETURNED */ +{ + if(nssCompareCssmData(curveOid, &CSSMOID_secp192r1)) { + *depth = FEE_DEPTH_secp192r1; + } + else if(nssCompareCssmData(curveOid, &CSSMOID_secp256r1)) { + *depth = FEE_DEPTH_secp256r1; + } + else if(nssCompareCssmData(curveOid, &CSSMOID_secp384r1)) { + *depth = FEE_DEPTH_secp384r1; + } + else if(nssCompareCssmData(curveOid, &CSSMOID_secp521r1)) { + *depth = FEE_DEPTH_secp521r1; + } + else { + dbgLog(("curveOidToFeeDepth: unknown curve OID\n")); + return FR_BadKeyBlob; + } + return FR_Success; +} + + +/* + * Validate a decoded CSSM_X509_ALGORITHM_IDENTIFIER and infer + * depth from its algorith.parameter + */ +static feeReturn feeAlgIdToDepth( + const CSSM_X509_ALGORITHM_IDENTIFIER *algId, + feeDepth *depth) +{ + const CSSM_OID *oid = &algId->algorithm; + /* FIXME what's the value here for a private key!? */ + if(!nssCompareCssmData(oid, &CSSMOID_ecPublicKey)) { + dbgLog(("feeAlgIdToDepth: bad OID")); + return FR_BadKeyBlob; + } + + /* + * AlgId.params is curve OID, still encoded since it's an ASN_ANY. + * First two bytes of encoded OID are (06, length) + */ + const CSSM_DATA *param = &algId->parameters; + if((param->Length <= 2) || (param->Data[0] != BER_TAG_OID)) { + dbgLog(("feeAlgIdToDepth: no curve params\n")); + return FR_BadKeyBlob; + } + + CSSM_OID decOid = {param->Length-2, algId->parameters.Data+2}; + return curveOidToFeeDepth(&decOid, depth); +} + +/* + * Prepare an CSSM_X509_ALGORITHM_IDENTIFIER for encoding. + */ +static feeReturn feeSetupAlgId( + feeDepth depth, + SecNssCoder &coder, + CSSM_X509_ALGORITHM_IDENTIFIER &algId) +{ + algId.algorithm = CSSMOID_ecPublicKey; + const CSSM_OID *curveOid = depthToOid(depth); + if(curveOid == NULL) { + return FR_IllegalDepth; + } + + /* quick & dirty encode of the parameter OID; it's an ASN_ANY in the template */ + coder.allocItem(algId.parameters, curveOid->Length + 2); + algId.parameters.Data[0] = BER_TAG_OID; + algId.parameters.Data[1] = curveOid->Length; + memmove(algId.parameters.Data+2, curveOid->Data, curveOid->Length); + return FR_Success; +} + +#pragma mark --- ECDSA public key, X.509 format --- + +/* + * Encode/decode public key in X.509 format. + */ +feeReturn feeDEREncodeX509PublicKey( + const unsigned char *pubBlob, /* x and y octet string */ + unsigned pubBlobLen, + curveParams *cp, + unsigned char **x509Blob, /* fmallocd and RETURNED */ + unsigned *x509BlobLen) /* RETURNED */ +{ + SecNssCoder coder; + CSSM_X509_SUBJECT_PUBLIC_KEY_INFO nssPubKeyInfo; + + memset(&nssPubKeyInfo, 0, sizeof(nssPubKeyInfo)); + + /* The x/y string, to be encoded in a bit string */ + nssPubKeyInfo.subjectPublicKey.Data = (uint8 *)pubBlob; + nssPubKeyInfo.subjectPublicKey.Length = pubBlobLen * 8; + + feeDepth depth; + feeReturn frtn = curveParamsDepth(cp, &depth); + if(frtn) { + dbgLog(("feeDEREncodePKCS8PrivateKey: curveParamsDepth error\n")); + return frtn; + } + + CSSM_X509_ALGORITHM_IDENTIFIER &algId = nssPubKeyInfo.algorithm; + frtn = feeSetupAlgId(depth, coder, algId); + if(frtn) { + return frtn; + } + + /* DER encode */ + CSSM_DATA encBlob; // mallocd by coder + PRErrorCode perr = coder.encodeItem(&nssPubKeyInfo, kSecAsn1SubjectPublicKeyInfoTemplate, encBlob); + if(perr) { + return FR_Memory; + } + + /* copy out */ + *x509Blob = (unsigned char *)fmalloc(encBlob.Length); + *x509BlobLen = encBlob.Length; + memmove(*x509Blob, encBlob.Data, encBlob.Length); + return FR_Success; +} + +feeReturn feeDERDecodeX509PublicKey( + const unsigned char *x509Blob, + unsigned x509BlobLen, + feeDepth *depth, /* RETURNED */ + unsigned char **pubBlob, /* x and y octet string RETURNED */ + unsigned *pubBlobLen) /* RETURNED */ +{ + SecNssCoder coder; + CSSM_X509_SUBJECT_PUBLIC_KEY_INFO nssPubKeyInfo; + PRErrorCode perr; + + memset(&nssPubKeyInfo, 0, sizeof(nssPubKeyInfo)); + perr = coder.decode(x509Blob, x509BlobLen, kSecAsn1SubjectPublicKeyInfoTemplate, + &nssPubKeyInfo); + if(perr) { + dbgLog(("decode(SubjectPublicKeyInfo) error")); + return FR_BadKeyBlob; + } + + /* verify alg identifier & depth */ + feeReturn frtn = feeAlgIdToDepth(&nssPubKeyInfo.algorithm, depth); + if(frtn) { + return frtn; + } + + /* copy public key string - it's in bits here */ + CSSM_DATA *pubKey = &nssPubKeyInfo.subjectPublicKey; + unsigned keyLen = (pubKey->Length + 7) / 8; + *pubBlob = (unsigned char *)fmalloc(keyLen); + if(*pubBlob == NULL) { + return FR_Memory; + } + memmove(*pubBlob, pubKey->Data, keyLen); + *pubBlobLen = keyLen; + return FR_Success; +} + +#pragma mark --- ECDSA keys, OpenSSL format --- + +/* + * Encode private, and decode private or public key, in unencrypted OpenSSL format. + */ +feeReturn feeDEREncodeOpenSSLPrivateKey( + const unsigned char *privBlob, /* private data octet string */ + unsigned privBlobLen, + const unsigned char *pubBlob, /* public key, optional */ + unsigned pubBlobLen, + curveParams *cp, + unsigned char **openBlob, /* fmallocd and RETURNED */ + unsigned *openBlobLen) /* RETURNED */ +{ + feeDepth depth; + const CSSM_OID *curveOid; + SecNssCoder coder; + + NSS_ECDSA_PrivateKey ecdsaPrivKey; + memset(&ecdsaPrivKey, 0, sizeof(ecdsaPrivKey)); + uint8 vers = 1; + ecdsaPrivKey.version.Data = &vers; + ecdsaPrivKey.version.Length = 1; + ecdsaPrivKey.privateKey.Data = (uint8 *)privBlob; + ecdsaPrivKey.privateKey.Length = privBlobLen; + + /* Params - ASN_ANY - actually the curve OID */ + if(curveParamsDepth(cp, &depth)) { + dbgLog(("feeDEREncodeOpenSSLPrivateKey: bad depth")); + return FR_BadKeyBlob; + } + curveOid = depthToOid(depth); + if(curveOid == NULL) { + return FR_BadKeyBlob; + } + + /* quickie DER-encode of the curve OID */ + try { + coder.allocItem(ecdsaPrivKey.params, curveOid->Length + 2); + } + catch(...) { + return FR_Memory; + } + ecdsaPrivKey.params.Data[0] = BER_TAG_OID; + ecdsaPrivKey.params.Data[1] = curveOid->Length; + memmove(ecdsaPrivKey.params.Data+2, curveOid->Data, curveOid->Length); + + /* public key - optional - bit string, length in bits */ + if(pubBlob) { + ecdsaPrivKey.pubKey.Data = (uint8 *)pubBlob; + ecdsaPrivKey.pubKey.Length = pubBlobLen * 8; + } + + CSSM_DATA encPriv = {0, NULL}; + PRErrorCode perr = coder.encodeItem(&ecdsaPrivKey, kSecAsn1ECDSAPrivateKeyInfoTemplate, encPriv); + if(perr) { + return FR_Memory; + } + + /* copy out */ + *openBlob = (unsigned char *)fmalloc(encPriv.Length); + *openBlobLen = encPriv.Length; + memmove(*openBlob, encPriv.Data, encPriv.Length); + return FR_Success; +} + +feeReturn feeDERDecodeOpenSSLKey( + const unsigned char *osBlob, + unsigned osBlobLen, + feeDepth *depth, /* RETURNED */ + unsigned char **privBlob, /* private data octet string RETURNED */ + unsigned *privBlobLen, /* RETURNED */ + unsigned char **pubBlob, /* public data octet string optionally RETURNED */ + unsigned *pubBlobLen) +{ + SecNssCoder coder; + NSS_ECDSA_PrivateKey ecdsaPrivKey; + memset(&ecdsaPrivKey, 0, sizeof(ecdsaPrivKey)); + if(coder.decode(osBlob, osBlobLen, + kSecAsn1ECDSAPrivateKeyInfoTemplate, &ecdsaPrivKey)) { + dbgLog(("Error decoding openssl priv key\n")); + return FR_BadKeyBlob; + } + + unsigned keyLen = ecdsaPrivKey.privateKey.Length; + if(keyLen == 0) { + dbgLog(("NULL priv key data in PKCS8\n")); + } + *privBlob = (unsigned char *)fmalloc(keyLen); + if(*privBlob == NULL) { + return FR_Memory; + } + *privBlobLen = keyLen; + memmove(*privBlob, ecdsaPrivKey.privateKey.Data, keyLen); + + /* curve OID --> depth */ + if(ecdsaPrivKey.params.Data != NULL) { + /* quickie decode */ + const CSSM_DATA *param = &ecdsaPrivKey.params; + if((param->Data[0] != BER_TAG_OID) || (param->Length <= 2)) { + dbgLog(("feeDERDecodeOpenSSLKey: bad curve params\n")); + return FR_BadKeyBlob; + } + CSSM_OID decOid = {param->Length-2, param->Data+2}; + if(curveOidToFeeDepth(&decOid, depth)) { + return FR_BadKeyBlob; + } + } + + /* Public key, if it's there and caller wants it */ + if((ecdsaPrivKey.pubKey.Length != 0) && (pubBlob != NULL)) { + *pubBlobLen = (ecdsaPrivKey.pubKey.Length + 7) / 8; + *pubBlob = (unsigned char *)fmalloc(*pubBlobLen); + memmove(*pubBlob, ecdsaPrivKey.pubKey.Data, *pubBlobLen); + } + return FR_Success; +} + +#pragma mark --- ECDSA public key, PKCS8 format --- + +/* + * Encode/decode private key in unencrypted PKCS8 format. + */ +feeReturn feeDEREncodePKCS8PrivateKey( + const unsigned char *privBlob, /* private data octet string */ + unsigned privBlobLen, + const unsigned char *pubBlob, /* public blob, optional */ + unsigned pubBlobLen, + curveParams *cp, + unsigned char **pkcs8Blob, /* fmallocd and RETURNED */ + unsigned *pkcs8BlobLen) /* RETURNED */ +{ + /* First encode a NSS_ECDSA_PrivateKey */ + unsigned char *encPriv = NULL; + unsigned encPrivLen = 0; + feeReturn frtn = feeDEREncodeOpenSSLPrivateKey(privBlob, privBlobLen, + pubBlob, pubBlobLen, cp, &encPriv, &encPrivLen); + if(frtn) { + return frtn; + } + + /* That encoding goes into NSS_PrivateKeyInfo.private key */ + SecNssCoder coder; + NSS_PrivateKeyInfo nssPrivKeyInfo; + CSSM_X509_ALGORITHM_IDENTIFIER &algId = nssPrivKeyInfo.algorithm; + memset(&nssPrivKeyInfo, 0, sizeof(nssPrivKeyInfo)); + nssPrivKeyInfo.privateKey.Data = (uint8 *)encPriv; + nssPrivKeyInfo.privateKey.Length = encPrivLen; + uint8 vers = 0; + + feeDepth depth; + frtn = curveParamsDepth(cp, &depth); + if(frtn) { + dbgLog(("feeDEREncodePKCS8PrivateKey: curveParamsDepth error\n")); + goto errOut; + } + frtn = feeSetupAlgId(depth, coder, algId); + if(frtn) { + goto errOut; + } + + nssPrivKeyInfo.version.Data = &vers; + nssPrivKeyInfo.version.Length = 1; + + /* DER encode */ + CSSM_DATA encPrivInfo; // mallocd by coder + if(coder.encodeItem(&nssPrivKeyInfo, kSecAsn1PrivateKeyInfoTemplate, encPrivInfo)) { + frtn = FR_Memory; + goto errOut; + } + + /* copy out */ + *pkcs8Blob = (unsigned char *)fmalloc(encPrivInfo.Length); + *pkcs8BlobLen = encPrivInfo.Length; + memmove(*pkcs8Blob, encPrivInfo.Data, encPrivInfo.Length); +errOut: + if(encPriv) { + ffree(encPriv); + } + return frtn; +} + +feeReturn feeDERDecodePKCS8PrivateKey( + const unsigned char *pkcs8Blob, + unsigned pkcs8BlobLen, + feeDepth *depth, /* RETURNED */ + unsigned char **privBlob, /* private data octet string RETURNED */ + unsigned *privBlobLen, /* RETURNED */ + unsigned char **pubBlob, /* optionally returned, if it's there */ + unsigned *pubBlobLen) +{ + NSS_PrivateKeyInfo nssPrivKeyInfo; + PRErrorCode perr; + SecNssCoder coder; + + memset(&nssPrivKeyInfo, 0, sizeof(nssPrivKeyInfo)); + perr = coder.decode(pkcs8Blob, pkcs8BlobLen, kSecAsn1PrivateKeyInfoTemplate, &nssPrivKeyInfo); + if(perr) { + dbgLog(("Error decoding top level PKCS8\n")); + return FR_BadKeyBlob; + } + + /* verify alg identifier & depth */ + feeReturn frtn = feeAlgIdToDepth(&nssPrivKeyInfo.algorithm, depth); + if(frtn) { + return frtn; + } + + /* + * nssPrivKeyInfo.privateKey is an octet string containing an encoded + * NSS_ECDSA_PrivateKey. + */ + frtn = feeDERDecodeOpenSSLKey((const unsigned char *)nssPrivKeyInfo.privateKey.Data, + nssPrivKeyInfo.privateKey.Length, depth, + privBlob, privBlobLen, + pubBlob, pubBlobLen); + + return frtn; +} + +#endif /* CRYPTKIT_DER_ENABLE */ diff --git a/libsecurity_cryptkit/lib/CryptKitDER.h b/libsecurity_cryptkit/lib/CryptKitDER.h new file mode 100644 index 00000000..9ecd44b1 --- /dev/null +++ b/libsecurity_cryptkit/lib/CryptKitDER.h @@ -0,0 +1,162 @@ +/* + * CryptKitDER.h - snacc-based routines to create and parse DER-encoded FEE + * keys and signatures + * + * Created 3/12/2001 by dmitch. + */ + +#ifndef _CRYPTKIT_DER_H_ +#define _CRYPTKIT_DER_H_ + +#include + +#if CRYPTKIT_DER_ENABLE + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Encode/decode the two FEE signature types. We malloc returned data via + * falloc(); caller must free via ffree(). + */ +feeReturn feeDEREncodeElGamalSignature( + giant u, + giant PmX, + unsigned char **encodedSig, // fallocd and RETURNED + unsigned *encodedSigLen); // RETURNED + +feeReturn feeDEREncodeECDSASignature( + giant c, + giant d, + unsigned char **encodedSig, // fallocd and RETURNED + unsigned *encodedSigLen); // RETURNED + +feeReturn feeDERDecodeElGamalSignature( + const unsigned char *encodedSig, + size_t encodedSigLen, + giant *u, // newGiant'd and RETURNED + giant *PmX); // newGiant'd and RETURNED + +feeReturn feeDERDecodeECDSASignature( + const unsigned char *encodedSig, + size_t encodedSigLen, + giant *c, // newGiant'd and RETURNED + giant *d); // newGiant'd and RETURNED + +/* + * Encode/decode the FEE private and public keys. We malloc returned data via + * falloc(); caller must free via ffree(). + * These use a DER format which is custom to this module. + */ +feeReturn feeDEREncodePublicKey( + int version, + const curveParams *cp, + giant plusX, + giant minusX, + giant plusY, // may be NULL + unsigned char **keyBlob, // fmallocd and RETURNED + unsigned *keyBlobLen); // RETURNED + +feeReturn feeDEREncodePrivateKey( + int version, + const curveParams *cp, + const giant privData, + unsigned char **keyBlob, // fmallocd and RETURNED + unsigned *keyBlobLen); // RETURNED + +feeReturn feeDERDecodePublicKey( + const unsigned char *keyBlob, + unsigned keyBlobLen, + int *version, // this and remainder RETURNED + curveParams **cp, + giant *plusX, + giant *minusX, + giant *plusY); // always valid, may be (giant)0 + +feeReturn feeDERDecodePrivateKey( + const unsigned char *keyBlob, + unsigned keyBlobLen, + int *version, // this and remainder RETURNED + curveParams **cp, + giant *privData); // RETURNED + +/* obtain the max size of a DER-encoded signature (either ElGamal or ECDSA) */ +unsigned feeSizeOfDERSig( + giant g1, + giant g2); + +/* + * Encode/decode public key in X.509 format. + */ +feeReturn feeDEREncodeX509PublicKey( + const unsigned char *pubBlob, /* x and y octet string */ + unsigned pubBlobLen, + curveParams *cp, + unsigned char **x509Blob, /* fmallocd and RETURNED */ + unsigned *x509BlobLen); /* RETURNED */ + +feeReturn feeDERDecodeX509PublicKey( + const unsigned char *x509Blob, + unsigned x509BlobLen, + feeDepth *depth, /* RETURNED */ + unsigned char **pubBlob, /* x and y octet string RETURNED */ + unsigned *pubBlobLen); /* RETURNED */ + +/* + * Encode private, and decode private or public key, in unencrypted OpenSSL format. + */ +feeReturn feeDEREncodeOpenSSLPrivateKey( + const unsigned char *privBlob, /* private data octet string */ + unsigned privBlobLen, + const unsigned char *pubBlob, /* public key, optional */ + unsigned pubBlobLen, + curveParams *cp, + unsigned char **openBlob, /* fmallocd and RETURNED */ + unsigned *openBlobLen); /* RETURNED */ + +feeReturn feeDERDecodeOpenSSLKey( + const unsigned char *osBlob, + unsigned osBlobLen, + feeDepth *depth, /* RETURNED */ + unsigned char **privBlob, /* private data octet string RETURNED */ + unsigned *privBlobLen, /* RETURNED */ + unsigned char **pubBlob, /* public data octet string optionally RETURNED */ + unsigned *pubBlobLen); + +/* + * Encode/decode private key in unencrypted PKCS8 format. + */ +feeReturn feeDEREncodePKCS8PrivateKey( + const unsigned char *privBlob, /* private data octet string */ + unsigned privBlobLen, + const unsigned char *pubBlob, /* public blob, optional */ + unsigned pubBlobLen, + curveParams *cp, + unsigned char **pkcs8Blob, /* fmallocd and RETURNED */ + unsigned *pkcs8BlobLen); /* RETURNED */ + +feeReturn feeDERDecodePKCS8PrivateKey( + const unsigned char *pkcs8Blob, + unsigned pkcs8BlobLen, + feeDepth *depth, /* RETURNED */ + unsigned char **privBlob, /* private data octet string RETURNED */ + unsigned *privBlobLen, /* RETURNED */ + unsigned char **pubBlob, /* optionally returned, if it's there */ + unsigned *pubBlobLen); + + +#ifdef __cplusplus +} +#endif + +#endif /* CRYPTKIT_DER_ENABLE */ +#endif /* _CRYPTKIT_DER_H_ */ + + diff --git a/libsecurity_cryptkit/lib/CryptKitSA.h b/libsecurity_cryptkit/lib/CryptKitSA.h new file mode 100644 index 00000000..ea9ace18 --- /dev/null +++ b/libsecurity_cryptkit/lib/CryptKitSA.h @@ -0,0 +1,23 @@ +/* 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/CurveParamDocs/FEEDaffine.nb b/libsecurity_cryptkit/lib/CurveParamDocs/FEEDaffine.nb new file mode 100644 index 00000000..19592d36 --- /dev/null +++ b/libsecurity_cryptkit/lib/CurveParamDocs/FEEDaffine.nb @@ -0,0 +1,253 @@ +(*********************************************************************** + + Mathematica-Compatible Notebook + +This notebook can be used on any computer system with Mathematica 3.0, +MathReader 3.0, or any compatible application. The data for the notebook +starts with the line of stars above. + +To get the notebook into a Mathematica-compatible application, do one of +the following: + +* Save the data starting with the line of stars above into a file + with a name ending in .nb, then open the file inside the application; + +* Copy the data starting with the line of stars above to the + clipboard, then use the Paste menu command inside the application. + +Data for notebooks contains only printable 7-bit ASCII and can be +sent directly in email or through ftp in text mode. Newlines can be +CR, LF or CRLF (Unix, Macintosh or MS-DOS style). + +NOTE: If you modify the data for this notebook not in a Mathematica- +compatible application, you must delete the line below containing the +word CacheID, otherwise Mathematica-compatible applications may try to +use invalid cache data. + +For more information on notebooks and Mathematica-compatible +applications, contact Wolfram Research: + web: http://www.wolfram.com + email: info@wolfram.com + phone: +1-217-398-0700 (U.S.) + +Notebook reader applications are available free of charge from +Wolfram Research. +***********************************************************************) + +(*CacheID: 232*) + + +(*NotebookFileLineBreakTest +NotebookFileLineBreakTest*) +(*NotebookOptionsPosition[ 10630, 213]*) +(*NotebookOutlinePosition[ 11308, 238]*) +(* CellTagsIndexPosition[ 11264, 234]*) +(*WindowFrame->Normal*) + + + +Notebook[{ +Cell[BoxData[ + \(\( (*\n\ + Algorithm\ 8.1 .10\ + \((Direct - embedding\ ECC\ encryption)\) . \t\t\t\n\ Support\ code\ + for\n\ R . \ Crandall\ and\ C . \ Pomerance, \n\ + "\"\n\ Springer - + Verlag\ 2001. \n\ c . \ 2000\ Perfectly\ Scientific, \ + Inc . \n\ All\ Rights\ Reserved . \n\t\n\t20\ Apr\ 2001\ RC\ + \((revamped\ for\ simplicity)\)\n\ 10\ Dec\ 2000\ AH\ + \((Formatting)\)\n\t14\ Sep\ 2000\ RT\ \((Creation)\)\n*) \n\)\)], + "Input"], + +Cell[BoxData[{ + \( (*\ CODE\ *) \n + \[IndentingNewLine] (*\ + We\ include\ functions\ from\ algorithm\ 7.2 .2\ for\ performing\ + elliptic\ \n\(arithmetic . \)\ *) \n + \n (*\ Next, \ + a\ function\ that\ negates\ a\ point\ pt\ on\ an\ elliptic\ + \(curve . \)\ *) \n + ellneg[pt_]\ := \ Mod[pt\ *\ {1, \(-1\), \ 1}, \ p]; \n + \n (*\ Next, \ elliptic\ subtraction\ pt1 - \(pt2 . \)\ *) \n + \(ellsub[pt1_, \ pt2_]\ := \ elladd[pt1, \ ellneg[pt2]]; \)\n + \n (*\ Next, \ the\ double\ of\ a\ \(point . \)\ *) \), + \(elldouble[pt_]\ := \ elladd[pt, pt]; \n + \n (*\ Next, \ elliptic\ addition\ pt1 + \(pt2 . \)\ *) \n\n\n + \(elladd[pt1_, \ pt2_]\ := \ \n\t + Block[{x1, y1, x2, y2, x3, y3, m}, \n\t\t + If[pt1[\([3]\)]\ == \ 0, \ Return[pt2]]; \n\t\t + If[pt2[\([3]\)]\ == \ 0, \ Return[pt1]]; \n\t\t + x1\ = \ pt1[\([1]\)]; \ y1\ = \ pt1[\([2]\)]; \n\t\t + x2\ = \ pt2[\([1]\)]; \ y2\ = \ pt2[\([2]\)]; \n\t\t + If[x1\ == \ x2, \ \n\t\t\t + If[Mod[y1 + y2, p] == 0, \ Return[{1, 1, 0}]]; \n\t\t\t + m\ = \ Mod[\((3\ x1^2\ + \ a)\)\ *\ PowerMod[2 y1, \(-1\), p], \ + p], \n\t\t\t + m\ = \ Mod[\((y2 - y1)\)\ PowerMod[x2 - x1, \(-1\), p], p]\n\t\t]; + \n\t\tx3\ = \ Mod[m^2\ - \ x1\ - \ x2, p]; \n\t\t + y3\ = \ Mod[m \((x1 - x3)\)\ - \ y1, \ p]; \n\t\t + Return[{x3, y3, 1}]\n\t]; \)\n\ \ + \n (*\ Next, \ elliptic - multiply\ a\ point\ pt\ by\ \(k . \)\ *) \), + \(\n\nelliptic[pt_, \ k_]\ := \ \n\t + Block[{hh, \ kk, pt2, lenh, \ lenk, \ hb, \ kb}, \n\t\t + If[k == 0, \ Return[{1, 1, 0}]]; \n\t\t + hh\ = \ Reverse[IntegerDigits[3 k, 2]]; \n\t\t + kk\ = \ Reverse[IntegerDigits[k, 2]]; \n\t\tpt2\ = \ pt; \n\t\t + lenh\ = \ Length[hh]; \n\t\tlenk\ = \ Length[kk]; \n\t\t + Do[\n\t\t\tpt2\ = \ elldouble[pt2]; \n\t\t\thb\ = \ hh[\([b]\)]; \n + \t\t\tIf[b\ <= \ lenk, \ kb\ = \ kk[\([b]\)], \ kb\ = \ 0]; \n + \t\t\tIf[{hb, kb}\ == \ {1, 0}, \n\t\t\t\t + pt2\ = \ elladd[pt2, \ pt], \n\t\t\t\t + If[{hb, \ kb}\ == \ {0, 1}, \n\t\t\t\t + pt2\ = \ ellsub[pt2, \ pt]]\n\t\t\t]\n\t\t\t, \n + \t\t\t{b, \ lenh - 1, \ 2, \(-1\)}\n\t\t\ ]; \n\tReturn[pt2]\n]\n + \n (*\ Next, \ + we\ include\ algorithm\ 2.3 .8\ for\ finding\ square\ roots\ \nmodulo\ + a\ prime\ p, \ + to\ be\ used\ to\ seek\ out\ valid\ y - + coordinates\ on\ \(curves . \)\ *) \n\), + \(sqrtmod[b_, p_] := \ \n\t + Module[{a, x, c, d, cd, m, t, tst}, \n\ \ \ \t\ta\ = \ Mod[b, p]; \n + \ \ \ \t\tIf[p\ == \ 2, \ Return[a]]; \n\ \ \ \ \t + If[MemberQ[{3, 7}, Mod[p, 8]], \n\ \ \ \ \ \ \t\t + Return[PowerMod[a, \((p + 1)\)/4, p]]\n\ \ \ \ \ \ \t]; \n\ \ \ \ \t + If[Mod[p, 8]\ == \ 5, \n\ \ \ \ \ \ \t\t + x\ = \ PowerMod[a, \((p + 3)\)/8, p]; \n\ \ \ \ \ \ \t\t + c\ = \ Mod[x^2, p]; \n\ \ \ \ \ \ \t\t + If[Not[c\ == \ a], \n\ \ \ \ \ \ \ \ \t\t + Return[Mod[x\ PowerMod[2, \((p - 1)\)/4, p], \ p]]\n + \ \ \ \ \ \ \ \ \t]; \n\ \ \ \ \ \ \t]; \n\ \ \ \ \t\n + \ \ \ \ \t (*\ Here, \ p\ = \ 1\ \(\((mod\ 8)\) . \)\ *) \n + \ \ \ \ \ \ \ttst\ = \ 1; \n\ \ \ \ \ \ \t + While[Not[tst\ == \ \(-1\)], \n\ \ \ \ \ \ \ \ \t + d\ = \ Random[Integer, {1, p}]; \n\ \ \ \ \ \ \ \ \t + tst\ = \ JacobiSymbol[d, p]\n\ \ \ \ \ \ \ \ ]; \n\ \ \ \ \ \ \t + t\ = \ \((p - 1)\)/2; \ s\ = \ 1; \n\ \ \ \ \ \ \t + While[EvenQ[t], \ t\ = \ t/2; \ \(++s\)]; \n\ \ \ \ \ \ \t + ca\ = \ PowerMod[a, t, p]; \n\ \ \ \ \ \ \t + cd\ = \ PowerMod[d, t, p]; \n\ \ \ \ \ \ \tm\ = \ 0; \n + \ \ \ \ \ \ \t + Do[\n\ \ \ \ \ \ \t\ \ \ + If[PowerMod[Mod[ca\ PowerMod[cd, \ m, \ p], p], \ + 2^\((s - 1 - i)\), \ p]\n\ \ \ \ \ \ \t\ \ \ \t\t == \ p - 1, + \ m\ += \ 2^i]\n\ \ \ \ \ \ \t\ \ \ , {i, 0, s - 1}\n + \ \ \ \ \ \ \t]; \ \ \ \ \ \ \t\ \ \ \ \n\ \ \ \ \ \ \t + Return[Mod[PowerMod[a, \ \((t + 1)\)/2, p]\ PowerMod[cd, \ m/2, p], + p]]; \ \n\t]; \n\n + \n (*\ Now, \ + the\ main\ routine . \ Parameters\ are\ given\ for\ 161 - + bit\ prime\ field\n\t\t\tand\ specific\ curve; \n\t\ \ + direct\ embedding\ proceeds\ on\ "\"\ integers\ x\ + \((mod\ p)\) . \ \n\ \ \ We\ start\ with\ relevant\ global\ + \((and\ public, \ except\ for\ kb)\)\n\ \ \ parameters\n\ *) \n + \[IndentingNewLine]p\ = \ + 1654338658923174831024422729553880293604080853451; \nA\ = \ \(-152\); + \nB\ = \ 722; \ng\ = \ \(-1\); + \ \ (*\ Quadratic\ nonresidue\ \((mod\ p)\)\ for\ this\ case, \ + as\ p\ = \ 3\ \(\((mod\ 4)\) . \)\ *) \n + Atwist\ = \ Mod[A\ \ Mod[h\ = \ g^2, p], \ p]; \n + Btwist\ = \ Mod[B\ \ Mod[h\ g, p], p]; \n + \n (*\ Next, \ + create\ public\ point\ P\ of\ prime\ order\ on\ main\ \(curve . \)\ *) + \nx1 = \ 124590448755381588517063157600522073397838354227; \ \ \n + pubpoint\ = + \ {x1, \ sqrtmod[Mod[x1\ Mod[x1^2\ + \ A, p]\ + \ B, p], \ p], 1}; \n + \n (*\ Next, \ + create\ public\ point\ P'\ of\ prime\ order\ on\ twist\ + \(curve . \)\ *) \n + x1twist\ = \ 480775151193986876474195670157924389403361833567; \n + pubpointtwist\ = + \ {x1twist, \ + sqrtmod[Mod[x1twist\ Mod[x1twist^2\ + \ Atwist, p]\ + \ Btwist, p], + \ p], 1}; \n\nkb\ = \ 968525826201321079923232842886222248; + \ \ (*\ Private\ key\ \(K_B . \)\ *) \n\n{a, b}\ = \ {A, B}; + \ \ (*\ Prepare\ elliptic\ algebra\ for\ main\ \(curve . \)\ *) \n + pubkey\ = \ \ \ elliptic[pubpoint, \ kb]; + \ \ \ \ \ \ \ \ (*\ Public\ key\ \(P_B . \)\ *) \n\ + \n{a, b}\ = \ {Atwist, \ Btwist}; + \ \ \ (*\ Prepare\ elliptic\ algebra\ for\ twist\ \(curve . \)\ *) \n + pubkeytwist\ = \ \telliptic[pubpointtwist, \ kb]; + \ \ \ \ \ (*\ Public\ key\ \(P_B' . \)\ *) \n\ \n\t\t\n + encryptEmbed[x_] := \ + Module[{cubic, \ curve, \ X\ = \ x, \ Y, \ pbk, \ X1}, + \[IndentingNewLine] (*\ First, \ + let\ us\ determine\ which\ curve . \ \n\t\t\ \ \ EITHER\ X\ lies\ in + \ the\ curve\ y^2\ = \ X^3\ + \ A\ X\ + \ B, \n\t\t\ \ \ + or\ Xt\ := \ + \(g\ X\ lies\ on\ y^2\ = \ + Xt^3\ + \ Atwist\ Xt\ + \ Btwist\)\ *) \n\t\t\ + cubic\ = \ Mod[X\ Mod[X^2\ + \ A, p]\ + \ B, p]; \n\t\t\ + If[JacobiSymbol[cubic, \ p]\ > \ \(-1\), \ \n\t\t\t\ \ \ \ \ \ + curve\ = \ 1; \ {a, b}\ = \ {A, B}; \ pbk\ = \ pubkey; \ + pbp\ = \ pubpoint, \t\t\t\ \ \ \ \ \ \n\t\t\t\t\ \ \ \ \ + curve\ = \ \(-1\); \ {a, b}\ = \ {Atwist, \ Btwist}; \ + pbk\ = \ pubkeytwist; \ pbp\ = \ pubpointtwist; \ \n + \t\t\t\t\t\t\t\t\tX\ = \ g\ X; \ \n\t\t\ \ \ \ \ \ \ + cubic\ = \ Mod[X\ Mod[X^2\ + \ Atwist, p]\ + \ Btwist, p]\n + \t\t\ \ ]; \n\t\t\ \ Y\ = \ sqrtmod[cubic, \ p]; \ \ \n + \t\t\t (*\ + Now\ we\ \(have : \ \n\t\t\t\t\t\t\ \ + \((X\ = \ x, Y)\)\ or\ \((X\ = \ g\ x, \ Y)\) lies\ on\ the\ + respective\ curve\); \n\t\t\t\t\ \ \ \ + \((a, b)\)\ parameters\ are\ set\ up\ for\ respective\ + \(curve . \)\ *) \n\t\t\t\ \n\t\t\t + r\ = \ Random[Integer, \ {2, p - 2}]; \n\t\t\t + u\ = \ elladd[elliptic[pbk, \ r], \ {X, \ Y, 1}]; \n\t\t\t + c\ = \ elliptic[pbp, \ r]; \n + \t\t\ \ {u, \ c, \ curve}\[IndentingNewLine]]; \[IndentingNewLine]\n + decryptEmbed[cipherList_] := \ + Module[{u\ = \ cipherList[\([1]\)], \ c\ = \ cipherList[\([2]\)], \ + curve\ = \ cipherList[\([3]\)]}, + \[IndentingNewLine]If[curve\ == \ 1, \n + \t\t\t\t{a, b}\ = \ {A, \ B}, \n + \t\t\t\ \ {a, b}\ = \ {Atwist, \ Btwist}\n\t\t\ \ \ ]; \n\t\t + X\ = \ \(ellsub[u, \ elliptic[c, \ kb]]\)[\([1]\)]; \n\t\t + If[curve\ != \ 1, \ X\ = \ Mod[X\ PowerMod[g, \(-1\), \ p], p]]; \n + \t\t\tX\[IndentingNewLine]]; \[IndentingNewLine]\n\)}], "Input"], + +Cell[BoxData[{ + \( (*\ EXAMPLE\ *) \ \n\n + \[IndentingNewLine]ciph\ = \ + encryptEmbed[plain\ = \ 1324578918324567]\), + \(decryptEmbed[ciph]\)}], "Input"] +}, +FrontEndVersion->"NeXT 3.0", +ScreenRectangle->{{0, 957}, {0, 768}}, +WindowToolbars->{}, +WindowSize->{762, 676}, +WindowMargins->{{Automatic, 45}, {Automatic, 0}}, +ShowCellLabel->False +] + + +(*********************************************************************** +Cached data follows. If you edit this Notebook file directly, not using +Mathematica, you must remove the line containing CacheID at the top of +the file. The cache data will then be recreated when you save this file +from within Mathematica. +***********************************************************************) + +(*CellTagsOutline +CellTagsIndex->{} +*) + +(*CellTagsIndex +CellTagsIndex->{} +*) + +(*NotebookFileOutline +Notebook[{ +Cell[1709, 49, 546, 10, 202, "Input"], +Cell[2258, 61, 8194, 144, 2206, "Input"], +Cell[10455, 207, 171, 4, 78, "Input"] +} +] +*) + + + + +(*********************************************************************** +End of Mathematica Notebook file. +***********************************************************************) + diff --git a/libsecurity_cryptkit/lib/CurveParamDocs/FEEDsansY.nb b/libsecurity_cryptkit/lib/CurveParamDocs/FEEDsansY.nb new file mode 100644 index 00000000..386f29ae --- /dev/null +++ b/libsecurity_cryptkit/lib/CurveParamDocs/FEEDsansY.nb @@ -0,0 +1,324 @@ +(*********************************************************************** + + Mathematica-Compatible Notebook + +This notebook can be used on any computer system with Mathematica 3.0, +MathReader 3.0, or any compatible application. The data for the notebook +starts with the line of stars above. + +To get the notebook into a Mathematica-compatible application, do one of +the following: + +* Save the data starting with the line of stars above into a file + with a name ending in .nb, then open the file inside the application; + +* Copy the data starting with the line of stars above to the + clipboard, then use the Paste menu command inside the application. + +Data for notebooks contains only printable 7-bit ASCII and can be +sent directly in email or through ftp in text mode. Newlines can be +CR, LF or CRLF (Unix, Macintosh or MS-DOS style). + +NOTE: If you modify the data for this notebook not in a Mathematica- +compatible application, you must delete the line below containing the +word CacheID, otherwise Mathematica-compatible applications may try to +use invalid cache data. + +For more information on notebooks and Mathematica-compatible +applications, contact Wolfram Research: + web: http://www.wolfram.com + email: info@wolfram.com + phone: +1-217-398-0700 (U.S.) + +Notebook reader applications are available free of charge from +Wolfram Research. +***********************************************************************) + +(*CacheID: 232*) + + +(*NotebookFileLineBreakTest +NotebookFileLineBreakTest*) +(*NotebookOptionsPosition[ 12180, 264]*) +(*NotebookOutlinePosition[ 12859, 289]*) +(* CellTagsIndexPosition[ 12815, 285]*) +(*WindowFrame->Normal*) + + + +Notebook[{ +Cell[BoxData[ + \(\( (*\n\tNo - Y - coordinate\ version\ of\ Algorithm\ 8.1 .10; \n\t + see\ program\ 8.1 .10 . directembed . nb\n\t\t\t\n\n\ Support\ code\ + for\n\ R . \ Crandall\ and\ C . \ Pomerance, \n\ + "\"\n\ Springer - + Verlag\ 2001. \n\ c . \ 2000\ Perfectly\ Scientific, \ + Inc . \n\ All\ Rights\ Reserved . \n\t\n\t20\ Apr\ 2001\ RC\ + \((revamped\ for\ simplicity)\)\n\ 10\ Dec\ 2000\ AH\ + \((Formatting)\)\n\t14\ Sep\ 2000\ RT\ \((Creation)\)\n*) \n\)\)], + "Input"], + +Cell[CellGroupData[{ + +Cell[BoxData[ + \(\( (*\ CODE\ *) \n + \n (*\ First, \ a\ function\ for\ inverting\ n\ mod\ \(p . \)\ *) \n + ellinv[n_]\ := \ If[n == 0, 0, PowerMod[n, \(-1\), p]]; \n + \n (*\ Next, \ + a\ function\ for\ normalizing\ the\ x\ \(coordinate . \)\ *) \n + ex[pt_]\ := \ Mod[pt[\([1]\)]\ *\ ellinv[pt[\([2]\)]], \ p]; \n + \n (*\ Next, \ + the\ doubleh \(()\)\ function\ for\ doubling\ a\ \(point . \)\ *) \n + elleven[pt_]\ := \ \n\t + Block[{x1\ = \ pt[\([1]\)], \ z1\ = \ pt[\([2]\)], \ e, \ f\ }, \n + \ \ \t\te\ = \ + Mod[\((x1^2\ - \ a\ z1^2)\)^2\ - \ + 4\ b\ \((2\ x1\ + \ c\ z1)\)\ z1^3, \ p]; \n\ \ \t\t + f\ = \ Mod[ + 4\ z1\ \((x1^3\ + \ c\ x1^2\ z1\ + \ a\ x1\ z1^2\ + \ b\ z1^3) + \), \ p]; \n\ \ \t\t{e, f}\n\t]; \n + \n (*\ Next, \ + the\ addh \(()\)\ function\ for\ adding\ pt\ and\ pu\ with\ pv\ = \ + pt - pu\ known\ \n + \(\((x\ and\ z\ coordinates\ only\ of\ course)\) . \)\ *) \n + ellodd[pt_, \ pu_, \ pv_]\ := \ \n\t + Block[\n\t\t{x1\ = \ pt[\([1]\)], \ z1\ = \ pt[\([2]\)], \n\t\t\ + x2\ = \ pu[\([1]\)], \ z2\ = \ pu[\([2]\)], \n\t\t\ + xx\ = \ pv[\([1]\)], \ zz\ = \ pv[\([2]\)], \ i, \ j\n\t\t\ }, \n + \ \ \t\ \ \ \ \ + i\ = \ Mod[ + zz\ \((\((x1\ x2\ - \ a\ z1\ z2)\)^2\ - \n + \ \ \t\ \ \ \ \ \ \ \ \ \ \t + 4\ b \((x1\ z2\ + \ x2\ z1\ + \ c\ z1\ z2)\)\ z1\ z2)\), + \ \n\ \ \t\ \ \ \ \ \ \ \ \ \ \tp\n\ \ \t\ \ \ \ \ \ \ \ \ ]; \n + \ \ \t\ \ \ \ \ j\ = \ Mod[xx\ \((x1\ z2\ - \ x2\ z1)\)^2, \ p]; \n + \ \ \t\t\ {i, j}\n\t]; \n + \n (*\ Now, \ the\ main\ routine, \ elliptic\ multiply\ [k] \(pt . \)\ *) + \nelliptic[pt_, \ k_]\ := \ \n\t + Block[{porg, \ ps, \ pp, \ q}, \n\t\tIf[k\ == 1, \ Return[pt]]; \n\t\t + If[k\ == 2, \ Return[elleven[pt]]]; \n\t\tporg\ = \ pt; \n\t\t + ps\ = \ elleven[pt]; \n\t\tpp\ = \ pt; \n\t\t + bitlist\ = \ Reverse[IntegerDigits[k, 2]]; \n\t\t + Do[\t\ \ \ \n\t\ \ \ \t\t + If[bitlist[\([q]\)]\ == \ 1, \n\t\ \ \ \t\ \ \ \t\t + pp\ = \ ellodd[ps, \ pp, \ porg]; \n\t\ \ \ \t\ \ \ \t\t + ps\ = \ elleven[ps]\n\t\ \ \ \t\ \ \ \t\t, \n + \t\ \ \ \t\ \ \ \ \ \ \tps\ = \ ellodd[pp, \ ps, \ porg]; \n + \t\t\ \ \ \ \ \tpp\ = \ elleven[pp]\n\t\ \ \ \t\t]\n + \t\ \ \ \t\t, \n + \t\ \ \ \t\t{q, \ Length[bitlist] - 1, \ 1, \ \(-1\)}\n\ \ \ \ \t]; + \n\ \ \ \ \tReturn[Mod[pp, p]]\n\t]; \n + \n (*\ Next, \ + we\ include\ algorithm\ 2.3 .8\ for\ finding\ square\ roots\ \nmodulo\ + a\ prime\ \(p . \)\ *) \n\n + sqrtmod[b_, p_] := \ \n\t + Module[{a, x, c, d, cd, m, t, tst}, \n\ \ \ \t\ta\ = \ Mod[b, p]; \n + \ \ \ \t\tIf[p\ == \ 2, \ Return[a]]; \n\ \ \ \ \t + If[MemberQ[{3, 7}, Mod[p, 8]], \n\ \ \ \ \ \ \t\t + Return[PowerMod[a, \((p + 1)\)/4, p]]\n\ \ \ \ \ \ \t]; \n\ \ \ \ \t + If[Mod[p, 8]\ == \ 5, \n\ \ \ \ \ \ \t\t + x\ = \ PowerMod[a, \((p + 3)\)/8, p]; \n\ \ \ \ \ \ \t\t + c\ = \ Mod[x^2, p]; \n\ \ \ \ \ \ \t\t + If[Not[c\ == \ a], \n\ \ \ \ \ \ \ \ \t\t + Return[Mod[x\ PowerMod[2, \((p - 1)\)/4, p], \ p]]\n + \ \ \ \ \ \ \ \ \t]; \n\ \ \ \ \ \ \t]; \n\ \ \ \ \t\n + \ \ \ \ \t (*\ Here, \ p\ = \ 1\ \(\((mod\ 8)\) . \)\ *) \n + \ \ \ \ \ \ \ttst\ = \ 1; \n\ \ \ \ \ \ \t + While[Not[tst\ == \ \(-1\)], \n\ \ \ \ \ \ \ \ \t + d\ = \ Random[Integer, {1, p}]; \n\ \ \ \ \ \ \ \ \t + tst\ = \ JacobiSymbol[d, p]\n\ \ \ \ \ \ \ \ ]; \n\ \ \ \ \ \ \t + t\ = \ \((p - 1)\)/2; \ s\ = \ 1; \n\ \ \ \ \ \ \t + While[EvenQ[t], \ t\ = \ t/2; \ \(++s\)]; \n\ \ \ \ \ \ \t + ca\ = \ PowerMod[a, t, p]; \n\ \ \ \ \ \ \t + cd\ = \ PowerMod[d, t, p]; \n\ \ \ \ \ \ \tm\ = \ 0; \n + \ \ \ \ \ \ \t + Do[\n\ \ \ \ \ \ \t\ \ \ + If[PowerMod[Mod[ca\ PowerMod[cd, \ m, \ p], p], \ + 2^\((s - 1 - i)\), \ p]\n\ \ \ \ \ \ \t\ \ \ \t\t == \ p - 1, + \ m\ += \ 2^i]\n\ \ \ \ \ \ \t\ \ \ , {i, 0, s - 1}\n + \ \ \ \ \ \ \t]; \ \ \ \ \ \ \t\ \ \ \ \n\ \ \ \ \ \ \t + Return[Mod[PowerMod[a, \ \((t + 1)\)/2, p]\ PowerMod[cd, \ m/2, p], + p]]; \ \n\t]; \n + \n (*\ Next, \ a\ function\ relevant\ to\ Algorithm\ 7.2 \( .8 . \)\ *) \n + \nellXadd[x1_, x2_] := \n\t + Module[{u2, v, g}, \[IndentingNewLine]\t\tg = x1 - x2; + \[IndentingNewLine]\t\tden = PowerMod[g, \(-2\), p]; + \[IndentingNewLine]\t\t + alpha = Mod[ + \((\((x1\ x2 + a)\) \((x1 + x2)\) + 2 c\ x1\ x2 + 2 b)\), p]; + \[IndentingNewLine]\t\t + beta = Mod[\((\((x1\ x2 - a)\)^2 - 4 b \((x1 + x2 + c)\))\), p]; + \[IndentingNewLine]\t\tdisc = Mod[alpha^2 - beta\ g^2, p]; + \[IndentingNewLine]\t\t{\ \ + Mod[\ den*\((alpha + sqrtmod[disc, p])\), p], \ \n\t\t\ \ \ \ + Mod[den*\((alpha - sqrtmod[disc, p])\), p]\n\t\t} + \[IndentingNewLine]\t]; \n + \n (*\ Now, \ + the\ main\ routine . \ Parameters\ are\ given\ for\ 161 - + bit\ prime\ field\n\t\t\tand\ specific\ curve; \n\t\ \ + direct\ embedding\ proceeds\ on\ "\"\ integers\ x\ + \((mod\ p)\) . \ \n\ \ \ We\ start\ with\ relevant\ global\ + \((and\ public, \ except\ for\ kb)\)\n\ \ \ \(parameters . \)\n\ *) \n + \[IndentingNewLine]p\ = \ + 1654338658923174831024422729553880293604080853451; \na\ = \ \(-152\); + \nb = \ 722; \nc\ = \ 0; \ \ (*\ Montgomery\ \(parameter . \)\ *) \n + \n (*\ Next, \ + create\ public\ point\ P\ of\ prime\ order\ on\ main\ \(curve . \)\ *) + \npubpoint\ = + \ {124590448755381588517063157600522073397838354227, \ 1}; \ \ \n + pubpointtwist\ = + \ {1173563507729187954550227059395955904200719019884, 1}; \n\n + kb\ = \ 968525826201321079923232842886222248; + \ \ (*\ Private\ key\ \(K_B . \)\ *) \n\n + pubkey\ = \ \ \ elliptic[pubpoint, \ kb]; + \ \ \ \ \ \ \ \ (*\ Public\ key\ \(P_B . \)\ *) \n + pubkeytwist\ = \ \telliptic[pubpointtwist, \ kb]; + \ \ \ \ \ (*\ Public\ key\ \(P_B' . \)\ *) \n\ \n\t\t\n + encryptEmbed[x_] := \ + Module[{cubic, \ curve, \ X\ = \ x, \ pbk, \ pbp, \ clueX, \ X2, \ uX, + \n\t\t\ \ piece, \ try, \ sign}, + \[IndentingNewLine] (*\ First, \ + let\ us\ determine\ which\ curve . \ \n\t\t\ \ \ EITHER\ X\ lies\ in + \ the\ curve\ y^2\ = \ X^3\ + \ c\ X^2\ + \ a\ X\ + \ b, \n + \t\t\ \ \ + or\ on\ g\ y^2\ = \ X^3\ + \ c\ X^2\ + \ a\ X\ + \ b\ *) \n + \t\t\ cubic\ = \ Mod[X\ Mod[X^2\ + c\ X\ + \ \ a, p]\ + \ b, p]; + \n\t\t\ If[JacobiSymbol[cubic, \ p]\ > \ \(-1\), \ \n + \t\t\t\ \ \ \ \ \ curve\ = \ 1; \ pbk\ = \ pubkey; \ + pbp\ = \ pubpoint, \t\t\t\ \ \ \ \ \ \n\t\t\t\t\ \ \ \ \ + curve\ = \ \(-1\)\ ; \ pbk\ = \ pubkeytwist; \ + pbp\ = \ pubpointtwist; \ \n\t\t\ \ ]; \n\t\t\n\t\t\t + r\ = \ Random[Integer, \ {2, p - 2}]; \t\t\ \ \n\t\t\t + clueX\ = \ ex[elliptic[pbp, \ r]]; \n\t\t\ \ + X2\ = \ ex[elliptic[pbk, \ r]]; + \ (*\ We\ shall\ be\ adding\ the\ points\ having\ X, \ X2, \ + and\n\t\t\t\t\t\ \ \ there\ is\ a\ sign\ ambiguity\ a\ la\ Algorithm + \ 7.2 .8\ because\ Y - + coordinates\n\t\t\t\t\t\t\ \ are\ being\ \(avoided . \)\ *) \ \n + \t\t\ \ \ uX\ = \ \(ellXadd[X, \ X2]\)[\([1]\)]; \n\t\t\n + \t\t (*\ Next, \ + feedback\ loop\ to\ determine\ which\ value\ of\ sign\ recovers\ + \(plaintext . \)\ *) \n\t\t\n\t\t\ \ \ + piece\ = \ ex[elliptic[{clueX, 1}, \ kb]]; \t\t\ \n\t\t\ \ \ + try\ = \ ellXadd[uX, \ piece]; \n\n\t\t\t\ + If[\ttry[\([1]\)]\ == \ X, \ sign\ = \ 1, \n + \t\t\t\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ + If[try[\([2]\)]\ == \ X, \ sign\ = \ \(-1\), \ Print["\"]] + \n\t\t\t]; \t\t\t\t\ \ \ \ \ \ \ \ \n + \t\t\ \ {uX, \ clueX, \ curve, \ sign}\[IndentingNewLine]]; + \[IndentingNewLine]\n + decryptEmbed[cipherList_] := \ + Module[{uX\ = \ cipherList[\([1]\)], \ + clueX\ = \ cipherList[\([2]\)], \ curve\ = \ cipherList[\([3]\)], + \ sign\ = \ cipherList[\([4]\)]}, \n\t\t\ \ \ + piece\ = \ ex[elliptic[{clueX, 1}, \ kb]]; \t\t\ \n\t\t\ \ \ + try\ = \ ellXadd[uX, \ piece]; \n\t\t\ \ \ + X\ = \ try[\([\((3 - sign)\)/2]\)]; \n\t\t\tX\[IndentingNewLine]]; + \[IndentingNewLine]\n\)\)], "Input"], + +Cell[BoxData[ + \(General::"spell1" \( : \ \) + "Possible spelling error: new symbol name \"\!\(beta\)\" is similar to \ +existing symbol \"\!\(Beta\)\"."\)], "Message"], + +Cell[BoxData[ + \(General::"spell1" \( : \ \) + "Possible spelling error: new symbol name \"\!\(sign\)\" is similar to \ +existing symbol \"\!\(Sign\)\"."\)], "Message"] +}, Open ]], + +Cell[CellGroupData[{ + +Cell[BoxData[ + \(\( (*\ EXAMPLE\ *) \ \n\n + ciph\ = \ encryptEmbed[plain\ = \ Random[Integer, p - 1]]; \n + If[decryptEmbed[ciph]\ != \ plain, \ Print["\"]], {ct, 1, 10}] + \)\)], "Input"], + +Cell[BoxData[ + \(General::"spell1" \( : \ \) + "Possible spelling error: new symbol name \"\!\(plain\)\" is similar to \ +existing symbol \"\!\(Plain\)\"."\)], "Message"] +}, Open ]], + +Cell[CellGroupData[{ + +Cell[BoxData[ + \(p\)], "Input"], + +Cell[BoxData[ + \(1654338658923174831024422729553880293604080853451\)], "Output"] +}, Open ]], + +Cell[CellGroupData[{ + +Cell[BoxData[ + \(CC\)], "Input"], + +Cell[BoxData[ + \(CC\)], "Output"] +}, Open ]], + +Cell[BoxData[ + \(6277101735386680763835789423207666416083908700390324961279\)], "Input"] +}, +FrontEndVersion->"NeXT 3.0", +ScreenRectangle->{{0, 957}, {0, 768}}, +WindowToolbars->{}, +WindowSize->{762, 676}, +WindowMargins->{{Automatic, 11}, {Automatic, 24}}, +ShowCellLabel->False +] + + +(*********************************************************************** +Cached data follows. If you edit this Notebook file directly, not using +Mathematica, you must remove the line containing CacheID at the top of +the file. The cache data will then be recreated when you save this file +from within Mathematica. +***********************************************************************) + +(*CellTagsOutline +CellTagsIndex->{} +*) + +(*CellTagsIndex +CellTagsIndex->{} +*) + +(*NotebookFileOutline +Notebook[{ +Cell[1709, 49, 576, 9, 242, "Input"], + +Cell[CellGroupData[{ +Cell[2310, 62, 8704, 154, 2269, "Input"], +Cell[11017, 218, 175, 3, 33, "Message"], +Cell[11195, 223, 175, 3, 33, "Message"] +}, Open ]], + +Cell[CellGroupData[{ +Cell[11407, 231, 215, 4, 65, "Input"], +Cell[11625, 237, 177, 3, 33, "Message"] +}, Open ]], + +Cell[CellGroupData[{ +Cell[11839, 245, 34, 1, 25, "Input"], +Cell[11876, 248, 83, 1, 24, "Output"] +}, Open ]], + +Cell[CellGroupData[{ +Cell[11996, 254, 35, 1, 24, "Input"], +Cell[12034, 257, 36, 1, 24, "Output"] +}, Open ]], +Cell[12085, 261, 91, 1, 24, "Input"] +} +] +*) + + + + +(*********************************************************************** +End of Mathematica Notebook file. +***********************************************************************) + diff --git a/libsecurity_cryptkit/lib/CurveParamDocs/README b/libsecurity_cryptkit/lib/CurveParamDocs/README new file mode 100644 index 00000000..a5b938c2 --- /dev/null +++ b/libsecurity_cryptkit/lib/CurveParamDocs/README @@ -0,0 +1,62 @@ +TOOLS for Apple-CryptKit curve generation/testing. +24 Apr 2001 REC + +The state-of-the-art in ECC (elliptic-curve cryptography) +is in a well known mode of imperfection. For example, +it is very easy to generate CM (complex-multiplication) +curves, with known order and parameters; yet, it is suspected +by some (though unproven in any sense of rigor) +that better security accrues if curves are entirely +"random" in the sense of random base prime p, and random (a,b) +under minimal constraints such as prime curve order, etc. +Thus the collection of this Directory is a potpourri of +various tools, including a Schoof implementation (schoof.c, +schoofs.c) for arbitrary curves. As expected, said implementation +is very slow, yet we have used it for some of the current +CryptKit curves, while for other curves we have used the +fast CM methods, and for yet other curves we have borrowed +recommended parameters from other investigators. + +Contained in this Directory are various C sources: + +* curvegen.c, curvegenFEE.c + Utility for generating CM curves, links to other sources + as shown in comment atop source. + +* factor.c + Utility for factoring such as curve orders; + see comment atop source. + +* giants.c, ellproj.c, fmodule.c, tools.c + Number-theoretical library sources, having standard and + some ECC-specific tools. + +* schoof.c, shoofs.c + Curve-order finder, using the celebratd Schoof algorithm + When run, you input p, a, b (Weierstrass parameterization) + and out comes the curve order, sometimes after a very long + wait. The source schoofs.c is a "sieving Schoof" method + as explained in the References below, for finding curves + of prime-or-nearly-prime order (along with the same constraint + for twists). + +together with Mathematica sources: + +* curverecords.nb + A program to test current CryptKit points/orders. + +* FEED affine.nb, FEEDsansY.nb + Programs for testing FEED, in particular the integrity of + any choice for x1Minus (a coordinate for the twist curve). + +References + +Crandall R and Pomerance C, "Prime numbers: a computational perspective," Springer-Verlag, 2001. + +Crandall, R. E., U.S. Patents #5159632 (1992), #5271061 (1993), + #5463690 (1994), "Method and apparatus for public key exchange in + a cryptographic system." + +Crandall, R. E. 1996 U. S. Patent #5581616, "Method and apparatus + for Digital Signature Authentication." + diff --git a/libsecurity_cryptkit/lib/CurveParamDocs/curvegen.c b/libsecurity_cryptkit/lib/CurveParamDocs/curvegen.c new file mode 100644 index 00000000..fe3b8aa9 --- /dev/null +++ b/libsecurity_cryptkit/lib/CurveParamDocs/curvegen.c @@ -0,0 +1,105 @@ +/************************************************************** + * + * curvegen.c + * + * CM curve generator. + * + * Compile with: + * + * % cc -O curvegen.c tools.c giants.c ellproj.c -lm -o curvegen + * + * Updates: + * 27 Sep 98 REC - Creation + * + * + * c. 1998 Perfectly Scientific, Inc. + * All Rights Reserved. + * + * + *************************************************************/ + +/* include files */ + +#include +#include +#include +#include +#ifdef _WIN32 + +#include + +#endif + +#include +#include "giants.h" +#include "tools.h" + +#define DCOUNT 27 + +int disc12[DCOUNT] = {-3, -4, -7, -8, -11, -19, -43, -67, -163, -15, -20, -24, -35, -40, -51, -52, -88, -91, -115, -123, -148, -187, -232, -235, -267, -403, -427}; /* All discriminants of class number 1,2. */ + +/************************************************************** + * + * Main Function + * + **************************************************************/ + +#define CM_SHORTS 4096 + +main(int argc, char **argv) { + giant p = newgiant(CM_SHORTS); + giant u = newgiant(CM_SHORTS); + giant v = newgiant(CM_SHORTS); + giant g[6]; + giant plus_order = newgiant(CM_SHORTS); + giant minus_order = newgiant(CM_SHORTS); + giant a = newgiant(CM_SHORTS); + giant b = newgiant(CM_SHORTS); + int d, dc, olen, k; + + init_tools(CM_SHORTS); /* Basic algorithms. */ + printf("Give base prime p:\n"); fflush(stdout); + gin(p); + for(dc=0; dc < 6; dc++) g[dc] = newgiant(CM_SHORTS); + for(dc = 0; dc < DCOUNT; dc++) { + d = disc12[dc]; + /* Next, seek representation 4N = u^2 + |d| v^2. */ + if(cornacchia4(p, d, u, v) == 0) continue; +/* Here, (u,v) give the quadratic representation of 4p. */ + printf("D: %d\n", d); fflush(stdout); + gtog(u, g[0]); + switch(d) { + case -3: olen = 3; /* Six orders: p + 1 +- g[0,1,2]. */ + gtog(u, g[1]); gtog(v, g[2]); + addg(g[2], g[2]); addg(v, g[2]); /* g[2] := 3v. */ + addg(g[2], g[1]); gshiftright(1, g[1]); /* g[1] = (u + 3v)/2. */ + subg(u, g[2]); gshiftright(1, g[2]); absg(g[2]); /* g[2] = |u-3v|/2. */ + break; + case -4: olen = 2; /* Four orders: p + 1 +- g[0,1]. */ + gtog(v, g[1]); addg(g[1], g[1]); /* g[1] = 2v. */ + break; + default: olen = 1; /* Two orders: p + 1 +- g[0]. */ + } + for(k=0; k < olen; k++) { + gtog(p, plus_order); iaddg(1, plus_order); + gtog(p, minus_order); iaddg(1, minus_order); + addg(g[k], plus_order); + subg(g[k], minus_order); + printf("curve orders: \n"); + printf("(%d) ", prime_probable(plus_order)); + gout(plus_order); + printf("(%d) ", prime_probable(minus_order)); + gout(minus_order); + } + } +} + + + + + + + + + + diff --git a/libsecurity_cryptkit/lib/CurveParamDocs/curverecords.nb b/libsecurity_cryptkit/lib/CurveParamDocs/curverecords.nb new file mode 100644 index 00000000..f66f4f8d --- /dev/null +++ b/libsecurity_cryptkit/lib/CurveParamDocs/curverecords.nb @@ -0,0 +1,898 @@ +(*********************************************************************** + + Mathematica-Compatible Notebook + +This notebook can be used on any computer system with Mathematica 3.0, +MathReader 3.0, or any compatible application. The data for the notebook +starts with the line of stars above. + +To get the notebook into a Mathematica-compatible application, do one of +the following: + +* Save the data starting with the line of stars above into a file + with a name ending in .nb, then open the file inside the application; + +* Copy the data starting with the line of stars above to the + clipboard, then use the Paste menu command inside the application. + +Data for notebooks contains only printable 7-bit ASCII and can be +sent directly in email or through ftp in text mode. Newlines can be +CR, LF or CRLF (Unix, Macintosh or MS-DOS style). + +NOTE: If you modify the data for this notebook not in a Mathematica- +compatible application, you must delete the line below containing the +word CacheID, otherwise Mathematica-compatible applications may try to +use invalid cache data. + +For more information on notebooks and Mathematica-compatible +applications, contact Wolfram Research: + web: http://www.wolfram.com + email: info@wolfram.com + phone: +1-217-398-0700 (U.S.) + +Notebook reader applications are available free of charge from +Wolfram Research. +***********************************************************************) + +(*CacheID: 232*) + + +(*NotebookFileLineBreakTest +NotebookFileLineBreakTest*) +(*NotebookOptionsPosition[ 18376, 710]*) +(*NotebookOutlinePosition[ 19227, 740]*) +(* CellTagsIndexPosition[ 19183, 736]*) +(*WindowFrame->Normal*) + + + +Notebook[{ +Cell["\<\ +(* curverecords + + Recorded data for Apple ECC curves. + + R. Crandall + 3 Apr 2001 + + + *) + +pointQ[x_] := (JacobiSymbol[x^3 + c x^2 + a x + b, p] > -1); + +(* Next, binary expansion for very old M'ca versions, + otherwise use IntegerDigits[.,2]. *) +bitList[k_] := Block[{li = {}, j = k}, +\tWhile[j > 0, +\t li = Append[li, Mod[j,2]]; +\t j = Floor[j/2]; +\t]; +\tReturn[Reverse[li]]; +\t]; +\t +ellinv[n_] := PowerMod[n,-1,p]; +(* Next, obtain actual x,y coords via normalization: + {x,y,z} := {X/Z^2, Y/Z^3, 1}. *) +normalize[pt_] := Block[{z,z2,z3}, +\t\tIf[pt[[3]] == 0, Return[pt]]; +\t\tz = ellinv[pt[[3]]]; +\t\tz2 = Mod[z^2,p]; +\t\tz3 = Mod[z z2,p]; +\t\tReturn[{Mod[pt[[1]] z2, p], Mod[pt[[2]] z3, p], 1}]; +\t\t]; + +ellneg[pt_] := Mod[pt * {1,-1,1}, p]; +ellsub[pt1_, pt2_] := elladd[pt1, ellneg[pt2]]; +elldouble[pt_] := Block[{x,y,z,m,y2,s}, +\tx = pt[[1]]; y = pt[[2]]; z = pt[[3]]; +\tIf[(y==0) || (z==0), Return[{1,1,0}]]; +\tm = Mod[3 x^2 + a Mod[Mod[z^2,p]^2,p],p]; +\tz = Mod[2 y z, p]; +\ty2 = Mod[y^2,p]; +\ts = Mod[4 x y2,p]; +\tx = Mod[m^2 - 2s,p]; +\ty = Mod[m(s - x) - 8 y2^2,p]; +\tReturn[{x,y,z}]; +]; + +elladd[pt0_, pt1_] := Block[ +\t{x0,y0,z0,x1,y1,z1, +\tt1,t2,t3,t4,t5,t6,t7}, +\tx0 = pt0[[1]]; y0 = pt0[[2]]; z0 = pt0[[3]]; +\tx1 = pt1[[1]]; y1 = pt1[[2]]; z1 = pt1[[3]]; +\tIf[z0 == 0, Return[pt1]]; +\tIf[z1 == 0, Return[pt0]]; + +\tt1 = x0; +\tt2 = y0; +\tt3 = z0; +\tt4 = x1; +\tt5 = y1; +\tIf[(z1 != 1), +\t\tt6 = z1; +\t\tt7 = Mod[t6^2, p]; +\t\tt1 = Mod[t1 t7, p]; +\t\tt7 = Mod[t6 t7, p]; +\t\tt2 = Mod[t2 t7, p]; +\t]; +\tt7 = Mod[t3^2, p]; +\tt4 = Mod[t4 t7, p]; +\tt7 = Mod[t3 t7, p]; +\tt5 = Mod[t5 t7, p]; +\tt4 = Mod[t1-t4, p]; +\tt5 = Mod[t2 - t5, p]; +\tIf[t4 == 0, If[t5 == 0, +\t\t\t\t Return[elldouble[pt0]], +\t \t\t\t\tReturn[{1,1,0}] +\t \t\t\t] +\t]; +\tt1 = Mod[2t1 - t4,p]; +\tt2 = Mod[2t2 - t5, p]; +\tIf[z1 != 1, t3 = Mod[t3 t6, p]]; +\tt3 = Mod[t3 t4, p]; +\tt7 = Mod[t4^2, p]; +\tt4 = Mod[t4 t7, p]; +\tt7 = Mod[t1 t7, p]; +\tt1 = Mod[t5^2, p]; +\tt1 = Mod[t1-t7, p]; +\tt7 = Mod[t7 - 2t1, p]; +\tt5 = Mod[t5 t7, p]; +\tt4 = Mod[t2 t4, p]; +\tt2 = Mod[t5-t4, p]; +\tIf[EvenQ[t2], t2 = t2/2, t2 = (p+t2)/2]; +\tReturn[{t1, t2, t3}]; +]; +\t\t +(* Next, elliptic-multiply a normalized pt by k. *) +elliptic[pt_, k_] := Block[{pt2, hh, kk, hb, kb, lenh, lenk}, +\tIf[k==0, Return[{1,1,0}]]; +\thh = Reverse[bitList[3k]]; +\tkk = Reverse[bitList[k]]; +\tpt2 = pt; +\tlenh = Length[hh]; +\tlenk = Length[kk]; +\tDo[ +\t\tpt2 = elldouble[pt2]; +\t\thb = hh[[b]]; +\t\tIf[b <= lenk, kb = kk[[b]], kb = 0]; +\t\tIf[{hb,kb} == {1,0}, +\t\t\tpt2 = elladd[pt2, pt], +\t\t\tIf[{hb, kb} == {0,1}, +\t\t\tpt2 = ellsub[pt2, pt]] +\t\t] +\t ,{b, lenh-1, 2,-1} +\t ]; +\tReturn[pt2]; +]; + +(* Next, provide point-finding functions. *) + +(* Next, perform (a + b w)^n (mod p), where pair = {a,b}, w2 = w^2. *) +pow[pair_, w2_, n_, p_] := Block[{bitlist, z}, + bitlist = bitList[n]; + z = pair; +\tDo[\t +\t zi = Mod[z[[2]]^2,p]; +\t z = {Mod[z[[1]]^2 + w2 zi, p], Mod[2 z[[1]] z[[2]], p]}; +\t If[bitlist[[q]] == 1, +\t zi = Mod[pair[[2]] z[[2]], p]; +\t \t z = {Mod[pair[[1]] z[[1]] + w2 zi, p], +\t \t Mod[pair[[1]] z[[2]] + pair[[2]] z[[1]], p]}; +\t ], +\t {q,2,Length[bitlist]} + ]; + Return[z] +]; + + +sqrt[x_, p_] := Module[{t, b, w2}, + If[Mod[x,p] == 0, Return[0]]; +\tIf[Mod[p,4] == 3, Return[PowerMod[x, (p+1)/4, p]]]; +\tIf[Mod[p,8] == 5, +\t\tb = PowerMod[x, (p-1)/4, p]; +\t\tIf[b==1, Return[PowerMod[x, (p+3)/8, p]], +\t\t\tReturn[Mod[2x PowerMod[4x, (p-5)/8,p],p]] +\t\t] +\t]; +\tt = 2; + While[True, + w2 = Mod[t^2 - x, p]; + If[JacobiSymbol[w2,p] == -1, Break[]]; + ++t + ]; + (* Next, raise (t + Sqrt[w2])^((p+1)/2). *) + t = pow[{t,1},w2, (p+1)/2, p]; + Return[t[[1]]]; + ]; + +findpoint[start_] := Block[{x = start, y, s}, +\tWhile[True, +\t s = Mod[x(Mod[x^2+a,p]) + b, p]; +\t y = sqrt[s, p]; +\t If[Mod[y^2, p] == s, Break[]]; +\t ++x; +\t]; +\tReturn[{x, y, 1}] +]; + +report[a_] := Module[{ia = IntegerDigits[a,65536]}, + Prepend[Reverse[ia], Length[ia]] + ]; + \ +\>", "Input", + AspectRatioFixed->True], + +Cell[CellGroupData[{ + +Cell["\<\ + + + +report[a_] := Module[{ia = IntegerDigits[a,65536]}, + Prepend[Reverse[ia], Length[ia]] + ]; + + +(* Case of Weierstrass/feemod curve. *) +p = 2^127 + 57675 +report[p] +r = 512000; s = 512001; + +a = Mod[-3 r s^3, p] +report[a] +b = Mod[-2 r s^5, p] +report[b] +pt = findpoint[3]; +pt +plusOrd = 170141183460469231756943134065055014407 +report[plusOrd] +PrineQ[plusOrd] +minusOrd = 170141183460469231706431473366713312401 +report[minusOrd] +PrimeQ[minusOrd] +elliptic[pt, plusOrd] +elliptic[pt, minusOrd]\ +\>", "Input", + AspectRatioFixed->True], + +Cell[BoxData[ + \(170141183460469025572049133804586627403\)], "Output"], + +Cell[BoxData[ + \({8, 29003, 44777, 29962, 4169, 54360, 65535, 65535, 32767}\)], "Output"], + +Cell[BoxData[ + \(170105154311605172483148226534443139403\)], "Output"], + +Cell[BoxData[ + \({8, 16715, 42481, 16221, 60523, 56573, 13644, 4000, 32761}\)], "Output"], + +Cell[BoxData[ + \(Reverse::"normal" \( : \ \) + "Nonatomic expression expected at position \!\(1\) in \ +\!\(Reverse[ib]\)."\)], "Message"], + +Cell[BoxData[ + \(Join::"heads" \( : \ \) + "Heads \!\(List\) and \!\(Reverse\) at positions \!\(1\) and \!\(2\) \ +are expected to be the same."\)], "Message"], + +Cell[BoxData[ + \(Join[{0}, Reverse[ib]]\)], "Output"], + +Cell[BoxData[ + \({6, 30690820274365139284340271178980469693, 1}\)], "Output"], + +Cell[BoxData[ + \({1, 1, 0}\)], "Output"], + +Cell[BoxData[ + \({29855379595419734109449938959593549451, + 71894799143021275114012027736812077762, + 78629090074833058028405436736324079039}\)], "Output"], + +Cell[CellGroupData[{ + +Cell[BoxData[{ + \( (*\ Case\ of\ Weierstrass/gen . \ mod\ \(curve . \)\ *) \n + p\ = \ 1654338658923174831024422729553880293604080853451; \n + Mod[p, 4]\), + \(Length[IntegerDigits[p, 2]]\), + \(report[p]\), + \(PrimeQ[p]\n\n\), + \(a\ = \ \(-152\); \nreport[a]\), + \(b\ = \ Mod[722, \ p]\), + \(report[b]\), + \(ptplus\ = \ + findpoint[1245904487553815885170631576005220733978383542270]\), + \(ptminus\ = \ + findpoint[1173563507729187954550227059395955904200719019884]\), + \(plusOrd\ = \ \ 1654338658923174831024425147405519522862430265804; \n + report[plusOrd]\), + \(PrimeQ[plusOrd]\), + \(minusOrd\ = \ 2 p + 2\ - \ plusOrd\), + \(report[minusOrd]\), + \(PrimeQ[minusOrd]\n\), + \(pt2\ = \ + elliptic[ptplus, \ plusOrd/\((2^2\ *\ 23\ *\ 359\ *\ 479\ *\ 102107)\)] + \), + \(pt3\ = \ elliptic[ptminus, \ minusOrd/\((2^2\ *\ 5^2\ *\ 17^2)\)]\)}], + "Input"], + +Cell[BoxData[ + \(3\)], "Output"], + +Cell[BoxData[ + \(161\)], "Output"], + +Cell[BoxData[ + \({11, 41419, 58349, 36408, 14563, 25486, 9098, 29127, 50972, 7281, 8647, + 1}\)], "Output"], + +Cell[BoxData[ + \(True\)], "Output"], + +Cell[BoxData[ + \({1, 152}\)], "Output"], + +Cell[BoxData[ + \(722\)], "Output"], + +Cell[BoxData[ + \({1, 722}\)], "Output"], + +Cell[BoxData[ + \({1245904487553815885170631576005220733978383542270, + 560361014661268580786436670038204012763093444403, 1}\)], "Output"], + +Cell[BoxData[ + \({1173563507729187954550227059395955904200719019885, + 1175039848591896005104837959278049495835875105211, 1}\)], "Output"], + +Cell[BoxData[ + \({11, 41420, 58349, 36408, 14563, 25486, 9100, 29127, 50972, 7281, 8647, + 1}\)], "Output"], + +Cell[BoxData[ + \(False\)], "Output"], + +Cell[BoxData[ + \(1654338658923174831024420311702241064345731441100\)], "Output"], + +Cell[BoxData[ + \({11, 41420, 58349, 36408, 14563, 25486, 9096, 29127, 50972, 7281, 8647, + 1}\)], "Output"], + +Cell[BoxData[ + \(False\)], "Output"], + +Cell[BoxData[ + \({1, 1, 0}\)], "Output"], + +Cell[BoxData[ + \({1190583420013022954017374261618382173651469909929, + 629194203259568943908951973353992532594049316627, + 1243063853191133727091858197899695654928311311960}\)], "Output"] +}, Open ]] +}, Open ]], + +Cell[CellGroupData[{ + +Cell["\<\ + + +(* Case of Weierstrass/feemod curve. *) +p = 2^160 + 5875 +report[p] +PrimeQ[p] +r = 512; s = 513; + +a = Mod[-3 r s^3, p] +report[a] +b = Mod[2 r s^5, p] +report[b] +pt = findpoint[3]; +pt +plusOrd = 1461501637330902918203687223801810245920805144027 +report[plusOrd] +PrimeQ[plusOrd] +minusOrd = 1461501637330902918203682441630755793391059953677 +report[minusOrd] +PrimeQ[minusOrd] + +elliptic[pt, plusOrd] +elliptic[pt, minusOrd]\ +\>", "Input", + AspectRatioFixed->True], + +Cell[BoxData[ + \(1461501637330902918203684832716283019655932548851\)], "Output"], + +Cell[BoxData[ + \({11, 5875, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}\)], "Output"], + +Cell[BoxData[ + \(True\)], "Output"], + +Cell[BoxData[ + \(1461501637330902918203684832716283019448563798259\)], "Output"], + +Cell[BoxData[ + \({11, 4339, 47068, 65487, 65535, 65535, 65535, 65535, 65535, 65535, + 65535, 0}\)], "Output"], + +Cell[BoxData[ + \(36382017816364032\)], "Output"], + +Cell[BoxData[ + \({4, 1024, 41000, 16704, 129}\)], "Output"], + +Cell[BoxData[ + \({7, 1141381147330837701163756056508811445797829159301, 1}\)], "Output"], + +Cell[BoxData[ + \(1461501637330902918203687223801810245920805144027\)], "Output"], + +Cell[BoxData[ + \({11, 50651, 30352, 49719, 403, 64085, 1, 0, 0, 0, 0, 1}\)], "Output"], + +Cell[BoxData[ + \(True\)], "Output"], + +Cell[BoxData[ + \(1461501637330902918203682441630755793391059953677\)], "Output"], + +Cell[BoxData[ + \({11, 26637, 35183, 15816, 65132, 1450, 65534, 65535, 65535, 65535, + 65535, 0}\)], "Output"], + +Cell[BoxData[ + \(True\)], "Output"], + +Cell[BoxData[ + \({1, 1, 0}\)], "Output"], + +Cell[BoxData[ + \({626678646813931825585362114548610779332932369721, + 425645027836716936906396416648647850487040622280, + 374678203163702432662589149043052098374578486466}\)], "Output"] +}, Open ]], + +Cell[CellGroupData[{ + +Cell[BoxData[{ + \( (*\ Case\ of\ NIST\ P - 192. \ *) \n + p\ = \ 6277101735386680763835789423207666416083908700390324961279; \n + Mod[p, 4]\), + \(Length[IntegerDigits[p, 2]]\), + \(report[p]\), + \(PrimeQ[p]\n\n\), + \(a\ = \ \(-3\); \nreport[a]\), + \(b\ = \ + Mod[\(-2455155546008943817740293915197451784769108058161191238065\), \ + p]\), + \(report[b]\), + \(pt\ = \ findpoint[3]; \npt\), + \(plusOrd\ = \ \ + 6277101735386680763835789423176059013767194773182842284081\), + \(report[plusOrd]\), + \(PrimeQ[plusOrd]\), + \(minusOrd\ = \ 2 p + 2\ - \ plusOrd\), + \(report[minusOrd]\), + \(PrimeQ[minusOrd]\), + \(elliptic[pt, \ plusOrd]\), + \(pt2\ = \ elliptic[pt, \ 23]\), + \(pt\ = \ elliptic[pt2, \ minusOrd/23]\), + \(report[minusOrd/23]\)}], "Input"], + +Cell[BoxData[ + \(3\)], "Output"], + +Cell[BoxData[ + \(192\)], "Output"], + +Cell[BoxData[ + \({12, 65535, 65535, 65535, 65535, 65534, 65535, 65535, 65535, 65535, + 65535, 65535, 65535}\)], "Output"], + +Cell[BoxData[ + \(True\)], "Output"], + +Cell[BoxData[ + \({1, 3}\)], "Output"], + +Cell[BoxData[ + \(3821946189377736946095495508010214631314800642229133723214\)], "Output"], + +Cell[BoxData[ + \({12, 17998, 16057, 8467, 327, 53173, 36315, 5716, 61528, 32536, 6755, + 64230, 39902}\)], "Output"], + +Cell[BoxData[ + \({3, 2573760116079900500718205355717584033158714840310676461950, 1}\)], + "Output"], + +Cell[BoxData[ + \(6277101735386680763835789423176059013767194773182842284081\)], "Output"], + +Cell[BoxData[ + \({12, 10289, 46290, 51633, 5227, 63542, 39390, 65535, 65535, 65535, + 65535, 65535, 65535}\)], "Output"], + +Cell[BoxData[ + \(True\)], "Output"], + +Cell[BoxData[ + \(6277101735386680763835789423239273818400622627597807638479\)], "Output"], + +Cell[BoxData[ + \({12, 55247, 19245, 13902, 60308, 1991, 26145, 0, 0, 0, 0, 0, 0}\)], + "Output"], + +Cell[BoxData[ + \(False\)], "Output"], + +Cell[BoxData[ + \({1974979226733528697945860683178722101664119564992975891016, + 4098724835649872426757510355842063594543191498480025032993, + 6276809135556566751199297417037505266020088100630063387404}\)], "Output"], + +Cell[BoxData[ + \({4331701396234773295967464070295991827703321716502384917379, + 6038875199291747318091498070766965234564517946489302751105, + 2975197300407214290225034931542769825877023149833302700493}\)], "Output"], + +Cell[BoxData[ + \({1, 1, 0}\)], "Output"], + +Cell[BoxData[ + \({12, 16649, 40728, 9152, 53911, 59923, 9684, 22795, 17096, 45590, + 34192, 25644, 2849}\)], "Output"] +}, Open ]], + +Cell[CellGroupData[{ + +Cell[BoxData[ + \(normalize[pt2]\)], "Input"], + +Cell[BoxData[ + \({572757471182948021179439097275935071491066938838024362853, + 1582598775998321197887787208733859332485461160705858323879, 1}\)], + "Output"], + +Cell[CellGroupData[{ + +Cell[BoxData[ + \(report[%[\([1]\)]]\)], "Input"], + +Cell[BoxData[ + \({12, 39781, 2122, 19172, 23122, 40686, 43699, 10062, 14682, 25122, + 55271, 56820, 5979}\)], "Output"] +}, Open ]] +}, Open ]], + +Cell[CellGroupData[{ + +Cell[BoxData[{ + \(minusOrd\), + \(plusOrd\)}], "Input"], + +Cell[BoxData[ + \(6277101735386680763835789423239273818400622627597807638479\)], "Output"], + +Cell[BoxData[ + \(6277101735386680763835789423176059013767194773182842284081\)], "Output"] +}, Open ]], + +Cell[CellGroupData[{ + +Cell[BoxData[ + \(IntegerDigits[13, 2]\)], "Input"], + +Cell[BoxData[ + \({1, 1, 0, 1}\)], "Output"] +}, Open ]], + +Cell[CellGroupData[{ + +Cell[BoxData[{ + \(minusOrd/23\), + \(\treport[minusOrd/23]\)}], "Input"], + +Cell[BoxData[ + \(272917466755942641905903887966924948626114027286861201673\)], "Output"], + +Cell[BoxData[ + \({12, 16649, 40728, 9152, 53911, 59923, 9684, 22795, 17096, 45590, + 34192, 25644, 2849}\)], "Output"] +}, Open ]], + +Cell[CellGroupData[{ + +Cell[BoxData[ + \(ord\ = \ 1024120625531724089187207582052247831; \n + Floor[4^Length[IntegerDigits[plusOrd, \ 2]]/plusOrd]\)], "Input"], + +Cell[BoxData[ + \(5846006549323611672814729766523023173564239767715\)], "Output"] +}, Open ]], + +Cell[CellGroupData[{ + +Cell[BoxData[ + \(report[%]\)], "Input"], + +Cell[BoxData[ + \({11, 59555, 9660, 63266, 63920, 5803, 65528, 65535, 65535, 65535, + 65535, 3}\)], "Output"] +}, Open ]], + +Cell[CellGroupData[{ + +Cell[BoxData[ + \(IntegerDigits[ + 6277101735386680763835789423207666416083908700390324961279, 2]\)], + "Input"], + +Cell[BoxData[ + \({1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1}\)], "Output"] +}, Open ]], + +Cell[CellGroupData[{ + +Cell[BoxData[{ + \(a\), + \(b\), + \(JacobiSymbol[3^3\ + \ a\ *\ 3\ - \ b, \ p]\)}], "Input"], + +Cell[BoxData[ + \(\(-3\)\)], "Output"], + +Cell[BoxData[ + \(3821946189377736946095495508010214631314800642229133723214\)], "Output"], + +Cell[BoxData[ + \(1\)], "Output"] +}, Open ]], + +Cell[CellGroupData[{ + +Cell[BoxData[ + \(minusOrd\)], "Input"], + +Cell[BoxData[ + \(6277101735386680763835789423239273818400622627597807638479\)], "Output"] +}, Open ]], + +Cell[CellGroupData[{ + +Cell[BoxData[ + \(o\ = 272917466755942641905903887966924948626114027286861201673; \n + Floor[4^Length[IntegerDigits[o, 2]]/o]\)], "Input"], + +Cell[BoxData[ + \(563958359038647099875871705988474052021461054728890671516\)], "Output"] +}, Open ]], + +Cell[CellGroupData[{ + +Cell[BoxData[ + \(report[%]\)], "Input"], + +Cell[BoxData[ + \({12, 57756, 63294, 44830, 2517, 2125, 63187, 65535, 65535, 65535, + 65535, 65535, 5887}\)], "Output"] +}, Open ]], + +Cell[CellGroupData[{ + +Cell[BoxData[ + \(IntegerDigits[1654338658923174831024422729553880293604080853451, 2]\)], + "Input"], + +Cell[BoxData[ + \({1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, + 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, + 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, + 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, + 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, + 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, + 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1}\)], "Output"] +}, Open ]] +}, +FrontEndVersion->"NeXT 3.0", +ScreenRectangle->{{0, 957}, {0, 768}}, +WindowToolbars->{}, +CellGrouping->Manual, +WindowSize->{520, 600}, +WindowMargins->{{Automatic, 44}, {-10, Automatic}}, +PrivateNotebookOptions->{"ColorPalette"->{RGBColor, -1}}, +ShowCellLabel->True, +ShowCellTags->False, +RenderingOptions->{"ObjectDithering"->True, +"RasterDithering"->False} +] + + +(*********************************************************************** +Cached data follows. If you edit this Notebook file directly, not using +Mathematica, you must remove the line containing CacheID at the top of +the file. The cache data will then be recreated when you save this file +from within Mathematica. +***********************************************************************) + +(*CellTagsOutline +CellTagsIndex->{} +*) + +(*CellTagsIndex +CellTagsIndex->{} +*) + +(*NotebookFileOutline +Notebook[{ +Cell[1709, 49, 4062, 173, 2136, "Input"], + +Cell[CellGroupData[{ +Cell[5796, 226, 556, 29, 336, "Input"], +Cell[6355, 257, 73, 1, 24, "Output"], +Cell[6431, 260, 92, 1, 24, "Output"], +Cell[6526, 263, 73, 1, 24, "Output"], +Cell[6602, 266, 92, 1, 24, "Output"], +Cell[6697, 269, 145, 3, 33, "Message"], +Cell[6845, 274, 166, 3, 33, "Message"], +Cell[7014, 279, 56, 1, 24, "Output"], +Cell[7073, 282, 80, 1, 24, "Output"], +Cell[7156, 285, 43, 1, 24, "Output"], +Cell[7202, 288, 168, 3, 50, "Output"], + +Cell[CellGroupData[{ +Cell[7395, 295, 949, 24, 381, "Input"], +Cell[8347, 321, 35, 1, 24, "Output"], +Cell[8385, 324, 37, 1, 24, "Output"], +Cell[8425, 327, 115, 2, 37, "Output"], +Cell[8543, 331, 38, 1, 24, "Output"], +Cell[8584, 334, 42, 1, 24, "Output"], +Cell[8629, 337, 37, 1, 24, "Output"], +Cell[8669, 340, 42, 1, 24, "Output"], +Cell[8714, 343, 145, 2, 37, "Output"], +Cell[8862, 347, 146, 2, 37, "Output"], +Cell[9011, 351, 115, 2, 37, "Output"], +Cell[9129, 355, 39, 1, 24, "Output"], +Cell[9171, 358, 83, 1, 24, "Output"], +Cell[9257, 361, 115, 2, 37, "Output"], +Cell[9375, 365, 39, 1, 24, "Output"], +Cell[9417, 368, 43, 1, 24, "Output"], +Cell[9463, 371, 200, 3, 50, "Output"] +}, Open ]] +}, Open ]], + +Cell[CellGroupData[{ +Cell[9712, 380, 469, 25, 312, "Input"], +Cell[10184, 407, 83, 1, 24, "Output"], +Cell[10270, 410, 74, 1, 24, "Output"], +Cell[10347, 413, 38, 1, 24, "Output"], +Cell[10388, 416, 83, 1, 24, "Output"], +Cell[10474, 419, 117, 2, 37, "Output"], +Cell[10594, 423, 51, 1, 24, "Output"], +Cell[10648, 426, 62, 1, 24, "Output"], +Cell[10713, 429, 91, 1, 24, "Output"], +Cell[10807, 432, 83, 1, 24, "Output"], +Cell[10893, 435, 89, 1, 24, "Output"], +Cell[10985, 438, 38, 1, 24, "Output"], +Cell[11026, 441, 83, 1, 24, "Output"], +Cell[11112, 444, 117, 2, 37, "Output"], +Cell[11232, 448, 38, 1, 24, "Output"], +Cell[11273, 451, 43, 1, 24, "Output"], +Cell[11319, 454, 198, 3, 50, "Output"] +}, Open ]], + +Cell[CellGroupData[{ +Cell[11554, 462, 844, 23, 420, "Input"], +Cell[12401, 487, 35, 1, 24, "Output"], +Cell[12439, 490, 37, 1, 24, "Output"], +Cell[12479, 493, 129, 2, 37, "Output"], +Cell[12611, 497, 38, 1, 24, "Output"], +Cell[12652, 500, 40, 1, 24, "Output"], +Cell[12695, 503, 92, 1, 24, "Output"], +Cell[12790, 506, 124, 2, 37, "Output"], +Cell[12917, 510, 103, 2, 50, "Output"], +Cell[13023, 514, 92, 1, 24, "Output"], +Cell[13118, 517, 128, 2, 37, "Output"], +Cell[13249, 521, 38, 1, 24, "Output"], +Cell[13290, 524, 92, 1, 24, "Output"], +Cell[13385, 527, 100, 2, 24, "Output"], +Cell[13488, 531, 39, 1, 24, "Output"], +Cell[13530, 534, 228, 3, 89, "Output"], +Cell[13761, 539, 228, 3, 89, "Output"], +Cell[13992, 544, 43, 1, 24, "Output"], +Cell[14038, 547, 126, 2, 37, "Output"] +}, Open ]], + +Cell[CellGroupData[{ +Cell[14201, 554, 47, 1, 25, "Input"], +Cell[14251, 557, 166, 3, 63, "Output"], + +Cell[CellGroupData[{ +Cell[14442, 564, 51, 1, 25, "Input"], +Cell[14496, 567, 127, 2, 37, "Output"] +}, Open ]] +}, Open ]], + +Cell[CellGroupData[{ +Cell[14672, 575, 61, 2, 38, "Input"], +Cell[14736, 579, 92, 1, 24, "Output"], +Cell[14831, 582, 92, 1, 24, "Output"] +}, Open ]], + +Cell[CellGroupData[{ +Cell[14960, 588, 53, 1, 25, "Input"], +Cell[15016, 591, 46, 1, 24, "Output"] +}, Open ]], + +Cell[CellGroupData[{ +Cell[15099, 597, 78, 2, 38, "Input"], +Cell[15180, 601, 91, 1, 24, "Output"], +Cell[15274, 604, 126, 2, 37, "Output"] +}, Open ]], + +Cell[CellGroupData[{ +Cell[15437, 611, 141, 2, 38, "Input"], +Cell[15581, 615, 83, 1, 24, "Output"] +}, Open ]], + +Cell[CellGroupData[{ +Cell[15701, 621, 42, 1, 25, "Input"], +Cell[15746, 624, 116, 2, 37, "Output"] +}, Open ]], + +Cell[CellGroupData[{ +Cell[15899, 631, 119, 3, 51, "Input"], +Cell[16021, 636, 666, 9, 128, "Output"] +}, Open ]], + +Cell[CellGroupData[{ +Cell[16724, 650, 103, 3, 51, "Input"], +Cell[16830, 655, 40, 1, 24, "Output"], +Cell[16873, 658, 92, 1, 24, "Output"], +Cell[16968, 661, 35, 1, 24, "Output"] +}, Open ]], + +Cell[CellGroupData[{ +Cell[17040, 667, 41, 1, 24, "Input"], +Cell[17084, 670, 92, 1, 24, "Output"] +}, Open ]], + +Cell[CellGroupData[{ +Cell[17213, 676, 143, 2, 64, "Input"], +Cell[17359, 680, 91, 1, 24, "Output"] +}, Open ]], + +Cell[CellGroupData[{ +Cell[17487, 686, 42, 1, 25, "Input"], +Cell[17532, 689, 126, 2, 37, "Output"] +}, Open ]], + +Cell[CellGroupData[{ +Cell[17695, 696, 103, 2, 38, "Input"], +Cell[17801, 700, 559, 7, 115, "Output"] +}, Open ]] +} +] +*) + + + + +(*********************************************************************** +End of Mathematica Notebook file. +***********************************************************************) + diff --git a/libsecurity_cryptkit/lib/CurveParamDocs/disc.h b/libsecurity_cryptkit/lib/CurveParamDocs/disc.h new file mode 100644 index 00000000..09461933 --- /dev/null +++ b/libsecurity_cryptkit/lib/CurveParamDocs/disc.h @@ -0,0 +1,312 @@ + +#define DISC_COUNT 1666 /* All fundamental (negatuve) D with + |D| <= 20000, h(D) <= 20. */ + +/* Next, list of fundamental discriminants |D| <= 20000, h(D) <= 20. */ +int disc[DISC_COUNT] = {-3, -4, -7, -8, -11, -19, -43, -67, -163, -15, -20, -24, -35, -40, -51, -52, + + -88, -91, -115, -123, -148, -187, -232, -235, -267, -403, -427, -23, -31, -59, + + -83, -107, -139, -211, -283, -307, -331, -379, -499, -547, -643, -883, -907, + + -39, -55, -56, -68, -84, -120, -132, -136, -155, -168, -184, -195, -203, -219, + + -228, -259, -280, -291, -292, -312, -323, -328, -340, -355, -372, -388, -408, + + -435, -483, -520, -532, -555, -568, -595, -627, -667, -708, -715, -723, -760, + + -763, -772, -795, -955, -1003, -1012, -1027, -1227, -1243, -1387, -1411, + + -1435, -1507, -1555, -47, -79, -103, -127, -131, -179, -227, -347, -443, -523, + + -571, -619, -683, -691, -739, -787, -947, -1051, -1123, -1723, -1747, -1867, + + -2203, -2347, -2683, -87, -104, -116, -152, -212, -244, -247, -339, -411, + + -424, -436, -451, -472, -515, -628, -707, -771, -808, -835, -843, -856, -1048, + + -1059, -1099, -1108, -1147, -1192, -1203, -1219, -1267, -1315, -1347, -1363, + + -1432, -1563, -1588, -1603, -1843, -1915, -1963, -2227, -2283, -2443, -2515, + + -2563, -2787, -2923, -3235, -3427, -3523, -3763, -71, -151, -223, -251, -463, + + -467, -487, -587, -811, -827, -859, -1163, -1171, -1483, -1523, -1627, -1787, + + -1987, -2011, -2083, -2179, -2251, -2467, -2707, -3019, -3067, -3187, -3907, + + -4603, -5107, -5923, -95, -111, -164, -183, -248, -260, -264, -276, -295, + + -299, -308, -371, -376, -395, -420, -452, -456, -548, -552, -564, -579, -580, + + -583, -616, -632, -651, -660, -712, -820, -840, -852, -868, -904, -915, -939, + + -952, -979, -987, -995, -1032, -1043, -1060, -1092, -1128, -1131, -1155, + + -1195, -1204, -1240, -1252, -1288, -1299, -1320, -1339, -1348, -1380, -1428, + + -1443, -1528, -1540, -1635, -1651, -1659, -1672, -1731, -1752, -1768, -1771, + + -1780, -1795, -1803, -1828, -1848, -1864, -1912, -1939, -1947, -1992, -1995, + + -2020, -2035, -2059, -2067, -2139, -2163, -2212, -2248, -2307, -2308, -2323, + + -2392, -2395, -2419, -2451, -2587, -2611, -2632, -2667, -2715, -2755, -2788, + + -2827, -2947, -2968, -2995, -3003, -3172, -3243, -3315, -3355, -3403, -3448, + + -3507, -3595, -3787, -3883, -3963, -4123, -4195, -4267, -4323, -4387, -4747, + + -4843, -4867, -5083, -5467, -5587, -5707, -5947, -6307, -199, -367, -419, + + -491, -563, -823, -1087, -1187, -1291, -1423, -1579, -2003, -2803, -3163, + + -3259, -3307, -3547, -3643, -4027, -4243, -4363, -4483, -4723, -4987, -5443, + + -6043, -6427, -6763, -6883, -7723, -8563, -8803, -9067, -10627, -119, -143, + + -159, -296, -303, -319, -344, -415, -488, -611, -635, -664, -699, -724, -779, + + -788, -803, -851, -872, -916, -923, -1115, -1268, -1384, -1492, -1576, -1643, + + -1684, -1688, -1707, -1779, -1819, -1835, -1891, -1923, -2152, -2164, -2363, + + -2452, -2643, -2776, -2836, -2899, -3028, -3091, -3139, -3147, -3291, -3412, + + -3508, -3635, -3667, -3683, -3811, -3859, -3928, -4083, -4227, -4372, -4435, + + -4579, -4627, -4852, -4915, -5131, -5163, -5272, -5515, -5611, -5667, -5803, + + -6115, -6259, -6403, -6667, -7123, -7363, -7387, -7435, -7483, -7627, -8227, + + -8947, -9307, -10147, -10483, -13843, -167, -271, -659, -967, -1283, -1303, + + -1307, -1459, -1531, -1699, -2027, -2267, -2539, -2731, -2851, -2971, -3203, + + -3347, -3499, -3739, -3931, -4051, -5179, -5683, -6163, -6547, -7027, -7507, + + -7603, -7867, -8443, -9283, -9403, -9643, -9787, -10987, -13003, -13267, + + -14107, -14683, -15667, -231, -255, -327, -356, -440, -516, -543, -655, -680, + + -687, -696, -728, -731, -744, -755, -804, -888, -932, -948, -964, -984, -996, + + -1011, -1067, -1096, -1144, -1208, -1235, -1236, -1255, -1272, -1336, -1355, + + -1371, -1419, -1464, -1480, -1491, -1515, -1547, -1572, -1668, -1720, -1732, + + -1763, -1807, -1812, -1892, -1955, -1972, -2068, -2091, -2104, -2132, -2148, + + -2155, -2235, -2260, -2355, -2387, -2388, -2424, -2440, -2468, -2472, -2488, + + -2491, -2555, -2595, -2627, -2635, -2676, -2680, -2692, -2723, -2728, -2740, + + -2795, -2867, -2872, -2920, -2955, -3012, -3027, -3043, -3048, -3115, -3208, + + -3252, -3256, -3268, -3304, -3387, -3451, -3459, -3592, -3619, -3652, -3723, + + -3747, -3768, -3796, -3835, -3880, -3892, -3955, -3972, -4035, -4120, -4132, + + -4147, -4152, -4155, -4168, -4291, -4360, -4411, -4467, -4531, -4552, -4555, + + -4587, -4648, -4699, -4708, -4755, -4771, -4792, -4795, -4827, -4888, -4907, + + -4947, -4963, -5032, -5035, -5128, -5140, -5155, -5188, -5259, -5299, -5307, + + -5371, -5395, -5523, -5595, -5755, -5763, -5811, -5835, -6187, -6232, -6235, + + -6267, -6283, -6472, -6483, -6603, -6643, -6715, -6787, -6843, -6931, -6955, + + -6963, -6987, -7107, -7291, -7492, -7555, -7683, -7891, -7912, -8068, -8131, + + -8155, -8248, -8323, -8347, -8395, -8787, -8827, -9003, -9139, -9355, -9523, + + -9667, -9843, -10003, -10603, -10707, -10747, -10795, -10915, -11155, -11347, + + -11707, -11803, -12307, -12643, -14443, -15163, -15283, -16003, -17803, -191, + + -263, -607, -631, -727, -1019, -1451, -1499, -1667, -1907, -2131, -2143, + + -2371, -2659, -2963, -3083, -3691, -4003, -4507, -4643, -5347, -5419, -5779, + + -6619, -7243, -7963, -9547, -9739, -11467, -11587, -11827, -11923, -12043, + + -14347, -15787, -16963, -215, -287, -391, -404, -447, -511, -535, -536, -596, + + -692, -703, -807, -899, -1112, -1211, -1396, -1403, -1527, -1816, -1851, + + -1883, -2008, -2123, -2147, -2171, -2335, -2427, -2507, -2536, -2571, -2612, + + -2779, -2931, -2932, -3112, -3227, -3352, -3579, -3707, -3715, -3867, -3988, + + -4187, -4315, -4443, -4468, -4659, -4803, -4948, -5027, -5091, -5251, -5267, + + -5608, -5723, -5812, -5971, -6388, -6499, -6523, -6568, -6979, -7067, -7099, + + -7147, -7915, -8035, -8187, -8611, -8899, -9115, -9172, -9235, -9427, -10123, + + -10315, -10363, -10411, -11227, -12147, -12667, -12787, -13027, -13435, + + -13483, -13603, -14203, -16867, -18187, -18547, -18643, -239, -439, -751, + + -971, -1259, -1327, -1427, -1567, -1619, -2243, -2647, -2699, -2843, -3331, + + -3571, -3803, -4099, -4219, -5003, -5227, -5323, -5563, -5827, -5987, -6067, + + -6091, -6211, -6571, -7219, -7459, -7547, -8467, -8707, -8779, -9043, -9907, + + -10243, -10267, -10459, -10651, -10723, -11083, -11971, -12163, -12763, + + -13147, -13963, -14323, -14827, -14851, -15187, -15643, -15907, -16603, + + -16843, -17467, -17923, -18043, -18523, -19387, -19867, -399, -407, -471, + + -559, -584, -644, -663, -740, -799, -884, -895, -903, -943, -1015, -1016, + + -1023, -1028, -1047, -1139, -1140, -1159, -1220, -1379, -1412, -1416, -1508, + + -1560, -1595, -1608, -1624, -1636, -1640, -1716, -1860, -1876, -1924, -1983, + + -2004, -2019, -2040, -2056, -2072, -2095, -2195, -2211, -2244, -2280, -2292, + + -2296, -2328, -2356, -2379, -2436, -2568, -2580, -2584, -2739, -2760, -2811, + + -2868, -2884, -2980, -3063, -3108, -3140, -3144, -3160, -3171, -3192, -3220, + + -3336, -3363, -3379, -3432, -3435, -3443, -3460, -3480, -3531, -3556, -3588, + + -3603, -3640, -3732, -3752, -3784, -3795, -3819, -3828, -3832, -3939, -3976, + + -4008, -4020, -4043, -4171, -4179, -4180, -4216, -4228, -4251, -4260, -4324, + + -4379, -4420, -4427, -4440, -4452, -4488, -4515, -4516, -4596, -4612, -4683, + + -4687, -4712, -4740, -4804, -4899, -4939, -4971, -4984, -5115, -5160, -5187, + + -5195, -5208, -5363, -5380, -5403, -5412, -5428, -5460, -5572, -5668, -5752, + + -5848, -5860, -5883, -5896, -5907, -5908, -5992, -5995, -6040, -6052, -6099, + + -6123, -6148, -6195, -6312, -6315, -6328, -6355, -6395, -6420, -6532, -6580, + + -6595, -6612, -6628, -6708, -6747, -6771, -6792, -6820, -6868, -6923, -6952, + + -7003, -7035, -7051, -7195, -7288, -7315, -7347, -7368, -7395, -7480, -7491, + + -7540, -7579, -7588, -7672, -7707, -7747, -7755, -7780, -7795, -7819, -7828, + + -7843, -7923, -7995, -8008, -8043, -8052, -8083, -8283, -8299, -8308, -8452, + + -8515, -8547, -8548, -8635, -8643, -8680, -8683, -8715, -8835, -8859, -8932, + + -8968, -9208, -9219, -9412, -9483, -9507, -9508, -9595, -9640, -9763, -9835, + + -9867, -9955, -10132, -10168, -10195, -10203, -10227, -10312, -10387, -10420, + + -10563, -10587, -10635, -10803, -10843, -10948, -10963, -11067, -11092, + + -11107, -11179, -11203, -11512, -11523, -11563, -11572, -11635, -11715, + + -11848, -11995, -12027, -12259, -12387, -12523, -12595, -12747, -12772, + + -12835, -12859, -12868, -13123, -13192, -13195, -13288, -13323, -13363, + + -13507, -13795, -13819, -13827, -14008, -14155, -14371, -14403, -14547, + + -14707, -14763, -14995, -15067, -15387, -15403, -15547, -15715, -16027, + + -16195, -16347, -16531, -16555, -16723, -17227, -17323, -17347, -17427, + + -17515, -18403, -18715, -18883, -18907, -19147, -19195, -19947, -19987, -383, + + -991, -1091, -1571, -1663, -1783, -2531, -3323, -3947, -4339, -4447, -4547, + + -4651, -5483, -6203, -6379, -6451, -6827, -6907, -7883, -8539, -8731, -9883, + + -11251, -11443, -12907, -13627, -14083, -14779, -14947, -16699, -17827, + + -18307, -19963, -335, -519, -527, -679, -1135, -1172, -1207, -1383, -1448, + + -1687, -1691, -1927, -2047, -2051, -2167, -2228, -2291, -2315, -2344, -2644, + + -2747, -2859, -3035, -3107, -3543, -3544, -3651, -3688, -4072, -4299, -4307, + + -4568, -4819, -4883, -5224, -5315, -5464, -5492, -5539, -5899, -6196, -6227, + + -6331, -6387, -6484, -6739, -6835, -7323, -7339, -7528, -7571, -7715, -7732, + + -7771, -7827, -8152, -8203, -8212, -8331, -8403, -8488, -8507, -8587, -8884, + + -9123, -9211, -9563, -9627, -9683, -9748, -9832, -10228, -10264, -10347, + + -10523, -11188, -11419, -11608, -11643, -11683, -11851, -11992, -12067, + + -12148, -12187, -12235, -12283, -12651, -12723, -12811, -12952, -13227, + + -13315, -13387, -13747, -13947, -13987, -14163, -14227, -14515, -14667, + + -14932, -15115, -15243, -16123, -16171, -16387, -16627, -17035, -17131, + + -17403, -17635, -18283, -18712, -19027, -19123, -19651, -311, -359, -919, + + -1063, -1543, -1831, -2099, -2339, -2459, -3343, -3463, -3467, -3607, -4019, + + -4139, -4327, -5059, -5147, -5527, -5659, -6803, -8419, -8923, -8971, -9619, + + -10891, -11299, -15091, -15331, -16363, -16747, -17011, -17299, -17539, + + -17683, -19507, -455, -615, -776, -824, -836, -920, -1064, -1124, -1160, + + -1263, -1284, -1460, -1495, -1524, -1544, -1592, -1604, -1652, -1695, -1739, + + -1748, -1796, -1880, -1887, -1896, -1928, -1940, -1956, -2136, -2247, -2360, + + -2404, -2407, -2483, -2487, -2532, -2552, -2596, -2603, -2712, -2724, -2743, + + -2948, -2983, -2987, -3007, -3016, -3076, -3099, -3103, -3124, -3131, -3155, + + -3219, -3288, -3320, -3367, -3395, -3496, -3512, -3515, -3567, -3655, -3668, + + -3684, -3748, -3755, -3908, -3979, -4011, -4015, -4024, -4036, -4148, -4264, + + -4355, -4371, -4395, -4403, -4408, -4539, -4548, -4660, -4728, -4731, -4756, + + -4763, -4855, -4891, -5019, -5028, -5044, -5080, -5092, -5268, -5331, -5332, + + -5352, -5368, -5512, -5560, -5592, -5731, -5944, -5955, -5956, -5988, -6051, + + -6088, -6136, -6139, -6168, -6280, -6339, -6467, -6504, -6648, -6712, -6755, + + -6808, -6856, -7012, -7032, -7044, -7060, -7096, -7131, -7144, -7163, -7171, + + -7192, -7240, -7428, -7432, -7467, -7572, -7611, -7624, -7635, -7651, -7667, + + -7720, -7851, -7876, -7924, -7939, -8067, -8251, -8292, -8296, -8355, -8404, + + -8472, -8491, -8632, -8692, -8755, -8808, -8920, -8995, -9051, -9124, -9147, + + -9160, -9195, -9331, -9339, -9363, -9443, -9571, -9592, -9688, -9691, -9732, + + -9755, -9795, -9892, -9976, -9979, -10027, -10083, -10155, -10171, -10291, + + -10299, -10308, -10507, -10515, -10552, -10564, -10819, -10888, -11272, + + -11320, -11355, -11379, -11395, -11427, -11428, -11539, -11659, -11755, + + -11860, -11883, -11947, -11955, -12019, -12139, -12280, -12315, -12328, + + -12331, -12355, -12363, -12467, -12468, -12472, -12499, -12532, -12587, + + -12603, -12712, -12883, -12931, -12955, -12963, -13155, -13243, -13528, + + -13555, -13588, -13651, -13803, -13960, -14307, -14331, -14467, -14491, + + -14659, -14755, -14788, -15235, -15268, -15355, -15603, -15688, -15691, + + -15763, -15883, -15892, -15955, -16147, -16228, -16395, -16408, -16435, + + -16483, -16507, -16612, -16648, -16683, -16707, -16915, -16923, -17067, + + -17187, -17368, -17563, -17643, -17763, -17907, -18067, -18163, -18195, + + -18232, -18355, -18363, -19083, -19443, -19492, -19555, -19923}; diff --git a/libsecurity_cryptkit/lib/CurveParamDocs/ellproj.c b/libsecurity_cryptkit/lib/CurveParamDocs/ellproj.c new file mode 100644 index 00000000..b98b2573 --- /dev/null +++ b/libsecurity_cryptkit/lib/CurveParamDocs/ellproj.c @@ -0,0 +1,448 @@ +/************************************************************** + * + * ellproj.c + * + Fast algorithms for fundamental elliptic curve arithmetic, + projective format. Such algorithms apply in domains such as: + -- factoring + -- primality studies (e.g. rigorous primality proofs) + -- elliptic curve cryptography (ECC) + + PROJECTIVE FORMAT + + Functions are supplied herein for projective format + of points. Alternative formats differ in their + range of applicability, efficiency, and so on. + Primary advantages of the projective format herein are: + -- No explicit inversions (until perhaps one such at the end of + an elliptic multiply operation) + -- Fairly low operation count (~11 muls for point doubling, + ~16 muls for point addition) + + The elliptic curve is over F_p, with p > 3 prime, and Weierstrass + parameterization: + + y^2 = x^3 + a x + b + + The projective-format coordinates are actually stored in + the form {X, Y, Z}, with true x,y + coordinates on the curve given by {x,y} = {X/Z^2, Y/Z^3}. + The function normalize_proj() performs the + transformation from projective->true. + (The other direction is trivial, i.e. {x,y} -> {x,y,1} will do.) + The basic point multiplication function is + + ell_mul_proj() + + which obtains the result k * P for given point P and integer + multiplier k. If true {x,y} are required for a multiple, one + passes a point P = {X, Y, 1} to ell_mul_proj(), then afterwards + calls normalize_proj(), + + Projective format is an answer to the typical sluggishness of + standard elliptic arithmetic, whose explicit inversion in the + field is, depending of course on the machinery and programmer, + costly. Projective format is thus especially interesting for + cryptography. + + REFERENCES + + Crandall R and Pomerance C 1998, "Prime numbers: a computational + perspective," Springer-Verlag, manuscript + + Solinas J 1998, IEEE P1363 Annex A (draft standard) + + LEGAL AND PATENT NOTICE + + This and related PSI library source code is intended solely for + educational and research applications, and should not be used + for commercial purposes without explicit permission from PSI + (not to mention proper clearance of legal restrictions beyond + the purview of PSI). + The code herein will not perform cryptography per se, + although the number-theoretical algorithms herein -- all of which + are in the public domain -- can be used in principle to effect + what is known as elliptic curve cryptography (ECC). Note that + there are strict constraints on how cryptography may be used, + especially in regard to exportability. + Therefore one should avoid any casual distribution of actual + cryptographic software. Along similar lines, because of various + patents, proprietary to Apple Computer, Inc., and perhaps to other + organizations, one should not tacitly assume that an ECC scheme is + unconstrained. For example,the commercial use of certain fields + F_p^k (i.e., fixation of certain primes p) is covered in Apple + patents. + + * Updates: + * 3 Apr 98 REC Creation + * + * c. 1998 Perfectly Scientific, Inc. + * All Rights Reserved. + * + * + *************************************************************/ + +/* include files */ + +#include +#include +#include +#include +#ifdef _WIN32 + +#include + +#endif + +#include +#include "giants.h" +#include "ellproj.h" +#include "tools.h" + +/* global variables */ + +static giant t0 = NULL, t1 = NULL, t2 = NULL, t3 = NULL, t4 = NULL, + t5 = NULL, t6 = NULL, t7 = NULL; + +/************************************************************** + * + * Maintenance functions + * + **************************************************************/ + +point_proj +new_point_proj(int shorts) +{ + point_proj pt; + + if(t0 == NULL) init_ell_proj(shorts); + pt = (point_proj) malloc(sizeof(point_struct_proj)); + pt->x = newgiant(shorts); + pt->y = newgiant(shorts); + pt->z = newgiant(shorts); + return(pt); +} + +void +free_point_proj(point_proj pt) +{ + free(pt->x); free(pt->y); free(pt->z); + free(pt); +} + +void +ptop_proj(point_proj pt1, point_proj pt2) +{ + gtog(pt1->x, pt2->x); + gtog(pt1->y, pt2->y); + gtog(pt1->z, pt2->z); +} + +void +init_ell_proj(int shorts) +/* Called by new_point_proj(), to set up giant registers. */ +{ + t0 = newgiant(shorts); + t1 = newgiant(shorts); + t2 = newgiant(shorts); + t3 = newgiant(shorts); + t4 = newgiant(shorts); + t5 = newgiant(shorts); + t6 = newgiant(shorts); + t7 = newgiant(shorts); +} + + +/************************************************************** + * + * Elliptic curve operations + * + **************************************************************/ + +/* Begin projective-format functions for + + y^2 = x^3 + a x + b. + + These are useful in elliptic curve cryptography (ECC). + A point is kept as a triple {X,Y,Z}, with the true (x,y) + coordinates given by + + {x,y} = {X/Z^2, Y/Z^3} + + The function normalize_proj() performs the inverse conversion to get + the true (x,y) pair. + */ + +void +ell_double_proj(point_proj pt, giant a, giant p) +/* pt := 2 pt on the curve. */ +{ + giant x = pt->x, y = pt->y, z = pt->z; + + if(isZero(y) || isZero(z)) { + itog(1,x); itog(1,y); itog(0,z); + return; + } + gtog(z,t1); squareg(t1); modg(p, t1); + squareg(t1); modg(p, t1); + mulg(a, t1); modg(p, t1); /* t1 := a z^4. */ + gtog(x, t2); squareg(t2); smulg(3, t2); modg(p, t2); /* t2 := 3x^2. */ + addg(t2, t1); modg(p, t1); /* t1 := slope m. */ + mulg(y, z); addg(z,z); modg(p, z); /* z := 2 y z. */ + gtog(y, t2); squareg(t2); modg(p, t2); /* t2 := y^2. */ + gtog(t2, t3); squareg(t3); modg(p, t3); /* t3 := y^4. */ + gshiftleft(3, t3); /* t3 := 8 y^4. */ + mulg(x, t2); gshiftleft(2, t2); modg(p, t2); /* t2 := 4xy^2. */ + gtog(t1, x); squareg(x); modg(p, x); + subg(t2, x); subg(t2, x); modg(p, x); /* x done. */ + gtog(t1, y); subg(x, t2); mulg(t2, y); subg(t3, y); + modg(p, y); +} +/* +elldouble[pt_] := Block[{x,y,z,m,y2,s}, + x = pt[[1]]; y = pt[[2]]; z = pt[[3]]; + If[(y==0) || (z==0), Return[{1,1,0}]]; + m = Mod[3 x^2 + a Mod[Mod[z^2,p]^2,p],p]; + z = Mod[2 y z, p]; + y2 = Mod[y^2,p]; + s = Mod[4 x y2,p]; + x = Mod[m^2 - 2s,p]; + y = Mod[m(s - x) - 8 y2^2,p]; + Return[{x,y,z}]; +]; +*/ + +void +ell_add_proj(point_proj pt0, point_proj pt1, giant a, giant p) +/* pt0 := pt0 + pt1 on the curve. */ +{ + giant x0 = pt0->x, y0 = pt0->y, z0 = pt0->z, + x1 = pt1->x, y1 = pt1->y, z1 = pt1->z; + + if(isZero(z0)) { + gtog(x1,x0); gtog(y1,y0); gtog(z1,z0); + return; + } + if(isZero(z1)) return; + gtog(x0, t1); gtog(y0,t2); gtog(z0, t3); + gtog(x1, t4); gtog(y1, t5); + if(!isone(z1)) { + gtog(z1, t6); + gtog(t6, t7); squareg(t7); modg(p, t7); + mulg(t7, t1); modg(p, t1); + mulg(t6, t7); modg(p, t7); + mulg(t7, t2); modg(p, t2); + } + gtog(t3, t7); squareg(t7); modg(p, t7); + mulg(t7, t4); modg(p, t4); + mulg(t3, t7); modg(p, t7); + mulg(t7, t5); modg(p, t5); + negg(t4); addg(t1, t4); modg(p, t4); + negg(t5); addg(t2, t5); modg(p, t5); + if(isZero(t4)) { + if(isZero(t5)) { + ell_double_proj(pt0, a, p); + } else { + itog(1, x0); itog(1, y0); itog(0, z0); + } + return; + } + addg(t1, t1); subg(t4, t1); modg(p, t1); + addg(t2, t2); subg(t5, t2); modg(p, t2); + if(!isone(z1)) { + mulg(t6, t3); modg(p, t3); + } + mulg(t4, t3); modg(p, t3); + gtog(t4, t7); squareg(t7); modg(p, t7); + mulg(t7, t4); modg(p, t4); + mulg(t1, t7); modg(p, t7); + gtog(t5, t1); squareg(t1); modg(p, t1); + subg(t7, t1); modg(p, t1); + subg(t1, t7); subg(t1, t7); modg(p, t7); + mulg(t7, t5); modg(p, t5); + mulg(t2, t4); modg(p, t4); + gtog(t5, t2); subg(t4,t2); modg(p, t2); + if(t2->n[0] & 1) { /* Test if t2 is odd. */ + addg(p, t2); + } + gshiftright(1, t2); + gtog(t1, x0); gtog(t2, y0); gtog(t3, z0); +} + +/* +elladd[pt0_, pt1_] := Block[ + {x0,y0,z0,x1,y1,z1, + t1,t2,t3,t4,t5,t6,t7}, + x0 = pt0[[1]]; y0 = pt0[[2]]; z0 = pt0[[3]]; + x1 = pt1[[1]]; y1 = pt1[[2]]; z1 = pt1[[3]]; + If[z0 == 0, Return[pt1]]; + If[z1 == 0, Return[pt0]]; + + t1 = x0; + t2 = y0; + t3 = z0; + t4 = x1; + t5 = y1; + If[(z1 != 1), + t6 = z1; + t7 = Mod[t6^2, p]; + t1 = Mod[t1 t7, p]; + t7 = Mod[t6 t7, p]; + t2 = Mod[t2 t7, p]; + ]; + t7 = Mod[t3^2, p]; + t4 = Mod[t4 t7, p]; + t7 = Mod[t3 t7, p]; + t5 = Mod[t5 t7, p]; + t4 = Mod[t1-t4, p]; + t5 = Mod[t2 - t5, p]; + If[t4 == 0, If[t5 == 0, + Return[elldouble[pt0]], + Return[{1,1,0}] + ] + ]; + t1 = Mod[2t1 - t4,p]; + t2 = Mod[2t2 - t5, p]; + If[z1 != 1, t3 = Mod[t3 t6, p]]; + t3 = Mod[t3 t4, p]; + t7 = Mod[t4^2, p]; + t4 = Mod[t4 t7, p]; + t7 = Mod[t1 t7, p]; + t1 = Mod[t5^2, p]; + t1 = Mod[t1-t7, p]; + t7 = Mod[t7 - 2t1, p]; + t5 = Mod[t5 t7, p]; + t4 = Mod[t2 t4, p]; + t2 = Mod[t5-t4, p]; + If[EvenQ[t2], t2 = t2/2, t2 = (p+t2)/2]; + Return[{t1, t2, t3}]; +]; +*/ + +void +ell_neg_proj(point_proj pt, giant p) +/* pt := -pt on the curve. */ +{ + negg(pt->y); modg(p, pt->y); +} + +void +ell_sub_proj(point_proj pt0, point_proj pt1, giant a, giant p) +/* pt0 := pt0 - pt1 on the curve. */ +{ + ell_neg_proj(pt1, p); + ell_add_proj(pt0, pt1,a,p); + ell_neg_proj(pt1,p); +} + +void +ell_mul_proj(point_proj pt0, point_proj pt1, giant k, giant a, giant p) +/* General elliptic multiplication; + pt1 := k*pt0 on the curve, + with k an arbitrary integer. + */ +{ + giant x = pt0->x, y = pt0->y, z = pt0->z, + xx = pt1->x, yy = pt1->y, zz = pt1->z; + int ksign, hlen, klen, b, hb, kb; + + if(isZero(k)) { + itog(1, xx); + itog(1, yy); + itog(0, zz); + return; + } + ksign = k->sign; + if(ksign < 0) negg(k); + gtog(x,xx); gtog(y,yy); gtog(z,zz); + gtog(k, t0); addg(t0, t0); addg(k, t0); /* t0 := 3k. */ + hlen = bitlen(t0); + klen = bitlen(k); + for(b = hlen-2; b > 0; b--) { + ell_double_proj(pt1,a,p); + hb = bitval(t0, b); + if(b < klen) kb = bitval(k, b); else kb = 0; + if((hb != 0) && (kb == 0)) + ell_add_proj(pt1, pt0, a, p); + else if((hb == 0) && (kb !=0)) + ell_sub_proj(pt1, pt0, a, p); + } + if(ksign < 0) { + ell_neg_proj(pt1, p); + k->sign = -k->sign; + } +} + +/* +elliptic[pt_, k_] := Block[{pt2, hh, kk, hb, kb, lenh, lenk}, + If[k==0, Return[{1,1,0}]]; + hh = Reverse[bitList[3k]]; + kk = Reverse[bitList[k]]; + pt2 = pt; + lenh = Length[hh]; + lenk = Length[kk]; + Do[ + pt2 = elldouble[pt2]; + hb = hh[[b]]; + If[b <= lenk, kb = kk[[b]], kb = 0]; + If[{hb,kb} == {1,0}, + pt2 = elladd[pt2, pt], + If[{hb, kb} == {0,1}, + pt2 = ellsub[pt2, pt]] + ] + ,{b, lenh-1, 2,-1} + ]; + Return[pt2]; +]; +*/ + +void +normalize_proj(point_proj pt, giant p) +/* Obtain actual x,y coords via normalization: + {x,y,z} := {x/z^2, y/z^3, 1}. + */ + +{ giant x = pt->x, y = pt->y, z = pt->z; + + if(isZero(z)) { + itog(1,x); itog(1,y); + return; + } + binvaux(p, z); gtog(z, t1); + squareg(z); modg(p, z); + mulg(z, x); modg(p, x); + mulg(t1, z); mulg(z, y); modg(p, y); + itog(1, z); +} + +/* +normalize[pt_] := Block[{z,z2,z3}, + If[pt[[3]] == 0, Return[pt]]; + z = ellinv[pt[[3]]]; + z2 = Mod[z^2,p]; + z3 = Mod[z z2,p]; + Return[{Mod[pt[[1]] z2, p], Mod[pt[[2]] z3, p], 1}]; + ]; +*/ + + +void +find_point_proj(point_proj pt, giant seed, giant a, giant b, giant p) +/* Starting with seed, finds a random (projective) point {x,y,1} on curve. + */ +{ giant x = pt->x, y = pt->y, z = pt->z; + + modg(p, seed); + while(1) { + gtog(seed, x); + squareg(x); modg(p, x); + addg(a, x); + mulg(seed,x); addg(b, x); + modg(p, x); /* x := seed^3 + a seed + b. */ + if(sqrtmod(p, x)) break; /* Test if cubic form has root. */ + iaddg(1, seed); + } + gtog(x, y); + gtog(seed,x); + itog(1, z); +} diff --git a/libsecurity_cryptkit/lib/CurveParamDocs/ellproj.h b/libsecurity_cryptkit/lib/CurveParamDocs/ellproj.h new file mode 100644 index 00000000..8f134144 --- /dev/null +++ b/libsecurity_cryptkit/lib/CurveParamDocs/ellproj.h @@ -0,0 +1,59 @@ +/************************************************************** + * + * ellproj.h + * + * Header file for ellproj.c + * + * Updates: + * 3 Apr 98 REC - Creation + * + * c. 1998 Perfectly Scientific, Inc. + * All Rights Reserved. + * + * + *************************************************************/ + +/* definitions */ + +typedef struct /* This is how to define a projective point. */ +{ + giant x; + giant y; + giant z; +} point_struct_proj; + +typedef point_struct_proj *point_proj; + +point_proj /* Allocates a new projective point. */ +new_point_proj(int shorts); + +void /* Frees point. */ +free_point_proj(point_proj pt); + +void /* Copies point to point. */ +ptop_proj(point_proj pt1, point_proj pt2); + +void /* Initialization. */ +init_ell_proj(int shorts); + +void /* Point doubling. */ +ell_double_proj(point_proj pt, giant a, giant p); + +void /* Point addition. */ +ell_add_proj(point_proj pt0, point_proj pt1, giant a, giant p); + +void /* Point negation. */ +ell_neg_proj(point_proj pt, giant p); + +void /* Point subtraction. */ +ell_sub_proj(point_proj pt0, point_proj pt1, giant a, giant p); + +void /* General elliptic mul. */ +ell_mul_proj(point_proj pt0, point_proj pt1, giant k, giant a, giant p); + +void /* Generate normalized point (X, Y, 1) from given (x,y,z). */ +normalize_proj(point_proj pt, giant p); + +void /* Find a point (x, y, 1) on the curve. */ +find_point_proj(point_proj pt, giant seed, giant a, giant b, giant p); + diff --git a/libsecurity_cryptkit/lib/CurveParamDocs/factor.c b/libsecurity_cryptkit/lib/CurveParamDocs/factor.c new file mode 100644 index 00000000..a0d0186f --- /dev/null +++ b/libsecurity_cryptkit/lib/CurveParamDocs/factor.c @@ -0,0 +1,844 @@ +/************************************************************** + * + * factor.c + * + * General purpose factoring program + * + * Updates: + * 18 May 97 REC - invoked new, fast divide functions + * 26 Apr 97 RDW - fixed tabs and unix EOL + * 20 Apr 97 RDW - conversion to TC4.5 + * + * c. 1997 Perfectly Scientific, Inc. + * All Rights Reserved. + * + * + *************************************************************/ + +/* include files */ + +#include +#include +#include +#include +#ifdef _WIN32 + +#include + +#endif + +#include +#include "giants.h" + + +/* definitions */ + +#define D 100 +#define NUM_PRIMES 6542 /* PrimePi[2^16]. */ + + +/* compiler options */ + +#ifdef _WIN32 +#pragma warning( disable : 4127 4706 ) /* disable conditional is constant warning */ +#endif + + +/* global variables */ + +extern giant scratch2; +int pr[NUM_PRIMES]; +giant xr = NULL, xs = NULL, zs = NULL, zr = NULL, xorg = NULL, + zorg = NULL, t1 = NULL, t2 = NULL, t3 = NULL, N = NULL, + gg = NULL, An = NULL, Ad = NULL; +giant xb[D+2], zb[D+2], xzb[D+2]; +int modmode = 0, Q, modcount = 0; + + +/* function prototypes */ + +void ell_even(giant x1, giant z1, giant x2, giant z2, giant An, + giant Ad, giant N); +void ell_odd(giant x1, giant z1, giant x2, giant z2, giant xor, + giant zor, giant N); +void ell_mul(giant xx, giant zz, int n, giant An, giant Ad, giant N); +int least_2(int n); +void dot(void); +int psi_rand(); + + +/************************************************************** + * + * Functions + * + **************************************************************/ + + +int +psi_rand( + void +) +{ + unsigned short hi; + unsigned short low; + time_t tp; + int result; + + time(&tp); + low = (unsigned short)rand(); + hi = (unsigned short)rand(); + result = ((hi << 16) | low) ^ ((int)tp); + + return (result & 0x7fffffff); +} + + +void +set_random_seed( + void +) +{ + /* Start the random number generator at a new position. */ + time_t tp; + + time(&tp); + srand((int)tp + (int)getpid()); +} + + +int +isprime( + int odd +) +{ + int j; + int p; + + for (j=1; ; j++) + { + p = pr[j]; + if (p*p > odd) + return(1); + if (odd % p == 0) + return(0); + } +} + + +int +primeq( + int p +) +{ + register int j=3; + + if ((p&1)==0) + return ((p==2)?1:0); + if (j>=p) + return (1); + while ((p%j)!=0) + { + j+=2; + if (j*j>p) + return(1); + } + return(0); +} + + +void +s_modg( + giant N, + giant t +) +{ + ++modcount; + switch (modmode) + { + case 0: + modg(N, t); + break; + case -1: + mersennemod(Q, t); + break; + case 1: + fermatmod(Q, t); + break; + } +} + + +void +reset_mod( + giant x, + giant N +) +/* Perform a divide (by the discovered factor) and switch back + to non-Fermat-non-Mersenne (i.e. normal) mod mode. */ +{ + divg(x, N); + modmode = 0; +} + +void +ell_even( + giant x1, + giant z1, + giant x2, + giant z2, + giant An, + giant Ad, + giant N +) +{ + gtog(x1, t1); + addg(z1, t1); + squareg(t1); + s_modg(N, t1); + gtog(x1, t2); + subg(z1, t2); + squareg(t2); + s_modg(N, t2); + gtog(t1, t3); + subg(t2, t3); + gtog(t2, x2); + mulg(t1, x2); + gshiftleft(2, x2); + s_modg(N, x2); + mulg(Ad, x2); + s_modg(N, x2); + mulg(Ad, t2); + gshiftleft(2, t2); + s_modg(N, t2); + gtog(t3, t1); + mulg(An, t1); + s_modg(N, t1); + addg(t1, t2); + mulg(t3, t2); + s_modg(N, t2); + gtog(t2,z2); +} + + +void +ell_odd( + giant x1, + giant z1, + giant x2, + giant z2, + giant xor, + giant zor, + giant N +) +{ + gtog(x1, t1); + subg(z1, t1); + gtog(x2, t2); + addg(z2, t2); + mulg(t1, t2); + s_modg(N, t2); + gtog(x1, t1); + addg(z1, t1); + gtog(x2, t3); + subg(z2, t3); + mulg(t3, t1); + s_modg(N, t1); + gtog(t2, x2); + addg(t1, x2); + squareg(x2); + s_modg(N, x2); + gtog(t2, z2); + subg(t1, z2); + squareg(z2); + s_modg(N, z2); + mulg(zor, x2); + s_modg(N, x2); + mulg(xor, z2); + s_modg(N, z2); +} + + +void +ell_mul( + giant xx, + giant zz, + int n, + giant An, + giant Ad, + giant N +) +{ + unsigned int c = (unsigned int)0x80000000; + + if (n==1) + return; + if (n==2) + { + ell_even(xx, zz, xx, zz, An, Ad, N); + return; + } + gtog(xx, xorg); + gtog(zz, zorg); + ell_even(xx, zz, xs, zs, An, Ad, N); + + while((c&n) == 0) + { + c >>= 1; + } + + c>>=1; + do + { + if (c&n) + { + ell_odd(xs, zs, xx, zz, xorg, zorg, N); + ell_even(xs, zs, xs, zs, An, Ad, N); + } + else + { + ell_odd(xx, zz, xs, zs, xorg, zorg, N); + ell_even(xx, zz, xx, zz, An, Ad, N); + } + c >>= 1; + } while(c); +} + + + +/* From R. P. Brent, priv. comm. 1996: +Let s > 5 be a pseudo-random seed (called $\sigma$ in the Tech. Report), + + u/v = (s^2 - 5)/(4s) + +Then starting point is (x_1, y_1) where + + x_1 = (u/v)^3 +and + a = (v-u)^3(3u+v)/(4u^3 v) - 2 +*/ + +void +choose12( + giant x, + giant z, + int k, + giant An, + giant Ad, + giant N +) +{ + itog(k, zs); + gtog(zs, xs); + squareg(xs); + itog(5, t2); + subg(t2, xs); + s_modg(N, xs); + addg(zs, zs); + addg(zs, zs); + s_modg(N, zs); + gtog(xs, x); + squareg(x); + s_modg(N, x); + mulg(xs, x); + s_modg(N, x); + gtog(zs, z); + squareg(z); + s_modg(N, z); + mulg(zs, z); + s_modg(N, z); + + /* Now for A. */ + gtog(zs, t2); + subg(xs, t2); + gtog(t2, t3); + squareg(t2); + s_modg(N, t2); + mulg(t3, t2); + s_modg(N, t2); /* (v-u)^3. */ + gtog(xs, t3); + addg(t3, t3); + addg(xs, t3); + addg(zs, t3); + s_modg(N, t3); + mulg(t3, t2); + s_modg(N, t2); /* (v-u)^3 (3u+v). */ + gtog(zs, t3); + mulg(xs, t3); + s_modg(N, t3); + squareg(xs); + s_modg(N, xs); + mulg(xs, t3); + s_modg(N, t3); + addg(t3, t3); + addg(t3, t3); + s_modg(N, t3); + gtog(t3, Ad); + gtog(t2, An); /* An/Ad is now A + 2. */ +} + + +void +ensure( + int q +) +{ + int nsh, j; + + N = newgiant(INFINITY); + if(!q) + { + gread(N,stdin); + q = bitlen(N) + 1; + } + nsh = q/4; /* Allowing (easily) enough space per giant, + since N is about 2^q, which is q bits, or + q/16 shorts. But squaring, etc. is allowed, + so we need at least q/8, and we choose q/4 + to be conservative. */ + if (!xr) + xr = newgiant(nsh); + if (!zr) + zr = newgiant(nsh); + if (!xs) + xs = newgiant(nsh); + if (!zs) + zs = newgiant(nsh); + if (!xorg) + xorg = newgiant(nsh); + if (!zorg) + zorg = newgiant(nsh); + if (!t1) + t1 = newgiant(nsh); + if (!t2) + t2 = newgiant(nsh); + if (!t3) + t3 = newgiant(nsh); + if (!gg) + gg = newgiant(nsh); + if (!An) + An = newgiant(nsh); + if (!Ad) + Ad = newgiant(nsh); + for (j=0;j 4) + /* This segment only takes effect in random mode. */ + limitbits = atoi(argv[argc-2]); + } + else + { + randmode = 0; + } + + modmode = 0; + if (argc > 2) + { + modmode = atoi(argv[1]); + Q = atoi(argv[2]); + } + if (modmode==0) + Q = 0; + ensure(Q); + if (modmode) + { + itog(1, N); + gshiftleft(Q, N); + itog(modmode, t1); + addg(t1, N); + } + pr[0] = 2; + for (k=0, npr=1;; k++) + { + if (primeq(3+2*k)) + { + pr[npr++] = 3+2*k; + if (npr >= NUM_PRIMES) + break; + } + } + + if (randmode == 0) + { + printf("Sieving...\n"); + fflush(stdout); + for (j=0; j < NUM_PRIMES; j++) + { + gtog(N, t1); + rem = idivg(pr[j], t1); + if (rem == 0) + { + printf("%d ", pr[j]); + gtog(t1, N); + if (isone(N)) + { + printf("\n"); + exit(0); + } + else + { + printf("* "); + fflush(stdout); + } + --j; + } + } + + if (bigprimeq(N)) + { + gout(N); + exit(0); + } + + printf("\n"); + printf("Commencing Pollard rho...\n"); + fflush(stdout); + itog(1, gg); + itog(3, t1); itog(3, t2); + + for (j=0; j < 15000; j++) + { + if((j%100) == 0) + { + dot(); + gcdg(N, gg); + if (!isone(gg)) + break; + } + squareg(t1); + iaddg(2, t1); + s_modg(N, t1); + squareg(t2); + iaddg(2, t2); + s_modg(N, t2); + squareg(t2); + iaddg(2, t2); + s_modg(N, t2); + gtog(t2, t3); + subg(t1, t3); + t3->sign = abs(t3->sign); + mulg(t3, gg); + s_modg(N, gg); + } + gcdg(N, gg); + + if ((gcompg(N,gg) != 0) && (!isone(gg))) + { + fprintf(stdout,"\n"); + gout(gg); + reset_mod(gg, N); + if (isone(N)) + { + printf("\n"); + exit(0); + } + else + { + printf("* "); + fflush(stdout); + } + if (bigprimeq(N)) + { + gout(N); + exit(0); + } + } + + printf("\n"); + printf("Commencing Pollard (p-1)...\n"); + fflush(stdout); + itog(1, gg); + itog(3, t1); + for (j=0; j< NUM_PRIMES; j++) + { + cnt = (int)(8*log(2.0)/log(1.0*pr[j])); + if (cnt < 2) + cnt = 1; + for (k=0; k< cnt; k++) + { + powermod(t1, pr[j], N); + } + itog(1, t2); + subg(t1, t2); + mulg(t2, gg); + s_modg(N, gg); + + if (j % 100 == 0) + { + dot(); + gcdg(N, gg); + if (!isone(gg)) + break; + } + } + gcdg(N, gg); + if ((gcompg(N,gg) != 0) && (!isone(gg))) + { + fprintf(stdout,"\n"); + gout(gg); + reset_mod(gg, N); + if (isone(N)) + { + printf("\n"); + exit(0); + } + else + { + printf("* "); + fflush(stdout); + } + if (bigprimeq(N)) + { + gout(N); + exit(0); + } + } + } /* This is the end of (randmode == 0) */ + + printf("\n"); + printf("Commencing ECM...\n"); + fflush(stdout); + + if (randmode) + set_random_seed(); + pass = 0; + while (++pass) + { + if (randmode == 0) + { + if (pass <= 3) + { + B = 1000; + } + else if (pass <= 10) + { + B = 10000; + } + else if (pass <= 100) + { + B = 100000L; + } else + { + B = 1000000L; + } + } + else + { + B = 2000000L; + } + C = 50*((int)B); + + /* Next, choose curve with order divisible by 16 and choose + * a point (xr/zr) on said curve. + */ + + /* Order-div-12 case. + * cnt = 8020345; Brent's parameter for stage one discovery + * of 27-digit factor of F_13. + */ + + cnt = psi_rand(); /* cnt = 8020345; */ + choose12(xr, zr, cnt, An, Ad, N); + printf("Choosing curve %d, with s = %d, B = %d, C = %d:\n", pass,cnt, B, C); fflush(stdout); + cnt = 0; + nshorts = 1; + count = 0; + for (j=0;jlimitbits)) + { + fprintf(stdout,"\n"); + gwriteln(gg, stdout); + fflush(stdout); + reset_mod(gg, N); + if (isone(N)) + { + printf("\n"); + exit(0); + } + else + { + printf("* "); + fflush(stdout); + } + if (bigprimeq(N)) + { + gout(N); + exit(0); + } + continue; + } + else + { + printf("\n"); + fflush(stdout); + } + + /* Continue; Invoke, to test Stage 1 only. */ + k = ((int)B)/D; + gtog(xr, xb[0]); + gtog(zr, zb[0]); + ell_mul(xb[0], zb[0], k*D+1 , An, Ad, N); + gtog(xr, xb[D+1]); + gtog(zr, zb[D+1]); + ell_mul(xb[D+1], zb[D+1], (k+2)*D+1 , An, Ad, N); + + for (j=1; j <= D; j++) + { + gtog(xr, xb[j]); + gtog(zr, zb[j]); + ell_mul(xb[j], zb[j], 2*j , An, Ad, N); + gtog(zb[j], xzb[j]); + mulg(xb[j], xzb[j]); + s_modg(N, xzb[j]); + } + modcount = 0; + printf("\nCommencing second stage, curve %d...\n",pass); fflush(stdout); + count = 0; + itog(1, gg); + + while (1) + { + gtog(zb[0], xzb[0]); + mulg(xb[0], xzb[0]); + s_modg(N, xzb[0]); + mulg(zb[0], gg); + s_modg(N,gg); /* Accumulate. */ + for (j = 1; j < D; j++) + { + if (!isprime(k*D+1+ 2*j)) + continue; + + /* Next, accumulate (xa - xb)(za + zb) - xa za + xb zb. */ + gtog(xb[0], t1); + subg(xb[j], t1); + gtog(zb[0], t2); + addg(zb[j], t2); + mulg(t1, t2); + s_modg(N, t1); + subg(xzb[0], t2); + addg(xzb[j], t2); + s_modg(N, t2); + --modcount; + mulg(t2, gg); + s_modg(N, gg); + if((++count)%1000==0) + dot(); + } + + k += 2; + if(k*D > C) + break; + gtog(xb[D+1], xs); + gtog(zb[D+1], zs); + ell_odd(xb[D], zb[D], xb[D+1], zb[D+1], xb[0], zb[0], N); + gtog(xs, xb[0]); + gtog(zs, zb[0]); + } + + gcdg(N, gg); + if((!isone(gg))&&(bitlen(gg)>limitbits)) + { + fprintf(stdout,"\n"); + gwriteln(gg, stdout); + fflush(stdout); + reset_mod(gg, N); + if (isone(N)) + { + printf("\n"); + exit(0); + } + else + { + printf("* "); + fflush(stdout); + } + if (bigprimeq(N)) + { + gout(N); + exit(0); + } + continue; + } + + printf("\n"); + fflush(stdout); + } + + return 0; +} + diff --git a/libsecurity_cryptkit/lib/CurveParamDocs/fmodule.c b/libsecurity_cryptkit/lib/CurveParamDocs/fmodule.c new file mode 100644 index 00000000..492b33b3 --- /dev/null +++ b/libsecurity_cryptkit/lib/CurveParamDocs/fmodule.c @@ -0,0 +1,410 @@ +/************************************************************** + * + * fmodule.c + * + * Factoring utilities. + * + * Updates: + * 13 Apr 98 REC - creation + * + * c. 1998 Perfectly Scientific, Inc. + * All Rights Reserved. + * + * + *************************************************************/ + +/* include files */ + +#include +#include +#include +#include +#ifdef _WIN32 + +#include + +#endif + +#include +#include "giants.h" +#include "fmodule.h" +#include "ellmont.h" + +#define NUM_PRIMES 6542 /* PrimePi[2^16]. */ +#define GENERAL_MOD 0 +#define FERMAT_MOD 1 +#define MERSENNE_MOD (-1) +#define D 100 /* A decimation parameter for stage-2 ECM factoring. */ + +/* compiler options */ + +#ifdef _WIN32 +#pragma warning( disable : 4127 4706 ) /* disable conditional is constant warning */ +#endif + + +/* global variables */ + +extern int pr[NUM_PRIMES]; /* Primes array from tools.c. */ + +unsigned short factors[NUM_PRIMES], exponents[NUM_PRIMES]; +int modmode = GENERAL_MOD; +int curshorts = 0; +static giant t1 = NULL, t2 = NULL, t3 = NULL, t4 = NULL; +static giant An = NULL, Ad = NULL; +static point_mont pt1, pt2; +point_mont pb[D+2]; +giant xzb[D+2]; + +static int verbosity = 0; + +/************************************************************** + * + * Functions + * + **************************************************************/ + +int +init_fmodule(int shorts) { + curshorts = shorts; + pb[0] = NULL; /* To guarantee proper ECM initialization. */ + t1 = newgiant(shorts); + t2 = newgiant(shorts); + t3 = newgiant(shorts); + t4 = newgiant(shorts); + An = newgiant(shorts); + Ad = newgiant(shorts); + pt1 = new_point_mont(shorts); + pt2 = new_point_mont(shorts); +} + +void +verbose(int state) +/* Call verbose(1) for output during factoring processes, + call verbose(0) to silence all that. + */ +{ + verbosity = state; +} + +void +dot(void) +{ + printf("."); + fflush(stdout); +} + +void +set_mod_mode(int mode) +/* Call this with mode := 1, 0, -1, for Fermat-mod, general mod, and Mersenne mod, + respectively; the point being that the special cases of + Fermat- and Mersenne-mod are much faster than + general mod. If all mods will be with respect to a number-to-be-factored, + of the form N = 2^m + 1, use Fermat mod; while if N = 2^m-1, use Mersenne mod. + */ +{ + modmode = mode; +} + +void +special_modg( + giant N, + giant t +) +{ + switch (modmode) + { + case MERSENNE_MOD: + mersennemod(bitlen(N), t); + break; + case FERMAT_MOD: + fermatmod(bitlen(N)-1, t); + break; + default: + modg(N, t); + break; + } +} + +unsigned short * +prime_list() { + return(&factors[0]); +} + +unsigned short * +exponent_list() { + return(&exponents[0]); +} + +int +sieve(giant N, int sievelim) +/* Returns number of N's prime factors < min(sievelim, 2^16), + with N reduced accordingly by said factors. + The n-th entry of factors[] becomes the n-th prime + factor of N, with corresponding exponent + becoming the n-th element of exponents[]. + */ +{ int j, pcount, rem; + unsigned short pri; + + pcount = 0; + exponents[0] = 0; + for (j=0; j < NUM_PRIMES; j++) + { + pri = pr[j]; + if(pri > sievelim) break; + do { + gtog(N, t1); + rem = idivg(pri, t1); + if(rem == 0) { + ++exponents[pcount]; + gtog(t1, N); + } + } while(rem == 0); + if(exponents[pcount] > 0) { + factors[pcount] = pr[j]; + ++pcount; + exponents[pcount] = 0; + } + } + return(pcount); +} + +int +pollard_rho(giant N, giant fact, int steps, int abort) +/* Perform Pollard-rho x:= 3; loop(x:= x^2 + 2), a total of steps times. + Parameter fact will be a nontrivial factor found, in which case + N is also modified as: N := N/fact. + The function returns 0 if no nontrivial factor found, else returns 1. + The abort parameter, when set, causes the factorer to exit on the + first nontrivial factor found (the requisite GCD is checked + every 1000 steps). If abort := 0, the full number + of steps are always performed, then one solitary GCD is taken, + before exit. + */ +{ + int j, found = 0; + + itog(3, t1); + gtog(t1, t2); + itog(1, fact); + for(j=0; j < steps; j++) { + squareg(t1); iaddg(2, t1); special_modg(N, t1); + squareg(t2); iaddg(2, t2); special_modg(N, t2); + squareg(t2); iaddg(2, t2); special_modg(N, t2); + gtog(t2, t3); subg(t1,t3); mulg(t3, fact); special_modg(N, fact); + if(((j % 1000 == 999) && abort) || (j == steps-1)) { + if(verbosity) dot(); + gcdg(N, fact); + if(!isone(fact)) { + found = (gcompg(N, fact) == 0) ? 0 : 1; + break; + } + } + } + if(verbosity) { printf("\n"); fflush(stdout); } + if(found) { + divg(fact, N); + return(1); + } + itog(1, fact); + return(0); +} + +int +pollard_pminus1(giant N, giant fact, int lim, int abort) +/* Perform Pollard-(p-1); where we test + + GCD[N, 3^P - 1], + + where P is an accumulation of primes <= min(lim, 2^16), + to appropriate powers. + Parameter fact will be a nontrivial factor found, in which case + N is also modified as: N := N/fact. + The function returns 0 if no nontrivial factor found, else returns 1. + The abort parameter, when set, causes the factorer to exit on the + first nontrivial factor found (the requisite GCD is checked + every 100 steps). If abort := 0, the full number + of steps are always performed, then one solitary GCD is taken, + before exit. + */ +{ int cnt, j, k, pri, found = 0; + + itog(3, fact); + for (j=0; j< NUM_PRIMES; j++) + { + pri = pr[j]; + if((pri > lim) || (j == NUM_PRIMES-1) || (abort && (j % 100 == 99))) { + if(verbosity) dot(); + gtog(fact, t1); + itog(1, t2); + subg(t2, t1); + special_modg(N, t1); + gcdg(N, t1); + if(!isone(t1)) { + found = (gcompg(N, t1) == 0) ? 0 : 1; + break; + } + if(pri > lim) break; + } + if(pri < 19) { cnt = 20-pri; /* Smaller primes get higher powers. */ + } else if(pri < 100) { + cnt = 2; + } else cnt = 1; + for (k=0; k< cnt; k++) + { + powermod(fact, pri, N); + } + } + if(verbosity) { printf("\n"); fflush(stdout); } + if(found) { + gtog(t1, fact); + divg(fact, N); + return(1); + } + itog(1, fact); + return(0); +} + +int +ecm(giant N, giant fact, int S, unsigned int B, unsigned int C) +/* Perform elliptic curve method (ECM), with: + Brent seed parameter = S + Stage-one limit = B + Stage-two limit = C + This function: + returns 1 if nontrivial factor is found in stage 1 of ECM; + returns 2 if nontrivial factor is found in stage 2 of ECM; + returns 0 otherwise. + In the positive return, parameter fact is the factor and N := N/fact. + */ +{ unsigned int pri, q; + int j, cnt, count, k; + + if(verbosity) { + printf("Finding curve and point, B = %u, C = %u, seed = %d...", B, C, S); + fflush(stdout); + } + find_curve_point_brent(pt1, S, An, Ad, N); + if(verbosity) { + printf("\n"); + printf("Commencing stage 1 of ECM...\n"); + fflush(stdout); + } + + q = pr[NUM_PRIMES-1]; + count = 0; + for(j=0; ; j++) { + if(j < NUM_PRIMES) { + pri = pr[j]; + } else { + q += 2; + if(primeq(q)) pri = q; + else continue; + } + if(verbosity) if((++count) % 100 == 0) dot(); + if(pri > B) break; + if(pri < 19) { cnt = 20-pri; + } else if(pri < 100) { + cnt = 2; + } else cnt = 1; + for(k = 0; k < cnt; k++) + ell_mul_int_brent(pt1, pri, An, Ad, N); + } + k = 19; + while (kz, fact); + gcdg(N, fact); + if((!isone(fact)) && (gcompg(N, fact) != 0)) { + divg(fact, N); + return(1); + } + if(B >= C) { /* No stage 2 planned. */ + itog(1, fact); + return(0); + } + +/* Commence second stage of ECM. */ + if(verbosity) { + printf("\n"); + printf("Commencing stage 2 of ECM...\n"); + fflush(stdout); + } + if(pb[0] == NULL) { + for(k=0; k < D+2; k++) { + pb[k] = new_point_mont(curshorts); + xzb[k] = newgiant(curshorts); + + } + } + k = ((int)B)/D; + ptop_mont(pt1, pb[0]); + ell_mul_int_brent(pb[0], k*D+1 , An, Ad, N); + ptop_mont(pt1, pb[D+1]); + ell_mul_int_brent(pb[D+1], (k+2)*D+1 , An, Ad, N); + + for (j=1; j <= D; j++) + { + ptop_mont(pt1, pb[j]); + ell_mul_int_brent(pb[j], 2*j , An, Ad, N); + gtog(pb[j]->z, xzb[j]); + mulg(pb[j]->x, xzb[j]); + special_modg(N, xzb[j]); + } + itog(1, fact); + count = 0; + while (1) { + if(verbosity) if((++count) % 10 == 0) dot(); + gtog(pb[0]->z, xzb[0]); + mulg(pb[0]->x, xzb[0]); + special_modg(N, xzb[0]); + mulg(pb[0]->z, fact); + special_modg(N, fact); /* Accumulate. */ + for (j = 1; j < D; j++) { + if (!primeq(k*D+1+2*j)) continue; +/* Next, accumulate (xa - xb)(za + zb) - xa za + xb zb. */ + gtog(pb[0]->x, t1); + subg(pb[j]->x, t1); + gtog(pb[0]->z, t2); + addg(pb[j]->z, t2); + mulg(t1, t2); + special_modg(N, t1); + subg(xzb[0], t2); + addg(xzb[j], t2); + special_modg(N, t2); + mulg(t2, fact); + special_modg(N, fact); + } + k += 2; + if(k*D > C) + break; + ptop_mont(pb[D+1], pt2); + ell_odd_brent(pb[D], pb[D+1], pb[0], N); + ptop_mont(pt2, pb[0]); + } + if(verbosity) { printf("\n"); fflush(stdout); } + + gcdg(N, fact); + if((!isone(fact)) && (gcompg(N, fact) != 0)) { + divg(fact, N); + return(2); /* Return value of 2 for stage-2 success! */ + } + itog(1, fact); + return(0); +} + + diff --git a/libsecurity_cryptkit/lib/CurveParamDocs/fmodule.h b/libsecurity_cryptkit/lib/CurveParamDocs/fmodule.h new file mode 100644 index 00000000..36070812 --- /dev/null +++ b/libsecurity_cryptkit/lib/CurveParamDocs/fmodule.h @@ -0,0 +1,36 @@ +/************************************************************** + * + * fmodule.h + * + * Header file for fmodule.c. + * + * Updates: + * 13 Apr 98 REC - creation + * + * c. 1998 Perfectly Scientific, Inc. + * All Rights Reserved. + * + * + *************************************************************/ + +#define GENERAL_MOD 0 +#define FERMAT_MOD 1 +#define MERSENNE_MOD (-1) + +int +init_fmodule(int shorts); + +void +s_modg( + giant N, + giant t +); + +unsigned short * +prime_list(); + +unsigned short * +exponent_list(); + +int +sieve(giant N, int sievelim); diff --git a/libsecurity_cryptkit/lib/CurveParamDocs/giants.c b/libsecurity_cryptkit/lib/CurveParamDocs/giants.c new file mode 100644 index 00000000..abf62d26 --- /dev/null +++ b/libsecurity_cryptkit/lib/CurveParamDocs/giants.c @@ -0,0 +1,3517 @@ +/************************************************************** + * + * giants.c + * + * Library for large-integer arithmetic. + * + * The large-gcd implementation is due to J. P. Buhler. + * Special mod routines use ideas of R. McIntosh. + * Contributions from G. Woltman, A. Powell acknowledged. + * + * Updates: + * 18 Jul 99 REC Added routine fer_mod(), for use when Fermat + giant itself is available. + * 17 Jul 99 REC Fixed sign bug in fermatmod() + * 17 Apr 99 REC Fixed various comment/line wraps + * 25 Mar 99 REC G. Woltman/A. Powell fixes Karat. routines + * 05 Mar 99 REC Moved invaux, binvaux giants to stack + * 05 Mar 99 REC Moved gread/gwrite giants to stack + * 05 Mar 99 REC No static on cur_den, cur_recip (A. Powell) + * 28 Feb 99 REC Error detection added atop newgiant(). + * 27 Feb 99 REC Reduced wasted work in addsignal(). + * 27 Feb 99 REC Reduced wasted work in FFTmulg(). + * 19 Feb 99 REC Generalized iaddg() per R. Mcintosh. + * 2 Feb 99 REC Fixed comments. + * 6 Dec 98 REC Fixed yet another Karatsuba glitch. + * 1 Dec 98 REC Fixed errant case of addg(). + * 28 Nov 98 REC Installed A. Powell's (correct) variant of + Karatsuba multiply. + * 15 May 98 REC Modified gwrite() to handle huge integers. + * 13 May 98 REC Changed to static stack declarations + * 11 May 98 REC Installed Karatsuba multiply, to handle + * medregion 'twixt grammar- and FFT-multiply. + * 1 May 98 JF gshifts now handle bits < 0 correctly. + * 30 Apr 98 JF 68k assembler code removed, + * stack giant size now invariant and based + * on first call of newgiant(), + * stack memory leaks fixed. + * 29 Apr 98 JF function prototyes cleaned up, + * GCD no longer uses personal stack, + * optimized shifts for bits%16 == 0. + * 27 Apr 98 JF scratch giants now replaced with stack + * 20 Apr 98 JF grammarsquareg fixed for asize == 0. + * scratch giants now static. + * 29 Jan 98 JF Corrected out-of-range errors in + * mersennemod and fermatmod. + * 23 Dec 97 REC Sped up divide routines via split-shift. + * 18 Nov 97 JF Improved mersennemod, fermatmod. + * 9 Nov 97 JF Sped up grammarsquareg. + * 20 May 97 RDW Fixed Win32 compiler warnings. + * 18 May 97 REC Installed new, fast divide. + * 17 May 97 REC Reduced memory for FFT multiply. + * 26 Apr 97 REC Creation. + * + * c. 1997,1998 Perfectly Scientific, Inc. + * All Rights Reserved. + * + **************************************************************/ + + +/* Include Files. */ + +#include +#include +#include +#include +#include "giants.h" + + +/* Compiler options. */ + +#ifdef _WIN32 +#pragma warning( disable : 4127 4706 ) /* disable conditional is constant warning */ +#endif + + +/* Global variables. */ + +int error = 0; +int mulmode = AUTO_MUL; +int cur_prec = 0; +int cur_shift = 0; +static int cur_stack_size = 0; +static int cur_stack_elem = 0; +static int stack_glen = 0; +static giant *stack; +giant cur_den = NULL, + cur_recip = NULL; +int current_max_size = 0, + cur_run = 0; +double * sinCos=NULL; +int checkFFTerror = 0; +double maxFFTerror; +static giant u0=NULL, u1=NULL, v0=NULL, v1=NULL; +static double *z = NULL, + *z2 = NULL; + +/* stack handling functions. */ +static giant popg(void); +static void pushg(int); + + +/* Private function prototypes. */ + +int gerr(void); +double gfloor(double); +int radixdiv(int, int, giant); +void columnwrite(FILE *, short *, char *, short, int); + +void normal_addg(giant, giant); +void normal_subg(giant, giant); +void reverse_subg(giant, giant); +int binvaux(giant, giant); +int invaux(giant, giant); +int allzeros(int, int, giant); +void auxmulg(giant a, giant b); +void karatmulg(giant a, giant b); +void karatsquareg(giant b); +void grammarmulg(giant a, giant b); +void grammarsquareg(giant b); + +int lpt(int, int *); +void addsignal(giant, double *, int); +void FFTsquareg(giant x); +void FFTmulg(giant y, giant x); +void scramble_real(); +void fft_real_to_hermitian(double *z, int n); +void fftinv_hermitian_to_real(double *z, int n); +void mul_hermitian(double *a, double *b, int n); +void square_hermitian(double *b, int n); +void giant_to_double(giant x, int sizex, double *z, int L); +void gswap(giant *, giant *); +void onestep(giant, giant, gmatrix); +void mulvM(gmatrix, giant, giant); +void mulmM(gmatrix, gmatrix); +void writeM(gmatrix); +static void punch(giant, gmatrix); +static void dotproduct(giant, giant, giant, giant); +void fix(giant *, giant *); +void hgcd(int, giant, giant, gmatrix); +void shgcd(int, int, gmatrix); + + + +/************************************************************** + * + * Functions + * + **************************************************************/ + + +/************************************************************** + * + * Initialization and utility functions + * + **************************************************************/ + +double +gfloor( + double f +) +{ + return floor(f); +} + + +void +init_sinCos( + int n +) +{ + int j; + double e = TWOPI/n; + + if (n<=cur_run) + return; + cur_run = n; + if (sinCos) + free(sinCos); + sinCos = (double *)malloc(sizeof(double)*(1+(n>>2))); + for (j=0;j<=(n>>2);j++) + { + sinCos[j] = sin(e*j); + } +} + + +double +s_sin( + int n +) +{ + int seg = n/(cur_run>>2); + + switch (seg) + { + case 0: return(sinCos[n]); + case 1: return(sinCos[(cur_run>>1)-n]); + case 2: return(-sinCos[n-(cur_run>>1)]); + case 3: return(-sinCos[cur_run-n]); + } + return 0; +} + + +double +s_cos( + int n +) +{ + int quart = (cur_run>>2); + + if (n < quart) + return(s_sin(n+quart)); + return(-s_sin(n-quart)); +} + + +int +gerr(void) +{ + return(error); +} + + +giant +popg ( + void +) +{ + int i; + + if (current_max_size <= 0) current_max_size = MAX_SHORTS; + + if (cur_stack_size == 0) { +/* Initialize the stack if we're just starting out. + * Note that all stack giants will be whatever current_max_size is + * when newgiant() is first called. */ + cur_stack_size = STACK_GROW; + stack = (giant *) malloc (cur_stack_size * sizeof(giant)); + for(i = 0; i < STACK_GROW; i++) + stack[i] = NULL; + if (stack_glen == 0) stack_glen = current_max_size; + } else if (cur_stack_elem >= cur_stack_size) { +/* Expand the stack if we need to. */ + i = cur_stack_size; + cur_stack_size += STACK_GROW; + stack = (giant *) realloc (stack,cur_stack_size * sizeof(giant)); + for (; i < cur_stack_size; i++) + stack[i] = NULL; + } else if (cur_stack_elem < cur_stack_size - 2*STACK_GROW) { +/* Prune the stack if it's too big. Disabled, so the stack can only expand */ + /* cur_stack_size -= STACK_GROW; + for (i = cur_stack_size - STACK_GROW; i < cur_stack_size; i++) + free(stack[i]); + stack = (giant *) realloc (stack,cur_stack_size * sizeof(giant)); */ + } + +/* Malloc our giant. */ + if (stack[cur_stack_elem] == NULL) + stack[cur_stack_elem] = malloc(stack_glen*sizeof(short)+sizeof(int)); + stack[cur_stack_elem]->sign = 0; + + return(stack[cur_stack_elem++]); +} + + +void +pushg ( + int a +) +{ + if (a < 0) return; + cur_stack_elem -= a; + if (cur_stack_elem < 0) cur_stack_elem = 0; +} + + +giant +newgiant( + int numshorts +) +{ + int size; + giant thegiant; + + if (numshorts > MAX_SHORTS) { + fprintf(stderr, "Requested giant too big.\n"); + fflush(stderr); + } + if (numshorts<=0) + numshorts = MAX_SHORTS; + size = numshorts*sizeof(short)+sizeof(int); + thegiant = (giant)malloc(size); + thegiant->sign = 0; + + if (newmin(2*numshorts,MAX_SHORTS) > current_max_size) + current_max_size = newmin(2*numshorts,MAX_SHORTS); + +/* If newgiant() is being called for the first time, set the + * size of the stack giants. */ + if (stack_glen == 0) stack_glen = current_max_size; + + return(thegiant); +} + + +gmatrix +newgmatrix( + void +) +/* Allocates space for a gmatrix struct, but does not + * allocate space for the giants. */ +{ + return((gmatrix) malloc (4*sizeof(giant))); +} + +int +bitlen( + giant n +) +{ + int b = 16, c = 1<<15, w; + + if (isZero(n)) + return(0); + w = n->n[abs(n->sign) - 1]; + while ((w&c) == 0) + { + b--; + c >>= 1; + } + return (16*(abs(n->sign)-1) + b); +} + + +int +bitval( + giant n, + int pos +) +{ + int i = abs(pos)>>4, c = 1 << (pos&15); + + return ((n->n[i]) & c); +} + + +int +isone( + giant g +) +{ + return((g->sign==1)&&(g->n[0]==1)); +} + + +int isZero( + giant thegiant +) +/* Returns TR if thegiant == 0. */ +{ + register int count; + int length = abs(thegiant->sign); + register unsigned short * numpointer = thegiant->n; + + if (length) + { + for(count = 0; countsign)*sizeof(short); + + memcpy((char *)destgiant,(char *)srcgiant,numbytes); +} + + +void +itog( + int i, + giant g +) +/* The giant g becomes set to the integer value i. */ +{ + unsigned int j = abs(i); + + if (i==0) + { + g->sign = 0; + g->n[0] = 0; + return; + } + g->n[0] = (unsigned short)(j & 0xFFFF); + j >>= 16; + if (j) + { + g->n[1] = (unsigned short)j; + g->sign = 2; + } + else + { + g->sign = 1; + } + if (i<0) + g->sign = -(g->sign); +} + + +signed int +gtoi( + giant x +) +/* Calculate the value of an int-sized giant NOT exceeding 31 bits. */ +{ + register int size = abs(x->sign); + register int sign = (x->sign < 0) ? -1 : 1; + + switch(size) + { + case 0: + break; + case 1: + return sign * x->n[0]; + case 2: + return sign * (x->n[0]+((x->n[1])<<16)); + default: + fprintf(stderr,"Giant too large for gtoi\n"); + break; + } + return 0; +} + + +int +gsign( + giant g +) +/* Returns the sign of g. */ +{ + if (isZero(g)) + return(0); + if (g->sign >0) + return(1); + return(-1); +} + + +#if 0 +int gcompg(a,b) +/* Returns -1,0,1 if ab, respectively. */ + giant a,b; +{ + int size = abs(a->sign); + + if(isZero(a)) size = 0; + if (size == 0) { + if (isZero(b)) return(0); else return(-gsign(b)); + } + + if (b->sign == 0) return(gsign(a)); + if (gsign(a)!=gsign(b)) return(gsign(a)); + if (size>abs(b->sign)) return(gsign(a)); + if (sizesign)) return(-gsign(a)); + + do { + --size; + if (a->n[size] > b->n[size]) return(gsign(a)); + if (a->n[size] < b->n[size]) return(-gsign(a)); + } while(size>0); + + return(0); +} +#else + +int +gcompg( + giant a, + giant b +) +/* Returns -1,0,1 if ab, respectively. */ +{ + int sa = a->sign, j, sb = b->sign, va, vb, sgn; + + if(sa > sb) + return(1); + if(sa < sb) + return(-1); + if(sa < 0) + { + sa = -sa; /* Take absolute value of sa. */ + sgn = -1; + } + else + { + sgn = 1; + } + for(j = sa-1; j >= 0; j--) + { + va = a->n[j]; + vb = b->n[j]; + if (va > vb) + return(sgn); + if (va < vb) + return(-sgn); + } + return(0); +} +#endif + + +void +setmulmode( + int mode +) +{ + mulmode = mode; +} + + +/************************************************************** + * + * Private I/O Functions + * + **************************************************************/ + + +int +radixdiv( + int base, + int divisor, + giant thegiant +) +/* Divides giant of arbitrary base by divisor. + * Returns remainder. Used by idivg and gread. */ +{ + int first = TR; + int finalsize = abs(thegiant->sign); + int j = finalsize-1; + unsigned short *digitpointer=&thegiant->n[j]; + unsigned int num,rem=0; + + if (divisor == 0) + { + error = DIVIDEBYZERO; + exit(error); + } + + while (j>=0) + { + num=rem*base + *digitpointer; + *digitpointer = (unsigned short)(num/divisor); + if (first) + { + if (*digitpointer == 0) + --finalsize; + else + first = FA; + } + rem = num % divisor; + --digitpointer; + --j; + } + + if ((divisor<0) ^ (thegiant->sign<0)) + finalsize=-finalsize; + thegiant->sign=finalsize; + return(rem); +} + + +void +columnwrite( + FILE *filepointer, + short *column, + char *format, + short arg, + int newlines +) +/* Used by gwriteln. */ +{ + char outstring[10]; + short i; + + sprintf(outstring,format,arg); + for (i=0; outstring[i]!=0; ++i) + { + if (newlines) + { + if (*column >= COLUMNWIDTH) + { + fputs("\\\n",filepointer); + *column = 0; + } + } + fputc(outstring[i],filepointer); + ++*column; + } +} + + +void +gwrite( + giant thegiant, + FILE *filepointer, + int newlines +) +/* Outputs thegiant to filepointer. Output is terminated by a newline. */ +{ + short column; + unsigned int i; + unsigned short *numpointer; + giant garbagegiant, basetengrand; + + basetengrand = popg(); + garbagegiant = popg(); + + if (isZero(thegiant)) + { + fputs("0",filepointer); + } + else + { + numpointer = basetengrand->n; + gtog(thegiant,garbagegiant); + + basetengrand->sign = 0; + do + { + *numpointer = (unsigned short)idivg(10000,garbagegiant); + ++numpointer; + if (++basetengrand->sign >= current_max_size) + { + error = OVFLOW; + exit(error); + } + } while (!isZero(garbagegiant)); + + if (!error) + { + i = basetengrand->sign-1; + column = 0; + if (thegiant->sign<0 && basetengrand->n[i]!=0) + columnwrite(filepointer,&column,"-",0, newlines); + columnwrite(filepointer,&column,"%d",basetengrand->n[i],newlines); + for( ; i>0; ) + { + --i; + columnwrite(filepointer,&column,"%04d",basetengrand->n[i],newlines); + } + } + } + pushg(2); +} + + +void +gwriteln( + giant theg, + FILE *filepointer +) +{ + gwrite(theg, filepointer, 1); + fputc('\n',filepointer); +} + + +void +gread( + giant theg, + FILE *filepointer +) +{ + char currentchar; + int isneg,size,backslash=FA,numdigits=0; + unsigned short *numpointer; + giant basetenthousand; + static char *inbuf = NULL; + + basetenthousand = popg(); + if (inbuf == NULL) + inbuf = (char*)malloc(MAX_DIGITS); + + currentchar = (char)fgetc(filepointer); + if (currentchar=='-') + { + isneg=TR; + } + else + { + isneg=FA; + if (currentchar!='+') + ungetc(currentchar,filepointer); + } + + do + { + currentchar = (char)fgetc(filepointer); + if ((currentchar>='0') && (currentchar<='9')) + { + inbuf[numdigits]=currentchar; + if(++numdigits==MAX_DIGITS) + break; + backslash=FA; + } + else + { + if (currentchar=='\\') + backslash=TR; + } + } while(((currentchar!=' ') && (currentchar!='\n') && + (currentchar!='\t')) || (backslash) ); + if (numdigits) + { + size = 0; + do + { + inbuf[numdigits] = 0; + numdigits-=4; + if (numdigits<0) + numdigits=0; + basetenthousand->n[size] = (unsigned short)strtol(&inbuf[numdigits],NULL,10); + ++size; + } while (numdigits>0); + + basetenthousand->sign = size; + theg->sign = 0; + numpointer = theg->n; + do + { + *numpointer = (unsigned short) + radixdiv(10000,1<<(8*sizeof(short)),basetenthousand); + ++numpointer; + if (++theg->sign >= current_max_size) + { + error = OVFLOW; + exit(error); + } + } while (!isZero(basetenthousand)); + + if (isneg) + theg->sign = -theg->sign; + } + pushg(1); +} + + + +/************************************************************** + * + * Private Math Functions + * + **************************************************************/ + + +void +negg( + giant g +) +/* g becomes -g. */ +{ + g->sign = -g->sign; +} + + +void +absg( + giant g +) +{ + /* g becomes the absolute value of g. */ + if (g->sign <0) + g->sign=-g->sign; +} + + +void +iaddg( + int i, + giant g +) +/* Giant g becomes g + (int)i. */ +{ + int w,j=0,carry = 0, size = abs(g->sign); + giant tmp; + + if (isZero(g)) + { + itog(i,g); + } + else if(g->sign < 0) { + tmp = popg(); + itog(i, tmp); + addg(tmp, g); + pushg(1); + return; + } + else + { + w = g->n[0]+i; + do + { + g->n[j] = (unsigned short) (w & 65535L); + carry = w >> 16; + w = g->n[++j]+carry; + } while ((carry!=0) && (jsign; + g->n[size] = (unsigned short)carry; + } +} + + +/* New subtract routines. + The basic subtract "subg()" uses the following logic table: + + a b if(b > a) if(a > b) + + + + b := b - a b := -(a - b) + - + b := b + (-a) N.A. + + - N.A. b := -((-b) + a) + - - b := (-a) - (-b) b := -((-b) - (-a)) + + The basic addition routine "addg()" uses: + + a b if(b > -a) if(-a > b) + + + + b := b + a N.A. + - + b := b - (-a) b := -((-a) - b) + + - b := a - (-b) b := -((-b) - a) + - - N.A. b := -((-b) + (-a)) + + In this way, internal routines "normal_addg," "normal_subg," + and "reverse_subg;" each of which assumes non-negative + operands and a non-negative result, are now used for greater + efficiency. + */ + +void +normal_addg( + giant a, + giant b +) +/* b := a + b, both a,b assumed non-negative. */ +{ + int carry = 0; + int asize = a->sign, bsize = b->sign; + long k; + int j=0; + unsigned short *aptr = a->n, *bptr = b->n; + + if (asize < bsize) + { + for (j=0; j= 65536L) + { + k -= 65536L; + ++carry; + } + *bptr++ = (unsigned short)k; + } + for (j=asize; j= 65536L) + { + k -= 65536L; + ++carry; + } + *bptr++ = (unsigned short)k; + } + } + else + { + for (j=0; j= 65536L) + { + k -= 65536L; + ++carry; + } + *bptr++ = (unsigned short)k; + } + for (j=bsize; j= 65536L) + { + k -= 65536L; + ++carry; + } + *bptr++ = (unsigned short)k; + } + } + if (carry) + { + *bptr = 1; ++j; + } + b->sign = j; +} + + +void +normal_subg( + giant a, + giant b +) +/* b := b - a; requires b, a non-negative and b >= a. */ +{ + int j, size = b->sign; + unsigned int k; + + if (a->sign == 0) + return; + + k = 0; + for (j=0; jsign; ++j) + { + k += 0xffff - a->n[j] + b->n[j]; + b->n[j] = (unsigned short)(k & 0xffff); + k >>= 16; + } + for (j=a->sign; jn[j]; + b->n[j] = (unsigned short)(k & 0xffff); + k >>= 16; + } + + if (b->n[0] == 0xffff) + iaddg(1,b); + else + ++b->n[0]; + + while ((size-- > 0) && (b->n[size]==0)); + + b->sign = (b->n[size]==0) ? 0 : size+1; +} + + +void +reverse_subg( + giant a, + giant b +) +/* b := a - b; requires b, a non-negative and a >= b. */ +{ + int j, size = a->sign; + unsigned int k; + + k = 0; + for (j=0; jsign; ++j) + { + k += 0xffff - b->n[j] + a->n[j]; + b->n[j] = (unsigned short)(k & 0xffff); + k >>= 16; + } + for (j=b->sign; jn[j]; + b->n[j] = (unsigned short)(k & 0xffff); + k >>= 16; + } + + b->sign = size; /* REC, 21 Apr 1996. */ + if (b->n[0] == 0xffff) + iaddg(1,b); + else + ++b->n[0]; + + while (!b->n[--size]); + + b->sign = size+1; +} + +void +addg( + giant a, + giant b +) +/* b := b + a, any signs any result. */ +{ + int asgn = a->sign, bsgn = b->sign; + + if (asgn == 0) + return; + if (bsgn == 0) + { + gtog(a,b); + return; + } + if ((asgn < 0) == (bsgn < 0)) + { + if (bsgn > 0) + { + normal_addg(a,b); + return; + } + absg(b); + if(a != b) absg(a); + normal_addg(a,b); + negg(b); + if(a != b) negg(a); + return; + } + if(bsgn > 0) + { + negg(a); + if (gcompg(b,a) >= 0) + { + normal_subg(a,b); + negg(a); + return; + } + reverse_subg(a,b); + negg(a); + negg(b); + return; + } + negg(b); + if(gcompg(b,a) < 0) + { + reverse_subg(a,b); + return; + } + normal_subg(a,b); + negg(b); + return; +} + +void +subg( + giant a, + giant b +) +/* b := b - a, any signs, any result. */ +{ + int asgn = a->sign, bsgn = b->sign; + + if (asgn == 0) + return; + if (bsgn == 0) + { + gtog(a,b); + negg(b); + return; + } + if ((asgn < 0) != (bsgn < 0)) + { + if (bsgn > 0) + { + negg(a); + normal_addg(a,b); + negg(a); + return; + } + negg(b); + normal_addg(a,b); + negg(b); + return; + } + if (bsgn > 0) + { + if (gcompg(b,a) >= 0) + { + normal_subg(a,b); + return; + } + reverse_subg(a,b); + negg(b); + return; + } + negg(a); + negg(b); + if (gcompg(b,a) >= 0) + { + normal_subg(a,b); + negg(a); + negg(b); + return; + } + reverse_subg(a,b); + negg(a); + return; +} + + +int +numtrailzeros( + giant g +) +/* Returns the number of trailing zero bits in g. */ +{ + register int numshorts = abs(g->sign), j, bcount=0; + register unsigned short gshort, c; + + for (j=0;jn[j]; + c = 1; + for (bcount=0;bcount<16; bcount++) + { + if (c & gshort) + break; + c <<= 1; + } + if (bcount<16) + break; + } + return(bcount + 16*j); +} + + +void +bdivg( + giant v, + giant u +) +/* u becomes greatest power of two not exceeding u/v. */ +{ + int diff = bitlen(u) - bitlen(v); + giant scratch7; + + if (diff<0) + { + itog(0,u); + return; + } + scratch7 = popg(); + gtog(v, scratch7); + gshiftleft(diff,scratch7); + if (gcompg(u,scratch7) < 0) + diff--; + if (diff<0) + { + itog(0,u); + pushg(1); + return; + } + itog(1,u); + gshiftleft(diff,u); + + pushg(1); +} + + +int +binvaux( + giant p, + giant x +) +/* Binary inverse method. Returns zero if no inverse exists, + * in which case x becomes GCD(x,p). */ +{ + + giant scratch7, u0, u1, v0, v1; + + if (isone(x)) + return(1); + u0 = popg(); + u1 = popg(); + v0 = popg(); + v1 = popg(); + itog(1, v0); + gtog(x, v1); + itog(0,x); + gtog(p, u1); + + scratch7 = popg(); + while(!isZero(v1)) + { + gtog(u1, u0); + bdivg(v1, u0); + gtog(x, scratch7); + gtog(v0, x); + mulg(u0, v0); + subg(v0,scratch7); + gtog(scratch7, v0); + + gtog(u1, scratch7); + gtog(v1, u1); + mulg(u0, v1); + subg(v1,scratch7); + gtog(scratch7, v1); + } + + pushg(1); + + if (!isone(u1)) + { + gtog(u1,x); + if(x->sign<0) addg(p, x); + pushg(4); + return(0); + } + if(x->sign<0) + addg(p, x); + pushg(4); + return(1); +} + + +int +binvg( + giant p, + giant x +) +{ + modg(p, x); + return(binvaux(p,x)); +} + + +int +invg( + giant p, + giant x +) +{ + modg(p, x); + return(invaux(p,x)); +} + +int +invaux( + giant p, + giant x +) +/* Returns zero if no inverse exists, in which case x becomes + * GCD(x,p). */ +{ + + giant scratch7, u0, u1, v0, v1; + + if ((x->sign==1)&&(x->n[0]==1)) + return(1); + + u0 = popg(); + u1 = popg(); + v0 = popg(); + v1 = popg(); + + itog(1,u1); + gtog(p, v0); + gtog(x, v1); + itog(0,x); + + scratch7 = popg(); + while (!isZero(v1)) + { + gtog(v0, u0); + divg(v1, u0); + gtog(u0, scratch7); + mulg(v1, scratch7); + subg(v0, scratch7); + negg(scratch7); + gtog(v1, v0); + gtog(scratch7, v1); + gtog(u1, scratch7); + mulg(u0, scratch7); + subg(x, scratch7); + negg(scratch7); + gtog(u1,x); + gtog(scratch7, u1); + } + pushg(1); + + if ((v0->sign!=1)||(v0->n[0]!=1)) + { + gtog(v0,x); + pushg(4); + return(0); + } + if(x->sign<0) + addg(p, x); + pushg(4); + return(1); +} + + +int +mersenneinvg( + int q, + giant x +) +{ + int k; + giant u0, u1, v1; + + u0 = popg(); + u1 = popg(); + v1 = popg(); + + itog(1, u0); + itog(0, u1); + itog(1, v1); + gshiftleft(q, v1); + subg(u0, v1); + mersennemod(q, x); + while (1) + { + k = -1; + if (isZero(x)) + { + gtog(v1, x); + pushg(3); + return(0); + } + while (bitval(x, ++k) == 0); + + gshiftright(k, x); + if (k) + { + gshiftleft(q-k, u0); + mersennemod(q, u0); + } + if (isone(x)) + break; + addg(u1, u0); + mersennemod(q, u0); + negg(u1); + addg(u0, u1); + mersennemod(q, u1); + if (!gcompg(v1,x)) { + pushg(3); + return(0); + } + addg(v1, x); + negg(v1); + addg(x, v1); + mersennemod(q, v1); + } + gtog(u0, x); + mersennemod(q,x); + pushg(3); + return(1); +} + + +void +cgcdg( + giant a, + giant v +) +/* Classical Euclid GCD. v becomes gcd(a, v). */ +{ + giant u, r; + + v->sign = abs(v->sign); + if (isZero(a)) + return; + + u = popg(); + r = popg(); + gtog(a, u); + u->sign = abs(u->sign); + while (!isZero(v)) + { + gtog(u, r); + modg(v, r); + gtog(v, u); + gtog(r, v); + } + gtog(u,v); + pushg(2); +} + + +void +gcdg( + giant x, + giant y +) +{ + if (bitlen(y)<= GCDLIMIT) + bgcdg(x,y); + else + ggcd(x,y); +} + +void +bgcdg( + giant a, + giant b +) +/* Binary form of the gcd. b becomes the gcd of a,b. */ +{ + int k = isZero(b), m = isZero(a); + giant u, v, t; + + if (k || m) + { + if (m) + { + if (k) + itog(1,b); + return; + } + if (k) + { + if (m) + itog(1,b); + else + gtog(a,b); + return; + } + } + + u = popg(); + v = popg(); + t = popg(); + + /* Now neither a nor b is zero. */ + gtog(a, u); + u->sign = abs(a->sign); + gtog(b, v); + v->sign = abs(b->sign); + k = numtrailzeros(u); + m = numtrailzeros(v); + if (k>m) + k = m; + gshiftright(k,u); + gshiftright(k,v); + if (u->n[0] & 1) + { + gtog(v, t); + negg(t); + } + else + { + gtog(u,t); + } + + while (!isZero(t)) + { + m = numtrailzeros(t); + gshiftright(m, t); + if (t->sign > 0) + { + gtog(t, u); + subg(v,t); + } + else + { + gtog(t, v); + negg(v); + addg(u,t); + } + } + gtog(u,b); + gshiftleft(k, b); + pushg(3); +} + + +void +powerg( + int m, + int n, + giant g +) +/* g becomes m^n, NO mod performed. */ +{ + giant scratch2 = popg(); + + itog(1, g); + itog(m, scratch2); + while (n) + { + if (n & 1) + mulg(scratch2, g); + n >>= 1; + if (n) + squareg(scratch2); + } + pushg(1); +} + +#if 0 +void +jtest( + giant n +) +{ + if (n->sign) + { + if (n->n[n->sign-1] == 0) + { + fprintf(stderr,"%d %d tilt",n->sign, (int)(n->n[n->sign-1])); + exit(7); + } + } +} +#endif + + +void +make_recip( + giant d, + giant r +) +/* r becomes the steady-state reciprocal + * 2^(2b)/d, where b = bit-length of d-1. */ +{ + int b; + giant tmp, tmp2; + + if (isZero(d) || (d->sign < 0)) + { + exit(SIGN); + } + tmp = popg(); + tmp2 = popg(); + itog(1, r); + subg(r, d); + b = bitlen(d); + addg(r, d); + gshiftleft(b, r); + gtog(r, tmp2); + while (1) + { + gtog(r, tmp); + squareg(tmp); + gshiftright(b, tmp); + mulg(d, tmp); + gshiftright(b, tmp); + addg(r, r); + subg(tmp, r); + if (gcompg(r, tmp2) <= 0) + break; + gtog(r, tmp2); + } + itog(1, tmp); + gshiftleft(2*b, tmp); + gtog(r, tmp2); + mulg(d, tmp2); + subg(tmp2, tmp); + itog(1, tmp2); + while (tmp->sign < 0) + { + subg(tmp2, r); + addg(d, tmp); + } + pushg(2); +} + +void +divg_via_recip( + giant d, + giant r, + giant n +) +/* n := n/d, where r is the precalculated + * steady-state reciprocal of d. */ +{ + int s = 2*(bitlen(r)-1), sign = gsign(n); + giant tmp, tmp2; + + if (isZero(d) || (d->sign < 0)) + { + exit(SIGN); + } + + tmp = popg(); + tmp2 = popg(); + + n->sign = abs(n->sign); + itog(0, tmp2); + while (1) + { + gtog(n, tmp); + mulg(r, tmp); + gshiftright(s, tmp); + addg(tmp, tmp2); + mulg(d, tmp); + subg(tmp, n); + if (gcompg(n,d) >= 0) + { + subg(d,n); + iaddg(1, tmp2); + } + if (gcompg(n,d) < 0) + break; + } + gtog(tmp2, n); + n->sign *= sign; + pushg(2); +} + +#if 1 +void +modg_via_recip( + giant d, + giant r, + giant n +) +/* This is the fastest mod of the present collection. + * n := n % d, where r is the precalculated + * steady-state reciprocal of d. */ + +{ + int s = (bitlen(r)-1), sign = n->sign; + giant tmp, tmp2; + + if (isZero(d) || (d->sign < 0)) + { + exit(SIGN); + } + + tmp = popg(); + tmp2 = popg(); + + n->sign = abs(n->sign); + while (1) + { + gtog(n, tmp); gshiftright(s-1, tmp); + mulg(r, tmp); + gshiftright(s+1, tmp); + mulg(d, tmp); + subg(tmp, n); + if (gcompg(n,d) >= 0) + subg(d,n); + if (gcompg(n,d) < 0) + break; + } + if (sign >= 0) + goto done; + if (isZero(n)) + goto done; + negg(n); + addg(d,n); +done: + pushg(2); + return; +} + +#else +void +modg_via_recip( + giant d, + giant r, + giant n +) +{ + int s = 2*(bitlen(r)-1), sign = n->sign; + giant tmp, tmp2; + + if (isZero(d) || (d->sign < 0)) + { + exit(SIGN); + } + + tmp = popg(); + tmp2 = popg() + + n->sign = abs(n->sign); + while (1) + { + gtog(n, tmp); + mulg(r, tmp); + gshiftright(s, tmp); + mulg(d, tmp); + subg(tmp, n); + if (gcompg(n,d) >= 0) + subg(d,n); + if (gcompg(n,d) < 0) + break; + } + if (sign >= 0) + goto done; + if (isZero(n)) + goto done; + negg(n); + addg(d,n); +done: + pushg(2); + return; +} +#endif + +void +modg( + giant d, + giant n +) +/* n becomes n%d. n is arbitrary, but the denominator d must be positive! */ +{ + if (cur_recip == NULL) { + cur_recip = newgiant(current_max_size); + cur_den = newgiant(current_max_size); + gtog(d, cur_den); + make_recip(d, cur_recip); + } else if (gcompg(d, cur_den)) { + gtog(d, cur_den); + make_recip(d, cur_recip); + } + modg_via_recip(d, cur_recip, n); +} + + +#if 0 +int +feemulmod ( + giant a, + giant b, + int q, + int k +) +/* a becomes (a*b) (mod 2^q-k) where q % 16 == 0 and k is "small" (0 < k < 65535). + * Returns 0 if unsuccessful, otherwise 1. */ +{ + giant carry, kk, scratch; + int i, j; + int asize = abs(a->sign), bsize = abs(b->sign); + unsigned short *aptr,*bptr,*destptr; + unsigned int words; + int kpower, curk; + + if ((q % 16) || (k <= 0) || (k >= 65535)) { + return (0); + } + + carry = popg(); + kk = popg(); + scratch = popg(); + + for (i=0; in[i]=0; + + words = q >> 4; + + bptr = b->n; + for (i = 0; i < bsize; i++) { + mult = *bptr++; + if (mult) { + kpower = i/words; + + if (kpower >= 1) itog (kpower,kk); + for (j = 1; j < kpower; k++) smulg(kpower,kk); + + itog(0,carry); + + aptr = a->n; + for (j = 0; j < bsize; b++) { + gtog(kk,scratch); + smulg(*aptr++,scratch); + smulg(mult,scratch); + iaddg(*destptr,scratch); + addg(carry,scratch); + *destptr++ = scratch->n[0]; + gshiftright(scratch,16); + gtog(scratch,carry); + if (destptr - scratch->n >= words) { + smulg(k, carry); + smulg(k, kk); + destptr -= words; + } + } + } + } + + int i,j,m; + unsigned int prod,carry=0; + int asize = abs(a->sign), bsize = abs(b->sign); + unsigned short *aptr,*bptr,*destptr; + unsigned short mult; + int words, excess; + int temp; + giant scratch = popg(), scratch2 = popg(), scratch3 = popg(); + short *carryptr = scratch->n; + int kpower,kpowerlimit, curk; + + if ((q % 16) || (k <= 0) || (k >= 65535)) { + return (0); + } + + scratch + + for (i=0; in[i]=0; + + words = q >> 4; + + bptr = b->n; + for (i=0; in; + destptr = scratch->n + i; + + if (kpower == 0) { + carry = 0; + } else if (kpower <= kpowerlimit) { + carry = 0; + curk = k; + for (j = 1; j < kpower; j++) curk *= k; + } else { + itog (k,scratch); + for (j = 1; j < kpower; j++) smulg(k,scratch); + itog(0,scratch2); + } + + for (j = 0; j < asize; j++) { + if(kpower == 0) { + prod = *aptr++ * mult + *destptr + carry; + *destptr++ = (unsigned short)(prod & 0xFFFF); + carry = prod >> 16; + } else if (kpower < kpowerlimit) { + prod = kcur * *aptr++; + temp = prod >> 16; + prod &= 0xFFFF; + temp *= mult; + prod *= mult; + temp += prod >> 16; + prod &= 0xFFFF; + prod += *destptr + carry; + carry = prod >> 16 + temp; + *destptr++ = (unsigned short)(prod & 0xFFFF); + } else { + gtog(scratch,scratch3); + smulg(*aptr++,scratch3); + smulg(mult,scratch3); + iaddg(*destptr,scratch3); + addg(scratch3,scratch2); + *destptr++ = scratch2->n[0]; + memmove(scratch2->n,scratch2->n+1,2*(scratch2->size-1)); + scratch2->sign--; + } + if (destptr - scratch->n > words) { + if (kpower == 0) { + curk = k; + carry *= k; + } else if (kpower < kpowerlimit) { + curk *= k; + carry *= curk; + } else if (kpower == kpowerlimit) { + itog (k,scratch); + for (j = 1; j < kpower; j++) smulg(k,scratch); + itog(carry,scratch2); + smulg(k,scratch2); + } else { + smulg(k,scratch); + smulg(k,scratch2); + } + kpower++; + destptr -= words; + } + } + + /* Next, deal with the carry term. Needs to be improved to + handle overflow carry cases. */ + if (kpower <= kpowerlimit) { + iaddg(carry,scratch); + } else { + addg(scratch2,scratch); + } + while(scratch->sign > q) + gtog(scratch,scratch2) + } + } + scratch->sign = destptr - scratch->n; + if (!carry) + --(scratch->sign); + scratch->sign *= gsign(a)*gsign(b); + gtog(scratch,a); + pushg(3); + return (1); +} +#endif + +int +idivg( + int divisor, + giant theg +) +{ + /* theg becomes theg/divisor. Returns remainder. */ + int n; + int base = 1<<(8*sizeof(short)); + + n = radixdiv(base,divisor,theg); + return(n); +} + + +void +divg( + giant d, + giant n +) +/* n becomes n/d. n is arbitrary, but the denominator d must be positive! */ +{ + if (cur_recip == NULL) { + cur_recip = newgiant(current_max_size); + cur_den = newgiant(current_max_size); + gtog(d, cur_den); + make_recip(d, cur_recip); + } else if (gcompg(d, cur_den)) { + gtog(d, cur_den); + make_recip(d, cur_recip); + } + divg_via_recip(d, cur_recip, n); +} + + +void +powermod( + giant x, + int n, + giant g +) +/* x becomes x^n (mod g). */ +{ + giant scratch2 = popg(); + gtog(x, scratch2); + itog(1, x); + while (n) + { + if (n & 1) + { + mulg(scratch2, x); + modg(g, x); + } + n >>= 1; + if (n) + { + squareg(scratch2); + modg(g, scratch2); + } + } + pushg(1); +} + + +void +powermodg( + giant x, + giant n, + giant g +) +/* x becomes x^n (mod g). */ +{ + int len, pos; + giant scratch2 = popg(); + + gtog(x, scratch2); + itog(1, x); + len = bitlen(n); + pos = 0; + while (1) + { + if (bitval(n, pos++)) + { + mulg(scratch2, x); + modg(g, x); + } + if (pos>=len) + break; + squareg(scratch2); + modg(g, scratch2); + } + pushg(1); +} + + +void +fermatpowermod( + giant x, + int n, + int q +) +/* x becomes x^n (mod 2^q+1). */ +{ + giant scratch2 = popg(); + + gtog(x, scratch2); + itog(1, x); + while (n) + { + if (n & 1) + { + mulg(scratch2, x); + fermatmod(q, x); + } + n >>= 1; + if (n) + { + squareg(scratch2); + fermatmod(q, scratch2); + } + } + pushg(1); +} + + +void +fermatpowermodg( + giant x, + giant n, + int q +) +/* x becomes x^n (mod 2^q+1). */ +{ + int len, pos; + giant scratch2 = popg(); + + gtog(x, scratch2); + itog(1, x); + len = bitlen(n); + pos = 0; + while (1) + { + if (bitval(n, pos++)) + { + mulg(scratch2, x); + fermatmod(q, x); + } + if (pos>=len) + break; + squareg(scratch2); + fermatmod(q, scratch2); + } + pushg(1); +} + + +void +mersennepowermod( + giant x, + int n, + int q +) +/* x becomes x^n (mod 2^q-1). */ +{ + giant scratch2 = popg(); + + gtog(x, scratch2); + itog(1, x); + while (n) + { + if (n & 1) + { + mulg(scratch2, x); + mersennemod(q, x); + } + n >>= 1; + if (n) + { + squareg(scratch2); + mersennemod(q, scratch2); + } + } + pushg(1); +} + + +void +mersennepowermodg( + giant x, + giant n, + int q +) +/* x becomes x^n (mod 2^q-1). */ +{ + int len, pos; + giant scratch2 = popg(); + + gtog(x, scratch2); + itog(1, x); + len = bitlen(n); + pos = 0; + while (1) + { + if (bitval(n, pos++)) + { + mulg(scratch2, x); + mersennemod(q, x); + } + if (pos>=len) + break; + squareg(scratch2); + mersennemod(q, scratch2); + } + pushg(1); +} + + +void +gshiftleft( + int bits, + giant g +) +/* shift g left bits bits. Equivalent to g = g*2^bits. */ +{ + int rem = bits&15, crem = 16-rem, words = bits>>4; + int size = abs(g->sign), j, k, sign = gsign(g); + unsigned short carry, dat; + + if (!bits) + return; + if (!size) + return; + if (bits < 0) { + gshiftright(-bits,g); + return; + } + if (size+words+1 > current_max_size) { + error = OVFLOW; + exit(error); + } + if (rem == 0) { + memmove(g->n + words, g->n, size * sizeof(short)); + for (j = 0; j < words; j++) g->n[j] = 0; + g->sign += (g->sign < 0)?(-words):(words); + } else { + k = size+words; + carry = 0; + for (j=size-1; j>=0; j--) { + dat = g->n[j]; + g->n[k--] = (unsigned short)((dat >> crem) | carry); + carry = (unsigned short)(dat << rem); + } + do { + g->n[k--] = carry; + carry = 0; + } while(k>=0); + + k = size+words; + if (g->n[k] == 0) + --k; + g->sign = sign*(k+1); + } +} + + +void +gshiftright( + int bits, + giant g +) +/* shift g right bits bits. Equivalent to g = g/2^bits. */ +{ + register int j,size=abs(g->sign); + register unsigned int carry; + int words = bits >> 4; + int remain = bits & 15, cremain = (16-remain); + + if (bits==0) + return; + if (isZero(g)) + return; + if (bits < 0) { + gshiftleft(-bits,g); + return; + } + if (words >= size) { + g->sign = 0; + return; + } + if (remain == 0) { + memmove(g->n,g->n + words,(size - words) * sizeof(short)); + g->sign += (g->sign < 0)?(words):(-words); + } else { + size -= words; + + if (size) + { + for(j=0;jn[j+words+1] << cremain; + g->n[j] = (unsigned short)((g->n[j+words] >> remain ) | carry); + } + g->n[size-1] = (unsigned short)(g->n[size-1+words] >> remain); + } + + if (g->n[size-1] == 0) + --size; + + if (g->sign > 0) + g->sign = size; + else + g->sign = -size; + } +} + + +void +extractbits( + int n, + giant src, + giant dest +) +/* dest becomes lowermost n bits of src. Equivalent to dest = src % 2^n. */ +{ + register int words = n >> 4, numbytes = words*sizeof(short); + register int bits = n & 15; + + if (n<=0) + return; + if (words >= abs(src->sign)) + gtog(src,dest); + else + { + memcpy((char *)(dest->n), (char *)(src->n), numbytes); + if (bits) + { + dest->n[words] = (unsigned short)(src->n[words] & ((1<n[words-1] == 0) && (words > 0)) + { + --words; + } + if (src->sign<0) + dest->sign = -words; + else + dest->sign = words; + } +} + + +int +allzeros( + int shorts, + int bits, + giant g +) +{ + int i=shorts; + + while (i>0) + { + if (g->n[--i]) + return(0); + } + return((int)(!(g->n[shorts] & ((1<>4, + bits = n & 15, + i = shorts, + mask = 1<g->sign-1; --temp) + { + g->n[temp] = 0; + } + if (g->n[shorts] & mask) + { /* if high bit is set, -g = 1. */ + g->sign = 1; + g->n[0] = 1; + return; + } + if (allzeros(shorts,bits,g)) + return; /* if g=0, -g = 0. */ + + while (i>0) + { --i; + g->n[i] = (unsigned short)(~(g->n[i+1])); + } + g->n[shorts] ^= mask-1; + + carry = 2; + i = 0; + while (carry) + { + temp = g->n[i]+carry; + g->n[i++] = (unsigned short)(temp & 0xffff); + carry = temp>>16; + } + while(!g->n[shorts]) + { + --shorts; + } + g->sign = shorts+1; +} + + +void +mersennemod ( + int n, + giant g +) +/* g := g (mod 2^n - 1) */ +{ + int the_sign, s; + giant scratch3 = popg(), scratch4 = popg(); + + if ((the_sign = gsign(g)) < 0) absg(g); + while (bitlen(g) > n) { + gtog(g,scratch3); + gshiftright(n,scratch3); + addg(scratch3,g); + gshiftleft(n,scratch3); + subg(scratch3,g); + } + if(!isZero(g)) { + if ((s = gsign(g)) < 0) absg(g); + itog(1,scratch3); + gshiftleft(n,scratch3); + itog(1,scratch4); + subg(scratch4,scratch3); + if(gcompg(g,scratch3) >= 0) subg(scratch3,g); + if (s < 0) { + g->sign = -g->sign; + addg(scratch3,g); + } + if (the_sign < 0) { + g->sign = -g->sign; + addg(scratch3,g); + } + } + pushg(2); +} + +void +fermatmod ( + int n, + giant g +) +/* g := g (mod 2^n + 1), */ +{ + int the_sign, s; + giant scratch3 = popg(); + + if ((the_sign = gsign(g)) < 0) absg(g); + while (bitlen(g) > n) { + gtog(g,scratch3); + gshiftright(n,scratch3); + subg(scratch3,g); + gshiftleft(n,scratch3); + subg(scratch3,g); + } + if((bitlen(g) < n) && (the_sign * (g->sign) >= 0)) goto leave; + if(!isZero(g)) { + if ((s = gsign(g)) < 0) absg(g); + itog(1,scratch3); + gshiftleft(n,scratch3); + iaddg(1,scratch3); + if(gcompg(g,scratch3) >= 0) subg(scratch3,g); + if (s * the_sign < 0) { + g->sign = -g->sign; + addg(scratch3,g); + } + } +leave: + pushg(1); + +} + +void +fer_mod ( + int n, + giant g, + giant modulus +) +/* Same as fermatmod(), except modulus = 2^n should be passed +if available (i.e. if already allocated and set). */ +{ + int the_sign, s; + giant scratch3 = popg(); + + if ((the_sign = gsign(g)) < 0) absg(g); + while (bitlen(g) > n) { + gtog(g,scratch3); + gshiftright(n,scratch3); + subg(scratch3,g); + gshiftleft(n,scratch3); + subg(scratch3,g); + } + if((bitlen(g) < n) && (the_sign * (g->sign) >= 0)) goto leave; + if(!isZero(g)) { + if ((s = gsign(g)) < 0) absg(g); + if(gcompg(g,modulus) >= 0) subg(modulus,g); + if (s * the_sign < 0) { + g->sign = -g->sign; + addg(modulus,g); + } + } +leave: + pushg(1); +} + + +void +smulg( + unsigned short i, + giant g +) +/* g becomes g * i. */ +{ + unsigned short carry = 0; + int size = abs(g->sign); + register int j,k,mul = abs(i); + unsigned short *digit = g->n; + + for (j=0; j>16); + *digit = (unsigned short)(k & 0xffff); + ++digit; + } + if (carry) + { + if (++j >= current_max_size) + { + error = OVFLOW; + exit(error); + } + *digit = carry; + } + + if ((g->sign>0) ^ (i>0)) + g->sign = -j; + else + g->sign = j; +} + + +void +squareg( + giant b +) +/* b becomes b^2. */ +{ + auxmulg(b,b); +} + + +void +mulg( + giant a, + giant b +) +/* b becomes a*b. */ +{ + auxmulg(a,b); +} + + +void +auxmulg( + giant a, + giant b +) +/* Optimized general multiply, b becomes a*b. Modes are: + * AUTO_MUL: switch according to empirical speed criteria. + * GRAMMAR_MUL: force grammar-school algorithm. + * KARAT_MUL: force Karatsuba divide-conquer method. + * FFT_MUL: force floating point FFT method. */ +{ + float grammartime; + int square = (a==b); + int sizea, sizeb; + + switch (mulmode) + { + case GRAMMAR_MUL: + if (square) grammarsquareg(b); + else grammarmulg(a,b); + break; + case FFT_MUL: + if (square) + FFTsquareg(b); + else + FFTmulg(a,b); + break; + case KARAT_MUL: + if (square) karatsquareg(b); + else karatmulg(a,b); + break; + case AUTO_MUL: + sizea = abs(a->sign); + sizeb = abs(b->sign); + if((sizea > KARAT_BREAK) && (sizea <= FFT_BREAK) && + (sizeb > KARAT_BREAK) && (sizeb <= FFT_BREAK)){ + if(square) karatsquareg(b); + else karatmulg(a,b); + + } else { + grammartime = (float)sizea; + grammartime *= (float)sizeb; + if (grammartime < FFT_BREAK * FFT_BREAK) + { + if (square) grammarsquareg(b); + else grammarmulg(a,b); + } + else + { + if (square) FFTsquareg(b); + else FFTmulg(a,b); + } + } + break; + } +} + +void +justg(giant x) { + int s = x->sign, sg = 1; + + if(s<0) { + sg = -1; + s = -s; + } + --s; + while(x->n[s] == 0) { + --s; + if(s < 0) break; + } + x->sign = sg*(s+1); +} + +/* Next, improved Karatsuba routines from A. Powell, + improvements by G. Woltman. */ + +void +karatmulg(giant x, giant y) +/* y becomes x*y. */ +{ + int s = abs(x->sign), t = abs(y->sign), w, bits, + sg = gsign(x)*gsign(y); + giant a, b, c, d, e, f; + + if((s <= KARAT_BREAK) || (t <= KARAT_BREAK)) { + grammarmulg(x,y); + return; + } + w = (s + t + 2)/4; bits = 16*w; + a = popg(); b = popg(); c = popg(); + d = popg(); e = popg(); f = popg(); + gtog(x,a); absg(a); if (w <= s) {a->sign = w; justg(a);} + gtog(x,b); absg(b); + gshiftright(bits, b); + gtog(y,c); absg(c); if (w <= t) {c->sign = w; justg(c);} + gtog(y,d); absg(d); + gshiftright(bits,d); + gtog(a,e); normal_addg(b,e); /* e := (a + b) */ + gtog(c,f); normal_addg(d,f); /* f := (c + d) */ + karatmulg(e,f); /* f := (a + b)(c + d) */ + karatmulg(c,a); /* a := a c */ + karatmulg(d,b); /* b := b d */ + normal_subg(a,f); + /* f := (a + b)(c + d) - a c */ + normal_subg(b,f); + /* f := (a + b)(c + d) - a c - b d */ + gshiftleft(bits, b); + normal_addg(f, b); + gshiftleft(bits, b); + normal_addg(a, b); + gtog(b, y); y->sign *= sg; + pushg(6); + + return; +} + +void +karatsquareg(giant x) +/* x becomes x^2. */ +{ + int s = abs(x->sign), w, bits; + giant a, b, c; + + if(s <= KARAT_BREAK) { + grammarsquareg(x); + return; + } + w = (s+1)/2; bits = 16*w; + a = popg(); b = popg(); c = popg(); + gtog(x, a); a->sign = w; justg(a); + gtog(x, b); absg(b); + gshiftright(bits, b); + gtog(a,c); normal_addg(b,c); + karatsquareg(c); + karatsquareg(a); + karatsquareg(b); + normal_subg(b, c); + normal_subg(a, c); + gshiftleft(bits, b); + normal_addg(c,b); + gshiftleft(bits, b); + normal_addg(a, b); + gtog(b, x); + pushg(3); + + return; +} + +void +grammarmulg( + giant a, + giant b +) +/* b becomes a*b. */ +{ + int i,j; + unsigned int prod,carry=0; + int asize = abs(a->sign), bsize = abs(b->sign); + unsigned short *aptr,*bptr,*destptr; + unsigned short mult; + giant scratch = popg(); + + for (i=0; in[i]=0; + } + + bptr = &(b->n[0]); + for (i=0; in[0]); + destptr = &(scratch->n[i]); + for (j=0; j> 16; + } + *destptr = (unsigned short)carry; + } + } + bsize+=asize; + if (!carry) + --bsize; + scratch->sign = gsign(a)*gsign(b)*bsize; + gtog(scratch,b); + pushg(1); +} + + +void +grammarsquareg ( + giant a +) +/* a := a^2. */ +{ + unsigned int cur_term; + unsigned int prod, carry=0, temp; + int asize = abs(a->sign), max = asize * 2 - 1; + unsigned short *ptr = a->n, *ptr1, *ptr2; + giant scratch; + + if(asize == 0) { + itog(0,a); + return; + } + + scratch = popg(); + + asize--; + + temp = *ptr; + temp *= temp; + scratch->n[0] = temp; + carry = temp >> 16; + + for (cur_term = 1; cur_term < max; cur_term++) { + ptr1 = ptr2 = ptr; + if (cur_term <= asize) { + ptr2 += cur_term; + } else { + ptr1 += cur_term - asize; + ptr2 += asize; + } + prod = carry & 0xFFFF; + carry >>= 16; + while(ptr1 < ptr2) { + temp = *ptr1++ * *ptr2--; + prod += (temp << 1) & 0xFFFF; + carry += (temp >> 15); + } + if (ptr1 == ptr2) { + temp = *ptr1; + temp *= temp; + prod += temp & 0xFFFF; + carry += (temp >> 16); + } + carry += prod >> 16; + scratch->n[cur_term] = (unsigned short) (prod); + } + if (carry) { + scratch->n[cur_term] = carry; + scratch->sign = cur_term+1; + } else scratch->sign = cur_term; + + gtog(scratch,a); + pushg(1); +} + + +/************************************************************** + * + * FFT multiply Functions + * + **************************************************************/ + +int initL = 0; + +int +lpt( + int n, + int *lambda +) +/* Returns least power of two greater than n. */ +{ + register int i = 1; + + *lambda = 0; + while (i maxFFTerror) + maxFFTerror = err; + } + z[j] =0; + k = 0; + do + { + g = gfloor(f*TWOM16); + z[j+k] += f-g*TWO16; + ++k; + f=g; + } while(f != 0.0); + } + car = 0; + for(j=0;j < last + 1;j++) + { + m = (int)(z[j]+car); + x->n[j] = (unsigned short)(m & 0xffff); + car = (m>>16); + } + if (car) + x->n[j] = (unsigned short)car; + else + --j; + + while(!(x->n[j])) --j; + + x->sign = j+1; +} + + +void +FFTsquareg( + giant x +) +{ + int j,size = abs(x->sign); + register int L; + + if (size<4) + { + grammarmulg(x,x); + return; + } + L = lpt(size+size, &j); + if(!z) z = (double *)malloc(MAX_SHORTS * sizeof(double)); + giant_to_double(x, size, z, L); + fft_real_to_hermitian(z, L); + square_hermitian(z, L); + fftinv_hermitian_to_real(z, L); + addsignal(x,z,L); + x->sign = abs(x->sign); +} + + +void +FFTmulg( + giant y, + giant x +) +{ + /* x becomes y*x. */ + int lambda, sizex = abs(x->sign), sizey = abs(y->sign); + int finalsign = gsign(x)*gsign(y); + register int L; + + if ((sizex<=4)||(sizey<=4)) + { + grammarmulg(y,x); + return; + } + L = lpt(sizex+sizey, &lambda); + if(!z) z = (double *)malloc(MAX_SHORTS * sizeof(double)); + if(!z2) z2 = (double *)malloc(MAX_SHORTS * sizeof(double)); + + giant_to_double(x, sizex, z, L); + giant_to_double(y, sizey, z2, L); + fft_real_to_hermitian(z, L); + fft_real_to_hermitian(z2, L); + mul_hermitian(z2, z, L); + fftinv_hermitian_to_real(z, L); + addsignal(x,z,L); + x->sign = finalsign*abs(x->sign); +} + + +void +scramble_real( + double *x, + int n +) +{ + register int i,j,k; + register double tmp; + + for (i=0,j=0;i>=1; + } + j += k; + } +} + + +void +fft_real_to_hermitian( + double *z, + int n +) +/* Output is {Re(z^[0]),...,Re(z^[n/2),Im(z^[n/2-1]),...,Im(z^[1]). + * This is a decimation-in-time, split-radix algorithm. + */ +{ + register double cc1, ss1, cc3, ss3; + register int is, id, i0, i1, i2, i3, i4, i5, i6, i7, i8, + a, a3, b, b3, nminus = n-1, dil, expand; + register double *x, e; + int nn = n>>1; + double t1, t2, t3, t4, t5, t6; + register int n2, n4, n8, i, j; + + init_sinCos(n); + expand = cur_run/n; + scramble_real(z, n); + x = z-1; /* FORTRAN compatibility. */ + is = 1; + id = 4; + do + { + for (i0=is;i0<=n;i0+=id) + { + i1 = i0+1; + e = x[i0]; + x[i0] = e + x[i1]; + x[i1] = e - x[i1]; + } + is = (id<<1)-1; + id <<= 2; + } while(is>=1) + { + n2 <<= 1; + n4 = n2>>2; + n8 = n2>>3; + is = 0; + id = n2<<1; + do + { + for (i=is;i>1; + double t1, t2, t3, t4, t5; + int n2, n4, n8, i, j; + + init_sinCos(n); + expand = cur_run/n; + x = z-1; + n2 = n<<1; + while(nn >>= 1) + { + is = 0; + id = n2; + n2 >>= 1; + n4 = n2>>2; + n8 = n4>>1; + do + { + for(i=is;i>1; + register double aa, bb, am, bm; + + b[0] *= a[0]; + b[half] *= a[half]; + for (k=1;k>1; + register double c, d; + + b[0] *= b[0]; + b[half] *= b[half]; + for (k=1;kn[j]; + } +} + + +void +gswap( + giant *p, + giant *q +) +{ + giant t; + + t = *p; + *p = *q; + *q = t; +} + + +void +onestep( + giant x, + giant y, + gmatrix A +) +/* Do one step of the euclidean algorithm and modify + * the matrix A accordingly. */ +{ + giant s4 = popg(); + + gtog(x,s4); + gtog(y,x); + gtog(s4,y); + divg(x,s4); + punch(s4,A); + mulg(x,s4); + subg(s4,y); + + pushg(1); +} + + +void +mulvM( + gmatrix A, + giant x, + giant y +) +/* Multiply vector by Matrix; changes x,y. */ +{ + giant s0 = popg(), s1 = popg(); + + gtog(A->ur,s0); + gtog( A->lr,s1); + dotproduct(x,y,A->ul,s0); + dotproduct(x,y,A->ll,s1); + gtog(s0,x); + gtog(s1,y); + + pushg(2); +} + + +void +mulmM( + gmatrix A, + gmatrix B +) +/* Multiply matrix by Matrix; changes second matrix. */ +{ + giant s0 = popg(); + giant s1 = popg(); + giant s2 = popg(); + giant s3 = popg(); + + gtog(B->ul,s0); + gtog(B->ur,s1); + gtog(B->ll,s2); + gtog(B->lr,s3); + dotproduct(A->ur,A->ul,B->ll,s0); + dotproduct(A->ur,A->ul,B->lr,s1); + dotproduct(A->ll,A->lr,B->ul,s2); + dotproduct(A->ll,A->lr,B->ur,s3); + gtog(s0,B->ul); + gtog(s1,B->ur); + gtog(s2,B->ll); + gtog(s3,B->lr); + + pushg(4); +} + + +void +writeM( + gmatrix A +) +{ + printf(" ul:"); + gout(A->ul); + printf(" ur:"); + gout(A->ur); + printf(" ll:"); + gout(A->ll); + printf(" lr:"); + gout(A->lr); +} + + +void +punch( + giant q, + gmatrix A +) +/* Multiply the matrix A on the left by [0,1,1,-q]. */ +{ + giant s0 = popg(); + + gtog(A->ll,s0); + mulg(q,A->ll); + gswap(&A->ul,&A->ll); + subg(A->ul,A->ll); + gtog(s0,A->ul); + gtog(A->lr,s0); + mulg(q,A->lr); + gswap(&A->ur,&A->lr); + subg(A->ur,A->lr); + gtog(s0,A->ur); + + pushg(1); +} + + +static void +dotproduct( + giant a, + giant b, + giant c, + giant d +) +/* Replace last argument with the dot product of two 2-vectors. */ +{ + giant s4 = popg(); + + gtog(c,s4); + mulg(a, s4); + mulg(b,d); + addg(s4,d); + + pushg(1); +} + + +void +ggcd( + giant xx, + giant yy +) +/* A giant gcd. Modifies its arguments. */ +{ + giant x = popg(), y = popg(); + gmatrix A = newgmatrix(); + + gtog(xx,x); gtog(yy,y); + for(;;) + { + fix(&x,&y); + if (bitlen(y) <= GCDLIMIT ) + break; + A->ul = popg(); + A->ur = popg(); + A->ll = popg(); + A->lr = popg(); + itog(1,A->ul); + itog(0,A->ur); + itog(0,A->ll); + itog(1,A->lr); + hgcd(0,x,y,A); + mulvM(A,x,y); + pushg(4); + fix(&x,&y); + if (bitlen(y) <= GCDLIMIT ) + break; + modg(y,x); + gswap(&x,&y); + } + bgcdg(x,y); + gtog(y,yy); + pushg(2); + free(A); +} + + +void +fix( + giant *p, + giant *q +) +/* Insure that x > y >= 0. */ +{ + if( gsign(*p) < 0 ) + negg(*p); + if( gsign(*q) < 0 ) + negg(*q); + if( gcompg(*p,*q) < 0 ) + gswap(p,q); +} + + +void +hgcd( + int n, + giant xx, + giant yy, + gmatrix A +) +/* hgcd(n,x,y,A) chops n bits off x and y and computes th + * 2 by 2 matrix A such that A[x y] is the pair of terms + * in the remainder sequence starting with x,y that is + * half the size of x. Note that the argument A is modified + * but that the arguments xx and yy are left unchanged. + */ +{ + giant x, y; + + if (isZero(yy)) + return; + + x = popg(); + y = popg(); + gtog(xx,x); + gtog(yy,y); + gshiftright(n,x); + gshiftright(n,y); + if (bitlen(x) <= INTLIMIT ) + { + shgcd(gtoi(x),gtoi(y),A); + } + else + { + gmatrix B = newgmatrix(); + int m = bitlen(x)/2; + + hgcd(m,x,y,A); + mulvM(A,x,y); + if (gsign(x) < 0) + { + negg(x); negg(A->ul); negg(A->ur); + } + if (gsign(y) < 0) + { + negg(y); negg(A->ll); negg(A->lr); + } + if (gcompg(x,y) < 0) + { + gswap(&x,&y); + gswap(&A->ul,&A->ll); + gswap(&A->ur,&A->lr); + } + if (!isZero(y)) + { + onestep(x,y,A); + m /= 2; + B->ul = popg(); + B->ur = popg(); + B->ll = popg(); + B->lr = popg(); + itog(1,B->ul); + itog(0,B->ur); + itog(0,B->ll); + itog(1,B->lr); + hgcd(m,x,y,B); + mulmM(B,A); + pushg(4); + } + free(B); + } + pushg(2); +} + + +void +shgcd( + register int x, + register int y, + gmatrix A +) +/* + * Do a half gcd on the integers a and b, putting the result in A + * It is fairly easy to use the 2 by 2 matrix description of the + * extended Euclidean algorithm to prove that the quantity q*t + * never overflows. + */ +{ + register int q, t, start = x; + int Aul = 1, Aur = 0, All = 0, Alr = 1; + + while (y != 0 && y > start/y) + { + q = x/y; + t = y; + y = x%y; + x = t; + t = All; + All = Aul-q*t; + Aul = t; + t = Alr; + Alr = Aur-q*t; + Aur = t; + } + itog(Aul,A->ul); + itog(Aur,A->ur); + itog(All,A->ll); + itog(Alr,A->lr); +} diff --git a/libsecurity_cryptkit/lib/CurveParamDocs/giants.h b/libsecurity_cryptkit/lib/CurveParamDocs/giants.h new file mode 100644 index 00000000..d25ffffb --- /dev/null +++ b/libsecurity_cryptkit/lib/CurveParamDocs/giants.h @@ -0,0 +1,314 @@ +/************************************************************** + * + * giants.h + * + * Header file for large-integer arithmetic library giants.c. + * + * Updates: + * 18 Jul 99 REC Added fer_mod(). + * 30 Apr 98 JF USE_ASSEMBLER_MUL removed + * 29 Apr 98 JF Function prototypes cleaned up + * 20 Apr 97 RDW + * + * c. 1997 Perfectly Scientific, Inc. + * All Rights Reserved. + * + **************************************************************/ + + +/************************************************************** + * + * Error Codes + * + **************************************************************/ + +#define DIVIDEBYZERO 1 +#define OVFLOW 2 +#define SIGN 3 +#define OVERRANGE 4 +#define AUTO_MUL 0 +#define GRAMMAR_MUL 1 +#define FFT_MUL 2 +#define KARAT_MUL 3 + +/************************************************************** + * + * Preprocessor definitions + * + **************************************************************/ + +/* 2^(16*MAX_SHORTS)-1 will fit into a giant, but take care: + * one usually has squares, etc. of giants involved, and + * every intermediate giant in a calculation must fit into + * this many shorts. Thus, if you want systematically to effect + * arithmetic on B-bit operands, you need MAX_SHORTS > B/8, + * perferably a tad larger than this; e.g. MAX_SHORTS > B/7. + */ +#define MAX_SHORTS (1<<19) + +#define INFINITY (-1) +#define FA 0 +#define TR 1 +#define COLUMNWIDTH 64 + +#define TWOPI (double)(2*3.1415926535897932384626433) +#define SQRT2 (double)(1.414213562373095048801688724209) +#define SQRTHALF (double)(0.707106781186547524400844362104) +#define TWO16 (double)(65536.0) +#define TWOM16 (double)(0.0000152587890625) + +/* Decimal digit ceiling in digit-input routines. */ +#define MAX_DIGITS 10000 + +/* Next, mumber of shorts per operand + at which Karatsuba breaks over. */ +#define KARAT_BREAK 40 + +/* Next, mumber of shorts per operand + at which FFT breaks over. */ +#define FFT_BREAK 200 + +#define newmin(a,b) ((a)<(b)? (a) : (b)) +#define newmax(a,b) ((a)>(b)? (a) : (b)) + +/* Maximum number of recursive steps needed to calculate + * gcds of integers. */ +#define STEPS 32 + +/* The limit below which hgcd is too ponderous */ +#define GCDLIMIT 5000 + +/* The limit below which ordinary ints will be used */ +#define INTLIMIT 31 + +/* Size by which to increment the stack used in pushg() and popg(). */ +#define STACK_GROW 16 + +#define gin(x) gread(x,stdin) +#define gout(x) gwriteln(x,stdout) + + +/************************************************************** + * + * Structure definitions + * + **************************************************************/ + +typedef struct +{ + int sign; + unsigned short n[1]; /* number of shorts = abs(sign) */ +} giantstruct; + +typedef giantstruct *giant; + +typedef struct _matrix +{ + giant ul; /* upper left */ + giant ur; /* upper right */ + giant ll; /* lower left */ + giant lr; /* lower right */ +} *gmatrix; + +typedef struct +{ + double re; + double im; +} complex; + + +/************************************************************** + * + * Function Prototypes + * + **************************************************************/ + +/************************************************************** + * + * Initialization and utility functions + * + **************************************************************/ + +/* trig lookups. */ +void init_sinCos(int); +double s_sin(int); +double s_cos(int); + + +/* Creates a new giant, numshorts = INFINITY invokes the + * maximum MAX_SHORTS. */ +giant newgiant(int numshorts); + +/* Creates a new giant matrix, but does not malloc + * the component giants. */ +gmatrix newgmatrix(void); + +/* Returns the bit-length n; e.g. n=7 returns 3. */ +int bitlen(giant n); + +/* Returns the value of the pos bit of n. */ +int bitval(giant n, int pos); + +/* Returns whether g is one. */ +int isone(giant g); + +/* Returns whether g is zero. */ +int isZero(giant g); + +/* Copies one giant to another. */ +void gtog(giant src, giant dest); + +/* Integer <-> giant. */ +void itog(int n, giant g); +signed int gtoi (giant); + +/* Returns the sign of g: -1, 0, 1. */ +int gsign(giant g); + +/* Returns 1, 0, -1 as a>b, a=b, a +#include +#include +#include +#include "giants.h" +#include "tools.h" +#include "ellproj.h" + +#define P_BREAK 32 + +#ifdef _WIN32 +#include +#define bzero(D, n) memset(D, 0x00, n) +#define bcopy(S, D, n) memcpy(D, S, n) +#endif + +#define Q_MAX 256 /* Bits in largest primes handled. */ +#define L_CEIL 100 /* Bound on Schoof L values (not all needed in general). */ + + +typedef struct + { + int deg; + giant *coe; + } polystruct; +typedef polystruct *poly; + +extern int *pr; + +static int Q, L_MAX; +static int MAX_DIGS, MAX_COEFFS; + +static giant *mcand, coe, tmp, err, aux, aux2, globx, globy, t1, t2, + t3, t4, t5; +static poly qscratch, rscratch, sscratch, tscratch, pbuff, + pbuff2, precip, cubic, powx, powy, kxn, kyn, kxd, kyd, + txn, txd, tyn, tyd, txn1, txd1, tyn1, tyd1, + nx, dx, ny, dy, mn, md, tmp1, tmp2, tmp3, tmp4; +static poly s[L_CEIL+2], smonic; +static giant p, a, b; +static int L; + +void quickmodg(giant g, giant x) +{ int sgn = x->sign; + + if(sgn == 0) return; + if(sgn > 0) { + if(gcompg(x, g) >= 0) subg(g, x); + return; + } + addg(g,x); + return; +} + +int +log_2(int n) { + int c = 1, d = -1; + while(c <= n) { + c <<= 1; + ++d; + } + return(d); +} + +void +justifyp(poly x) { + int j; + for(j = x->deg; j >= 0; j--) { + if(!is0(x->coe[j])) break; + } + x->deg = (j>0)? j : 0; +} + +void +polyrem(poly x) { + int j; + for(j=0; j <= x->deg; j++) { + modg(p, x->coe[j]); + } + justifyp(x); +} + + +giant * +newa(int n) { + giant *p = (giant *)malloc(n*sizeof(giant)); + int j; + for(j=0; jcoe = (giant *)newa(coeffs); + return(pol); +} + +void +init_all() { + int j; + + j = (2*Q + log_2(MAX_COEFFS) + 32 + 15)/16; + j = j * MAX_COEFFS; + globx = newgiant(j); + globy = newgiant(j); + s[0] = newpoly(MAX_COEFFS); + + for(j=1; j<=L_MAX+1; j++) { + s[j] = newpoly(j*(j+1)); + } + smonic = newpoly(MAX_COEFFS); + powx = newpoly(MAX_COEFFS); + powy = newpoly(MAX_COEFFS); + kxn = newpoly(MAX_COEFFS); + kxd = newpoly(MAX_COEFFS); + kyn = newpoly(MAX_COEFFS); + kyd = newpoly(MAX_COEFFS); + txn = newpoly(MAX_COEFFS); + txd = newpoly(MAX_COEFFS); + tyn = newpoly(MAX_COEFFS); + tyd = newpoly(MAX_COEFFS); + txn1 = newpoly(MAX_COEFFS); + txd1 = newpoly(MAX_COEFFS); + tyn1 = newpoly(MAX_COEFFS); + tyd1 = newpoly(MAX_COEFFS); + nx = newpoly(MAX_COEFFS); + ny = newpoly(MAX_COEFFS); + dx = newpoly(MAX_COEFFS); + dy = newpoly(MAX_COEFFS); + mn = newpoly(MAX_COEFFS); + md = newpoly(MAX_COEFFS); + tmp1 = newpoly(MAX_COEFFS); + tmp2 = newpoly(MAX_COEFFS); + tmp3 = newpoly(MAX_COEFFS); + tmp4 = newpoly(MAX_COEFFS); + mcand = (giant *)newa(MAX_COEFFS); +/* The next three need extra space for remaindering routines. */ + qscratch = newpoly(2*MAX_COEFFS); + rscratch = newpoly(2*MAX_COEFFS); + pbuff = newpoly(2*MAX_COEFFS); + pbuff2 = newpoly(MAX_COEFFS); + sscratch = newpoly(MAX_COEFFS); + tscratch = newpoly(MAX_COEFFS); + tmp = newgiant(MAX_DIGS); + err = newgiant(MAX_DIGS); + coe = newgiant(MAX_DIGS); + aux = newgiant(MAX_DIGS); + aux2 = newgiant(MAX_DIGS); + t3 = newgiant(MAX_DIGS); + t4 = newgiant(MAX_DIGS); + t5 = newgiant(MAX_DIGS); + cubic = newpoly(4); + precip = newpoly(MAX_COEFFS); +} + +void +atoa(giant *a, giant *b, int n) { + int j; + for(j=0; jdeg = x->deg; + atoa(x->coe, y->coe, y->deg+1); +} + +void +negp(poly y) +/* y := -y. */ +{ int j; + for(j=0; j <= y->deg; j++) { + negg(y->coe[j]); + quickmodg(p, y->coe[j]); + } +} + +int +iszer(giant a) { + + if(a->sign == 0) return(1); + return(0); + +} + +int +iszerop(poly x) { + if(x->deg == 0 && iszer(x->coe[0])) return 1; + return 0; +} + +int +is0(giant a) { + return(iszer(a)); +} + +int +is1(giant a) { + return(isone(a)); +} + + +void +addp(poly x, poly y) +/* y += x. */ +{ + int d = x->deg, j; + + if(y->deg > d) d = y->deg; + for(j = 0; j <= d; j++) { + if((j <= x->deg) && (j <= y->deg)) { + addg(x->coe[j], y->coe[j]); + quickmodg(p, y->coe[j]); + continue; + } + if((j <= x->deg) && (j > y->deg)) { + gtog(x->coe[j], y->coe[j]); + quickmodg(p, y->coe[j]); + continue; + } + } + y->deg = d; + justifyp(y); +} + +void +subp(poly x, poly y) +/* y -= x. */ +{ + int d = x->deg, j; + + if(y->deg > d) d = y->deg; + for(j = 0; j <= d; j++) { + if((j <= x->deg) && (j <= y->deg)) { + subg(x->coe[j], y->coe[j]); + quickmodg(p, y->coe[j]); + continue; + } + if((j <= x->deg) && (j > y->deg)) { + gtog(x->coe[j], y->coe[j]); + negg(y->coe[j]); + quickmodg(p, y->coe[j]); + continue; + } + } + y->deg = d; + justifyp(y); +} + + +void +grammarmulp(poly a, poly b) +/* b *= a. */ +{ + int dega = a->deg, degb = b->deg, deg = dega + degb; + register int d, kk, first, diffa; + + for(d=deg; d>=0; d--) { + diffa = d-dega; + itog(0, coe); + for(kk=0; kk<=d; kk++) { + if((kk>degb)||(kkcoe[kk], tmp); + mulg(a->coe[d-kk], tmp); + modg(p, tmp); + addg(tmp, coe); + quickmodg(p, coe); + } + gtog(coe, mcand[d]); + } + atoa(mcand, b->coe, deg+1); + b->deg = deg; + justifyp(b); +} + +void +atop(giant *a, poly x, int deg) +/* Copy array to poly, with monic option. */ +{ + int adeg = abs(deg); + x->deg = adeg; + atoa(a, x->coe, adeg); + if(deg < 0) { + itog(1, x->coe[adeg]); + } else { + gtog(a[adeg], x->coe[adeg]); + } +} + +void +just(giant g) { + while((g->n[g->sign-1] == 0) && (g->sign > 0)) --g->sign; +} + +void +unstuff_partial(giant g, poly y, int words){ + int j; + for(j=0; j < y->deg; j++) { + bcopy((g->n) + j*words, y->coe[j]->n, words*sizeof(short)); + y->coe[j]->sign = words; + just(y->coe[j]); + } +} + +void +stuff(poly x, giant g, int words) { + int deg = x->deg, j, coedigs; + + g->sign = words*(1 + deg); + for(j=0; j <= deg; j++) { + coedigs = (x->coe[j])->sign; + bcopy(x->coe[j]->n, (g->n) + j*words, coedigs*sizeof(short)); + bzero((g->n) + (j*words+coedigs), + sizeof(short)*(words-coedigs)); + } + just(g); +} + +int maxwords = 0; +void + +binarysegmul(poly x, poly y) { + int bits = bitlen(p), xwords, ywords, words; + + xwords = (2*bits + log_2(x->deg+1) + 32 + 15)/16; + ywords = (2*bits + log_2(y->deg+1) + 32 + 15)/16; + if(xwords > ywords) words = xwords; else words = ywords; + stuff(x, globx, words); + stuff(y, globy, words); + mulg(globx, globy); + gtog(y->coe[y->deg], globx); /* Save high coeff. */ + y->deg += x->deg; + gtog(globx, y->coe[y->deg]); /* Move high coeff. */ + unstuff_partial(globy, y, words); + mulg(x->coe[x->deg], y->coe[y->deg]); /* resolve high coeff. */ + justifyp(y); +} + +binarysegsquare(poly y) { + int bits = bitlen(p), words; + words = (2*bits + log_2(y->deg+1) + 32 + 15)/16; + stuff(y, globy, words); + squareg(globy); + gtog(y->coe[y->deg], globx); /* Save high coeff. */ + y->deg += y->deg; + gtog(globx, y->coe[y->deg]); /* Move high coeff. */ + unstuff_partial(globy, y, words); + mulg(y->coe[y->deg], y->coe[y->deg]); /* resolve high coeff. */ + justifyp(y); +} + +void +assess(poly x, poly y){ + int max = 0, j; + for(j=0; j <= x->deg; j++) { + if(bitlen(x->coe[j]) > max) max = bitlen(x->coe[j]); + } + max = 0; + for(j=0; j <= y->deg; j++) { + if(bitlen(y->coe[j]) > max) max = bitlen(y->coe[j]); + } +} + +int +pcompp(poly x, poly y) { + int j; + if(x->deg != y->deg) return 1; + for(j=0; j <= x->deg; j++) { + if(gcompg(x->coe[j], y->coe[j])) return 1; + } + return 0; +} + +/* +int max_deg = 0; +*/ + +void +mulp(poly x, poly y) +/* y *= x. */ +{ + int n, degx = x->deg, degy = y->deg; + +/* +if(degx > max_deg) { + max_deg = degx; printf("xdeg: %d\n", degx); +} + +if(degy > max_deg) { + max_deg = degy; printf("ydeg: %d\n", degy); +} +*/ + if((degx < P_BREAK) || (degy < P_BREAK)) { + grammarmulp(x,y); + justifyp(y); + return; + } + if(x==y) binarysegsquare(y); + else binarysegmul(x, y); +} + +void +revp(poly x) +/* Reverse the coefficients of x. */ +{ int j, deg = x->deg; + + for(j=0; j <= deg/2; j++) { + gtog(x->coe[deg-j], tmp); + gtog(x->coe[j], x->coe[deg-j]); + gtog(tmp, x->coe[j]); + } + justifyp(x); +} + +void +recipp(poly f, int deg) +/* f := 1/f, via newton method. */ +{ + int lim = deg + 1, prec = 1; + + sscratch->deg = 0; itog(1, sscratch->coe[0]); + itog(1, aux); + while(prec < lim) { + prec <<= 1; + if(prec > lim) prec = lim; + f->deg = prec-1; + ptop(sscratch, tscratch); + mulp(f, tscratch); + tscratch->deg = prec-1; + polyrem(tscratch); + subg(aux, tscratch->coe[0]); + quickmodg(p, tscratch->coe[0]); + mulp(sscratch, tscratch); + tscratch->deg = prec-1; + polyrem(tscratch); + subp(tscratch, sscratch); + sscratch->deg = prec-1; + polyrem(sscratch); + } + justifyp(sscratch); + ptop(sscratch, f); +} + +int +left_justifyp(poly x, int start) +/* Left-justify the polynomial, checking from position "start." */ +{ + int j, shift = 0; + + for(j = start; j <= x->deg; j++) { + if(!is0(x->coe[j])) { + shift = start; + break; + } + } + x->deg -= shift; + for(j=0; j<= x->deg; j++) { + gtog(x->coe[j+shift], x->coe[j]); + } + return(shift); +} + +void +remp(poly x, poly y, int mode) +/* y := x (mod y). + mode = 0 is normal operation, + = 1 jams a fixed reciprocal, + = 2 uses the fixed reciprocal. + */ +{ + int degx = x->deg, degy = y->deg, d, shift; + + if(degy == 0) { + y->deg = 0; + itog(0, y->coe[0]); + return; + } + d = degx - degy; + if(d < 0) { + ptop(x, y); + return; + } + revp(x); revp(y); + ptop(y, rscratch); + switch(mode) { + case 0: recipp(rscratch, d); + break; + case 1: recipp(rscratch, degy); /* degy -1. */ + ptop(rscratch, precip); + rscratch->deg = d; justifyp(rscratch); + break; + case 2: ptop(precip, rscratch); + rscratch->deg = d; justifyp(rscratch); + break; + } +/* Next, a limited-precision multiply. */ + if(d < degx) { x->deg = d; justifyp(x);} + mulp(x, rscratch); + rscratch->deg = d; + polyrem(rscratch); + justifyp(rscratch); + x->deg = degx; justifyp(x); + mulp(rscratch, y); + subp(x, y); + negp(y); polyrem(y); + shift = left_justifyp(y, d+1); + for(d = y->deg+1; d <= degx-shift; d++) itog(0, y->coe[d]); + y->deg = degx - shift; + revp(y); + revp(x); +} + +fullmod(poly x) { + polyrem(x); + ptop(smonic, s[0]); + remp(x, s[0], 2); + ptop(s[0], x); + polyrem(x); +} + +scalarmul(giant s, poly x) { + int j; + for(j=0; j <= x->deg; j++) { + mulg(s, x->coe[j]); + modg(p, x->coe[j]); + } +} + + +schain(int el) { + int j; + + s[0]->deg = 0; + itog(0, s[0]->coe[0]); + + s[1]->deg = 0; + itog(1, s[1]->coe[0]); + s[2]->deg = 0; + itog(2, s[2]->coe[0]); + + s[3]->deg = 4; + gtog(a, aux); mulg(a, aux); negg(aux); + gtog(aux, s[3]->coe[0]); + gtog(b, aux); smulg(12, aux); + gtog(aux, s[3]->coe[1]); + gtog(a, aux); smulg(6, aux); + gtog(aux, s[3]->coe[2]); + itog(0, s[3]->coe[3]); + itog(3, s[3]->coe[4]); + + s[4]->deg = 6; + gtog(a, aux); mulg(a, aux); mulg(a, aux); + gtog(b, tmp); mulg(b, tmp); smulg(8, tmp); addg(tmp, aux); + negg(aux); + gtog(aux, s[4]->coe[0]); + gtog(b, aux); mulg(a, aux); smulg(4, aux); negg(aux); + gtog(aux, s[4]->coe[1]); + gtog(a, aux); mulg(a, aux); smulg(5, aux); negg(aux); + gtog(aux, s[4]->coe[2]); + gtog(b, aux); smulg(20, aux); + gtog(aux, s[4]->coe[3]); + gtog(a, aux); smulg(5, aux); + gtog(aux, s[4]->coe[4]); + itog(0, s[4]->coe[5]); + itog(1, s[4]->coe[6]); + itog(4, aux); + scalarmul(aux, s[4]); + cubic->deg = 3; + itog(1, cubic->coe[3]); + itog(0, cubic->coe[2]); + gtog(a, cubic->coe[1]); + gtog(b, cubic->coe[0]); + for(j=5; j <= el; j++) { + if(j % 2 == 0) { + ptop(s[j/2 + 2], s[j]); mulp(s[j/2-1], s[j]); + polyrem(s[j]); mulp(s[j/2-1], s[j]); polyrem(s[j]); + ptop(s[j/2-2], s[0]); mulp(s[j/2+1], s[0]); polyrem(s[0]); + mulp(s[j/2+1], s[0]); polyrem(s[0]); + subp(s[0], s[j]); mulp(s[j/2], s[j]); polyrem(s[j]); + gtog(p, aux); iaddg(1, aux); gshiftright(1, aux); + scalarmul(aux, s[j]); + } else { + ptop(s[(j-1)/2+2], s[j]); + mulp(s[(j-1)/2], s[j]); +polyrem(s[j]); + mulp(s[(j-1)/2], s[j]); +polyrem(s[j]); + mulp(s[(j-1)/2], s[j]); +polyrem(s[j]); + ptop(s[(j-1)/2-1], s[0]); + mulp(s[(j-1)/2 + 1], s[0]); polyrem(s[0]); + mulp(s[(j-1)/2 + 1], s[0]); polyrem(s[0]); + mulp(s[(j-1)/2 + 1], s[0]); polyrem(s[0]); + if(((j-1)/2) % 2 == 1) { + mulp(cubic, s[0]); polyrem(s[0]); + mulp(cubic, s[0]); polyrem(s[0]); + } else { + mulp(cubic, s[j]); polyrem(s[j]); + mulp(cubic, s[j]); polyrem(s[j]); + } +// polyout(s[1]); polyout(s[3]); polyout(s[0]); polyout(s[j]); + subp(s[0], s[j]); + polyrem(s[j]); + } + } +} + +init_recip(int el) { + int j; + ptop(s[el], smonic); + if(el == 2) { + mulp(cubic, smonic); polyrem(smonic); + } + gtog(smonic->coe[smonic->deg], aux); /* High coeff. */ + binvg(p, aux); + scalarmul(aux, smonic); /* s is now monic. */ + s[0]->deg = smonic->deg + 1; + for(j=0; j <= s[0]->deg; j++) itog(1, s[0]->coe[j]); + ptop(smonic, pbuff); + remp(s[0], pbuff, 1); /* Initialize reciprocal of s as precip. */ +} + +/* void powerpoly(poly x, giant n) +{ int len, pos; + ptop(x, pbuff); + x->deg = 0; itog(1, x->coe[0]); + len = bitlen(n); + pos = 0; + while(1) { + if(bitval(n, pos++)) { + mulp(pbuff, x); + fullmod(x); + } + if(pos>=len) break; + mulp(pbuff, pbuff); + fullmod(pbuff); + } +} +*/ + +void powerpoly(poly x, giant n) +/* Base-4 window. */ +{ int pos, code; + ptop(x, pbuff); /* x. */ + ptop(pbuff, pbuff2); + mulmod(pbuff2, pbuff2); mulmod(pbuff, pbuff2); /* x^3. */ + pos = bitlen(n)-2; + while(pos >= 0) { + mulmod(x, x); + if(pos==0) { + if(bitval(n, pos) != 0) { + mulmod(pbuff, x); + } + break; + } + code = (bitval(n, pos) != 0) * 2 + (bitval(n, pos-1) != 0); + switch(code) { + case 0: mulmod(x,x); break; + case 1: mulmod(x,x); + mulmod(pbuff, x); + break; + case 2: mulmod(pbuff, x); + mulmod(x,x); break; + case 3: mulmod(x,x); mulmod(pbuff2, x); break; + } + pos -= 2; + } +} + +mulmod(poly x, poly y) { + mulp(x, y); fullmod(y); +} + +elldoublep(poly n1, poly d1, poly m1, poly c1, poly n0, poly d0, + poly m0, poly c0) { + + ptop(n1, mn); mulmod(n1, mn); + ptop(mn, pbuff); addp(mn, mn); addp(pbuff, mn); + fullmod(mn); + ptop(d1, pbuff); mulmod(d1, pbuff); + scalarmul(a, pbuff); addp(pbuff, mn); + fullmod(mn); + mulmod(c1, mn); + ptop(m1, md); addp(md, md); + mulmod(d1, md); mulmod(d1, md); mulmod(cubic, md); + + ptop(d1, n0); mulmod(mn, n0); mulmod(mn, n0); + mulmod(cubic, n0); + ptop(n1, pbuff); addp(pbuff, pbuff); fullmod(pbuff); + mulmod(md, pbuff); mulmod(md, pbuff); + subp(pbuff, n0); fullmod(n0); + ptop(md, d0); mulmod(md, d0); mulmod(d1, d0); + + ptop(mn, m0); mulmod(c1, m0); + ptop(d0, pbuff); mulmod(n1, pbuff); + ptop(n0, c0); mulmod(d1, c0); subp(c0, pbuff); + fullmod(pbuff); + mulmod(pbuff, m0); + ptop(m1, pbuff); mulmod(md, pbuff); + mulmod(d1, pbuff); mulmod(d0, pbuff); + subp(pbuff, m0); fullmod(m0); + + ptop(c1, c0); mulmod(md, c0); mulmod(d1, c0); mulmod(d0, c0); +} + +elladdp(poly n1, poly d1, poly m1, poly c1, poly n2, poly d2, poly m2, poly c2, poly n0, poly d0, poly m0, poly c0) { + ptop(m2, mn); mulmod(c1, mn); + ptop(m1, pbuff); mulmod(c2, pbuff); + subp(pbuff, mn); fullmod(mn); + mulmod(d1, mn); mulmod(d2, mn); + + ptop(n2, md); mulmod(d1, md); + ptop(n1, pbuff); mulmod(d2, pbuff); + subp(pbuff, md); fullmod(md); + mulmod(c1, md); mulmod(c2, md); + + ptop(cubic, n0); mulmod(mn, n0); mulmod(mn, n0); + mulmod(d1, n0); mulmod(d2, n0); + ptop(n1, pbuff); mulmod(d2, pbuff); + ptop(n2, d0); mulmod(d1, d0); + addp(d0, pbuff); mulmod(md, pbuff); mulmod(md, pbuff); + subp(pbuff, n0); fullmod(n0); + + ptop(md, d0); mulmod(md, d0); mulmod(d1, d0); mulmod(d2, d0); + + ptop(mn, m0); mulmod(c1, m0); + ptop(d0, pbuff); mulmod(n1, pbuff); + ptop(d1, c0); mulmod(n0, c0); + subp(c0, pbuff); fullmod(pbuff); + mulmod(pbuff, m0); + ptop(m1, pbuff); mulmod(md, pbuff); + mulmod(d0, pbuff); mulmod(d1, pbuff); + subp(pbuff, m0); fullmod(m0); + + ptop(md, c0); mulmod(c1, c0); mulmod(d0, c0); mulmod(d1, c0); + +} + +polyout(poly x) { + int j; + for(j=0; j <= x->deg; j++) {printf("%d: ",j); gout(x->coe[j]);} +} + +main(int argc, char **argv) { + int j, ct = 0, el, xmatch, ymatch; + int k, t; + int T[L_CEIL], P[L_CEIL], LL[L_CEIL]; + giant ss[L_CEIL]; + unsigned int ord, ordminus; + point_proj pt, pt2; + + p = newgiant(INFINITY); /* Also sets up internal giants' stacks. */ + j = ((Q_MAX+15)/16); + init_tools(2*j); + a = newgiant(j); + b = newgiant(j); + +entry: + printf("Give p > 3, a, b on separate lines:\n"); fflush(stdout); + gin(p); /* Field prime. */ + if((Q = bitlen(p)) > Q_MAX) { + fprintf(stderr, "p too large, larger than %d bits.\n", Q); + goto entry; + } + if(!prime_probable(p)) { + fprintf(stderr, "p is not but must be prime.\n", Q); + goto entry; + } + gin(a); gin(b); /* Curve parameters. */ + + t1 = newgiant(2*j); + t2 = newgiant(2*j); +/* Next, discriminant test for legitimacy of curve. */ + gtog(a, t1); squareg(t1); modg(p, t1); mulg(a, t1); modg(p, t1); + gshiftleft(2, t1); /* 4 a^3 mod p. */ + gtog(b, t2); squareg(t2); modg(p, t2); smulg(27, t2); + addg(t2, t1); modg(p, t1); + if(isZero(t1)) { + fprintf(stderr, "Discriminant FAILED\n"); + goto entry; + } + printf("Discriminant PASSED\n"); fflush(stdout); + +/* Next, find an efficient prime power array such that + Prod[powers] >= 16 p. */ + + /* Create minimal prime power array such that Prod[powers]^2 > 16p. */ + + gtog(p, t2); gshiftleft(4, t2); /* t2 := 16p. */ + + L_MAX = 3; + while(L_MAX <= L_CEIL-1) { + for(j=0; j <= L_MAX; j++) LL[j] = 0; + for(j=2; j <= L_MAX; j++) { + if(primeq(j)) { + LL[j] = 1; + k = j; + while(1) { + k *= j; + if(k <= L_MAX) { + LL[k] = 1; + LL[k/j] = 0; + } + else break; + } + } + } + itog(1, t1); + for(j=2; j <= L_MAX; j++) { + if(LL[j]) { smulg(j, t1); smulg(j, t1); } /* Building up t1^2. */ + } + if(gcompg(t1, t2) > 0) break; + ++L_MAX; + } + + printf("Initializing for prime powers:\n"); + for(j=2; j <= L_MAX; j++) { + if(LL[j]) printf("%d ", j); + } + printf("\n"); + fflush(stdout); + + + MAX_DIGS = (2 + (Q+15)/8); /* Size of (squared) coefficients. */ + MAX_COEFFS = ((L_MAX+1)*(L_MAX+2)); + + init_all(); + schain(L_MAX+1); + +for(L = 2; L <= L_MAX; L++) { + if(!LL[L]) continue; +printf("Resolving Schoof L = %d...\n", L); + P[ct] = L; /* Stuff another prime power. */ + init_recip(L); +// printf("s: "); polyout(s[L]); + gtog(p, aux2); + k = idivg(L, aux2); /* p (mod L). */ + +printf("power...\n"); + txd->deg = 0; itog(1, txd->coe[0]); + tyd->deg = 0; itog(1, tyd->coe[0]); + txn->deg = 1; itog(0, txn->coe[0]); itog(1, txn->coe[1]); + ptop(txn, kxn); + + gtog(p, aux2); + powerpoly(txn, aux2); /* x^p. */ +printf("x^p done...\n"); + ptop(txn, powx); + powerpoly(powx, aux2); +printf("x^p^2 done...\n"); + ptop(cubic, tyn); + gtog(p, aux2); itog(1, aux); subg(aux, aux2); + gshiftright(1, aux2); /* aux2 := (p-1)/2. */ + powerpoly(tyn, aux2); /* y^p. */ +printf("y^p done...\n"); + ptop(tyn, powy); mulp(tyn, powy); fullmod(powy); + mulp(cubic, powy); fullmod(powy); + powerpoly(powy, aux2); + mulp(tyn, powy); fullmod(powy); +printf("Powers done...\n"); + +// printf("pow" ); polyout(powx); polyout(powy); + ptop(txn, txn1); ptop(txd, txd1); /* Save t = 1 case. */ + ptop(tyn, tyn1); ptop(tyd, tyd1); +/* We now shall test + (powx, y powy) + k(kxn/kxd, y kyn/kyd) = t(txn/txd, y tyn/tyd) + */ + + if(k==1) { ptop(txd, kxd); ptop(txd, kyd); + ptop(txd, kyn); + } else { + ptop(s[k], kxd); mulp(s[k], kxd); fullmod(kxd); + if(k%2==0) { mulp(cubic, kxd); fullmod(kxd); } + mulp(kxd, kxn); fullmod(kxn); + ptop(s[k-1], pbuff); mulp(s[k+1], pbuff); fullmod(pbuff); + if(k%2==1) {mulp(cubic, pbuff); fullmod(pbuff); } + subp(pbuff, kxn); fullmod(kxn); + + ptop(s[k+2], kyn); mulp(s[k-1], kyn); fullmod(kyn); + mulp(s[k-1], kyn); fullmod(kyn); + if(k > 2) { + ptop(s[k-2], pbuff); mulp(s[k+1], pbuff); fullmod(pbuff); + mulp(s[k+1], pbuff); fullmod(pbuff); + subp(pbuff, kyn); fullmod(kyn); + } + ptop(s[k], kyd); mulp(s[k], kyd); fullmod(kyd); + mulp(s[k], kyd); fullmod(kyd); + if(k%2==0) { mulp(cubic, kyd); fullmod(kyd); + mulp(cubic, kyd); fullmod(kyd);} + itog(4, aux2); scalarmul(aux2, kyd); + } +//printf("kP: "); polyout(kxn); polyout(kxd); polyout(kyn); polyout(kyd); +/* Commence t = 0 check. */ +printf("Checking t = %d ...\n", 0); +fflush(stdout); + + ptop(powx, pbuff); mulp(kxd, pbuff); + subp(kxn, pbuff); + fullmod(pbuff); + + xmatch = ymatch = 0; + if(iszerop(pbuff)) { + xmatch = 1; + /* Now check y coords. */ + if(L == 2) goto resolve; + ptop(powy, pbuff); mulp(kyd, pbuff); + addp(kyn, pbuff); + fullmod(pbuff); + if(iszerop(pbuff)) { + resolve: + printf("%d %d\n", L, 0); + T[ct++] = 0; + continue; + } else ymatch = 1; + } +/* Combine pt1 and pt2. */ + if((xmatch == 1) && (ymatch == 1)) + elldoublep(powx, txd, powy, txd, nx, dx, ny, dy); + else + elladdp(powx, txd, powy, txd, kxn, kxd, kyn, kyd, nx, dx, ny, dy); +/* Now {nx/dx, ny/dy} is (fixed) LHS. */ +// printf("add12: "); polyout(nx); polyout(dx); polyout(ny); polyout(dy); +/* Commence t > 0 check. */ + for(t=1; t <= L/2; t++) { +printf("Checking t = %d ...\n", t); + if(t > 1) { /* Add (tx1, ty1) to (txn, tyn). */ + ptop(txn1, pbuff); mulmod(txd, pbuff); + ptop(txn, powx); mulmod(txd1, powx); + subp(powx, pbuff); fullmod(pbuff); + if(!iszerop(pbuff)) + elladdp(txn1, txd1, tyn1, tyd1, txn, txd, tyn, tyd, + tmp1, tmp2, tmp3, tmp4); + else elldoublep(txn, txd, tyn, tyd, + tmp1, tmp2, tmp3, tmp4); + ptop(tmp1, txn); ptop(tmp2, txd); + ptop(tmp3, tyn); ptop(tmp4, tyd); + } +// printf("tQ: "); polyout(txn); polyout(txd); polyout(tyn); polyout(tyd); + /* Next, check {nx/dx, ny/dy} =? {txn/txd, tyn/tyd}. */ + ptop(nx, pbuff); mulmod(txd, pbuff); + ptop(dx, powx); mulmod(txn, powx); + subp(powx, pbuff); fullmod(pbuff); + if(!iszerop(pbuff)) continue; + /* Next, check y. */ + // printf("y check!\n"); + ptop(ny, pbuff); mulmod(tyd, pbuff); + ptop(dy, powx); mulmod(tyn, powx); + subp(powx, pbuff); fullmod(pbuff); + if(iszerop(pbuff)) { + printf("%d %d\n", L, t); + T[ct++] = t; + } else { + printf("%d %d\n", L, L-t); + T[ct++] = L-t; + } + fflush(stdout); + break; + } +} + +/* Now, prime powers P[] and CRT residues T[] are intact. */ + printf("Prime powers L:\n"); + printf("{"); + for(j=0; j < ct-1; j++) { + printf("%d, ", P[j]); + } + printf("%d }\n", P[ct-1]); + + printf("Residues t (mod L):\n"); + printf("{"); + for(j=0; j < ct-1; j++) { + printf("%d, ", T[j]); + } + printf("%d }\n", T[ct-1]); + +/* Mathematica algorithm for order: +plis = {2^5, 3^3, 5^2, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47}; +tlis = {1, 26, 4, 2, 4, 11, 6, 5, 19, 22, 10, 16, 7, 22, 11}; +prod = Apply[Times, plis]; +prlis = prod/plis; +invlis = Table[PowerMod[prlis[[q]], -1, plis[[q]]],{q,1,Length[plis]}]; +p = 2^127 - 1; +t = Mod[tlis . (prlis * invlis), prod]; +ord = p + 1 - If[t^2 > 4p, t - prod, t] +*/ + + itog(1, t1); + for(j=0; j < ct; j++) { + free(s[j]); /* Just to clear memory. */ + smulg(P[j], t1); + } + + for(j=0; j < 2*ct; j++) { + ss[j] = newgiant(MAX_DIGS); + } + + for(j=0; j < ct; j++) { + gtog(t1, ss[j]); + itog(P[j], t2); + divg(t2, ss[j]); + } + + for(j=0; j < ct; j++) { + gtog(ss[j], ss[j+ct]); + itog(P[j], t2); + invg(t2, ss[j+ct]); + } + + itog(0, t4); + for(j=0; j < ct; j++) { + itog(T[j], t5); + mulg(ss[j], t5); + mulg(ss[j+ct], t5); + addg(t5, t4); + } + modg(t1, t4); + gtog(p, t5); + iaddg(1, t5); + gtog(t4, t2); + squareg(t4); + gtog(p, t3); gshiftleft(2, t3); + if(gcompg(t4, t3) > 0) subg(t1, t2); + subg(t2, t5); + printf("Parameters:\n"); + printf("p = "); gout(p); + printf("a = "); gout(a); + printf("b = "); gout(b); + printf("Curve order:\n"); + printf("o = "); gout(t5); gtog(t5, t3); /* Save order as t3. */ + printf("Twist order:\n"); + printf("o' = "); + addg(t2, t5); + addg(t2, t5); + gout(t5); +/* Next, verify the order. */ + printf("Verifying order o:...\n"); + init_ell_proj(MAX_DIGS); + pt = new_point_proj(MAX_DIGS); + pt2 = new_point_proj(MAX_DIGS); + itog(1,t2); + find_point_proj(pt, t2, a, b, p); + printf("A point on the curve y^2 = x^3 + a x + b (mod p) is:\n"); + printf("(x,y,z) = {\n"); gout(pt->x); printf(","); + gout(pt->y); printf(","); gout(pt->z); + printf("}\n"); + ell_mul_proj(pt, pt2, t3, a, p); + printf("A multiple is:\n"); + printf("o * (x,y,z) = {\n"); + gout(pt2->x); printf(",");gout(pt2->y); printf(",");gout(pt2->z); + printf("}\n"); + if(!isZero(pt2->z)) { + printf("TILT: multiple should be point-at-infinity.\n"); + exit(1); + } + printf("VERIFIED: multiple is indeed point-at-infinity.\n"); +} diff --git a/libsecurity_cryptkit/lib/CurveParamDocs/schoofs.c b/libsecurity_cryptkit/lib/CurveParamDocs/schoofs.c new file mode 100644 index 00000000..bf70b3ab --- /dev/null +++ b/libsecurity_cryptkit/lib/CurveParamDocs/schoofs.c @@ -0,0 +1,1044 @@ +/* schoofs.c + + Elliptic curve order calculator, for + + y^2 = x^3 + a x + b (mod p) + + (NOTE: + This version has order sieving, triggering on the + initial b parameter and incrementing same. + Parameter details are described in schoof.c) + + Compile with: + + % cc -O schoofs.c giants.c tools.c -lm -o schoofs + + and run, entering the a,b parameters. + + * Change history: + + 20 Mar 01 (REC) Added binarysegsquare() and base-4 ladder + 20 Mar 01 (REC) Bumped MAX_DIGS as in schoof.c + 4 Feb 99 (REC) Sieving invoked. + 2 Feb 99 (REC) Added explicit CRT result + 12 Jan 99 (REC) Removed (hopefully) last of memory crashes + 20 Jan 98 (REC) Creation + + * c. 1998 Perfectly Scientific, Inc. + * All Rights Reserved. + * + * + *************************************************************/ + +#include +#include +#include +#include"giants.h" +#include "tools.h" + +#define P_BREAK 32 + + +#define Q 256 /* See schoof.c for explanation. */ +#define L_MAX 100 +#define MAX_DIGS (2 + (Q+15)/8) /* Size of (squared) coefficients. */ +#define MAX_COEFFS ((L_MAX+1)*(L_MAX+2)) + +typedef struct + { + int deg; + giant *coe; + } polystruct; +typedef polystruct *poly; + + +static giant *mcand, coe, tmp, err, aux, aux2, globx, globy, t1, t2, + t3, t4, t5; +static poly qscratch, rscratch, sscratch, tscratch, pbuff, pbuff2, + precip, cubic, powx, powy, kxn, kyn, kxd, kyd, + txn, txd, tyn, tyd, txn1, txd1, tyn1, tyd1, + nx, dx, ny, dy, mn, md, tmp1, tmp2, tmp3, tmp4; +static poly s[L_MAX+2], smonic; +static giant p, a, b, magcheck; +int L; + +void quickmodg(giant g, giant x) +{ int sgn = x->sign; + + if(sgn == 0) return; + if(sgn > 0) { + if(gcompg(x, g) >= 0) subg(g, x); + return; + } + addg(g,x); + return; +} + +int +log_2(int n) { + int c = 1, d = -1; + while(c <= n) { + c <<= 1; + ++d; + } + return(d); +} + +void +justifyp(poly x) { + int j; + for(j = x->deg; j >= 0; j--) { + if(!is0(x->coe[j])) break; + } + x->deg = (j>0)? j : 0; +} + +void +polyrem(poly x) { + int j; + for(j=0; j <= x->deg; j++) { + modg(p, x->coe[j]); + } + justifyp(x); +} + + +giant * +newa(int n) { + giant *p = (giant *)malloc(n*sizeof(giant)); + int j; + for(j=0; jcoe = (giant *)newa(coeffs); + return(pol); +} + +void +init_all() { + int j; + + j = (2*Q + log_2(MAX_COEFFS) + 32 + 15)/16; + globx = newgiant(MAX_COEFFS * j); + globy = newgiant(MAX_COEFFS * j); + + init_tools(MAX_DIGS); + powx = newpoly(MAX_COEFFS); + powy = newpoly(MAX_COEFFS); + kxn = newpoly(MAX_COEFFS); + kxd = newpoly(MAX_COEFFS); + kyn = newpoly(MAX_COEFFS); + kyd = newpoly(MAX_COEFFS); + txn = newpoly(MAX_COEFFS); + txd = newpoly(MAX_COEFFS); + tyn = newpoly(MAX_COEFFS); + tyd = newpoly(MAX_COEFFS); + txn1 = newpoly(MAX_COEFFS); + txd1 = newpoly(MAX_COEFFS); + tyn1 = newpoly(MAX_COEFFS); + tyd1 = newpoly(MAX_COEFFS); + nx = newpoly(MAX_COEFFS); + ny = newpoly(MAX_COEFFS); + dx = newpoly(MAX_COEFFS); + dy = newpoly(MAX_COEFFS); + mn = newpoly(MAX_COEFFS); + md = newpoly(MAX_COEFFS); + tmp1 = newpoly(MAX_COEFFS); + tmp2 = newpoly(MAX_COEFFS); + tmp3 = newpoly(MAX_COEFFS); + tmp4 = newpoly(MAX_COEFFS); + mcand = (giant *)newa(MAX_COEFFS); + + s[0] = newpoly(MAX_COEFFS); + + for(j=1; j<=L_MAX+1; j++) { + s[j] = newpoly(j*(j+1)); + } + smonic = newpoly(MAX_COEFFS); +/* The next three need extra space for remaindering routine. */ + qscratch = newpoly(2*MAX_COEFFS); + rscratch = newpoly(2*MAX_COEFFS); + pbuff = newpoly(2*MAX_COEFFS); + pbuff2 = newpoly(MAX_COEFFS); + sscratch = newpoly(MAX_COEFFS); + tscratch = newpoly(MAX_COEFFS); + tmp = newgiant(MAX_DIGS); + err = newgiant(MAX_DIGS); + coe = newgiant(MAX_DIGS); + aux = newgiant(MAX_DIGS); + aux2 = newgiant(MAX_DIGS); + t1 = newgiant(MAX_DIGS); + t2 = newgiant(MAX_DIGS); + t3 = newgiant(MAX_DIGS); + t4 = newgiant(MAX_DIGS); + t5 = newgiant(MAX_DIGS); + cubic = newpoly(4); + p = newgiant(MAX_DIGS); + a = newgiant(MAX_DIGS); + b = newgiant(MAX_DIGS); + magcheck = newgiant(MAX_DIGS); + precip = newpoly(MAX_COEFFS); +} + +void +atoa(giant *a, giant *b, int n) { + int j; + for(j=0; jdeg = x->deg; + atoa(x->coe, y->coe, y->deg+1); +} + +void +negp(poly y) +/* y := -y. */ +{ int j; + for(j=0; j <= y->deg; j++) { + negg(y->coe[j]); + quickmodg(p, y->coe[j]); + } +} + +int +iszer(giant a) { + + if(a->sign == 0) return(1); + return(0); + +} + +int +iszerop(poly x) { + if(x->deg == 0 && iszer(x->coe[0])) return 1; + return 0; +} + +int +is0(giant a) { + return(iszer(a)); +} + +int +is1(giant a) { + return(isone(a)); +} + + +void +addp(poly x, poly y) +/* y += x. */ +{ + int d = x->deg, j; + + if(y->deg > d) d = y->deg; + for(j = 0; j <= d; j++) { + if((j <= x->deg) && (j <= y->deg)) { + addg(x->coe[j], y->coe[j]); + quickmodg(p, y->coe[j]); + continue; + } + if((j <= x->deg) && (j > y->deg)) { + gtog(x->coe[j], y->coe[j]); + quickmodg(p, y->coe[j]); + continue; + } + } + y->deg = d; + justifyp(y); +} + +void +subp(poly x, poly y) +/* y -= x. */ +{ + int d = x->deg, j; + + if(y->deg > d) d = y->deg; + for(j = 0; j <= d; j++) { + if((j <= x->deg) && (j <= y->deg)) { + subg(x->coe[j], y->coe[j]); + quickmodg(p, y->coe[j]); + continue; + } + if((j <= x->deg) && (j > y->deg)) { + gtog(x->coe[j], y->coe[j]); + negg(y->coe[j]); + quickmodg(p, y->coe[j]); + continue; + } + } + y->deg = d; + justifyp(y); +} + + +void +grammarmulp(poly a, poly b) +/* b *= a. */ +{ + int dega = a->deg, degb = b->deg, deg = dega + degb; + register int d, kk, first, diffa; + + for(d=deg; d>=0; d--) { + diffa = d-dega; + itog(0, coe); + for(kk=0; kk<=d; kk++) { + if((kk>degb)||(kkcoe[kk], tmp); + mulg(a->coe[d-kk], tmp); + modg(p, tmp); + addg(tmp, coe); + quickmodg(p, coe); + } + gtog(coe, mcand[d]); + } + atoa(mcand, b->coe, deg+1); + b->deg = deg; + justifyp(b); +} + +void +atop(giant *a, poly x, int deg) +/* Copy array to poly, with monic option. */ +{ + int adeg = abs(deg); + x->deg = adeg; + atoa(a, x->coe, adeg); + if(deg < 0) { + itog(1, x->coe[adeg]); + } else { + gtog(a[adeg], x->coe[adeg]); + } +} + +void +just(giant g) { + while((g->n[g->sign-1] == 0) && (g->sign > 0)) --g->sign; +} + +void +unstuff_partial(giant g, poly y, int words){ + int j; + for(j=0; j < y->deg; j++) { + bcopy((g->n) + j*words, y->coe[j]->n, words*sizeof(short)); + y->coe[j]->sign = words; + just(y->coe[j]); + } +} + +void +stuff(poly x, giant g, int words) { + int deg = x->deg, j, coedigs; + + g->sign = words*(1 + deg); + for(j=0; j <= deg; j++) { + coedigs = (x->coe[j])->sign; + bcopy(x->coe[j]->n, (g->n) + j*words, coedigs*sizeof(short)); + bzero((g->n) + (j*words+coedigs), + sizeof(short)*(words-coedigs)); + } + just(g); +} + +int maxwords = 0; +void + +binarysegmul(poly x, poly y) { + int bits = bitlen(p), xwords, ywords, words; + + xwords = (2*bits + log_2(x->deg+1) + 32 + 15)/16; + ywords = (2*bits + log_2(y->deg+1) + 32 + 15)/16; + if(xwords > ywords) words = xwords; else words = ywords; +if(words > maxwords) { + maxwords = words; +// printf("m: %d\n", words); + fflush(stdout); +} + stuff(x, globx, words); + stuff(y, globy, words); + mulg(globx, globy); + gtog(y->coe[y->deg], globx); /* Save high coeff. */ + y->deg += x->deg; + gtog(globx, y->coe[y->deg]); /* Move high coeff. */ + unstuff_partial(globy, y, words); + mulg(x->coe[x->deg], y->coe[y->deg]); /* resolve high coeff. */ + justifyp(y); +} + +binarysegsquare(poly y) { + int bits = bitlen(p), words; + words = (2*bits + log_2(y->deg+1) + 32 + 15)/16; + stuff(y, globy, words); + squareg(globy); + gtog(y->coe[y->deg], globx); /* Save high coeff. */ + y->deg += y->deg; + gtog(globx, y->coe[y->deg]); /* Move high coeff. */ + unstuff_partial(globy, y, words); + mulg(y->coe[y->deg], y->coe[y->deg]); /* resolve high coeff. */ + justifyp(y); +} + + +void +assess(poly x, poly y){ + int max = 0, j; + for(j=0; j <= x->deg; j++) { + if(bitlen(x->coe[j]) > max) max = bitlen(x->coe[j]); + } +// printf("max: %d ", max); + max = 0; + for(j=0; j <= y->deg; j++) { + if(bitlen(y->coe[j]) > max) max = bitlen(y->coe[j]); + } +// printf("%d\n", max); + + +} + +int +pcompp(poly x, poly y) { + int j; + if(x->deg != y->deg) return 1; + for(j=0; j <= x->deg; j++) { + if(gcompg(x->coe[j], y->coe[j])) return 1; + } + return 0; +} + +int maxdeg = 0; + +void +mulp(poly x, poly y) +/* y *= x. */ +{ + int n, degx = x->deg, degy = y->deg; + +/* +if(degx > max_deg) { + max_deg = degx; printf("xdeg: %d\n", degx); +} + +if(degy > max_deg) { + max_deg = degy; printf("ydeg: %d\n", degy); +} +*/ + if((degx < P_BREAK) || (degy < P_BREAK)) { + grammarmulp(x,y); + justifyp(y); + return; + } + if(x==y) binarysegsquare(y); + else binarysegmul(x, y); +} + +void +revp(poly x) +/* Reverse the coefficients of x. */ +{ int j, deg = x->deg; + + for(j=0; j <= deg/2; j++) { + gtog(x->coe[deg-j], tmp); + gtog(x->coe[j], x->coe[deg-j]); + gtog(tmp, x->coe[j]); + } + justifyp(x); +} + +void +recipp(poly f, int deg) +/* f := 1/f, via newton method. */ +{ + int lim = deg + 1, prec = 1; + + sscratch->deg = 0; itog(1, sscratch->coe[0]); + itog(1, aux); + while(prec < lim) { + prec <<= 1; + if(prec > lim) prec = lim; + f->deg = prec-1; + ptop(sscratch, tscratch); + mulp(f, tscratch); + tscratch->deg = prec-1; + polyrem(tscratch); + subg(aux, tscratch->coe[0]); + quickmodg(p, tscratch->coe[0]); + mulp(sscratch, tscratch); + tscratch->deg = prec-1; + polyrem(tscratch); + subp(tscratch, sscratch); + sscratch->deg = prec-1; + polyrem(sscratch); + } + justifyp(sscratch); + ptop(sscratch, f); +} + +int +left_justifyp(poly x, int start) +/* Left-justify the polynomial, checking from position "start." */ +{ + int j, shift = 0; + + for(j = start; j <= x->deg; j++) { + if(!is0(x->coe[j])) { + shift = start; + break; + } + } + x->deg -= shift; + for(j=0; j<= x->deg; j++) { + gtog(x->coe[j+shift], x->coe[j]); + } + return(shift); +} + +void +remp(poly x, poly y, int mode) +/* y := x (mod y). + mode = 0 is normal operation, + = 1 jams a fixed reciprocal, + = 2 uses the fixed reciprocal. + */ +{ + int degx = x->deg, degy = y->deg, d, shift; + + if(degy == 0) { + y->deg = 0; + itog(0, y->coe[0]); + return; + } + d = degx - degy; + if(d < 0) { + ptop(x, y); + return; + } + revp(x); revp(y); + ptop(y, rscratch); + switch(mode) { + case 0: recipp(rscratch, d); + break; + case 1: recipp(rscratch, degy); /* degy -1. */ + ptop(rscratch, precip); + rscratch->deg = d; justifyp(rscratch); + break; + case 2: ptop(precip, rscratch); + rscratch->deg = d; justifyp(rscratch); + break; + } +/* Next, a limited-precision multiply. */ + if(d < degx) { x->deg = d; justifyp(x);} + mulp(x, rscratch); + rscratch->deg = d; + polyrem(rscratch); + justifyp(rscratch); + x->deg = degx; justifyp(x); + mulp(rscratch, y); + subp(x, y); + negp(y); polyrem(y); + shift = left_justifyp(y, d+1); + for(d = y->deg+1; d <= degx-shift; d++) itog(0, y->coe[d]); + y->deg = degx - shift; + revp(y); + revp(x); +} + +fullmod(poly x) { + polyrem(x); + ptop(smonic, s[0]); + remp(x, s[0], 2); + ptop(s[0], x); + polyrem(x); +} + +scalarmul(giant s, poly x) { + int j; + for(j=0; j <= x->deg; j++) { + mulg(s, x->coe[j]); + modg(p, x->coe[j]); + } +} + + +schain(int el) { + int j; + + s[0]->deg = 0; + itog(0, s[0]->coe[0]); + + s[1]->deg = 0; + itog(1, s[1]->coe[0]); + s[2]->deg = 0; + itog(2, s[2]->coe[0]); + + s[3]->deg = 4; + gtog(a, aux); mulg(a, aux); negg(aux); + gtog(aux, s[3]->coe[0]); + gtog(b, aux); smulg(12, aux); + gtog(aux, s[3]->coe[1]); + gtog(a, aux); smulg(6, aux); + gtog(aux, s[3]->coe[2]); + itog(0, s[3]->coe[3]); + itog(3, s[3]->coe[4]); + + s[4]->deg = 6; + gtog(a, aux); mulg(a, aux); mulg(a, aux); + gtog(b, tmp); mulg(b, tmp); smulg(8, tmp); addg(tmp, aux); + negg(aux); + gtog(aux, s[4]->coe[0]); + gtog(b, aux); mulg(a, aux); smulg(4, aux); negg(aux); + gtog(aux, s[4]->coe[1]); + gtog(a, aux); mulg(a, aux); smulg(5, aux); negg(aux); + gtog(aux, s[4]->coe[2]); + gtog(b, aux); smulg(20, aux); + gtog(aux, s[4]->coe[3]); + gtog(a, aux); smulg(5, aux); + gtog(aux, s[4]->coe[4]); + itog(0, s[4]->coe[5]); + itog(1, s[4]->coe[6]); + itog(4, aux); + scalarmul(aux, s[4]); + cubic->deg = 3; + itog(1, cubic->coe[3]); + itog(0, cubic->coe[2]); + gtog(a, cubic->coe[1]); + gtog(b, cubic->coe[0]); + for(j=5; j <= el; j++) { + if(j % 2 == 0) { + ptop(s[j/2 + 2], s[j]); mulp(s[j/2-1], s[j]); + polyrem(s[j]); mulp(s[j/2-1], s[j]); polyrem(s[j]); + ptop(s[j/2-2], s[0]); mulp(s[j/2+1], s[0]); polyrem(s[0]); + mulp(s[j/2+1], s[0]); polyrem(s[0]); + subp(s[0], s[j]); mulp(s[j/2], s[j]); polyrem(s[j]); + gtog(p, aux); iaddg(1, aux); gshiftright(1, aux); + scalarmul(aux, s[j]); + } else { + ptop(s[(j-1)/2+2], s[j]); + mulp(s[(j-1)/2], s[j]); polyrem(s[j]); + mulp(s[(j-1)/2], s[j]); polyrem(s[j]); + mulp(s[(j-1)/2], s[j]); polyrem(s[j]); + ptop(s[(j-1)/2-1], s[0]); + mulp(s[(j-1)/2 + 1], s[0]); polyrem(s[0]); + mulp(s[(j-1)/2 + 1], s[0]); polyrem(s[0]); + mulp(s[(j-1)/2 + 1], s[0]); polyrem(s[0]); + if(((j-1)/2) % 2 == 1) { + mulp(cubic, s[0]); polyrem(s[0]); + mulp(cubic, s[0]); polyrem(s[0]); + } else { + mulp(cubic, s[j]); polyrem(s[j]); + mulp(cubic, s[j]); polyrem(s[j]); + } +// polyout(s[1]); polyout(s[3]); polyout(s[0]); polyout(s[j]); + subp(s[0], s[j]); + polyrem(s[j]); + } + } +} + +init_recip(int el) { + int j; + ptop(s[el], smonic); + if(el == 2) { + mulp(cubic, smonic); polyrem(smonic); + } + gtog(smonic->coe[smonic->deg], aux); /* High coeff. */ + binvg(p, aux); + scalarmul(aux, smonic); /* s is now monic. */ + s[0]->deg = smonic->deg + 1; + for(j=0; j <= s[0]->deg; j++) itog(1, s[0]->coe[j]); + ptop(smonic, pbuff); + remp(s[0], pbuff, 1); /* Initialize reciprocal of s as precip. */ +} + +void powerpoly(poly x, giant n) +/* Base-4 window. */ +{ int pos, code; + ptop(x, pbuff); /* x. */ + ptop(pbuff, pbuff2); + mulmod(pbuff2, pbuff2); mulmod(pbuff, pbuff2); /* x^3. */ + pos = bitlen(n)-2; + while(pos >= 0) { + mulmod(x, x); + if(pos==0) { + if(bitval(n, pos) != 0) { + mulmod(pbuff, x); + } + break; + } + code = (bitval(n, pos) != 0) * 2 + (bitval(n, pos-1) != 0); + switch(code) { + case 0: mulmod(x,x); break; + case 1: mulmod(x,x); + mulmod(pbuff, x); + break; + case 2: mulmod(pbuff, x); + mulmod(x,x); break; + case 3: mulmod(x,x); mulmod(pbuff2, x); break; + } + pos -= 2; + } +} + +mulmod(poly x, poly y) { + mulp(x, y); fullmod(y); +} + +elldoublep(poly n1, poly d1, poly m1, poly c1, poly n0, poly d0, + poly m0, poly c0) { + + ptop(n1, mn); mulmod(n1, mn); + ptop(mn, pbuff); addp(mn, mn); addp(pbuff, mn); + fullmod(mn); + ptop(d1, pbuff); mulmod(d1, pbuff); + scalarmul(a, pbuff); addp(pbuff, mn); + fullmod(mn); + mulmod(c1, mn); + ptop(m1, md); addp(md, md); + mulmod(d1, md); mulmod(d1, md); mulmod(cubic, md); + + ptop(d1, n0); mulmod(mn, n0); mulmod(mn, n0); + mulmod(cubic, n0); + ptop(n1, pbuff); addp(pbuff, pbuff); fullmod(pbuff); + mulmod(md, pbuff); mulmod(md, pbuff); + subp(pbuff, n0); fullmod(n0); + ptop(md, d0); mulmod(md, d0); mulmod(d1, d0); + + ptop(mn, m0); mulmod(c1, m0); + ptop(d0, pbuff); mulmod(n1, pbuff); + ptop(n0, c0); mulmod(d1, c0); subp(c0, pbuff); + fullmod(pbuff); + mulmod(pbuff, m0); + ptop(m1, pbuff); mulmod(md, pbuff); + mulmod(d1, pbuff); mulmod(d0, pbuff); + subp(pbuff, m0); fullmod(m0); + + ptop(c1, c0); mulmod(md, c0); mulmod(d1, c0); mulmod(d0, c0); +} + +elladdp(poly n1, poly d1, poly m1, poly c1, poly n2, poly d2, poly m2, poly c2, poly n0, poly d0, poly m0, poly c0) { + ptop(m2, mn); mulmod(c1, mn); + ptop(m1, pbuff); mulmod(c2, pbuff); + subp(pbuff, mn); fullmod(mn); + mulmod(d1, mn); mulmod(d2, mn); + + ptop(n2, md); mulmod(d1, md); + ptop(n1, pbuff); mulmod(d2, pbuff); + subp(pbuff, md); fullmod(md); + mulmod(c1, md); mulmod(c2, md); + + ptop(cubic, n0); mulmod(mn, n0); mulmod(mn, n0); + mulmod(d1, n0); mulmod(d2, n0); + ptop(n1, pbuff); mulmod(d2, pbuff); + ptop(n2, d0); mulmod(d1, d0); + addp(d0, pbuff); mulmod(md, pbuff); mulmod(md, pbuff); + subp(pbuff, n0); fullmod(n0); + + ptop(md, d0); mulmod(md, d0); mulmod(d1, d0); mulmod(d2, d0); + + ptop(mn, m0); mulmod(c1, m0); + ptop(d0, pbuff); mulmod(n1, pbuff); + ptop(d1, c0); mulmod(n0, c0); + subp(c0, pbuff); fullmod(pbuff); + mulmod(pbuff, m0); + ptop(m1, pbuff); mulmod(md, pbuff); + mulmod(d0, pbuff); mulmod(d1, pbuff); + subp(pbuff, m0); fullmod(m0); + + ptop(md, c0); mulmod(c1, c0); mulmod(d0, c0); mulmod(d1, c0); + +} + +polyout(poly x) { + int j; + for(j=0; j <= x->deg; j++) {printf("%d: ",j); gout(x->coe[j]);} +} + +#define SIEVE_CUT 7 + +main(int argc, char **argv) { + int j, ct, el, xmatch, ymatch; + int k, k2, t, linit; + int T[L_MAX], P[L_MAX]; + giant ss[L_MAX]; + unsigned int ord, ordminus; + + printf("Initializing...\n"); fflush(stdout); + init_all(); + + for(j=0; j < L_MAX; j++) { /* Array to be used for CRT reconstruction. */ + ss[j] = NULL; + } + + printf("Give p, a, b on separate lines:\n"); fflush(stdout); + gin(p); /* Field prime. */ + if(bitlen(p) > Q) { + fprintf(stderr, "p too large, larger than %d bits.\n", Q); + exit(0); + } + + gin(a); gin(b); /* Curve parameters. */ + +newb: + printf("Checking discriminant for:\nb = "); + gout(b); + gtog(a, t1); squareg(t1); modg(p, t1); mulg(a, t1); modg(p, t1); + gshiftleft(2, t1); /* 4 a^3. */ + gtog(b, t2); squareg(t2); modg(p, t2); smulg(27, t2); + addg(t2, t1); modg(p, t1); + if(isZero(t1)) { + printf("Discriminant FAILED\n"); + iaddg(1, b); + goto newb; + } + printf("Discriminant PASSED\n"); + printf("Starting sieve process:\n"); + + + schain(SIEVE_CUT + 1); /* Do first piece of chain, for small-sieving. */ + linit = 0; + ct = 0; + itog(1, magcheck); +for(el = 2; el <= L_MAX; el += 1 + (el%2)) { + if(!primeq(el)) continue; + L = el; while(L*el <= 4) L *= el; +printf("Resolving Schoof L = %d...\n", L); + P[ct] = L; /* Stuff another prime power. */ + smulg(L, magcheck); + gtog(magcheck, tmp); squareg(tmp); gshiftright(2, tmp); + if(gcompg(tmp, p) > 0) break; /* Done...go to CRT phase. */ +if((L > SIEVE_CUT) && (linit == 0)) { + schain(L_MAX+1); + linit = 1; + } + init_recip(L); +// printf("s: "); polyout(s[L]); + gtog(p, aux2); + k = idivg(L, aux2); /* p (mod L). */ + gtog(p, aux2); + k2 = idivg(el, aux2); +// printf("power...\n"); + txd->deg = 0; itog(1, txd->coe[0]); + tyd->deg = 0; itog(1, tyd->coe[0]); + txn->deg = 1; itog(0, txn->coe[0]); itog(1, txn->coe[1]); + ptop(txn, kxn); + + gtog(p, aux2); + powerpoly(txn, aux2); /* x^p. */ +// printf("x^p done...\n"); + ptop(txn, powx); + powerpoly(powx, aux2); +// printf("x^p^2 done...\n"); + ptop(cubic, tyn); + gtog(p, aux2); itog(1, aux); subg(aux, aux2); + gshiftright(1, aux2); /* aux2 := (p-1)/2. */ + powerpoly(tyn, aux2); /* y^p. */ +// printf("y^p done...\n"); + ptop(tyn, powy); mulp(tyn, powy); fullmod(powy); + mulp(cubic, powy); fullmod(powy); + powerpoly(powy, aux2); + mulp(tyn, powy); fullmod(powy); +// printf("Powers done...\n"); + +// printf("pow" ); polyout(powx); polyout(powy); + ptop(txn, txn1); ptop(txd, txd1); /* Save t = 1 case. */ + ptop(tyn, tyn1); ptop(tyd, tyd1); +/* We now shall test + (powx, y powy) + k(kxn/kxd, y kyn/kyd) = t(txn/txd, y tyn/tyd) + */ + + if(k==1) { ptop(txd, kxd); ptop(txd, kyd); + ptop(txd, kyn); + } else { + ptop(s[k], kxd); mulp(s[k], kxd); fullmod(kxd); + if(k%2==0) { mulp(cubic, kxd); fullmod(kxd); } + mulp(kxd, kxn); fullmod(kxn); + ptop(s[k-1], pbuff); mulp(s[k+1], pbuff); fullmod(pbuff); + if(k%2==1) {mulp(cubic, pbuff); fullmod(pbuff); } + subp(pbuff, kxn); fullmod(kxn); + + ptop(s[k+2], kyn); mulp(s[k-1], kyn); fullmod(kyn); + mulp(s[k-1], kyn); fullmod(kyn); + if(k > 2) { + ptop(s[k-2], pbuff); mulp(s[k+1], pbuff); fullmod(pbuff); + mulp(s[k+1], pbuff); fullmod(pbuff); + subp(pbuff, kyn); fullmod(kyn); + } + ptop(s[k], kyd); mulp(s[k], kyd); fullmod(kyd); + mulp(s[k], kyd); fullmod(kyd); + if(k%2==0) { mulp(cubic, kyd); fullmod(kyd); + mulp(cubic, kyd); fullmod(kyd);} + itog(4, aux2); scalarmul(aux2, kyd); + } +//printf("kP: "); polyout(kxn); polyout(kxd); polyout(kyn); polyout(kyd); +/* Commence t = 0 check. */ +// printf("Checking t = %d ...\n", 0); +fflush(stdout); + + ptop(powx, pbuff); mulp(kxd, pbuff); + subp(kxn, pbuff); + fullmod(pbuff); + + xmatch = ymatch = 0; + if(iszerop(pbuff)) { + xmatch = 1; + /* Now check y coords. */ + if(L == 2) goto resolve; + ptop(powy, pbuff); mulp(kyd, pbuff); + addp(kyn, pbuff); + fullmod(pbuff); + if(iszerop(pbuff)) { + resolve: + printf("%d %d\n", L, 0); + T[ct++] = 0; + if((k2 + 1 - T[ct-1]) % el == 0) { + printf("TILT: %d\n", el); + el = 2; + iaddg(1, b); + goto newb; + } + continue; + } else ymatch = 1; + } +/* Combine pt1 and pt2. */ + if((xmatch == 1) && (ymatch == 1)) + elldoublep(powx, txd, powy, txd, nx, dx, ny, dy); + else + elladdp(powx, txd, powy, txd, kxn, kxd, kyn, kyd, nx, dx, ny, dy); + +/* Now {nx/dx, ny/dy} is (fixed) LHS. */ +// printf("add12: "); polyout(nx); polyout(dx); polyout(ny); polyout(dy); +/* Commence t > 0 check. */ + for(t=1; t <= L/2; t++) { +// printf("Checking t = %d ...\n", t); + if(t > 1) { /* Add (tx1, ty1) to (txn, tyn). */ + ptop(txn1, pbuff); mulmod(txd, pbuff); + ptop(txn, powx); mulmod(txd1, powx); + subp(powx, pbuff); fullmod(pbuff); + if(!iszerop(pbuff)) + elladdp(txn1, txd1, tyn1, tyd1, txn, txd, tyn, tyd, + tmp1, tmp2, tmp3, tmp4); + else elldoublep(txn, txd, tyn, tyd, + tmp1, tmp2, tmp3, tmp4); + ptop(tmp1, txn); ptop(tmp2, txd); + ptop(tmp3, tyn); ptop(tmp4, tyd); + } +// printf("tQ: "); polyout(txn); polyout(txd); polyout(tyn); polyout(tyd); + /* Next, check {nx/dx, ny/dy} =? {txn/txd, tyn/tyd}. */ + ptop(nx, pbuff); mulmod(txd, pbuff); + ptop(dx, powx); mulmod(txn, powx); + subp(powx, pbuff); fullmod(pbuff); + if(!iszerop(pbuff)) continue; + /* Next, check y. */ + // printf("y check!\n"); + ptop(ny, pbuff); mulmod(tyd, pbuff); + ptop(dy, powx); mulmod(tyn, powx); + subp(powx, pbuff); fullmod(pbuff); + if(iszerop(pbuff)) { + printf("%d %d\n", L, t); + T[ct++] = t; + } else { + printf("%d %d\n", L, L-t); + T[ct++] = L-t; + } + if((k2 + 1 - T[ct-1]) % el == 0) { + printf("TILT: %d\n", el); + el = 2; + iaddg(1, b); + goto newb; + } + + fflush(stdout); + break; + } +} + +/* Now, prime powers P[] and CRT residues T[] are intact. */ + printf("Prime powers L:\n"); + printf("{"); + for(j=0; j < ct-1; j++) { + printf("%d, ", P[j]); + } + printf("%d }\n", P[ct-1]); + + printf("Residues t (mod L):\n"); + printf("{"); + for(j=0; j < ct-1; j++) { + printf("%d, ", T[j]); + } + printf("%d }\n", T[ct-1]); + +/* Mathematica algorithm for order: +plis = {2^5, 3^3, 5^2, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47}; +tlis = {1, 26, 4, 2, 4, 11, 6, 5, 19, 22, 10, 16, 7, 22, 11}; +prod = Apply[Times, plis]; +prlis = prod/plis; +invlis = Table[PowerMod[prlis[[q]], -1, plis[[q]]],{q,1,Length[plis]}]; +p = 2^127 - 1; +t = Mod[tlis . (prlis * invlis), prod]; +ord = p + 1 - If[t^2 > 4p, t - prod, t] +*/ + + itog(1, t1); + for(j=0; j < ct; j++) { + smulg(P[j], t1); + } + + for(j=0; j < 2*ct; j++) { + if(!ss[j]) ss[j] = newgiant(MAX_DIGS); + } + + for(j=0; j < ct; j++) { + gtog(t1, ss[j]); + itog(P[j], t2); + divg(t2, ss[j]); + } + + for(j=0; j < ct; j++) { + gtog(ss[j], ss[j+ct]); + itog(P[j], t2); + invg(t2, ss[j+ct]); + } + + itog(0, t4); + for(j=0; j < ct; j++) { + itog(T[j], t5); + mulg(ss[j], t5); + mulg(ss[j+ct], t5); + addg(t5, t4); + } + modg(t1, t4); + gtog(p, t5); + iaddg(1, t5); + gtog(t4, t2); + squareg(t4); + gtog(p, t3); gshiftleft(2, t3); + if(gcompg(t4, t3) > 0) subg(t1, t2); + subg(t2, t5); + printf("Parameters:\n"); + printf("p = "); gout(p); + printf("a = "); gout(a); + printf("b = "); gout(b); + printf("Curve order:\n"); + printf("o = "); gout(t5); + printf("pprob: %d\n", prime_probable(t5)); + printf("Twist order:\n"); + printf("o' = "); + addg(t2, t5); + addg(t2, t5); + gout(t5); + printf("pprob: %d\n", prime_probable(t5)); + + iaddg(1,b); + goto newb; +} diff --git a/libsecurity_cryptkit/lib/CurveParamDocs/tools.c b/libsecurity_cryptkit/lib/CurveParamDocs/tools.c new file mode 100644 index 00000000..9586537b --- /dev/null +++ b/libsecurity_cryptkit/lib/CurveParamDocs/tools.c @@ -0,0 +1,445 @@ +/************************************************************** + * + * tools.c + * + * Number-theoretical algorithm implementations + * + * Updates: + * 30 Apr 99 REC Modified init_tools type to void. + * 3 Apr 98 REC Creation + * + * + * c. 1998 Perfectly Scientific, Inc. + * All Rights Reserved. + * + * + *************************************************************/ + +/* include files */ + +#include +#include +#include +#include +#ifdef _WIN32 + +#include + +#endif + +#include +#include "giants.h" +#include "tools.h" + +/* definitions */ + +#define STACK_COUNT 20 + +/* global variables */ + +int pr[NUM_PRIMES]; /* External use allowed. */ +static giant tmp[STACK_COUNT]; +static int stack = 0; +static giant popg(); +static void pushg(); + +/************************************************************** + * + * Maintenance functions + * + **************************************************************/ + + +void +init_tools(int shorts) +{ + int j; + + for(j = 0; j < STACK_COUNT; j++) { + tmp[j] = newgiant(shorts); + } + make_primes(); /* Create table of all primes < 2^16, + to be used by other programs as array + pr[0..NUM_PRIMES]. */ +} + +static giant +popg() { + return(tmp[stack++]); +} + +static void +pushg(int n) { + stack -= n; +} + +/************************************************************** + * + * Number-theoretical functions + * + **************************************************************/ + +int +prime_literal( + unsigned int p +) +/* Primality test via small, literal sieve. + After init, one should use primeq() instead. + */ +{ + unsigned int j=3; + + if ((p & 1)==0) + return ((p == 2)?1:0); + if (j >= p) + return (1); + while ((p%j)!=0) + { + j += 2; + if (j*j > p) + return(1); + } + return(0); +} + +int +primeq( + unsigned int odd +) +/* Faster primality test, using preset array pr[] of primes. + This test is valid for all unsigned, 32-bit integers odd. + */ +{ + unsigned int p; + unsigned int j; + + if(odd < 2) return (0); + if ((odd & 1)==0) + return ((odd == 2)?1:0); + for (j=1; ;j++) + { + p = pr[j]; + if (p*p > odd) + return(1); + if (odd % p == 0) + return(0); + } +} + +void +make_primes() +{ int k, npr; + pr[0] = 2; + for (k=0, npr=1;; k++) + { + if (prime_literal(3+2*k)) + { + pr[npr++] = 3+2*k; + if (npr >= NUM_PRIMES) + break; + } + } +} + +int +prime_probable(giant p) +/* Invoke Miller-Rabin test of given security depth. + For MILLER_RABIN_DEPTH == 8, this is an ironclad primality + test for suspected primes p < 3.4 x 10^{14}. +*/ +{ + giant t1 = popg(), t2 = popg(), t3 = popg(); + int j, ct, s; + + if((p->n[0] & 1) == 0) { /* Evenness test. */ + pushg(3); return(0); + } + if(bitlen(p) < 32) { /* Single-word case. */ + pushg(3); + return(primeq((unsigned int)gtoi(p))); + } + itog(-1, t1); + addg(p, t1); /* t1 := p-1. */ + gtog(t1, t2); + s = 1; + gshiftright(1, t2); + while(t2->n[0] & 1 == 0) { + gshiftright(1, t2); + ++s; + } + /* Now, p-1 = 2^s * t2. */ + for(j = 0; j < MILLER_RABIN_DEPTH; j++) { + itog(pr[j+1], t3); + powermodg(t3, t2, p); + ct = 1; + if(isone(t3)) continue; + if(gcompg(t3, t1) == 0) continue; + while((ct < s) && (gcompg(t1, t3) != 0)) { + squareg(t3); modg(p, t3); + if(isone(t3)) { + goto composite; + } + ++ct; + } + if(gcompg(t1, t3) != 0) goto composite; + } + goto prime; + +composite: + pushg(3); return(0); +prime: pushg(3); return(1); +} + +int +jacobi_symbol(giant a, giant n) +/* Standard Jacobi symbol (a/n). Parameter n must be odd, positive. */ +{ int t = 1, u; + giant t5 = popg(), t6 = popg(), t7 = popg(); + + gtog(a, t5); modg(n, t5); + gtog(n, t6); + while(!isZero(t5)) { + u = (t6->n[0]) & 7; + while((t5->n[0] & 1) == 0) { + gshiftright(1, t5); + if((u==3) || (u==5)) t = -t; + } + gtog(t5, t7); gtog(t6, t5); gtog(t7, t6); + u = (t6->n[0]) & 3; + if(((t5->n[0] & 3) == 3) && ((u & 3) == 3)) t = -t; + modg(t6, t5); + } + if(isone(t6)) { + pushg(3); + return(t); + } + pushg(3); + return(0); +} + +int +pseudoq(giant a, giant p) +/* Query whether a^(p-1) = 1 (mod p). */ +{ + int x; + giant t1 = popg(), t2 = popg(); + + gtog(p, t1); itog(1, t2); subg(t2, t1); + gtog(a, t2); + powermodg(t2, t1, p); + x = isone(t2); + pushg(2); + return(x); +} + +int +pseudointq(int a, giant p) +/* Query whether a^(p-1) = 1 (mod p). */ +{ + int x; + giant t4 = popg(); + + itog(a, t4); + x = pseudoq(t4, p); + pushg(1); + return(x); +} + + +void +powFp2(giant a, giant b, giant w2, giant n, giant p) +/* Perform powering in the field F_p^2: + a + b w := (a + b w)^n (mod p), where parameter w2 is a quadratic + nonresidue (formally equal to w^2). + */ +{ int j; + giant t6 = popg(), t7 = popg(), t8 = popg(), t9 = popg(); + + if(isZero(n)) { + itog(1,a); + itog(0,b); + pushg(4); + return; + } + gtog(a, t8); gtog(b, t9); + for(j = bitlen(n)-2; j >= 0; j--) { + gtog(b, t6); + mulg(a, b); addg(b,b); modg(p, b); /* b := 2 a b. */ + squareg(t6); modg(p, t6); + mulg(w2, t6); modg(p, t6); + squareg(a); addg(t6, a); modg(p, a); /* a := a^2 + b^2 w2. */ + if(bitval(n, j)) { + gtog(b, t6); mulg(t8, b); modg(p, b); + gtog(a, t7); mulg(t9, a); addg(a, b); modg(p, b); + mulg(t9, t6); modg(p, t6); mulg(w2, t6); modg(p, t6); + mulg(t8, a); addg(t6, a); modg(p, a); + } + } + pushg(4); + return; +} + +int +sqrtmod(giant p, giant x) +/* If Sqrt[x] (mod p) exists, function returns 1, else 0. + In either case x is modified, but if 1 is returned, + x:= Sqrt[x] (mod p). + */ +{ giant t0 = popg(), t1 = popg(), t2 = popg(), t3 = popg(), + t4 = popg(); + + modg(p, x); /* Justify the argument. */ + gtog(x, t0); /* Store x for eventual validity check on square root. */ + if((p->n[0] & 3) == 3) { /* The case p = 3 (mod 4). */ + gtog(p, t1); + iaddg(1, t1); gshiftright(2, t1); + powermodg(x, t1, p); + goto resolve; + } +/* Next, handle case p = 5 (mod 8). */ + if((p->n[0] & 7) == 5) { + gtog(p, t1); itog(1, t2); + subg(t2, t1); gshiftright(2, t1); + gtog(x, t2); + powermodg(t2, t1, p); /* t2 := x^((p-1)/4) % p. */ + iaddg(1, t1); + gshiftright(1, t1); /* t1 := (p+3)/8. */ + if(isone(t2)) { + powermodg(x, t1, p); /* x^((p+3)/8) is root. */ + goto resolve; + } else { + itog(1, t2); subg(t2, t1); /* t1 := (p-5)/8. */ + gshiftleft(2,x); + powermodg(x, t1, p); + mulg(t0, x); addg(x, x); modg(p, x); /* 2x (4x)^((p-5)/8. */ + goto resolve; + } + } + +/* Next, handle tougher case: p = 1 (mod 8). */ + itog(2, t1); + while(1) { /* Find appropriate nonresidue. */ + gtog(t1, t2); + squareg(t2); subg(x, t2); modg(p, t2); + if(jacobi_symbol(t2, p) == -1) break; + iaddg(1, t1); + } /* t2 is now w^2 in F_p^2. */ + itog(1, t3); + gtog(p, t4); iaddg(1, t4); gshiftright(1, t4); + powFp2(t1, t3, t2, t4, p); + gtog(t1, x); + +resolve: + gtog(x,t1); squareg(t1); modg(p, t1); + if(gcompg(t0, t1) == 0) { + pushg(5); + return(1); /* Success. */ + } + pushg(5); + return(0); /* No square root. */ +} + +void +sqrtg(giant n) +/* n:= Floor[Sqrt[n]]. */ +{ giant t5 = popg(), t6 = popg(); + + itog(1, t5); gshiftleft(1 + bitlen(n)/2, t5); + while(1) { + gtog(n, t6); + divg(t5, t6); + addg(t5, t6); gshiftright(1, t6); + if(gcompg(t6, t5) >= 0) break; + gtog(t6, t5); + } + gtog(t5, n); + pushg(2); +} + +int +cornacchia4(giant n, int d, giant u, giant v) +/* Seek representation 4n = u^2 + |d| v^2, + for (negative) discriminant d and n > |D|/4. + Parameter u := 0 and 0 is returned, if no representation is found; + else 1 is returned and u, v properly set. + */ +{ int r = n->n[0] & 7, sym; + giant t1 = popg(), t2 = popg(), t3 = popg(), t4 = popg(); + + itog(d, t1); + if((n->n[0]) & 7 == 1) { /* n = 1 (mod 8). */ + sym = jacobi_symbol(t1,n); + if(sym != 1) { + itog(0,u); + pushg(4); + return(0); + } + gtog(t1, t2); + sqrtmod(n, t2); /* t2 := Sqrt[d] (mod n). */ + } else { /* Avoid separate Jacobi/Legendre test. */ + gtog(t1, t2); + if(sqrtmod(n, t2) == 0) { + itog(0, u); + pushg(4); + return(0); + } + } +/* t2 is now a valid square root of d (mod n). */ + gtog(t2, t3); + subg(t1, t3); /* t3 := t2 - d. */ + if((t3->n[0] & 1) == 1) { + negg(t2); + addg(n, t2); + } + gtog(n, t3); addg(t3, t3); /* t3 := 2n. */ + gtog(n, t4); gshiftleft(2, t4); sqrtg(t4); /* t4 = [Sqrt[4 p]]. */ + while(gcompg(t2, t4) > 0) { + gtog(t3, t1); + gtog(t2, t3); + gtog(t1, t2); + modg(t3, t2); + } + gtog(n, t4); gshiftleft(2, t4); + gtog(t2, t3); squareg(t3); + subg(t3, t4); /* t4 := 4n - t2^2. */ + gtog(t4, t3); + itog(d, t1); absg(t1); + modg(t1, t3); + if(!isZero(t3)) { + itog(0,u); + pushg(4); + return(0); + } + divg(t1, t4); + gtog(t4, t1); + sqrtg(t4); /* t4 := [Sqrt[t4/Abs[d]]]. */ + gtog(t4, t3); + squareg(t3); + if(gcompg(t3, t1) != 0) { + itog(0, u); + pushg(4); + return(0); + } + gtog(t2, u); + gtog(t4, v); + pushg(4); + return(1); +} + +/* +rep[p_, d_] := Module[{t, x0, a, b, c}, + If[JacobiSymbol[d,p] != 1, Return[{0,0}]]; + x0 = sqrt[d, p]; + If[Mod[x0-d,2] == 1, x0 = p-x0]; + a = 2p; b = x0; c = sqrtint[4 p]; + While[b > c, {a,b} = {b, Mod[a,b]}]; + t = 4p - b^2; + If[Mod[t,Abs[d]] !=0, Return[{0,0}]]; + v = t/Abs[d]; + u = sqrtint[v]; + If[u^2 != v, Return[{0,0}]]; + Return[{b, u}] + ]; +*/ + + diff --git a/libsecurity_cryptkit/lib/CurveParamDocs/tools.h b/libsecurity_cryptkit/lib/CurveParamDocs/tools.h new file mode 100644 index 00000000..34981eee --- /dev/null +++ b/libsecurity_cryptkit/lib/CurveParamDocs/tools.h @@ -0,0 +1,65 @@ +/************************************************************** + * + * tools.h + * + * Header file for tools.c. + * + * Updates: + * 30 Apr 99 REC Modified init_tools type to void. + * 3 Apr 98 REC Creation + * + * + * c. 1998 Perfectly Scientific, Inc. + * All Rights Reserved. + * + * + *************************************************************/ + +#define NUM_PRIMES 6542 /* PrimePi[2^16]. */ +#define MILLER_RABIN_DEPTH (8) + +void +init_tools(int shorts); + +void +make_primes(); + +int +prime_literal( + unsigned int p +); + +int +primeq( + unsigned int odd +); + +void +make_primes(); + +int +prime_probable(giant p); + +int +jacobi_symbol(giant a, giant n); + +int +pseudoq(giant a, giant p); + +int +pseudointq(int a, giant p); + + +void +powFp2(giant a, giant b, giant w2, giant n, giant p); + +int +sqrtmod(giant p, giant x); + +void +sqrtg(giant n); + +int +cornacchia4(giant n, int d, giant u, giant v); + + diff --git a/libsecurity_cryptkit/lib/ECDSA_Profile.h b/libsecurity_cryptkit/lib/ECDSA_Profile.h new file mode 100644 index 00000000..d0be400c --- /dev/null +++ b/libsecurity_cryptkit/lib/ECDSA_Profile.h @@ -0,0 +1,91 @@ +/* + File: ECDSA_Profile.h + + Contains: ECDSA Profiling support. + + Written by: Doug Mitchell + + Copyright: Copyright 1998 by 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 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. + *************************************************************************** + */ + +#ifndef _CK_ECDSA_PROFILE_H_ +#define _CK_ECDSA_PROFILE_H_ + +#include "ckconfig.h" + +#if CRYPTKIT_ECDSA_ENABLE + +#include "feeDebug.h" + +#ifdef FEE_DEBUG +#define ECDSA_PROFILE 0 +#else /* FEE_DEBUG */ +#define ECDSA_PROFILE 0 /* always off */ +#endif /* FEE_DEBUG */ + +#if ECDSA_PROFILE + +#include + +/* + * Unlike the profiling macros in feeDebug.h, these are intended to + * be used for fragments of code, not entire functions. + */ +#define SIGPROF_START \ +{ \ + struct tsval _profStartTime; \ + struct tsval _profEndTime; \ + kern_timestamp(&_profStartTime); + +/* + * This one goes at the end of the routine, just before the (only) return. + * There must be a static accumulator (an unsigned int) on a per-routine basis. + */ +#define SIGPROF_END(accum) \ + kern_timestamp(&_profEndTime); \ + accum += (_profEndTime.low_val - _profStartTime.low_val); \ +} + + +/* + * Accumulators. + */ +extern unsigned signStep1; +extern unsigned signStep2; +extern unsigned signStep34; +extern unsigned signStep5; +extern unsigned signStep67; +extern unsigned signStep8; +extern unsigned vfyStep1; +extern unsigned vfyStep3; +extern unsigned vfyStep4; +extern unsigned vfyStep5; +extern unsigned vfyStep6; +extern unsigned vfyStep7; + +#else /* ECDSA_PROFILE */ + +#define SIGPROF_START +#define SIGPROF_END(accum) + +#endif /* ECDSA_PROFILE */ + +#endif /* CRYPTKIT_ECDSA_ENABLE */ +#endif /* _CK_ECDSA_PROFILE_H_ */ diff --git a/libsecurity_cryptkit/lib/ECDSA_Verify_Prefix.h b/libsecurity_cryptkit/lib/ECDSA_Verify_Prefix.h new file mode 100644 index 00000000..3c52bde5 --- /dev/null +++ b/libsecurity_cryptkit/lib/ECDSA_Verify_Prefix.h @@ -0,0 +1,6 @@ +/* + * Prefix file for ECDSA Verify build. + * + * This symbol disables features not needed for ECDSA verify. + */ +#define ECDSA_VERIFY_ONLY 1 diff --git a/libsecurity_cryptkit/lib/HmacSha1Legacy.c b/libsecurity_cryptkit/lib/HmacSha1Legacy.c new file mode 100644 index 00000000..c3b286da --- /dev/null +++ b/libsecurity_cryptkit/lib/HmacSha1Legacy.c @@ -0,0 +1,167 @@ +/* + * 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: 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 +*/ + +#include "ckconfig.h" + +#if CRYPTKIT_HMAC_LEGACY + +#include "HmacSha1Legacy.h" +#include "ckSHA1.h" +#include +#include +#include + +#define kHMACSHA1DigestSize 20 + +/* XXX These should really be in ckSHA1.h */ +#define kSHA1DigestSize 20 +#define kSHA1BlockSize 64 + +/* + * bug-for-bug compatible with BSAFE 4.0. See + * BSafe/bsource/algs/ahchhmac.c. + * + * This implementation, and the BSAFE implementation it emulates, work fine + * when calculating a MAC in a single update (init, update, final). They + * generate nonconforming MACs when performing multiple updates because + * the entire algorithm - both inner and outer digests - are performed + * in the update() step. As a result, if one e.g. calculates a MAC of + * a block of text with one update, and then calculates the MAC over the + * same block of text via two updates, different results will obtain.ÊThe + * incorrect result from the multiple-update scenario is repeatable if and + * only if the same boundaries (same update sizes) are observed on each operation. + * + * Because all of the data to be MAC'd is in fact protected by both levels of + * SHA1, and all of the key bits are used, this nonconforming implementation is + * believed to be as strong, cryptographically, as a conforming SHA1HMAC + * implementation. + */ +struct hmacLegacyContext { + sha1Obj sha1Context; + UInt8 k_ipad[kSHA1BlockSize]; + UInt8 k_opad[kSHA1BlockSize]; +}; + +hmacLegacyContextRef hmacLegacyAlloc() +{ + hmacLegacyContextRef hmac = + (hmacLegacyContextRef)malloc(sizeof(struct hmacLegacyContext)); + memset(hmac, 0, sizeof(struct hmacLegacyContext)); + return hmac; +} + +void hmacLegacyFree( + hmacLegacyContextRef hmac) +{ + if(hmac != NULL) { + if(hmac->sha1Context != NULL) { + sha1Free (hmac->sha1Context); + } + memset(hmac, 0, sizeof(struct hmacLegacyContext)); + free(hmac); + } +} + +/* reusable init */ +OSStatus hmacLegacyInit( + hmacLegacyContextRef hmac, + const void *keyPtr, + UInt32 keyLen) +{ + UInt8 *key; + UInt32 byte; + + if(hmac->sha1Context == NULL) { + hmac->sha1Context = sha1Alloc(); + if(hmac->sha1Context == NULL) { + return memFullErr; + } + } + else { + sha1Reinit(hmac->sha1Context); + } + /* this implementation requires a 20-byte key */ + if (keyLen != kSHA1DigestSize) { + /* FIXME */ + return paramErr; + } + key = (UInt8*)keyPtr; + + /* The HMAC_SHA_1 transform looks like: + SHA1 (K XOR opad || SHA1 (K XOR ipad || text)) + Where K is a n byte key + ipad is the byte 0x36 repeated 64 times. + opad is the byte 0x5c repeated 64 times. + text is the data being protected. + */ + /* Copy the key into k_ipad and k_opad while doing the XOR. */ + for (byte = 0; byte < keyLen; byte++) + { + hmac->k_ipad[byte] = key[byte] ^ 0x36; + hmac->k_opad[byte] = key[byte] ^ 0x5c; + } + + /* Fill the remainder of k_ipad and k_opad with 0 XORed with + * appropriate value. */ + memset (hmac->k_ipad + keyLen, 0x36, kSHA1BlockSize - keyLen); + memset (hmac->k_opad + keyLen, 0x5c, kSHA1BlockSize - keyLen); + + /* remainder happens in update */ + return noErr; +} + +OSStatus hmacLegacyUpdate( + hmacLegacyContextRef hmac, + const void *textPtr, + UInt32 textLen) +{ + UInt8 innerDigest[kSHA1DigestSize]; + + /* compute SHA1(k_ipad || data) ==> innerDigest */ + sha1AddData (hmac->sha1Context, hmac->k_ipad, kSHA1BlockSize); + sha1AddData (hmac->sha1Context, (UInt8*)textPtr, textLen); + memcpy (innerDigest, sha1Digest(hmac->sha1Context), kSHA1DigestSize); + + /* reset context (BSAFE does this implicitly in a final() call) */ + sha1Reinit(hmac->sha1Context); + + /* compute SHA1(k_opad || innerDigest) */ + sha1AddData (hmac->sha1Context, hmac->k_opad, kSHA1BlockSize); + sha1AddData (hmac->sha1Context, innerDigest, kSHA1DigestSize); + + /* if there is another update coming, it gets added in to existing + * context; if the next step is a final, the current digest state is used. */ + return noErr; +} + +OSStatus hmacLegacyFinal( + hmacLegacyContextRef hmac, + void *resultPtr) // caller mallocs, must be HMACSHA1_OUT_SIZE bytes +{ + memcpy (resultPtr, sha1Digest (hmac->sha1Context), kSHA1DigestSize); + return noErr; +} + +#endif /* CRYPTKIT_HMAC_LEGACY */ diff --git a/libsecurity_cryptkit/lib/HmacSha1Legacy.h b/libsecurity_cryptkit/lib/HmacSha1Legacy.h new file mode 100644 index 00000000..d611263e --- /dev/null +++ b/libsecurity_cryptkit/lib/HmacSha1Legacy.h @@ -0,0 +1,70 @@ +/* + * 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: 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 +*/ +#ifndef __HMAC_SHA1_LEGACY__ +#define __HMAC_SHA1_LEGACY__ + +#if !defined(__MACH__) +#include +#else +#include +#endif + +#if CRYPTKIT_HMAC_LEGACY + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * This version is bug-for-bug compatible with the HMACSHA1 implementation in + * an old crypto library. + */ +struct hmacLegacyContext; +typedef struct hmacLegacyContext *hmacLegacyContextRef; + +hmacLegacyContextRef hmacLegacyAlloc(); +void hmacLegacyFree( + hmacLegacyContextRef hmac); +OSStatus hmacLegacyInit( + hmacLegacyContextRef hmac, + const void *keyPtr, + UInt32 keyLen); +OSStatus hmacLegacyUpdate( + hmacLegacyContextRef hmac, + const void *textPtr, + UInt32 textLen); +OSStatus hmacLegacyFinal( + hmacLegacyContextRef hmac, + void *resultPtr); // caller mallocs, must be kSHA1DigestSize bytes + +#ifdef __cplusplus +} +#endif + +#endif /* CRYPTKIT_HMAC_LEGACY */ + +#endif /* __HMAC_SHA1_LEGACY__ */ diff --git a/libsecurity_cryptkit/lib/Mathematica.FEE b/libsecurity_cryptkit/lib/Mathematica.FEE new file mode 100644 index 00000000..7f129d52 --- /dev/null +++ b/libsecurity_cryptkit/lib/Mathematica.FEE @@ -0,0 +1,57 @@ +(* Elliptic algebra functions: FEE format. + + y^2 = x^3 + c x^2 + a x + b. + + Montgomery: b = 0, a = 1; + Weierstrass: c = 0; + Atkin3: c = a = 0; + Atkin4: c = b = 0; + + Parameters c, a, b, p must be global. + *) + +elleven[pt_] := Block[{x1 = pt[[1]], z1 = pt[[2]], e, f }, + e = Mod[(x1^2 - a z1^2)^2 - 4 b (2 x1 + c z1) z1^3, p]; + f = Mod[4 z1 (x1^3 + c x1^2 z1 + a x1 z1^2 + b z1^3), p]; + Return[{e,f}] +]; + +ellodd[pt_, pu_, pv_] := Block[ + {x1 = pt[[1]], z1 = pt[[2]], + x2 = pu[[1]], z2 = pu[[2]], + xx = pv[[1]], zz = pv[[2]], i, j}, + i = Mod[zz ((x1 x2 - a z1 z2)^2 - + 4 b(x1 z2 + x2 z1 + c z1 z2) z1 z2), p]; + j = Mod[xx (x1 z2 - x2 z1)^2, p]; + Return[{i,j}] +]; + +bitList[k_] := Block[{li = {}, j = k}, + While[j > 0, + li = Append[li, Mod[j,2]]; + j = Floor[j/2]; + ]; + Return[Reverse[li]]; + ]; + +elliptic[pt_, k_] := Block[{porg, ps, pp, q}, + + If[k ==1, Return[pt]]; + If[k ==2, Return[elleven[pt]]]; + porg = pt; + ps = elleven[pt]; + pp = pt; + bitlist = bitList[k]; + Do[ + If[bitlist[[q]] == 1, + pp = ellodd[ps, pp, porg]; + ps = elleven[ps], + ps = ellodd[pp, ps, porg]; + pp = elleven[pp] + ], + {q,2,Length[bitlist]} + ]; + Return[Mod[pp,p]] +]; +ellinv[n_] := PowerMod[n,-1,p]; +ex[pt_] := Mod[pt[[1]] * ellinv[pt[[2]]], p]; diff --git a/libsecurity_cryptkit/lib/NSCipherFile.h b/libsecurity_cryptkit/lib/NSCipherFile.h new file mode 100644 index 00000000..a1d21bc8 --- /dev/null +++ b/libsecurity_cryptkit/lib/NSCipherFile.h @@ -0,0 +1,111 @@ +/* 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. + *************************************************************************** + * + * NSCipherFile.h - ObjC wrapper for feeCipherFile + * + * Revision History + * ---------------- + * 28 Oct 96 Doug Mitchell at NeXT + * Created. + */ + +#import +#import + +@interface NSCipherFile : NSObject +{ + void *_priv; +} + +/* + * Alloc and return an autoreleased NSCipherFile object associated with + * the specified data. + */ ++ newFromCipherText : (NSData *)cipherText + encrType : (cipherFileEncrType)encrType + sendPubKeyData : (NSData *)sendPubKeyData + otherKeyData : (NSData *)otherKeyData + sigData : (NSData *)sigData // optional; nil means no signature + userData : (unsigned)userData; // for caller's convenience + +/* + * Obtain the contents of a feeCipherFile as NSData. + */ +- (NSData *)dataRepresentation; + +/* + * Alloc and return an autoreleased NSCipherFile object given a data + * representation. + */ ++ newFromDataRepresentation : (NSData *)dataRep; + +/* + * Given an NSCipherFile object, obtain its constituent parts. + */ +- (cipherFileEncrType)encryptionType; +- (NSData *)cipherText; +- (NSData *)sendPubKeyData; +- (NSData *)otherKeyData; +- (NSData *)sigData; +- (unsigned)userData; + +/* + * High-level cipherFile support. + */ + +/* + * Obtain the data representation of a NSCipherFile given the specified + * plainText and cipherFileEncrType. + * Receiver's public key is required for all encrTypes; sender's private + * key is required for signature generation and also for encrType + * CFE_PublicDES and CFE_FEED. + */ ++(feeReturn)createCipherFileForPrivKey : (NSFEEPublicKey *)sendPrivKey + recvPubKey : (NSFEEPublicKey *)recvPubKey + encrType : (cipherFileEncrType)encrType + plainText : (NSData *)plainText + genSig : (BOOL)genSig + doEnc64 : (BOOL)doEnc64 // YES ==> perform enc64 + userData : (unsigned)userData // for caller's convenience + cipherFileData : (NSData **)cipherFileData; // RETURNED + +/* + * Parse and decrypt a data representation of an NSCipherFile object. + * + * recvPrivKey is required in all cases. If sendPubKey is present, + * sendPubKey - rather than the embedded sender's public key - will be + * used for signature validation. + */ ++ (feeReturn)parseCipherFileData : (NSFEEPublicKey *)recvPrivKey + sendPubKey : (NSFEEPublicKey *)sendPubKey + cipherFileData : (NSData *)cipherFileData + doDec64 : (BOOL)doDec64 + encrType : (cipherFileEncrType *)encrType // RETURNED + plainText : (NSData **)plainText // RETURNED + sigStatus : (feeSigStatus *)sigStatus // RETURNED + sigSigner : (NSString **)sigSigner // RETURNED + userData : (unsigned *)userData; // RETURNED + +/* + * Parse and decrypt an NSCipherFile object obtained via + * +newFromDataRepresentation. + * + * recvPrivKey is required in all cases. If sendPubKey is present, + * sendPubKey - rather than the embedded sender's public key - will be + * used for signature validation. + */ +- (feeReturn)decryptCipherFileData : (NSFEEPublicKey *)recvPrivKey + sendPubKey : (NSFEEPublicKey *)sendPubKey + plainText : (NSData **)plainText // RETURNED + sigStatus : (feeSigStatus *)sigStatus // RETURNED + sigSigner : (NSString **)sigSigner; // RETURNED + + +@end diff --git a/libsecurity_cryptkit/lib/NSCipherFile.m b/libsecurity_cryptkit/lib/NSCipherFile.m new file mode 100644 index 00000000..000b00e3 --- /dev/null +++ b/libsecurity_cryptkit/lib/NSCipherFile.m @@ -0,0 +1,360 @@ +/* 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. + *************************************************************************** + * + * NSCipherFile.m - ObjC wrapper for feeCipherFile + * + * Revision History + * ---------------- + * 28 Oct 96 Doug Mitchell at NeXT + * Created. + */ + +#import "NSCipherFile.h" +#import "feeCipherFile.h" +#import "falloc.h" +#import "NSFEEPublicKeyPrivate.h" /* for -feePubKey */ + +/* + * Private instance data. + */ +typedef struct { + feeCipherFile cfile; +} _cfPriv; + +@implementation NSCipherFile + +- (void)dealloc +{ + if(_priv) { + _cfPriv *cfPriv = _priv; + if(cfPriv->cfile) { + feeCFileFree(cfPriv->cfile); + } + } + [super dealloc]; +} + +/* + * Alloc and return an autoreleased NSCipherFile object associated with + * the specified data. + */ ++ newFromCipherText : (NSData *)cipherText + encrType : (cipherFileEncrType)encrType + sendPubKeyData : (NSData *)sendPubKeyData + otherKeyData : (NSData *)otherKeyData + sigData : (NSData *)sigData // optional; nil means no signature + userData : (unsigned)userData // for caller's convenience +{ + NSCipherFile *result; + _cfPriv *cfPriv; + + result = [[self alloc] autorelease]; + result->_priv = cfPriv = fmalloc(sizeof(_cfPriv)); + cfPriv->cfile = feeCFileNewFromCipherText(encrType, + [cipherText bytes], + [cipherText length], + [sendPubKeyData bytes], + [sendPubKeyData length], + [otherKeyData bytes], + [otherKeyData length], + [sigData bytes], + [sigData length], + userData); + if(cfPriv->cfile) { + return result; + } + else { + return nil; + } +} + +/* + * Obtain the contents of a feeCipherFile as NSData. + */ +- (NSData *)dataRepresentation +{ + _cfPriv *cfPriv = _priv; + NSData *result; + const unsigned char *rep; + unsigned repLen; + feeReturn frtn; + + if(cfPriv == NULL) { + return nil; + } + frtn = feeCFileDataRepresentation(cfPriv->cfile, + &rep, + &repLen); + if(frtn) { + return nil; + } + result = [NSData dataWithBytesNoCopy:(unsigned char *)rep + length:repLen]; + return result; +} + +/* + * Alloc and return an autoreleased NSCipherFile object given a data + * representation. + */ ++ newFromDataRepresentation : (NSData *)dataRep +{ + NSCipherFile *result; + _cfPriv *cfPriv; + feeReturn frtn; + + result = [[self alloc] autorelease]; + result->_priv = cfPriv = fmalloc(sizeof(_cfPriv)); + frtn = feeCFileNewFromDataRep([dataRep bytes], + [dataRep length], + &cfPriv->cfile); + if(frtn) { + return nil; + } + else { + return result; + } +} + +/* + * Given an NSCipherFile object, obtain its constituent parts. + */ +- (cipherFileEncrType)encryptionType +{ + _cfPriv *cfPriv = _priv; + + if(cfPriv == NULL) { + return CFE_Other; + } + return feeCFileEncrType(cfPriv->cfile); +} + +- (NSData *)cipherText +{ + _cfPriv *cfPriv = _priv; + const unsigned char *ctext; + unsigned ctextLen; + + if(cfPriv == NULL) { + return nil; + } + ctext = feeCFileCipherText(cfPriv->cfile, &ctextLen); + return [NSData dataWithBytesNoCopy:(unsigned char *)ctext + length:ctextLen]; +} + +- (NSData *)sendPubKeyData +{ + _cfPriv *cfPriv = _priv; + const unsigned char *key; + unsigned keyLen; + + if(cfPriv == NULL) { + return nil; + } + key = feeCFileSendPubKeyData(cfPriv->cfile, &keyLen); + if(key) { + return [NSData dataWithBytesNoCopy:(unsigned char *)key + length:keyLen]; + } + else { + return nil; + } +} + +- (NSData *)otherKeyData +{ + _cfPriv *cfPriv = _priv; + const unsigned char *key; + unsigned keyLen; + + if(cfPriv == NULL) { + return nil; + } + key = feeCFileOtherKeyData(cfPriv->cfile, &keyLen); + if(key) { + return [NSData dataWithBytesNoCopy:(unsigned char *)key + length:keyLen]; + } + else { + return nil; + } +} + +- (NSData *)sigData +{ + _cfPriv *cfPriv = _priv; + const unsigned char *sig; + unsigned sigLen; + + if(cfPriv == NULL) { + return nil; + } + sig = feeCFileSigData(cfPriv->cfile, &sigLen); + if(sig) { + return [NSData dataWithBytesNoCopy:(unsigned char *)sig + length:sigLen]; + } + else { + return nil; + } +} + +- (unsigned)userData +{ + _cfPriv *cfPriv = _priv; + + if(cfPriv == NULL) { + return 0; + } + return feeCFileUserData(cfPriv->cfile); +} + +/* + * High-level cipherFile support. + */ + +/* + * Create a cipherfile of specified cipherFileEncrType for given plaintext. + */ ++(feeReturn)createCipherFileForPrivKey : (NSFEEPublicKey *)sendPrivKey + recvPubKey : (NSFEEPublicKey *)recvPubKey + encrType : (cipherFileEncrType)encrType + plainText : (NSData *)plainText + genSig : (BOOL)genSig + doEnc64 : (BOOL)doEnc64 // YES ==> perform enc64 + userData : (unsigned)userData // for caller's convenience + cipherFileData : (NSData **)cipherFileData // RETURNED +{ + feeReturn frtn; + unsigned char *cfileData; + unsigned cfileDataLen; + feePubKey privKey = NULL; + + if(sendPrivKey) { + privKey = [sendPrivKey feePubKey]; + } + frtn = createCipherFile(privKey, + [recvPubKey feePubKey], + encrType, + [plainText bytes], + [plainText length], + genSig, + doEnc64, + userData, + &cfileData, + &cfileDataLen); + if(frtn) { + return frtn; + } + *cipherFileData = + [NSData dataWithBytesNoCopy:(unsigned char *)cfileData + length:cfileDataLen]; + return frtn; +} + +/* + * Parse and decrypt a data representation of an NSCipherFile object. + */ ++ (feeReturn)parseCipherFileData : (NSFEEPublicKey *)recvPrivKey + sendPubKey : (NSFEEPublicKey *)sendPubKey + cipherFileData : (NSData *)cipherFileData + doDec64 : (BOOL)doDec64 + encrType : (cipherFileEncrType *)encrType // RETURNED + plainText : (NSData **)plainText // RETURNED + sigStatus : (feeSigStatus *)sigStatus // RETURNED + sigSigner : (NSString **)sigSigner // RETURNED + userData : (unsigned *)userData // RETURNED +{ + feeReturn frtn; + unsigned char *ptext; + unsigned ptextLen; + feeUnichar *signer; + unsigned signerLen; + feePubKey _pubKey = NULL; + + if(recvPrivKey == nil) { + return FR_IllegalArg; // always required + } + if(sendPubKey) { + _pubKey = [sendPubKey feePubKey]; + } + + frtn = parseCipherFile([recvPrivKey feePubKey], + _pubKey, + [cipherFileData bytes], + [cipherFileData length], + doDec64, + encrType, + &ptext, + &ptextLen, + sigStatus, + &signer, + &signerLen, + userData); + if(frtn) { + return frtn; + } + *plainText = [NSData dataWithBytesNoCopy:ptext length:ptextLen]; + *sigSigner = [NSString stringWithCharacters:signer length:signerLen]; + ffree(signer); + return frtn; +} + +/* + * Parse and decrypt an NSCipherFile object obtained via + * +newFromDataRepresentation. + * + * recvPrivKey is required in all cases. If sendPubKey is present, + * sendPubKey - rather than the embedded sender's public key - will be + * used for signature validation. + */ +- (feeReturn)decryptCipherFileData : (NSFEEPublicKey *)recvPrivKey + sendPubKey : (NSFEEPublicKey *)sendPubKey + plainText : (NSData **)plainText // RETURNED + sigStatus : (feeSigStatus *)sigStatus // RETURNED + sigSigner : (NSString **)sigSigner // RETURNED +{ + _cfPriv *cfPriv = _priv; + feeReturn frtn; + unsigned char *ptext; + unsigned ptextLen; + feeUnichar *signer; + unsigned signerLen; + feePubKey _pubKey = NULL; + + if(cfPriv == NULL) { + return FR_IllegalArg; + } + if(recvPrivKey == nil) { + return FR_IllegalArg; // always required + } + if(sendPubKey) { + _pubKey = [sendPubKey feePubKey]; + } + + frtn = decryptCipherFile(cfPriv->cfile, + [recvPrivKey feePubKey], + _pubKey, + &ptext, + &ptextLen, + sigStatus, + &signer, + &signerLen); + if(frtn) { + return frtn; + } + *plainText = [NSData dataWithBytesNoCopy:ptext length:ptextLen]; + *sigSigner = [NSString stringWithCharacters:signer length:signerLen]; + ffree(signer); + return frtn; + +} +@end diff --git a/libsecurity_cryptkit/lib/NSCryptors.h b/libsecurity_cryptkit/lib/NSCryptors.h new file mode 100644 index 00000000..81b22862 --- /dev/null +++ b/libsecurity_cryptkit/lib/NSCryptors.h @@ -0,0 +1,83 @@ +/* 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. + *************************************************************************** + * + * NSCryptors.h - common cryptographic protocols + * + * Revision History + * ---------------- + * ??? 1994 Blaine Garst at NeXT + * Created. + */ + + +#import +#import +#import + + +/************ Utilities ******************************************/ + +#ifdef NeXT + +NSString *NSPromptForPassPhrase(NSString *prompt); + // useful for command line (/dev/tty) programs + +#endif NeXT + +/************ Data Hashing Protocol *****************/ + +@protocol NSDataDigester ++ digester; // provides a concrete digester + +// primitives +- (void)digestData:(NSData *)data; // use for multi-bite messages +- (NSData *)messageDigest; // provide digest; re-init + +// conveniences that only use the above primitives +// all in one gulp (eats salt first, if present) +- (NSData *)digestData:(NSData *)data withSalt:(NSData *)salt; + +@end + + +/****** Encryption/Decryption Protocol ***********/ + +@protocol NSCryptor +- (NSData *)encryptData:(NSData *)input; +- (NSData *)decryptData:(NSData *)input; +- (unsigned)keyBitsize; +@end + + +/*************** Public Key Services *************/ + +@protocol NSPublicKey +- (NSString *)publicKeyString; +- (NSString *)algorithmName; // "Diffie-Hellman" "FEE" ... +- (NSString *)usageName; // "Blaine Garst - home" +- (NSData *)padWithPublicKey:(id )otherKey; +- (unsigned)keyBitsize; +@end + +/********* Key Ring ************************/ + +@protocol NSKeyRing +- keyForUsageName:(NSString *)user; +@end + +/********** Digital Signatures **************/ + +// protocol adapted by various signature schemes (FEE, DSA, RSA...) +@protocol NSDigitalSignature +- (NSData *)digitalSignatureForData:(NSData *)message; + // generate a signature for the data + +- (BOOL)isValidDigitalSignature:(NSData *)sig forData:(NSData *)data; +@end diff --git a/libsecurity_cryptkit/lib/NSDESCryptor.h b/libsecurity_cryptkit/lib/NSDESCryptor.h new file mode 100644 index 00000000..0590ff27 --- /dev/null +++ b/libsecurity_cryptkit/lib/NSDESCryptor.h @@ -0,0 +1,39 @@ +/* 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. + *************************************************************************** + * + * NSDESCryptor.h created by blaine on Thu 22-Feb-1996 + */ + +#import "NSCryptors.h" + +/****** Digital Encryption Standard/Algorithm ********/ + +@interface NSDESCryptor : NSObject +{ + void *_priv; +} + ++ cryptorWithState:(NSData *)s; + +- initWithState:(NSData *)state; + // designated initializer + // 8 bytes with most sig bit ignored: 56 bits + +- (void)setCryptorState:(NSData *)state; // reset +- (void)setBlockMode:(BOOL)yorn; // default is chaining mode + +/* + * NSCryptor methods + */ +- (NSData *)encryptData:(NSData *)input; +- (NSData *)decryptData:(NSData *)input; +- (unsigned)keyBitsize; + +@end diff --git a/libsecurity_cryptkit/lib/NSDESCryptor.m b/libsecurity_cryptkit/lib/NSDESCryptor.m new file mode 100644 index 00000000..3e3d566f --- /dev/null +++ b/libsecurity_cryptkit/lib/NSDESCryptor.m @@ -0,0 +1,130 @@ +/* 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. + *************************************************************************** + * + * NSDESCryptor.m - DES encrypt/decrypt class + * + * Revision History + * ---------------- + * 28 Mar 97 Doug Mitchell at Apple + * Rewrote using feeDES module. + * 22 Feb 96 Blaine Garst at NeXT + * Created. + */ + +#import +#import "NSDESCryptor.h" +#import "feeDES.h" +#import "falloc.h" +#import "ckutilities.h" +#import "feeFunctions.h" + +/* + * Note: Our _priv ivar is actuall a feeDES pointer. + */ +@implementation NSDESCryptor + ++ cryptorWithState:(NSData *)s { + return [[[self alloc] initWithState:s] autorelease]; +} + +- (void)setCryptorState:(NSData *)state { + if(_priv == NULL) { + return; + } + feeDESSetState(_priv, [state bytes], [state length]); +} + +- initWithState:(NSData *)state { + feeReturn frtn; + + if(_priv == NULL) { + _priv = feeDESNewWithState([state bytes], [state length]); + } + else { + frtn = feeDESSetState(_priv, [state bytes], [state length]); + if(frtn) { + NSLog(@"NSDESCryptor: bad initial state\n"); + return nil; + } + } + return self; +} + +- (void)dealloc +{ + if(_priv) { + feeDESFree(_priv); + } + [super dealloc]; +} + +- (void)setBlockMode:(BOOL)yorn { + if(_priv == NULL) { + return; + } + if(yorn) { + feeDESSetBlockMode(_priv); + } + else { + feeDESSetChainMode(_priv); + } +} + +- (NSData *)encryptData:(NSData *)input { + NSData *result; + feeReturn frtn; + unsigned char *cipherText; + unsigned cipherTextLen; + + if(_priv == NULL) { + return nil; + } + frtn = feeDESEncrypt(_priv, + [input bytes], + [input length], + &cipherText, + &cipherTextLen); + if(frtn) { + NSLog(@"NSDESCryptor encrypt: %s", feeReturnString(frtn)); + return nil; + } + result = [NSData dataWithBytes:cipherText length:cipherTextLen]; + ffree(cipherText); + return result; +} + +- (NSData *)decryptData:(NSData *)input { + NSData *result; + feeReturn frtn; + unsigned char *plainText; + unsigned plainTextLen; + + if(_priv == NULL) { + return nil; + } + frtn = feeDESDecrypt(_priv, + [input bytes], + [input length], + &plainText, + &plainTextLen); + if(frtn) { + NSLog(@"NSDESCryptor decrypt: %s", feeReturnString(frtn)); + return nil; + } + result = [NSData dataWithBytes:plainText length:plainTextLen]; + ffree(plainText); + return result; +} + +- (unsigned)keyBitsize { + return feeDESKeySize(_priv); +} + +@end diff --git a/libsecurity_cryptkit/lib/NSFEEPublicKey.h b/libsecurity_cryptkit/lib/NSFEEPublicKey.h new file mode 100644 index 00000000..8cebd4d2 --- /dev/null +++ b/libsecurity_cryptkit/lib/NSFEEPublicKey.h @@ -0,0 +1,74 @@ +/* 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. + *************************************************************************** + * + * NSFEEPublicKey.h + * + * Revision History + * ---------------- + * 27 Feb 1997 Doug Mitchell at Apple + * Broke out from NSCryptors.h. + */ + +#import + +@interface NSFEEPublicKey : NSObject + { +@private + void *_pubKey; +} + ++ keyWithPrivateData:(NSData *)private + depth:(unsigned)depth // depth is in range 0-23 + usageName:(NSString *)uname; + // able to encrypt/decrypt data + // able to create/verify digital signatures + ++ keyWithPublicKeyString:(NSString *)hexstr; + // able to encrypt data + // able to verify digital signatures + +/* + * Create new key with curve parameters matching existing oldKey. + */ ++ keyWithPrivateData:(NSData *)passwd + andKey:(NSFEEPublicKey *)oldKey + usageName:(NSString *)uname; + +/* + * Convenience methods. The first three use the default depth + * (FEE_DEPTH_DEFAULT). + */ ++ keyWithPrivateData:(NSData *)passwd + usageName:(NSString *)uname; ++ keyWithPrivateString:(NSString *)private + usageName:(NSString *)uname; ++ keyWithPrivateString:(NSString *)private + andKey:(NSFEEPublicKey *)oldKey + usageName:(NSString *)uname; + ++ keyWithPrivateString:(NSString *)private + depth:(unsigned)depth + usageName:(NSString *)uname; + +/* + * NSCryptor protocol + */ +- (NSData *)encryptData:(NSData *)data; // done with public knowledge +- (NSData *)decryptData:(NSData *)data; // done with private knowledge + +/* + * NSDigitalSignature protocol + */ +- (NSData *)digitalSignatureForData:(NSData *)data; + // data is hashed with MD5 and then signed with private knowledge +- (BOOL)isValidDigitalSignature:(NSData *)sig forData:(NSData *)data; + // data is hashed with MD5 and then verified with public knowledge + +@end diff --git a/libsecurity_cryptkit/lib/NSFEEPublicKey.m b/libsecurity_cryptkit/lib/NSFEEPublicKey.m new file mode 100644 index 00000000..3e99d642 --- /dev/null +++ b/libsecurity_cryptkit/lib/NSFEEPublicKey.m @@ -0,0 +1,496 @@ +/* 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. + *************************************************************************** + * + * NSFEEPublicKey.m - NSFEEPublicKey class implementation + * + * Revision History + * ---------------- + * 17 Jul 97 Doug Mitchell at Apple + * Added ECDSA signature routines. + * 21 Aug 96 Doug Mitchell at NeXT + * Modified to use C-only FeePublicKey module. + * ???? 1994 Blaine Garst at NeXT + * Created. + */ + +#import +#import + +#import "NSCryptors.h" +#import "NSFEEPublicKeyPrivate.h" +#import "feePublicKey.h" +#import "feePublicKeyPrivate.h" +#import "ckutilities.h" +#import "mutils.h" +#import "feeTypes.h" +#import "curveParams.h" +#import "falloc.h" +#import "feeDigitalSignature.h" +#import "feeHash.h" +#import "feeFunctions.h" +#import "feeFEEDExp.h" + +/* + Elliptic curve algebra over finite fields F(p**k), where p = 2**q -1 is a + Mersenne prime. + q is bit-depth. + A private key (a) is a large integer that when multiplied by an initial + curve point P yields the public key aP. + Public keys can be used to generate one-time pads because multiplication + is commutative: + + a(bP) == b(aP) + */ + +@implementation NSFEEPublicKey + +/* + * Root method to create new public key from private "password" data. + */ ++ keyWithPrivateData:(NSData *)passwd + depth:(unsigned)depth + usageName:(NSString *)uname +{ + NSFEEPublicKey *result; + feeReturn frtn; + unichar *uc; + + result = [[self alloc] autorelease]; + result->_pubKey = feePubKeyAlloc(); + uc = fmalloc([uname length] * sizeof(unichar)); + [uname getCharacters:uc]; + frtn = feePubKeyInitFromPrivData(result->_pubKey, + [passwd bytes], [passwd length], + uc, [uname length], + depth); + ffree(uc); + if(frtn) { + NSLog(@"keyWithPrivateData: %s\n", feeReturnString(frtn)); + return nil; + } + return result; +} + +/* + * Create new key with curve parameters matching existing oldKey. + */ ++ keyWithPrivateData:(NSData *)passwd + andKey:(NSFEEPublicKey *)oldKey + usageName:(NSString *)uname +{ + NSFEEPublicKey *result; + feeReturn frtn; + unichar *uc; + + result = [[self alloc] autorelease]; + result->_pubKey = feePubKeyAlloc(); + uc = fmalloc([uname length] * sizeof(unichar)); + [uname getCharacters:uc]; + frtn = feePubKeyInitFromKey(result->_pubKey, + [passwd bytes], [passwd length], + uc, [uname length], + oldKey->_pubKey); + ffree(uc); + if(frtn) { + NSLog(@"keyWithPrivateData:andKey: %s\n", + feeReturnString(frtn)); + return nil; + } + return result; +} + ++ keyWithPrivateData:(NSData *)passwd + usageName:(NSString *)uname +{ + // 4 gives 127 bits of protection + // although the RSA challenge number of 127 bits has been + // broken, FEE is much stronger at the same length + return [self keyWithPrivateData:passwd + depth:FEE_DEPTH_DEFAULT + usageName:uname]; +} + +/* + * The standard way of creating a new key given a private "password" string. + */ ++ keyWithPrivateString:(NSString *)private + usageName:(NSString *)uname +{ + NSData *pdata; + id result; + + /* + * FIXME - handle other encodings? + */ + pdata = [private dataUsingEncoding:NSUTF8StringEncoding]; + result = [self keyWithPrivateData:pdata usageName:uname]; + return result; +} + ++ keyWithPrivateString:(NSString *)private + andKey:(NSFEEPublicKey *)oldKey + usageName:(NSString *)uname +{ + NSData *pdata; + id result; + + if (!uname) return nil; + + pdata = [private dataUsingEncoding:NSUTF8StringEncoding]; + result = [self keyWithPrivateData:pdata andKey:oldKey usageName:uname]; + return result; +} + ++ keyWithPrivateString:(NSString *)private + depth:(unsigned)depth + usageName:(NSString *)uname +{ + NSData *pdata; + id result; + + if (!uname) return nil; + + pdata = [private dataUsingEncoding:NSUTF8StringEncoding]; + result = [self keyWithPrivateData:pdata depth:depth usageName:uname]; + return result; +} + +/* + * The standard way of creating a new key given a public key string. + */ ++ keyWithPublicKeyString:(NSString *)hexstr +{ + NSFEEPublicKey *result; + feeReturn frtn; + NSStringEncoding defEndoding; + const char *s; + + /* + * Protect against gross errors in the key string formatting... + */ + defEndoding = [NSString defaultCStringEncoding]; + if([hexstr canBeConvertedToEncoding:defEndoding] == NO) { + NSLog(@"NSFEEPublicKey: Bad Public Key String Format (1)\n"); + return nil; + } + + /* + * FIXME - docs say this string is "autoreleased". How is a cString + * autoreleased? + */ + s = [hexstr cString]; + result = [[self alloc] autorelease]; + result->_pubKey = feePubKeyAlloc(); + + frtn = feePubKeyInitFromKeyString(result->_pubKey, + s, strlen(s)); + if(frtn) { + NSLog(@"keyWithPublicKeyString:andKey: %s\n", + feeReturnString(frtn)); + return nil; + } + return result; +} + +- (void)dealloc +{ + if(_pubKey) { + feePubKeyFree(_pubKey); + } + [super dealloc]; +} + +/* + * Create a public key in the form of a string. This string contains an + * encoded version of all of our ivars except for _private. + * + * See KeyStringFormat.doc for info on the format of the public key string; + * PLEASE UPDATE THIS DOCUMENT WHEN YOU MAKE CHANGES TO THE STRING FORMAT. + */ +- (NSString *)publicKeyString +{ + char *keyStr; + unsigned keyStrLen; + feeReturn frtn; + NSString *result; + + if(_pubKey == NULL) { + return nil; + } + frtn = feePubKeyCreateKeyString(_pubKey, &keyStr, &keyStrLen); + if(frtn) { + NSLog(@"publicKeyString: %s\n", + feeReturnString(frtn)); + return nil; + } + result = [NSString stringWithCString:keyStr]; + ffree((void *)keyStr); + return result; +} + +- (BOOL)isEqual:(NSFEEPublicKey *)other +{ + if((other == nil) || (other->_pubKey == NULL) || (_pubKey == NULL)) { + return NO; + } + if(feePubKeyIsEqual(_pubKey, other->_pubKey)) { + return YES; + } + else { + return NO; + } +} + +- (unsigned)keyBitsize +{ + if(_pubKey == NULL) { + return 0; + } + return feePubKeyBitsize(_pubKey); +} + +- (NSString *)algorithmName +{ + return [NSString stringWithCString:feePubKeyAlgorithmName()]; +} + +- (NSString *)usageName +{ + unsigned unameLen; + const feeUnichar *uname; + NSString *result; + + if(_pubKey == NULL) { + return nil; + } + uname = feePubKeyUsageName(_pubKey, &unameLen); + result = [NSString stringWithCharacters:uname length:unameLen]; + return result; +} + +- (NSString *)signer +{ + return [self usageName]; +} + +- (NSData *)padWithPublicKey:(id )otherKey +{ + NSFEEPublicKey *other; + NSMutableData *result; + feeReturn frtn; + unsigned char *padData; + unsigned padDataLen; + + if(_pubKey == NULL) { + return nil; + } + if (![otherKey isMemberOfClass:isa]) { + return nil; + } + other = otherKey; + if(other->_pubKey == NULL) { + return nil; + } + frtn = feePubKeyCreatePad(_pubKey, + other->_pubKey, + &padData, + &padDataLen); + if(frtn) { + NSLog(@"padWithPublicKey: %s\n", feeReturnString(frtn)); + return nil; + } + result = [NSData dataWithBytesNoCopy:padData length:padDataLen]; + return result; +} + +- (NSData *)encryptData:(NSData *)data +{ + feeFEEDExp feed; + NSData *result; + feeReturn frtn; + unsigned char *ctext; + unsigned ctextLen; + + if(_pubKey == NULL) { + return nil; + } + feed = feeFEEDExpNewWithPubKey(_pubKey); + frtn = feeFEEDExpEncrypt(feed, + [data bytes], + [data length], + &ctext, + &ctextLen); + if(frtn == FR_Success) { + result = [NSData dataWithBytesNoCopy:ctext length:ctextLen]; + } + else { + NSLog(@"feeFEEDEncrypt: %s\n", feeReturnString(frtn)); + result = nil; + } + feeFEEDExpFree(feed); + return result; +} + +- (NSData *)decryptData:(NSData *)data +{ + feeFEEDExp feed; + NSData *result; + feeReturn frtn; + unsigned char *ptext; + unsigned ptextLen; + + if(_pubKey == NULL) { + return nil; + } + feed = feeFEEDExpNewWithPubKey(_pubKey); + frtn = feeFEEDExpDecrypt(feed, + [data bytes], + [data length], + &ptext, + &ptextLen); + if(frtn == FR_Success) { + result = [NSData dataWithBytesNoCopy:ptext length:ptextLen]; + } + else { + NSLog(@"feeFEEDDecrypt: %s\n", feeReturnString(frtn)); + result = nil; + } + feeFEEDExpFree(feed); + return result; +} + +/* + * When 1, we use ECDSA unless we're using a depth which does not + * have curve orders. + * WARNING - enabling ECDSA by default breaks ICE and compatibility + * with Java signatures, at least until we have a Java ECDSA + * implementation. + */ +#define ECDSA_SIG_DEFAULT 0 + +- (NSData *)digitalSignatureForData:(NSData *)data +{ + NSData *result; + unsigned char *sig; + unsigned sigLen; + feeReturn frtn; + curveParams *cp; + + if(_pubKey == NULL) { + return nil; + } + cp = feePubKeyCurveParams(_pubKey); + if(!ECDSA_SIG_DEFAULT || isZero(cp->x1OrderPlus)) { + frtn = feePubKeyCreateSignature(_pubKey, + [data bytes], + [data length], + &sig, + &sigLen); + } + else { + frtn = feePubKeyCreateECDSASignature(_pubKey, + [data bytes], + [data length], + &sig, + &sigLen); + } + if(frtn) { + NSLog(@"digitalSignatureForData: %s\n", feeReturnString(frtn)); + return nil; + } + result = [NSData dataWithBytesNoCopy:sig length:sigLen]; + return result; +} + +- (BOOL)isValidDigitalSignature:(NSData *)signa + forData:(NSData *)data +{ + feeReturn frtn; + feeUnichar *sigSigner; + unsigned sigSignerLen; + curveParams *cp; + + if(_pubKey == NULL) { + return NO; + } + cp = feePubKeyCurveParams(_pubKey); + if(!ECDSA_SIG_DEFAULT || isZero(cp->x1OrderPlus)) { + frtn = feePubKeyVerifySignature(_pubKey, + [data bytes], + [data length], + [signa bytes], + [signa length], + &sigSigner, + &sigSignerLen); + } + else { + frtn = feePubKeyVerifyECDSASignature(_pubKey, + [data bytes], + [data length], + [signa bytes], + [signa length], + &sigSigner, + &sigSignerLen); + } + + /* + * FIXME - We just throw away the signer for now... + */ + if(sigSignerLen) { + ffree(sigSigner); + } + + switch(frtn) { + case FR_Success: + return YES; + case FR_InvalidSignature: + return NO; + default: + /* + * Something other than simple signature mismatch... + */ + NSLog(@"isValidDigitalSignature: %s\n", feeReturnString(frtn)); + return NO; + } +} + +@end + +@implementation NSFEEPublicKey(Private) + +- (key)minus +{ + if(_pubKey == NULL) { + return NULL; + } + return feePubKeyMinusCurve(_pubKey); +} + +- (key)plus +{ + if(_pubKey == NULL) { + return NULL; + } + return feePubKeyPlusCurve(_pubKey); +} + +- (feePubKey)feePubKey +{ + return _pubKey; +} + +#if FEE_DEBUG +- (void)dump +{ + printPubKey(_pubKey); +} +#endif FEE_DEBUG + +@end diff --git a/libsecurity_cryptkit/lib/NSFEEPublicKeyPrivate.h b/libsecurity_cryptkit/lib/NSFEEPublicKeyPrivate.h new file mode 100644 index 00000000..ed0bc6fd --- /dev/null +++ b/libsecurity_cryptkit/lib/NSFEEPublicKeyPrivate.h @@ -0,0 +1,36 @@ +/* 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/NSMD5Hash.h b/libsecurity_cryptkit/lib/NSMD5Hash.h new file mode 100644 index 00000000..468832c6 --- /dev/null +++ b/libsecurity_cryptkit/lib/NSMD5Hash.h @@ -0,0 +1,34 @@ +/* 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. + *************************************************************************** + * + * NSMD5Hash.h + * + * Revision History + * ---------------- + * 28 Mar 97 Doug Mitchell at Apple + * Created. + */ + +#import +#import + +@interface NSMD5Hash : NSObject + +{ + void *_priv; +} + ++ digester; // provides a concrete digester +- init; // reusable +- (void)digestData:(NSData *)data; +- (NSData *)messageDigest; // provide digest; re-init +- (NSData *)digestData:(NSData *)data withSalt:(NSData *)salt; + +@end diff --git a/libsecurity_cryptkit/lib/NSMD5Hash.m b/libsecurity_cryptkit/lib/NSMD5Hash.m new file mode 100644 index 00000000..30eed334 --- /dev/null +++ b/libsecurity_cryptkit/lib/NSMD5Hash.m @@ -0,0 +1,79 @@ +/* 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. + *************************************************************************** + * + * NSMD5Hash.h + * + * Revision History + * ---------------- + * 28 Mar 97 Doug Mitchell at Apple + * Created. + */ + +/* + * Note: our _priv ivar is actually a feeHash pointer. + */ +#import "NSCryptors.h" +#import "NSMD5Hash.h" +#import "feeHash.h" +#import "falloc.h" + +@implementation NSMD5Hash + ++ digester +{ + return [[self alloc] init]; +} + +- init +{ + if(_priv == NULL) { + _priv = feeHashAlloc(); + } + else { + feeHashReinit(_priv); + } + return self; +} + +- (void)digestData:(NSData *)data +{ + if(_priv == NULL) { + return; + } + feeHashAddData(_priv, [data bytes], [data length]); +} + +- (NSData *)messageDigest +{ + unsigned char *cp; + NSData *md; + + if(_priv == NULL) { + return nil; + } + cp = feeHashDigest(_priv); + md = [NSData dataWithBytes:cp length:feeHashDigestLen()]; + feeHashReinit(_priv); + return md; +} + +- (NSData *)digestData:(NSData *)data withSalt:(NSData *)salt +{ + if(_priv == NULL) { + return nil; + } + if(salt != nil) { + [self digestData:salt]; + } + [self digestData:data]; + return [self messageDigest]; +} + +@end diff --git a/libsecurity_cryptkit/lib/NSRandomNumberGenerator.h b/libsecurity_cryptkit/lib/NSRandomNumberGenerator.h new file mode 100644 index 00000000..bb76867e --- /dev/null +++ b/libsecurity_cryptkit/lib/NSRandomNumberGenerator.h @@ -0,0 +1,36 @@ +/* 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. + *************************************************************************** + * + * NSRandomNumberGenerator.h + * + * Revision History + * ---------------- + * 28 Mar 97 Doug Mitchell at Apple + * Simplified. + * ?? 96 Blaine Garst at NeXT + * Created. + */ + +#import + +@interface NSRandomNumberGenerator : NSObject +{ + void *_priv; +} + +- initWithSeed:(unsigned)seed; // designated initializer +- init; // we'll come up with the best seed + // we can + +- (unsigned)nextNumber; +- (unsigned)nextNumberInRange:(NSRange)range; +- (NSData *)randomDataWithLength:(unsigned)l; + +@end diff --git a/libsecurity_cryptkit/lib/NSRandomNumberGenerator.m b/libsecurity_cryptkit/lib/NSRandomNumberGenerator.m new file mode 100644 index 00000000..6a969bda --- /dev/null +++ b/libsecurity_cryptkit/lib/NSRandomNumberGenerator.m @@ -0,0 +1,83 @@ +/* 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. + *************************************************************************** + * + * NSRandomNumberGenerator.m + * + * Revision History + * ---------------- + * 28 Mar 97 Doug Mitchell at Apple + * Rewrote using feeRandom module. + * ?? 96 Blaine Garst at NeXT + * Created. + */ + +/* + * Note: out _priv ivar is actually a feeRand pointer. + */ + +#import +#import "NSRandomNumberGenerator.h" +#import "feeRandom.h" +#import "falloc.h" + +@implementation NSRandomNumberGenerator + +- init +{ + if(_priv == NULL) { + _priv = feeRandAlloc(); + } + /* + * else no need to re-init + */ + return self; +} + +- initWithSeed:(unsigned)seed +{ + if(_priv != NULL) { + /* + * Free & re-init to use new seed + */ + feeRandFree(_priv); + } + _priv = feeRandAllocWithSeed(seed); + return self; +} + +- (unsigned)nextNumber +{ + if(_priv == NULL) { + return 0; + } + return feeRandNextNum(_priv); +} + +- (unsigned)nextNumberInRange:(NSRange)range +{ + if(_priv == NULL) { + return 0; + } + return range.location + ([self nextNumber] % range.length); +} + +- (NSData *)randomDataWithLength:(unsigned)l +{ + unsigned char *cp; + + if(_priv == NULL) { + return nil; + } + cp = fmalloc(l); + feeRandBytes(_priv, cp, l); + return [NSData dataWithBytesNoCopy:cp length:l]; +} + +@end diff --git a/libsecurity_cryptkit/lib/README b/libsecurity_cryptkit/lib/README new file mode 100644 index 00000000..f0e6c555 --- /dev/null +++ b/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 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/lib/TOP_README b/libsecurity_cryptkit/lib/TOP_README new file mode 100644 index 00000000..cf6207e4 --- /dev/null +++ b/libsecurity_cryptkit/lib/TOP_README @@ -0,0 +1,30 @@ + Apple FEE Library Source, v. 1.0 + Last Update: 28 Jan 1998 + + + 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 two subdirecories. One, CryptKit, contains the +source code for the Apple Fast Elliptic Encryption (FEE) library. The +other directory, Examples, contains a number of programs which illustrate +the use of the FEE library. All code is written in ANSI C; UNIX Makefiles +are provided for each directory. See the README files in the respective +directories for information on the contents of specific files, porting +issues, and so forth. + +Note that all source files in these directories 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. + + + 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/lib/buildSrcTree b/libsecurity_cryptkit/lib/buildSrcTree new file mode 100644 index 00000000..b4a1c999 --- /dev/null +++ b/libsecurity_cryptkit/lib/buildSrcTree @@ -0,0 +1,34 @@ +#! /bin/csh -f +# +# Build "outside release" version of CryptKit source tree. Places +# source in $argv[1]/CryptKit. +# +if ( $#argv < 1 ) then + echo Usage: buildSrcTree target_dir + exit(1) +endif +# +set TARGDIR=CryptKit +# +set CFILES="CipherFileDES.c CipherFileFEED.c ckDES.c ckMD5.c elliptic.c giantIntegers.c ckSHA1.c ckSHA1_priv.c byteRep.c curveParams.c enc64.c falloc.c feeCipherFile.c feeCipherFileAtom.c feeDES.c feeDigitalSignature.c feeECDSA.c feeFEED.c feeFEEDExp.c feeHash.c feePublicKey.c feeRandom.c platform.c ckutilities.c giantPort_PPC.c ellipticProj.c" +# +set HFILES="CipherFileDES.h CipherFileFEED.h CipherFileTypes.h Crypt.h ckDES.h ECDSA_Profile.h ckMD5.h elliptic.h giantIntegers.h ckSHA1.h ckSHA1_priv.h byteRep.h ckconfig.h curveParams.h curveParamData.h ellipticMeasure.h enc64.h falloc.h feeCipherFile.h feeDES.h feeDebug.h feeDigitalSignature.h feeECDSA.h feeFEED.h feeFEEDExp.h feeFunctions.h feeHash.h feePublicKey.h feePublicKeyPrivate.h feeRandom.h feeTypes.h platform.h ckutilities.h giantPortCommon.h giantPort_Generic.h giantPort_PPC_Gnu.h giantPort_PPC.h giantPort_i486.h ellipticProj.h" +# +set SFILES="giantPort_i486.s giantPort_PPC_Gnu.s" +set OTHERFILES="README" +# +set MAKEFILE_SRC=unixMakefile +set MAKEFILE_DEST=Makefile +set TOP_README_SRC=TOP_README +set TOP_README_DST=README +# +set DSTROOT=$argv[1] +set DSTDIR=${DSTROOT}/${TARGDIR} +mkdir -p ${DSTDIR} || exit(1) +# +cp -p ${CFILES} ${HFILES} ${SFILES} ${OTHERFILES} ${DSTDIR} || exit(1) +# +# These files get renamed... +# +cp -p ${MAKEFILE_SRC} ${DSTDIR}/${MAKEFILE_DEST} || exit(1) +cp -p ${TOP_README_SRC} ${DSTROOT}/${TOP_README_DST} diff --git a/libsecurity_cryptkit/lib/byteRep.c b/libsecurity_cryptkit/lib/byteRep.c new file mode 100644 index 00000000..a6f07c2f --- /dev/null +++ b/libsecurity_cryptkit/lib/byteRep.c @@ -0,0 +1,476 @@ +/* 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. + *************************************************************************** + * + * byteRep.c - FEE portable byte representation support + * + * Revision History + * ---------------- + * 10/06/98 ap + * Changed to compile with C++. + * 18 Apr 98 Doug Mitchell at Apple + * Mods for variable size giantDigit. + * 20 Jan 98 Doug Mitchell at Apple + * Added curve param fields for CURVE_PARAM_VERSION 2. + * 17 Jul 97 Doug Mitchell at Apple + * Added signature routines. + * 9 Jan 97 Doug Mitchell at NeXT + * Split off from utilities.c + */ + +#include "byteRep.h" +#include "feeTypes.h" +#include "curveParams.h" +#include "giantIntegers.h" +#include "elliptic.h" +#include "falloc.h" +#include "ckutilities.h" +#include "feeDebug.h" +#include + +#ifndef NULL +#define NULL ((void *)0) +#endif /* NULL */ + +/* + * Support for portable bytestream representation of keys and signatures. + * Platform and endianness independent; format shared with JavaFEE + * implementation. + */ + +/* + * Some handy macros. + */ +#define ENC_BYTE(n, b, bytes) \ + *b++ = n; \ + bytes++; + +#define ENC_INT(n, b, bytes, i) \ + i = intToByteRep(n, b); \ + bytes += i; \ + b += i; + +#define ENC_GIANT(g, b, bytes, i) \ + i = giantToByteRep(g, b); \ + bytes += i; \ + b += i; + +#define DEC_BYTE(n, b, blen, bytes) \ + n = *b++; \ + bytes++; \ + blen--; + +#define DEC_INT(n, b, blen, bytes) \ + n = byteRepToInt(b); \ + b += sizeof(int); \ + bytes += sizeof(int); \ + blen -= gLen; + +#define DEC_GIANT(g, b, blen, glen, bytes, out) \ + g = byteRepToGiant(b, blen, &glen); \ + if(g == NULL) { \ + goto out; \ + } \ + b += glen; \ + bytes += glen; \ + blen -= gLen; + + + + +/* + * The routines which convert various types to byte reps return the number + * of bytes written to the output stream. + */ +int 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); + return 4; +} + +int shortToByteRep(short s, unsigned char *buf) +{ + *buf++ = (unsigned char)((s >> 8) & 0xff); + *buf = (unsigned char)(s & 0xff); + return 2; +} + +/* + * 7 Apr 1998 : leading int is now the number of bytes in the giant's + * giantDigits array. This value is signed. + */ +int giantToByteRep(giant g, unsigned char *buf) +{ + int numBytes = g->sign * GIANT_BYTES_PER_DIGIT; + unsigned aNumBytes = abs(numBytes); + + CKASSERT(g != NULL); + intToByteRep(numBytes, buf); + buf += sizeof(int); + serializeGiant(g, buf, aNumBytes); + return (sizeof(int) + aNumBytes); +} + +int keyToByteRep(key k, unsigned char *buf) +{ + int numBytes = 0; + int i; + + CKASSERT(k != NULL); + ENC_GIANT(k->x, buf, numBytes, i); + + /* only write y for plus curve */ + if(k->twist == CURVE_PLUS) { + CKASSERT(k->y != NULL); + ENC_GIANT(k->y, buf, numBytes, i); + } + return numBytes; +} + +#define CURVE_PARAM_VERSION 3 +#define CURVE_PARAM_VERSION_MIN 3 + +int curveParamsToByteRep(curveParams *cp, unsigned char *buf) +{ + int numBytes = 0; + int i; + + CKASSERT(cp != NULL); + ENC_INT(CURVE_PARAM_VERSION, buf, numBytes, i); + ENC_INT(CURVE_PARAM_VERSION_MIN, buf, numBytes, i); + ENC_BYTE(cp->primeType, buf, numBytes); + ENC_BYTE(cp->curveType, buf, numBytes); + ENC_INT(cp->q, buf, numBytes, i); + ENC_INT(cp->k, buf, numBytes, i); + ENC_INT(cp->m, buf, numBytes, i); + ENC_INT(0, buf, numBytes, i); // spare + + ENC_GIANT(cp->a, buf, numBytes, i); + ENC_GIANT(cp->b, buf, numBytes, i); + ENC_GIANT(cp->c, buf, numBytes, i); + ENC_GIANT(cp->x1Plus, buf, numBytes, i); + ENC_GIANT(cp->x1Minus, buf, numBytes, i); + ENC_GIANT(cp->cOrderPlus, buf, numBytes, i); + ENC_GIANT(cp->cOrderMinus, buf, numBytes, i); + ENC_GIANT(cp->x1OrderPlus, buf, numBytes, i); + ENC_GIANT(cp->x1OrderMinus, buf, numBytes, i); + if(cp->primeType == FPT_General) { + ENC_GIANT(cp->basePrime, buf, numBytes, i); + } + return numBytes; +} + +int sigToByteRep(int magic, + int version, + int minVersion, + giant g0, + giant g1, + unsigned char *buf) +{ + int numBytes = 0; + int i; + + ENC_INT(magic, buf, numBytes, i); + ENC_INT(version, buf, numBytes, i); + ENC_INT(minVersion, buf, numBytes, i); + ENC_INT(0, buf, numBytes, i); // spare + ENC_GIANT(g0, buf, numBytes, i); + ENC_GIANT(g1, buf, numBytes, i); + + return numBytes; +} + + +/* + * return the size of various data types' byte representations. + */ +int lengthOfByteRepGiant(giant g) +{ + CKASSERT(g != NULL); + return sizeof(int) + (GIANT_BYTES_PER_DIGIT * abs(g->sign)); +} + +int lengthOfByteRepKey(key k) +{ + int len = lengthOfByteRepGiant(k->x); + + CKASSERT(k != NULL); + if(k->twist == CURVE_PLUS) { + CKASSERT(k->y != NULL); + len += lengthOfByteRepGiant(k->y); + } + return len; +} + +int lengthOfByteRepCurveParams(curveParams *cp) +{ + int length; + + CKASSERT(cp != NULL); + length = (6 * sizeof(int)) + // ver, minVers, q, k, m, spare + 2 + // primeType + curveType + lengthOfByteRepGiant(cp->a) + + lengthOfByteRepGiant(cp->b) + + lengthOfByteRepGiant(cp->c) + + lengthOfByteRepGiant(cp->x1Plus) + + lengthOfByteRepGiant(cp->x1Minus) + + lengthOfByteRepGiant(cp->cOrderPlus) + + lengthOfByteRepGiant(cp->cOrderMinus) + + lengthOfByteRepGiant(cp->x1OrderPlus) + + lengthOfByteRepGiant(cp->x1OrderMinus); + if(cp->primeType == FPT_General) { + length += lengthOfByteRepGiant(cp->basePrime); + } + return length; +} + +int lengthOfByteRepSig(giant g0, + giant g1) +{ + int length = (4 * sizeof(int)) + // magic, version, minVersion, + // spare + lengthOfByteRepGiant(g0) + + lengthOfByteRepGiant(g1); + return length; +} + +/* + * Routine to cons up various types from a byte rep stream. + */ +int byteRepToInt(const unsigned char *buf) { + int result; + + result = (((int)buf[0] << 24) & 0xff000000) | + (((int)buf[1] << 16) & 0x00ff0000) | + (((int)buf[2] << 8) & 0xff00) | + (((int)buf[3]) & 0xff); + return result; +} + +unsigned short byteRepToShort(const unsigned char *buf) { + unsigned short result; + + result = (((unsigned short)buf[0] << 8) & 0xff00) | + (((unsigned short)buf[1]) & 0xff); + return result; +} + +/* + * Probably need byteRepToShortArray... + */ + +/* + * byte rep stream to giant. Returns NULL on error; returns number of bytes + * of *buf snarfed in *giantLen if successful. + * + * 7 Apr 1998 : leading int is now the number of bytes in the giant's + * giantDigits array. This value is signed. + */ +giant byteRepToGiant(const unsigned char *buf, + unsigned bufLen, + unsigned *giantLen) +{ + giant g; + int numDigits; + int numBytes; // signed! + unsigned aNumBytes; + + if(bufLen < sizeof(int)) { + return (giant)NULL; + } + numBytes = byteRepToInt(buf); + aNumBytes = abs(numBytes); + numDigits = BYTES_TO_GIANT_DIGITS(aNumBytes); + buf += sizeof(int); + bufLen -= sizeof(int); + if(numDigits > MAX_DIGITS) { + return (giant)NULL; + } + + if(bufLen < aNumBytes) { + return (giant)NULL; + } + + /* 9 Apr 1998 - sign = 0 means no following n[] bytes in the + * byteRep. We do need to alloc one digit, in this case, though... + * Note that the giantstruct has one implicit digit in n[]. + */ + if(aNumBytes == 0) { + g = (giant)fmalloc(sizeof(giantstruct)); + g->capacity = 1; + } + else { + g = (giant)fmalloc(sizeof(giantstruct) + + aNumBytes - GIANT_BYTES_PER_DIGIT); + g->capacity = numDigits; + } + deserializeGiant(buf, g, aNumBytes); + + /* deserializeGiant always cooks up positive giant; sign is + * properly trimmed to handle trailing (M.S.) zeroes. */ + if(numBytes < 0) { + g->sign = -g->sign; + } + *giantLen = sizeof(int) + aNumBytes; + return g; + +} + +/* + * Convert a byte stream (and some other parameters) into a + * keystruct. + * Returns NULL on error; returns number of bytes of *buf snarfed in + * *keyLen if successful. + */ +key byteRepToKey(const unsigned char *buf, + unsigned bufLen, + int twist, + curveParams *cp, + unsigned *keyLen) // returned +{ + key k; + giant x; + giant y; + unsigned gLen; + unsigned totalLen; + + x = byteRepToGiant(buf, bufLen, &gLen); + if(x == NULL) { + return NULL; + } + bufLen -= gLen; + buf += gLen; + totalLen = gLen; + if(twist == CURVE_PLUS) { + /* this also contains y */ + y = byteRepToGiant(buf, bufLen, &gLen); + if(y == NULL) { + freeGiant(x); + return NULL; + } + totalLen += gLen; + } + else { + /* minus curve, y is not used */ + y = newGiant(1); + int_to_giant(0, y); + } + k = (key)fmalloc(sizeof(keystruct)); + k->twist = twist; + k->cp = cp; + k->x = x; + k->y = y; + *keyLen = totalLen; + return k; +} + +curveParams *byteRepToCurveParams(const unsigned char *buf, + unsigned bufLen, + unsigned *cpLen) +{ + curveParams *cp; + unsigned gLen = 0; + int version; + int minVersion; + int spare; + int bytes = 0; + + if(bufLen < (5 * sizeof(int))) { // ver, minVers, q, k, spare + return NULL; + } + cp = newCurveParams(); + + DEC_INT(version, buf, bufLen, bytes); + DEC_INT(minVersion, buf, bufLen, bytes); + if(minVersion > CURVE_PARAM_VERSION) { + /* + * Can't parse this; things have changed too much between + * this version of the code and the time this curveParams + * was written. + */ + goto abort; + } + + DEC_BYTE(cp->primeType, buf, bufLen, bytes); + DEC_BYTE(cp->curveType, buf, bufLen, bytes); + DEC_INT(cp->q, buf, bufLen, bytes); + DEC_INT(cp->k, buf, bufLen, bytes); + DEC_INT(cp->m, buf, bufLen, bytes); + DEC_INT(spare, buf, bufLen, bytes); + + DEC_GIANT(cp->a, buf, bufLen, gLen, bytes, abort); + DEC_GIANT(cp->b, buf, bufLen, gLen, bytes, abort); + DEC_GIANT(cp->c, buf, bufLen, gLen, bytes, abort); + DEC_GIANT(cp->x1Plus, buf, bufLen, gLen, bytes, abort); + DEC_GIANT(cp->x1Minus, buf, bufLen, gLen, bytes, abort); + DEC_GIANT(cp->cOrderPlus, buf, bufLen, gLen, bytes, abort); + DEC_GIANT(cp->cOrderMinus, buf, bufLen, gLen, bytes, abort); + DEC_GIANT(cp->x1OrderPlus, buf, bufLen, gLen, bytes, abort); + DEC_GIANT(cp->x1OrderMinus, buf, bufLen, gLen, bytes, abort); + + /* + * basePrime only present in byte rep for PT_GENERAL + */ + if(cp->primeType == FPT_General) { + DEC_GIANT(cp->basePrime, buf, bufLen, gLen, bytes, abort); + } + + /* remaining fields inferred */ + curveParamsInferFields(cp); + allocRecipGiants(cp); + + *cpLen = bytes; + return cp; + +abort: + freeCurveParams(cp); + return NULL; +} + +/* + * Returns 0 if bad format, e.g., if minVersion of sig is > than codeVersion. + */ +int byteRepToSig(const unsigned char *buf, + unsigned bufLen, + int codeVersion, + int *sigMagic, // RETURNED + int *sigVersion, // RETURNED + int *sigMinVersion, // RETURNED + giant *g0, // alloc'd & RETURNED + giant *g1) // alloc'd & RETURNED +{ + unsigned gLen = 0; + int spare; + int bytes = 0; + + if(bufLen < (4 * sizeof(int))) { // magic, version, minVersion, + // spare + return 0; + } + DEC_INT(*sigMagic, buf, bufLen, bytes); + DEC_INT(*sigVersion, buf, bufLen, bytes); + DEC_INT(*sigMinVersion, buf, bufLen, bytes); + if(*sigMinVersion > codeVersion) { + return 0; + } + DEC_INT(spare, buf, bufLen, bytes); + // deleted 2/20/01 DEC_INT(*signerLen, buf, bufLen, bytes); + // deleted 2/20/01 *signer = byteRepToUnichars(buf, *signerLen); + // deleted 2/20/01 buf += (2 * *signerLen); + // deleted 2/20/01 bufLen -= (2 * *signerLen); + DEC_GIANT(*g0, buf, bufLen, gLen, bytes, abort); + DEC_GIANT(*g1, buf, bufLen, gLen, bytes, abort); + + return 1; +abort: + return 0; +} diff --git a/libsecurity_cryptkit/lib/byteRep.h b/libsecurity_cryptkit/lib/byteRep.h new file mode 100644 index 00000000..71bb45ae --- /dev/null +++ b/libsecurity_cryptkit/lib/byteRep.h @@ -0,0 +1,80 @@ +/* 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. + *************************************************************************** + * + * byteRep.h - FEE portable byte representation support + * + * Revision History + * ---------------- + * 17 Jul 97 Doug Mitchell at Apple + * Added signature routines. + * 9 Jan 97 Doug Mitchell at NeXT + * Split off from ckutilities.h + */ + +#ifndef _CK_BYTEREP_H_ +#define _CK_BYTEREP_H_ + +#include "feeTypes.h" +#include "giantIntegers.h" +#include "elliptic.h" +#include "curveParams.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Support for bytestream key and signature representation. + */ +int intToByteRep(int i, unsigned char *buf); +int shortToByteRep(short s, unsigned char *buf); +int giantToByteRep(giant g, unsigned char *buf); +int keyToByteRep(key k, unsigned char *buf); +int curveParamsToByteRep(curveParams *cp, unsigned char *buf); +int sigToByteRep(int magic, + int version, + int minVersion, + giant g0, + giant g1, + unsigned char *buf); + +int lengthOfByteRepGiant(giant g); +int lengthOfByteRepKey(key k); +int lengthOfByteRepCurveParams(curveParams *cp); +int lengthOfByteRepSig(giant g0, + giant g1); + +int byteRepToInt(const unsigned char *buf); +unsigned short byteRepToShort(const unsigned char *buf); +giant byteRepToGiant(const unsigned char *buf, + unsigned bufLen, + unsigned *giantLen); +key byteRepToKey(const unsigned char *buf, + unsigned bufLen, + int twist, + curveParams *cp, + unsigned *keyLen); // returned +curveParams *byteRepToCurveParams(const unsigned char *buf, + unsigned bufLen, + unsigned *cpLen); +int byteRepToSig(const unsigned char *buf, + unsigned bufLen, + int codeVersion, + int *sigMagic, // RETURNED + int *sigVersion, // RETURNED + int *sigMinVersion, // RETURNED + giant *g0, // alloc'd & RETURNED + giant *g1); // alloc'd & RETURNED + +#ifdef __cplusplus +} +#endif + +#endif /*_CK_BYTEREP_H_*/ diff --git a/libsecurity_cryptkit/lib/changes b/libsecurity_cryptkit/lib/changes new file mode 100644 index 00000000..6ca31b42 --- /dev/null +++ b/libsecurity_cryptkit/lib/changes @@ -0,0 +1,222 @@ + CryptKit change log + +CryptKit-8 + -- Added prototypes for NSFEEPublicKey convenience methods to NSCryptors.h + +CryptKit-9 + * Alpha version to dreece and crandall 13 Aug 1996 + * FEE_KEY_VERSION 3, FEE_KEYSTRING_VERSION 1 + +CryptKit-10 + -- Added KeyStringFormat.doc + -- Deleted -publicKeyData, keyWithPublicKeyData (public keys now always + represented as strings) + -- Beefed up range and validity checking in: + -- hexstr_to_giant() + -- new_hexstr_from_key() + -- +keyWithPublicKeyString + -- Added check for valid_hexstr() and NULL hexstr_to_key() in + +digitalSignatureWithDataRepresentation + -- Added and enforced MAX_UNAME_LENGTH + -- added key_equal(_plus, other->_plus) to -[NSFEEPublicKey isEqual:] + -- last version with NSGiantIntegers.m, utilities.m, NSFastEllipticCurve.m + as ObjC files + +CryptKit-11 + * FEE_KEYSTRING_VERSION = 2 + FEE_KEYSTRING_VERSION_MIN = 1 + -- Major rewrite of all top-level classes; ported bulk of logic to + portable C code. ObjC API (in NSCryptors.h, NSDESCryptor.h) unchanged. + +CryptKit-12 + * Alpha version sent to REC 6 Sep 1996 and to dreece 12 Sep 96 + -- Added platform.[ch] + -- Fixed (bminBytes kludge from make_pad() + -- was iszero(); is isZero() + -- made bitlen() assertion conditional on FEE_DEBUG + -- Trimmed plainBlockSize by one byte if q mod 8 = 0 in feeFEED, + feeFEEEDExp. This is an incompatible change! But I don't think anyone + was using the last version.... + +CryptKit-22 + * Integrated into cryptdev master 31 Mar 1997 + -- New NSMD5Hash class + -- Rewrote NSDESCryptor using feeDES + -- NSDataDigester was interface, is protocol + -- Deleted digestObjectsWithKeys method from NSDataDigester + -- Deleted NSRequestConcreteImplementation from NSDESCryptor and + NSRandomNumberGenerator + -- Rewrote NSRandomNumberGenerator using feeRandom + -- Cleaned up misc. #ifdefs and stale code + -- Put DES per-instance variables in struct _desInst + -- Fixed memory leaks in feePubKeyCreateKeyString(), feeFEED.c + -- Removed ANSI C headers from Public Header; framework is now strictly + ObjC + +CryptKit-23 + * Integrated into cryptdev master 1 May 1997 + * Associated with ComDemo announcement 1 May 1997 + -- No functional changes, only debugging printfs + +CryptKit-24 + * Integrated into cryptdev master 11 June 1997 + -- Mods to build on Mac CodeWarrior + -- was #import, is #include + -- mods to platform.[ch] + -- lots of compiler warning fixes, mainly due to MW's inability to + implicitly cast unsigned char * to char * + +CryptKit-25 + * Integrated into cryptdev master 18 June 1997 + -- New divg_via_recip(), modg_via_recip(), make_recip() + -- new per-curveParams fields x1OrderPlusRecip and lesserX1OrderRecip + -- Added lesserX1OrderJustify(), x1OrderPlusJustify(), binvg_cp() + -- Added new multiple stack borrowGiant() mechanism + -- All calls to borrowGiant() and newGiant() explicitly pass needed size; + no more borrowGiant(0) + -- Deleted old (i.e., obsolete and/or debugging) code from + NSGiantIntegers.c and NSFastEllipticCurve.c + -- Added description of FEED and FEEDExp ciphertext to ByteRep.doc + -- Marked KeyStringFormat.doc as obsolete + +CryptKit-26 + -- Implemented ECDSA in feeECDSA.[ch] + -- Added binvg_orderPlus(), x1OrderPlusMod() + -- Added generic signature encode/decode to byteRep.[ch] diff --git a/libsecurity_cryptkit/lib/ckDES.c b/libsecurity_cryptkit/lib/ckDES.c new file mode 100644 index 00000000..713f9d47 --- /dev/null +++ b/libsecurity_cryptkit/lib/ckDES.c @@ -0,0 +1,546 @@ +/* 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. + *************************************************************************** + * + * DES.c - raw DES encryption engine + * + * 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 + * Changed to use platform-dependent fmalloc(), ffree() + * 31 Mar 97 Doug Mitchell 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 + * Broke out from NSDESCryptor.m + * 22 Feb 96 Blaine Garst at NeXT + * Created. + */ + +#include "ckconfig.h" + +#if CRYPTKIT_SYMMETRIC_ENABLE + +#include "ckDES.h" +#include "falloc.h" +#include + +#ifndef NULL +#define NULL ((void *)0) +#endif /* NULL */ + +#define DES_DEBUG 0 /* enables some printfs */ + +/* Sofware DES functions + * written 12 Dec 1986 by Phil Karn, KA9Q; large sections adapted from + * the 1977 public-domain program by Jim Gillogly + */ + +#ifdef __LITTLE_ENDIAN__ +/* Byte swap a long */ +static unsigned int byteswap(unsigned int x) { + register char *cp,tmp; + + cp = (char *)&x; + tmp = cp[3]; + cp[3] = cp[0]; + cp[0] = tmp; + + tmp = cp[2]; + cp[2] = cp[1]; + cp[1] = tmp; + + return x; +} +#endif + +/* Tables defined in the Data Encryption Standard documents */ + +/* initial permutation IP */ +static const char ip[] = { + 58, 50, 42, 34, 26, 18, 10, 2, + 60, 52, 44, 36, 28, 20, 12, 4, + 62, 54, 46, 38, 30, 22, 14, 6, + 64, 56, 48, 40, 32, 24, 16, 8, + 57, 49, 41, 33, 25, 17, 9, 1, + 59, 51, 43, 35, 27, 19, 11, 3, + 61, 53, 45, 37, 29, 21, 13, 5, + 63, 55, 47, 39, 31, 23, 15, 7 +}; + +/* final permutation IP^-1 */ +static const char fp[] = { + 40, 8, 48, 16, 56, 24, 64, 32, + 39, 7, 47, 15, 55, 23, 63, 31, + 38, 6, 46, 14, 54, 22, 62, 30, + 37, 5, 45, 13, 53, 21, 61, 29, + 36, 4, 44, 12, 52, 20, 60, 28, + 35, 3, 43, 11, 51, 19, 59, 27, + 34, 2, 42, 10, 50, 18, 58, 26, + 33, 1, 41, 9, 49, 17, 57, 25 +}; + +/* expansion operation matrix + * This is for reference only; it is unused in the code + * as the f() function performs it implicitly for speed + */ +#ifdef notdef +static char ei[] = { + 32, 1, 2, 3, 4, 5, + 4, 5, 6, 7, 8, 9, + 8, 9, 10, 11, 12, 13, + 12, 13, 14, 15, 16, 17, + 16, 17, 18, 19, 20, 21, + 20, 21, 22, 23, 24, 25, + 24, 25, 26, 27, 28, 29, + 28, 29, 30, 31, 32, 1 +}; +#endif + +/* permuted choice table (key) */ +static const char pc1[] = { + 57, 49, 41, 33, 25, 17, 9, + 1, 58, 50, 42, 34, 26, 18, + 10, 2, 59, 51, 43, 35, 27, + 19, 11, 3, 60, 52, 44, 36, + + 63, 55, 47, 39, 31, 23, 15, + 7, 62, 54, 46, 38, 30, 22, + 14, 6, 61, 53, 45, 37, 29, + 21, 13, 5, 28, 20, 12, 4 +}; + +/* number left rotations of pc1 */ +static const char totrot[] = { + 1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28 +}; + +/* permuted choice key (table) */ +static const char pc2[] = { + 14, 17, 11, 24, 1, 5, + 3, 28, 15, 6, 21, 10, + 23, 19, 12, 4, 26, 8, + 16, 7, 27, 20, 13, 2, + 41, 52, 31, 37, 47, 55, + 30, 40, 51, 45, 33, 48, + 44, 49, 39, 56, 34, 53, + 46, 42, 50, 36, 29, 32 +}; + +/* The (in)famous S-boxes */ +static const char si[8][64] = { + { + /* S1 */ + 14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7, + 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8, + 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0, + 15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13 + }, + { + /* S2 */ + 15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10, + 3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5, + 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15, + 13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9 + }, + { + /* S3 */ + 10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8, + 13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1, + 13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7, + 1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12 + }, + { + /* S4 */ + 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15, + 13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9, + 10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4, + 3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14 + }, + { + /* S5 */ + 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9, + 14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6, + 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14, + 11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3 + }, + { + /* S6 */ + 12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11, + 10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8, + 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6, + 4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13 + }, + { + /* S7 */ + 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1, + 13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6, + 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2, + 6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12 + }, + { + /* S8 */ + 13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7, + 1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2, + 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8, + 2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11 + } +}; + +/* 32-bit permutation function P used on the output of the S-boxes */ +static const char p32i[] = { + 16, 7, 20, 21, + 29, 12, 28, 17, + 1, 15, 23, 26, + 5, 18, 31, 10, + 2, 8, 24, 14, + 32, 27, 3, 9, + 19, 13, 30, 6, + 22, 11, 4, 25 +}; +/* End of DES-defined tables */ + +/* Lookup tables initialized once only at startup by desinit() */ +static long (*sp)[64]; /* Combined S and P boxes */ + +static char (*iperm)[16][8]; /* Initial and final permutations */ +static char (*fperm)[16][8]; + + +/* bit 0 is left-most in byte */ +static const int bytebit[] = { + 0200,0100,040,020,010,04,02,01 +}; + +static const int nibblebit[] = { + 010,04,02,01 +}; + +/* Allocate space and initialize DES lookup arrays + * mode == 0: standard Data Encryption Algorithm + * mode == 1: DEA without initial and final permutations for speed + * mode == 2: DEA without permutations and with 128-byte key (completely + * independent subkeys for each round) + */ +/* Initialize the lookup table for the combined S and P boxes */ +static void spinit() { + char pbox[32]; + int p,i,s,j,rowcol; + long val; + + /* Compute pbox, the inverse of p32i. + * This is easier to work with + */ + for(p=0;p<32;p++){ + for(i=0;i<32;i++){ + if(p32i[i]-1 == p){ + pbox[p] = i; + break; + } + } + } + for(s = 0; s < 8; s++){ /* For each S-box */ + for(i=0; i<64; i++){ /* For each possible input */ + val = 0; + /* The row number is formed from the first and last + * bits; the column number is from the middle 4 + */ + rowcol = (i & 32) | ((i & 1) ? 16 : 0) | ((i >> 1) & 0xf); + for(j=0;j<4;j++){ /* For each output bit */ + if(si[s][rowcol] & (8 >> j)){ + val |= 1L << (31 - pbox[4*s + j]); + } + } + sp[s][i] = val; + +#if DES_DEBUG + printf("sp[%d][%2d] = %08lx\n",s,i,sp[s][i]); +#endif + } + } +} + +/* initialize a perm array */ +static void perminit(char perm[16][16][8], const char p[64]) { + register int l, j, k; + int i,m; + + /* Clear the permutation array */ + for (i=0; i<16; i++) + for (j=0; j<16; j++) + for (k=0; k<8; k++) + perm[i][j][k]=0; + + for (i=0; i<16; i++) /* each input nibble position */ + for (j = 0; j < 16; j++)/* each possible input nibble */ + for (k = 0; k < 64; k++)/* each output bit position */ + { l = p[k] - 1; /* where does this bit come from*/ + if ((l >> 2) != i) /* does it come from input posn?*/ + continue; /* if not, bit k is 0 */ + if (!(j & nibblebit[l & 3])) + continue; /* any such bit in input? */ + m = k & 07; /* which bit is this in the byte*/ + perm[i][j][k>>3] |= bytebit[m]; + } +} + +int desinit(desInst dinst, int mode) { + dinst->desmode = mode; + + /* + * Remainder only has to be done once. + */ + if(sp != NULL){ + /* Already initialized */ + return 0; + } + if((sp = (long (*)[64])fmalloc(sizeof(long) * 8 * 64)) == NULL){ + return -1; + } + spinit(); + if(mode == 1 || mode == 2) /* No permutations */ + return 0; + + iperm = (char (*)[16][8])fmalloc(sizeof(char) * 16 * 16 * 8); + if(iperm == NULL){ + ffree((char *)sp); + return -1; + } + perminit(iperm,ip); + + fperm = (char (*)[16][8])fmalloc(sizeof(char) * 16 * 16 * 8); + if(fperm == NULL){ + ffree((char *)sp); + ffree((char *)iperm); + return -1; + } + perminit(fperm,fp); + + return 0; +} +/* Free up storage used by DES */ +void desdone(desInst dinst) { +#if 0 + /* + * no per-instance mallocd data + */ + if(sp == NULL) + return; /* Already done */ + + // free((char *)sp); // NO! just free instance data; leave statics + // since these are consts + ffree((char *)dinst->kn); + //if(iperm != NULL) + // free((char *)iperm); + //if(fperm != NULL) + // free((char *)fperm); + + //sp = NULL; + //iperm = NULL; + //fperm = NULL; + dinst->kn = NULL; +#endif /* 0 */ +} +/* Set key (initialize key schedule array) */ +void dessetkey(desInst dinst, char *key) { + char pc1m[56]; /* place to modify pc1 into */ + char pcr[56]; /* place to rotate pc1 into */ + register int i,j,l; + int m; + + /* In mode 2, the 128 bytes of subkey are set directly from the + * user's key, allowing him to use completely independent + * subkeys for each round. Note that the user MUST specify a + * full 128 bytes. + * + * I would like to think that this technique gives the NSA a real + * headache, but I'm not THAT naive. + */ + if(dinst->desmode == 2){ + for(i=0;i<16;i++) + for(j=0;j<8;j++) + dinst->kn[i][j] = *key++; + return; + } + /* Clear key schedule */ + for (i=0; i<16; i++) + for (j=0; j<8; j++) + dinst->kn[i][j]=0; + + for (j=0; j<56; j++) { /* convert pc1 to bits of key */ + l=pc1[j]-1; /* integer bit location */ + m = l & 07; /* find bit */ + pc1m[j]=(key[l>>3] & /* find which key byte l is in */ + bytebit[m]) /* and which bit of that byte */ + ? 1 : 0; /* and store 1-bit result */ + } + for (i=0; i<16; i++) { /* key chunk for each iteration */ + for (j=0; j<56; j++) /* rotate pc1 the right amount */ + pcr[j] = pc1m[(l=j+totrot[i])<(j<28? 28 : 56) ? l: l-28]; + /* rotate left and right halves independently */ + for (j=0; j<48; j++){ /* select bits individually */ + /* check bit that goes to dinst->kn[j] */ + if (pcr[pc2[j]-1]){ + /* mask it in if it's there */ + l= j % 6; + dinst->kn[i][j/6] |= bytebit[l] >> 2; + } + } + } +#if DES_DEBUG + for(i=0;i<16;i++) { + printf("dinst->kn[%d] = ", i); + for(j=0;j<8;j++) { + printf("%x ", dinst->kn[i][j]); + } + printf("\n"); + } + +#endif /* 1 */ +} + +/* The nonlinear function f(r,k), the heart of DES */ +static long int f(unsigned long r, unsigned char subkey[8]) { + /* 32 bits */ + /* 48-bit key for this round */ + register unsigned long rval,rt; +#if DES_DEBUG + printf("f(%08lx, %02x %02x %02x %02x %02x %02x %02x %02x) = ", + r, + subkey[0], subkey[1], subkey[2], + subkey[3], subkey[4], subkey[5], + subkey[6], subkey[7]); +#endif + /* Run E(R) ^ K through the combined S & P boxes + * This code takes advantage of a convenient regularity in + * E, namely that each group of 6 bits in E(R) feeding + * a single S-box is a contiguous segment of R. + */ + rt = (r >> 1) | ((r & 1) ? 0x80000000 : 0); + rval = 0; + rval |= sp[0][((rt >> 26) ^ *subkey++) & 0x3f]; + rval |= sp[1][((rt >> 22) ^ *subkey++) & 0x3f]; + rval |= sp[2][((rt >> 18) ^ *subkey++) & 0x3f]; + rval |= sp[3][((rt >> 14) ^ *subkey++) & 0x3f]; + rval |= sp[4][((rt >> 10) ^ *subkey++) & 0x3f]; + rval |= sp[5][((rt >> 6) ^ *subkey++) & 0x3f]; + rval |= sp[6][((rt >> 2) ^ *subkey++) & 0x3f]; + rt = (r << 1) | ((r & 0x80000000) ? 1 : 0); + rval |= sp[7][(rt ^ *subkey) & 0x3f]; +#if DES_DEBUG + printf(" %08lx\n",rval); +#endif + return rval; +} + +/* Do one DES cipher round */ +static void round(desInst dinst, int num, unsigned long int *block) { + /* i.e. the num-th one */ + + /* The rounds are numbered from 0 to 15. On even rounds + * the right half is fed to f() and the result exclusive-ORs + * the left half; on odd rounds the reverse is done. + */ + if(num & 1){ + block[1] ^= f(block[0],dinst->kn[num]); + } else { + block[0] ^= f(block[1],dinst->kn[num]); + } +} + +/* Permute inblock with perm */ +static void permute(char *inblock, char perm[16][16][8], char *outblock) { + /* result into outblock,64 bits */ + /* 2K bytes defining perm. */ + register int i,j; + register char *ib, *ob; /* ptr to input or output block */ + register char *p, *q; + + if(perm == NULL){ + /* No permutation, just copy */ + for(i=8; i!=0; i--) + *outblock++ = *inblock++; + return; + } + /* Clear output block */ + for (i=8, ob = outblock; i != 0; i--) + *ob++ = 0; + + ib = inblock; + for (j = 0; j < 16; j += 2, ib++) { /* for each input nibble */ + ob = outblock; + p = perm[j][(*ib >> 4) & 017]; + q = perm[j + 1][*ib & 017]; + for (i = 8; i != 0; i--){ /* and each output byte */ + *ob++ |= *p++ | *q++; /* OR the masks together*/ + } + } +} +/* In-place encryption of 64-bit block */ +void endes(desInst dinst, char *block) { + register int i; + unsigned long work[2]; /* Working data storage */ + long tmp; + + permute(block,iperm,(char *)work); /* Initial Permutation */ +#ifdef __LITTLE_ENDIAN__ + work[0] = byteswap(work[0]); + work[1] = byteswap(work[1]); +#endif + + /* Do the 16 rounds */ + for (i=0; i<16; i++) + round(dinst,i,work); + + /* Left/right half swap */ + tmp = work[0]; + work[0] = work[1]; + work[1] = tmp; + +#ifdef __LITTLE_ENDIAN__ + work[0] = byteswap(work[0]); + work[1] = byteswap(work[1]); +#endif + permute((char *)work,fperm,block); /* Inverse initial permutation */ +} +/* In-place decryption of 64-bit block */ +void dedes(desInst dinst, char *block) { + register int i; + unsigned long work[2]; /* Working data storage */ + long tmp; + + permute(block,iperm,(char *)work); /* Initial permutation */ + +#ifdef __LITTLE_ENDIAN__ + work[0] = byteswap(work[0]); + work[1] = byteswap(work[1]); +#endif + + /* Left/right half swap */ + tmp = work[0]; + work[0] = work[1]; + work[1] = tmp; + + /* Do the 16 rounds in reverse order */ + for (i=15; i >= 0; i--) + round(dinst,i,work); + +#ifdef __LITTLE_ENDIAN__ + work[0] = byteswap(work[0]); + work[1] = byteswap(work[1]); +#endif + + permute((char *)work,fperm,block); /* Inverse initial permutation */ +} + +#endif /* CRYPTKIT_SYMMETRIC_ENABLE */ diff --git a/libsecurity_cryptkit/lib/ckDES.h b/libsecurity_cryptkit/lib/ckDES.h new file mode 100644 index 00000000..0cd9d7ff --- /dev/null +++ b/libsecurity_cryptkit/lib/ckDES.h @@ -0,0 +1,70 @@ +/* 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. + *************************************************************************** + * + * DES.h - raw DES encryption engine interface + * + * Revision History + * ---------------- + * 31 Mar 97 Doug Mitchell at Apple + * Put per-instance data in struct _desInst + * 21 Aug 96 Doug Mitchell at NeXT + * Broke out from NSDESCryptor.m + * 22 Feb 96 Blaine Garst at NeXT + * Created. + */ + +#ifndef _CK_DES_H_ +#define _CK_DES_H_ + +#include "ckconfig.h" + +#if CRYPTKIT_SYMMETRIC_ENABLE + +#ifdef __cplusplus +extern "C" { +#endif + +#define DES_BLOCK_SIZE_BYTES 8 /* in bytes */ +#define DES_KEY_SIZE_BITS 56 /* effective key size in bits */ +#define DES_KEY_SIZE_BITS_EXTERNAL 64 /* clients actually pass in this much */ +#define DES_KEY_SIZE_BYTES_EXTERNAL (DES_KEY_SIZE_BITS_EXTERNAL / 8) + +#define DES_MODE_STD 0 /* standard Data Encryption Algorithm */ +#define DES_MODE_FAST 1 /* DEA without initial and final */ + /* permutations for speed */ +#define DES_MODE_128 2 /* DEA without permutations and with */ + /* 128-byte key (completely independent */ + /* subkeys for each round) */ + +/* + * Per-instance data. + */ +struct _desInst { + /* 8 16-bit subkeys for each of 16 rounds, initialized by setkey() + */ + unsigned char kn[16][8]; + int desmode; +}; + +typedef struct _desInst *desInst; + +int desinit(desInst dinst, int mode); +void dessetkey(desInst dinst, char *key); +void endes(desInst dinst, char *block); +void dedes(desInst dinst, char *block); +void desdone(desInst dinst); + +#ifdef __cplusplus +} +#endif + +#endif /* CRYPTKIT_SYMMETRIC_ENABLE */ + +#endif /*_CK_DES_H_*/ diff --git a/libsecurity_cryptkit/lib/ckMD5.c b/libsecurity_cryptkit/lib/ckMD5.c new file mode 100644 index 00000000..6d59f3d1 --- /dev/null +++ b/libsecurity_cryptkit/lib/ckMD5.c @@ -0,0 +1,365 @@ +/* + File: MD5.c + + Written by: Colin Plumb + + Copyright: Copyright 1998 by 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 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 "ckconfig.h" + +#if CRYPTKIT_MD5_ENABLE && !CRYPTKIT_LIBMD_DIGEST + +#include "ckMD5.h" +#include "platform.h" +#include "byteRep.h" +#include + + +#define MD5_DEBUG 0 + +#if MD5_DEBUG +static inline void dumpCtx(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]); + +#if __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(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(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(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 */ + #if old_way + /* + * On a little endian machine, this writes the l.s. byte of + * the bit count to ctx->in[56] and the m.s byte of the bit count to + * ctx->in[63]. + */ + ((UINT32 *) ctx->in)[14] = ctx->bits[0]; + ((UINT32 *) ctx->in)[15] = ctx->bits[1]; + #else // new_way + intToByteRep(ctx->bits[0], &ctx->in[56]); + intToByteRep(ctx->bits[1], &ctx->in[60]); + #endif // new_way + + 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 */ + +#endif /* CRYPTKIT_MD5_ENABLE && CRYPTKIT_LIBMD_DIGEST */ diff --git a/libsecurity_cryptkit/lib/ckMD5.h b/libsecurity_cryptkit/lib/ckMD5.h new file mode 100644 index 00000000..251a89d9 --- /dev/null +++ b/libsecurity_cryptkit/lib/ckMD5.h @@ -0,0 +1,90 @@ +/* + File: MD5.h + + Written by: Colin Plumb + + Copyright: Copyright 1998 by 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 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_ + +#include "ckconfig.h" + +#if CRYPTKIT_MD5_ENABLE +#if CRYPTKIT_LIBMD_DIGEST + +/* + * In this case we use the MD5 implementation in libSystem. + */ +#include + +typedef CC_MD5_CTX MD5Context; + +#define MD5Init(c) CC_MD5_Init(c) +#define MD5Update(c, d, l) CC_MD5_Update(c, d, l) +#define MD5Final(c, d) CC_MD5_Final(d, c) + +#define MD5_DIGEST_SIZE CC_MD5_DIGEST_LENGTH + +#else /* ! CRYPTKIT_LIBMD_DIGEST */ + +/* Our own private implementation */ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __alpha +typedef unsigned int UINT32; +#elif defined (macintosh) || defined (__ppc__) +typedef unsigned int UINT32; +#else +typedef unsigned long UINT32; +#endif + +typedef struct { + UINT32 buf[4]; + UINT32 bits[2]; // bits[0] is low 32 bits of bit count + unsigned char in[64]; +} MD5Context; + +#define MD5_DIGEST_SIZE 16 /* in bytes */ + +void MD5Init(MD5Context *context); +void MD5Update(MD5Context *context, unsigned char const *buf, + unsigned len); +void MD5Final(MD5Context *context, unsigned char *digest); + +/* + * This is needed to make RSAREF happy on some MS-DOS compilers. + */ +typedef MD5Context MD5_CTX; + +#ifdef __cplusplus +} +#endif + +#endif /* CRYPTKIT_LIBMD_DIGEST */ +#endif /* CRYPTKIT_MD5_ENABLE */ +#endif /*_CK_MD5_H_*/ diff --git a/libsecurity_cryptkit/lib/ckSHA1.c b/libsecurity_cryptkit/lib/ckSHA1.c new file mode 100644 index 00000000..1da6b492 --- /dev/null +++ b/libsecurity_cryptkit/lib/ckSHA1.c @@ -0,0 +1,227 @@ +/* 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. + *************************************************************************** + * + * ckSHA1.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 "ckconfig.h" +#include "feeTypes.h" +#include "ckSHA1.h" + +#if CRYPTKIT_LIBMD_DIGEST +/* + * For linking with AppleCSP: use libSystem SHA1 implementation. + */ +#include +#else +#include "ckSHA1_priv.h" +#endif +#include "falloc.h" +#include "platform.h" + +#if CRYPTKIT_LIBMD_DIGEST +/* + * Trivial wrapper for SHA_CTX; a sha1Obj is a pointer to this. + */ +typedef struct { + CC_SHA1_CTX ctx; + unsigned char digest[CC_SHA1_DIGEST_LENGTH]; +} Sha1Obj; + +sha1Obj sha1Alloc(void) +{ + void *rtn = fmalloc(sizeof(Sha1Obj)); + memset(rtn, 0, sizeof(Sha1Obj)); + CC_SHA1_Init(&(((Sha1Obj *)rtn)->ctx)); + return (sha1Obj)rtn; +} + +void sha1Reinit(sha1Obj sha1) +{ + Sha1Obj *ctx = (Sha1Obj *)sha1; + CC_SHA1_Init(&ctx->ctx); +} + +void sha1Free(sha1Obj sha1) +{ + memset(sha1, 0, sizeof(Sha1Obj)); + ffree(sha1); +} + +void sha1AddData(sha1Obj sha1, + const unsigned char *data, + unsigned dataLen) +{ + Sha1Obj *ctx = (Sha1Obj *)sha1; + CC_SHA1_Update(&ctx->ctx, data, dataLen); +} + +unsigned char *sha1Digest(sha1Obj sha1) +{ + Sha1Obj *ctx = (Sha1Obj *)sha1; + CC_SHA1_Final(ctx->digest, &ctx->ctx); + return ctx->digest; +} + +unsigned sha1DigestLen(void) +{ + return CC_SHA1_DIGEST_LENGTH; +} + +#else /* standalone cryptkit implementation */ + +/* + * 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; +} + +unsigned sha1DigestLen(void) +{ + return SHS_DIGESTSIZE; +} + +#endif /* CRYPTKIT_LIBMD_DIGEST */ diff --git a/libsecurity_cryptkit/lib/ckSHA1.h b/libsecurity_cryptkit/lib/ckSHA1.h new file mode 100644 index 00000000..4fd08316 --- /dev/null +++ b/libsecurity_cryptkit/lib/ckSHA1.h @@ -0,0 +1,75 @@ +/* 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. + *************************************************************************** + * + * ckSHA1.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_ + +#if !defined(__MACH__) +#include +#else +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * 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); + +/* + * Obtain the length of the message digest. + */ +unsigned sha1DigestLen(void); + +#ifdef __cplusplus +} +#endif + +#endif /*_CK_SHA1_H_*/ diff --git a/libsecurity_cryptkit/lib/ckSHA1_priv.c b/libsecurity_cryptkit/lib/ckSHA1_priv.c new file mode 100644 index 00000000..356a07e3 --- /dev/null +++ b/libsecurity_cryptkit/lib/ckSHA1_priv.c @@ -0,0 +1,321 @@ +/* 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. + *************************************************************************** + * + * ckSHA1_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 "ckconfig.h" + +#if !CRYPTKIT_LIBMD_DIGEST + +#include "ckSHA1_priv.h" +#include "platform.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; +} + +/* __LITTLE_ENDIAN__ is in fact #defined on OS X on PPC.... */ +//#ifdef __LITTLE_ENDIAN__ +#if 0 + +/* 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->data, SHS_DIGESTSIZE ); + } + +#endif /* CRYPTKIT_LIBMD_DIGEST */ diff --git a/libsecurity_cryptkit/lib/ckSHA1_priv.h b/libsecurity_cryptkit/lib/ckSHA1_priv.h new file mode 100644 index 00000000..d3d953bb --- /dev/null +++ b/libsecurity_cryptkit/lib/ckSHA1_priv.h @@ -0,0 +1,60 @@ +/* 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. + *************************************************************************** + * + * ckSHA1_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_ + +#include "ckconfig.h" + +#if !CRYPTKIT_LIBMD_DIGEST + +#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 /* !CRYPTKIT_LIBMD_DIGEST */ + +#endif /* _CK_SHA1_PRIV_H_ */ diff --git a/libsecurity_cryptkit/lib/ckconfig.h b/libsecurity_cryptkit/lib/ckconfig.h new file mode 100644 index 00000000..9deb12e6 --- /dev/null +++ b/libsecurity_cryptkit/lib/ckconfig.h @@ -0,0 +1,106 @@ +/* + File: ckconfig.h + + Contains: Common config info. + + Written by: Doug Mitchell + + Copyright: Copyright 1998 by 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 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. + *************************************************************************** + */ + +#ifndef _CK_CONFIG_H_ +#define _CK_CONFIG_H_ + +/* + * Common build flags. + */ +#define DEBUG_ENGINE 0 + +#define ENGINE_127_BITS 0 /* hard-coded 127 elliptic() */ + +/* + * These flags are set en masse, one set per target in the XCode project file or + * Makefile. They determine what gets compiled into the library. Every flag + * has to be defined for every configureation - preprocessors directives use + * #if, not #ifdef. + */ + +#ifdef CK_SECURITY_BUILD +/* + * Standard Security.framework build + */ +#define CRYPTKIT_DER_ENABLE 1 /* DER encoding support */ +#define CRYPTKIT_LIBMD_DIGEST 1 /* use CommonCrypto digests */ +#define CRYPTKIT_ELL_PROJ_ENABLE 1 /* elliptic projection */ +#define CRYPTKIT_ECDSA_ENABLE 1 /* ECDSA (requires ELL_PROJ_ENABLE) */ +#define CRYPTKIT_CIPHERFILE_ENABLE 0 /* cipherfile w/symmetric encryption */ +#define CRYPTKIT_SYMMETRIC_ENABLE 0 /* symmetric encryption */ +#define CRYPTKIT_ASYMMETRIC_ENABLE 1 /* asymmetric encryption */ +#define CRYPTKIT_MD5_ENABLE 1 /* MD5 hash */ +#define CRYPTKIT_SHA1_ENABLE 1 /* SHA1 hash - needed for GHMAX_LEGACY */ +#define CRYPTKIT_HMAC_LEGACY 1 +#define CRYPTKIT_KEY_EXCHANGE 0 /* FEE key exchange */ +#define CRYPTKIT_HIGH_LEVEL_SIG 0 /* high level one-shot signature */ +#define CRYPTKIT_GIANT_STACK_ENABLE 0 /* cache of giants */ + +#elif defined(CK_STANDALONE_BUILD) +/* + * Standalone library build + */ +#define CRYPTKIT_DER_ENABLE 0 +#define CRYPTKIT_LIBMD_DIGEST 0 +#define CRYPTKIT_ELL_PROJ_ENABLE 1 +#define CRYPTKIT_ECDSA_ENABLE 1 +#define CRYPTKIT_CIPHERFILE_ENABLE 1 +#define CRYPTKIT_SYMMETRIC_ENABLE 1 +#define CRYPTKIT_ASYMMETRIC_ENABLE 1 +#define CRYPTKIT_MD5_ENABLE 1 +#define CRYPTKIT_SHA1_ENABLE 1 +#define CRYPTKIT_HMAC_LEGACY 0 +#define CRYPTKIT_KEY_EXCHANGE 1 +#define CRYPTKIT_HIGH_LEVEL_SIG 1 +#define CRYPTKIT_GIANT_STACK_ENABLE 1 + +#elif defined(CK_MINIMUM_SIG_BUILD) +/* + * Standalone, just ElGamal signature and key generation + */ +#define CRYPTKIT_DER_ENABLE 0 +#define CRYPTKIT_LIBMD_DIGEST 0 +#define CRYPTKIT_ELL_PROJ_ENABLE 0 +#define CRYPTKIT_ECDSA_ENABLE 0 +#define CRYPTKIT_CIPHERFILE_ENABLE 0 +#define CRYPTKIT_SYMMETRIC_ENABLE 0 +#define CRYPTKIT_ASYMMETRIC_ENABLE 0 +#define CRYPTKIT_MD5_ENABLE 1 +/* FIXME convert native ElGamal to use SHA1! */ +#define CRYPTKIT_SHA1_ENABLE 0 +#define CRYPTKIT_HMAC_LEGACY 0 +#define CRYPTKIT_KEY_EXCHANGE 0 +#define CRYPTKIT_HIGH_LEVEL_SIG 0 +#define CRYPTKIT_GIANT_STACK_ENABLE 1 + +#else + +#error You must supply a build configuration. +#endif + +#endif /* _CK_CONFIG_H_ */ diff --git a/libsecurity_cryptkit/lib/ckutilities.c b/libsecurity_cryptkit/lib/ckutilities.c new file mode 100644 index 00000000..26bec08e --- /dev/null +++ b/libsecurity_cryptkit/lib/ckutilities.c @@ -0,0 +1,416 @@ +/* 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. + *************************************************************************** + * + * ckutilities.c - general C routines + * + * Revision History + * ---------------- + * 10/06/98 ap + * Changed to compile with C++. + * 08 Apr 98 Doug Mitchell at Apple + * Mods for variable size giantDigit. + * Rewrote serializeGiant(), deserializeGiant() to conform to IEEE P1363. + * 23 Mar 98 Doug Mitchell at Apple + * Added FR_WrongSignatureType, FR_BadKeyBlob to frtnStrings. + * Added initCryptKit(). + * 19 Jan 98 Doug Mitchell at Apple + * Added cStringToUc() + * 09 Jan 98 Doug Mitchell at Apple + * Added non-FEE_DEBUG version of printGiantHex() + * 27 Jan 97 Doug Mitchell at NeXT + * Addd serializeGiant(), deserializeGiant; Deleted data_to_giant() + * 12 Dec 96 Doug Mitchell at NeXT + * Added byteRepTo{int,key,giant}(). + * 2 Aug 96 Doug Mitchell at NeXT + * Broke out from Blaine Garst's original NSCryptors.m + */ + +#include "ckutilities.h" +#include "falloc.h" +#include "feeTypes.h" +#include "feeDebug.h" +#include "feeFunctions.h" +#include "byteRep.h" +#include "platform.h" +#include "curveParams.h" +#include +#ifdef NeXT +#include +#include +#include +#include +#endif // NeXT + +/* + * feeReturn strings. + */ +typedef struct { + feeReturn frtn; + const char *frtnString; +} frtnItem; + +static const frtnItem frtnStrings[] = { +#ifndef NDEBUG + { FR_Success, "Success" }, + { FR_BadPubKey, "Bad Public Key" }, + { FR_BadPubKeyString, "Bad Public Key String" }, + { FR_IncompatibleKey, "Incompatible key format" }, + { FR_IllegalDepth, "Illegal Depth" }, + { FR_BadUsageName, "Bad Usage Name" }, + { FR_BadSignatureFormat, "Bad Signature Format" }, + { FR_InvalidSignature, "Invalid Signature" }, + { FR_IllegalArg, "Illegal Argument" }, + { FR_BadCipherText, "Bad Ciphertext Format" }, + { FR_Unimplemented, "Unimplemented Function" }, + { FR_BadCipherFile, "Bad CipherFile Format" }, + { FR_BadEnc64, "Bad enc64 Format" }, + { FR_WrongSignatureType, "Wrong Signature Type" }, + { FR_BadKeyBlob, "Bad Key Blob" }, + { FR_IllegalCurve, "Bad curve type" }, + { FR_Internal, "Internal Library Error" }, + { FR_Memory, "Out of Memory" }, + { FR_ShortPrivData, "Insufficient Seed Data" }, +#endif /* NDEBUG */ + { (feeReturn) 0, NULL }, +}; + +/* + * One-time only init of CryptKit library. + */ +void initCryptKit(void) +{ + #if GIANTS_VIA_STACK + curveParamsInitGiants(); + #endif +} + +/* + * Shutdown. + */ +void terminateCryptKit() +{ + #if GIANTS_VIA_STACK + freeGiantStacks(); + #endif +} + +/* + * Create a giant, initialized with specified char[] data. + */ +giant giant_with_data(const unsigned char *d, int len) { + int numDigits = BYTES_TO_GIANT_DIGITS(len); + giant result; + + result = newGiant(numDigits); + deserializeGiant(d, result, len); + return result; +} + +/* + * Obtain a malloc'd memory chunk init'd with specified giant's data. + * Resulting bytes are portable. Size of malloc'd memory is always zero + * mod GIANT_BYTES_PER_DIGIT. + * + * Calling this function for a giant obtained by giant_with_data() yields + * the original data, with extra byte(s) of leading zeros if the original + * was not zero mod GIANT_BYTES_PER_DIGIT. + */ +unsigned char *mem_from_giant(giant g, + unsigned *memLen) /* RETURNED size of malloc'd region */ +{ + unsigned char *cp; + unsigned numDigits = (g->sign < 0) ? -g->sign : g->sign; + + *memLen = numDigits * GIANT_BYTES_PER_DIGIT; + cp = (unsigned char*) fmalloc(*memLen); + serializeGiant(g, cp, *memLen); + return cp; +} + +extern const char *feeReturnString(feeReturn frtn) +{ + const frtnItem *fi = frtnStrings; + + while(fi->frtnString) { + if(fi->frtn == frtn) { + return fi->frtnString; + } + fi++; + } + return "Unknown Status"; +} + +#if FEE_DEBUG +void printGiant(const giant x) +{ + int i; + + printf("sign=%d cap=%d n[]=", x->sign, x->capacity); + for(i=0; isign); i++) { + printf("%u:", x->n[i]); + } + printf("\n"); +} + +void printGiantHex(const giant x) +{ + int i; + + printf("sign=%d cap=%d n[]=", x->sign, x->capacity); + for(i=0; isign); i++) { + printf("%x:", x->n[i]); + } + printf("\n"); +} + +/* + * Print in the form + * sign=8 cap=16 n[]=29787 + 3452 * w^1 + 55260 * w^2 + ... + */ +void printGiantExp(const giant x) +{ + int i; + int size = abs(x->sign); + + printf("sign=%d cap=%d n[]=", x->sign, x->capacity); + for(i=0; in[i]); + if(i > 0) { + printf("* w^%d ", i); + } + if(i<(size-1)) { + printf("+ "); + } + } + printf("\n"); +} + +void printKey(const key k) +{ + printf(" twist %d\n", k->twist); + printf(" x: "); + printGiant(k->x); +} + +void printCurveParams(const curveParams *p) +{ + const char *pt; + const char *ct; + + switch(p->primeType) { + case FPT_Mersenne: + pt = "FPT_Mersenne"; + break; + case FPT_FEE: + pt = "FPT_FEE"; + break; + case FPT_General: + pt = "FPT_General"; + break; + default: + pt = "UNKNOWN!"; + break; + } + switch(p->curveType) { + case FCT_Montgomery: + ct = "FCT_Montgomery"; + break; + case FCT_Weierstrass: + ct = "FCT_Weierstrass"; + break; + case FCT_General: + ct = "FCT_General"; + break; + default: + ct = "UNKNOWN!"; + break; + } + printf(" q %d k %d primeType %s curveType %s\n", + p->q, p->k, pt, ct); + printf(" minBytes %d maxDigits %d\n", p->minBytes, p->maxDigits); + printf(" a : "); + printGiant(p->a); + printf(" b : "); + printGiant(p->b); + printf(" c : "); + printGiant(p->c); + printf(" basePrime : "); + printGiant(p->basePrime); + printf(" x1Plus : "); + printGiant(p->x1Plus); + printf(" x1Minus : "); + printGiant(p->x1Minus); + printf(" cOrderPlus : "); + printGiant(p->cOrderPlus); + printf(" cOrderMinus : "); + printGiant(p->cOrderMinus); + printf(" x1OrderPlus : "); + printGiant(p->x1OrderPlus); + printf(" x1OrderMinus: "); + printGiant(p->x1OrderMinus); +} +#else +void printGiant(const giant x) {} +void printGiantHex(const giant x) {} +void printGiantExp(const giant x) {} +void printKey(const key k) {} +void printCurveParams(const curveParams *p) {} + +#endif /* FEE_DEBUG */ + +#if defined(NeXT) && !defined(WIN32) + +void getpassword(const char *prompt, char *pbuf) +{ + struct sgttyb ttyb; + int flags; + register char *p; + register int c; + FILE *fi; + void (*sig)(int); + + if ((fi = fdopen(open("/dev/tty", 2, 0), "r")) == NULL) + fi = stdin; + else + setbuf(fi, (char *)NULL); + sig = signal(SIGINT, SIG_IGN); + ioctl(fileno(fi), TIOCGETP, &ttyb); + flags = ttyb.sg_flags; + ttyb.sg_flags &= ~ECHO; + ioctl(fileno(fi), TIOCSETP, &ttyb); + fprintf(stderr, "%s", prompt); fflush(stderr); + for (p=pbuf; (c = getc(fi))!='\n' && c!=EOF;) { + if (p < &pbuf[PHRASELEN-1]) + *p++ = c; + } + *p = '\0'; + fprintf(stderr, "\n"); fflush(stderr); + ttyb.sg_flags = flags; + ioctl(fileno(fi), TIOCSETP, &ttyb); + (void)signal(SIGINT, sig); + if (fi != stdin) + fclose(fi); +} +#endif // NeXT + +/* + * serialize, deserialize giants's n[] to/from byte stream. + * First byte of byte stream is the MS byte of the resulting giant, + * regardless of the size of giantDigit. + * + * No assumption is made about the alignment of cp. + * + * As of 7 Apr 1998, these routines are in compliance with IEEE P1363, + * section 5.5.1, for the representation of a large integer as a byte + * stream. + */ +void serializeGiant(giant g, + unsigned char *cp, + unsigned numBytes) +{ + unsigned digitDex; + unsigned numDigits = BYTES_TO_GIANT_DIGITS(numBytes); + giantDigit digit; + unsigned char *ptr; + unsigned digitByte; + int size = abs(g->sign); + + if(numBytes == 0) { + return; + } + if(numBytes > (g->capacity * GIANT_BYTES_PER_DIGIT)) { + CKRaise("serializeGiant: CAPACITY EXCEEDED!\n"); + } + + /* + * note we might be asked to write more than the valid number + * if bytes in the giant in the case if truncated sign due to + * zero M.S. digit(s).... + */ + + /* + * zero out unused digits so we can infer sign during deserialize + */ + for(digitDex=size; digitDexn[digitDex] = 0; + } + + /* + * Emit bytes starting from l.s. byte. L.s. byte of the outgoing + * data stream is *last*. L.s. digit of giant's digits is *first*. + */ + digitDex = 0; + ptr = &cp[numBytes - 1]; + do { + /* one loop per giant digit */ + digit = g->n[digitDex++]; + for(digitByte=0; digitByte>= 8; + } + } while(numBytes != 0); + +} + +/* + * Resulting sign here is always positive; leading zeroes are reflected + * in an altered g->sign. + */ +void deserializeGiant(const unsigned char *cp, + giant g, + unsigned numBytes) +{ + unsigned numDigits; + giantDigit digit; + int digitDex; + unsigned digitByte; + const unsigned char *ptr; + + if(numBytes == 0) { + g->sign = 0; + return; + } + numDigits = (numBytes + GIANT_BYTES_PER_DIGIT - 1) / + GIANT_BYTES_PER_DIGIT; + if(numBytes > (g->capacity * GIANT_BYTES_PER_DIGIT)) { + CKRaise("deserializeGiant: CAPACITY EXCEEDED!\n"); + } + + /* + * Start at l.s. byte. That's the end of the cp[] array and + * the beginning of the giantDigit array. + */ + digitDex = 0; + ptr = &cp[numBytes - 1]; + do { + /* one loop per digit */ + digit = 0; + for(digitByte=0; digitByten before this break? */ + if(--numBytes == 0) { + break; + } + } + g->n[digitDex++] = digit; + } while (numBytes != 0); + + /* + * Infer sign from non-zero n[] elements + */ + g->sign = numDigits; + gtrimSign(g); +} + diff --git a/libsecurity_cryptkit/lib/ckutilities.h b/libsecurity_cryptkit/lib/ckutilities.h new file mode 100644 index 00000000..f74f3788 --- /dev/null +++ b/libsecurity_cryptkit/lib/ckutilities.h @@ -0,0 +1,47 @@ +/* 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. + *************************************************************************** + * + * ckutilities.h - general private C routine declarations + * + * Revision History + * ---------------- + * 10/06/98 ap + * Changed to compile with C++. + * 2 Aug 96 Doug Mitchell at NeXT + * Broke out from Blaine Garst's original NSCryptors.m + */ + +#ifndef _CK_UTILITIES_H_ +#define _CK_UTILITIES_H_ + +#include "giantIntegers.h" +#include "elliptic.h" +#include "feeTypes.h" + +#ifdef __cplusplus +extern "C" { +#endif + +unsigned char *mem_from_giant(giant x, unsigned *memLen); +giant giant_with_data(const unsigned char *d, int len); + +void serializeGiant(giant g, + unsigned char *cp, + unsigned numBytes); + +void deserializeGiant(const unsigned char *cp, + giant g, + unsigned numBytes); + +#ifdef __cplusplus +} +#endif + +#endif /* _CK_UTILITIES_H_ */ diff --git a/libsecurity_cryptkit/lib/curveParamData.h b/libsecurity_cryptkit/lib/curveParamData.h new file mode 100644 index 00000000..24b5e6fc --- /dev/null +++ b/libsecurity_cryptkit/lib/curveParamData.h @@ -0,0 +1,540 @@ +/* New ECC curves, + + 14 Apr 2001 (REC) ensured x1Minus arithmetic & prime point orders + 5 Apr 2001 (REC) factored minusorder for NIST-P-192 + 3 Apr 2001 (REC) first draft + + c. 2001 Apple Computer, Inc. + All Rights Reserved. + + Currently there are 7 (seven) curves, at varying + bit-depth and varying parameter types: + + FEE curves (use Montgomery arithmetic and feemod base-prime): + 31 bits + 127 bits + IEEE curves (use projective arithmetic): + 31 bits (feemod base-prime) + 128 bits (feemod base-prime) + 161 bits (feemod base-prime) (default preference) + 161 bits (general prime) + 192 bits (general. prime) (NIST-recommended) + + Each curve is given key comments atop the parameters. + For performance considerations, + + primeType->Mersenne is faster than primeType->feemod is + faster than primeType->general + + curveType->Montgomery is faster than curveType->Weierstrass, + + Some choices are not obvious except to cryptographers; + e.g., the two curves given for 161 bits exist because + of cryptographic controversies; probably the curve with + both orders prime is more secure, so it is perhaps + the curve of choice at 161 bits. + + The parameters/points have standard meaning, except for our + special entities as listed below. It is important to note the + principle thgat, without exception, every CryptKit base prime + p is = 3 (mod 4). This allows simple square-rooting in the field + F_p. Because of this universal constraint, (-1) is always a + quadratic nonresidue and so twist curves as below can assume + g = -1. + + (...)plusOrder := The usual elliptic-curve order; + (...)x1Plus := x-coordinate on y^2 = x^3 + c x^2 + a x + b; + (...)x1OrderPlus := Order of x1Plus, always divides plusOrder + (...)minusOrder := Order of the twist curve = 2p+2-plusOrder + (...)x1Minus := x-coordinate chosen on the twist curve + g y^2 = x^3 + c x^2 + a x + b + where g = -1 is the nonresidue, and such that + the special, x-coordinates-only, twofold-ambiguous "add" of + FEED works on the minus curve, using the same curve + parameters a,b,c as for the plus curve. Note that + x1Minus is to be chosen so that the correct "add" arithmetic + occurs, and also so that the desired point order accrues. + (...)x1OrderMinus := Order of x1Plus, always divides minusOrder. + + In each of the curves specified below, the plusOrder (at least) + is prime, while each of the point orders x1OrderPlus/Minus + is always prime. + + Note that the older labels Atkin3, Atkin4 have been abolished. + + */ + + /* FEE CURVE: USE FOR FEE SIG. & FEED ONLY. + * primeType->Mersenne + * curveType->Montgomery + * q = 31; k = 1; p = 2^q - k; + * a = 1; b = 0; c = 666; + * Both orders composite. + */ +static const arrayDigit ga_31m_x1Plus[] = + {2, 61780, 6237}; + /* 408809812 */ +static const arrayDigit ga_31m_x1Minus[] = + {2,12973,30585}; + /* 2004431533 */ +static const arrayDigit ga_31m_plusOrder[] = + {2, 25928, 32768 }; + /* 2147509576 = 2^3 * 268438697. */ +static const arrayDigit ga_31m_minusOrder[] = + {2, 39608, 32767 }; + /* 2147457720 = 2^3 * 3 * 5 * 17895481. */ +static const arrayDigit ga_31m_x1OrderPlus[] = + {2, 3241, 4096}; + /* 268438697 */ +static const arrayDigit ga_31m_x1OrderMinus[] = + {2, 4153, 273}; + /* 17895481 */ +static const arrayDigit ga_31m_x1OrderPlusRecip[] = + {2, 52572, 16383}; +static const arrayDigit ga_31m_lesserX1OrderRecip[] = + {2, 759, 960}; + + /* IEEE P1363 COMPATIBLE. + * primeType->Mersenne + * curveType->Weierstrass + * q = 31; k = 1; p = 2^q-k; + * a = 5824692 b = 2067311435 c = 0 + * Both orders prime. + */ +static const arrayDigit ga_31w_x1Plus[] = + {1, 6 }; +static const arrayDigit ga_31w_x1Minus[] = + {1, 7 }; +static const arrayDigit ga_31w_plusOrder[] = + {2,59003,32766 }; + /* 2147411579 */ +static const arrayDigit ga_31w_minusOrder[] = + {2,6533,32769 }; + /* 2147555717 */ +static const arrayDigit ga_31w_x1OrderPlus[] = + {2,59003,32766}; + /* 2147411579 */ +static const arrayDigit ga_31w_x1OrderMinus[] = + {2,6533,32769}; + /* 2147555717 */ +static const arrayDigit ga_31w_x1OrderPlusRecip[] = + {2, 6535, 32769}; + +static const arrayDigit ga_31w_a[] = + {2,57524,88}; + /* 5824692 */ +static const arrayDigit ga_31w_b[] = + {2,43851,31544}; + /* 2067311435 */ + + /* FEE CURVE: USE FOR FEE SIG. & FEED ONLY. + * primeType->Mersenne + * curveType->Montgomery + * q = 127; k = 1; p = 2^q - k; + * a = 1; b = 0; c = 666; + * Both orders composite. + */ +static const arrayDigit ga_127m_x1Plus[] = + {8, 24044, 39922, 11050, + 24692, 34049, 9793, 1228, 31562}; + /* 163879370753099435779911346846180728300 */ +static const arrayDigit ga_127m_x1Minus[] = + {8,49015,6682,26772,63672,45560,46133,24769,8366}; + /* 43440717976631899041527862406676135799 */ +static const arrayDigit ga_127m_plusOrder[] = + { 8, 14612, 61088, 34331, + 32354, 65535, 65535, 65535, + 32767}; + /* 170141183460469231722347548493196835092 = +2^2 * 3^4 * 71 * 775627 * 9535713005180210505588285449. */ +static const arrayDigit ga_127m_minusOrder[] = + { 8, 50924, 4447, 31204, + 33181, 0, 0, 0, + 32768 }; + /* 170141183460469231741027058938571376364 = +2^2 * 17 * 743 * 1593440383 * 2113371777483973234080067. */ +static const arrayDigit ga_127m_x1OrderPlus[] = + {6, 8201, 61942, 37082, + 53787, 49605, 7887 }; + /* 9535713005180210505588285449 */ +static const arrayDigit ga_127m_x1OrderMinus[] = + {6, 14659, 1977,16924, + 7446, 49030, 1}; + /* 2113371777483973234080067 */ +static const arrayDigit ga_127m_x1OrderPlusRecip[] = + {6, 21911, 8615, 0, 40960, 64107, 8507}; +static const arrayDigit ga_127m_lesserX1OrderRecip[] = + {6, 44759, 65533, 17695, 61560, 18883, 2}; + + /* IEEE P1363 COMPATIBLE. + * primeType->feemod + * curveType->Weierstrass + * q = 127; k = -57675; p = 2^q - k; + * a = 170141183460469025572049133804586627403; + * b = 170105154311605172483148226534443139403; c = 0; + * Both orders prime.: + */ +static const arrayDigit ga_128w_x1Plus[] = + {1,6}; + /* 6 */ +static const arrayDigit ga_128w_x1Minus[] = + {1,3}; + /* 3 */ +static const arrayDigit ga_128w_plusOrder[] = + {8,40455,13788,48100,24190,1,0,0,32768}; + /* 170141183460469231756943134065055014407. */ +static const arrayDigit ga_128w_minusOrder[] = + {8,9361,51749,17435,41345,65534,65535,65535,32767}; + /* 170141183460469231706431473366713312401. */ +static const arrayDigit ga_128w_x1OrderPlus[] = + {8,40455,13788,48100,24190,1,0,0,32768}; + /* 170141183460469231756943134065055014407. */ +static const arrayDigit ga_128w_x1OrderMinus[] = + {8,9361,51749,17435,41345,65534,65535,65535,32767}; + /* 170141183460469231706431473366713312401. */ +static const arrayDigit ga_128w_x1OrderPlusRecip[] = + {9,34802,10381,4207,34309,65530,65535,65535,65535,1}; +static const arrayDigit ga_128w_lesserX1OrderRecip[] = + {8,56178,13786,48100,24190,1,0,0,32768}; + +static const arrayDigit ga_128w_a[] = + {8,29003,44777,29962,4169,54360,65535,65535,32767}; + /* 170141183460469025572049133804586627403; */ +static const arrayDigit ga_128w_b[] = + {8,16715,42481,16221,60523,56573,13644,4000,32761}; + /* 170105154311605172483148226534443139403. */ + + /* IEEE P1363 COMPATIBLE. + * primeType->feemod + * curveType->Weierstrass + * q = 160; k = -5875; p = 2^q - k; + * a = 1461501637330902918203684832716283019448563798259; + * b = 36382017816364032; c = 0; + * Both orders prime.: + */ +static const arrayDigit ga_161w_x1Plus[] = + {1,7}; + /* 7 */ +static const arrayDigit ga_161w_x1Minus[] = + {1,4}; + /* 4 */ +static const arrayDigit ga_161w_plusOrder[] = + {11,50651,30352,49719,403,64085,1,0,0,0,0,1}; + /* 1461501637330902918203687223801810245920805144027. */ +static const arrayDigit ga_161w_minusOrder[] = + {10,26637,35183,15816,65132,1450,65534,65535,65535,65535,65535}; + /* 1461501637330902918203682441630755793391059953677. */ +static const arrayDigit ga_161w_x1OrderPlus[] = + {11,50651,30352,49719,403,64085,1,0,0,0,0,1}; + /* 1461501637330902918203687223801810245920805144027. */ +static const arrayDigit ga_161w_x1OrderMinus[] = + {10,26637,35183,15816,65132,1450,65534,65535,65535,65535,65535}; + /* 1461501637330902918203682441630755793391059953677. */ +static const arrayDigit ga_161w_x1OrderPlusRecip[] = + {11,59555,9660,63266,63920,5803,65528,65535,65535,65535,65535,3}; +/* added by dmitch */ +static const arrayDigit ga_161w_lesserX1OrderRecip[] = + {12,38902,30352,49719,403,64085,1,0,0,0,0,1,0}; +/* end addenda */ + +static const arrayDigit ga_161w_a[] = {10,4339,47068,65487,65535,65535,65535,65535,65535,65535,65535}; +/* 1461501637330902918203684832716283019448563798259; */ +static const arrayDigit ga_161w_b[] = {4,1024,41000,16704,129}; +/* 36382017816364032. */ + + /* IEEE P1363 COMPATIBLE. + * primeType->General + * curveType->Weierstrass + * p is a 161-bit random prime (below, ga_161_gen_bp[]); + * a = -152; b = 722; c = 0; + * Both orders composite.: + */ +static const arrayDigit ga_161_gen_bp[] = + {11,41419,58349,36408,14563,25486,9098,29127,50972,7281,8647,1}; + /* baseprime = 1654338658923174831024422729553880293604080853451 */ +static const arrayDigit ga_161_gen_x1Plus[] = + {10,59390,38748,49144,50217,32781,46057,53816,62856,18968,55868}; + /* 1245904487553815885170631576005220733978383542270 */ +static const arrayDigit ga_161_gen_x1Minus[] = + {10,12140,40021,9852,49578,18446,39468,28773,10952,26720,52624}; + /* 1173563507729187954550227059395955904200719019884 */ +static const arrayDigit ga_161_gen_plusOrder[] = + {11,41420,58349,36408,14563,25486,9100,29127,50972,7281,8647,1}; + /* 1654338658923174831024425147405519522862430265804 = + 2^2 * 23 * 359 * 479 * 102107 * 1024120625531724089187207582052247831. */ +static const arrayDigit ga_161_gen_minusOrder[] = + {11,41420,58349,36408,14563,25486,9096,29127,50972,7281,8647,1}; + /* 1654338658923174831024420311702241064345731441100 = +2^2 * 5^2 * 17^2 * 57243552211874561627142571339177891499852299. */ +static const arrayDigit ga_161_gen_x1OrderPlus[] = + {8,59671,64703,58305,55887,34170,37971,15627,197}; + /* 1024120625531724089187207582052247831 */ +static const arrayDigit ga_161_gen_x1OrderMinus[] = + {10,49675,56911,64364,6281,5543,59511,52057,44604,37151,2}; + /* 57243552211874561627142571339177891499852299 */ +static const arrayDigit ga_161_gen_x1OrderPlusRecip[] = + {8, 7566, 37898, 14581, 2404, 52670, 23839, 17554, 332}; + +static const arrayDigit ga_161_gen_a[] = {-1, 152}; /* a = -152 */ +static const arrayDigit ga_161_gen_b[] = { 1, 722}; /* b = 722 */ + + + /* IEEE P1363 COMPATIBLE. + * (NIST-P-192 RECOMMENDED PRIME) + * primeType->General + * curveType->Weierstrass + * p is a 192-bit prime (with efficient bit structure) (below, ga_192_gen_bp[]); + * a = -3; b = 2455155546008943817740293915197451784769108058161191238065; c = 0; + * Plus-order is prime, minus-order is composite. + */ +static const arrayDigit ga_192_gen_bp[] = + {12,65535,65535,65535,65535,65534,65535,65535,65535,65535,65535,65535,65535}; + /* baseprime = +6277101735386680763835789423207666416083908700390324961279 */ +static const arrayDigit ga_192_gen_x1Plus[] = + {1,3}; + /* 3 */ +static const arrayDigit ga_192_gen_x1Minus[] = + {12,25754,63413,46363,42413,24848,21836,55473,50853,40413,10264,8715,59556}; + /* 5704344264203732742656350325931731344592841761552300598426 */ +static const arrayDigit ga_192_gen_plusOrder[] = + {12,10289,46290,51633,5227,63542,39390,65535,65535,65535,65535,65535,65535}; + /* 6277101735386680763835789423176059013767194773182842284081 */ +static const arrayDigit ga_192_gen_minusOrder[] = + {13,55247,19245,13902,60308,1991,26145,0,0,0,0,0,0,1}; + /* 6277101735386680763835789423239273818400622627597807638479 = + 23 * 10864375060560251605900677743 * + 25120401793443689936479125511 */ +static const arrayDigit ga_192_gen_x1OrderPlus[] = + {12,10289,46290,51633,5227,63542,39390,65535,65535,65535,65535,65535,65535}; + /* 6277101735386680763835789423176059013767194773182842284081 */ +static const arrayDigit ga_192_gen_x1OrderMinus[] = + {12,16649,40728,9152,53911,59923,9684,22795,17096,45590,34192,25644,2849}; + /* 272917466755942641905903887966924948626114027286861201673 = +10864375060560251605900677743 * 25120401793443689936479125511 +*/ +static const arrayDigit ga_192_gen_x1OrderPlusRecip[] = + {13,55247,19245,13902,60308,1993,26145,0,0,0,0,0,0,1}; +static const arrayDigit ga_192_gen_lesserX1OrderRecip[] = +{12,57756,63294,44830,2517,2125,63187,65535,65535,65535,65535,65535,5887}; + +static const arrayDigit ga_192_gen_a[] = {-1, 3}; /* a = -3. */ +static const arrayDigit ga_192_gen_b[] = +{12,47537,49478,57068,65208,12361,29220,59819,4007,32999,58780,1305,25633}; +/* b = 2455155546008943817740293915197451784769108058161191238065. */ + +/*** + *** ANSI X9.62/Certicom curves + ***/ + +/* + * secp192r1 + * + * p = FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF + * = 6277101735386680763835789423207666416083908700390324961279 (d) + * a = FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC + * = 6277101735386680763835789423207666416083908700390324961276 + * b = 64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1 + * = 2455155546008943817740293915197451784769108058161191238065 + * x = 188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012 + * = 602046282375688656758213480587526111916698976636884684818 + * y = 07192B95FFC8DA78631011ED6B24CDD573F977A11E794811 + * = 174050332293622031404857552280219410364023488927386650641 + * order = FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831 + * = 6277101735386680763835789423176059013767194773182842284081 + * x1OrderRecip = 1000000000000000000000000662107c9eb94364e4b2dd7cf + */ +static const arrayDigit ga_192_secp_bp[] = + {12, 0xffff, 0xffff, 0xffff, 0xffff, 0xfffe, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff}; +static const arrayDigit ga_192_secp_x1Plus[] = + {12, 0x1012, 0x82ff, 0xafd, 0xf4ff, 0x8800, 0x43a1, 0x20eb, 0x7cbf, 0x90f6, 0xb030, 0xa80e, 0x188d}; +static const arrayDigit ga_192_secp_y1Plus[] = + {12, 0x4811, 0x1e79, 0x77a1, 0x73f9, 0xcdd5, 0x6b24, 0x11ed, 0x6310, 0xda78, 0xffc8, 0x2b95, 0x719}; +static const arrayDigit ga_192_secp_plusOrder[] = + {12, 0x2831, 0xb4d2, 0xc9b1, 0x146b, 0xf836, 0x99de, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff}; +/* the curve order is prime, so x1Order = curveOrder */ +static const arrayDigit ga_192_secp_x1OrderPlus[] = + {12, 0x2831, 0xb4d2, 0xc9b1, 0x146b, 0xf836, 0x99de, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff}; +static const arrayDigit ga_192_secp_x1OrderPlusRecip[] = + {13, 0xd7cf, 0x4b2d, 0x364e, 0xeb94, 0x7c9, 0x6621, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1}; +static const arrayDigit ga_192_secp_a[] = + {12, 0xfffc, 0xffff, 0xffff, 0xffff, 0xfffe, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff}; +static const arrayDigit ga_192_secp_b[] = + {12, 0xb9b1, 0xc146, 0xdeec, 0xfeb8, 0x3049, 0x7224, 0xe9ab, 0xfa7, 0x80e7, 0xe59c, 0x519, 0x6421}; + + +/* + * secp256r1 + * + * p = FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF + * = 115792089210356248762697446949407573530086143415290314195533631308867097853951 + * a = FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC + * = 115792089210356248762697446949407573530086143415290314195533631308867097853948 + * b = 5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B + * = 41058363725152142129326129780047268409114441015993725554835256314039467401291 + * x = 6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296 + * = 48439561293906451759052585252797914202762949526041747995844080717082404635286 + * y = 4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5 + * = 36134250956749795798585127919587881956611106672985015071877198253568414405109 + * order = FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551 + * = 115792089210356248762697446949407573529996955224135760342422259061068512044369 + * FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551 + * x1OrderRecip = 100000000fffffffffffffffeffffffff43190552df1a6c21012ffd85eedf9bfe + */ +static const arrayDigit ga_256_secp_bp[] = + {16, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x1, 0x0, 0xffff, 0xffff}; +static const arrayDigit ga_256_secp_x1Plus[] = + {16, 0xc296, 0xd898, 0x3945, 0xf4a1, 0x33a0, 0x2deb, 0x7d81, 0x7703, 0x40f2, + 0x63a4, 0xe6e5, 0xf8bc, 0x4247, 0xe12c, 0xd1f2, 0x6b17}; +static const arrayDigit ga_256_secp_y1Plus[] = + {16, 0x51f5, 0x37bf, 0x4068, 0xcbb6, 0x5ece, 0x6b31, 0x3357, 0x2bce, 0x9e16, + 0x7c0f, 0xeb4a, 0x8ee7, 0x7f9b, 0xfe1a, 0x42e2, 0x4fe3}; +static const arrayDigit ga_256_secp_plusOrder[] = + {16, 0x2551, 0xfc63, 0xcac2, 0xf3b9, 0x9e84, 0xa717, 0xfaad, 0xbce6, 0xffff, + 0xffff, 0xffff, 0xffff, 0x0, 0x0, 0xffff, 0xffff}; +static const arrayDigit ga_256_secp_x1OrderPlus[] = + {16, 0x2551, 0xfc63, 0xcac2, 0xf3b9, 0x9e84, 0xa717, 0xfaad, 0xbce6, 0xffff, + 0xffff, 0xffff, 0xffff, 0x0, 0x0, 0xffff, 0xffff}; +static const arrayDigit ga_256_secp_x1OrderPlusRecip[] = + {17, 0x9bfe, 0xeedf, 0xfd85, 0x12f, 0x6c21, 0xdf1a, 0x552, 0x4319, 0xffff, + 0xffff, 0xfffe, 0xffff, 0xffff, 0xffff, 0x0, 0x0, 0x1}; +static const arrayDigit ga_256_secp_a[] = + {16, 0xfffc, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x1, 0x0, 0xffff, 0xffff}; +static const arrayDigit ga_256_secp_b[] = + {16, 0x604b, 0x27d2, 0x3c3e, 0x3bce, 0xb0f6, 0xcc53, 0x6b0, 0x651d, 0x86bc, + 0x7698, 0xbd55, 0xb3eb, 0x93e7, 0xaa3a, 0x35d8, 0x5ac6}; + +/* + * secp384r1 + * + * p = FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF\ + * 0000000000000000FFFFFFFF + * = 394020061963944792122790401001436138050797392704654466679482934042457217\ + * 71496870329047266088258938001861606973112319 + * a = FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF\ + * 0000000000000000FFFFFFFC + * = 394020061963944792122790401001436138050797392704654466679482934042457217\ + * 71496870329047266088258938001861606973112316 + * b = B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D\ + * 8A2ED19D2A85C8EDD3EC2AEF + * = 275801935599597058778490118403890480930569058563615685214287073019886892\ + * 41309860865136260764883745107765439761230575 + * x = AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25D\ + * BF55296C3A545E3872760AB7 + * = 262470350957996892686231567445669818918529234911092133878156159009255188\ + * 54738050089022388053975719786650872476732087 + * y = 3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE\ + * 1D7E819D7A431D7C90EA0E5F + * = 832571096148902998554675128952010817928785304886131559470920590248050319\ + * 9884419224438643760392947333078086511627871 + * order = FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB2\ + * 48B0A77AECEC196ACCC52973 + * = 394020061963944792122790401001436138050797392704654466679469052796276593\ + * 99113263569398956308152294913554433653942643 + */ +static const arrayDigit ga_384_secp_bp[] = + {24, 0xffff, 0xffff, 0x0, 0x0, 0x0, 0x0, 0xffff, 0xffff, 0xfffe, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff}; +static const arrayDigit ga_384_secp_x1Plus[] = + {24, 0xab7, 0x7276, 0x5e38, 0x3a54, 0x296c, 0xbf55, 0xf25d, 0x5502, 0x2a38, + 0x8254, 0x41e0, 0x59f7, 0x9b98, 0x8ba7, 0x3b62, 0x6e1d, 0xad74, 0xf320, + 0xc71e, 0x8eb1, 0x537, 0xbe8b, 0xca22, 0xaa87}; +static const arrayDigit ga_384_secp_y1Plus[] = + {24, 0xe5f, 0x90ea, 0x1d7c, 0x7a43, 0x819d, 0x1d7e, 0xb1ce, 0xa60, 0xb8c0, + 0xb5f0, 0x3113, 0xe9da, 0x147c, 0x289a, 0x1dbd, 0xf8f4, 0xdc29, 0x9292, + 0x98bf, 0x5d9e, 0x2c6f, 0x9626, 0xde4a, 0x3617}; +static const arrayDigit ga_384_secp_plusOrder[] = + {24, 0x2973, 0xccc5, 0x196a, 0xecec, 0xa77a, 0x48b0, 0xdb2, 0x581a, 0x2ddf, + 0xf437, 0x4d81, 0xc763, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff}; +static const arrayDigit ga_384_secp_x1OrderPlus[] = + {24, 0x2973, 0xccc5, 0x196a, 0xecec, 0xa77a, 0x48b0, 0xdb2, 0x581a, 0x2ddf, + 0xf437, 0x4d81, 0xc763, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff}; +static const arrayDigit ga_384_secp_x1OrderPlusRecip[] = + {25, 0xd68d, 0x333a, 0xe695, 0x1313, 0x5885, 0xb74f, 0xf24d, 0xa7e5, 0xd220, 0xbc8, + 0xb27e, 0x389c, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1}; +static const arrayDigit ga_384_secp_a[] = + {24, 0xfffc, 0xffff, 0x0, 0x0, 0x0, 0x0, 0xffff, 0xffff, 0xfffe, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff}; +static const arrayDigit ga_384_secp_b[] = + {24, 0x2aef, 0xd3ec, 0xc8ed, 0x2a85, 0xd19d, 0x8a2e, 0x398d, 0xc656, 0x875a, + 0x5013, 0x88f, 0x314, 0x4112, 0xfe81, 0x9c6e, 0x181d, 0x2d19, 0xe3f8, 0x56b, + 0x988e, 0xe7e4, 0xe23e, 0x2fa7, 0xb331}; + +/* + * secp521r1 + * p = 01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\ + * FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + * = 686479766013060971498190079908139321726943530014330540939446345918554318\ + * 339765605212255964066145455497729631139148085803712198799971664381257402\ + * 8291115057151 + * a = 01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\ + * FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC + * = 686479766013060971498190079908139321726943530014330540939446345918554318\ + * 339765605212255964066145455497729631139148085803712198799971664381257402\ + * 8291115057148 + * b = 0051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E15619\ + * 3951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00 + * = 109384903807373427451111239076680556993620759895168374899458639449595311\ + * 615073501601370873757375962324859213229670631330943845253159101291214232\ + * 7488478985984 + * x = 00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B\ + * 5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66 + * = 266174080205021706322876871672336096072985916875697314770667136841880294\ + * 499642780849154508062777190235209424122506555866215711354557091681416163\ + * 7315895999846 + * y = 011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE\ + * 72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650 + * = 375718002577002046354550722449118360359445513476976248669456777961554447\ + * 744055631669123440501294553956214444453728942852258566672919658081012434\ + * 4277578376784 + * order = 01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA5186\ + * 8783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409 + * = 686479766013060971498190079908139321726943530014330540939446345918554318\ + * 339765539424505774633321719753296399637136332111386476861244038034037280\ + * 8892707005449 + * orderRecip = 200 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000005 \ + * ae79787c 40d06994 8033feb7 08f65a2f c44a3647 7663b851 449048e1 6ec79bf7 + * orderRecip = 2000000000000000000000000000000000000000000000000000000000000000005ae79787c40d069948033feb708f65a2fc44a36477663b851449048e16ec79bf7 + */ +static const arrayDigit ga_521_secp_bp[] = + {33, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0x1ff}; +static const arrayDigit ga_521_secp_x1Plus[] = + {33, 0xbd66, 0xc2e5, 0x7e31, 0xf97e, 0x429b, 0x856a, 0xb3c1, 0x3348, 0xa8de, 0xa2ff, + 0xc127, 0xfe1d, 0x5928, 0xefe7, 0x5e77, 0xa14b, 0x3dba, 0x6b4d, 0xaf60, 0xf828, 0xb521, + 0x53f, 0x8139, 0x9c64, 0xb442, 0x2395, 0xcb66, 0x9e3e, 0xe9cd, 0x404, 0x6b7, 0x858e, 0xc6}; +static const arrayDigit ga_521_secp_y1Plus[] = + {33, 0x6650, 0x9fd1, 0x9476, 0x88be, 0xc240, 0xa272, 0x7086, 0x353c, 0x761, 0x3fad, + 0xb901, 0xc550, 0x2640, 0x5ef4, 0x7299, 0x97ee, 0x662c, 0x273e, 0xbd17, 0x17af, 0x4468, + 0x579b, 0x4449, 0x98f5, 0x1bd9, 0x2c7d, 0x5fb4, 0x5c8a, 0xc004, 0x9a3b, 0x6a78, 0x3929, + 0x118}; +static const arrayDigit ga_521_secp_plusOrder[] = + {33, 0x6409, 0x9138, 0xb71e, 0xbb6f, 0x47ae, 0x899c, 0xc9b8, 0x3bb5, 0xa5d0, 0xf709, + 0x148, 0x7fcc, 0x966b, 0xbf2f, 0x8783, 0x5186, 0xfffa, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0x1ff}; +static const arrayDigit ga_521_secp_x1OrderPlus[] = + {33, 0x6409, 0x9138, 0xb71e, 0xbb6f, 0x47ae, 0x899c, 0xc9b8, 0x3bb5, 0xa5d0, 0xf709, + 0x148, 0x7fcc, 0x966b, 0xbf2f, 0x8783, 0x5186, 0xfffa, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0x1ff}; +static const arrayDigit ga_521_secp_x1OrderPlusRecip[] = +{33, 0x9bf7, 0x6ec7, 0x48e1, 0x4490, 0xb851, 0x7663, 0x3647, 0xc44a, 0x5a2f, 0x8f6, 0xfeb7, 0x8033, 0x6994, 0x40d0, 0x787c, 0xae79, 0x5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x200}; +static const arrayDigit ga_521_secp_a[] = + {33, 0xfffc, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0x1ff}; +static const arrayDigit ga_521_secp_b[] = + {33, 0x3f00, 0x6b50, 0x1fd4, 0xef45, 0x34f1, 0x3d2c, 0xdf88, 0x3573, 0xbf07, + 0x3bb1, 0xc0bd, 0x1652, 0x937b, 0xec7e, 0x3951, 0x5619, 0x9e1, 0x8ef1, 0x8991, + 0xb8b4, 0x15f3, 0x99b3, 0x725b, 0xa2da, 0x40ee, 0xb685, 0x21a0, 0x929a, 0x9a1f, + 0x8e1c, 0xb961, 0x953e, 0x51}; diff --git a/libsecurity_cryptkit/lib/curveParamDataOld.h b/libsecurity_cryptkit/lib/curveParamDataOld.h new file mode 100644 index 00000000..2b0c6fbf --- /dev/null +++ b/libsecurity_cryptkit/lib/curveParamDataOld.h @@ -0,0 +1,350 @@ +/* + * curveParamDataOld.h - prototype FEE curve parameters (obsolete as of 4/9/2001) + */ +#warning Using obsolete curveParam data! +/* + * q = 31 k = 1, Weierstrass + * a = 7 b = 1 c = 0 + */ +static arrayDigit ga_w31_1_a[] = {1, 7}; +static arrayDigit ga_w31_1_x1Plus[] = + {2,15438,14404}; + /* 943995982 */ +static arrayDigit ga_w31_1_x1Minus[] = + {2, 10400, 19905}; + /* 1304504480 */ +static arrayDigit ga_w31_1_plusOrder[] = + {2, 3848, 32769}; + /* 2147553032 */ +static arrayDigit ga_w31_1_minusOrder[] = + {2, 61688, 32766 }; + /* 2147414264 */ +static arrayDigit ga_w31_1_x1OrderPlus[] = + {2, 8673, 4096}; + /* 268444129 */ +static arrayDigit ga_w31_1_x1OrderMinus[] = + {2, 56863, 4095 }; + /* 268426783 */ +static arrayDigit ga_w31_1_x1OrderPlusRecip[] = + {2, 30845, 16383}; +static arrayDigit ga_w31_1_lesserX1OrderRecip[] = + {2, 8673, 4096}; + +/* + * q = 31 k = 1, Montgomery + * a = 1 b = 0 c = 666 + */ +static arrayDigit ga_m31_1_x1Plus[] = + {2, 61780, 6237}; + /* 408809812 */ +static arrayDigit ga_m31_1_x1Minus[] = + {2,12973,30585}; + /* 2004431533 */ +static arrayDigit ga_m31_1_plusOrder[] = + {2, 25928, 32768 }; + /* 2147509576 */ +static arrayDigit ga_m31_1_minusOrder[] = + {2, 39608, 32767 }; + /* 2147457720 */ +static arrayDigit ga_m31_1_x1OrderPlus[] = + {2, 3241, 4096}; + /* 268438697 */ +static arrayDigit ga_m31_1_x1OrderMinus[] = + {2, 4153, 273}; + /* 17895481 */ +static arrayDigit ga_m31_1_x1OrderPlusRecip[] = + {2, 52572, 16383}; +static arrayDigit ga_m31_1_lesserX1OrderRecip[] = + {2, 759, 960}; + +/* + * q = 31 k = 1, Montgomery, prime curve orders + * a = 5824692 b = 2067311435 c = 0 + */ +static arrayDigit ga_31_1P_x1Plus[] = + {1, 6 }; +static arrayDigit ga_31_1P_x1Minus[] = + {1, 7 }; +static arrayDigit ga_31_1P_plusOrder[] = + {2,59003,32766 }; + /* 2147411579 */ +static arrayDigit ga_31_1P_minusOrder[] = + {2,6533,32769 }; + /* 2147555717 */ +static arrayDigit ga_31_1P_x1OrderPlus[] = + {2,59003,32766}; + /* 2147411579 */ +static arrayDigit ga_31_1P_x1OrderMinus[] = + {2,6533,32769}; + /* 2147555717 */ +static arrayDigit ga_31_1P_x1OrderPlusRecip[] = + {2, 6535, 32769}; + +static arrayDigit ga_31_1P_a[] = + {2,57524,88}; + /* 5824692 */ +static arrayDigit ga_31_1P_b[] = + {2,43851,31544}; + /* 2067311435 */ + +/* + * q = 40 k = 213, Weierstrass + * a = 1627500953 b = 523907505 c = 0 + */ +static arrayDigit ga_40_213_x1Plus[] = + {1, 1 }; +static arrayDigit ga_40_213_x1Minus[] = + {1, 2 }; +static arrayDigit ga_40_213_plusOrder[] = + {3,11655,25,256}; + /* 1099513277831 */ +static arrayDigit ga_40_213_minusOrder[] = + {3,53457,65510,255}; + /* 1099509977297 */ +static arrayDigit ga_40_213_x1OrderPlus[] = + {3,11655,25,256}; + /* 1099513277831 */ +static arrayDigit ga_40_213_x1OrderMinus[] = + {3,53457,65510,255}; + /* 1099509977297 */ +static arrayDigit ga_40_213_x1OrderPlusRecip[] = + {3, 18925, 65435, 1023}; +static arrayDigit ga_40_213_lesserX1OrderRecip[] = + {3, 12081, 25, 256}; + +static arrayDigit ga_40_213_a[] = + {2,45465,24833}; + /* 1627500953 */ +static arrayDigit ga_40_213_b[] = + {2,12721,7994}; + /* 523907505 */ + +/* + * q = 127 k = 1 + * a = 1 b = 0 c = 666 + */ +static arrayDigit ga_127_1_x1Plus[] = + {8, 24044, 39922, 11050, + 24692, 34049, 9793, 1228, 31562}; + /* 163879370753099435779911346846180728300 */ +static arrayDigit ga_127_1_x1Minus[] = + {8,49015,6682,26772,63672,45560,46133,24769,8366}; + /* 43440717976631899041527862406676135799 */ +static arrayDigit ga_127_1_plusOrder[] = + { 8, 14612, 61088, 34331, + 32354, 65535, 65535, 65535, + 32767}; + /* 170141183460469231722347548493196835092 */ +static arrayDigit ga_127_1_minusOrder[] = + { 8, 50924, 4447, 31204, + 33181, 0, 0, 0, + 32768 }; + /* 170141183460469231741027058938571376364 */ +static arrayDigit ga_127_1_x1OrderPlus[] = + {6, 8201, 61942, 37082, + 53787, 49605, 7887 }; + /* 9535713005180210505588285449 */ +static arrayDigit ga_127_1_x1OrderMinus[] = + {6, 14659, 1977,16924, + 7446, 49030, 1}; + /* 2113371777483973234080067 */ +static arrayDigit ga_127_1_x1OrderPlusRecip[] = + {6, 21911, 8615, 0, 40960, 64107, 8507}; +static arrayDigit ga_127_1_lesserX1OrderRecip[] = + {6, 44759, 65533, 17695, 61560, 18883, 2}; + +/* + * This is only used for the FEE_DEPTH_127_GEN (FPT_General) case. + */ +static arrayDigit ga_127_1_bp[] = + {8, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 32767}; + +/* + * q = 127 k = 1, Weierstrass + * a = 666 b = 1 c = 0 + */ +static arrayDigit ga_127_1W_x1Plus[] = + {8, 8152, 12974, 29415, + 29630, 64916, 34821, 65368, + 29317}; + /* 152227746030289977478827896983637598168 */ +static arrayDigit ga_127_1W_x1Minus[] = + {8, 33297, 13207, 15262, + 22815, 21569, 49926, 18455, + 22807}; + /* 118422176668700242826570137796135584273 */ +static arrayDigit ga_127_1W_plusOrder[] = + {8, 7568, 62409, 28235, + 47403, 65534, 65535, 65535, + 32767 }; + /* 170141183460469231708136695161971875216 + = 2 * 2 * 2 * 2 * 11 * 17 * 47 * 103 * 10861 * + 1081540940469355570836125423 */ +static arrayDigit ga_127_1W_minusOrder[] = + {8, 57968, 3126,37300, 18132, 1, 0, 0, 32768 }; + /* 170141183460469231755237912269796336240 + = 2 * 2 * 2 * 2 * 3 * 5 * 19 * 34267 * + 1088851169917897274673487152937 */ +static arrayDigit ga_127_1W_x1OrderPlus[] = + { 6, 46831, 48825, 15584, 56652, 41267, 894 }; + /* 1081540940469355570836125423 */ +static arrayDigit ga_127_1W_x1OrderMinus[] = + {7, 1833, 34556, 10366, 60186, 37860, 48708, 13}; + /* 1088851169917897274673487152937 */ +static arrayDigit ga_127_1W_x1OrderPlusRecip[] = + {6, 48506, 2992, 0, 28160, 5127, 1172}; + +/* + * q = 160 k = 57 + * a = c = 0 b = 3 + */ +static arrayDigit ga_160_57_x1Plus[] = + {10,12520,51433,52060,51310,41288,18467,39861,56172,11574,31757}; + /* 708208703989516599321256243677211664634713026792 */ +static arrayDigit ga_160_57_x1Minus[] = + {10,40240,19544,56125,45242,10556,34052,10700,5155,57632,13213}; + /* 294679357488322649182890242541447794429265485104 */ +static arrayDigit ga_160_57_plusOrder[] = + {11,62853,63609,4196,64365,22452,1,0,0,0,0,1}; + /* 1461501637330902918203686455826517732113793021317 */ +static arrayDigit ga_160_57_minusOrder[] = + {10,2571,1926,61339,1170,43083,65534,65535,65535,65535,65535}; + /* 1461501637330902918203683209606048307198072064523 */ +static arrayDigit ga_160_57_x1OrderPlus[] = + {5,171,21451,35098,934,63868}; + /* 1178156913548056058331307 */ +static arrayDigit ga_160_57_x1OrderMinus[] = + {7,255,39523,10835,12387,25442,37088,9774}; + /* 774420897524543052406523561181439 */ +static arrayDigit ga_160_57_x1OrderPlusRecip[] = + {6, 49805, 35001, 38758, 35853, 1711, 1}; +static arrayDigit ga_160_57_b[] = {1, 3}; /* b = (giant)3 */ + +/* + * This is only used for the FEE_DEPTH_160_GEN (FPT_General) case. + */ +static arrayDigit ga_160_57_bp[] = + {10,65479,65535,65535,65535,65535,65535,65535,65535,65535,65535}; + /* 1461501637330902918203684832716283019655932542919 */ + + +/* + * q = 192 k = 1425 + * a = 0 b = -11 c = 0 + */ +static arrayDigit ga_192_1425_x1Plus[] = + {12, 44344, 60264, 44908, + 24163, 37728, 58781, 45290, + 62313, 45939, 59670, 20046, + 8781}; + /* 841082007613983662909216085212018592355989658924032240952 */ +static arrayDigit ga_192_1425_x1Minus[] = + {12,32855,61817,23700,48262,13770,23791,31597,23825,7973,37638, + 62245,25400}; + /* 2432927643133372385673335524462623851522707126886260637783 */ +static arrayDigit ga_192_1425_plusOrder[] = + {13, 7615, 52517, 60178, + 40906, 43135, 27853, 1, + 0, 0, 0, 0, 0, 1}; + /* 6277101735386680763835789423320567585182165941785488334271 */ +static arrayDigit ga_192_1425_minusOrder[] = + {12, 55073, 13018, 5357, + 24629, 22400, 37682, 65534, + 65535, 65535, 65535, 65535, + 65535}; + /* 6277101735386680763835789423094765247022544947142580688673 */ +static arrayDigit ga_192_1425_x1OrderPlus[] = + {11, 55217, 35908, 19375, + 13869, 14836, 18343, 39323, + 50251, 7215, 49984, 21171}; + /* 30942565846835947234516838572438382480699614724151217 */ +static arrayDigit ga_192_1425_x1OrderMinus[] = + {12, 42525, 5637, 42463, + 55864, 53758, 3234, 41914, + 27439, 9168, 44294, 64393, 2}; + /* 285673405333212613836790125294441598644816135581967901 */ +static arrayDigit ga_192_1425_x1OrderPlusRecip[] = + {11, 31243, 31728, 18067, + 25698, 58801, 65534, 65535, + 65535, 65535, 49151, 50715}; +static arrayDigit ga_192_1425_b[] = {-1, 11}; /* b = (giant)(-11) */ + +/* + * q = 192 k = -529891 + * a = -152 b = 722 c = 0 + */ +static arrayDigit ga_192_M529891_x1Plus[] = + {12, 27752, 118, 22193, + 28093, 63505, 16219, 38086, + 5777, 13552, 56652, 28149, + 56180}; + /* 5381016108938327910020782805833379575685074837329310805096 */ +static arrayDigit ga_192_M529891_x1Minus[] = + {12, 20031, 4376, 4872, + 24519, 24047, 14628, 60533, + 27380, 49464, 20541, 38806, + 59062}; + /* 5657072442654455186533371860713762559076927475376430009919 */ +static arrayDigit ga_192_M529891_plusOrder[] = + {13, 5604, 8, 0, + 0, 0, 0, 2, + 0, 0, 0, 0, + 0, 1}; + /* 6277101735386680763835789423366122741130884119651122943460 */ +static arrayDigit ga_192_M529891_minusOrder[] = + {12, 5604, 8, 0, + 0, 0, 0, 65534, + 65535, 65535, 65535, 65535, + 65535}; + /* 6277101735386680763835789423049210091073826769276947142116 */ +static arrayDigit ga_192_M529891_x1OrderPlus[] = + {12, 28623, 26214, 26214, + 26214, 26214, 58982, 16681, + 4766, 10724, 40513, 58386, + 297}; + /* 28532280615394003471980861015300557914231291452959649743 */ +static arrayDigit ga_192_M529891_x1OrderMinus[] = + {11, 18083, 10335, 12214, + 61896, 30741, 14099, 7255, + 33291, 27015, 23037, 196}; + /* 286968072376896521631921223217092198374509106906787 */ +static arrayDigit ga_192_M529891_x1OrderPlusRecip[] = + {12, 58420, 65535, 65535, + 65535, 65535, 63775, 65535, + 65535, 65535, 65535, 65535, 879}; +static arrayDigit ga_192_M529891_lesserX1OrderRecip[] = + {11, 65535, 65535, 65535, 35223, + 667, 0, 0, 0, 0, 50380, 333}; +static arrayDigit ga_192_M529891_a[] = {-1, 152}; /* a = -152 */ +static arrayDigit ga_192_M529891_b[] = { 1, 722}; /* b = 722 */ + +/* + * FPT_General, 161 bits + */ +static arrayDigit ga_161_gen_bp[] = + {11,41419,58349,36408,14563,25486,9098,29127,50972,7281,8647,1}; + /* baseprime = 1654338658923174831024422729553880293604080853451 */ +static arrayDigit ga_161_gen_x1Plus[] = + {10,59390,38748,49144,50217,32781,46057,53816,62856,18968,55868}; + /* 1245904487553815885170631576005220733978383542270 */ +static arrayDigit ga_161_gen_x1Minus[] = + {10,62588,37264,57758,58571,20023,11302,61317,50155,46534,18610}; + /* 415032703104741702601157337572231150005648422012 */ +static arrayDigit ga_161_gen_plusOrder[] = + {11,41420,58349,36408,14563,25486,9100,29127,50972,7281,8647,1}; + /* 1654338658923174831024425147405519522862430265804 */ +static arrayDigit ga_161_gen_minusOrder[] = + {11,41420,58349,36408,14563,25486,9096,29127,50972,7281,8647,1}; + /* 1654338658923174831024420311702241064345731441100 */ +static arrayDigit ga_161_gen_x1OrderPlus[] = + {8,59671,64703,58305,55887,34170,37971,15627,197}; + /* 1024120625531724089187207582052247831 */ +static arrayDigit ga_161_gen_x1OrderMinus[] = + {10,49675,56911,64364,6281,5543,59511,52057,44604,37151,2}; + /* 57243552211874561627142571339177891499852299 */ +static arrayDigit ga_161_gen_x1OrderPlusRecip[] = + {8, 7566, 37898, 14581, 2404, 52670, 23839, 17554, 332}; + +static arrayDigit ga_161_gen_a[] = {-1, 152}; /* a = -152 */ +static arrayDigit ga_161_gen_b[] = { 1, 722}; /* b = 722 */ + diff --git a/libsecurity_cryptkit/lib/curveParams.c b/libsecurity_cryptkit/lib/curveParams.c new file mode 100644 index 00000000..cce030b5 --- /dev/null +++ b/libsecurity_cryptkit/lib/curveParams.c @@ -0,0 +1,1399 @@ +/* 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. + *************************************************************************** + * + * curveParams.c - FEE curve parameter static data and functions + * + * Revision History + * ---------------- + * 10/06/98 ap + * Changed to compile with C++. + * 9 Sep 98 Doug Mitchell at NeXT + * Added y1Plus for IEEE P1363 compliance. + * Added curveParamsInferFields(). + * 08 Apr 98 Doug Mitchell at Apple + * Mods for giantDigit. + * 20 Jan 98 Doug Mitchell at Apple + * Added primeType, m, basePrimeRecip; added a few PT_GENERAL curves. + * 19 Jan 1998 Doug Mitchell at Apple + * New curve: q=160, k=57 + * 09 Jan 1998 Doug Mitchell at Apple + * Removed obsolete (i.e., incomplete) curves parameters. + * 11 Jun 1997 Doug Mitchell at Apple + * Added x1OrderPlusRecip and lesserX1OrderRecip fields + * Added curveParamsInitGiants() + * 9 Jan 1997 Doug Mitchell at NeXT + * Major mods for IEEE-style parameters. + * 7 Aug 1996 Doug Mitchell at NeXT + * Created. + */ + +#include "curveParams.h" +#include "giantIntegers.h" +#include "elliptic.h" +#include "ellipticProj.h" +#include "platform.h" +#include "falloc.h" +#include "feeDebug.h" +#include + +typedef unsigned short arrayDigit; + +static giant arrayToGiant(const arrayDigit *array); + +/* + * Can't declare giants statically; we declare them here via static arrayDigit + * arrays which contain the 'digits' in base 65536 of a giant + * used as a curve parameter. First element is sign; next element is + * l.s. digit; size of each array is abs(sign) + 1. These arrays are + * converted to a giant via arrayToGiant(). + * + * Static q and k values, as well as pointers to the arrayDigit arrays + * associated with the various giants for a given curve, are kept in an + * array of curveParamsStatic structs; a feeDepth is an index into this + * array. A curveParamsStatic struct is converted to a curveParams struct in + * curveParamsForDepth(). + */ +typedef struct { + feePrimeType primeType; + feeCurveType curveType; + unsigned q; + int k; + const arrayDigit *basePrime; // FPT_General only + arrayDigit m; // must be 1 for current release + const arrayDigit *a; + const arrayDigit *b; + const arrayDigit *c; + const arrayDigit *x1Plus; + const arrayDigit *y1Plus; // optional, currently only used for ECDSA curves + const arrayDigit *x1Minus; // optional, not used for ECDSA curves + const arrayDigit *cOrderPlus; + const arrayDigit *cOrderMinus; // optional, not used for ECDSA curves + const arrayDigit *x1OrderPlus; + const arrayDigit *x1OrderMinus; // optional, not used for ECDSA curves + const arrayDigit *x1OrderPlusRecip; + + /* + * A null lesserX1OrderRecip when x1OrderPlusRecip is non-null + * means that the two values are identical; in this case, only + * one giant is alloc'd in the actual curveParams struct. + */ + const arrayDigit *lesserX1OrderRecip; +} curveParamsStatic; + +/* + * First some common giant-arrays used in lots of curveGiants. + */ +static const arrayDigit ga_666[] = {1, 666 }; // a common value for 'c' +static const arrayDigit ga_zero[] = {1, 0 }; // (giant)0 +static const arrayDigit ga_one[] = {1, 1 }; // (giant)1 + +/* + * Here are the actual static arrays, one for each giant we know about. + * Since they're variable size, we have to allocate and name each one + * individually.... + */ + +#if FEE_PROTOTYPE_CURVES +#include "curveParamDataOld.h" +#else +#include "curveParamData.h" +#endif + +/* + * Now the curveParamsStatic structs, which provide templates for creating the + * fields in a specific curveParams struct. + * + * All giants in a curveParamsStatic struct except for basePrime are + * guaranteed valid. + * + * Note these are stored as an array, an index into which is a feeDepth + * parameter. + */ +#if FEE_PROTOTYPE_CURVES +static curveParamsStatic curveParamsArray[] = { + { // depth=0 + FPT_Mersenne, + FCT_Weierstrass, + 31, 1, // q=31, k=1 + NULL, // basePrime only used for FPT_General + 1, // m = 1 + ga_w31_1_a, // a = 7 + ga_one, // b = 1 + ga_zero, // c = 0 + ga_w31_1_x1Plus, + NULL, // y1Plus + ga_w31_1_x1Minus, + ga_w31_1_plusOrder, + ga_w31_1_minusOrder, + ga_w31_1_x1OrderPlus, + ga_w31_1_x1OrderMinus, + ga_w31_1_x1OrderPlusRecip, + ga_w31_1_lesserX1OrderRecip + }, + { // depth=1 + FPT_Mersenne, + FCT_Montgomery, + 31, 1, // q=31, k=1 + NULL, + 1, // m = 1 + ga_one, // a = 1 + ga_zero, // b = 0 + ga_666, // c = 666 + ga_m31_1_x1Plus, + NULL, // y1Plus + ga_m31_1_x1Minus, + ga_m31_1_plusOrder, + ga_m31_1_minusOrder, + ga_m31_1_x1OrderPlus, + ga_m31_1_x1OrderMinus, + ga_m31_1_x1OrderPlusRecip, + ga_m31_1_lesserX1OrderRecip + + }, + { // depth=2 + FPT_Mersenne, + FCT_Weierstrass, + 31, 1, // q=31, k=1, prime curve orders + NULL, + 1, // m = 1 + ga_31_1P_a, // a = 5824692 + ga_31_1P_b, // b = 2067311435 + ga_zero, // c = 0 + ga_31_1P_x1Plus, + NULL, // y1Plus + ga_31_1P_x1Minus, + ga_31_1P_plusOrder, + ga_31_1P_minusOrder, + ga_31_1P_x1OrderPlus, + ga_31_1P_x1OrderMinus, + ga_31_1P_x1OrderPlusRecip, + NULL // x1PlusOrder is lesser + + }, + { // depth=3 + FPT_FEE, + FCT_Weierstrass, + 40, 213, // q=40, k=213, prime curve orders + NULL, + 1, // m = 1 + ga_40_213_a, // a = 1627500953 + ga_40_213_b, // b = 523907505 + ga_zero, // c = 0 + ga_40_213_x1Plus, + NULL, // y1Plus + ga_40_213_x1Minus, + ga_40_213_plusOrder, + ga_40_213_minusOrder, + ga_40_213_x1OrderPlus, + ga_40_213_x1OrderMinus, + ga_40_213_x1OrderPlusRecip, + ga_40_213_lesserX1OrderRecip + + }, + { // depth=4 + FPT_Mersenne, + FCT_Montgomery, + 127, 1, + NULL, + 1, // m = 1 + ga_one, // a = 1 + ga_zero, // b = 0 + ga_666, // c = 666 + ga_127_1_x1Plus, + NULL, // y1Plus + ga_127_1_x1Minus, + ga_127_1_plusOrder, + ga_127_1_minusOrder, + ga_127_1_x1OrderPlus, + ga_127_1_x1OrderMinus, + ga_127_1_x1OrderPlusRecip, + ga_127_1_lesserX1OrderRecip + + }, + { // depth=5 + FPT_Mersenne, + FCT_Weierstrass, + 127, 1, // q=127, k=1 Weierstrass + NULL, + 1, // m = 1 + ga_666, // a = 666 + ga_one, // b = 1 + ga_zero, // c = 0 + ga_127_1W_x1Plus, + NULL, // y1Plus + ga_127_1W_x1Minus, + ga_127_1W_plusOrder, + ga_127_1W_minusOrder, + ga_127_1W_x1OrderPlus, + ga_127_1W_x1OrderMinus, + ga_127_1W_x1OrderPlusRecip, + NULL // x1PlusOrder is lesser + + }, + { // depth=6 + FPT_FEE, + FCT_Weierstrass, // also Atkin3 + 160, 57, + NULL, + 1, // m = 1 + ga_zero, // a = 0 + ga_160_57_b, // b = 3 + ga_zero, // c = 0 + ga_160_57_x1Plus, + NULL, // y1Plus + ga_160_57_x1Minus, + ga_160_57_plusOrder, + ga_160_57_minusOrder, + ga_160_57_x1OrderPlus, + ga_160_57_x1OrderMinus, + ga_160_57_x1OrderPlusRecip, + NULL // x1PlusOrder is lesser + }, + { // depth=7 + FPT_FEE, + FCT_Weierstrass, // also Atkin3 + 192, 1425, + NULL, + 1, // m = 1 + ga_zero, // a = 0 + ga_192_1425_b, // b = -11 + ga_zero, // c = 0 + ga_192_1425_x1Plus, + NULL, // y1Plus + ga_192_1425_x1Minus, + ga_192_1425_plusOrder, + ga_192_1425_minusOrder, + ga_192_1425_x1OrderPlus, + ga_192_1425_x1OrderMinus, + ga_192_1425_x1OrderPlusRecip, + NULL // x1PlusOrder is lesser + + }, + { // depth=8 + FPT_FEE, + FCT_Weierstrass, + 192, -529891, + NULL, + 1, // m = 1 + ga_192_M529891_a, // a = -152 + ga_192_M529891_b, // b = 722 + ga_zero, // c = 0 + ga_192_M529891_x1Plus, + NULL, // y1Plus + ga_192_M529891_x1Minus, + ga_192_M529891_plusOrder, + ga_192_M529891_minusOrder, + ga_192_M529891_x1OrderPlus, + ga_192_M529891_x1OrderMinus, + ga_192_M529891_x1OrderPlusRecip, + ga_192_M529891_lesserX1OrderRecip + + }, + /* + * FPT_General curves, currently just copies of known FPT_FEE or FPT_Mersenne + * curves with primeType set to FPT_General. These are just for + * verification the general curve are handled properly. + * We include the q parameter here for use by feeKeyBitsToDepth(). + */ + { // depth=9 + FPT_General, + FCT_General, + 127, 0, + ga_127_1_bp, // explicit basePrime + 1, // m = 1 + ga_one, // a = 1 + ga_zero, // b = 0 + ga_666, // c = 666 + ga_127_1_x1Plus, + NULL, // y1Plus + ga_127_1_x1Minus, + ga_127_1_plusOrder, + ga_127_1_minusOrder, + ga_127_1_x1OrderPlus, + ga_127_1_x1OrderMinus, + ga_127_1_x1OrderPlusRecip, + ga_127_1_lesserX1OrderRecip + + }, + + { // depth=10, FPT_General version of q=160 + FPT_General, + FCT_Weierstrass, + 160, 0, // we don't use these... + ga_160_57_bp, // explicit basePrime + 1, // m = 1 + ga_zero, // a = 0 + ga_160_57_b, // b = 3 + ga_zero, + ga_160_57_x1Plus, + NULL, // y1Plus + ga_160_57_x1Minus, + ga_160_57_plusOrder, + ga_160_57_minusOrder, + ga_160_57_x1OrderPlus, + ga_160_57_x1OrderMinus, + ga_160_57_x1OrderPlusRecip, + NULL // x1PlusOrder is lesser + }, + + { // depth=11, FPT_General, 161 bits + FPT_General, + FCT_Weierstrass, + //161, 0, + 161, 0, // for verifying we don't use these... + ga_161_gen_bp, // explicit basePrime + 1, // m = 1 + ga_161_gen_a, // a = -152 + ga_161_gen_b, // b = 722 + ga_zero, // c = 0 + ga_161_gen_x1Plus, + NULL, // y1Plus + ga_161_gen_x1Minus, + ga_161_gen_plusOrder, + ga_161_gen_minusOrder, + ga_161_gen_x1OrderPlus, + ga_161_gen_x1OrderMinus, + ga_161_gen_x1OrderPlusRecip, + NULL // x1PlusOrder is lesser + }, + +}; + +#else /* FEE_PROTOTYPE_CURVES */ + +static const curveParamsStatic curveParamsArray[] = { +{ + /* + * depth = 0 + * FEE CURVE: USE FOR FEE SIG. & FEED ONLY. + * primeType->Mersenne + * curveType->Montgomery + * q = 31; k = 1; p = 2^q - k; + * a = 1; b = 0; c = 666; + * Both orders composite. + */ + FPT_Mersenne, + FCT_Montgomery, + 31, 1, // q=31, k=1 + NULL, // basePrime only used for FPT_General + 1, // m = 1 + ga_one, // a = 1 + ga_zero, // b = 0 + ga_666, // c = 666 + ga_31m_x1Plus, + NULL, // y1Plus + ga_31m_x1Minus, + ga_31m_plusOrder, + ga_31m_minusOrder, + ga_31m_x1OrderPlus, + ga_31m_x1OrderMinus, + ga_31m_x1OrderPlusRecip, + ga_31m_lesserX1OrderRecip +}, +{ + /* + * depth = 1 + * IEEE P1363 COMPATIBLE. + * primeType->Mersenne + * curveType->Weierstrass + * q = 31; k = 1; p = 2^q-k; + * a = 5824692 b = 2067311435 c = 0 + * Both orders prime. + */ + FPT_Mersenne, + FCT_Weierstrass, + 31, 1, // q=31, k=1 + NULL, // basePrime only used for FPT_General + 1, // m = 1 + ga_31w_a, + ga_31w_b, + ga_zero, // c = 0 + ga_31w_x1Plus, + NULL, // y1Plus + ga_31w_x1Minus, + ga_31w_plusOrder, + ga_31w_minusOrder, + ga_31w_x1OrderPlus, + ga_31w_x1OrderMinus, + ga_31w_x1OrderPlusRecip, + NULL // x1PlusOrder is lesser +}, +{ + /* + * depth = 2 + * FEE CURVE: USE FOR FEE SIG. & FEED ONLY. + * primeType->Mersenne + * curveType->Montgomery + * q = 127; k = 1; p = 2^q - k; + * a = 1; b = 0; c = 666; + * Both orders composite. + */ + FPT_Mersenne, + FCT_Montgomery, + 127, 1, // q = 127; k = 1 + NULL, // basePrime only used for FPT_General + 1, // m = 1 + ga_one, + ga_zero, + ga_666, + ga_127m_x1Plus, + NULL, // y1Plus + ga_127m_x1Minus, + ga_127m_plusOrder, + ga_127m_minusOrder, + ga_127m_x1OrderPlus, + ga_127m_x1OrderMinus, + ga_127m_x1OrderPlusRecip, + ga_127m_lesserX1OrderRecip +}, +{ + /* + * depth = 3 + * IEEE P1363 COMPATIBLE. + * primeType->feemod + * curveType->Weierstrass + * q = 127; k = -57675; p = 2^q - k; + * a = 170141183460469025572049133804586627403; + * b = 170105154311605172483148226534443139403; c = 0; + * Both orders prime. + */ + FPT_FEE, + FCT_Weierstrass, + 127, -57675, // q = 127; k = -57675 + NULL, // basePrime only used for FPT_General + 1, // m = 1 + ga_128w_a, + ga_128w_b, + ga_zero, + ga_128w_x1Plus, + NULL, // y1Plus + ga_128w_x1Minus, + ga_128w_plusOrder, + ga_128w_minusOrder, + ga_128w_x1OrderPlus, + ga_128w_x1OrderMinus, + ga_128w_x1OrderPlusRecip, + /* REC said NULL, dmitch says: */ + ga_128w_lesserX1OrderRecip // x1PlusOrder is lesser +}, +{ + /* + * depth = 4 + * IEEE P1363 COMPATIBLE. + * primeType->feemod + * curveType->Weierstrass + * q = 160; k = -5875; p = 2^q - k; + * a = 1461501637330902918203684832716283019448563798259; + * b = 36382017816364032; c = 0; + * Both orders prime.: + */ + FPT_FEE, + FCT_Weierstrass, + 160, -5875, // q = 160; k = -5875 + NULL, // basePrime only used for FPT_General + 1, // m = 1 + ga_161w_a, + ga_161w_b, + ga_zero, + ga_161w_x1Plus, + NULL, // y1Plus + ga_161w_x1Minus, + ga_161w_plusOrder, + ga_161w_minusOrder, + ga_161w_x1OrderPlus, + ga_161w_x1OrderMinus, + ga_161w_x1OrderPlusRecip, + /* dmitch addenda - REC said NULL */ + ga_161w_lesserX1OrderRecip +}, +{ + /* + * depth = 5 + * IEEE P1363 COMPATIBLE. + * primeType->General + * curveType->Weierstrass + * p is a 161-bit random prime (below, ga_161_gen_bp[]); + * a = -152; b = 722; c = 0; + * Both orders composite. + */ + FPT_General, + FCT_Weierstrass, + 161, 0, // not used + ga_161_gen_bp, // basePrime + 1, // m = 1 + ga_161_gen_a, + ga_161_gen_b, + ga_zero, + ga_161_gen_x1Plus, + NULL, // y1Plus + ga_161_gen_x1Minus, + ga_161_gen_plusOrder, + ga_161_gen_minusOrder, + ga_161_gen_x1OrderPlus, + ga_161_gen_x1OrderMinus, + ga_161_gen_x1OrderPlusRecip, + NULL // x1PlusOrder is lesser +}, +{ + /* + * depth = 6 + * IEEE P1363 COMPATIBLE. + * (NIST-P-192 RECOMMENDED PRIME) + * primeType->General + * curveType->Weierstrass + * p is a 192-bit random prime (below, ga_161_gen_bp[]); + * a = -3; + * b = 2455155546008943817740293915197451784769108058161191238065; + * c = 0; + * Plus-order is prime, minus-order is composite. + */ + FPT_General, + FCT_Weierstrass, + 192, 0, // only used for initGiantStacks(giantMaxDigits()) + ga_192_gen_bp, // basePrime + 1, // m = 1 + ga_192_gen_a, + ga_192_gen_b, + ga_zero, + ga_192_gen_x1Plus, + NULL, // y1Plus + ga_192_gen_x1Minus, + ga_192_gen_plusOrder, + ga_192_gen_minusOrder, + ga_192_gen_x1OrderPlus, + ga_192_gen_x1OrderMinus, + ga_192_gen_x1OrderPlusRecip, + ga_192_gen_lesserX1OrderRecip +}, + +/* ANSI X9.62/Certicom curves */ +{ + /* + * depth = 7 + * ANSI X9.62/Certicom secp192r1 + */ + FPT_General, + FCT_Weierstrass, + 192, 0, // only used for initGiantStacks(giantMaxDigits()) + ga_192_secp_bp, // basePrime + 1, // m = 1 + ga_192_secp_a, + ga_192_secp_b, + ga_zero, + ga_192_secp_x1Plus, + ga_192_secp_y1Plus, + NULL, // x1Minus + ga_192_secp_plusOrder, + NULL, // minusOrder, + ga_192_secp_x1OrderPlus, + NULL, // x1OrderMinus, + ga_192_secp_x1OrderPlusRecip, +}, +{ + /* + * depth = 8 + * ANSI X9.62/Certicom secp256r1 + */ + FPT_General, + FCT_Weierstrass, + 256, 0, // only used for initGiantStacks(giantMaxDigits()) + ga_256_secp_bp, // basePrime + 1, // m = 1 + ga_256_secp_a, + ga_256_secp_b, + ga_zero, + ga_256_secp_x1Plus, + ga_256_secp_y1Plus, + NULL, + ga_256_secp_plusOrder, + NULL, + ga_256_secp_x1OrderPlus, + NULL, + ga_256_secp_x1OrderPlusRecip, + NULL +}, +{ + /* + * depth = 9 + * ANSI X9.62/Certicom secp384r1 + */ + FPT_General, + FCT_Weierstrass, + 384, 0, // only used for initGiantStacks(giantMaxDigits()) + ga_384_secp_bp, // basePrime + 1, // m = 1 + ga_384_secp_a, + ga_384_secp_b, + ga_zero, + ga_384_secp_x1Plus, + ga_384_secp_y1Plus, + NULL, + ga_384_secp_plusOrder, + NULL, + ga_384_secp_x1OrderPlus, + NULL, + ga_384_secp_x1OrderPlusRecip, + NULL +}, +{ + /* + * depth = 10 + * ANSI X9.62/Certicom secp521r1 + */ + FPT_General, + FCT_Weierstrass, + 521, 0, + ga_521_secp_bp, // basePrime + 1, // m = 1 + ga_521_secp_a, + ga_521_secp_b, + ga_zero, + ga_521_secp_x1Plus, + ga_521_secp_y1Plus, + NULL, + ga_521_secp_plusOrder, + NULL, + ga_521_secp_x1OrderPlus, + NULL, + ga_521_secp_x1OrderPlusRecip, + NULL +} +}; +#endif /* FEE_PROTOTYPE_CURVES */ + +/* + * Convert the static form of a giant - i.e., an array of arrayDigits, + * the first of which is the sign, the remainder of which are base 65536 + * digits - into a giant. A null pointer on input results in a null return. + */ +static giant arrayToGiant(const arrayDigit *array) +{ + unsigned numBytes; // in result->n[] + int numDigits; // ditto + giant result; + giantDigit digit; + unsigned char byte; + unsigned i; + unsigned digitDex; // index into result->n[] + unsigned digitByte; // byte selector in digit + const arrayDigit *ap; // running ptr into array + short sign; + + if(array == NULL) { + CKRaise("arrayToGiant: NULL array"); + } + sign = (short)array[0]; + numBytes = abs(sign) * sizeof(unsigned short); + numDigits = BYTES_TO_GIANT_DIGITS(numBytes); + + /* note giantstruct has one explicit giantDigit */ + result = (giant) fmalloc(sizeof(giantstruct) + + ((numDigits - 1) * GIANT_BYTES_PER_DIGIT)); + result->capacity = numDigits; + + ap = array + 1; + digit = 0; + digitDex = 0; + + for(i=0; i> 8); + } + else { + /* even, i.e., l.s. byte */ + byte = (unsigned char)(*ap); + } + + /* add byte to current digit */ + digit |= (byte << (8 * digitByte)); + if(++i == numBytes) { + /* end of array, perhaps in the midst of a digit */ + break; + } + } + result->n[digitDex++] = digit; + digit = 0; + }; + + /* Careful: + * -- array elements are unsigned. The first element is + * he number of SHORTS in the array; convert to native + * digits. + * -- in the very odd (test only) case of giantDigit = unsigned char, + * we might have fewer valid digits than numDigits (might have + * leading zeros). + */ + if(sign < 0) { + result->sign = -numDigits; + } + else { + result->sign = numDigits; + } + gtrimSign(result); + return result; +} + +/* + * Obtain a malloc'd and uninitialized curveParams, to be init'd by caller. + */ +curveParams *newCurveParams(void) +{ + curveParams *params = (curveParams*) fmalloc(sizeof(curveParams)); + + bzero(params, sizeof(curveParams)); + return params; +} + +/* + * Alloc and zero reciprocal giants, when maxDigits is known. + * Currently only called when creating a curveParams from a public key. + * cp->primeType must be valid on input. + */ +void allocRecipGiants(curveParams *cp) +{ + cp->lesserX1OrderRecip = newGiant(cp->maxDigits); + cp->x1OrderPlusRecip = newGiant(cp->maxDigits); + int_to_giant(0, cp->lesserX1OrderRecip); + int_to_giant(0, cp->x1OrderPlusRecip); +} + +/* + * Obtain a malloc'd curveParams for a specified feeDepth. + */ +curveParams *curveParamsForDepth(feeDepth depth) +{ + curveParams *cp; + const curveParamsStatic *cps = &curveParamsArray[depth]; + + if(depth > FEE_DEPTH_MAX) { + return NULL; + } + #if GIANTS_VIA_STACK + curveParamsInitGiants(); + #endif + cp = newCurveParams(); + cp->primeType = cps->primeType; + cp->curveType = cps->curveType; + cp->q = cps->q; + cp->k = cps->k; + cp->m = cps->m; + if(cp->primeType == FPT_General) { + cp->basePrime = arrayToGiant(cps->basePrime); + } + cp->a = arrayToGiant(cps->a); + cp->b = arrayToGiant(cps->b); + cp->c = arrayToGiant(cps->c); + cp->x1Plus = arrayToGiant(cps->x1Plus); + if(cps->y1Plus) { + cp->y1Plus = arrayToGiant(cps->y1Plus); + } + if(cps->x1Minus) { + cp->x1Minus = arrayToGiant(cps->x1Minus); + } + cp->cOrderPlus = arrayToGiant(cps->cOrderPlus); + if(cps->cOrderMinus) { + cp->cOrderMinus = arrayToGiant(cps->cOrderMinus); + } + cp->x1OrderPlus = arrayToGiant(cps->x1OrderPlus); + if(cps->x1OrderMinus) { + cp->x1OrderMinus = arrayToGiant(cps->x1OrderMinus); + } + cp->x1OrderPlusRecip = arrayToGiant(cps->x1OrderPlusRecip); + + /* + * Special case optimization for equal reciprocals. + */ + if(cps->lesserX1OrderRecip == NULL) { + cp->lesserX1OrderRecip = cp->x1OrderPlusRecip; + } + else { + cp->lesserX1OrderRecip = arrayToGiant(cps->lesserX1OrderRecip); + } + + /* remainder calculated at runtime */ + curveParamsInferFields(cp); + return cp; +} + +/* + * Alloc a new curveParams struct as a copy of specified instance. + * This is the only way we can create a curveParams struct which doesn't + * match any existing known curve params. + */ +curveParams *curveParamsCopy(curveParams *cp) +{ + curveParams *newcp = newCurveParams(); + + newcp->primeType = cp->primeType; + newcp->curveType = cp->curveType; + newcp->q = cp->q; + newcp->k = cp->k; + newcp->m = cp->m; + newcp->basePrime = copyGiant(cp->basePrime); + newcp->minBytes = cp->minBytes; + newcp->maxDigits = cp->maxDigits; + + newcp->a = copyGiant(cp->a); + newcp->b = copyGiant(cp->b); + newcp->c = copyGiant(cp->c); + newcp->x1Plus = copyGiant(cp->x1Plus); + if(cp->x1Minus) { + newcp->x1Minus = copyGiant(cp->x1Minus); + } + newcp->y1Plus = copyGiant(cp->y1Plus); + newcp->cOrderPlus = copyGiant(cp->cOrderPlus); + if(cp->cOrderMinus) { + newcp->cOrderMinus = copyGiant(cp->cOrderMinus); + } + newcp->x1OrderPlus = copyGiant(cp->x1OrderPlus); + if(cp->x1OrderMinus) { + newcp->x1OrderMinus = copyGiant(cp->x1OrderMinus); + } + + newcp->x1OrderPlusRecip = copyGiant(cp->x1OrderPlusRecip); + if(cp->x1OrderPlusRecip == cp->lesserX1OrderRecip) { + /* + * Equal reciprocals; avoid new malloc + */ + newcp->lesserX1OrderRecip = newcp->x1OrderPlusRecip; + } + else { + newcp->lesserX1OrderRecip = copyGiant(cp->lesserX1OrderRecip); + } + if(cp->primeType == FPT_General) { + newcp->basePrimeRecip = copyGiant(cp->basePrimeRecip); + } + return newcp; +} + +/* + * Free a curveParams struct. + */ +void freeCurveParams(curveParams *cp) +{ + if(cp->basePrime != NULL) { + freeGiant(cp->basePrime); + } + if(cp->a != NULL) { + freeGiant(cp->a); + } + if(cp->b != NULL) { + freeGiant(cp->b); + } + if(cp->c != NULL) { + freeGiant(cp->c); + } + if(cp->x1Plus != NULL) { + freeGiant(cp->x1Plus); + } + if(cp->x1Minus != NULL) { + freeGiant(cp->x1Minus); + } + if(cp->y1Plus != NULL) { + freeGiant(cp->y1Plus); + } + if(cp->cOrderPlus != NULL) { + freeGiant(cp->cOrderPlus); + } + if(cp->cOrderMinus != NULL) { + freeGiant(cp->cOrderMinus); + } + if(cp->x1OrderPlus != NULL) { + freeGiant(cp->x1OrderPlus); + } + if(cp->x1OrderMinus != NULL) { + freeGiant(cp->x1OrderMinus); + } + if(cp->x1OrderPlusRecip != NULL) { + freeGiant(cp->x1OrderPlusRecip); + } + + /* + * Special case - if these are equal, we only alloc'd one giant + */ + if(cp->lesserX1OrderRecip != cp->x1OrderPlusRecip) { + freeGiant(cp->lesserX1OrderRecip); + } + if(cp->basePrimeRecip != NULL) { + freeGiant(cp->basePrimeRecip); + } + ffree(cp); +} + +/* + * Returns 1 if two sets of curve parameters are equivalent, else returns 0. + */ +int curveParamsEquivalent(curveParams *cp1, curveParams *cp2) +{ + if(cp1 == cp2) { + /* + * Trivial case, actually common for signature verify + */ + return 1; + } + if(cp1->primeType != cp2->primeType) { + return 0; + } + if(cp1->curveType != cp2->curveType) { + return 0; + } + if(cp1->k != cp2->k) { + return 0; + } + if(cp1->q != cp2->q) { + return 0; + } + if(cp1->m != cp2->m) { + return 0; + } + if(gcompg(cp1->basePrime, cp2->basePrime)) { + return 0; + } + if(gcompg(cp1->a, cp2->a)) { + return 0; + } + if(gcompg(cp1->b, cp2->b)) { + return 0; + } + if(gcompg(cp1->c, cp2->c)) { + return 0; + } + if(gcompg(cp1->x1Plus, cp2->x1Plus)) { + return 0; + } + if((cp1->x1Minus != NULL) && (cp2->x1Minus != NULL)) { + if(gcompg(cp1->x1Minus, cp2->x1Minus)) { + return 0; + } + } + if(gcompg(cp1->cOrderPlus, cp2->cOrderPlus)) { + return 0; + } + if((cp1->cOrderMinus != NULL) && (cp2->cOrderMinus != NULL)) { + if(gcompg(cp1->cOrderMinus, cp2->cOrderMinus)) { + return 0; + } + } + if(gcompg(cp1->x1OrderPlus, cp2->x1OrderPlus)) { + return 0; + } + if((cp1->x1OrderMinus != NULL) && (cp2->x1OrderMinus != NULL)) { + if(gcompg(cp1->x1OrderMinus, cp2->x1OrderMinus)) { + return 0; + } + } + /* + * If we got this far, reciprocals can't possibly be different + */ + return 1; +} + +/* + * Obtain the lesser of {x1OrderPlus, x1OrderMinus}. Returned value is not + * malloc'd; it's a pointer to one of the orders in *cp. + */ +giant lesserX1Order(curveParams *cp) +{ + CKASSERT(!isZero(cp->x1OrderPlus)); + + if(cp->x1OrderMinus == NULL) { + return(cp->x1OrderPlus); + } + else if(gcompg(cp->x1OrderPlus, cp->x1OrderMinus) >= 0) { + return(cp->x1OrderMinus); + } + else { + return(cp->x1OrderPlus); + } +} + +#if GIANTS_VIA_STACK + +/* + * Prime the curveParams and giants modules for quick allocs of giants. + */ +static int giantsInitd = 0; + +void curveParamsInitGiants(void) +{ + const curveParamsStatic *cps = &curveParamsArray[FEE_DEPTH_MAX]; + + if(giantsInitd) { + return; + } + + /* + * Figure the max giant size of the largest depth we know about... + */ + initGiantStacks(giantMaxDigits(giantMinBytes(cps->q, cps->k))); + giantsInitd = 1; +} + +#endif // GIANTS_VIA_STACK + +/* + * Infer the following fields from a partially constructed curveParams: + * + * basePrimeRecip if primeType == FPT_General + * basePrime if primeType != FPT_General + * y1Plus if curveType == FCT_Weierstrass and not pre-calculated + * minBytes + * maxDigits + * + * Assumes the following valid on entry: + * curveType + * primeType + * basePrime if primeType == FPT_General + * q, k if primeType != FPT_General + */ +void curveParamsInferFields(curveParams *cp) +{ + /* calc maxDigits, minBytes */ + calcGiantSizes(cp); + + /* basePrime or its reciprocal */ + if(cp->primeType == FPT_General) { + /* FIXME this should be declared statically! */ + cp->basePrimeRecip = newGiant(cp->maxDigits); + make_recip(cp->basePrime, cp->basePrimeRecip); + } + else { + /* + * FPT_FEE, FPT_Mersenne + */ + cp->basePrime = newGiant(cp->maxDigits); + make_base_prim(cp); + } + + /* y1Plus */ + #if CRYPTKIT_ELL_PROJ_ENABLE + if(cp->curveType == FCT_Weierstrass) { + if(cp->y1Plus == NULL) { + /* ECDSA Curves already have this */ + pointProj pt = newPointProj(cp->maxDigits); + findPointProj(pt, cp->x1Plus, cp); + + /* initial point is supposed to be on curve! */ + if(gcompg(pt->x, cp->x1Plus)) { + CKRaise("curveParamsInferFields failure"); + } + cp->y1Plus = copyGiant(pt->y); + freePointProj(pt); + } + } + else { + cp->y1Plus = newGiant(1); + } + #else /* CRYPTKIT_ELL_PROJ_ENABLE */ + cp->y1Plus = newGiant(1); + #endif + + if((cp->x1OrderPlusRecip == NULL) || isZero(cp->x1OrderPlusRecip)) { + /* + * an easy way of figuring this one out, this should not + * normally run. + */ + cp->x1OrderPlusRecip = newGiant(cp->maxDigits); + make_recip(cp->x1OrderPlus, cp->x1OrderPlusRecip); + if(cp->lesserX1OrderRecip != NULL) { + freeGiant(cp->lesserX1OrderRecip); + } + cp->lesserX1OrderRecip = cp->x1OrderPlusRecip; + } +} + +/* + * Given key size in bits, obtain the asssociated depth. + * Returns FR_IllegalDepth if specify key size not found + * in current curve tables. + */ +#define LOG_DEPTH 0 + +#if FEE_PROTOTYPE_CURVES +feeReturn feeKeyBitsToDepth(unsigned keySize, + feePrimeType primeType, /* FPT_Fefault means "best one" */ + feeCurveType curveType, /* FCT_Default means "best one" */ + feeDepth *depth) +{ + feeReturn frtn = FR_Success; + switch(keySize) { + case 31: + switch(curveType) { + case FCT_Montgomery: + default: + *depth = FEE_DEPTH_31_1_M; + break; + case FCT_Weierstrass: + *depth = FEE_DEPTH_31_1_P; + break; + } + break; + case 40: + switch(curveType) { + case FCT_Weierstrass: + default: + *depth = FEE_DEPTH_40_213; + break; + case FCT_Montgomery: + return FR_IllegalDepth; + } + break; + case 127: + switch(curveType) { + case FCT_Montgomery: + if(primeType == FPT_General) { + *depth = FEE_DEPTH_127_GEN; + } + else{ + *depth = FEE_DEPTH_127_1; + } + break; + case FCT_Weierstrass: + default: + *depth = FEE_DEPTH_127_1W; + break; + } + break; + case 160: + switch(curveType) { + case FCT_Montgomery: + return FR_IllegalDepth; + case FCT_Weierstrass: + default: + if(primeType == FPT_General) { + *depth = FEE_DEPTH_160_GEN; + } + else { + *depth = FEE_DEPTH_160_57; + } + break; + } + break; + case 192: + switch(curveType) { + case FCT_Montgomery: + *depth = FEE_DEPTH_192_M529891; + case FCT_Weierstrass: + default: + *depth = FEE_DEPTH_192_1425; + break; + } + break; + default: + frtn = FR_IllegalDepth; + break; + } + #if LOG_DEPTH + printf("feeKeyBitsToDepth: depth %d\n", *depth); + #endif + return frtn; +} + +#else /* FEE_PROTOTYPE_CURVES */ + +feeReturn feeKeyBitsToDepth(unsigned keySize, + feePrimeType primeType, /* FPT_Fefault means "best one" */ + feeCurveType curveType, /* FCT_Default means "best one" */ + feeDepth *depth) +{ + feeReturn frtn = FR_Success; + switch(keySize) { + case 31: + if(primeType == FPT_General) { + return FR_IllegalDepth; + } + /* note we cut a request for FPT_FEE some slack...this is actually + * FPT_Mersenne, but that is technically a subset of FEE. */ + switch(curveType) { + case FCT_Montgomery: + *depth = FEE_DEPTH_31M; + break; + case FCT_Weierstrass: + case FCT_Default: + *depth = FEE_DEPTH_31W; + break; + default: + return FR_IllegalDepth; + } + break; + case 127: + /* Montgomery only */ + if(primeType == FPT_General) { + return FR_IllegalDepth; + } + /* note we cut a request for FPT_FEE some slack...this is actually + * FPT_Mersenne, but that is technically a subset of FEE. */ + switch(curveType) { + case FCT_Montgomery: + case FCT_Default: + *depth = FEE_DEPTH_127M; + break; + case FCT_Weierstrass: + default: + return FR_IllegalDepth; + } + break; + case 128: + /* Weierstrass/feemod only */ + switch(primeType) { + case FPT_General: + case FPT_Mersenne: + return FR_IllegalDepth; + default: + /* FPT_Default, FPT_FEE */ + break; + } + switch(curveType) { + case FCT_Weierstrass: + case FCT_Default: + *depth = FEE_DEPTH_128W; + break; + default: + return FR_IllegalDepth; + } + break; + case 161: + switch(curveType) { + case FCT_Weierstrass: + case FCT_Default: + switch(primeType) { + case FPT_General: + *depth = FEE_DEPTH_161G; + break; + case FPT_FEE: + case FPT_Default: + *depth = FEE_DEPTH_161W; + break; + default: + /* i.e., FPT_Mersenne */ + return FR_IllegalDepth; + } + break; + default: + return FR_IllegalDepth; + } + break; + case 192: + switch(curveType) { + case FCT_Montgomery: + default: + return FR_IllegalDepth; + case FCT_Weierstrass: + case FCT_Default: + switch(primeType) { + case FPT_General: + case FPT_Default: + *depth = FEE_DEPTH_192G; + break; + default: + /* i.e., FPT_Mersenne, FPT_FEE */ + return FR_IllegalDepth; + } + break; + case FCT_ANSI: + switch(primeType) { + case FPT_General: + case FPT_Default: + break; + default: + return FR_IllegalDepth; + } + *depth = FEE_DEPTH_secp192r1; + break; + } + break; + case 256: + switch(curveType) { + case FCT_ANSI: + case FCT_Default: + break; + default: + return FR_IllegalDepth; + } + switch(primeType) { + case FPT_General: + case FPT_Default: + break; + default: + return FR_IllegalDepth; + } + *depth = FEE_DEPTH_secp256r1; + break; + case 384: + switch(curveType) { + case FCT_ANSI: + case FCT_Default: + break; + default: + return FR_IllegalDepth; + } + switch(primeType) { + case FPT_General: + case FPT_Default: + break; + default: + return FR_IllegalDepth; + } + *depth = FEE_DEPTH_secp384r1; + break; + case 521: + switch(curveType) { + case FCT_ANSI: + case FCT_Default: + break; + default: + return FR_IllegalDepth; + } + switch(primeType) { + case FPT_General: + case FPT_Default: + break; + default: + return FR_IllegalDepth; + } + *depth = FEE_DEPTH_secp521r1; + break; + + default: + frtn = FR_IllegalDepth; + break; + } + #if LOG_DEPTH + printf("feeKeyBitsToDepth: depth %d\n", *depth); + #endif + return frtn; +} + +#endif /* FEE_PROTOTYPE_CURVES */ + +/* + * Obtain depth for specified curveParams + */ +feeReturn curveParamsDepth( + curveParams *cp, + feeDepth *depth) +{ + if(cp == NULL) { + return FR_IllegalArg; + } + + /* We do it this way to allow reconstructing depth from an encoded curveParams */ + feeCurveType curveType = cp->curveType; + if((curveType == FCT_Weierstrass) && (cp->x1Minus == NULL)) { + /* actually an ANSI curve */ + curveType = FCT_ANSI; + } + return feeKeyBitsToDepth(cp->q, cp->primeType, curveType, depth); +} + + diff --git a/libsecurity_cryptkit/lib/curveParams.h b/libsecurity_cryptkit/lib/curveParams.h new file mode 100644 index 00000000..a75b49ed --- /dev/null +++ b/libsecurity_cryptkit/lib/curveParams.h @@ -0,0 +1,230 @@ +/* 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. + *************************************************************************** + * + * curveParams.h - FEE curve parameter functions + * + * Revision History + * ---------------- + * 9 Sep 98 Doug Mitchell at NeXT + * Added y1Plus for IEEE P1363 compliance. + * 20 Jan 98 Doug Mitchell at Apple + * Added primeType, m, basePrimeRecip. + * 11 Jun 97 Doug Mitchell at Apple + * Added x1OrderPlusRecip and lesserX1OrderRecip + * Disabled CP_SET_GIANT_SIZE hack + * 9 Jan 1997 Doug Mitchell at NeXT + * Major mods for IEEE-style parameters. + * 7 Aug 1996 Doug Mitchell at NeXT + * Created. + */ + +#ifndef _CK_CURVEPARAMS_H_ +#define _CK_CURVEPARAMS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "giantIntegers.h" +#include "feeTypes.h" + +/* + * Parameters defining a specific elliptic curve (and its initial points). + */ +typedef struct { + + /* + * Basic characteristic of prime field (PT_FEE, etc.) + */ + feePrimeType primeType; + + /* + * Basic curve type (CT_MONTGOMERY, etc.) + * Note that FCT_ANSI is stored here as FCT_Weierstrass. + */ + feeCurveType curveType; + + /* + * Parameters defining the base prime (2^q - k) for + * FPT_FEE and FPT_Mersenne. For FPT_General, q is the + * prime size in bits and k is 0. + */ + unsigned q; + int k; + + /* + * For all primeTypes, the field is defined as F(basePrime**m). + * This library can only deal with m == 1 for now. + */ + unsigned m; + + /* + * coefficients in the following equation: + * y^2 = x^3 + (c * x^2) + (a * x) + b + */ + giant a; + giant b; + giant c; + + /* + * Initial public point x-coordinates. + * x1Minus not used for ECDSA; X9.62 curves don't have this field. + */ + giant x1Plus; + giant x1Minus; + + /* + * Y coordinate of normalized projective initial public + * point for plus curve. I.e., Initial point = {x1Plus, p1Plus, 1}. + * Only valid for curveType == CT_WEIERSTRASS. This is calculated + * when a new curveParams is created. + */ + giant y1Plus; + + /* + * Curve orders. These are prime, or have large prime factors. + * cOrderMinus not used for ECDSA; X9.62 curves don't have this field. + */ + giant cOrderPlus; + giant cOrderMinus; + + /* + * Point orders (the large prime factors of the respective + * curve orders). + * x1OrderMinus not used for ECDSA; X9.62 curves don't have this field. + */ + giant x1OrderPlus; + giant x1OrderMinus; + + /* + * The base prime. For PT_GENERAL, this is a basic defining + * characteristic of a curve; otherwise, it is derived as 2**q - k. + */ + giant basePrime; + + /* + * The remaining fields are calculated and stored here as an + * optimization. + */ + + /* + * The minimum size of a giant, in bytes, to represent any point + * on this curve. This is generally used only when serializing + * giants of a known size. + */ + unsigned minBytes; + + /* + * The maximum size of a giant, in giantDigits, to be used with all + * FEE arithmetic for this curve. This is generally used to alloc + * giants. + */ + unsigned maxDigits; + + /* + * Reciprocals of lesserX1Order() and x1OrderPlus. Calculated + * lazily by clients in the case of creation of a curveParams + * struct from a byteRep representation. + */ + giant x1OrderPlusRecip; + giant lesserX1OrderRecip; + + /* + * Reciprocal of basePrime. Only used for PT_GENERAL. + */ + giant basePrimeRecip; +} curveParams; + +#if 0 +/* + * Values for primeType. + */ +#define PT_MERSENNE 0 /* basePrime = 2**q - 1 */ +#define PT_FEE 1 /* basePrime = 2**q - k, k is "small" */ +#define PT_GENERAL 2 /* other prime modulus */ + +/* + * Values for curveType. Note that Atkin3 (a=0) and Atkin4 (b=0) are + * subsets of CT_WEIERSTRASS. + */ +#define CT_MONTGOMERY 0 /* a=1, b=0 */ +#define CT_WEIERSTRASS 1 /* c=0 */ +#define CT_GENERAL 4 /* other */ +#endif 0 + +/* + * Obtain a malloc'd curveParams for a specified feeDepth. + */ +curveParams *curveParamsForDepth(feeDepth depth); + +/* + * Obtain a malloc'd and uninitialized curveParams, to be init'd by caller + * (when matching existing curve params). + */ +curveParams *newCurveParams(void); + +/* + * Alloc and zero reciprocal giants, when maxDigits is known. + */ +void allocRecipGiants(curveParams *cp); + +/* + * Alloc a new curveParams struct as a copy of specified instance. + */ +curveParams *curveParamsCopy(curveParams *cp); + +/* + * Free a curveParams struct. + */ +void freeCurveParams(curveParams *cp); + +/* + * Returns 1 if two sets of curve parameters are equivalent, else returns 0. + */ +int curveParamsEquivalent(curveParams *cp1, curveParams *cp2); + +/* + * Obtain the lesser of {x1OrderPlus, x1OrderMinus}. Returned value is not + * malloc'd; it's a pointer to one of the orders in *cp. + */ +giant lesserX1Order(curveParams *cp); + +/* + * Prime the curveParams and giants modules for quick allocs of giants. + */ +void curveParamsInitGiants(void); + +/* + * Infer run-time calculated fields from a partially constructed curveParams. + */ +void curveParamsInferFields(curveParams *cp); + +/* + * Given key size in bits, obtain the asssociated depth. + * Returns FR_IllegalDepth if specify key size not found + * in current curve tables. + */ +feeReturn feeKeyBitsToDepth(unsigned keyBits, + feePrimeType primeType, /* FPT_Fefault means "best one" */ + feeCurveType curveType, /* FCT_Default means "best one" */ + feeDepth *depth); + +/* + * Obtain depth for specified curveParams + */ +feeReturn curveParamsDepth( + curveParams *cp, + feeDepth *depth); + +#ifdef __cplusplus +} +#endif + +#endif /* _CK_CURVEPARAMS_H_ */ diff --git a/libsecurity_cryptkit/lib/elliptic.c b/libsecurity_cryptkit/lib/elliptic.c new file mode 100644 index 00000000..c025e8ee --- /dev/null +++ b/libsecurity_cryptkit/lib/elliptic.c @@ -0,0 +1,1438 @@ +/* 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. + *************************************************************************** + + elliptic.c - Library for Apple-proprietary Fast Elliptic + Encryption. The algebra in this module ignores elliptic point's + y-coordinates. + + Patent information: + + FEE is patented, U.S. Patents #5159632 (1992), #5271061 (1993), + #5463690 (1994). These patents are implemented + in various elliptic algebra functions such as + numer/denom_plus/times(), and in the fact of special + forms for primes: p = 2^q-k. + + Digital signature using fast elliptic addition, in + U. S. Patent #5581616 (1996), is implemented in the + signature_compare() function. + + FEED (Fast Elliptic Encryption) is patent pending (as of Jan 1998). + Various functions such as elliptic_add() implement the patent ideas. + + + Modification history since the U.S. Patent: + ------------------------------------------- + 10/06/98 ap + Changed to compile with C++. + 9 Sep 98 Doug Mitchell 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 + Used inline platform-dependent giant arithmetic. + 20 Jan 98 Doug Mitchell 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 + Microscopic feemod optimization. + 10 Jan 98 Doug Mitchell and Richard Crandall at Apple + ell_odd, ell_even() Montgomery optimization. + 09 Jan 98 Doug Mitchell and Richard Crandall at Apple + ell_odd, ell_even() Atkin3 optimization. + 08 Jan 97 Doug Mitchell at Apple + Cleaned up some debugging code; added gsquareTime + 11 Jun 97 Doug Mitchell and Richard Crandall 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 + 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 + 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 + Added mersennePrimes[24..26] + 08 Aug 96 Doug Mitchell at NeXT + Fixed giant leak in elliptic_add() + 05 Aug 96 Doug Mitchell at NeXT + Removed dead code + 24 Jul 96 Doug Mitchell at NeXT + Added ENGINE_127_BITS dependency for use of security engine + 24 Oct 92 Richard Crandall at NeXT + Modified new_public_from_private() + 1991 Richard Crandall at NeXT + Created. + + + FEE curve algebra, Jan 1997. + + Curves are: + + y^2 = x^3 + c x^2 + a x + b + + where useful parameterizations for practical purposes are: + + Montgomery: a = 1, b = 0. (The original 1991 FEE system.) + Weierstrass: c = 0. (The basic IEEE form.) + Atkin3: c = a = 0. + Atkin4: c = b = 0. + + However, the code is set up to work with any a, b, c. + The underlying fields F_{p^m} are of odd characteristic, + with all operations are (mod p). The special FEE-class + primes p are of the form: + + p = 2^q - k = 3 (mod 4) + + where k is single-precision. For such p, the mod operations + are especially fast (asymptotically vanishing time with respect + to a multiply). Note that the whole system + works equally well (except for slower execution) for arbitrary + primes p = 3 (mod 4) of the same bit length (q or q+1). + + The elliptic arithmetic now proceeds on the basis of + five fundamental operations that calculate various + numerator/denominator parts of the elliptic terms: + + numer_double(giant x, giant z, giant res, curveParams *par) + res := (x^2 - a z^2)^2 - 4 b (2 x + c z) z^3. + + numer_plus(giant x1, giant x2, giant res, curveParams *par) + res = (x1 x2 + a)(x1 + x2) + 2(c x1 x2 + b). + + denom_double(giant x, giant z, giant res, curveParams *par) + res = 4 z (x^3 + c x^2 z + a x z^2 + b z^3). + + denom_times(giant x1, giant z1, giant x2, giant z2, giant res, + curveParams *par) + res := (x1 z2 - x2 z1)^2 + + numer_times(giant x1, giant z1, giant x2, giant z2, giant res, + curveParams *par) + res := (x1 x2 - a z1 z2)^2 - 4 b(x1 z2 + x2 z1 + c z1 z2) z1 z2 + + If x(+-) represent the sum and difference x-coordinates + respectively, then, in pseudocode, + + For unequal starting coords: + x(+) + x(-) = U = 2 numer_plus/denom_times + x(+) x(-) = V = numer_times/denom_times + + and for equal starting coords: + x(+) = numer_double/denom_double + + The elliptic_add() function uses the fact that + + x(+) = U/2 + s*Sqrt[U^2/4 - V] + + where the sign s = +-1. + +*/ + +#include "ckconfig.h" +#include +#include +#include +#include "platform.h" + +#include "giantIntegers.h" +#include "elliptic.h" +#include "ellipticProj.h" +#include "ckutilities.h" +#include "curveParams.h" +#include "feeDebug.h" +#include "ellipticMeasure.h" +#include "falloc.h" +#include "giantPortCommon.h" + +#if FEE_PROFILE + +unsigned numerDoubleTime; +unsigned numerPlusTime; +unsigned numerTimesTime; +unsigned denomDoubleTime; +unsigned denomTimesTime; +unsigned ellipticTime; +unsigned sigCompTime; +unsigned powerModTime; +unsigned ellAddTime; +unsigned whichCurveTime; +unsigned modgTime; +unsigned mulgTime; +unsigned binvauxTime; +unsigned gsquareTime; + +unsigned numMulg; +unsigned numFeemod; +unsigned numGsquare; +unsigned numBorrows; + +void clearProfile() +{ + numerDoubleTime = 0; + numerPlusTime = 0; + numerTimesTime = 0; + denomDoubleTime = 0; + denomTimesTime = 0; + ellipticTime = 0; + sigCompTime = 0; + powerModTime = 0; + ellAddTime = 0; + whichCurveTime = 0; + modgTime = 0; + mulgTime = 0; + binvauxTime = 0; + gsquareTime = 0; + numMulg = 0; + numFeemod = 0; + numGsquare = 0; + numBorrows = 0; +} + +#endif // FEE_PROFILE + +#if ELL_PROFILE +unsigned ellOddTime; +unsigned ellEvenTime; +unsigned numEllOdds; +unsigned numEllEvens; + +void clearEllProfile() +{ + ellOddTime = 0; + ellEvenTime = 0; + numEllOdds = 0; + numEllEvens = 0; +} + +#endif /* ELL_PROFILE */ +#if ELLIPTIC_MEASURE + +int doEllMeasure; // gather stats on/off */ +int bitsInN; +int numFeeMods; +int numMulgs; + +void dumpEll() +{ + printf("\nbitlen(n) : %d\n", bitsInN); + printf("feemods : %d\n", numFeeMods); + printf("mulgs : %d\n", numMulgs); +} + +#endif // ELLIPTIC_MEASURE + +/********** Globals ********************************/ + +static void make_base(curveParams *par, giant result); // result = with 2^q-k +static int keys_inconsistent(key pub1, key pub2); +/* Return non-zero if pub1, pub2 have inconsistent parameters. + */ + + +static void ell_even(giant x1, giant z1, giant x2, giant z2, curveParams *par); +static void ell_odd(giant x1, giant z1, giant x2, giant z2, giant xxor, + giant zor, curveParams *par); +static void numer_double(giant x, giant z, giant res, curveParams *par); +static void numer_plus(giant x1, giant x2, giant res, curveParams *par); +static void denom_double(giant x, giant z, giant res, curveParams *par); +static void denom_times(giant x1, giant z1, giant x2, giant z2, giant res, + curveParams *par); +static void numer_times(giant x1, giant z1, giant x2, giant z2, giant res, + curveParams *par); +static void feepowermodg(curveParams *par, giant x, giant n); +static void curveOrderJustifyWithRecip(giant g, giant curveOrder, giant recip); + +/* + * Completely rewritten in CryptKit-18, 13 Jan 1997, for new IEEE-style + * curveParameters. + */ +int which_curve(giant x, curveParams *par) + /* Returns (+-1) depending on whether x is on curve + (+-)y^2 = x^3 + c x^2 + a x + b. + */ +{ + giant t1; + giant t2; + giant t3; + int result; + PROF_START; + + t1 = borrowGiant(par->maxDigits); + t2 = borrowGiant(par->maxDigits); + t3 = borrowGiant(par->maxDigits); + + /* First, set t2:= x^3 + c x^2 + a x + b. */ + gtog(x, t2); addg(par->c, t2); + mulg(x, t2); addg(par->a, t2); /* t2 := x^2 + c x + a. */ + feemod(par, t2); + mulg(x, t2); addg(par->b, t2); + feemod(par, t2); + /* Next, test whether t2 is a square. */ + gtog(t2, t1); + make_base(par, t3); iaddg(1, t3); gshiftright(1, t3); /* t3 = (p+1)/2. */ + feepowermodg(par, t1, t3); /* t1 := t2^((p+1)/2) (mod p). */ + if(gcompg(t1, t2) == 0) + result = CURVE_PLUS; + else + result = CURVE_MINUS; + returnGiant(t1); + returnGiant(t2); + returnGiant(t3); + PROF_END(whichCurveTime); + return result; +} + +key new_public(curveParams *cp, int twist) { + key k; + + k = (key) fmalloc(sizeof(keystruct)); + k->cp = cp; + k->twist = twist; + + k->x = newGiant(cp->maxDigits); + if((twist == CURVE_PLUS) && (cp->curveType == FCT_Weierstrass)) { + k->y = newGiant(cp->maxDigits); + } + else { + /* + * no projective algebra. We could optimize and save a few bytes + * here by setting y to NULL, but that really complicates things + * in may other places. Best to have a real giant. + */ + k->y = newGiant(1); + } + return(k); +} + +key new_public_with_key(key old_key, curveParams *cp) +{ + key result; + + result = new_public(cp, old_key->twist); + CKASSERT((old_key->x != NULL) && (old_key->y != NULL)); + CKASSERT((result->x != NULL) && (result->y != NULL)); + gtog(old_key->x, result->x); + gtog(old_key->y, result->y); + return result; +} + +void free_key(key pub) { + if(!pub) { + return; + } + if (pub->x) { + freeGiant(pub->x); + } + if (pub->y) { + freeGiant(pub->y); + } + ffree(pub); +} + +/* + * Specify private data for key created by new_public(). + * Generates k->x. + */ +void set_priv_key_giant(key k, giant privGiant) +{ + curveParams *cp = k->cp; + + /* elliptiy multiply of initial public point times private key */ + #if CRYPTKIT_ELL_PROJ_ENABLE + if((k->twist == CURVE_PLUS) && (cp->curveType == FCT_Weierstrass)) { + /* projective */ + + pointProj pt1 = newPointProj(cp->maxDigits); + + CKASSERT((cp->y1Plus != NULL) && (!isZero(cp->y1Plus))); + CKASSERT(k->y != NULL); + + /* pt1 := {x1Plus, y1Plus, 1} */ + gtog(cp->x1Plus, pt1->x); + gtog(cp->y1Plus, pt1->y); + int_to_giant(1, pt1->z); + + /* pt1 := pt1 * privateKey */ + ellMulProjSimple(pt1, privGiant, cp); + + /* result back to {k->x, k->y} */ + gtog(pt1->x, k->x); + gtog(pt1->y, k->y); + freePointProj(pt1); // FIXME - clear the giants + } + else { + #else + { + #endif /* CRYPTKIT_ELL_PROJ_ENABLE */ + /* FEE */ + if(k->twist == CURVE_PLUS) { + gtog(cp->x1Plus, k->x); + } + else { + gtog(cp->x1Minus, k->x); + } + elliptic_simple(k->x, privGiant, k->cp); + } +} + +int key_equal(key one, key two) { + if (keys_inconsistent(one, two)) return 0; + return !gcompg(one->x, two->x); +} + +static void make_base(curveParams *par, giant result) +/* Jams result with 2^q-k. */ +{ + gtog(par->basePrime, result); +} + +void make_base_prim(curveParams *cp) +/* Jams cp->basePrime with 2^q-k. Assumes valid maxDigits, q, k. */ +{ + giant tmp = borrowGiant(cp->maxDigits); + + CKASSERT(cp->primeType != FPT_General); + int_to_giant(1, cp->basePrime); + gshiftleft((int)cp->q, cp->basePrime); + int_to_giant(cp->k, tmp); + subg(tmp, cp->basePrime); + returnGiant(tmp); +} + +static int sequalg(int n, giant g) { + if((g->sign == 1) && (g->n[0] == n)) return(1); + return(0); +} + + +/* + * Elliptic multiply: x := n * {x, 1} + */ +void elliptic_simple(giant x, giant n, curveParams *par) { + giant ztmp = borrowGiant(par->maxDigits); + giant cur_n = borrowGiant(par->maxDigits); + + START_ELL_MEASURE(n); + int_to_giant(1, ztmp); + elliptic(x, ztmp, n, par); + binvg_cp(par, ztmp); + mulg(ztmp, x); + feemod(par, x); + END_ELL_MEASURE; + + returnGiant(cur_n); + returnGiant(ztmp); +} + +/* + * General elliptic multiply. + * + * {xx, zz} := k * {xx, zz} + */ +void elliptic(giant xx, giant zz, giant k, curveParams *par) { + int len = bitlen(k); + int pos = len - 2; + giant xs; + giant zs; + giant xorg; + giant zorg; + + PROF_START; + if(sequalg(1,k)) return; + if(sequalg(2,k)) { + ell_even(xx, zz, xx, zz, par); + goto out; + } + zs = borrowGiant(par->maxDigits); + xs = borrowGiant(par->maxDigits); + zorg = borrowGiant(par->maxDigits); + xorg = borrowGiant(par->maxDigits); + gtog(xx, xorg); gtog(zz, zorg); + ell_even(xx, zz, xs, zs, par); + do { + if(bitval(k, pos--)) { + ell_odd(xs, zs, xx, zz, xorg, zorg, par); + ell_even(xs, zs, xs, zs, par); + } else { + ell_odd(xx, zz, xs, zs, xorg, zorg, par); + ell_even(xx, zz, xx, zz, par); + } + } while (pos >= 0); // REC fix 9/23/94 + returnGiant(xs); + returnGiant(zs); + returnGiant(xorg); + returnGiant(zorg); +out: + PROF_END(ellipticTime); +} + +/* + * Completely rewritten in CryptKit-18, 13 Jan 1997, for new IEEE-style + * curveParameters. + */ +void elliptic_add(giant x1, giant x2, giant x3, curveParams *par, int s) { + + /* Addition algorithm for x3 = x1 + x2 on the curve, with sign ambiguity s. + From theory, we know that if {x1,1} and {x2,1} are on a curve, then + their elliptic sum (x1,1} + {x2,1} = {x3,1} must have x3 as one of two + values: + + x3 = U/2 + s*Sqrt[U^2/4 - V] + + where sign s = +-1, and U,V are functions of x1,x2. Tho present function + is called a maximum of twice, to settle which of +- is s. When a call + is made, it is guaranteed already that x1, x2 both lie on the same curve + (+- curve); i.e., which curve (+-) is not connected at all with sign s of + the x3 relation. + */ + + giant cur_n; + giant t1; + giant t2; + giant t3; + giant t4; + giant t5; + + PROF_START; + cur_n = borrowGiant(par->maxDigits); + t1 = borrowGiant(par->maxDigits); + t2 = borrowGiant(par->maxDigits); + t3 = borrowGiant(par->maxDigits); + t4 = borrowGiant(par->maxDigits); + t5 = borrowGiant(par->maxDigits); + + if(gcompg(x1, x2)==0) { + int_to_giant(1, t1); + numer_double(x1, t1, x3, par); + denom_double(x1, t1, t2, par); + binvg_cp(par, t2); + mulg(t2, x3); feemod(par, x3); + goto out; + } + numer_plus(x1, x2, t1, par); + int_to_giant(1, t3); + numer_times(x1, t3, x2, t3, t2, par); + int_to_giant(1, t4); int_to_giant(1, t5); + denom_times(x1, t4, x2, t5, t3, par); + binvg_cp(par, t3); + mulg(t3, t1); feemod(par, t1); /* t1 := U/2. */ + mulg(t3, t2); feemod(par, t2); /* t2 := V. */ + /* Now x3 will be t1 +- Sqrt[t1^2 - t2]. */ + gtog(t1, t4); gsquare(t4); feemod(par, t4); + subg(t2, t4); + make_base(par, cur_n); iaddg(1, cur_n); gshiftright(2, cur_n); + /* cur_n := (p+1)/4. */ + feepowermodg(par, t4, cur_n); /* t4 := t2^((p+1)/4) (mod p). */ + gtog(t1, x3); + if(s != SIGN_PLUS) negg(t4); + addg(t4, x3); + feemod(par, x3); + +out: + returnGiant(cur_n); + returnGiant(t1); + returnGiant(t2); + returnGiant(t3); + returnGiant(t4); + returnGiant(t5); + + PROF_END(ellAddTime); +} + +/* + * Key exchange atom. + */ +giant make_pad(giant privGiant, key publicKey) { + curveParams *par = publicKey->cp; + giant result = newGiant(par->maxDigits); + + gtog(publicKey->x, result); + elliptic_simple(result, privGiant, par); + return result; +} + +static void ell_even(giant x1, giant z1, giant x2, giant z2, curveParams *par) { + giant t1; + giant t2; + giant t3; + + EPROF_START; + + t1 = borrowGiant(par->maxDigits); + t2 = borrowGiant(par->maxDigits); + t3 = borrowGiant(par->maxDigits); + + if(par->curveType == FCT_Montgomery) { + /* Begin Montgomery OPT: 10 Jan 98 REC. */ + gtog(x1, t1); gsquare(t1); feemod(par, t1); /* t1 := x1^2. */ + gtog(z1, t2); gsquare(t2); feemod(par, t2); /* t2 := z1^2. */ + + gtog(x1, t3); mulg(z1, t3); feemod(par, t3); + gtog(t3, z2); mulg(par->c, z2); feemod(par, z2); + addg(t1, z2); addg(t2, z2); mulg(t3, z2); gshiftleft(2, z2); + feemod(par, z2); /* z2 := 4 x1 z1 (x1^2 + c x1 z1 + z1^2). */ + gtog(t1, x2); subg(t2, x2); gsquare(x2); feemod(par, x2); + /* x2 := (x1^2 - z1^2)^2. */ + /* End OPT: 10 Jan 98 REC. */ + } + else if((par->curveType == FCT_Weierstrass) && isZero(par->a)) { + /* Begin Atkin3 OPT: 9 Jan 98 REC. */ + gtog(x1, t1); + gsquare(t1); feemod(par, t1); + mulg(x1, t1); feemod(par, t1); /* t1 := x^3. */ + gtog(z1, t2); + gsquare(t2); feemod(par, t2); + mulg(z1, t2); feemod(par, t2); /* t2 := z1^3 */ + mulg(par->b, t2); feemod(par, t2); /* t2 := b z1^3. */ + gtog(t1, t3); addg(t2, t3); /* t3 := x^3 + b z1^3 */ + mulg(z1, t3); feemod(par, t3); /* t3 *= z1 + * = z1 ( x^3 + b z1^3 ) */ + gshiftleft(2, t3); feemod(par, t3); /* t3 = 4 z1 (x1^3 + b z1^3) */ + + gshiftleft(3, t2); /* t2 = 8 b z1^3 */ + subg(t2, t1); /* t1 = x^3 - 8 b z1^3 */ + mulg(x1, t1); feemod(par, t1); /* t1 = x1 (x1^3 - 8 b z1^3) */ + + gtog(t3, z2); + gtog(t1, x2); + /* End OPT: 9 Jan 98 REC. */ + } + else { + numer_double(x1, z1, t1, par); + denom_double(x1, z1, t2, par); + gtog(t1, x2); gtog(t2, z2); + } + returnGiant(t1); + returnGiant(t2); + returnGiant(t3); + + EPROF_END(ellEvenTime); + EPROF_INCR(numEllEvens); + + /* + printf("ell_even end\n"); + printf(" x1 : "); printGiant(x1); + printf(" z1 : "); printGiant(z1); + printf(" x2 : "); printGiant(x2); + printf(" z2 : "); printGiant(z2); + */ +} + +static void ell_odd(giant x1, giant z1, giant x2, giant z2, giant xxor, + giant zor, curveParams *par) +{ + + giant t1; + giant t2; + + EPROF_START; + t1 = borrowGiant(par->maxDigits); + t2 = borrowGiant(par->maxDigits); + + if(par->curveType == FCT_Montgomery) { + /* Begin Montgomery OPT: 10 Jan 98 REC. */ + giant t3 = borrowGiant(par->maxDigits); + giant t4 = borrowGiant(par->maxDigits); + + gtog(x1, t1); addg(z1, t1); /* t1 := x1 + z1. */ + gtog(x2, t2); subg(z2, t2); /* t2 := x2 - z2. */ + gtog(x1, t3); subg(z1, t3); /* t3 := x1 - z1. */ + gtog(x2, t4); addg(z2, t4); /* t4 := x2 + z2. */ + mulg(t2, t1); feemod(par, t1); /* t1 := (x1 + z1)(x2 - z2) */ + mulg(t4, t3); feemod(par, t3); /* t4 := (x2 + z2)(x1 - z1) */ + gtog(t1, z2); subg(t3, z2); /*???gshiftright(1, z2);*/ + /* z2 := ((x1 + z1)(x2 - z2) - x2)/2 */ + gsquare(z2); feemod(par, z2); + mulg(xxor, z2); feemod(par, z2); + gtog(t1, x2); addg(t3, x2); /*????gshiftright(1, x2);*/ + gsquare(x2); feemod(par, x2); + mulg(zor, x2); feemod(par, x2); + + returnGiant(t3); + returnGiant(t4); + } + else if((par->curveType == FCT_Weierstrass) && isZero(par->a)) { + /* Begin Atkin3 OPT: 9 Jan 98 REC. */ + + giant t3 = borrowGiant(par->maxDigits); + giant t4 = borrowGiant(par->maxDigits); + + gtog(x1, t1); mulg(x2, t1); feemod(par, t1); /* t1 := x1 x2. */ + gtog(z1, t2); mulg(z2, t2); feemod(par, t2); /* t2 := z1 z2. */ + gtog(x1, t3); mulg(z2, t3); feemod(par, t3); /* t3 := x1 z2. */ + gtog(z1, t4); mulg(x2, t4); feemod(par, t4); /* t4 := x2 z1. */ + gtog(t3, z2); subg(t4, z2); gsquare(z2); feemod(par, z2); + mulg(xxor, z2); feemod(par, z2); + gtog(t1, x2); gsquare(x2); feemod(par, x2); + addg(t4, t3); mulg(t2, t3); feemod(par, t3); + mulg(par->b, t3); feemod(par, t3); + addg(t3, t3); addg(t3, t3); + subg(t3, x2); mulg(zor, x2); feemod(par, x2); + + returnGiant(t3); + returnGiant(t4); + /* End OPT: 9 Jan 98 REC. */ + } + else { + numer_times(x1, z1, x2, z2, t1, par); + mulg(zor, t1); feemod(par, t1); + denom_times(x1, z1, x2, z2, t2, par); + mulg(xxor, t2); feemod(par, t2); + + gtog(t1, x2); gtog(t2, z2); + } + + returnGiant(t1); + returnGiant(t2); + + EPROF_END(ellOddTime); + EPROF_INCR(numEllOdds); + + /* + printf("ell_odd end\n"); + printf(" x2 : "); printGiant(x2); + printf(" z2 : "); printGiant(z2); + */ +} + +/* + * return codes from keys_inconsistent() and signature_compare(). The actual + * values are not public; they are defined here for debugging. + */ +#define CURVE_PARAM_MISMATCH 1 +#define TWIST_PARAM_MISMATCH 2 +#define SIGNATURE_INVALID 3 + + +/* + * Determine whether two keystructs have compatible parameters (i.e., same + * twist and curveParams). Return 0 if compatible, else non-zero. + */ +static int keys_inconsistent(key pub1, key pub2){ + if(!curveParamsEquivalent(pub1->cp, pub2->cp)) { + return CURVE_PARAM_MISMATCH; + } + if(pub1->twist != pub2->twist) { + return TWIST_PARAM_MISMATCH; + } + return 0; +} + +int signature_compare(giant p0x, giant p1x, giant p2x, curveParams *par) +/* Returns non-zero iff p0x cannot be the x-coordinate of the sum of two points whose respective x-coordinates are p1x, p2x. */ +{ + int ret = 0; + giant t1; + giant t2; + giant t3; + giant t4; + giant t5; + + PROF_START; + + t1 = borrowGiant(par->maxDigits); + t2 = borrowGiant(par->maxDigits); + t3 = borrowGiant(par->maxDigits); + t4 = borrowGiant(par->maxDigits); + t5 = borrowGiant(par->maxDigits); + + if(gcompg(p1x, p2x) == 0) { + int_to_giant(1, t1); + numer_double(p1x, t1, t2, par); + denom_double(p1x, t1, t3, par); + mulg(p0x, t3); subg(t3, t2); + feemod(par, t2); + } else { + numer_plus(p1x, p2x, t1, par); + gshiftleft(1, t1); feemod(par, t1); + int_to_giant(1, t3); + numer_times(p1x, t3, p2x, t3, t2, par); + int_to_giant(1, t4); int_to_giant(1, t5); + denom_times(p1x, t4 , p2x, t5, t3, par); + /* Now we require t3 x0^2 - t1 x0 + t2 == 0. */ + mulg(p0x, t3); feemod(par, t3); + subg(t1, t3); mulg(p0x, t3); + feemod(par, t3); + addg(t3, t2); + feemod(par, t2); + } + + if(!isZero(t2)) ret = SIGNATURE_INVALID; + returnGiant(t1); + returnGiant(t2); + returnGiant(t3); + returnGiant(t4); + returnGiant(t5); + PROF_END(sigCompTime); + return(ret); +} + + +static void numer_double(giant x, giant z, giant res, curveParams *par) +/* Numerator algebra. + res := (x^2 - a z^2)^2 - 4 b (2 x + c z) z^3. + */ +{ + giant t1; + giant t2; + + PROF_START; + t1 = borrowGiant(par->maxDigits); + t2 = borrowGiant(par->maxDigits); + + gtog(x, t1); gsquare(t1); feemod(par, t1); + gtog(z, res); gsquare(res); feemod(par, res); + gtog(res, t2); + if(!isZero(par->a) ) { + if(!isone(par->a)) { /* Speedup - REC 17 Jan 1997. */ + mulg(par->a, res); feemod(par, res); + } + subg(res, t1); feemod(par, t1); + } + gsquare(t1); feemod(par, t1); + /* t1 := (x^2 - a z^2)^2. */ + if(isZero(par->b)) { /* Speedup - REC 17 Jan 1997. */ + gtog(t1, res); + goto done; + } + if(par->curveType != FCT_Weierstrass) { // i.e., !isZero(par->c) + // Speedup - REC 17 Jan 1997. + gtog(z, res); mulg(par->c, res); feemod(par, res); + } else { + int_to_giant(0, res); + } + addg(x, res); addg(x, res); mulg(par->b, res); + feemod(par, res); + gshiftleft(2, res); mulg(z, res); feemod(par, res); + mulg(t2, res); feemod(par, res); + negg(res); addg(t1, res); + feemod(par, res); + +done: + returnGiant(t1); + returnGiant(t2); + PROF_END(numerDoubleTime); +} + +static void numer_plus(giant x1, giant x2, giant res, curveParams *par) +/* Numerator algebra. + res = (x1 x2 + a)(x1 + x2) + 2(c x1 x2 + b). + */ +{ + giant t1; + giant t2; + + PROF_START; + t1 = borrowGiant(par->maxDigits); + t2 = borrowGiant(par->maxDigits); + + gtog(x1, t1); mulg(x2, t1); feemod(par, t1); + gtog(x2, t2); addg(x1, t2); feemod(par, t2); + gtog(t1, res); + if(!isZero(par->a)) + addg(par->a, res); + mulg(t2, res); feemod(par, res); + if(par->curveType == FCT_Weierstrass) { // i.e., isZero(par->c) + int_to_giant(0, t1); + } + else { + mulg(par->c, t1); feemod(par, t1); + } + if(!isZero(par->b)) + addg(par->b, t1); + gshiftleft(1, t1); + addg(t1, res); feemod(par, res); + + returnGiant(t1); + returnGiant(t2); + PROF_END(numerPlusTime); +} + +static void denom_double(giant x, giant z, giant res, curveParams *par) +/* Denominator algebra. + res = 4 z (x^3 + c x^2 z + a x z^2 + b z^3). */ +{ + giant t1; + giant t2; + + PROF_START; + t1 = borrowGiant(par->maxDigits); + t2 = borrowGiant(par->maxDigits); + + gtog(x, res); gtog(z, t1); + if(par->curveType != FCT_Weierstrass) { // i.e., !isZero(par->c) + gtog(par->c, t2); mulg(t1, t2); feemod(par, t2); + addg(t2, res); + } + mulg(x, res); feemod(par, res); + gsquare(t1); feemod(par, t1); + if(!isZero(par->a)) { + gtog(t1, t2); + mulg(par->a, t2); feemod(par, t2); + addg(t2, res); + } + mulg(x, res); feemod(par, res); + if(!isZero(par->b)) { + mulg(z, t1); feemod(par, t1); + mulg(par->b, t1); feemod(par, t1); + addg(t1, res); + } + mulg(z, res); gshiftleft(2, res); + feemod(par, res); + + returnGiant(t1); + returnGiant(t2); + PROF_END(denomDoubleTime); +} + + + +static void denom_times(giant x1, giant z1, giant x2, giant z2, giant res, + curveParams *par) +/* Denominator algebra. + res := (x1 z2 - x2 z1)^2 + */ +{ + giant t1; + + PROF_START; + t1 = borrowGiant(par->maxDigits); + + gtog(x1, res); mulg(z2, res); feemod(par, res); + gtog(z1, t1); mulg(x2, t1); feemod(par, t1); + subg(t1, res); gsquare(res); feemod(par, res); + + returnGiant(t1); + PROF_END(denomTimesTime); +} + +static void numer_times(giant x1, giant z1, giant x2, giant z2, giant res, + curveParams *par) +/* Numerator algebra. + res := (x1 x2 - a z1 z2)^2 - + 4 b(x1 z2 + x2 z1 + c z1 z2) z1 z2 + */ +{ + giant t1; + giant t2; + giant t3; + giant t4; + + PROF_START; + t1 = borrowGiant(par->maxDigits); + t2 = borrowGiant(par->maxDigits); + t3 = borrowGiant(par->maxDigits); + t4 = borrowGiant(par->maxDigits); + + gtog(x1, t1); mulg(x2, t1); feemod(par, t1); + gtog(z1, t2); mulg(z2, t2); feemod(par, t2); + gtog(t1, res); + if(!isZero(par->a)) { + gtog(par->a, t3); + mulg(t2, t3); feemod(par, t3); + subg(t3, res); + } + gsquare(res); feemod(par, res); + if(isZero(par->b)) + goto done; + if(par->curveType != FCT_Weierstrass) { // i.e., !isZero(par->c) + gtog(par->c, t3); + mulg(t2, t3); feemod(par, t3); + } else int_to_giant(0, t3); + gtog(z1, t4); mulg(x2, t4); feemod(par, t4); + addg(t4, t3); + gtog(x1, t4); mulg(z2, t4); feemod(par, t4); + addg(t4, t3); mulg(par->b, t3); feemod(par, t3); + mulg(t2, t3); gshiftleft(2, t3); feemod(par, t3); + subg(t3, res); + feemod(par, res); + +done: + returnGiant(t1); + returnGiant(t2); + returnGiant(t3); + returnGiant(t4); + PROF_END(numerTimesTime); +} + +/* + * New, 13 Jan 1997. + */ +static void feepowermodg(curveParams *par, giant x, giant n) +/* Power ladder. + x := x^n (mod 2^q-k) + */ +{ + int len, pos; + giant t1; + + PROF_START; + t1 = borrowGiant(par->maxDigits); + gtog(x, t1); + int_to_giant(1, x); + len = bitlen(n); + pos = 0; + while(1) { + if(bitval(n, pos++)) { + mulg(t1, x); + feemod(par, x); + } + if(pos>=len) break; + gsquare(t1); + feemod(par, t1); + } + returnGiant(t1); + PROF_END(powerModTime); +} + +/* + * Set g := g mod curveOrder; + * force g to be between 2 and (curveOrder-2), inclusive. + * + * Tolerates zero curve orders (indicating "not known"). + */ + +/* + * This version is not normally used; it's for when the reciprocal of + * curveOrder is not known and won't be used again. + */ +void curveOrderJustify(giant g, giant curveOrder) +{ + giant recip; + + CKASSERT(!isZero(curveOrder)); + + recip = borrowGiant(2 * abs(g->sign)); + make_recip(curveOrder, recip); + curveOrderJustifyWithRecip(g, curveOrder, recip); + returnGiant(recip); +} + +/* + * New optimzation of curveOrderJustify using known reciprocal, 11 June 1997. + * g is set to be within [2, curveOrder-2]. + */ +static void curveOrderJustifyWithRecip(giant g, giant curveOrder, giant recip) +{ + giant tmp; + + CKASSERT(!isZero(curveOrder)); + + modg_via_recip(curveOrder, recip, g); // g now in [0, curveOrder-1] + + if(isZero(g)) { + /* + * First degenerate case - (g == 0) : set g := 2 + */ + dbgLog(("curveOrderJustify: case 1\n")); + int_to_giant(2, g); + return; + } + if(isone(g)) { + /* + * Second case - (g == 1) : set g := 2 + */ + dbgLog(("curveOrderJustify: case 2\n")); + int_to_giant(2, g); + return; + } + tmp = borrowGiant(g->capacity); + gtog(g, tmp); + iaddg(1, tmp); + if(gcompg(tmp, curveOrder) == 0) { + /* + * Third degenerate case - (g == (curveOrder-1)) : set g -= 1 + */ + dbgLog(("curveOrderJustify: case 3\n")); + int_to_giant(1, tmp); + subg(tmp, g); + } + returnGiant(tmp); + return; +} + +#define RECIP_DEBUG 0 +#if RECIP_DEBUG +#define recipLog(x) printf x +#else // RECIP_DEBUG +#define recipLog(x) +#endif // RECIP_DEBUG + +/* + * curveOrderJustify routines with specific orders, using (and possibly + * generating) associated reciprocals. + */ +void lesserX1OrderJustify(giant g, curveParams *cp) +{ + /* + * Note this is a pointer to a giant in *cp, not a newly + * malloc'd giant! + */ + giant lesserX1Ord = lesserX1Order(cp); + + if(isZero(lesserX1Ord)) { + return; + } + + /* + * Calculate reciprocal if we don't have it + */ + if(isZero(cp->lesserX1OrderRecip)) { + if((lesserX1Ord == cp->x1OrderPlus) && + (!isZero(cp->x1OrderPlusRecip))) { + /* + * lesserX1Ord happens to be x1OrderPlus, and we + * have a reciprocal for x1OrderPlus. Copy it over. + */ + recipLog(( + "x1OrderPlusRecip --> lesserX1OrderRecip\n")); + gtog(cp->x1OrderPlusRecip, cp->lesserX1OrderRecip); + } + else { + /* Calculate the reciprocal. */ + recipLog(("calc lesserX1OrderRecip\n")); + make_recip(lesserX1Ord, cp->lesserX1OrderRecip); + } + } + else { + recipLog(("using existing lesserX1OrderRecip\n")); + } + curveOrderJustifyWithRecip(g, lesserX1Ord, cp->lesserX1OrderRecip); +} + +/* + * Common code used by x1OrderPlusJustify() and x1OrderPlusMod() to generate + * reciprocal of x1OrderPlus. + * 8 Sep 1998 - also used by feeSigSign(). + */ +void calcX1OrderPlusRecip(curveParams *cp) +{ + if(isZero(cp->x1OrderPlusRecip)) { + if((cp->x1OrderPlus == lesserX1Order(cp)) && + (!isZero(cp->lesserX1OrderRecip))) { + /* + * lesserX1Order happens to be x1OrderPlus, and we + * have a reciprocal for lesserX1Order. Copy it over. + */ + recipLog(( + "lesserX1OrderRecip --> x1OrderPlusRecip\n")); + gtog(cp->lesserX1OrderRecip, cp->x1OrderPlusRecip); + } + else { + /* Calculate the reciprocal. */ + recipLog(("calc x1OrderPlusRecip\n")); + make_recip(cp->x1OrderPlus, cp->x1OrderPlusRecip); + } + } + else { + recipLog(("using existing x1OrderPlusRecip\n")); + } +} + +void x1OrderPlusJustify(giant g, curveParams *cp) +{ + CKASSERT(!isZero(cp->x1OrderPlus)); + + /* + * Calculate reciprocal if we don't have it + */ + calcX1OrderPlusRecip(cp); + curveOrderJustifyWithRecip(g, cp->x1OrderPlus, cp->x1OrderPlusRecip); +} + +/* + * g := g mod x1OrderPlus. Result may be zero. + */ +void x1OrderPlusMod(giant g, curveParams *cp) +{ + CKASSERT(!isZero(cp->x1OrderPlus)); + + /* + * Calculate reciprocal if we don't have it + */ + calcX1OrderPlusRecip(cp); + modg_via_recip(cp->x1OrderPlus, cp->x1OrderPlusRecip, g); +} + +/* + * New general-purpose giant mod routine, 8 Jan 97. + * x := x mod basePrime. + */ + +/* + * This stuff is used to analyze the critical loop behavior inside feemod(). + */ +#define FEEMOD_LOOP_TEST 0 +#if FEEMOD_LOOP_TEST +/* + * these two are only examined via debugger + */ +unsigned feemodCalls = 0; // calls to feemod() +unsigned feemodMultLoops = 0; // times while() loop runs > once +#define FEEMOD_LOOP_INCR feemodLoops++ +#define FEEMOD_CALL_INCR feemodCalls++ +#else // FEEMOD_LOOP_TEST +#define FEEMOD_LOOP_INCR +#define FEEMOD_CALL_INCR +#endif // FEEMOD_LOOP_TEST + + +void +feemod(curveParams *par, giant x) +{ + int sign, sign2; + giant t1; + giant t3; + giant t4; + giant t5; + #if FEEMOD_LOOP_TEST + unsigned feemodLoops = 0; + #endif // FEEMOD_LOOP_TEST + + FEEMOD_CALL_INCR; // for FEEMOD_LOOP_TEST + INCR_FEEMODS; // for ellipticMeasure + PROF_INCR(numFeemod); // for general profiling + + switch(par->primeType) { + case FPT_Mersenne: + /* + * Super-optimized Mersenne prime modulus case + */ + gmersennemod(par->q, x); + break; + + case FPT_FEE: + /* + * General 2**q-k case + */ + sign = (x->sign < 0) ? -1 : 1; + sign2 = 1; + x->sign = abs(x->sign); + if(gcompg(par->basePrime, x) >= 0) { + goto outFee; + } + t1 = borrowGiant(par->maxDigits); + t3 = borrowGiant(par->maxDigits); + t4 = borrowGiant(par->maxDigits); + t5 = borrowGiant(par->maxDigits); + + /* Begin OPT: 11 Jan 98 REC. */ + if( ((par->q & (GIANT_BITS_PER_DIGIT - 1)) == 0) && + (par->k >= 0) && + (par->k < GIANT_DIGIT_MASK)) { + + /* + * Microscopic mod for certain regions of {q,k} + * parameter space. + */ + int j, digits, excess, max; + giantDigit carry; + giantDigit termHi; // double precision + giantDigit termLo; + giantDigit *p1, *p2; + + digits = par->q >> GIANT_LOG2_BITS_PER_DIGIT; + while(bitlen(x) > par->q) { + excess = (x->sign) - digits; + max = (excess > digits) ? excess : digits; + carry = 0; + + p1 = &x->n[0]; + p2 = &x->n[digits]; + + if(excess <= digits) { + carry = VectorMultiply(par->k, + p2, + excess, + p1); + + /* propagate final carry */ + p1 += excess; + for(j = excess; j < digits; j++) { + + /* + * term = *p1 + carry; + * *p1++ = term & 65535; + * carry = term >> 16; + */ + termLo = giantAddDigits(*p1, carry, &carry); + *p1++ = termLo; + } + } else { + carry = VectorMultiply(par->k, + p2, + digits, + p1); + p1 += digits; + p2 += digits; + for(j = digits; j < excess; j++) { + /* + * term = (par->k)*(*p2++) + carry; + */ + giantMulDigits(par->k, + *p2++, + &termLo, + &termHi); + giantAddDouble(&termLo, &termHi, carry); + + /* + * *p1++ = term & 65535; + * carry = term >> 16; + */ + *p1++ = termLo; + carry = termHi; + } + } + + if(carry > 0) { + x->n[max] = carry; + } else { + while(--max){ + if(x->n[max] != 0) break; + } + } + x->sign = max + 1; + FEEMOD_LOOP_INCR; + } + } else { /* Macroscopic mod for general PT_FEE case. */ + int_to_giant(par->k, t4); + while(bitlen(x) > par->q) { + /* Enter fast loop, as in FEE patent. */ + int_to_giant(1, t5); + gtog(x, t3); + extractbits(par->q, t3, x); + while(bitlen(t3) > par->q) { + gshiftright(par->q, t3); + extractbits(par->q, t3, t1); + PAUSE_ELL_MEASURE; + mulg(t4, t5); + mulg(t5, t1); + RESUME_ELL_MEASURE; + addg(t1, x); + } + FEEMOD_LOOP_INCR; + } + } + /* End OPT: 11 Jan 98 REC. */ + + sign2 = (x->sign < 0)? -1: 1; + x->sign = abs(x->sign); + returnGiant(t1); + returnGiant(t3); + returnGiant(t4); + returnGiant(t5); + outFee: + if(gcompg(x, par->basePrime) >=0) subg(par->basePrime, x); + if(sign != sign2) { + giant t2 = borrowGiant(par->maxDigits); + gtog(par->basePrime, t2); + subg(x, t2); + gtog(t2, x); + returnGiant(t2); + } + break; + /* end case PT_FEE */ + + case FPT_General: + /* + * Use brute-force modg. + */ + #if FEE_DEBUG + if(par->basePrimeRecip == NULL) { + CKRaise("feemod(PT_GENERAL): No basePrimeRecip!\n"); + } + #endif /* FEE_DEBUG */ + modg_via_recip(par->basePrime, par->basePrimeRecip, x); + break; + + case FPT_Default: + /* never appears here */ + CKASSERT(0); + break; + } /* switch primeType */ + + #if FEEMOD_LOOP_TEST + if(feemodLoops > 1) { + feemodMultLoops++; + if(feemodLoops > 2) { + printf("feemod while loop executed %d times\n", feemodLoops); + } + } + #endif // FEEMOD_LOOP_TEST + + return; +} + +/* + * For a given curveParams, calculate minBytes and maxDigits. + * Assumes valid primeType, and also a valid basePrime for PT_GENERAL. + */ +void calcGiantSizes(curveParams *cp) +{ + + if(cp->primeType == FPT_General) { + cp->minBytes = (bitlen(cp->basePrime) + 7) / 8; + } + else { + cp->minBytes = giantMinBytes(cp->q, cp->k); + } + cp->maxDigits = giantMaxDigits(cp->minBytes); +} + +unsigned giantMinBytes(unsigned q, int k) +{ + unsigned kIsNeg = (k < 0) ? 1 : 0; + + return (q + 7 + kIsNeg) / 8; +} + +/* + * min value for "extra" bytes. Derived from the fact that during sig verify, + * we have to multiply a giant representing a digest - which may be + * 20 bytes for SHA1 - by a giant of minBytes. + */ +#define MIN_EXTRA_BYTES 20 + +unsigned giantMaxDigits(unsigned minBytes) +{ + unsigned maxBytes = 4 * minBytes; + + if((maxBytes - minBytes) < MIN_EXTRA_BYTES) { + maxBytes = minBytes + MIN_EXTRA_BYTES; + } + return BYTES_TO_GIANT_DIGITS(maxBytes); +} + + +/* + * Optimized binvg(basePrime, x). Avoids the general modg() in favor of + * feemod. + */ +int binvg_cp(curveParams *cp, giant x) +{ + feemod(cp, x); + return(binvaux(cp->basePrime, x)); +} + +/* + * Optimized binvg(x1OrderPlus, x). Uses x1OrderPlusMod(). + */ +int binvg_x1OrderPlus(curveParams *cp, giant x) +{ + x1OrderPlusMod(x, cp); + return(binvaux(cp->x1OrderPlus, x)); +} diff --git a/libsecurity_cryptkit/lib/elliptic.h b/libsecurity_cryptkit/lib/elliptic.h new file mode 100644 index 00000000..04d2383d --- /dev/null +++ b/libsecurity_cryptkit/lib/elliptic.h @@ -0,0 +1,165 @@ +/* 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. + *************************************************************************** + * + * elliptic.h - Fast Elliptic Encryption functions. + * + * Revision History + * ---------------- + * 10/06/98 ap + * Changed to compile with C++. + * 19 Feb 97 Doug Mitchell at NeXT + * Created. + */ + +#ifndef _CK_NSFEE_H_ +#define _CK_NSFEE_H_ + +#include "giantIntegers.h" +#include "feeTypes.h" +#include "curveParams.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Twist, or "which curve", parameter. + */ +#define CURVE_PLUS ((int)1) +#define CURVE_MINUS ((int)(-1)) + +typedef struct { + int twist; // CURVE_PLUS or CURVE_MINUS + giant x; // x coord of public key + + /* + * only valid for (twist == CURVE_PLUS) and curveType CT_WEIERSTRASS. + * Otherwise it's a zero-value giant. + */ + giant y; // y coord of public key + + /* + * Note: this module never allocs or frees a curveParams structs. + * This field is always maintained by clients of this module. + */ + curveParams *cp; // common curve parameters +} keystruct; + +typedef keystruct *key; + +/* + * Select which curve is the default curve for calculating signatures and + * doing key exchange. This *must* be CURVE_PLUS for key exchange to work + * with ECDSA keys and curves. + */ +#define DEFAULT_CURVE CURVE_PLUS + +key new_public(curveParams *cp, int twist); + +/* + * Specify private data for key created by new_public(). + * Generates k->x. + */ +void set_priv_key_giant(key k, giant privGiant); + +/* + * Generate new key with twist and k->x from old_key. + */ +key new_public_with_key(key old_key, curveParams *cp); + +/* + * Returns 1 if all parameters of two keys are equal, else returns 0. + */ +int key_equal(key first, key second); + +/* + * De-allocate an allocated key. + */ +void free_key(key pub); + +/* + * x3 = x1 + x2 on the curve, with sign ambiguity s. + * + * Note that int s is not just the twist field, because both s = +-1 must + * be tested in general. + */ +void elliptic_add(giant x1, giant x2, giant x3, curveParams *par, int s); + +/* + * Values for the 's', or sign, argument to elliptic_add(). + */ +#define SIGN_PLUS 1 +#define SIGN_MINUS (-1) + + +/* + * Elliptic multiply: x := n * {x, 1} + */ +void elliptic_simple(giant x, giant n, curveParams *par); + +/* + * General elliptic multiply: {xx, zz} := k * {xx, zz} + */ +void elliptic(giant xx, giant zz, giant k, curveParams *par); + +/* + * Returns CURVE_PLUS or CURVE_MINUS, indicating which curve a particular + * x coordinate resides on. + */ +int which_curve(giant x, curveParams *par); + +/* + * Generate (2**q)-k. + */ +void make_base_prim(curveParams *cp); + +/* + * return a new giant that is the pad from private data and public key + */ +giant make_pad(giant privGiant, key publicKey); + +/* + * Returns non-zero if x(p1) cannot be the x-coordinate of the + * sum of two points whose respective x-coordinates are x(p2), x(p3). + */ +int signature_compare(giant p0x, giant p1x, giant p2x, curveParams *par); + +/* + * Set g := g mod curveOrder; + * force g to be between 2 and (curveOrder-2), inclusive. + */ +void curveOrderJustify(giant g, giant curveOrder); + +void lesserX1OrderJustify(giant g, curveParams *cp); +void x1OrderPlusJustify(giant g, curveParams *cp); +void x1OrderPlusMod(giant g, curveParams *cp); + +void calcX1OrderPlusRecip(curveParams *cp); + +/* + * x := x mod basePrime. + */ +void feemod(curveParams *par, giant x); + +/* + * For a given curveParams, calculate minBytes and maxDigits. + */ +void calcGiantSizes(curveParams *cp); +unsigned giantMinBytes(unsigned q, int k); +unsigned giantMaxDigits(unsigned minBytes); + +int binvg_cp(curveParams *cp, giant x); +int binvg_x1OrderPlus(curveParams *cp, giant x); + +#ifdef __cplusplus +} +#endif + +#endif /*_CK_NSFEE_H_*/ diff --git a/libsecurity_cryptkit/lib/ellipticMeasure.h b/libsecurity_cryptkit/lib/ellipticMeasure.h new file mode 100644 index 00000000..73c614f9 --- /dev/null +++ b/libsecurity_cryptkit/lib/ellipticMeasure.h @@ -0,0 +1,86 @@ +/* + File: ellipticMeasure.h + + Contains: xxx put contents here xxx + + Written by: Doug Mitchell + + Copyright: Copyright 1998 by 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 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. + *************************************************************************** + * + * Measurement of feemods and mulgs withing an elliptic_simple() call. + */ + +#include "feeDebug.h" + +#ifdef FEE_DEBUG +#define ELLIPTIC_MEASURE 0 +#else // FEE_DEBUG +#define ELLIPTIC_MEASURE 0 /* always off */ +#endif // FEE_DEBUG + +#if ELLIPTIC_MEASURE + +extern int doEllMeasure; // gather stats on/off */ +extern int bitsInN; +extern int numFeeMods; +extern int numMulgs; + +#define START_ELL_MEASURE(n) \ + doEllMeasure = 1; \ + bitsInN = bitlen(n); \ + numFeeMods = 0; \ + numMulgs = 0; + +#define END_ELL_MEASURE doEllMeasure = 0; + +#define INCR_FEEMODS \ + if(doEllMeasure) { \ + numFeeMods++; \ + } + +#define INCR_MULGS \ + if(doEllMeasure) { \ + numMulgs++; \ + } + +/* + * These two are used around mulg() calls in feemod() itself; they + * inhibit the counting of those mulg() calls. + */ +#define PAUSE_ELL_MEASURE \ + { \ + int tempEllMeasure = doEllMeasure; \ + doEllMeasure = 0; + +#define RESUME_ELL_MEASURE \ + doEllMeasure = tempEllMeasure; \ + } + +#else // ELLIPTIC_MEASURE + +#define START_ELL_MEASURE(n) +#define END_ELL_MEASURE +#define INCR_FEEMODS +#define INCR_MULGS +#define PAUSE_ELL_MEASURE +#define RESUME_ELL_MEASURE + +#endif // ELLIPTIC_MEASURE diff --git a/libsecurity_cryptkit/lib/ellipticProj.c b/libsecurity_cryptkit/lib/ellipticProj.c new file mode 100644 index 00000000..d4d3ada5 --- /dev/null +++ b/libsecurity_cryptkit/lib/ellipticProj.c @@ -0,0 +1,566 @@ +/* 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. + *************************************************************************** + * + * ellipticProj.c - elliptic projective algebra routines. + * + * Revision History + * ---------------- + * 1 Sep 1998 Doug Mitchell and Richard Crandall at Apple + * Created. + * + ************************************************************** + + PROJECTIVE FORMAT + + Functions are supplied herein for projective format + of points. Alternative formats differ in their + range of applicability, efficiency, and so on. + Primary advantages of the projective format herein are: + -- No explicit inversions (until perhaps one such at the end of + an elliptic multiply operation) + -- Fairly low operation count (~11 muls for point doubling, + ~16 muls for point addition) + + The elliptic curve is over F_p, with p > 3 prime, and Weierstrass + parameterization: + + y^2 = x^3 + a x + b + + The projective-format coordinates are actually stored in + the form {X, Y, Z}, with true x,y + coordinates on the curve given by {x,y} = {X/Z^2, Y/Z^3}. + The function normalizeProj() performs the + transformation from projective->true. + (The other direction is trivial, i.e. {x,y} -> {x,y,1} will do.) + The basic point multiplication function is + + ellMulProj() + + which obtains the result k * P for given point P and integer + multiplier k. If true {x,y} are required for a multiple, one + passes a point P = {X, Y, 1} to ellMulProj(), then afterwards + calls normalizeProj(), + + Projective format is an answer to the typical sluggishness of + standard elliptic arithmetic, whose explicit inversion in the + field is, depending of course on the machinery and programmer, + costly. Projective format is thus especially interesting for + cryptography. + + REFERENCES + + Crandall R and Pomerance C 1998, "Prime numbers: a computational + perspective," Springer-Verlag, manuscript + + Solinas J 1998, IEEE P1363 Annex A (draft standard) + +***********************************************************/ + +#include "ckconfig.h" +#if CRYPTKIT_ELL_PROJ_ENABLE + +#include "ellipticProj.h" +#include "falloc.h" +#include "curveParams.h" +#include "elliptic.h" +#include "feeDebug.h" + +/* + * convert REC-style smulg to generic imulg + */ +#define smulg(s, g) imulg((unsigned)s, g) + +pointProj newPointProj(unsigned numDigits) +{ + pointProj pt; + + pt = (pointProj) fmalloc(sizeof(pointProjStruct)); + pt->x = newGiant(numDigits); + pt->y = newGiant(numDigits); + pt->z = newGiant(numDigits); + return(pt); +} + +void freePointProj(pointProj pt) +{ + clearGiant(pt->x); freeGiant(pt->x); + clearGiant(pt->y); freeGiant(pt->y); + clearGiant(pt->z); freeGiant(pt->z); + ffree(pt); +} + +void ptopProj(pointProj pt1, pointProj pt2) +{ + gtog(pt1->x, pt2->x); + gtog(pt1->y, pt2->y); + gtog(pt1->z, pt2->z); +} + +/************************************************************** + * + * Elliptic curve operations + * + **************************************************************/ + +/* Begin projective-format functions for + + y^2 = x^3 + a x + b. + + These are useful in elliptic curve cryptography (ECC). + A point is kept as a triple {X,Y,Z}, with the true (x,y) + coordinates given by + + {x,y} = {X/Z^2, Y/Z^3} + + The function normalizeProj() performs the inverse conversion to get + the true (x,y) pair. + */ + +void ellDoubleProj(pointProj pt, curveParams *cp) +/* pt := 2 pt on the curve. */ +{ + giant x = pt->x, y = pt->y, z = pt->z; + giant t1; + giant t2; + giant t3; + + if(isZero(y) || isZero(z)) { + int_to_giant(1,x); int_to_giant(1,y); int_to_giant(0,z); + return; + } + t1 = borrowGiant(cp->maxDigits); + t2 = borrowGiant(cp->maxDigits); + t3 = borrowGiant(cp->maxDigits); + + if((cp->a->sign >= 0) || (cp->a->n[0] != 3)) { /* Path prior to Apr2001. */ + gtog(z,t1); gsquare(t1); feemod(cp, t1); + gsquare(t1); feemod(cp, t1); + mulg(cp->a, t1); feemod(cp, t1); /* t1 := a z^4. */ + gtog(x, t2); gsquare(t2); feemod(cp, t2); + smulg(3, t2); /* t2 := 3x^2. */ + addg(t2, t1); feemod(cp, t1); /* t1 := slope m. */ + } else { /* New optimization for a = -3 (post Apr 2001). */ + gtog(z, t1); gsquare(t1); feemod(cp, t1); /* t1 := z^2. */ + gtog(x, t2); subg(t1, t2); /* t2 := x-z^2. */ + addg(x, t1); smulg(3, t1); /* t1 := 3(x+z^2). */ + mulg(t2, t1); feemod(cp, t1); /* t1 := slope m. */ + } + mulg(y, z); addg(z,z); feemod(cp, z); /* z := 2 y z. */ + gtog(y, t2); gsquare(t2); feemod(cp, t2); /* t2 := y^2. */ + gtog(t2, t3); gsquare(t3); feemod(cp, t3); /* t3 := y^4. */ + gshiftleft(3, t3); /* t3 := 8 y^4. */ + mulg(x, t2); gshiftleft(2, t2); feemod(cp, t2); /* t2 := 4xy^2. */ + gtog(t1, x); gsquare(x); feemod(cp, x); + subg(t2, x); subg(t2, x); feemod(cp, x); /* x done. */ + gtog(t1, y); subg(x, t2); mulg(t2, y); subg(t3, y); + feemod(cp, y); + returnGiant(t1); + returnGiant(t2); + returnGiant(t3); +} + +void ellAddProj(pointProj pt0, pointProj pt1, curveParams *cp) +/* pt0 := pt0 + pt1 on the curve. */ +{ + giant x0 = pt0->x, y0 = pt0->y, z0 = pt0->z, + x1 = pt1->x, y1 = pt1->y, z1 = pt1->z; + giant t1; + giant t2; + giant t3; + giant t4; + giant t5; + giant t6; + giant t7; + + if(isZero(z0)) { + gtog(x1,x0); gtog(y1,y0); gtog(z1,z0); + return; + } + if(isZero(z1)) return; + + t1 = borrowGiant(cp->maxDigits); + t2 = borrowGiant(cp->maxDigits); + t3 = borrowGiant(cp->maxDigits); + t4 = borrowGiant(cp->maxDigits); + t5 = borrowGiant(cp->maxDigits); + t6 = borrowGiant(cp->maxDigits); + t7 = borrowGiant(cp->maxDigits); + + gtog(x0, t1); gtog(y0,t2); gtog(z0, t3); + gtog(x1, t4); gtog(y1, t5); + if(!isone(z1)) { + gtog(z1, t6); + gtog(t6, t7); gsquare(t7); feemod(cp, t7); + mulg(t7, t1); feemod(cp, t1); + mulg(t6, t7); feemod(cp, t7); + mulg(t7, t2); feemod(cp, t2); + } + gtog(t3, t7); gsquare(t7); feemod(cp, t7); + mulg(t7, t4); feemod(cp, t4); + mulg(t3, t7); feemod(cp, t7); + mulg(t7, t5); feemod(cp, t5); + negg(t4); addg(t1, t4); feemod(cp, t4); + negg(t5); addg(t2, t5); feemod(cp, t5); + if(isZero(t4)) { + if(isZero(t5)) { + ellDoubleProj(pt0, cp); + } else { + int_to_giant(1, x0); int_to_giant(1, y0); + int_to_giant(0, z0); + } + goto out; + } + addg(t1, t1); subg(t4, t1); feemod(cp, t1); + addg(t2, t2); subg(t5, t2); feemod(cp, t2); + if(!isone(z1)) { + mulg(t6, t3); feemod(cp, t3); + } + mulg(t4, t3); feemod(cp, t3); + gtog(t4, t7); gsquare(t7); feemod(cp, t7); + mulg(t7, t4); feemod(cp, t4); + mulg(t1, t7); feemod(cp, t7); + gtog(t5, t1); gsquare(t1); feemod(cp, t1); + subg(t7, t1); feemod(cp, t1); + subg(t1, t7); subg(t1, t7); feemod(cp, t7); + mulg(t7, t5); feemod(cp, t5); + mulg(t2, t4); feemod(cp, t4); + gtog(t5, t2); subg(t4,t2); feemod(cp, t2); + if(t2->n[0] & 1) { /* Test if t2 is odd. */ + addg(cp->basePrime, t2); + } + gshiftright(1, t2); + gtog(t1, x0); gtog(t2, y0); gtog(t3, z0); +out: + returnGiant(t1); + returnGiant(t2); + returnGiant(t3); + returnGiant(t4); + returnGiant(t5); + returnGiant(t6); + returnGiant(t7); +} + + +void ellNegProj(pointProj pt, curveParams *cp) +/* pt := -pt on the curve. */ +{ + negg(pt->y); feemod(cp, pt->y); +} + +void ellSubProj(pointProj pt0, pointProj pt1, curveParams *cp) +/* pt0 := pt0 - pt1 on the curve. */ +{ + ellNegProj(pt1, cp); + ellAddProj(pt0, pt1,cp); + ellNegProj(pt1, cp); +} + +/* + * Simple projective multiply. + * + * pt := pt * k, result normalized. + */ +void ellMulProjSimple(pointProj pt0, giant k, curveParams *cp) +{ + pointProjStruct pt1; // local, giants borrowed + + CKASSERT(isone(pt0->z)); + CKASSERT(cp->curveType == FCT_Weierstrass); + + /* ellMulProj assumes constant pt0, can't pass as src and dst */ + pt1.x = borrowGiant(cp->maxDigits); + pt1.y = borrowGiant(cp->maxDigits); + pt1.z = borrowGiant(cp->maxDigits); + ellMulProj(pt0, &pt1, k, cp); + normalizeProj(&pt1, cp); + CKASSERT(isone(pt1.z)); + + ptopProj(&pt1, pt0); + returnGiant(pt1.x); + returnGiant(pt1.y); + returnGiant(pt1.z); +} + +void ellMulProj(pointProj pt0, pointProj pt1, giant k, curveParams *cp) +/* General elliptic multiplication; + pt1 := k*pt0 on the curve, + with k an arbitrary integer. + */ +{ + giant x = pt0->x, y = pt0->y, z = pt0->z, + xx = pt1->x, yy = pt1->y, zz = pt1->z; + int ksign, hlen, klen, b, hb, kb; + giant t0; + + CKASSERT(cp->curveType == FCT_Weierstrass); + if(isZero(k)) { + int_to_giant(1, xx); + int_to_giant(1, yy); + int_to_giant(0, zz); + return; + } + t0 = borrowGiant(cp->maxDigits); + ksign = k->sign; + if(ksign < 0) negg(k); + gtog(x,xx); gtog(y,yy); gtog(z,zz); + gtog(k, t0); addg(t0, t0); addg(k, t0); /* t0 := 3k. */ + hlen = bitlen(t0); + klen = bitlen(k); + for(b = hlen-2; b > 0; b--) { + ellDoubleProj(pt1,cp); + hb = bitval(t0, b); + if(b < klen) kb = bitval(k, b); else kb = 0; + if((hb != 0) && (kb == 0)) + ellAddProj(pt1, pt0, cp); + else if((hb == 0) && (kb !=0)) + ellSubProj(pt1, pt0, cp); + } + if(ksign < 0) { + ellNegProj(pt1, cp); + k->sign = -k->sign; + } + returnGiant(t0); +} + +void normalizeProj(pointProj pt, curveParams *cp) +/* Obtain actual x,y coords via normalization: + {x,y,z} := {x/z^2, y/z^3, 1}. + */ + +{ giant x = pt->x, y = pt->y, z = pt->z; + giant t1; + + CKASSERT(cp->curveType == FCT_Weierstrass); + if(isZero(z)) { + int_to_giant(1,x); int_to_giant(1,y); + return; + } + t1 = borrowGiant(cp->maxDigits); + binvg_cp(cp, z); // was binvaux(p, z); + gtog(z, t1); + gsquare(z); feemod(cp, z); + mulg(z, x); feemod(cp, x); + mulg(t1, z); mulg(z, y); feemod(cp, y); + int_to_giant(1, z); + returnGiant(t1); +} + +static int +jacobi_symbol(giant a, curveParams *cp) +/* Standard Jacobi symbol (a/cp->basePrime). + basePrime must be odd, positive. */ +{ + int t = 1, u; + giant t5 = borrowGiant(cp->maxDigits); + giant t6 = borrowGiant(cp->maxDigits); + giant t7 = borrowGiant(cp->maxDigits); + int rtn; + + gtog(a, t5); feemod(cp, t5); + gtog(cp->basePrime, t6); + while(!isZero(t5)) { + u = (t6->n[0]) & 7; + while((t5->n[0] & 1) == 0) { + gshiftright(1, t5); + if((u==3) || (u==5)) t = -t; + } + gtog(t5, t7); gtog(t6, t5); gtog(t7, t6); + u = (t6->n[0]) & 3; + if(((t5->n[0] & 3) == 3) && ((u & 3) == 3)) t = -t; + modg(t6, t5); + } + if(isone(t6)) { + rtn = t; + } + else { + rtn = 0; + } + returnGiant(t5); + returnGiant(t6); + returnGiant(t7); + + return rtn; +} + +static void +powFp2(giant a, giant b, giant w2, giant n, curveParams *cp) +/* Perform powering in the field F_p^2: + a + b w := (a + b w)^n (mod p), where parameter w2 is a quadratic + nonresidue (formally equal to w^2). + */ +{ + int j; + giant t6; + giant t7; + giant t8; + giant t9; + + if(isZero(n)) { + int_to_giant(1,a); + int_to_giant(0,b); + return; + } + t6 = borrowGiant(cp->maxDigits); + t7 = borrowGiant(cp->maxDigits); + t8 = borrowGiant(cp->maxDigits); + t9 = borrowGiant(cp->maxDigits); + gtog(a, t8); gtog(b, t9); + for(j = bitlen(n)-2; j >= 0; j--) { + gtog(b, t6); + mulg(a, b); addg(b,b); feemod(cp, b); /* b := 2 a b. */ + gsquare(t6); feemod(cp, t6); + mulg(w2, t6); feemod(cp, t6); + gsquare(a); addg(t6, a); feemod(cp, a); + /* a := a^2 + b^2 w2. */ + if(bitval(n, j)) { + gtog(b, t6); mulg(t8, b); feemod(cp, b); + gtog(a, t7); mulg(t9, a); addg(a, b); feemod(cp, b); + mulg(t9, t6); feemod(cp, t6); + mulg(w2, t6); feemod(cp, t6); + mulg(t8, a); addg(t6, a); feemod(cp, a); + } + } + returnGiant(t6); + returnGiant(t7); + returnGiant(t8); + returnGiant(t9); + return; +} + +static void +powermodg( + giant x, + giant n, + curveParams *cp +) +/* x becomes x^n (mod basePrime). */ +{ + int len, pos; + giant scratch2 = borrowGiant(cp->maxDigits); + + gtog(x, scratch2); + int_to_giant(1, x); + len = bitlen(n); + pos = 0; + while (1) + { + if (bitval(n, pos++)) + { + mulg(scratch2, x); + feemod(cp, x); + } + if (pos>=len) + break; + gsquare(scratch2); + feemod(cp, scratch2); + } + returnGiant(scratch2); +} + +static int sqrtmod(giant x, curveParams *cp) +/* If Sqrt[x] (mod p) exists, function returns 1, else 0. + In either case x is modified, but if 1 is returned, + x:= Sqrt[x] (mod p). + */ +{ + int rtn; + giant t0 = borrowGiant(cp->maxDigits); + giant t1 = borrowGiant(cp->maxDigits); + giant t2 = borrowGiant(cp->maxDigits); + giant t3 = borrowGiant(cp->maxDigits); + giant t4 = borrowGiant(cp->maxDigits); + + giant p = cp->basePrime; + + feemod(cp, x); /* Justify the argument. */ + gtog(x, t0); /* Store x for eventual validity check on square root. */ + if((p->n[0] & 3) == 3) { /* The case p = 3 (mod 4). */ + gtog(p, t1); + iaddg(1, t1); gshiftright(2, t1); + powermodg(x, t1, cp); + goto resolve; + } + /* Next, handle case p = 5 (mod 8). */ + if((p->n[0] & 7) == 5) { + gtog(p, t1); int_to_giant(1, t2); + subg(t2, t1); gshiftright(2, t1); + gtog(x, t2); + powermodg(t2, t1, cp); /* t2 := x^((p-1)/4) % p. */ + iaddg(1, t1); + gshiftright(1, t1); /* t1 := (p+3)/8. */ + if(isone(t2)) { + powermodg(x, t1, cp); /* x^((p+3)/8) is root. */ + goto resolve; + } else { + int_to_giant(1, t2); subg(t2, t1); + /* t1 := (p-5)/8. */ + gshiftleft(2,x); + powermodg(x, t1, cp); + mulg(t0, x); addg(x, x); feemod(cp, x); + /* 2x (4x)^((p-5)/8. */ + goto resolve; + } + } + + /* Next, handle tougher case: p = 1 (mod 8). */ + int_to_giant(2, t1); + while(1) { /* Find appropriate nonresidue. */ + gtog(t1, t2); + gsquare(t2); subg(x, t2); feemod(cp, t2); + if(jacobi_symbol(t2, cp) == -1) break; + iaddg(1, t1); + } /* t2 is now w^2 in F_p^2. */ + int_to_giant(1, t3); + gtog(p, t4); iaddg(1, t4); gshiftright(1, t4); + powFp2(t1, t3, t2, t4, cp); + gtog(t1, x); + +resolve: + gtog(x,t1); gsquare(t1); feemod(cp, t1); + if(gcompg(t0, t1) == 0) { + rtn = 1; /* Success. */ + } + else { + rtn = 0; /* no square root */ + } + returnGiant(t0); + returnGiant(t1); + returnGiant(t2); + returnGiant(t3); + returnGiant(t4); + return rtn; +} + + +void findPointProj(pointProj pt, giant seed, curveParams *cp) +/* Starting with seed, finds a random (projective) point {x,y,1} on curve. + */ +{ + giant x = pt->x, y = pt->y, z = pt->z; + + CKASSERT(cp->curveType == FCT_Weierstrass); + feemod(cp, seed); + while(1) { + gtog(seed, x); + gsquare(x); feemod(cp, x); // x := seed^2 + addg(cp->a, x); // x := seed^2 + a + mulg(seed,x); // x := seed^3 + a*seed + addg(cp->b, x); + feemod(cp, x); // x := seed^3 + a seed + b. + /* test cubic form for having root. */ + if(sqrtmod(x, cp)) break; + iaddg(1, seed); + } + gtog(x, y); + gtog(seed,x); + int_to_giant(1, z); +} + +#endif /* CRYPTKIT_ELL_PROJ_ENABLE */ diff --git a/libsecurity_cryptkit/lib/ellipticProj.h b/libsecurity_cryptkit/lib/ellipticProj.h new file mode 100644 index 00000000..3dfc3288 --- /dev/null +++ b/libsecurity_cryptkit/lib/ellipticProj.h @@ -0,0 +1,76 @@ +/* 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. + *************************************************************************** + * + * ellipticProj.h - declaration of elliptic projective algebra routines. + * + * Revision History + * ---------------- + * 10/06/98 ap + * Changed to compile with C++. + * 1 Sep 1998 Doug Mitchell at Apple + * Created. + */ + +#ifndef _CRYPTKIT_ELLIPTIC_PROJ_H_ +#define _CRYPTKIT_ELLIPTIC_PROJ_H_ + +#include "ckconfig.h" + +#if CRYPTKIT_ELL_PROJ_ENABLE + +#include "giantIntegers.h" +#include "curveParams.h" + +/* + * A projective point. + */ +typedef struct { + giant x; + giant y; + giant z; +} pointProjStruct; + +typedef pointProjStruct *pointProj; + +pointProj /* Allocates a new projective point. */ +newPointProj(unsigned numDigits); + +void /* Frees point. */ +freePointProj(pointProj pt); + +void /* Copies point to point; pt2 := pt1. */ +ptopProj(pointProj pt1, pointProj pt2); + +void /* Point doubling. */ +ellDoubleProj(pointProj pt, curveParams *cp); + +void /* Point adding; pt0 := pt0 - pt1. */ +ellAddProj(pointProj pt0, pointProj pt1, curveParams *cp); + +void /* Point negation; pt := -pt. */ +ellNegProj(pointProj pt, curveParams *cp); + +void /* Point subtraction; pt0 := pt0 - pt1. */ +ellSubProj(pointProj pt0, pointProj pt1, curveParams *cp); + +void /* pt := pt * k, result normalized */ +ellMulProjSimple(pointProj pt0, giant k, curveParams *cp); + +void /* General elliptic mul; pt1 := k*pt0. */ +ellMulProj(pointProj pt0, pointProj pt1, giant k, curveParams *cp); + +void /* Generate normalized point (X, Y, 1) from given (x,y,z). */ +normalizeProj(pointProj pt, curveParams *cp); + +void /* Find a point (x, y, 1) on the curve. */ +findPointProj(pointProj pt, giant seed, curveParams *cp); + +#endif /* CRYPTKIT_ELL_PROJ_ENABLE*/ +#endif /* _CRYPTKIT_ELLIPTIC_PROJ_H_ */ diff --git a/libsecurity_cryptkit/lib/enc64.c b/libsecurity_cryptkit/lib/enc64.c new file mode 100644 index 00000000..46de4710 --- /dev/null +++ b/libsecurity_cryptkit/lib/enc64.c @@ -0,0 +1,417 @@ +/* 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. + *************************************************************************** + * + * enc64.c - encode/decode in 64-char IA5 format, per RFC 1421 + * + * Revision History + * ---------------- + * 11/27/98 dmitch + * Added ECDSA_VERIFY_ONLY dependencies. + * 10/06/98 ap + * Changed to compile with C++. + * 12 Dec 96 Doug Mitchell at NeXT + * Newlines optional in dec64() and isValidEnc64(). + * 9 Oct 96 Doug Mitchell at NeXT + * Created. + */ + +#include "enc64.h" +#include "falloc.h" + +/* + * 11/27/98 dmitch: The ECDSA_VERIFY_ONLY symbol, when #defined, disables all + * of the code in this module except that which is necessary for ECDSA + * siggnature verification. + */ + +#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 '=' +//#define ENC_LINE_LEN 64 + +#ifndef ECDSA_VERIFY_ONLY + +/* + * 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 *enc64(const unsigned char *inbuf, + unsigned inlen, + unsigned *outlen) // RETURNED +{ + return enc64WithLines(inbuf, inlen, 0, outlen); +} + +unsigned char *enc64WithLines(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. For Microsoft compatibility, + * we always generate newlines as \r\n; when decoding, we tolerate + * \r\n or \n. + */ + len = outTextLen + (2 * numLines) + 1; + outbuf = (unsigned char*) fmalloc(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++ = '\r'; + *outp++ = '\n'; + olen += 2; + thisLine = 0; + } + } + *outp++ = '\r'; + *outp++ = '\n'; + *outp = '\0'; + olen += 3; + *outlen = olen; + return outbuf; +} + +#endif /* ECDSA_VERIFY_ONLY */ + +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*) fmalloc(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; + } + ffree(news); + *outlen = olen; + return outbuf; /* normal return */ + +errorOut: + ffree(news); + ffree(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 isValidEnc64(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_cryptkit/lib/enc64.h b/libsecurity_cryptkit/lib/enc64.h new file mode 100644 index 00000000..bdf32cae --- /dev/null +++ b/libsecurity_cryptkit/lib/enc64.h @@ -0,0 +1,65 @@ +/* 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. + *************************************************************************** + * + * enc64.h - encode/decode in 64-char IA5 format, per RFC 1421 + * + * Revision History + * ---------------- + * 9 Oct 96 Doug Mitchell at NeXT + * Created. + */ + +#ifndef _CK_ENC64_H_ +#define _CK_ENC64_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Given input buffer inbuf, length inlen, decode from 64-char IA5 format to + * binary. Result is fmalloced and returned; its length is returned in *outlen. + * NULL return indicates corrupted input. + */ +unsigned char *enc64(const unsigned char *inbuf, + unsigned inlen, + unsigned *outlen); // RETURNED + +/* + * Enc64, with embedded newlines every lineLen in result. A newline is + * the Microsoft-style "\r\n". + */ +unsigned char *enc64WithLines(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 fmalloced and returned; its length is returned in *outlen. + * NULL return indicates corrupted input. All whitespace in inbuf is + * ignored. + */ +unsigned char *dec64(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 isValidEnc64(const unsigned char *inbuf, + unsigned inbufLen); + +#ifdef __cplusplus +} +#endif + +#endif /*_CK_ENC64_H_*/ diff --git a/libsecurity_cryptkit/lib/engineNSA127.c b/libsecurity_cryptkit/lib/engineNSA127.c new file mode 100644 index 00000000..2c0cc3a1 --- /dev/null +++ b/libsecurity_cryptkit/lib/engineNSA127.c @@ -0,0 +1,543 @@ +/* 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. + *************************************************************************** + + CONFIDENTIAL CONFIDENTIAL CONFIDENTIAL + engineNSA.c + + Security Engine code, to be compiled prior to software + distribution. The code performs the + elliptic curve algebra fundamental to the patented FEE + system. + + This Engine is designed to be virtually nonmalleable + with respect to key size. This is achieved herein + via hard-coding of numerical algorithms with respect to + the DEPTH = 4 security level (127 bit Mersenne prime). + + In meetings between the NSA and NeXT Software, Inc. in + 1995-1996, the notion of Security Engine emerged as a + means by which one could discourage disassembly of + FEE compilations, especially when such disassembly + has the sinister goal of modifying encryption depth. + + DO NOT EVEN THINK ABOUT READING THE SOURCE CODE + 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. +*/ + +/* This engine requires no initialization. There is one + function to becalled externally, namely elliptic(). + */ + + + + + + + + + + + + + + + + + + + +/* + * Revision History + * ---------------- + * 10/06/98 ap + * Changed to compile with C++. + * 6 Aug 06 Doug Mitchell at NeXT + * 'a' argument to elliptic() and ell_even() is now a giant. + * 25 Jul 96 Richard Crandall and Doug Mitchell 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 + * 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 + * Created. + */ + +#include "ckconfig.h" + +#if ENGINE_127_BITS +/* + * This file is obsolete as of 8 January 1997. + */ +#error Hey! New curveParam-dependent 127-bit elliptic() needed! +#warning Using NSA-approved 127-bit security engine... + +#include "NSGiantIntegers.h" + +#define D 65536 +#define DM 65535 + +/* + * Size of 127-bit giantstruct n[] array, in shorts. + */ +#define SHORTCOUNT (8 * 2) +#define BORROW_SIZE 0 + + +static void +ENGINEmul(giant a, giant b) { + int a0,a1,a2,a3,a4,a5,a6,a7, + b0,b1,b2,b3,b4,b5,b6,b7; + int asign, bsign; + int i, j, car; + unsigned int prod; + unsigned short mult; + + gmersennemod(127, a); + gmersennemod(127, b); + asign = a->sign; + bsign = b->sign; + + for(j = abs(asign); j < SHORTCOUNT; j++) a->n[j] = 0; + for(j = abs(bsign); j < SHORTCOUNT; j++) b->n[j] = 0; + a0 = a->n[0]; + a1 = a->n[1]; + a2 = a->n[2]; + a3 = a->n[3]; + a4 = a->n[4]; + a5 = a->n[5]; + a6 = a->n[6]; + a7 = a->n[7]; + b0 = b->n[0]; + b1 = b->n[1]; + b2 = b->n[2]; + b3 = b->n[3]; + b4 = b->n[4]; + b5 = b->n[5]; + b6 = b->n[6]; + b7 = b->n[7]; + for(j = 0; j < SHORTCOUNT; j++) b->n[j] = 0; + + i = 0; + mult = b0; + car = 0; + + prod = a0 * mult + b->n[i] + car; + b->n[i++] = prod & DM; + car = prod/D; + + prod = a1 * mult + b->n[i] + car; + b->n[i++] = prod & DM; + car = prod/D; + + prod = a2 * mult + b->n[i] + car; + b->n[i++] = prod & DM; + car = prod/D; + + prod = a3 * mult + b->n[i] + car; + b->n[i++] = prod & DM; + car = prod/D; + + prod = a4 * mult + b->n[i] + car; + b->n[i++] = prod & DM; + car = prod/D; + + prod = a5 * mult + b->n[i] + car; + b->n[i++] = prod & DM; + car = prod/D; + + prod = a6 * mult + b->n[i] + car; + b->n[i++] = prod & DM; + car = prod/D; + + prod = a7 * mult + b->n[i] + car; + b->n[i++] = prod & DM; + car = prod/D; + + b->n[i] = car; + + i = 1; + mult = b1; + car = 0; + + prod = a0 * mult + b->n[i] + car; + b->n[i++] = prod & DM; + car = prod/D; + + prod = a1 * mult + b->n[i] + car; + b->n[i++] = prod & DM; + car = prod/D; + + prod = a2 * mult + b->n[i] + car; + b->n[i++] = prod & DM; + car = prod/D; + + prod = a3 * mult + b->n[i] + car; + b->n[i++] = prod & DM; + car = prod/D; + + prod = a4 * mult + b->n[i] + car; + b->n[i++] = prod & DM; + car = prod/D; + + prod = a5 * mult + b->n[i] + car; + b->n[i++] = prod & DM; + car = prod/D; + + prod = a6 * mult + b->n[i] + car; + b->n[i++] = prod & DM; + car = prod/D; + + prod = a7 * mult + b->n[i] + car; + b->n[i++] = prod & DM; + car = prod/D; + + b->n[i] = car; + + i = 2; + mult = b2; + car = 0; + + prod = a0 * mult + b->n[i] + car; + b->n[i++] = prod & DM; + car = prod/D; + + prod = a1 * mult + b->n[i] + car; + b->n[i++] = prod & DM; + car = prod/D; + + prod = a2 * mult + b->n[i] + car; + b->n[i++] = prod & DM; + car = prod/D; + + prod = a3 * mult + b->n[i] + car; + b->n[i++] = prod & DM; + car = prod/D; + + prod = a4 * mult + b->n[i] + car; + b->n[i++] = prod & DM; + car = prod/D; + + prod = a5 * mult + b->n[i] + car; + b->n[i++] = prod & DM; + car = prod/D; + + prod = a6 * mult + b->n[i] + car; + b->n[i++] = prod & DM; + car = prod/D; + + prod = a7 * mult + b->n[i] + car; + b->n[i++] = prod & DM; + car = prod/D; + + b->n[i] = car; + + i = 3; + mult = b3; + car = 0; + + prod = a0 * mult + b->n[i] + car; + b->n[i++] = prod & DM; + car = prod/D; + + prod = a1 * mult + b->n[i] + car; + b->n[i++] = prod & DM; + car = prod/D; + + prod = a2 * mult + b->n[i] + car; + b->n[i++] = prod & DM; + car = prod/D; + + prod = a3 * mult + b->n[i] + car; + b->n[i++] = prod & DM; + car = prod/D; + + prod = a4 * mult + b->n[i] + car; + b->n[i++] = prod & DM; + car = prod/D; + + prod = a5 * mult + b->n[i] + car; + b->n[i++] = prod & DM; + car = prod/D; + + prod = a6 * mult + b->n[i] + car; + b->n[i++] = prod & DM; + car = prod/D; + + prod = a7 * mult + b->n[i] + car; + b->n[i++] = prod & DM; + car = prod/D; + + b->n[i] = car; + + i = 4; + mult = b4; + car = 0; + + prod = a0 * mult + b->n[i] + car; + b->n[i++] = prod & DM; + car = prod/D; + + prod = a1 * mult + b->n[i] + car; + b->n[i++] = prod & DM; + car = prod/D; + + prod = a2 * mult + b->n[i] + car; + b->n[i++] = prod & DM; + car = prod/D; + + prod = a3 * mult + b->n[i] + car; + b->n[i++] = prod & DM; + car = prod/D; + + prod = a4 * mult + b->n[i] + car; + b->n[i++] = prod & DM; + car = prod/D; + + prod = a5 * mult + b->n[i] + car; + b->n[i++] = prod & DM; + car = prod/D; + + prod = a6 * mult + b->n[i] + car; + b->n[i++] = prod & DM; + car = prod/D; + + prod = a7 * mult + b->n[i] + car; + b->n[i++] = prod & DM; + car = prod/D; + + b->n[i] = car; + + i = 5; + mult = b5; + car = 0; + + prod = a0 * mult + b->n[i] + car; + b->n[i++] = prod & DM; + car = prod/D; + + prod = a1 * mult + b->n[i] + car; + b->n[i++] = prod & DM; + car = prod/D; + + prod = a2 * mult + b->n[i] + car; + b->n[i++] = prod & DM; + car = prod/D; + + prod = a3 * mult + b->n[i] + car; + b->n[i++] = prod & DM; + car = prod/D; + + prod = a4 * mult + b->n[i] + car; + b->n[i++] = prod & DM; + car = prod/D; + + prod = a5 * mult + b->n[i] + car; + b->n[i++] = prod & DM; + car = prod/D; + + prod = a6 * mult + b->n[i] + car; + b->n[i++] = prod & DM; + car = prod/D; + + prod = a7 * mult + b->n[i] + car; + b->n[i++] = prod & DM; + car = prod/D; + + b->n[i] = car; + + i = 6; + mult = b6; + car = 0; + + prod = a0 * mult + b->n[i] + car; + b->n[i++] = prod & DM; + car = prod/D; + + prod = a1 * mult + b->n[i] + car; + b->n[i++] = prod & DM; + car = prod/D; + + prod = a2 * mult + b->n[i] + car; + b->n[i++] = prod & DM; + car = prod/D; + + prod = a3 * mult + b->n[i] + car; + b->n[i++] = prod & DM; + car = prod/D; + + prod = a4 * mult + b->n[i] + car; + b->n[i++] = prod & DM; + car = prod/D; + + prod = a5 * mult + b->n[i] + car; + b->n[i++] = prod & DM; + car = prod/D; + + prod = a6 * mult + b->n[i] + car; + b->n[i++] = prod & DM; + car = prod/D; + + prod = a7 * mult + b->n[i] + car; + b->n[i++] = prod & DM; + car = prod/D; + + b->n[i] = car; + + i = 7; + mult = b7; + car = 0; + + prod = a0 * mult + b->n[i] + car; + b->n[i++] = prod & DM; + car = prod/D; + + prod = a1 * mult + b->n[i] + car; + b->n[i++] = prod & DM; + car = prod/D; + + prod = a2 * mult + b->n[i] + car; + b->n[i++] = prod & DM; + car = prod/D; + + prod = a3 * mult + b->n[i] + car; + b->n[i++] = prod & DM; + car = prod/D; + + prod = a4 * mult + b->n[i] + car; + b->n[i++] = prod & DM; + car = prod/D; + + prod = a5 * mult + b->n[i] + car; + b->n[i++] = prod & DM; + car = prod/D; + + prod = a6 * mult + b->n[i] + car; + b->n[i++] = prod & DM; + car = prod/D; + + prod = a7 * mult + b->n[i] + car; + b->n[i++] = prod & DM; + car = prod/D; + + b->n[i] = car; + b->sign = abs(b->sign) + abs(a->sign); + for(j = (b->sign)-1; j >= 0; j--) { + if(b->n[j] != 0) { + break; + } + } + b->sign = j+1; + gmersennemod(127,b); +} + +static void +ell_even(giant x1, giant z1, giant x2, giant z2, giant a, int q) +{ + giant t1, t2, t3; + + t1 = borrowGiant(BORROW_SIZE); + t2 = borrowGiant(BORROW_SIZE); + t3 = borrowGiant(BORROW_SIZE); + + gtog(x1, t1); gsquare(t1); gmersennemod(q, t1); + gtog(z1, t2); gsquare(t2); gmersennemod(q, t2); + gtog(x1, t3); ENGINEmul(z1, t3); + gtog(t1, x2); subg(t2, x2); gsquare(x2); gmersennemod(q, x2); + gtog(a, z2); + ENGINEmul(t3, z2); + addg(t1, z2); addg(t2, z2); ENGINEmul(t3, z2); + gshiftleft(2, z2); + gmersennemod(q, z2); + + returnGiant(t1); + returnGiant(t2); + returnGiant(t3); +} + +static void +ell_odd(giant x1, giant z1, giant x2, giant z2, giant xor, giant zor, int q) +{ + giant t1, t2, t3; + + t1 = borrowGiant(BORROW_SIZE); + t2 = borrowGiant(BORROW_SIZE); + t3 = borrowGiant(BORROW_SIZE); + + gtog(x1, t1); subg(z1, t1); + gtog(x2, t2); addg(z2, t2); + ENGINEmul(t1, t2); + gtog(x1, t1); addg(z1, t1); + gtog(x2, t3); subg(z2, t3); + ENGINEmul(t3, t1); + gtog(t2, x2); addg(t1, x2); + gsquare(x2); gmersennemod(q, x2); //? + gtog(t2, z2); subg(t1, z2); + gsquare(z2); gmersennemod(q, z2); //? + ENGINEmul(zor, x2); + ENGINEmul(xor, z2); + + returnGiant(t1); + returnGiant(t2); + returnGiant(t3); +} + +/* Elliptic multiply. + For given curve parameter a and given prime p = 2^q-1, + the point (xx,zz) becomes k * (xx,zz), in place. + */ +void +elliptic(giant xx, giant zz, giant k, giant a, int q) +{ + int len = bitlen(k), pos = len-2; + giant xs; + giant zs; + giant xorg; + giant zorg; + + if(scompg(1,k)) return; + if(scompg(2,k)) { + ell_even(xx, zz, xx, zz, a, q); + return; + } + + zs = borrowGiant(BORROW_SIZE); + xs = borrowGiant(BORROW_SIZE); + zorg = borrowGiant(BORROW_SIZE); + xorg = borrowGiant(BORROW_SIZE); + + gtog(xx, xorg); gtog(zz, zorg); + ell_even(xx, zz, xs, zs, a, q); + do{ + if(bitval(k, pos--)) { + ell_odd(xs, zs, xx, zz, xorg, zorg, q); + ell_even(xs, zs, xs, zs, a, q); + } else { + ell_odd(xx, zz, xs, zs, xorg, zorg, q); + ell_even(xx, zz, xx, zz, a, q); + } + } while(pos >=0); + + returnGiant(xs); + returnGiant(zs); + returnGiant(xorg); + returnGiant(zorg); +} + +#endif /* ENGINE_127_BITS */ diff --git a/libsecurity_cryptkit/lib/falloc.c b/libsecurity_cryptkit/lib/falloc.c new file mode 100644 index 00000000..b19237c0 --- /dev/null +++ b/libsecurity_cryptkit/lib/falloc.c @@ -0,0 +1,109 @@ +/* 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. + *************************************************************************** + * + * falloc.c - FEE malloc routines + * + * Revision History + * ---------------- + * 28 May 98 Doug Mitchell at Apple + * Added Mac-specific allocators from temp memory + * 20 Aug 96 Doug Mitchell at NeXT + * Created. + */ + +#include "platform.h" +#include "falloc.h" +#include + +/* watchpoint emulator */ +#define FALLOC_WATCH 0 +#if FALLOC_WATCH +#include +/* set these with debugger */ +void *mallocWatchAddrs; +void *freeWatchAddrs; +#endif + +/* if NULL, use our own */ +static mallocExternFcn *mallocExt = NULL; +static freeExternFcn *freeExt = NULL; +static reallocExternFcn *reallocExt = NULL; + +void fallocRegister(mallocExternFcn *mallocExtern, + freeExternFcn *freeExtern, + reallocExternFcn *reallocExtern) +{ + mallocExt = mallocExtern; + freeExt = freeExtern; + reallocExt = reallocExtern; +} + +/* + * All this can be optimized and tailored to specific platforms, of course... + */ + +void *fmalloc(unsigned size) +{ + void *rtn; + if(mallocExt != NULL) { + rtn = (mallocExt)(size); + } + else { + rtn = malloc(size); + } + #if FALLOC_WATCH + if(rtn == mallocWatchAddrs) { + printf("====fmalloc watchpoint (0x%x) hit\n", + (unsigned)mallocWatchAddrs); + } + #endif + return rtn; +} + +void *fmallocWithData(const void *origData, + unsigned origDataLen) +{ + void *rtn = fmalloc(origDataLen); + + bcopy(origData, rtn, origDataLen); + return rtn; +} + +void ffree(void *data) +{ + #if FALLOC_WATCH + if(data == freeWatchAddrs) { + printf("====ffree watchpoint (0x%x) hit\n", + (unsigned)freeWatchAddrs); + } + #endif + if(freeExt != NULL) { + (freeExt)(data); + } + else { + free(data); + } +} + +void *frealloc(void *oldPtr, unsigned newSize) +{ + #if FALLOC_WATCH + if(oldPtr == freeWatchAddrs) { + printf("====frealloc watchpoint (0x%x) hit\n", + (unsigned)freeWatchAddrs); + } + #endif + if(reallocExt != NULL) { + return (reallocExt)(oldPtr, newSize); + } + else { + return realloc(oldPtr, newSize); + } +} diff --git a/libsecurity_cryptkit/lib/falloc.h b/libsecurity_cryptkit/lib/falloc.h new file mode 100644 index 00000000..56adfaef --- /dev/null +++ b/libsecurity_cryptkit/lib/falloc.h @@ -0,0 +1,47 @@ +/* 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. + *************************************************************************** + * + * falloc.h - FEE malloc routines + * + * Revision History + * ---------------- + * 20 Aug 96 Doug Mitchell at NeXT + * Created. + */ + +#ifndef _CK_FALLOC_H_ +#define _CK_FALLOC_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Clients can *optionally* register external memory alloc/free functions here. + */ +typedef void *(mallocExternFcn)(unsigned size); +typedef void (freeExternFcn)(void *data); +typedef void *(reallocExternFcn)(void *oldData, unsigned newSize); +void fallocRegister(mallocExternFcn *mallocExtern, + freeExternFcn *freeExtern, + reallocExternFcn *reallocExtern); + + +void *fmalloc(unsigned size); /* general malloc */ +void *fmallocWithData(const void *origData, + unsigned origDataLen); /* malloc, copy existing data */ +void ffree(void *data); /* general free */ +void *frealloc(void *oldPtr, unsigned newSize); + +#ifdef __cplusplus +} +#endif + +#endif /*_CK_FALLOC_H_*/ diff --git a/libsecurity_cryptkit/lib/feeCipherFile.c b/libsecurity_cryptkit/lib/feeCipherFile.c new file mode 100644 index 00000000..4edde3d4 --- /dev/null +++ b/libsecurity_cryptkit/lib/feeCipherFile.c @@ -0,0 +1,280 @@ +/* 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. + *************************************************************************** + * + * feeCipherFile.c - general cipherfile support + * + * Revision History + * ---------------- + * 05 Feb 97 Doug Mitchell at Apple + * Added CFE_FEED and CFE_FEEDExp types. + * 24 Oct 96 Doug Mitchell at NeXT + * Created. + */ + +#include "feeCipherFile.h" +#include "falloc.h" +#include "feeFEEDExp.h" +#include "feeFEED.h" +#include "feeDebug.h" +#include "CipherFileFEED.h" +#include "CipherFileDES.h" + + +/* + * Create a cipherfile of specified cipherFileEncrType. + */ +feeReturn createCipherFile(feePubKey sendPrivKey, + feePubKey recvPubKey, + cipherFileEncrType encrType, + const unsigned char *plainText, + unsigned plainTextLen, + int genSig, // 1 ==> generate signature + int doEnc64, // 1 ==> perform enc64 + unsigned userData, // for caller's convenience + unsigned char **cipherFileData, // RETURNED + unsigned *cipherFileDataLen) // RETURNED +{ + feeReturn frtn = FR_Success; + feeCipherFile cipherFile = NULL; + unsigned char *cipherData = NULL; + unsigned cipherDataLen; + + /* + * Dispatch to encrType-specific code. + */ + switch(encrType) { + case CFE_RandDES: + frtn = createRandDES(sendPrivKey, + recvPubKey, + plainText, + plainTextLen, + genSig, + userData, + &cipherFile); + break; + case CFE_PublicDES: + frtn = createPubDES(sendPrivKey, + recvPubKey, + plainText, + plainTextLen, + genSig, + userData, + &cipherFile); + break; + case CFE_FEED: + frtn = createFEED(sendPrivKey, + recvPubKey, + plainText, + plainTextLen, + genSig, + userData, + &cipherFile); + break; + case CFE_FEEDExp: + frtn = createFEEDExp(sendPrivKey, + recvPubKey, + plainText, + plainTextLen, + genSig, + userData, + &cipherFile); + break; + default: + frtn = FR_Unimplemented; + break; + } + + if(frtn) { + goto out; + } + + /* + * Common logic for all encrTypes + */ + + /* + * Get the cipherfile's raw data + */ + frtn = feeCFileDataRepresentation(cipherFile, + (const unsigned char **)&cipherData, + &cipherDataLen); + if(frtn) { + goto out; + } + + /* + * Optionally encode in 64-char ASCII + */ + if(doEnc64) { + *cipherFileData = enc64(cipherData, + cipherDataLen, + cipherFileDataLen); + ffree(cipherData); + if(*cipherFileData == NULL) { + frtn = FR_Internal; + ffree(cipherData); + goto out; + } + } + else { + *cipherFileData = cipherData; + *cipherFileDataLen = cipherDataLen; + } +out: + /* free stuff */ + if(cipherFile) { + feeCFileFree(cipherFile); + } + return frtn; +} + +/* + * Parse a cipherfile. + * + * sendPubKey only needed for cipherFileEncrType CFE_RandDES if signature + * is present. If sendPubKey is present, it will be used for signature + * validation rather than the embedded sender's public key. + */ +feeReturn parseCipherFile(feePubKey recvPrivKey, + feePubKey sendPubKey, + const unsigned char *cipherFileData, + unsigned cipherFileDataLen, + int doDec64, // 1 ==> perform dec64 + cipherFileEncrType *encrType, // RETURNED + unsigned char **plainText, // RETURNED + unsigned *plainTextLen, // RETURNED + feeSigStatus *sigStatus, // RETURNED + unsigned *userData) // RETURNED +{ + feeReturn frtn; + unsigned char *cipherData = NULL; + unsigned cipherDataLen; + int freeCipherData = 0; + feeCipherFile cipherFile = NULL; + + *plainText = NULL; + *plainTextLen = 0; + + if(recvPrivKey == NULL) { // always required + frtn = FR_BadPubKey; + goto out; + } + + /* + * First, optional dec64() + */ + if(doDec64) { + cipherData = dec64(cipherFileData, + cipherFileDataLen, + &cipherDataLen); + if(cipherData == NULL) { + frtn = FR_BadEnc64; + goto out; + } + else { + freeCipherData = 1; + } + } + else { + cipherData = (unsigned char *)cipherFileData; + cipherDataLen = cipherFileDataLen; + } + + /* + * Cons up a feeCipherFile object. + */ + frtn = feeCFileNewFromDataRep(cipherData, + cipherDataLen, + &cipherFile); + if(frtn) { + goto out; + } + *encrType = feeCFileEncrType(cipherFile); + *userData = feeCFileUserData(cipherFile); + frtn = decryptCipherFile(cipherFile, + recvPrivKey, + sendPubKey, + plainText, + plainTextLen, + sigStatus); + +out: + /* free stuff */ + + if(cipherData && freeCipherData) { + ffree(cipherData); + } + if(cipherFile) { + feeCFileFree(cipherFile); + } + return frtn; +} + +/* + * Decrypt a feeCipherFile obtained via feeCFileNewFromDataRep(). + * recvPrivKey is required in all cases. If sendPubKey is present, + * sendPubKey - rather than the embedded sender's public key - will be + * used for signature validation. + */ +feeReturn decryptCipherFile(feeCipherFile cipherFile, + feePubKey recvPrivKey, // required + feePubKey sendPubKey, // optional, for signature + unsigned char **plainText, // malloc'd & RETURNED + unsigned *plainTextLen, // RETURNED + feeSigStatus *sigStatus) // RETURNED +{ + cipherFileEncrType encrType = feeCFileEncrType(cipherFile); + feeReturn frtn; + + *plainText = NULL; + *plainTextLen = 0; + + /* + * Dispatch to encrType-specific code. + */ + switch(encrType) { + case CFE_RandDES: + frtn = decryptRandDES(cipherFile, + recvPrivKey, + sendPubKey, + plainText, + plainTextLen, + sigStatus); + break; + case CFE_PublicDES: + frtn = decryptPubDES(cipherFile, + recvPrivKey, + sendPubKey, + plainText, + plainTextLen, + sigStatus); + break; + case CFE_FEED: + frtn = decryptFEED(cipherFile, + recvPrivKey, + sendPubKey, + plainText, + plainTextLen, + sigStatus); + break; + case CFE_FEEDExp: + frtn = decryptFEEDExp(cipherFile, + recvPrivKey, + sendPubKey, + plainText, + plainTextLen, + sigStatus); + break; + default: + frtn = FR_Unimplemented; + break; + } + return frtn; +} diff --git a/libsecurity_cryptkit/lib/feeCipherFile.h b/libsecurity_cryptkit/lib/feeCipherFile.h new file mode 100644 index 00000000..2c67f51d --- /dev/null +++ b/libsecurity_cryptkit/lib/feeCipherFile.h @@ -0,0 +1,164 @@ +/* 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. + *************************************************************************** + * + * feeCipherFile.h + * + * Revision History + * ---------------- + * 24 Oct 96 Doug Mitchell at NeXT + * Created. + */ + +#ifndef _CK_FEECIPHERFILE_H_ +#define _CK_FEECIPHERFILE_H_ + +#if !defined(__MACH__) +#include +#include +#include +#include +#else +#include "ckconfig.h" +#include "feeTypes.h" +#include "feePublicKey.h" +#include "CipherFileTypes.h" +#endif + +#if CRYPTKIT_CIPHERFILE_ENABLE + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Opaque cipherfile object. + */ +typedef void *feeCipherFile; + +/* + * Alloc and return a new feeCipherFile object associated with the specified + * data. + */ +feeCipherFile feeCFileNewFromCipherText(cipherFileEncrType encrType, + const unsigned char *cipherText, + unsigned cipherTextLen, + const unsigned char *sendPubKeyData, + unsigned sendPubKeyDataLen, + const unsigned char *otherKeyData, + unsigned otherKeyDataDataLen, + const unsigned char *sigData, // optional; NULL means no signature + unsigned sigDataLen, // 0 if sigData is NULL + unsigned userData); // for caller's convenience + +/* + * Obtain the contents of a feeCipherFile as a byte stream. Caller must free + * the returned data. + */ +feeReturn feeCFileDataRepresentation(feeCipherFile cipherFile, + const unsigned char **dataRep, // RETURNED + unsigned *dataRepLen); // RETURNED + +/* + * Alloc and return a new feeCipherFile object, given a byte stream (originally + * obtained from feeCFDataRepresentation()). + */ +feeReturn feeCFileNewFromDataRep(const unsigned char *dataRep, + unsigned dataRepLen, + feeCipherFile *cipherFile); // RETURNED if sucessful + +/* + * Free a feeCipherFile object. + */ +void feeCFileFree(feeCipherFile cipherFile); + +/* + * Given a feeCipherFile object (typically obtained from + * feeCFileNewFromDataRep()), obtain its constituent parts. + * + * Data returned must be freed by caller. + * feeCFileSigData(), feeCFileSendPubKeyData, and feeCFileOtherKeyData() + * may return NULL, indicating component not present. + */ +cipherFileEncrType feeCFileEncrType(feeCipherFile cipherFile); +unsigned char *feeCFileCipherText(feeCipherFile cipherFile, + unsigned *cipherTextLen); // RETURNED +unsigned char *feeCFileSendPubKeyData(feeCipherFile cipherFile, + unsigned *sendPubKeyDataLen); // RETURNED +unsigned char *feeCFileOtherKeyData(feeCipherFile cipherFile, + unsigned *otherKeyDataLen); // RETURNED +unsigned char *feeCFileSigData(feeCipherFile cipherFile, + unsigned *sigDataLen); // RETURNED +unsigned feeCFileUserData(feeCipherFile cipherFile); + +/* + * High-level feeCipherFile support. + */ + +/* + * Obtain the data representation of a feeCipherFile given the specified + * plainText and cipherFileEncrType. + * Receiver's public key is required for all encrTypes; sender's private + * key is required for signature generation and also for encrType + * CFE_PublicDES and CFE_FEED. + */ +feeReturn createCipherFile(feePubKey sendPrivKey, + feePubKey recvPubKey, + cipherFileEncrType encrType, + const unsigned char *plainText, + unsigned plainTextLen, + int genSig, // 1 ==> generate signature + int doEnc64, // 1 ==> perform enc64 + unsigned userData, // for caller's convenience + unsigned char **cipherFileData, // RETURNED + unsigned *cipherFileDataLen); // RETURNED + +/* + * Parse and decrypt a cipherfile given its data representation. + * + * recvPrivKey is required in all cases. If sendPubKey is present, + * sendPubKey - rather than the embedded sender's public key - will be + * used for signature validation. + */ +feeReturn parseCipherFile(feePubKey recvPrivKey, // required + feePubKey sendPubKey, // optional, for signature + const unsigned char *cipherFileData, + unsigned cipherFileDataLen, + int doDec64, // 1 ==> perform dec64 + cipherFileEncrType *encrType, // RETURNED + unsigned char **plainText, // malloc'd & RETURNED + unsigned *plainTextLen, // RETURNED + feeSigStatus *sigStatus, // RETURNED + unsigned *userData); // RETURNED + +/* + * Decrypt a feeCipherFile object obtained via feeCFileNewFromDataRep(). + * recvPrivKey is required in all cases. If sendPubKey is present, + * sendPubKey - rather than the embedded sender's public key - will be + * used for signature validation. + * + * Note: this function is used (in conjunction with feeCFileNewFromDataRep()) + * rather than the simpler parseCipherFile(), in case the caller needs + * access to CipherFile fields not returned in parseCipherFile(). For + * example, the caller might want to get the sender's public key data + * via feeCFileSendPubKeyData(). + */ +feeReturn decryptCipherFile(feeCipherFile cipherFile, + feePubKey recvPrivKey, // required + feePubKey sendPubKey, // optional, for signature + unsigned char **plainText, // malloc'd & RETURNED + unsigned *plainTextLen, // RETURNED + feeSigStatus *sigStatus); // RETURNED + +#ifdef __cplusplus +} +#endif + +#endif /* CRYPTKIT_CIPHERFILE_ENABLE */ +#endif /*_CK_FEECIPHERFILE_H_*/ diff --git a/libsecurity_cryptkit/lib/feeCipherFileAtom.c b/libsecurity_cryptkit/lib/feeCipherFileAtom.c new file mode 100644 index 00000000..a68aecd7 --- /dev/null +++ b/libsecurity_cryptkit/lib/feeCipherFileAtom.c @@ -0,0 +1,400 @@ +/* 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. + *************************************************************************** + * + * feeCipherFile.c + * + * Revision History + * ---------------- + * 10/06/98 ap + * Changed to compile with C++. + * 05 Feb 97 Doug Mitchell at Apple + * Modified to use portable byte representation. + * 23 Oct 96 Doug Mitchell at NeXT + * Created. + */ + +#include "feeCipherFile.h" +#include "falloc.h" +#include "platform.h" +#include "feeDebug.h" +#include "byteRep.h" + +#ifndef NULL +#define NULL ((void *)0) +#endif /* NULL */ + +/* + * These must match constants of same name in CipherFileAtom.java. + */ +#define CFILE_MAGIC 0xfeecf111 +#define CFILE_VERSION 1 +#define CFILE_MIN_VERSION 1 + +/* + * Format of a feeCipherFile header. + * Offsets and lengths refer to locations of components in cFileInst.dataRep. + * This struct appears at the start of a feeCipherFile data representation. + */ +typedef struct { + unsigned magic; + unsigned version; + unsigned minVersion; + unsigned totalLength; // equals dataRepLen + cipherFileEncrType encrType; + unsigned cipherTextOffset; // offset of ciphertext + unsigned cipherTextLen; // in bytes + unsigned sendPubKeyDataOffset; // optional + unsigned sendPubKeyDataLen; + unsigned otherKeyDataOffset; // optional + unsigned otherKeyDataLen; + unsigned sigDataOffset; // optional + unsigned sigDataLen; // 0 means no signature + unsigned userData; +} cFileHeader; + +/* + * Private data, represented by a feeCipherFile handle. + */ +typedef struct { + cFileHeader header; + unsigned char *dataRep; // raw data + unsigned dataRepLen; +} cFileInst; + +static unsigned lengthOfByteRepCfileHdr(void); +static unsigned cfileHdrToByteRep(cFileHeader *hdr, + unsigned char *s); +static void byteRepToCfileHdr(const unsigned char *s, + cFileHeader *hdr); + + +/* + * alloc, free cFileInst + */ +static cFileInst *cFileInstAlloc() +{ + cFileInst *cfinst = (cFileInst *) fmalloc(sizeof(cFileInst)); + + bzero(cfinst, sizeof(cFileInst)); + return cfinst; +} + +static void cFileInstFree(cFileInst *cfinst) +{ + if(cfinst->dataRep) { + ffree(cfinst->dataRep); + } + ffree(cfinst); +} + +/* + * Alloc and return a new feeCipherFile object associated with the specified + * data. + */ +feeCipherFile feeCFileNewFromCipherText(cipherFileEncrType encrType, + const unsigned char *cipherText, + unsigned cipherTextLen, + const unsigned char *sendPubKeyData, // optional + unsigned sendPubKeyDataLen, // 0 if sendPubKeyData is NULL + const unsigned char *otherKeyData, // optional + unsigned otherKeyDataLen, // 0 if otherKeyData is NULL + const unsigned char *sigData, // optional; NULL means no signature + unsigned sigDataLen, // 0 if sigData is NULL + unsigned userData) // for caller's convenience +{ + cFileInst *cfinst; + cFileHeader *header; + unsigned char *data; + + if(cipherTextLen == 0) { + return NULL; + } + cfinst = cFileInstAlloc(); + header = &cfinst->header; + + /* + * Init the header. + */ + header->magic = CFILE_MAGIC; + header->version = CFILE_VERSION; + header->minVersion = CFILE_MIN_VERSION; + header->totalLength = lengthOfByteRepCfileHdr() + cipherTextLen + + sendPubKeyDataLen + otherKeyDataLen + + sigDataLen; + header->encrType = encrType; + header->cipherTextOffset = lengthOfByteRepCfileHdr(); + header->cipherTextLen = cipherTextLen; + header->sendPubKeyDataOffset = header->cipherTextOffset + + cipherTextLen; + header->sendPubKeyDataLen = sendPubKeyDataLen; + header->otherKeyDataOffset = header->sendPubKeyDataOffset + + sendPubKeyDataLen; + header->otherKeyDataLen = otherKeyDataLen; + header->sigDataOffset = header->otherKeyDataOffset + + otherKeyDataLen; + header->sigDataLen = sigDataLen; + header->userData = userData; + + /* + * Alloc a data representation, copy various components to it. + */ + cfinst->dataRepLen = header->totalLength; + data = cfinst->dataRep = (unsigned char*) fmalloc(cfinst->dataRepLen); + cfileHdrToByteRep(header, data); + + data = cfinst->dataRep + header->cipherTextOffset; + bcopy(cipherText, data, cipherTextLen); + if(sendPubKeyDataLen) { + data = cfinst->dataRep + header->sendPubKeyDataOffset; + bcopy(sendPubKeyData, data, sendPubKeyDataLen); + } + if(otherKeyDataLen) { + data = cfinst->dataRep + header->otherKeyDataOffset; + bcopy(otherKeyData, data, otherKeyDataLen); + } + if(sigDataLen) { + data = cfinst->dataRep + header->sigDataOffset; + bcopy(sigData, data, sigDataLen); + } + return (feeCipherFile)cfinst; +} + +/* + * Obtain the contents of a feeCipherFile as a byte stream. + */ +feeReturn feeCFileDataRepresentation(feeCipherFile cipherFile, + const unsigned char **dataRep, + unsigned *dataRepLen) +{ + cFileInst *cfinst = (cFileInst *)cipherFile; + + if(cfinst->dataRepLen == 0) { + *dataRep = NULL; + *dataRepLen = 0; + return FR_BadCipherFile; + } + *dataRep = (unsigned char*) fmallocWithData(cfinst->dataRep, cfinst->dataRepLen); + *dataRepLen = cfinst->dataRepLen; + return FR_Success; +} + +/* + * Alloc and return a new feeCipherFile object, given a byte stream (originally + * obtained from feeCFDataRepresentation()). + */ +feeReturn feeCFileNewFromDataRep(const unsigned char *dataRep, + unsigned dataRepLen, + feeCipherFile *cipherFile) // RETURNED if sucessful +{ + cFileInst *cfinst = cFileInstAlloc(); + cFileHeader *header; + + if(dataRepLen < lengthOfByteRepCfileHdr()) { + dbgLog(("datRep too short\n")); + goto abort; + } + cfinst->dataRep = (unsigned char*) fmallocWithData(dataRep, dataRepLen); + cfinst->dataRepLen = dataRepLen; + header = &cfinst->header; + byteRepToCfileHdr(dataRep, header); + + /* + * As much consistency checking as we can manage here. + */ + if(header->magic != CFILE_MAGIC) { + dbgLog(("Bad cipherFile magic number\n")); + goto abort; + } + if(header->minVersion > CFILE_VERSION) { + dbgLog(("Incompatible cipherFile version\n")); + goto abort; + } + if(header->totalLength != dataRepLen) { + dbgLog(("Bad totalLength in cipherFile header\n")); + goto abort; + } + if(((header->cipherTextOffset + header->cipherTextLen) > + header->totalLength) || + ((header->sendPubKeyDataOffset + header->sendPubKeyDataLen) > + header->totalLength) || + ((header->otherKeyDataOffset + header->otherKeyDataLen) > + header->totalLength) || + ((header->sigDataOffset + header->sigDataLen) > + header->totalLength)) { + dbgLog(("Bad element lengths in cipherFile header\n")); + goto abort; + } + + /* + * OK, looks good. + */ + *cipherFile = (feeCipherFile)cfinst; + return FR_Success; +abort: + cFileInstFree(cfinst); + *cipherFile = NULL; + return FR_BadCipherFile; +} + +/* + * Free a feeCipherFile object. + */ +void feeCFileFree(feeCipherFile cipherFile) +{ + cFileInstFree((cFileInst *)cipherFile); +} + +/* + * Given a feeCipherFile object (typically obtained from + * feeCFileNewFromData()), obtain its constituent parts. + * + * Data returned must be freed by caller. + * feeCFileSigData() may return NULL, indicating no signature present. + */ +cipherFileEncrType feeCFileEncrType(feeCipherFile cipherFile) +{ + cFileInst *cfinst = (cFileInst *)cipherFile; + + return cfinst->header.encrType; +} + +unsigned char *feeCFileCipherText(feeCipherFile cipherFile, + unsigned *cipherTextLen) +{ + cFileInst *cfinst = (cFileInst *)cipherFile; + + if(cfinst->header.cipherTextLen) { + *cipherTextLen = cfinst->header.cipherTextLen; + return (unsigned char*) fmallocWithData(cfinst->dataRep + + cfinst->header.cipherTextOffset, *cipherTextLen); + } + else { + dbgLog(("feeCFileCipherText: no cipherText\n")); + *cipherTextLen = 0; + return NULL; + } +} + +unsigned char *feeCFileSendPubKeyData(feeCipherFile cipherFile, + unsigned *sendPubKeyDataLen) +{ + cFileInst *cfinst = (cFileInst *)cipherFile; + + if(cfinst->header.sendPubKeyDataLen) { + *sendPubKeyDataLen = cfinst->header.sendPubKeyDataLen; + return (unsigned char*) fmallocWithData(cfinst->dataRep + + cfinst->header.sendPubKeyDataOffset, + *sendPubKeyDataLen); + } + else { + *sendPubKeyDataLen = 0; + return NULL; + } +} + +unsigned char *feeCFileOtherKeyData(feeCipherFile cipherFile, + unsigned *otherKeyDataLen) +{ + cFileInst *cfinst = (cFileInst *)cipherFile; + + if(cfinst->header.otherKeyDataLen) { + *otherKeyDataLen = cfinst->header.otherKeyDataLen; + return (unsigned char*) fmallocWithData(cfinst->dataRep + + cfinst->header.otherKeyDataOffset, *otherKeyDataLen); + } + else { + *otherKeyDataLen = 0; + return NULL; + } +} + +unsigned char *feeCFileSigData(feeCipherFile cipherFile, + unsigned *sigDataLen) +{ + cFileInst *cfinst = (cFileInst *)cipherFile; + + if(cfinst->header.sigDataLen) { + *sigDataLen = cfinst->header.sigDataLen; + return (unsigned char*) fmallocWithData(cfinst->dataRep + + cfinst->header.sigDataOffset, *sigDataLen); + } + else { + /* + * Not an error + */ + *sigDataLen = 0; + return NULL; + } +} + +unsigned feeCFileUserData(feeCipherFile cipherFile) +{ + cFileInst *cfinst = (cFileInst *)cipherFile; + + return cfinst->header.userData; +} + +/* + * Convert between cFileHeader and portable byte representation. + */ + +/* + * Return size of byte rep of cFileHeader. We just happen to know that + * this is the same size as the header.... + */ +static unsigned lengthOfByteRepCfileHdr(void) +{ + return sizeof(cFileHeader); +} + +static unsigned cfileHdrToByteRep(cFileHeader *hdr, + unsigned char *s) +{ + s += intToByteRep(hdr->magic, s); + s += intToByteRep(hdr->version, s); + s += intToByteRep(hdr->minVersion, s); + s += intToByteRep(hdr->totalLength, s); + s += intToByteRep(hdr->encrType, s); + s += intToByteRep(hdr->cipherTextOffset, s); + s += intToByteRep(hdr->cipherTextLen, s); + s += intToByteRep(hdr->sendPubKeyDataOffset, s); + s += intToByteRep(hdr->sendPubKeyDataLen, s); + s += intToByteRep(hdr->otherKeyDataOffset, s); + s += intToByteRep(hdr->otherKeyDataLen, s); + s += intToByteRep(hdr->sigDataOffset, s); + s += intToByteRep(hdr->sigDataLen, s); + s += intToByteRep(hdr->userData, s); + return sizeof(cFileHeader); +} + +#define DEC_INT(n, b) \ + n = byteRepToInt(b); \ + b += sizeof(int); + +static void byteRepToCfileHdr(const unsigned char *s, + cFileHeader *hdr) +{ + DEC_INT(hdr->magic, s); + DEC_INT(hdr->version, s); + DEC_INT(hdr->minVersion, s); + DEC_INT(hdr->totalLength, s); +// DEC_INT(hdr->encrType, s); + hdr->encrType = (cipherFileEncrType) byteRepToInt(s); + s += sizeof(int); + DEC_INT(hdr->cipherTextOffset, s); + DEC_INT(hdr->cipherTextLen, s); + DEC_INT(hdr->sendPubKeyDataOffset, s); + DEC_INT(hdr->sendPubKeyDataLen, s); + DEC_INT(hdr->otherKeyDataOffset, s); + DEC_INT(hdr->otherKeyDataLen, s); + DEC_INT(hdr->sigDataOffset, s); + DEC_INT(hdr->sigDataLen, s); + DEC_INT(hdr->userData, s); +} diff --git a/libsecurity_cryptkit/lib/feeDES.c b/libsecurity_cryptkit/lib/feeDES.c new file mode 100644 index 00000000..632457a5 --- /dev/null +++ b/libsecurity_cryptkit/lib/feeDES.c @@ -0,0 +1,529 @@ +/* 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. + *************************************************************************** + * + * FeeDES.c - generic, portable DES encryption object + * + * Revision History + * ---------------- + * 10/06/98 ap + * Changed to compile with C++. + * 05 Jan 98 Doug Mitchell at Apple + * Avoid a bcopy() on encrypt/decrypt of each block + * 31 Mar 97 Doug Mitchell at Apple + * New per-instance API for DES.c + * 26 Aug 96 Doug Mitchell at NeXT + * Created. + */ + +#include "ckconfig.h" + +#if CRYPTKIT_SYMMETRIC_ENABLE + +#include "feeDES.h" +#include "feeTypes.h" +#include "ckDES.h" +#include "falloc.h" +#include "feeDebug.h" +#include "feeFunctions.h" +#include "platform.h" +#include + +#ifndef NULL +#define NULL ((void *)0) +#endif /* NULL */ + +typedef struct { + int blockMode; /* default = 0 */ + unsigned char lastBlock[DES_BLOCK_SIZE_BYTES]; /* for CBC */ + struct _desInst dinst; +} fdesInst; + +static void feeDESInit(desInst dinst) +{ + desinit(dinst, DES_MODE_STD); // detects redundant calls +} + +/* + * Alloc and init a feeDES object with specified initial state. + * State must be at least 8 bytes; only 8 bytes are used, ignoring + * MSB of each bytes. + */ +feeDES feeDESNewWithState(const unsigned char *state, + unsigned stateLen) +{ + fdesInst *fdinst; + + if(stateLen < FEE_DES_MIN_STATE_SIZE) { + return NULL; + } + fdinst = (fdesInst*) fmalloc(sizeof(fdesInst)); + bzero(fdinst, sizeof(fdesInst)); + feeDESInit(&fdinst->dinst); + feeDESSetState((feeDES)fdinst, state, stateLen); + return fdinst; +} + +void feeDESFree(feeDES des) +{ + memset(des, 0, sizeof(fdesInst)); + ffree(des); +} + +/* + * Set new initial state. + */ +feeReturn feeDESSetState(feeDES des, + const unsigned char *state, + unsigned stateLen) +{ + fdesInst *fdinst = (fdesInst*) des; + char Key[DES_KEY_SIZE_BYTES_EXTERNAL]; + // 'key' causes problems with + // some weird Unix header + unsigned byte; + + if(stateLen < (DES_KEY_SIZE_BYTES_EXTERNAL)) { + return FR_IllegalArg; + } + bzero(fdinst->lastBlock, DES_BLOCK_SIZE_BYTES); + bcopy(state, Key, DES_KEY_SIZE_BYTES_EXTERNAL); + + /* + * Set up parity bits + */ + for(byte=0; bytedinst, Key); + return FR_Success; +} + +void feeDESSetBlockMode(feeDES des) +{ + fdesInst *fdinst = (fdesInst*) des; + + fdinst->blockMode = 1; +} + +void feeDESSetChainMode(feeDES des) +{ + fdesInst *fdinst = (fdesInst*) des; + + fdinst->blockMode = 0; +} + +unsigned feeDESPlainBlockSize(feeDES des) +{ + return DES_BLOCK_SIZE_BYTES; +} + +unsigned feeDESCipherBlockSize(feeDES des) +{ + return DES_BLOCK_SIZE_BYTES; +} + +unsigned feeDESCipherBufSize(feeDES des) +{ + /* + * Normally DES_BLOCK_SIZE, two blocks for finalBlock + */ + return 2 * DES_BLOCK_SIZE_BYTES; +} + +/* + + * Return the size of ciphertext to hold specified size of plaintext. + + */ + +unsigned feeDESCipherTextSize(feeDES des, unsigned plainTextSize) + +{ + + unsigned blocks = (plainTextSize + DES_BLOCK_SIZE_BYTES - 1) / + DES_BLOCK_SIZE_BYTES; + + if((plainTextSize % DES_BLOCK_SIZE_BYTES) == 0) { + /* + * One more block for resid count + */ + blocks++; + } + + return blocks * DES_BLOCK_SIZE_BYTES; + +} + + +/* + * Key size in bits. + */ +unsigned feeDESKeySize(feeDES des) +{ + return DES_KEY_SIZE_BITS; +} + +/* + * Encrypt a block or less of data. Caller malloc's cipherText. + */ +feeReturn feeDESEncryptBlock(feeDES des, + const unsigned char *plainText, + unsigned plainTextLen, + unsigned char *cipherText, + unsigned *cipherTextLen, // RETURNED + int finalBlock) +{ + fdesInst *fdinst = (fdesInst*) des; + feeReturn frtn = FR_Success; + unsigned cipherLen; + + if(plainTextLen > DES_BLOCK_SIZE_BYTES) { + return FR_IllegalArg; + } + if(plainTextLen) { + /* + * We're called with plainTextLen = 0 and finalBlock + * recursively to clean up last block. + */ + bcopy(plainText, cipherText, plainTextLen); + } + if(plainTextLen < DES_BLOCK_SIZE_BYTES) { + if(!finalBlock) { + /* + * odd-size block only legal last time thru + */ + return FR_IllegalArg; + } + + /* + * Last block, final byte = residual length. + */ + cipherText[DES_BLOCK_SIZE_BYTES - 1] = plainTextLen; + } + + if(!fdinst->blockMode) { + /* + * CBC mode; chain in last cipher word + */ + unsigned char *cp = cipherText; + unsigned char *cp1 = fdinst->lastBlock; + int i; + + for(i=0; idinst, (char *)cipherText); /* Encrypt block */ + if(!fdinst->blockMode){ + /* + * Save outgoing ciphertext for chain + */ + bcopy(cipherText, fdinst->lastBlock, DES_BLOCK_SIZE_BYTES); + } + cipherLen = DES_BLOCK_SIZE_BYTES; + + if(finalBlock) { + if(plainTextLen == DES_BLOCK_SIZE_BYTES) { + /* + * Special case: finalBlock true, plainTextLen == blockSize. + * In this case we generate one more block of ciphertext, + * with a resid length of zero. + */ + unsigned moreCipher; // additional cipherLen + + frtn = feeDESEncryptBlock(des, + NULL, // plainText not used + 0, // resid + cipherText + DES_BLOCK_SIZE_BYTES, // append... + &moreCipher, + 1); + if(frtn == FR_Success) { + cipherLen += moreCipher; + } + + } + if(plainTextLen != 0) { + /* + * Reset internal state in prep for next encrypt/decrypt. + * Note we avoid this in the recursive call (plainTextLen = 0). + */ + bzero(fdinst->lastBlock, DES_BLOCK_SIZE_BYTES); + } + } + + if(frtn == FR_Success) { + *cipherTextLen = cipherLen; + } + return frtn; +} + +/* + * Decrypt a block of data. Caller malloc's plainText. Always + * generates DES_BLOCK_SIZE_BYTES bytes or less of plainText. + */ +feeReturn feeDESDecryptBlock(feeDES des, + const unsigned char *cipherText, + unsigned cipherTextLen, + unsigned char *plainText, + unsigned *plainTextLen, // RETURNED + int finalBlock) +{ + fdesInst *fdinst = (fdesInst*) des; + unsigned char work[DES_BLOCK_SIZE_BYTES]; + unsigned char ivtmp[DES_BLOCK_SIZE_BYTES]; + + if(cipherTextLen != DES_BLOCK_SIZE_BYTES) { + /* + * We always generate ciphertext in multiples of block size. + */ + return FR_IllegalArg; + } + + bcopy(cipherText, work, DES_BLOCK_SIZE_BYTES); + if(!fdinst->blockMode && !finalBlock) { + /* + * Save incoming ciphertext for chain + */ + bcopy(cipherText, ivtmp, DES_BLOCK_SIZE_BYTES); + } + dedes(&fdinst->dinst, (char *)work); + if(!fdinst->blockMode){ + /* + * Unchain block using previous block's ciphertext; + * save current ciphertext for next + */ + char *cp = (char *)work; + char *cp1 = (char*)fdinst->lastBlock; + int i; + + for(i=0; ilastBlock, DES_BLOCK_SIZE_BYTES); + } + } + if(finalBlock) { + /* + * deal with residual block; its size is in last byte of + * work[] + */ + unsigned resid = work[DES_BLOCK_SIZE_BYTES-1]; + + if(resid > (DES_BLOCK_SIZE_BYTES-1)) { + return FR_BadCipherText; + } + if(resid > 0) { + bcopy(work, plainText, resid); + } + *plainTextLen = resid; + + /* + * Reset internal state in prep for next encrypt/decrypt. + */ + bzero(fdinst->lastBlock, DES_BLOCK_SIZE_BYTES); + } + else { + bcopy(work, plainText, DES_BLOCK_SIZE_BYTES); + *plainTextLen = DES_BLOCK_SIZE_BYTES; + } + return FR_Success; +} + +/* + * Convenience routines to encrypt & decrypt multi-block data. + */ +feeReturn feeDESEncrypt(feeDES des, + const unsigned char *plainText, + unsigned plainTextLen, + unsigned char **cipherText, // malloc'd and RETURNED + unsigned *cipherTextLen) // RETURNED +{ + const unsigned char *ptext; // per block + unsigned ptextLen; // total to go + unsigned thisPtextLen; // per block + unsigned ctextLen; // per block + unsigned char *ctextResult; // to return + unsigned char *ctextPtr; + unsigned ctextLenTotal; // running total + feeReturn frtn; + int finalBlock; + unsigned ctextMallocd; + + if(plainTextLen == 0) { + dbgLog(("feeDESDecrypt: NULL plainText\n")); + return FR_IllegalArg; + } + + ptext = plainText; + ptextLen = plainTextLen; + ctextMallocd = feeDESCipherTextSize(des, plainTextLen); + ctextResult = (unsigned char*) fmalloc(ctextMallocd); + ctextPtr = ctextResult; + ctextLenTotal = 0; + + while(1) { + if(ptextLen <= DES_BLOCK_SIZE_BYTES) { + finalBlock = 1; + thisPtextLen = ptextLen; + } + else { + finalBlock = 0; + thisPtextLen = DES_BLOCK_SIZE_BYTES; + } + frtn = feeDESEncryptBlock(des, + ptext, + thisPtextLen, + ctextPtr, + &ctextLen, + finalBlock); + if(frtn) { + dbgLog(("feeDESEncrypt: encrypt error: %s\n", + feeReturnString(frtn))); + break; + } + if(ctextLen == 0) { + dbgLog(("feeDESEncrypt: null ciphertext\n")); + frtn = FR_Internal; + break; + } + ctextLenTotal += ctextLen; + if(ctextLenTotal > (plainTextLen + DES_BLOCK_SIZE_BYTES)) { + dbgLog(("feeDESEncrypt: ciphertext overflow\n")); + frtn = FR_Internal; + break; + } + if(finalBlock) { + break; + } + ctextPtr += ctextLen; + ptext += thisPtextLen; + ptextLen -= thisPtextLen; + } + if(frtn) { + ffree(ctextResult); + *cipherText = NULL; + *cipherTextLen = 0; + } + else { + #if FEE_DEBUG + if(ctextLenTotal != ctextMallocd) { + dbgLog(("feeDESEncrypt: ctextLen error\n")); + } + #endif /* FEE_DEBUG */ + *cipherText = ctextResult; + *cipherTextLen = ctextLenTotal; + } + return frtn; + +} + +feeReturn feeDESDecrypt(feeDES des, + const unsigned char *cipherText, + unsigned cipherTextLen, + unsigned char **plainText, // malloc'd and RETURNED + unsigned *plainTextLen) // RETURNED +{ + const unsigned char *ctext; + unsigned ctextLen; // total to go + unsigned ptextLen; // per block + unsigned char *ptextResult; // to return + unsigned char *ptextPtr; + unsigned ptextLenTotal; // running total + feeReturn frtn = FR_Success; + int finalBlock; + + if(cipherTextLen % DES_BLOCK_SIZE_BYTES) { + dbgLog(("feeDESDecrypt: unaligned cipherText\n")); + return FR_BadCipherText; + } + if(cipherTextLen == 0) { + dbgLog(("feeDESDecrypt: NULL cipherText\n")); + return FR_BadCipherText; + } + + ctext = cipherText; + ctextLen = cipherTextLen; + + /* + * Plaintext length always <= cipherTextLen + */ + ptextResult = (unsigned char*) fmalloc(cipherTextLen); + ptextPtr = ptextResult; + ptextLenTotal = 0; + + while(ctextLen) { + if(ctextLen == DES_BLOCK_SIZE_BYTES) { + finalBlock = 1; + } + else { + finalBlock = 0; + } + frtn = feeDESDecryptBlock(des, + ctext, + DES_BLOCK_SIZE_BYTES, + ptextPtr, + &ptextLen, + finalBlock); + if(frtn) { + dbgLog(("feeDESDecrypt decrypt: %s\n", + feeReturnString(frtn))); + break; + } + if(ptextLen == 0) { + /* + * Normal termination case for + * plainTextLen % DES_BLOCK_SIZE_BYTES == 0 + */ + if(!finalBlock) { + dbgLog(("feeDESDecrypt: decrypt sync" + " error!\n")); + frtn = FR_BadCipherText; + break; + } + else { + break; + } + } + else { + ptextPtr += ptextLen; + ptextLenTotal += ptextLen; + } + ctext += DES_BLOCK_SIZE_BYTES; + ctextLen -= DES_BLOCK_SIZE_BYTES; + } + + if(frtn) { + ffree(ptextResult); + *plainText = NULL; + *plainTextLen = 0; + } + else { + *plainText = ptextResult; + *plainTextLen = ptextLenTotal; + } + return frtn; +} + +#endif /* CRYPTKIT_SYMMETRIC_ENABLE */ diff --git a/libsecurity_cryptkit/lib/feeDES.h b/libsecurity_cryptkit/lib/feeDES.h new file mode 100644 index 00000000..299e805a --- /dev/null +++ b/libsecurity_cryptkit/lib/feeDES.h @@ -0,0 +1,141 @@ +/* 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. + *************************************************************************** + * + * FeeDES.h - generic, portable DES encryption object + * + * Revision History + * ---------------- + * 26 Aug 96 Doug Mitchell at NeXT + * Created. + */ + +#ifndef _CK_FEEDES_H_ +#define _CK_FEEDES_H_ + +#if !defined(__MACH__) +#include +#include +#else +#include +#include +#endif + +#if CRYPTKIT_SYMMETRIC_ENABLE + +#ifdef __cplusplus +extern "C" { +#endif + +#define FEE_DES_MIN_STATE_SIZE 8 + +/* + * Opaque object handle. + */ +typedef void *feeDES; + +/* + * Alloc and init a feeDES object with specified initial state. + * State must be at least 8 bytes; only 8 bytes are used, ignoring + * MSB of each bytes. + */ +feeDES feeDESNewWithState(const unsigned char *state, + unsigned stateLen); + +void feeDESFree(feeDES des); + +/* + * Set new initial state. + */ +feeReturn feeDESSetState(feeDES des, + const unsigned char *state, + unsigned stateLen); + +/* + * Set block or chain (CBC) mode. CBC is default. + */ +void feeDESSetBlockMode(feeDES des); +void feeDESSetChainMode(feeDES des); + +/* + * Plaintext block size. + */ +unsigned feeDESPlainBlockSize(feeDES des); + +/* + * Ciphertext block size used for decryption. + */ +unsigned feeDESCipherBlockSize(feeDES des); + +/* + * Required size of buffer for ciphertext, upon encrypting one + * block of plaintext. + */ +unsigned feeDESCipherBufSize(feeDES des); + +/* + + * Return the size of ciphertext to hold specified size of plaintext. + + */ + +unsigned feeDESCipherTextSize(feeDES des, unsigned plainTextSize); + + +/* + * Key size in bits. + */ +unsigned feeDESKeySize(feeDES des); + +/* + * Encrypt a block or less of data. Caller malloc's cipherText. Generates + * up to (2 * feeDESBlockSize) bytes of cipherText. If plainTextLen is + * less than feeDESBlockSize, finalBlock must be true. + */ +feeReturn feeDESEncryptBlock(feeDES des, + const unsigned char *plainText, + unsigned plainTextLen, + unsigned char *cipherText, + unsigned *cipherTextLen, // RETURNED + int finalBlock); + +/* + * Decrypt (exactly) a block of data. Caller malloc's plainText. Always + * generates feeDESBlockSize bytes of plainText, unless 'finalBlock' is + * non-zero (in which case feeDESBlockSize or less bytes of plainText are + * generated). + */ +feeReturn feeDESDecryptBlock(feeDES des, + const unsigned char *cipherText, + unsigned cipherTextLen, + unsigned char *plainText, + unsigned *plainTextLen, // RETURNED + int finalBlock); + +/* + * Convenience routines to encrypt & decrypt multi-block data. + */ +feeReturn feeDESEncrypt(feeDES des, + const unsigned char *plainText, + unsigned plainTextLen, + unsigned char **cipherText, // malloc'd and RETURNED + unsigned *cipherTextLen); // RETURNED + +feeReturn feeDESDecrypt(feeDES des, + const unsigned char *cipherText, + unsigned cipherTextLen, + unsigned char **plainText, // malloc'd and RETURNED + unsigned *plainTextLen); // RETURNED + +#ifdef __cplusplus +} +#endif + +#endif /* CRYPTKIT_SYMMETRIC_ENABLE */ +#endif /*_CK_FEEDES_H_*/ diff --git a/libsecurity_cryptkit/lib/feeDebug.h b/libsecurity_cryptkit/lib/feeDebug.h new file mode 100644 index 00000000..8cd39fd2 --- /dev/null +++ b/libsecurity_cryptkit/lib/feeDebug.h @@ -0,0 +1,195 @@ +/* + File: feeDebug.h + + Contains: Debug macros. + + Written by: Doug Mitchell + + Copyright: Copyright 1998 by Apple Computer, Inc. + All rights reserved. + + Change History (most recent first): + + <9> 10/06/98 ap Changed to compile with C++. + + To Do: +*/ + +/* 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. + *************************************************************************** + */ + +#ifndef _CK_FEEDEBUG_H_ +#define _CK_FEEDEBUG_H_ + +#include "giantIntegers.h" +#include "elliptic.h" +#include "curveParams.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef NDEBUG +#define FEE_DEBUG 0 +#else +#define FEE_DEBUG 1 +#endif + +/* + * In utilities.c... + */ +extern void printGiant(const giant x); +extern void printGiantHex(const giant x); +extern void printGiantExp(const giant x); +extern void printKey(const key k); +extern void printCurveParams(const curveParams *p); + +#if FEE_DEBUG + +#define dbgLog(x) printf x + + +#else /* FEE_DEBUG */ + +#define dbgLog(x) + +#endif /* FEE_DEBUG */ + +/* + * Profiling. + */ +#define FEE_PROFILE 0 /* general purpose profile */ +#define ELL_PROFILE 0 /* ell_even/ell_odd only */ + +#if (FEE_PROFILE || ELL_PROFILE) +#include +#endif /* (FEE_PROFILE || ELL_PROFILE) */ + +/* + * Place this macro after the last local and before any code in a routine + * to profile. + */ +#define CPROF_START \ + struct tsval _profStartTime; \ + struct tsval _profEndTime; \ + kern_timestamp(&_profStartTime); + +/* + * This one goes at the end of the routine, just before the (only) return. + * There must be a static accumulator (an unsigned int) on a per-routine basis. + */ +#define CPROF_END(accum) \ + kern_timestamp(&_profEndTime); \ + accum += (_profEndTime.low_val - _profStartTime.low_val); + +/* + * Increment a profiling counter. + */ +#define CPROF_INCR(ctr) ctr++ + +#if FEE_PROFILE + +#define PROF_START CPROF_START +#define PROF_END(a) CPROF_END(a) +#define PROF_INCR(ctr) CPROF_INCR(ctr) + +/* + * As of 14 Apr 1998, we no longer time mulg or gsquare calls with this + * mechanism; the time overhead is the same magnitude as the mulg. Instead + * we'll just count the mulgs and gsquares. + */ +#define PROF_TIME_MULGS 0 + + +/* + * Fundamental ops + */ +extern unsigned ellAddTime; +extern unsigned whichCurveTime; +extern unsigned ellipticTime; +extern unsigned sigCompTime; + +/* + * low-level primitives + */ +extern unsigned numerDoubleTime; +extern unsigned numerPlusTime; +extern unsigned numerTimesTime; +extern unsigned denomDoubleTime; +extern unsigned denomTimesTime; +extern unsigned powerModTime; +extern unsigned modgTime; +extern unsigned binvauxTime; + +/* + * Counters for calculating microseconds per {mulg, feemod, ...} + */ +extern unsigned numMulg; +extern unsigned numFeemod; +extern unsigned numGsquare; +extern unsigned numBorrows; + +extern void clearProfile(); + +#else /* FEE_PROFILE */ +#define PROF_START +#define PROF_END(a) +#define PROF_INCR(ctr) +#endif /* FEE_PROFILE */ + +#if ELL_PROFILE +extern unsigned ellOddTime; +extern unsigned ellEvenTime; +extern unsigned numEllOdds; +extern unsigned numEllEvens; +extern void clearEllProfile(); + +#define EPROF_START CPROF_START +#define EPROF_END(a) CPROF_END(a) +#define EPROF_INCR(ctr) CPROF_INCR(ctr) + +#else /* ELL_PROFILE */ +#define EPROF_START +#define EPROF_END(a) +#define EPROF_INCR(ctr) +#endif /* ELL_PROFILE */ + +/* + * NULL gets defined externally if FEE_DEBUG is true.. + */ +#if !FEE_DEBUG +#ifndef NULL +#define NULL ((void *)0) +#endif /* NULL */ +#endif /* !FEE_DEBUG */ + +#if FEE_DEBUG + +#include "platform.h" + +#define CKASSERT(expression) \ + ((expression) ? (void)0 : \ + (printf ("Assertion failed: " #expression \ + ", file " __FILE__ ", line %d.\n", __LINE__), \ + CKRaise("Assertion Failure"))) + +#else /* FEE_DEBUG */ + +#define CKASSERT(expression) + +#endif /* FEE_DEBUG */ + +#ifdef __cplusplus +} +#endif + +#endif /* _CK_FEEDEBUG_H_ */ diff --git a/libsecurity_cryptkit/lib/feeDigitalSignature.c b/libsecurity_cryptkit/lib/feeDigitalSignature.c new file mode 100644 index 00000000..08ccc5ae --- /dev/null +++ b/libsecurity_cryptkit/lib/feeDigitalSignature.c @@ -0,0 +1,674 @@ +/* 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. + *************************************************************************** + * + * feeDigitalSignature.c + * + * Revision History + * ---------------- + * 10/06/98 ap + * Changed to compile with C++. + * 9 Sep 98 Doug Mitchell at NeXT + * Major changes to use projective elliptic algebra for + * Weierstrass curves. + * 15 Jan 97 Doug Mitchell 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 + * Ported guts of Blaine Garst's NSFEEDigitalSignature.m to C. + */ + +#include "ckconfig.h" +#include "feeTypes.h" +#include "feePublicKey.h" +#include "feePublicKeyPrivate.h" +#include "feeDigitalSignature.h" +#include "giantIntegers.h" +#include "elliptic.h" +#include "feeRandom.h" +#include "curveParams.h" +#include "falloc.h" +#include "ckutilities.h" +#include "feeDebug.h" +#include "platform.h" +#include "byteRep.h" +#include "feeECDSA.h" +#if CRYPTKIT_DER_ENABLE +#include "CryptKitDER.h" +#endif + +#include +#include "ellipticProj.h" + +#define SIG_DEBUG 0 +#if SIG_DEBUG +int sigDebug=1; // tweakable at runtime via debugger +#endif // SIG_DEBUG + +#define SIG_CURVE DEFAULT_CURVE + +/* + * true : justify randGiant to [2, x1OrderPlus-2] + * false : no truncate or mod of randGiant + */ +#define RAND_JUST_X1_ORDER_PLUS 1 + +#define FEE_SIG_VERSION 4 +#define FEE_SIG_VERSION_MIN 4 + +#ifndef max +#define max(a,b) ((a)>(b)? (a) : (b)) +#endif // max + +typedef struct { + giant PmX; // m 'o' P1; m = random + #if CRYPTKIT_ELL_PROJ_ENABLE + giant PmY; // y-coord of m 'o' P1 if we're + // using projective coords + #endif /* CRYPTKIT_ELL_PROJ_ENABLE */ + + giant u; + giant randGiant; // random m as giant - only known + // when signing +} sigInst; + +static sigInst *sinstAlloc() +{ + sigInst *sinst = (sigInst*) fmalloc(sizeof(sigInst)); + + bzero(sinst, sizeof(sigInst)); + return sinst; +} + +/* + * Create new feeSig object, including a random large integer 'randGiant' for + * possible use in salting a feeHash object, and 'PmX', equal to + * randGiant 'o' P1. Note that this is not called when *verifying* a + * signature, only when signing. + */ +feeSig feeSigNewWithKey( + feePubKey pubKey, + feeRandFcn randFcn, /* optional */ + void *randRef) +{ + sigInst *sinst = sinstAlloc(); + feeRand frand; + unsigned char *randBytes; + unsigned randBytesLen; + curveParams *cp; + + if(pubKey == NULL) { + return NULL; + } + cp = feePubKeyCurveParams(pubKey); + if(cp == NULL) { + return NULL; + } + + /* + * Generate random m, a little larger than key size, save as randGiant + */ + randBytesLen = (feePubKeyBitsize(pubKey) / 8) + 1; + randBytes = (unsigned char*) fmalloc(randBytesLen); + if(randFcn) { + randFcn(randRef, randBytes, randBytesLen); + } + else { + frand = feeRandAlloc(); + feeRandBytes(frand, randBytes, randBytesLen); + feeRandFree(frand); + } + sinst->randGiant = giant_with_data(randBytes, randBytesLen); + memset(randBytes, 0, randBytesLen); + ffree(randBytes); + + #if FEE_DEBUG + if(isZero(sinst->randGiant)) { + printf("feeSigNewWithKey: randGiant = 0!\n"); + } + #endif // FEE_DEBUG + + /* + * Justify randGiant to be in [2, x1OrderPlus] + */ + x1OrderPlusJustify(sinst->randGiant, cp); + + /* PmX := randGiant 'o' P1 */ + sinst->PmX = newGiant(cp->maxDigits); + + #if CRYPTKIT_ELL_PROJ_ENABLE + + if(cp->curveType == FCT_Weierstrass) { + + pointProjStruct pt0; + + sinst->PmY = newGiant(cp->maxDigits); + + /* cook up pt0 as P1 */ + pt0.x = sinst->PmX; + pt0.y = sinst->PmY; + pt0.z = borrowGiant(cp->maxDigits); + gtog(cp->x1Plus, pt0.x); + gtog(cp->y1Plus, pt0.y); + int_to_giant(1, pt0.z); + + /* pt0 := P1 'o' randGiant */ + ellMulProjSimple(&pt0, sinst->randGiant, cp); + + returnGiant(pt0.z); + } + else { + if(SIG_CURVE == CURVE_PLUS) { + gtog(cp->x1Plus, sinst->PmX); + } + else { + gtog(cp->x1Minus, sinst->PmX); + } + elliptic_simple(sinst->PmX, sinst->randGiant, cp); + } + #else /* CRYPTKIT_ELL_PROJ_ENABLE */ + + if(SIG_CURVE == CURVE_PLUS) { + gtog(cp->x1Plus, sinst->PmX); + } + else { + gtog(cp->x1Minus, sinst->PmX); + } + elliptic_simple(sinst->PmX, sinst->randGiant, cp); + + #endif /* CRYPTKIT_ELL_PROJ_ENABLE */ + + return sinst; +} + +void feeSigFree(feeSig sig) +{ + sigInst *sinst = (sigInst*) sig; + + if(sinst->PmX) { + clearGiant(sinst->PmX); + freeGiant(sinst->PmX); + } + #if CRYPTKIT_ELL_PROJ_ENABLE + if(sinst->PmY) { + clearGiant(sinst->PmY); + freeGiant(sinst->PmY); + } + #endif /* CRYPTKIT_ELL_PROJ_ENABLE */ + if(sinst->u) { + clearGiant(sinst->u); + freeGiant(sinst->u); + } + if(sinst->randGiant) { + clearGiant(sinst->randGiant); + freeGiant(sinst->randGiant); + } + ffree(sinst); +} + +/* + * Obtain Pm after feeSigNewWithKey() or feeSigParse() + */ +unsigned char *feeSigPm(feeSig sig, + unsigned *PmLen) +{ + sigInst *sinst = (sigInst*) sig; + unsigned char *Pm; + + if(sinst->PmX == NULL) { + dbgLog(("feeSigPm: no PmX!\n")); + return NULL; + } + else { + Pm = mem_from_giant(sinst->PmX, PmLen); + #if SIG_DEBUG + if(sigDebug) + { + int i; + + printf("Pm : "); printGiant(sinst->PmX); + printf("PmData: "); + for(i=0; i<*PmLen; i++) { + printf("%x:", Pm[i]); + } + printf("\n"); + } + #endif // SIG_DEBUG + } + return Pm; +} + +/* + * Sign specified block of data (most likely a hash result) using + * specified feePubKey. + */ +feeReturn feeSigSign(feeSig sig, + const unsigned char *data, // data to be signed + unsigned dataLen, // in bytes + feePubKey pubKey) +{ + sigInst *sinst = (sigInst*) sig; + giant messageGiant = NULL; + unsigned maxlen; + giant privGiant; + unsigned privGiantBytes; + feeReturn frtn = FR_Success; + unsigned randBytesLen; + unsigned uDigits; // alloc'd digits in sinst->u + curveParams *cp; + + if(pubKey == NULL) { + return FR_BadPubKey; + } + cp = feePubKeyCurveParams(pubKey); + if(cp == NULL) { + return FR_BadPubKey; + } + + privGiant = feePubKeyPrivData(pubKey); + if(privGiant == NULL) { + dbgLog(("Attempt to Sign without private data\n")); + frtn = FR_IllegalArg; + goto abort; + } + privGiantBytes = abs(privGiant->sign) * GIANT_BYTES_PER_DIGIT; + + /* + * Note PmX = m 'o' P1. + * Get message/digest as giant. May be significantly different + * in size from pubKey's basePrime. + */ + messageGiant = giant_with_data(data, dataLen); // M(text) + randBytesLen = feePubKeyBitsize(pubKey) / 8; + maxlen = max(randBytesLen, dataLen); + + /* leave plenty of room.... */ + uDigits = (3 * (privGiantBytes + maxlen)) / GIANT_BYTES_PER_DIGIT; + sinst->u = newGiant(uDigits); + gtog(privGiant, sinst->u); // u := ourPri + mulg(messageGiant, sinst->u); // u *= M(text) + addg(sinst->randGiant, sinst->u); // u += m + + /* + * Paranoia: we're using the curveParams from the caller's pubKey; + * this cp will have a valid x1OrderPlusRecip if pubKey is the same + * as the one passed to feeSigNewWithKey() (since feeSigNewWithKey + * called x1OrderPlusJustify()). But the caller could conceivably be + * using a different instance of their pubKey, in which case + * the key's cp->x1OrderPlusRecip may not be valid. + */ + calcX1OrderPlusRecip(cp); + + /* u := u mod x1OrderPlus */ + #if SIG_DEBUG + if(sigDebug) { + printf("sigSign:\n"); + printf("u pre-modg : "); + printGiant(sinst->u); + } + #endif + modg_via_recip(cp->x1OrderPlus, cp->x1OrderPlusRecip, sinst->u); + + #if SIG_DEBUG + if(sigDebug) { + printf("privGiant : "); + printGiant(privGiant); + printf("u : "); + printGiant(sinst->u); + printf("messageGiant: "); + printGiant(messageGiant); + printf("curveParams :\n"); + printCurveParams(cp); + } + #endif // SIG_DEBUG +abort: + if(messageGiant) { + freeGiant(messageGiant); + } + return frtn; +} + +/* + * Given a feeSig processed by feeSigSign, obtain a malloc'd byte + * array representing the signature. + * See ByteRep.doc for info on the format of the signature string; + * PLEASE UPDATE THIS DOCUMENT WHEN YOU MAKE CHANGES TO THE STRING FORMAT. + */ +feeReturn feeSigData(feeSig sig, + unsigned char **sigData, // IGNORED....malloc'd and RETURNED + unsigned *sigDataLen) // RETURNED +{ + sigInst *sinst = (sigInst*) sig; + + #if CRYPTKIT_DER_ENABLE + return feeDEREncodeElGamalSignature(sinst->u, sinst->PmX, sigData, sigDataLen); + #else + *sigDataLen = lengthOfByteRepSig(sinst->u, sinst->PmX); + *sigData = (unsigned char*) fmalloc(*sigDataLen); + sigToByteRep(FEE_SIG_MAGIC, + FEE_SIG_VERSION, + FEE_SIG_VERSION_MIN, + sinst->u, + sinst->PmX, + *sigData); + return FR_Success; + #endif +} + +/* + * Obtain a feeSig object by parsing an existing signature block. + * Note that if Pm is used to salt a hash of the signed data, this must + * function must be called prior to hashing. + */ +feeReturn feeSigParse(const unsigned char *sigData, + size_t sigDataLen, + feeSig *sig) // RETURNED +{ + sigInst *sinst = NULL; + feeReturn frtn; + #if !CRYPTKIT_DER_ENABLE + int version; + int magic; + int minVersion; + int rtn; + #endif + + sinst = sinstAlloc(); + #if CRYPTKIT_DER_ENABLE + frtn = feeDERDecodeElGamalSignature(sigData, sigDataLen, &sinst->u, &sinst->PmX); + if(frtn) { + goto abort; + } + #else + rtn = byteRepToSig(sigData, + sigDataLen, + FEE_SIG_VERSION, + &magic, + &version, + &minVersion, + &sinst->u, + &sinst->PmX); + if(rtn == 0) { + frtn = FR_BadSignatureFormat; + goto abort; + } + switch(magic) { + case FEE_ECDSA_MAGIC: + frtn = FR_WrongSignatureType; // ECDSA! + goto abort; + case FEE_SIG_MAGIC: + break; // proceed + default: + frtn = FR_BadSignatureFormat; + goto abort; + } + #endif /* CRYPTKIT_DER_ENABLE */ + + #if SIG_DEBUG + if(sigDebug) { + printf("sigParse: \n"); + printf("u: "); + printGiant(sinst->u); + } + #endif // SIG_DEBUG + + *sig = sinst; + return FR_Success; + +abort: + if(sinst) { + feeSigFree(sinst); + } + return frtn; +} + +/* + * Verify signature, obtained via feeSigParse, for specified + * data (most likely a hash result) and feePubKey. Returns non-zero if + * signature valid. + */ + +#define LOG_BAD_SIG 0 + +#if CRYPTKIT_ELL_PROJ_ENABLE + +feeReturn feeSigVerifyNoProj(feeSig sig, + const unsigned char *data, + unsigned dataLen, + feePubKey pubKey); + +static void borrowPointProj(pointProj pt, unsigned maxDigits) +{ + pt->x = borrowGiant(maxDigits); + pt->y = borrowGiant(maxDigits); + pt->z = borrowGiant(maxDigits); +} + +static void returnPointProj(pointProj pt) +{ + returnGiant(pt->x); + returnGiant(pt->y); + returnGiant(pt->z); +} + +feeReturn feeSigVerify(feeSig sig, + const unsigned char *data, + unsigned dataLen, + feePubKey pubKey) +{ + pointProjStruct Q; + giant messageGiant = NULL; + pointProjStruct scratch; + sigInst *sinst = (sigInst*) sig; + feeReturn frtn; + curveParams *cp; + key origKey; // may be plus or minus key + + if(sinst->PmX == NULL) { + dbgLog(("sigVerify without parse!\n")); + return FR_IllegalArg; + } + + cp = feePubKeyCurveParams(pubKey); + if(cp->curveType != FCT_Weierstrass) { + return feeSigVerifyNoProj(sig, data, dataLen, pubKey); + } + + borrowPointProj(&Q, cp->maxDigits); + borrowPointProj(&scratch, cp->maxDigits); + + /* + * Q := P1 + */ + gtog(cp->x1Plus, Q.x); + gtog(cp->y1Plus, Q.y); + int_to_giant(1, Q.z); + + messageGiant = giant_with_data(data, dataLen); // M(ciphertext) + + /* Q := u 'o' P1 */ + ellMulProjSimple(&Q, sinst->u, cp); + + /* scratch := theirPub */ + origKey = feePubKeyPlusCurve(pubKey); + gtog(origKey->x, scratch.x); + gtog(origKey->y, scratch.y); + int_to_giant(1, scratch.z); + + #if SIG_DEBUG + if(sigDebug) { + printf("verify origKey:\n"); + printKey(origKey); + printf("messageGiant: "); + printGiant(messageGiant); + printf("curveParams:\n"); + printCurveParams(cp); + } + #endif // SIG_DEBUG + + /* scratch := M 'o' theirPub */ + ellMulProjSimple(&scratch, messageGiant, cp); + + #if SIG_DEBUG + if(sigDebug) { + printf("signature_compare, with\n"); + printf("p0 = Q:\n"); + printGiant(Q.x); + printf("p1 = Pm:\n"); + printGiant(sinst->PmX); + printf("p2 = scratch = R:\n"); + printGiant(scratch.x); + } + #endif // SIG_DEBUG + + if(signature_compare(Q.x, sinst->PmX, scratch.x, cp)) { + + frtn = FR_InvalidSignature; + #if LOG_BAD_SIG + printf("***yup, bad sig***\n"); + #endif // LOG_BAD_SIG + } + else { + frtn = FR_Success; + } + freeGiant(messageGiant); + + returnPointProj(&Q); + returnPointProj(&scratch); + return frtn; +} + +#else /* CRYPTKIT_ELL_PROJ_ENABLE */ + +#define feeSigVerifyNoProj(s, d, l, k) feeSigVerify(s, d, l, k) + +#endif /* CRYPTKIT_ELL_PROJ_ENABLE */ + +/* + * FEE_SIG_USING_PROJ true : this is the "no Weierstrass" case + * feeSigVerifyNoProj false : this is redefined to feeSigVerify + */ +feeReturn feeSigVerifyNoProj(feeSig sig, + const unsigned char *data, + unsigned dataLen, + feePubKey pubKey) +{ + giant Q = NULL; + giant messageGiant = NULL; + giant scratch = NULL; + sigInst *sinst = (sigInst*) sig; + feeReturn frtn; + curveParams *cp; + key origKey; // may be plus or minus key + + if(sinst->PmX == NULL) { + dbgLog(("sigVerify without parse!\n")); + frtn = FR_IllegalArg; + goto out; + } + + cp = feePubKeyCurveParams(pubKey); + Q = newGiant(cp->maxDigits); + + /* + * pick a key (+/-) + * Q := P1 + */ + if(SIG_CURVE == CURVE_PLUS) { + origKey = feePubKeyPlusCurve(pubKey); + gtog(cp->x1Plus, Q); + } + else { + origKey = feePubKeyMinusCurve(pubKey); + gtog(cp->x1Minus, Q); + } + + messageGiant = giant_with_data(data, dataLen); // M(ciphertext) + + /* Q := u 'o' P1 */ + elliptic_simple(Q, sinst->u, cp); + + /* scratch := theirPub */ + scratch = newGiant(cp->maxDigits); + gtog(origKey->x, scratch); + + #if SIG_DEBUG + if(sigDebug) { + printf("verify origKey:\n"); + printKey(origKey); + printf("messageGiant: "); + printGiant(messageGiant); + printf("curveParams:\n"); + printCurveParams(cp); + } + #endif // SIG_DEBUG + + /* scratch := M 'o' theirPub */ + elliptic_simple(scratch, messageGiant, cp); + + #if SIG_DEBUG + if(sigDebug) { + printf("signature_compare, with\n"); + printf("p0 = Q:\n"); + printGiant(Q); + printf("p1 = Pm:\n"); + printGiant(sinst->PmX); + printf("p2 = scratch = R:\n"); + printGiant(scratch); + } + #endif // SIG_DEBUG + + if(signature_compare(Q, sinst->PmX, scratch, cp)) { + + frtn = FR_InvalidSignature; + #if LOG_BAD_SIG + printf("***yup, bad sig***\n"); + #endif // LOG_BAD_SIG + } + else { + frtn = FR_Success; + } +out: + if(messageGiant != NULL) { + freeGiant(messageGiant); + } + if(Q != NULL) { + freeGiant(Q); + } + if(scratch != NULL) { + freeGiant(scratch); + } + return frtn; +} + +/* + * For given key, calculate maximum signature size. + */ +feeReturn feeSigSize( + feePubKey pubKey, + unsigned *maxSigLen) +{ + /* For now, assume that u and Pm.x in the signature are + * same size as the key's associated curveParams->basePrime. + * We might have to pad this a bit.... + */ + curveParams *cp = feePubKeyCurveParams(pubKey); + + if(cp == NULL) { + return FR_BadPubKey; + } + #if CRYPTKIT_DER_ENABLE + *maxSigLen = feeSizeOfDERSig(cp->basePrime, cp->basePrime); + #else + *maxSigLen = (unsigned)lengthOfByteRepSig(cp->basePrime, cp->basePrime); + #endif + return FR_Success; +} diff --git a/libsecurity_cryptkit/lib/feeDigitalSignature.h b/libsecurity_cryptkit/lib/feeDigitalSignature.h new file mode 100644 index 00000000..3f9b1b22 --- /dev/null +++ b/libsecurity_cryptkit/lib/feeDigitalSignature.h @@ -0,0 +1,111 @@ +/* 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. + *************************************************************************** + * + * feeDigitalSignature.h - generic, portable FEE Digital Signature object + * + * Revision History + * ---------------- + * 22 Aug 96 Doug Mitchell at NeXT + * Created. + */ + +#ifndef _CK_FEEDIGITALSIG_H_ +#define _CK_FEEDIGITALSIG_H_ + +#if !defined(__MACH__) +#include +#include +#else +#include +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#define FEE_SIG_MAGIC 0xfee00516 + +/* + * Opaque signature handle. + */ +typedef void *feeSig; + +/* + * Create new feeSig object, including a random large integer 'Pm' for + * possible use in salting a feeHash object. + */ +feeSig feeSigNewWithKey( + feePubKey pubKey, + feeRandFcn randFcn, /* optional */ + void *randRef); /* optional */ + +void feeSigFree( + feeSig sig); + +/* + * Obtain a malloc'd Pm after or feeSigNewWithKey() feeSigParse() + */ +unsigned char *feeSigPm( + feeSig sig, + unsigned *PmLen); /* RETURNED */ + +/* + * Sign specified block of data (most likely a hash result) using + * specified feePubKey. + */ +feeReturn feeSigSign( + feeSig sig, + const unsigned char *data, // data to be signed + unsigned dataLen, // in bytes + feePubKey pubKey); + +/* + * Given a feeSig processed by feeSigSign, obtain a malloc'd byte + * array representing the signature. + */ +feeReturn feeSigData( + feeSig sig, + unsigned char **sigData, // malloc'd and RETURNED + unsigned *sigDataLen); // RETURNED + +/* + * Obtain a feeSig object by parsing an existing signature block. + * Note that if Pm is used to salt a hash of the signed data, this must + * be performed prior to hashing. + */ +feeReturn feeSigParse( + const unsigned char *sigData, + size_t sigDataLen, + feeSig *sig); // RETURNED + +/* + * Verify signature, obtained via feeSigParse, for specified + * data (most likely a hash result) and feePubKey. Returns FR_Success or + * FR_InvalidSignature. + */ +feeReturn feeSigVerify( + feeSig sig, + const unsigned char *data, + unsigned dataLen, + feePubKey pubKey); + +/* + * For given key, calculate maximum signature size. + */ +feeReturn feeSigSize( + feePubKey pubKey, + unsigned *maxSigLen); + +#ifdef __cplusplus +} +#endif + +#endif /*_CK_FEEDIGITALSIG_H_*/ diff --git a/libsecurity_cryptkit/lib/feeECDSA.c b/libsecurity_cryptkit/lib/feeECDSA.c new file mode 100644 index 00000000..c312bf45 --- /dev/null +++ b/libsecurity_cryptkit/lib/feeECDSA.c @@ -0,0 +1,666 @@ +/* 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. + *************************************************************************** + * + * feeECDSA.c - Elliptic Curve Digital Signature Algorithm (per IEEE 1363) + * + * Revision History + * ---------------- + * 11/27/98 dmitch + * Added ECDSA_VERIFY_ONLY dependencies. + * 10/06/98 ap + * Changed to compile with C++. + * 3 Sep 98 Doug Mitchell at Apple + * Rewrote using projective elliptic algebra, per IEEE P1363. + * 17 Dec 97 Doug Mitchell at Apple + * Fixed c==0 bug in feeECDSAVerify() + * 16 Jul 97 Doug Mitchell at Apple, based on algorithms by Richard Crandall + * Created. + */ + +/**** + Nomenclature, per IEEE P1363 D1, Dec. 1997 + + G = initial public point = (x1Plus, y1Plus) as usual + x1OrderPlus = IEEE r = (always prime) order of x1Plus + f = message to be signed, generally a SHA1 message digest + s = signer's private key + W = signer's public key + * : integer multiplication, as in (x * y) + 'o' : elliptic multiply, as in (u 'o' G) + + Signing algorithm: + + 1) Obtain random u in [2, x1OrderPlus-2]; + 2) Compute x coordinate, call it c, of u 'o' G (elliptic mul); + 3) Reduce: c := c mod x1OrderPlus; + 4) If c = 0, goto (1); + 5) Compute u^(-1) (mod x1OrderPlus); + 6) Compute signature s as: + + d = [u^(-1) (f + (s*c))] (mod x1OrderPlus) + + 7) If d = 0, goto (1); + 8) Signature is the integer pair (c, d). Each integer + in the pair must be in [1, x1OrderPlus-1]. + + Note: therefore a component of the signature could be slightly + larger than base prime. + + Verification algorithm, given signature (c, d): + + 1) Compute h = d^(-1) (mod x1OrderPlus); + 2) Compute h1 = digest as giant integer (skips assigning to 'f' as in + IEEE spec) + 3) Compute h1 = h1 * h (mod x1OrderPlus) (i.e., = f * h) + 4) Compute h2 = c * h (mod x1OrderPlus); + 5) Compute h2W = h2 'o' W + 6) Compute h1G = h1 'o' G + 7) Compute elliptic sum of h1G + h2W + 8) If elliptic sum is point at infinity, signature is bad; stop. + 9) cPrime = x coordinate of elliptic sum, mod x1OrderPlus + 10) Signature is good iff cPrime == c. + +***********/ + +#include "ckconfig.h" + +#if CRYPTKIT_ECDSA_ENABLE + +#include "feeTypes.h" +#include "feePublicKey.h" +#include "feePublicKeyPrivate.h" +#include "giantIntegers.h" +#include "elliptic.h" +#include "feeRandom.h" +#include "curveParams.h" +#include "falloc.h" +#include "ckutilities.h" +#include "feeDebug.h" +#include "platform.h" +#include "byteRep.h" +#include +#include "feeECDSA.h" +#include "byteRep.h" +#include "feeDigitalSignature.h" +#include "ECDSA_Profile.h" +#include "ellipticProj.h" +#if CRYPTKIT_DER_ENABLE +#include "CryptKitDER.h" +#endif + +#ifndef ECDSA_VERIFY_ONLY +static void ECDSA_encode(giant c, + giant d, + unsigned char **sigData, // malloc'd and RETURNED + unsigned *sigDataLen); // RETURNED +#endif /* ECDSA_VERIFY_ONLY */ + +static feeReturn ECDSA_decode(const unsigned char *sigData, + size_t sigDataLen, + giant *gs, // alloc'd & RETURNED + giant *x0, // alloc'd & RETURNED + unsigned *sigVersion); // RETURNED + + +#define ECDSA_DEBUG 0 +#if ECDSA_DEBUG +int ecdsaDebug=1; /* tweakable at runtime via debugger */ +#define sigDbg(x) \ + if(ecdsaDebug) { \ + printf x; \ + } +#define sigLogGiant(s, g) \ + if(ecdsaDebug) { \ + printf(s); \ + printGiant(g) /*printGiantExp(g)*/; \ + } +#else // ECDSA_DEBUG +#define sigDbg(x) +#define sigLogGiant(s, g) +#endif // ECDSA_DEBUG + +#if ECDSA_PROFILE +/* + * Profiling accumulators. + */ +unsigned signStep1; +unsigned signStep2; +unsigned signStep34; +unsigned signStep5; +unsigned signStep67; +unsigned signStep8; +unsigned vfyStep1; +unsigned vfyStep3; +unsigned vfyStep4; +unsigned vfyStep5; +unsigned vfyStep6; +unsigned vfyStep7; +unsigned vfyStep8; +#endif // ECDSA_PROFILE + +/* + * Totally incompatible with feeDigitalSignature.c. Caller must be aware of + * signature format. We will detect an ElGamal signature, however, and + * return FR_WrongSignatureType from feeECDSAVerify(). + */ +#define FEE_ECDSA_VERSION 2 +#define FEE_ECDSA_VERSION_MIN 2 + +/* + * When true, use ellMulProjSimple rather than elliptic_simple in + * sign operation. Using ellMulProjSimple is a *big* win. + */ +#define ECDSA_SIGN_USE_PROJ 1 + +/* + * Sign specified block of data (most likely a hash result) using + * specified private key. Result, an enc64-encoded signature block, + * is returned in *sigData. + */ + +#ifndef ECDSA_VERIFY_ONLY + +feeReturn feeECDSASign(feePubKey pubKey, + const unsigned char *data, // data to be signed + unsigned dataLen, // in bytes + feeRandFcn randFcn, // optional + void *randRef, // optional + unsigned char **sigData, // malloc'd and RETURNED + unsigned *sigDataLen) // RETURNED +{ + curveParams *cp; + + /* giant integers per IEEE P1363 notation */ + + giant c; // both 1363 'c' and 'i' + // i.e., x-coord of u's pub key + giant d; + giant u; // random private key + giant s; // private key as giant + giant f; // data (message) as giant + + feeReturn frtn = FR_Success; + feeRand frand; + unsigned char *randBytes; + unsigned randBytesLen; + giant privGiant; + #if ECDSA_SIGN_USE_PROJ + pointProjStruct pt; // pt->x = c + giant pty; // pt->y + giant ptz; // pt->z + #endif // ECDSA_SIGN_USE_PROJ + + if(pubKey == NULL) { + return FR_BadPubKey; + } + cp = feePubKeyCurveParams(pubKey); + if(cp == NULL) { + return FR_BadPubKey; + } + if(cp->curveType != FCT_Weierstrass) { + return FR_IllegalCurve; + } + + CKASSERT(!isZero(cp->x1OrderPlus)); + + /* + * Private key and message to be signed as giants + */ + privGiant = feePubKeyPrivData(pubKey); + if(privGiant == NULL) { + dbgLog(("Attempt to Sign without private data\n")); + return FR_IllegalArg; + } + s = borrowGiant(cp->maxDigits); + gtog(privGiant, s); + if(dataLen > (cp->maxDigits * GIANT_BYTES_PER_DIGIT)) { + f = borrowGiant(BYTES_TO_GIANT_DIGITS(dataLen)); + } + else { + f = borrowGiant(cp->maxDigits); + } + deserializeGiant(data, f, dataLen); + + /* + * Certicom SEC1 states that if the digest is larger than the modulus, + * use the left q bits of the digest. + */ + unsigned hashBits = dataLen * 8; + if(hashBits > cp->q) { + gshiftright(hashBits - cp->q, f); + } + + sigDbg(("ECDSA sign:\n")); + sigLogGiant(" s : ", s); + sigLogGiant(" f : ", f); + + c = borrowGiant(cp->maxDigits); + d = borrowGiant(cp->maxDigits); + u = borrowGiant(cp->maxDigits); + if(randFcn == NULL) { + frand = feeRandAlloc(); + } + else { + frand = NULL; + } + + /* + * Random size is just larger than base prime + */ + randBytesLen = (feePubKeyBitsize(pubKey) / 8) + 1; + randBytes = (unsigned char*) fmalloc(randBytesLen); + + #if ECDSA_SIGN_USE_PROJ + /* quick temp pointProj */ + pty = borrowGiant(cp->maxDigits); + ptz = borrowGiant(cp->maxDigits); + pt.x = c; + pt.y = pty; + pt.z = ptz; + #endif // ECDSA_SIGN_USE_PROJ + + while(1) { + /* Repeat this loop until we have a non-zero c and d */ + + /* + * 1) Obtain random u in [2, x1OrderPlus-2] + */ + SIGPROF_START; + if(randFcn) { + randFcn(randRef, randBytes, randBytesLen); + } + else { + feeRandBytes(frand, randBytes, randBytesLen); + } + deserializeGiant(randBytes, u, randBytesLen); + x1OrderPlusJustify(u, cp); + SIGPROF_END(signStep1); + sigLogGiant(" u : ", u); + + /* + * note 'o' indicates elliptic multiply, * is integer mult. + * + * 2) Compute x coordinate, call it c, of u 'o' G + * 3) Reduce: c := c mod x1OrderPlus; + * 4) If c == 0, goto (1); + */ + SIGPROF_START; + gtog(cp->x1Plus, c); + + #if ECDSA_SIGN_USE_PROJ + + /* projective coordinates */ + gtog(cp->y1Plus, pty); + int_to_giant(1, ptz); + ellMulProjSimple(&pt, u, cp); + + #else /* ECDSA_SIGN_USE_PROJ */ + + /* the FEE way */ + elliptic_simple(c, u, cp); + + #endif /* ECDSA_SIGN_USE_PROJ */ + + SIGPROF_END(signStep2); + SIGPROF_START; + x1OrderPlusMod(c, cp); + SIGPROF_END(signStep34); + if(isZero(c)) { + dbgLog(("feeECDSASign: zero modulo (1)\n")); + continue; + } + + /* + * 5) Compute u^(-1) mod x1OrderPlus; + */ + SIGPROF_START; + gtog(u, d); + binvg_x1OrderPlus(cp, d); + SIGPROF_END(signStep5); + sigLogGiant(" u^(-1) : ", d); + + /* + * 6) Compute signature d as: + * d = [u^(-1) (f + s*c)] (mod x1OrderPlus) + */ + SIGPROF_START; + mulg(c, s); // s *= c + x1OrderPlusMod(s, cp); + addg(f, s); // s := f + (s * c) + x1OrderPlusMod(s, cp); + mulg(s, d); // d := u^(-1) (f + (s * c)) + x1OrderPlusMod(d, cp); + SIGPROF_END(signStep67); + + /* + * 7) If d = 0, goto (1); + */ + if(isZero(d)) { + dbgLog(("feeECDSASign: zero modulo (2)\n")); + continue; + } + sigLogGiant(" c : ", c); + sigLogGiant(" d : ", d); + break; // normal successful exit + } + + /* + * 8) signature is now the integer pair (c, d). + */ + + /* + * Cook up raw data representing the signature. + */ + SIGPROF_START; + ECDSA_encode(c, d, sigData, sigDataLen); + SIGPROF_END(signStep8); + + if(frand != NULL) { + feeRandFree(frand); + } + ffree(randBytes); + returnGiant(u); + returnGiant(d); + returnGiant(c); + returnGiant(f); + returnGiant(s); + #if ECDSA_SIGN_USE_PROJ + returnGiant(pty); + returnGiant(ptz); + #endif /* ECDSA_SIGN_USE_PROJ */ + return frtn; +} + +#endif /* ECDSA_VERIFY_ONLY */ + +/* + * Verify signature for specified data (most likely a hash result) and + * feePubKey. Returns FR_Success or FR_InvalidSignature. + */ + +#define LOG_BAD_SIG 0 + +feeReturn feeECDSAVerify(const unsigned char *sigData, + size_t sigDataLen, + const unsigned char *data, + unsigned dataLen, + feePubKey pubKey) +{ + /* giant integers per IEEE P1363 notation */ + giant h; // s^(-1) + giant h1; // f h + giant h2; // c times h + giant littleC; // newGiant from ECDSA_decode + giant littleD; // ditto + giant c; // borrowed, full size + giant d; // ditto + giant cPrime = NULL; // i mod r + pointProj h1G = NULL; // h1 'o' G + pointProj h2W = NULL; // h2 'o' W + key W; // i.e., their public key + + unsigned version; + feeReturn frtn; + curveParams *cp = feePubKeyCurveParams(pubKey); + int result; + + if(cp == NULL) { + return FR_BadPubKey; + } + + /* + * First decode the byteRep string. + */ + frtn = ECDSA_decode(sigData, + sigDataLen, + &littleC, + &littleD, + &version); + if(frtn) { + return frtn; + } + + /* + * littleC and littleD have capacity = abs(sign), probably + * not big enough.... + */ + c = borrowGiant(cp->maxDigits); + d = borrowGiant(cp->maxDigits); + gtog(littleC, c); + gtog(littleD, d); + freeGiant(littleC); + freeGiant(littleD); + + sigDbg(("ECDSA verify:\n")); + + /* + * W = signer's public key + */ + W = feePubKeyPlusCurve(pubKey); + + /* + * 1) Compute h = d^(-1) (mod x1OrderPlus); + */ + SIGPROF_START; + h = borrowGiant(cp->maxDigits); + gtog(d, h); + binvg_x1OrderPlus(cp, h); + SIGPROF_END(vfyStep1); + + /* + * 2) h1 = digest as giant (skips assigning to 'f' in P1363) + */ + if(dataLen > (cp->maxDigits * GIANT_BYTES_PER_DIGIT)) { + h1 = borrowGiant(BYTES_TO_GIANT_DIGITS(dataLen)); + } + else { + h1 = borrowGiant(cp->maxDigits); + } + deserializeGiant(data, h1, dataLen); + + /* + * Certicom SEC1 states that if the digest is larger than the modulus, + * use the left q bits of the digest. + */ + unsigned hashBits = dataLen * 8; + if(hashBits > cp->q) { + gshiftright(hashBits - cp->q, h1); + } + + sigLogGiant(" Wx : ", W->x); + sigLogGiant(" f : ", h1); + sigLogGiant(" c : ", c); + sigLogGiant(" d : ", d); + sigLogGiant(" s^(-1) : ", h); + + /* + * 3) Compute h1 = f * h mod x1OrderPlus; + */ + SIGPROF_START; + mulg(h, h1); // h1 := f * h + x1OrderPlusMod(h1, cp); + SIGPROF_END(vfyStep3); + + /* + * 4) Compute h2 = c * h (mod x1OrderPlus); + */ + SIGPROF_START; + h2 = borrowGiant(cp->maxDigits); + gtog(c, h2); + mulg(h, h2); // h2 := c * h + x1OrderPlusMod(h2, cp); + SIGPROF_END(vfyStep4); + + /* + * 5) Compute h2W = h2 'o' W (W = theirPub) + */ + CKASSERT((W->y != NULL) && !isZero(W->y)); + h2W = newPointProj(cp->maxDigits); + gtog(W->x, h2W->x); + gtog(W->y, h2W->y); + int_to_giant(1, h2W->z); + ellMulProjSimple(h2W, h2, cp); + + /* + * 6) Compute h1G = h1 'o' G (G = {x1Plus, y1Plus, 1} ) + */ + CKASSERT((cp->y1Plus != NULL) && !isZero(cp->y1Plus)); + h1G = newPointProj(cp->maxDigits); + gtog(cp->x1Plus, h1G->x); + gtog(cp->y1Plus, h1G->y); + int_to_giant(1, h1G->z); + ellMulProjSimple(h1G, h1, cp); + + /* + * 7) h1G := (h1 'o' G) + (h2 'o' W) + */ + ellAddProj(h1G, h2W, cp); + + /* + * 8) If elliptic sum is point at infinity, signature is bad; stop. + */ + if(isZero(h1G->z)) { + dbgLog(("feeECDSAVerify: h1 * G = point at infinity\n")); + result = 1; + goto vfyDone; + } + normalizeProj(h1G, cp); + + /* + * 9) cPrime = x coordinate of elliptic sum, mod x1OrderPlus + */ + cPrime = borrowGiant(cp->maxDigits); + gtog(h1G->x, cPrime); + x1OrderPlusMod(cPrime, cp); + + /* + * 10) Good sig iff cPrime == c + */ + result = gcompg(c, cPrime); + +vfyDone: + if(result) { + frtn = FR_InvalidSignature; + #if LOG_BAD_SIG + printf("***yup, bad sig***\n"); + #endif // LOG_BAD_SIG + } + else { + frtn = FR_Success; + } + + returnGiant(c); + returnGiant(d); + returnGiant(h); + returnGiant(h1); + returnGiant(h2); + if(h1G != NULL) { + freePointProj(h1G); + } + if(h2W != NULL) { + freePointProj(h2W); + } + if(cPrime != NULL) { + returnGiant(cPrime); + } + return frtn; +} + +#ifndef ECDSA_VERIFY_ONLY + +/* + * Encode to/from byteRep. + */ +static void ECDSA_encode(giant c, + giant d, + unsigned char **sigData, // malloc'd and RETURNED + unsigned *sigDataLen) // RETURNED +{ + #if CRYPTKIT_DER_ENABLE + feeDEREncodeECDSASignature(c, d, sigData, sigDataLen); + #else + *sigDataLen = lengthOfByteRepSig(c, d); + *sigData = (unsigned char*) fmalloc(*sigDataLen); + sigToByteRep(FEE_ECDSA_MAGIC, + FEE_ECDSA_VERSION, + FEE_ECDSA_VERSION_MIN, + c, + d, + *sigData); + #endif +} + +#endif /* ECDSA_VERIFY_ONLY */ + +static feeReturn ECDSA_decode(const unsigned char *sigData, + size_t sigDataLen, + giant *c, // alloc'd & RETURNED + giant *d, // alloc'd & RETURNED + unsigned *sigVersion) // RETURNED +{ + #if CRYPTKIT_DER_ENABLE + feeReturn frtn = feeDERDecodeECDSASignature(sigData, sigDataLen, c, d); + if(frtn == FR_Success) { + *sigVersion = FEE_ECDSA_VERSION; + } + return frtn; + #else + int magic; + int minVersion; + int rtn; + + rtn = byteRepToSig(sigData, + sigDataLen, + FEE_ECDSA_VERSION, + &magic, + (int *)sigVersion, + &minVersion, + c, + d); + if(rtn == 0) { + return FR_BadSignatureFormat; + } + switch(magic) { + case FEE_ECDSA_MAGIC: + return FR_Success; + case FEE_SIG_MAGIC: // ElGamal sig! + return FR_WrongSignatureType; + default: + return FR_BadSignatureFormat; + } + #endif +} + +/* + * For given key, calculate maximum signature size. + */ +feeReturn feeECDSASigSize( + feePubKey pubKey, + unsigned *maxSigLen) +{ + /* For now, assume that c and d in the signature are + * same size as the key's associated curveParams->basePrime. + * We might have to pad this a bit.... + */ + curveParams *cp = feePubKeyCurveParams(pubKey); + + if(cp == NULL) { + return FR_BadPubKey; + } + #if CRYPTKIT_DER_ENABLE + *maxSigLen = feeSizeOfDERSig(cp->basePrime, cp->basePrime); + #else + *maxSigLen = (unsigned)lengthOfByteRepSig(cp->basePrime, cp->basePrime); + #endif + return FR_Success; +} + +#endif /* CRYPTKIT_ECDSA_ENABLE */ + diff --git a/libsecurity_cryptkit/lib/feeECDSA.h b/libsecurity_cryptkit/lib/feeECDSA.h new file mode 100644 index 00000000..d092bb85 --- /dev/null +++ b/libsecurity_cryptkit/lib/feeECDSA.h @@ -0,0 +1,82 @@ +/* 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. + *************************************************************************** + * + * feeECDSA.h - Elliptic Curve Digital Signature Algorithm (per IEEE 1363) + * + * Revision History + * ---------------- + * 16 Jul 97 Doug Mitchell at Apple + * Created. + */ + +#ifndef _CK_FEEECDSA_H_ +#define _CK_FEEECDSA_H_ + +#if !defined(__MACH__) +#include +#include +#include +#else +#include +#include +#include +#endif + +/* + * Keep this one defined and visible even if we can't actually do ECDSA - feeSigParse() + * uses it to detect "wriong signature type". + */ +#define FEE_ECDSA_MAGIC 0xfee00517 + +#if CRYPTKIT_ECDSA_ENABLE + +#ifdef __cplusplus +extern "C" { +#endif + + +/* + * Sign specified block of data (most likely a hash result) using + * specified private key. Result, an enc64-encoded signature block, + * is returned in *sigData. + */ +feeReturn feeECDSASign(feePubKey pubKey, + const unsigned char *data, // data to be signed + unsigned dataLen, // in bytes + feeRandFcn randFcn, // optional + void *randRef, // optional + unsigned char **sigData, // malloc'd and RETURNED + unsigned *sigDataLen); // RETURNED + +/* + * Verify signature, obtained via feeECDSASign, for specified + * data (most likely a hash result) and feePubKey. Returns FR_Success or + * FR_InvalidSignature. + */ +feeReturn feeECDSAVerify(const unsigned char *sigData, + size_t sigDataLen, + const unsigned char *data, + unsigned dataLen, + feePubKey pubKey); + +/* + * For given key, calculate maximum signature size. + */ +feeReturn feeECDSASigSize( + feePubKey pubKey, + unsigned *maxSigLen); + +#ifdef __cplusplus +} +#endif + +#endif /* CRYPTKIT_ECDSA_ENABLE */ + +#endif /*_CK_FEEECDSA_H_*/ diff --git a/libsecurity_cryptkit/lib/feeFEED.c b/libsecurity_cryptkit/lib/feeFEED.c new file mode 100644 index 00000000..ecefc79d --- /dev/null +++ b/libsecurity_cryptkit/lib/feeFEED.c @@ -0,0 +1,1233 @@ +/* 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. + *************************************************************************** + * + * FeeFEED.c - generic, portable FEED encryption object, expanionless version + * + * Revision History + * ---------------- + * 10/06/98 ap + * Changed to compile with C++. + * 20 Jan 1998 Doug Mitchell at Apple + * Mods for primeType == PT_GENERAL case. + * 12 Jun 1997 Doug Mitchell at Apple + * Was curveOrderJustify(), is lesserX1OrderJustify() + * 31 Mar 1997 Doug Mitchell at Apple + * Fixed initialRS leak + * 3 Mar 1997 Doug Mitchell at Apple + * Trimmed plainBlockSize by one byte if q mod 8 = 0 + * 30 Jan 1997 Doug Mitchell at NeXT + * Created. + */ + +/* + * FIXME - a reusable init function would be nice (i.e., free up + * session-dependent state and re-init it)... + */ +#include "ckconfig.h" + +#if CRYPTKIT_ASYMMETRIC_ENABLE + +#include "feeTypes.h" +#include "feeFEED.h" +#include "feeFEEDExp.h" +#include "feePublicKey.h" +#include "feePublicKeyPrivate.h" +#include "elliptic.h" +#include "falloc.h" +#include "feeRandom.h" +#include "ckutilities.h" +#include "feeFunctions.h" +#include "platform.h" +#include "curveParams.h" +#include "feeDebug.h" +#include +#include + +#define FEED_DEBUG 0 +#define BUFFER_DEBUG 0 +#if BUFFER_DEBUG +#define bprintf(s) printf s +#else +#define bprintf(s) +#endif + +/* + * Minimum combined size of random r and s, in bytes. For small q sizes, + * r and s may be even smaller, but we never truncate them to smaller than + * this. + * This must be kept in sync with constant of same name in FEED.java. + */ +#define RS_MIN_SIZE 16 + +/* + * Private data. + */ +typedef struct { + curveParams *cp; + + /* + * the clues are initially (r * ourPriv * theirPub(+/-)). + */ + giant cluePlus; + giant clueMinus; + + /* + * sPlus and sMinus are based on the random s generated at encrypt + * time. Values are s * x1{Plus,Minus}. + */ + giant sPlus; + giant sMinus; + giant r; /* random, generated at encrypt time */ + unsigned plainBlockSize; /* plaintext block size */ + unsigned cipherBlockSize; /* ciphertext block size */ + unsigned char *initialRS; /* initial random R,S as bytes */ + unsigned initialRSSize; /* in bytes */ + feeFEEDExp feedExp; /* for encr/decr r+s params */ + + /* + * The first few blocks of ciphertext in a stream are the 2:1-FEED + * encrypted r and s parameters. While decrypting, we stash incoming + * ciphertext in rsCtext until we get enough ciphertext to decrypt + * initialRS. RsBlockCount keeps a running count of the + * cipherBlocks received. When rsBlockCount == rsSizeCipherBlocks, we + * FEEDExp-decrypt rsCtext to get r and s (actually, to get + * initialRS; r and s are extraced later in initFromRS()). + * + * During encrypt, if rsBlockCount is zero, the first thing we send as + * ciphertext is the FEED-encrypted initialRS. + */ + unsigned char *rsCtext; /* buffer for encrypted initialRS */ + unsigned rsBlockCount; /* running total of incoming rs + * cipherblocks */ + + int forEncrypt; /* added for feeFEED*TextSize() */ + + /* + * These are calculated at init time - for encrypt and + * decrypt - as an optimization. + */ + unsigned rsCtextSize; /* number of meaningful bytes in + * rsCtext */ + unsigned rsSizeCipherBlocks; /* # of our cipherblocks holding + * rsCtext */ + + /* + * temporary variables used for encrypt/decrypt. The values in these + * are not needed to be kept from block to block; we just + * alloc them once per lifetime of a feeFEED object as an optimization. + */ + giant xp; /* plaintext */ + giant xm; /* ciphertext */ + giant tmp1; /* scratch */ + giant tmp2; /* scratch */ +} feedInst; + +/* + * "zero residue" indicator. + */ +#define RESID_ZERO 0xff + +/* + * cons up: + * cluePlus(0) + * clueMinus(0) + * sPlus + * sMinus + * r + * Assumes: + * cluePlus = clueMinus = ourPriv * theirPub + * initialRS + * initialRSSize + * cp + * + * Called at feeFEEDNewWithPubKey while encrypting, or upon decrypting + * first block of data. + */ +static feeReturn initFromRS(feedInst *finst) +{ + giant s; + unsigned rSize = finst->initialRSSize / 2; + + #if FEED_DEBUG + if((finst->initialRS == NULL) || + (finst->cp == NULL) || + (finst->cluePlus == NULL) || + (finst->clueMinus == NULL) || + (finst->initialRSSize == 0)) { + dbgLog(("initFromRS: resource shortage\n")); + return FR_Internal; + } + #endif // FEED_DEBUG + + finst->r = giant_with_data(finst->initialRS, rSize); + s = giant_with_data(finst->initialRS+rSize, rSize); + + #if FEED_DEBUG + if(isZero(finst->r)) { + printf("initFromRS: r = 0! initialRSSize = %d; encr = %s\n", + finst->initialRSSize, + (finst->rsCtext == NULL) ? "TRUE" : "FALSE"); + } + if(isZero(s)) { + printf("initFromRS: s = 0! initialRSSize = %d; encr = %s\n", + finst->initialRSSize, + (finst->rsCtext == NULL) ? "TRUE" : "FALSE"); + } + #endif // FEE_DEBUG + /* + * Justify r and s to be in [2, minimumX1Order]. + */ + lesserX1OrderJustify(finst->r, finst->cp); + lesserX1OrderJustify(s, finst->cp); + + /* + * sPlus = s * x1Plus + * sMinus = s * x1Minus + */ + finst->sPlus = newGiant(finst->cp->maxDigits); + finst->sMinus = newGiant(finst->cp->maxDigits); + gtog(finst->cp->x1Plus, finst->sPlus); + elliptic_simple(finst->sPlus, s, finst->cp); + gtog(finst->cp->x1Minus, finst->sMinus); + elliptic_simple(finst->sMinus, s, finst->cp); + + /* + * And finally, the initial clues. They are currently set to + * ourPriv * theirPub. + */ + #if FEED_DEBUG + printf("cluePlus : "); printGiant(finst->cluePlus); + printf("clueMinus: "); printGiant(finst->clueMinus); + #endif // FEED_EEBUG + + elliptic_simple(finst->cluePlus, finst->r, finst->cp); + elliptic_simple(finst->clueMinus, finst->r, finst->cp); + + #if FEED_DEBUG + printf("r : "); printGiant(finst->r); + printf("s : "); printGiant(s); + printf("sPlus : "); printGiant(finst->sPlus); + printf("sMinus : "); printGiant(finst->sMinus); + printf("cluePlus : "); printGiant(finst->cluePlus); + printf("clueMinus: "); printGiant(finst->clueMinus); + #endif // FEED_DEBUG + + freeGiant(s); + return FR_Success; +} + +/* + * Alloc and init a feeFEED object associated with specified public and + * private keys. + */ +feeFEED feeFEEDNewWithPubKey(feePubKey myPrivKey, + feePubKey theirPubKey, + int forEncrypt, // 0 ==> decrypt 1 ==> encrypt + feeRandFcn randFcn, // optional + void *randRef) +{ + feedInst *finst; + giant privGiant; + key k; + unsigned expPlainSize; + unsigned expCipherSize; + unsigned expBlocks; + + if(!curveParamsEquivalent(feePubKeyCurveParams(theirPubKey), + feePubKeyCurveParams(myPrivKey))) { + dbgLog(("feeFEEDNewWithPubKey: Incompatible Keys\n")); + return NULL; + } + finst = (feedInst*) fmalloc(sizeof(feedInst)); + bzero(finst, sizeof(feedInst)); + finst->forEncrypt = forEncrypt; + finst->cp = curveParamsCopy(feePubKeyCurveParams(theirPubKey)); + finst->rsBlockCount = 0; + finst->xp = newGiant(finst->cp->maxDigits); + finst->xm = newGiant(finst->cp->maxDigits); + finst->tmp1 = newGiant(finst->cp->maxDigits); + if(forEncrypt) { + finst->tmp2 = newGiant(finst->cp->maxDigits); + } + + /* + * cluePlus = ourPriv * theirPub+ + * clueMinus = ourPriv * theirPub- + */ + finst->cluePlus = newGiant(finst->cp->maxDigits); + finst->clueMinus = newGiant(finst->cp->maxDigits); + privGiant = feePubKeyPrivData(myPrivKey); + if(privGiant == NULL) { + dbgLog(("feeFEEDNewWithPubKey: no private key\n")); + goto abort; + } + k = feePubKeyPlusCurve(theirPubKey); + gtog(k->x, finst->cluePlus); // cluePlus = theirPub+ + elliptic_simple(finst->cluePlus, privGiant, finst->cp); + k = feePubKeyMinusCurve(theirPubKey); + gtog(k->x, finst->clueMinus); // theirPub- + elliptic_simple(finst->clueMinus, privGiant, finst->cp); + + /* + * Set up block sizes. + */ + if(finst->cp->primeType == FPT_General) { + unsigned blen = bitlen(finst->cp->basePrime); + + finst->plainBlockSize = blen / 8; + if((blen & 0x7) == 0) { + /* + * round down some more... + */ + finst->plainBlockSize--; + } + } + else { + finst->plainBlockSize = finst->cp->q / 8; + if(((finst->cp->q & 0x7) == 0) && (finst->cp->k > 0)) { + /* + * Special case, with q mod 8 == 0. Here we have to + * trim back the plainBlockSize by one byte. + */ + finst->plainBlockSize--; + } + } + finst->cipherBlockSize = finst->cp->minBytes + 1; + + /* + * the size of initialRS is subject to tweaking - if we make it + * not a multiple of plainBlockSize, we save one FEEDExp cipherBlock + * in our ciphertext. + */ + finst->initialRSSize = finst->plainBlockSize * 2; + if(finst->initialRSSize > RS_MIN_SIZE) { + unsigned minPlainBlocks; + unsigned maxSize; + + /* + * How many plainblocks to hold RS_MIN_SIZE? + */ + minPlainBlocks = (RS_MIN_SIZE + finst->plainBlockSize - 1) / + finst->plainBlockSize; + + /* + * Max size = that many plainblocks, less 2 bytes (to avoid + * extra residue block). + */ + maxSize = minPlainBlocks * finst->plainBlockSize - 2; + + /* + * But don't bother with more than 2 plainblocks worth + */ + if(finst->initialRSSize > maxSize) { + finst->initialRSSize = maxSize; + } + } + /* else leave it alone, that's small enough */ + + if(forEncrypt) { + feeRand frand = NULL; + + /* + * Encrypt-capable FEEDExp object + */ + finst->feedExp = feeFEEDExpNewWithPubKey(theirPubKey, + randFcn, + randRef); + if(finst->feedExp == NULL) { + goto abort; + } + + /* + * Generate initial r and s data. + */ + finst->initialRS = (unsigned char*) fmalloc(finst->initialRSSize); + if(randFcn != NULL) { + randFcn(randRef, finst->initialRS, finst->initialRSSize); + } + else { + frand = feeRandAlloc(); + feeRandBytes(frand, finst->initialRS, finst->initialRSSize); + feeRandFree(frand); + } + if(initFromRS(finst)) { + goto abort; + } + } + else { + /* + * Decrypt-capable FEEDExp object + */ + finst->feedExp = feeFEEDExpNewWithPubKey(myPrivKey, + randFcn, + randRef); + if(finst->feedExp == NULL) { + goto abort; + } + + } + + /* + * Figure out how many of our cipherblocks it takes to hold + * a FEEDExp-encrypted initialRS. If initialRSSize is an exact + * multiple of expPlainSize, we get an additional feedExp + * residue block. + */ + expPlainSize = feeFEEDExpPlainBlockSize(finst->feedExp); + expCipherSize = feeFEEDExpCipherBlockSize(finst->feedExp); + expBlocks = (finst->initialRSSize + expPlainSize - 1) / + expPlainSize; + if((finst->initialRSSize % expPlainSize) == 0) { + expBlocks++; + } + + /* + * Total meaningful bytes of encrypted initialRS + */ + finst->rsCtextSize = expBlocks * expCipherSize; + + /* + * Number of our cipherblocks it takes to hold rsCtextSize + */ + finst->rsSizeCipherBlocks = (finst->rsCtextSize + + finst->cipherBlockSize - 1) / finst->cipherBlockSize; + if(!forEncrypt) { + finst->rsCtext = (unsigned char*) fmalloc(finst->rsSizeCipherBlocks * + finst->cipherBlockSize); + } + + /* + * Sanity check... + */ + #if FEED_DEBUG + { + unsigned fexpBlockSize = feeFEEDExpCipherBlockSize(finst->feedExp); + + /* + * FEEDExp has one more giant in ciphertext, plaintext is + * same size + */ + if((finst->cipherBlockSize + finst->cp->minBytes) != + fexpBlockSize) { + dbgLog(("feeFEEDNewWithPubKey: FEEDExp CBlock Size " + "screwup\n")); + goto abort; + } + fexpBlockSize = feeFEEDExpPlainBlockSize(finst->feedExp); + if(fexpBlockSize != finst->plainBlockSize) { + dbgLog(("feeFEEDNewWithPubKey: FEEDExp PBlock Size " + "screwup\n")); + goto abort; + } + } + #endif // FEED_DEBUG + + return finst; + +abort: + feeFEEDFree(finst); + return NULL; +} + +void feeFEEDFree(feeFEED feed) +{ + feedInst *finst = (feedInst*) feed; + + if(finst->cp) { + freeCurveParams(finst->cp); + } + if(finst->initialRS) { + ffree(finst->initialRS); + } + if(finst->cluePlus) { + freeGiant(finst->cluePlus); + } + if(finst->clueMinus) { + freeGiant(finst->clueMinus); + } + if(finst->sPlus) { + freeGiant(finst->sPlus); + } + if(finst->sMinus) { + freeGiant(finst->sMinus); + } + if(finst->r) { + freeGiant(finst->r); + } + if(finst->feedExp) { + feeFEEDExpFree(finst->feedExp); + } + if(finst->rsCtext) { + ffree(finst->rsCtext); + } + if(finst->xp) { + freeGiant(finst->xp); + } + if(finst->xm) { + freeGiant(finst->xm); + } + if(finst->tmp1) { + freeGiant(finst->tmp1); + } + if(finst->tmp2) { + freeGiant(finst->tmp2); + } + ffree(finst); +} + +unsigned feeFEEDPlainBlockSize(feeFEED feed) +{ + feedInst *finst = (feedInst *) feed; + + return finst->plainBlockSize; +} + +unsigned feeFEEDCipherBlockSize(feeFEED feed) +{ + feedInst *finst = (feedInst *) feed; + + return finst->cipherBlockSize; +} + +/* + * Calculate size of buffer currently needed to encrypt one block of + * plaintext. Also used to calculate required input during decrypt + * to get any output. + */ +unsigned feeFEEDCipherBufSize(feeFEED feed, + int finalBlock) +{ + feedInst *finst = (feedInst *) feed; + unsigned blocks = 1; // always at least one block of ciphertext + + if(finst->rsBlockCount == 0) { + /* haven't sent/seen encrypted RS yet */ + blocks += finst->rsSizeCipherBlocks; + } + + if(finalBlock) { + /* only needed if ptext is aligned, but tell caller to malloc */ + blocks++; + } + bprintf(("$$$ feeFEEDCipherBufSize( %s, %s): rtn 0x%x\n", + finst->forEncrypt ? "encrypt" : "decrypt", + finalBlock ? " final" : "!final", + blocks * finst->cipherBlockSize)); + return blocks * finst->cipherBlockSize; +} + +/* + * Return the size of ciphertext currently needed to encrypt specified + * size of plaintext. Also can be used to calculate size of ciphertext + * which can be decrypted into specified size of plaintext. + */ +unsigned feeFEEDCipherTextSize(feeFEED feed, + unsigned plainTextSize, + int finalBlock) +{ + feedInst *finst = (feedInst *) feed; + + /* how many blocks of plaintext? */ + unsigned blocks = (plainTextSize + finst->plainBlockSize - 1) / + finst->plainBlockSize; + + if(finst->forEncrypt) { + /* have we generated RS? */ + if(finst->rsBlockCount == 0) { + /* haven't sent encrypted RS yet */ + blocks += finst->rsSizeCipherBlocks; + } + + /* final? residue? */ + if(finalBlock) { + if((plainTextSize % finst->plainBlockSize) == 0) { + blocks++; + } + } + } /* encrypting */ + else { + /* + * Decrypting - how much ciphertext can we decrypt safely into + * specified plaintext? Add in RS if we haven't seen it all + * yet. + */ + #if BUFFER_DEBUG + if(finst->rsBlockCount > finst->rsSizeCipherBlocks) { + printf("******HEY! rsBlockCount overflow! (blockCount %d rsSize %d)\n", + finst->rsBlockCount, finst->rsSizeCipherBlocks); + } + #endif + blocks += (finst->rsSizeCipherBlocks - finst->rsBlockCount); + } + bprintf(("$$$ feeFEEDCipherTextSize(%s, %s, 0x%x): rtn 0x%x\n", + finst->forEncrypt ? "encrypt" : "decrypt", + finalBlock ? " final" : "!final", + plainTextSize, blocks * finst->cipherBlockSize)); + return blocks * finst->cipherBlockSize; +} + +/* + * Return the size of plaintext currently needed to decrypt specified size + * of ciphertext. Also can be used to calculate size of plaintext + * which can be encrypted into specified size of ciphertext. + */ +unsigned feeFEEDPlainTextSize(feeFEED feed, + unsigned cipherTextSize, + int finalBlock) // ignored if !forEncrypt +{ + feedInst *finst = (feedInst *) feed; + + /* start with basic cipher block count */ + unsigned cipherBlocks = (cipherTextSize + finst->cipherBlockSize - 1) / + finst->cipherBlockSize; + + /* where are we in the RS stream? */ + unsigned rsBlocksToGo = finst->rsSizeCipherBlocks - finst->rsBlockCount; + if(finst->forEncrypt) { + /* + * Encrypting, seeking plaintext size we can encrypt given + * a specified size of ciphertext. + */ + if(rsBlocksToGo >= cipherBlocks) { + /* no room! next encrypt would overflow ctext buffer! */ + return 0; + } + cipherBlocks -= rsBlocksToGo; + + /* another constraint - residue */ + if(finalBlock) { + if(cipherBlocks) { + /* skip if already zero... */ + cipherBlocks--; + } + } + } /* encrypting */ + else { + /* decrypting */ + if(rsBlocksToGo >= cipherBlocks) { + /* still processing RS, no plaintext will be generated. Play it real + * safe and just tell caller one block. */ + cipherBlocks = 1; + } + else { + /* diminish by size of RS to be gobbled with no output */ + cipherBlocks -= rsBlocksToGo; + } + } + bprintf(("$$$ feeFEEDPlainTextSize( %s, %s, 0x%x): rtn 0x%x\n", + finst->forEncrypt ? "encrypt" : "decrypt", + finalBlock ? " final" : "!final", + cipherTextSize, cipherBlocks * finst->plainBlockSize)); + return cipherBlocks * finst->plainBlockSize; +} + +/* + * Bits in last byte of cipherblock + */ +#define CLUE_BIT 0x01 /* 1 ==> plus curve */ +#define CLUE_PLUS 0x01 +#define CLUE_MINUS 0x00 +#define PARITY_BIT 0x02 /* 1 ==> plus 's' arg to elliptic_add() */ +#define PARITY_PLUS 0x02 +#define PARITY_MINUS 0x00 + +/* + * Encrypt a block or less of data. Caller malloc's cipherText. + * Generates up to feeFEEDCipherBufSize() bytes of ciphertext. + */ +feeReturn feeFEEDEncryptBlock(feeFEED feed, + const unsigned char *plainText, + unsigned plainTextLen, + unsigned char *cipherText, + unsigned *cipherTextLen, // RETURNED + int finalBlock) +{ + feedInst *finst = (feedInst *) feed; + unsigned ctextLen = 0; + feeReturn frtn = FR_Success; + int whichCurve; + giant thisClue; // not alloc'd or freed + giant thisS; // ditto + unsigned char clueByte; + + if(plainTextLen > finst->plainBlockSize) { + return FR_IllegalArg; + } + if((plainTextLen < finst->plainBlockSize) && !finalBlock) { + return FR_IllegalArg; + } + if(finst->initialRS == NULL) { + /* + * Init'd for decrypt? + */ + return FR_IllegalArg; + } + + /* + * First block - encrypt initialRS via FEEDExp + */ + if(finst->rsBlockCount == 0) { + unsigned char *thisCtext; // malloc's by FEEDExp + unsigned padLen; + + if(finst->initialRS == NULL) { + /* + * init'd for decrypt or reused + */ + dbgLog(("feeFEEDEncryptBlock: NULL initialRS!\n")); + return FR_IllegalArg; + } + + frtn = feeFEEDExpEncrypt(finst->feedExp, + finst->initialRS, + finst->initialRSSize, + &thisCtext, + &ctextLen); + if(frtn) { + /* + * Should never happen... + */ + dbgLog(("feeFEEDEncryptBlock: error writing encrypted" + " initialRS (%s)\n", feeReturnString(frtn))); + return FR_Internal; + } + bcopy(thisCtext, cipherText, ctextLen); + cipherText += ctextLen; + ffree(thisCtext); + + finst->rsBlockCount = finst->rsSizeCipherBlocks; + padLen = finst->cipherBlockSize - + (ctextLen % finst->cipherBlockSize); // zeros to write + + #if 0 /* FEED_DEBUG */ + + /* + * Hard-coded assumptions and tests about initRSSize... + * Currently we assume that initRSSize % expBlockSize = 0 + */ + if((ctextLen / finst->cipherBlockSize) != 5) { + dbgLog(("feeFEEDEncryptBlock: cipherblock size screwup (1)\n")); + return FR_Internal; + } + if(padLen != 3) { + dbgLog(("feeFEEDEncryptBlock: cipherblock size screwup (2)\n")); + return FR_Internal; + } + #endif // FEED_DEBUG + + /* + * pad to multiple of (our) cipherblock size. + */ + while(padLen) { + *cipherText++ = 0; + ctextLen++; + padLen--; + } + } + + /* + * plaintext to giant xp + */ + if(finalBlock) { + unsigned char *ptext = (unsigned char*) fmalloc(finst->plainBlockSize); + bzero(ptext, finst->plainBlockSize); + if(plainTextLen) { + /* + * skip for empty block with resid length 0 + */ + bcopy(plainText, ptext, plainTextLen); + } + if(plainTextLen < finst->plainBlockSize) { + if(plainTextLen == 0) { + /* + * Special case - resid block with no actual plaintext. + * Can't actually write zero here; it screws up + * deserializing the giant during decrypt + */ + ptext[finst->plainBlockSize - 1] = RESID_ZERO; + bprintf(("=== FEED encrypt: RESID_ZERO\n")); + } + else { + ptext[finst->plainBlockSize - 1] = plainTextLen; + bprintf(("=== FEED encrypt: resid len 0x%x\n", plainTextLen)); + } + } + /* + * else handle evenly aligned case (i.e., finalBlock true + * and (plainTextLen == plainBlockSize)) below... + */ + deserializeGiant(ptext, finst->xp, finst->plainBlockSize); + ffree(ptext); + } + else { + deserializeGiant(plainText, finst->xp, plainTextLen); + } + + /* + * encrypt xp + * xm = xp + clue(+/-) + * determine parity needed to restore xp + * parity = ((xm + clue(+/-) == xp) ? 1 : -1 + * and adjust clue + * clue[n+1] = r * clue[n] + (s * P1) + */ + whichCurve = which_curve(finst->xp, finst->cp); + if(whichCurve == CURVE_PLUS) { + thisClue = finst->cluePlus; + thisS = finst->sPlus; + clueByte = CLUE_PLUS; + } + else { + thisClue = finst->clueMinus; + thisS = finst->sMinus; + clueByte = CLUE_MINUS; + } + // calculate xm + elliptic_add(thisClue, finst->xp, finst->xm, finst->cp, SIGN_PLUS); + // save xm + clue in tmp1 + elliptic_add(finst->xm, thisClue, finst->tmp1, finst->cp, SIGN_PLUS); + // Adjust clue + elliptic_simple(thisClue, finst->r, finst->cp); + gtog(thisClue, finst->tmp2); + elliptic_add(finst->tmp2, thisS, thisClue, finst->cp, SIGN_PLUS); + + /* + * Calculate parity + */ + if(gcompg(finst->tmp1, finst->xp) == 0) { + clueByte |= PARITY_PLUS; + } + + /* + * Ciphertext = (xm, clueByte) + */ + serializeGiant(finst->xm, cipherText, finst->cp->minBytes); + cipherText += finst->cp->minBytes; + ctextLen += finst->cp->minBytes; + *cipherText++ = clueByte; + ctextLen++; + + #if FEED_DEBUG + printf("encrypt clue %d\n", clueByte); + printf(" xp : "); printGiant(finst->xp); + printf(" xm : "); printGiant(finst->xm); + printf(" cluePlus :"); printGiant(finst->cluePlus); + printf(" clueMinus :"); printGiant(finst->clueMinus); + #endif // FEED_DEBUG + + if(finalBlock && (plainTextLen == finst->plainBlockSize)) { + /* + * Special case: finalBlock true, plainTextLen == blockSize. + * In this case we generate one more block of ciphertext, + * with a resid length of zero. + */ + unsigned moreCipher; // additional cipherLen + + frtn = feeFEEDEncryptBlock(feed, + NULL, // plainText not used + 0, // resid + cipherText, // append... + &moreCipher, + 1); + if(frtn == FR_Success) { + ctextLen += moreCipher; + } + } + bprintf(("=== FEED encryptBlock ptextLen 0x%x ctextLen 0x%x\n", + plainTextLen, ctextLen)); + + *cipherTextLen = ctextLen; + return frtn; +} + +/* + * Decrypt (exactly) a block of data. Caller malloc's plainText. Always + * generates feeFEEDPlainBlockSize of plaintext, unless finalBlock is + * non-zero (in which case feeFEEDPlainBlockSize or less bytes of plainText are + * generated). + */ +feeReturn feeFEEDDecryptBlock(feeFEED feed, + const unsigned char *cipherText, + unsigned cipherTextLen, + unsigned char *plainText, + unsigned *plainTextLen, // RETURNED + int finalBlock) +{ + feedInst *finst = (feedInst *) feed; + feeReturn frtn = FR_Success; + unsigned char clueByte; + giant thisClue; // not alloc'd + giant thisS; // ditto + int parity; + + if(finst->rsCtext == NULL) { + /* + * Init'd for encrypt? + */ + return FR_IllegalArg; + } + if(cipherTextLen != finst->cipherBlockSize) { + dbgLog(("feeFEEDDecryptBlock: bad cipherTextLen\n")); + return FR_IllegalArg; + } + if(finst->rsBlockCount < finst->rsSizeCipherBlocks) { + /* + * Processing initialRS, FEEDExp-encrypted + */ + unsigned char *rsPtr = finst->rsCtext + + (finst->rsBlockCount * finst->cipherBlockSize); + unsigned feedExpCipherSize; + + if(finalBlock) { + dbgLog(("feeFEEDDecryptBlock: incomplete initialRS\n")); + return FR_BadCipherText; + } + bcopy(cipherText, rsPtr, finst->cipherBlockSize); + finst->rsBlockCount++; + if(finst->rsBlockCount < finst->rsSizeCipherBlocks) { + /* + * Not done with this yet... + */ + bprintf(("=== FEED Decrypt: gobbled 0x%x bytes ctext, no ptext (1)\n", + cipherTextLen)); + *plainTextLen = 0; + return FR_Success; + } + + #if FEED_DEBUG + if((finst->rsBlockCount * finst->cipherBlockSize) < + finst->rsCtextSize) { + dbgLog(("feeFEEDDecryptBlock: rsCtextSize underflow!\n")); + return FR_Internal; + } + #endif // FEED_DEBUG + + /* + * OK, we should have the FEEDExp ciphertext for initialRS + * in rsCtext. Note the last few bytes are extra; we don't + * pass them to FEEDExp. + */ + feedExpCipherSize = feeFEEDCipherBlockSize(finst->feedExp); + frtn = feeFEEDExpDecrypt(finst->feedExp, + finst->rsCtext, + finst->rsCtextSize, + &finst->initialRS, + &finst->initialRSSize); + if(frtn) { + dbgLog(("feeFEEDDecryptBlock: error decrypting " + "initialRS (%s)\n", feeReturnString(frtn))); + return FR_BadCipherText; + } + + /* + * we already know how long this should be... + */ + if(finst->initialRSSize != finst->initialRSSize) { + dbgLog(("feeFEEDDecryptBlock: initialRS sync error\n")); + return FR_BadCipherText; + } + + /* + * Set up clues + */ + if(initFromRS(finst)) { + dbgLog(("feeFEEDDecryptBlock: bad initialRS\n")); + return FR_BadCipherText; + } + else { + /* + * Normal completion of last cipherblock containing + * initialRS. + */ + bprintf(("=== FEED Decrypt: gobbled 0x%x bytes ctext, no ptext (2)\n", + cipherTextLen)); + *plainTextLen = 0; + return FR_Success; + } + } + + /* + * grab xm and clueByte from cipherText + */ + deserializeGiant(cipherText, finst->xm, finst->cp->minBytes); + cipherText += finst->cp->minBytes; + clueByte = *cipherText; + + if((clueByte & CLUE_BIT) == CLUE_PLUS) { + thisClue = finst->cluePlus; + thisS = finst->sPlus; + } + else { + thisClue = finst->clueMinus; + thisS = finst->sMinus; + } + if((clueByte & PARITY_BIT) == PARITY_PLUS) { + parity = SIGN_PLUS; + } + else { + parity = SIGN_MINUS; + } + + /* + * recover xp + * xp = xm + clue(+/-) w/parity + * adjust clue + * clue[n+1] = r * clue[n] + (s * P1) + */ + elliptic_add(thisClue, finst->xm, finst->xp, finst->cp, parity); + + elliptic_simple(thisClue, finst->r, finst->cp); + gtog(thisClue, finst->tmp1); + elliptic_add(finst->tmp1, thisS, thisClue, finst->cp, SIGN_PLUS); + + /* + * plaintext in xp + */ + #if FEED_DEBUG + printf("decrypt clue %d\n", clueByte); + printf(" xp : "); printGiant(finst->xp); + printf(" xm : "); printGiant(finst->xm); + printf(" cluePlus :"); printGiant(finst->cluePlus); + printf(" clueMinus :"); printGiant(finst->clueMinus); + #endif // FEED_DEBUG + + if(finalBlock) { + /* + * Snag data from xp in order to find out how much to move to + * *plainText + */ + unsigned char *ptext = (unsigned char*) fmalloc(finst->plainBlockSize); + + serializeGiant(finst->xp, ptext, finst->plainBlockSize); + *plainTextLen = ptext[finst->plainBlockSize - 1]; + if(*plainTextLen == RESID_ZERO) { + bprintf(("=== FEED Decrypt: RESID_ZERO\n")); + *plainTextLen = 0; + } + else if(*plainTextLen > (finst->plainBlockSize - 1)) { + dbgLog(("feeFEEDDecryptBlock: ptext overflow!\n")); + bprintf(("feeFEEDDecryptBlock: ptext overflow!\n")); + frtn = FR_BadCipherText; + } + else { + bprintf(("=== FEED Decrypt: resid len 0x%x\n", *plainTextLen)); + bcopy(ptext, plainText, *plainTextLen); + } + ffree(ptext); + } + else { + *plainTextLen = finst->plainBlockSize; + serializeGiant(finst->xp, plainText, *plainTextLen); + } + bprintf(("=== FEED decryptBlock ptextLen 0x%x ctextLen 0x%x\n", + *plainTextLen, cipherTextLen)); + + return frtn; +} + +/* + * Convenience routines to encrypt & decrypt multi-block data. + */ +feeReturn feeFEEDEncrypt(feeFEED feed, + const unsigned char *plainText, + unsigned plainTextLen, + unsigned char **cipherText, // malloc'd and RETURNED + unsigned *cipherTextLen) // RETURNED +{ + const unsigned char *ptext; // per block + unsigned ptextLen; // total to go + unsigned thisPtextLen; // per block + unsigned char *ctext; // per block + unsigned ctextLen; // per block + unsigned char *ctextResult; // to return + unsigned ctextResultLen; // size of ctextResult + unsigned char *ctextPtr; + unsigned ctextLenTotal; // running total + feeReturn frtn; + int finalBlock; + unsigned numBlocks; + unsigned plainBlockSize; + #if FEE_DEBUG + unsigned expectedCtextSize; + + expectedCtextSize = feeFEEDCipherTextSize(feed, plainTextLen, 1); + #endif + + if(plainTextLen == 0) { + dbgLog(("feeFEEDDecrypt: NULL plainText\n")); + return FR_IllegalArg; + } + + ptext = plainText; + ptextLen = plainTextLen; + ctext = (unsigned char*) fmalloc(feeFEEDCipherBufSize(feed, 1)); + plainBlockSize = feeFEEDPlainBlockSize(feed); + numBlocks = (plainTextLen + plainBlockSize - 1)/plainBlockSize; + + /* + * Calculate the worst-case size needed to hold all of the ciphertext + */ + ctextResultLen = feeFEEDCipherTextSize(feed, plainTextLen, 1); + ctextResult = (unsigned char*) fmalloc(ctextResultLen); + ctextPtr = ctextResult; + ctextLenTotal = 0; + + while(1) { + if(ptextLen <= plainBlockSize) { + finalBlock = 1; + thisPtextLen = ptextLen; + } + else { + finalBlock = 0; + thisPtextLen = plainBlockSize; + } + frtn = feeFEEDEncryptBlock(feed, + ptext, + thisPtextLen, + ctext, + &ctextLen, + finalBlock); + if(frtn) { + dbgLog(("feeFEEDEncrypt: encrypt error: %s\n", + feeReturnString(frtn))); + break; + } + if(ctextLen == 0) { + dbgLog(("feeFEEDEncrypt: null ciphertext\n")); + frtn = FR_Internal; + break; + } + bcopy(ctext, ctextPtr, ctextLen); + ctextLenTotal += ctextLen; + if(ctextLenTotal > ctextResultLen) { + dbgLog(("feeFEEDEncrypt: ciphertext overflow\n")); + frtn = FR_Internal; + break; + } + if(finalBlock) { + break; + } + ctextPtr += ctextLen; + ptext += thisPtextLen; + ptextLen -= thisPtextLen; + } + + ffree(ctext); + if(frtn) { + ffree(ctextResult); + *cipherText = NULL; + *cipherTextLen = 0; + } + else { + *cipherText = ctextResult; + *cipherTextLen = ctextLenTotal; + #if FEE_DEBUG + if(expectedCtextSize != ctextLenTotal) { + printf("feeFEEDEncrypt: feeFEEDCipherTextSize error!\n"); + printf("ptext %d exp ctext %d actual ctext %d\n", + plainTextLen, + expectedCtextSize, + ctextLenTotal); + } + #endif // FEE_DEBUG + } + return frtn; + +} + +feeReturn feeFEEDDecrypt(feeFEED feed, + const unsigned char *cipherText, + unsigned cipherTextLen, + unsigned char **plainText, // malloc'd and RETURNED + unsigned *plainTextLen) // RETURNED +{ + const unsigned char *ctext; + unsigned ctextLen; // total to go + unsigned char *ptext; // per block + unsigned ptextLen; // per block + unsigned char *ptextResult; // to return + unsigned char *ptextPtr; + unsigned ptextLenTotal; // running total + feeReturn frtn = FR_Success; + int finalBlock; + unsigned numBlocks; + unsigned plainBlockSize = feeFEEDPlainBlockSize(feed); + unsigned cipherBlockSize = feeFEEDCipherBlockSize(feed); + + if(cipherTextLen % cipherBlockSize) { + dbgLog(("feeFEEDDecrypt: unaligned cipherText\n")); + return FR_BadCipherText; + } + if(cipherTextLen == 0) { + dbgLog(("feeFEEDDecrypt: NULL cipherText\n")); + return FR_BadCipherText; + } + + ptext = (unsigned char*) fmalloc(plainBlockSize); + ctext = cipherText; + ctextLen = cipherTextLen; + numBlocks = cipherTextLen / cipherBlockSize; + ptextResult = (unsigned char*) fmalloc(plainBlockSize * numBlocks); + ptextPtr = ptextResult; + ptextLenTotal = 0; + + while(ctextLen) { + if(ctextLen == cipherBlockSize) { + finalBlock = 1; + } + else { + finalBlock = 0; + } + frtn = feeFEEDDecryptBlock(feed, + ctext, + cipherBlockSize, + ptext, + &ptextLen, + finalBlock); + if(frtn) { + dbgLog(("feeFEEDDecryptBlock: %s\n", + feeReturnString(frtn))); + break; + } + if(ptextLen) { + if(ptextLen > plainBlockSize) { + dbgLog(("feeFEEDDecrypt: ptext overflow!\n")); + frtn = FR_Internal; + break; + } + bcopy(ptext, ptextPtr, ptextLen); + ptextPtr += ptextLen; + ptextLenTotal += ptextLen; + } + /* + * note ptextLen == 0 is normal termination case for + * plainTextLen % plainBlockSize == 0. + * Also expected for first 4 blocks of ciphertext; + * proceed (we break when ctextLen is exhausted). + */ + ctext += cipherBlockSize; + ctextLen -= cipherBlockSize; + } + + ffree(ptext); + if(frtn) { + ffree(ptextResult); + *plainText = NULL; + *plainTextLen = 0; + } + else { + *plainText = ptextResult; + *plainTextLen = ptextLenTotal; + } + return frtn; + +} + +#endif /* CRYPTKIT_ASYMMETRIC_ENABLE */ diff --git a/libsecurity_cryptkit/lib/feeFEED.h b/libsecurity_cryptkit/lib/feeFEED.h new file mode 100644 index 00000000..e825e480 --- /dev/null +++ b/libsecurity_cryptkit/lib/feeFEED.h @@ -0,0 +1,140 @@ +/* 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. + *************************************************************************** + * + * FeeFEED.h - generic, portable FEED encryption object + * + * Revision History + * ---------------- + * 28 Aug 96 Doug Mitchell at NeXT + * Created. + */ + +#ifndef _CK_FEEFEED_H_ +#define _CK_FEEFEED_H_ + +#if !defined(__MACH__) +#include +#include +#include +#else +#include +#include +#include +#endif + +#if CRYPTKIT_ASYMMETRIC_ENABLE + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Opaque object handle. + */ +typedef void *feeFEED; + +/* + * forEncrypt argument values. + */ +#define FF_DECRYPT 0 +#define FF_ENCRYPT 1 + +/* + * Alloc and init a feeFEED object associated with specified feePubKey + * objects. + */ +feeFEED feeFEEDNewWithPubKey(feePubKey myPrivKey, + feePubKey theirPubKey, + int forEncrypt, // FF_DECRYPT, FF_ENCRYPT + feeRandFcn randFcn, // optional + void *randRef); + +void feeFEEDFree(feeFEED feed); + +/* + * Plaintext block size. + */ +unsigned feeFEEDPlainBlockSize(feeFEED feed); + +/* + * Ciphertext block size used for decryption. + */ +unsigned feeFEEDCipherBlockSize(feeFEED feed); + +/* + * Calculate size of buffer currently needed to encrypt one block of + * plaintext. + */ +unsigned feeFEEDCipherBufSize(feeFEED feed, + int finalBlock); + +/* + * Return the size of ciphertext currently needed to encrypt specified + * size of plaintext. Also can be used to calculate size of ciphertext + * which can be decrypted into specified size of plaintext. + */ +unsigned feeFEEDCipherTextSize(feeFEED feed, + unsigned plainTextSize, + int finalBlock); + +/* + * Return the size of plaintext currently needed to decrypt specified size + * of ciphertext. Also can be used to calculate size of plaintext + * which can be encrypted into specified size of ciphertext. + */ +unsigned feeFEEDPlainTextSize(feeFEED feed, + unsigned cipherTextSize, + int finalBlock); // ignored if decrypting + +/* + * Encrypt a block or less of data. Caller malloc's cipherText. + */ +feeReturn feeFEEDEncryptBlock(feeFEED feed, + const unsigned char *plainText, + unsigned plainTextLen, + unsigned char *cipherText, + unsigned *cipherTextLen, // RETURNED + int finalBlock); + +/* + * Decrypt (exactly) a block of data. Caller malloc's plainText. Always + * generates feeFEEDBlockSize bytes of plainText, unless 'finalBlock' is + * non-zero (in which case feeFEEDBlockSize or less bytes of plainText are + * generated). + */ +feeReturn feeFEEDDecryptBlock(feeFEED feed, + const unsigned char *cipherText, + unsigned cipherTextLen, + unsigned char *plainText, + unsigned *plainTextLen, // RETURNED + int finalBlock); + +/* + * Convenience routines to encrypt & decrypt multi-block data. + */ +feeReturn feeFEEDEncrypt(feeFEED feed, + const unsigned char *plainText, + unsigned plainTextLen, + unsigned char **cipherText, // malloc'd and RETURNED + unsigned *cipherTextLen); // RETURNED + +feeReturn feeFEEDDecrypt(feeFEED feed, + const unsigned char *cipherText, + unsigned cipherTextLen, + unsigned char **plainText, // malloc'd and RETURNED + unsigned *plainTextLen); // RETURNED + +#ifdef __cplusplus +} +#endif + +#endif /* CRYPTKIT_ASYMMETRIC_ENABLE */ + +#endif /*_CK_FEEFEED_H_*/ diff --git a/libsecurity_cryptkit/lib/feeFEEDExp.c b/libsecurity_cryptkit/lib/feeFEEDExp.c new file mode 100644 index 00000000..685c2968 --- /dev/null +++ b/libsecurity_cryptkit/lib/feeFEEDExp.c @@ -0,0 +1,735 @@ +/* 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. + *************************************************************************** + * + * FeeFEEDExp.c - generic FEED encryption object, 2:1 expansion + * + * Revision History + * ---------------- + * 10/06/98 ap + * Changed to compile with C++. + * 20 Jan 1998 Doug Mitchell at Apple + * Mods for primeType == PT_GENERAL case. + * 12 Jun 1997 Doug Mitchell at Apple + * Was curveOrderJustify(), is lesserX1OrderJustify() + * 03 Mar 1997 Doug Mitchell at Apple + * Trimmed plainBlockSize by one byte if q mod 8 = 0 + * 03 Feb 97 Doug Mitchell at NeXT + * Renamed to feeFEEDExp.c + * Justified random xaux to [2, minimumX1Order] + * Added feeFEEDExpCipherTextSize() + * 15 Jan 97 Doug Mitchell at NeXT + * Cleaned up which_curve/index code to use CURVE_MINUS/CURVE_PLUS + * 28 Aug 96 Doug Mitchell at NeXT + * Created from Blaine Garst's NSFEECryptor.m. + */ + +#include "ckconfig.h" + +#if CRYPTKIT_ASYMMETRIC_ENABLE + +#include "feeTypes.h" +#include "feeFEEDExp.h" +#include "feePublicKey.h" +#include "feePublicKeyPrivate.h" +#include "elliptic.h" +#include "falloc.h" +#include "feeRandom.h" +#include "ckutilities.h" +#include "feeFunctions.h" +#include "platform.h" +#include "feeDebug.h" +#include + +#define FEED_DEBUG 0 + +#define PRINT_GIANT(g) printGiant(g) + +/* + * Format of clue byte. Currently just one bit. + */ +#define CLUE_ELL_ADD_SIGN 0x01 +#define CLUE_ELL_ADD_SIGN_PLUS 0x01 +#define CLUE_ELL_ADD_SIGN_MINUS 0x00 + +/* + * Private data. + */ +typedef struct { + key plus; + key minus; + unsigned plainBlockSize; /* plaintext block size */ + unsigned cipherBlockSize;/* ciphertext block size */ + curveParams *cp; + giant gPriv; /* private data, only for decrypt */ + /* one of the follow two is valid for encrypt */ + feeRand rand; /* only created for encrypt */ + feeRandFcn randFcn; + void *randRef; + + /* + * temporary variables used for encrypt/decrypt. The values in these + * is not needed to be kept from block to block; we just + * alloc them once per lifetime of a feeFEED object as an optimization. + */ + giant xp; /* plaintext */ + giant xc; /* clue = r(P1?) */ + giant xq; /* r(pubB?) or priB?(xc) */ + giant xm; /* ciphertext */ + giant xaux; /* scratch */ + unsigned char *randData; /* only created for encrypt */ +} feedInst; + +/* + * "zero residue" indicator. + */ +#define RESID_ZERO 0xff + +/* + * Alloc and init a feeFEEDExp object associated with specified feePubKey. + */ +feeFEEDExp feeFEEDExpNewWithPubKey( + feePubKey pubKey, + feeRandFcn randFcn, // optional + void *randRef) +{ + feedInst *finst = (feedInst *) fmalloc(sizeof(feedInst)); + giant privGiant; + + finst->cp = curveParamsCopy(feePubKeyCurveParams(pubKey)); + finst->plus = new_public_with_key(feePubKeyPlusCurve(pubKey), + finst->cp); + finst->minus = new_public_with_key(feePubKeyMinusCurve(pubKey), + finst->cp); + + /* + * These might yield NULL data; we can only encrypt in that case. + */ + privGiant = feePubKeyPrivData(pubKey); + if(privGiant) { + finst->gPriv = newGiant(finst->cp->maxDigits); + gtog(privGiant, finst->gPriv); + } + else { + finst->gPriv = NULL; + } + + /* + * Conservative, rounding down, on plaintext blocks since we don't + * want to split bytes. + */ + if(finst->cp->primeType == FPT_General) { + unsigned blen = bitlen(finst->cp->basePrime); + + finst->plainBlockSize = blen / 8; + if((blen % 8) == 0) { + /* + * round down some more... + */ + finst->plainBlockSize--; + } + } + else { + finst->plainBlockSize = finst->cp->q / 8; + if(((finst->cp->q & 0x7) == 0) && (finst->cp->k > 0)) { + /* + * Special case, with q mod 8 == 0. Here we have to trim back + * the plainBlockSize by one byte. + */ + finst->plainBlockSize--; + } + } + + /* + * One block of ciphertext - two giants (with implied sign) and a + * parity byte + */ + finst->cipherBlockSize = (2 * finst->cp->minBytes) + 1; + + finst->xp = newGiant(finst->cp->maxDigits); + finst->xc = newGiant(finst->cp->maxDigits); + finst->xq = newGiant(finst->cp->maxDigits); + finst->xm = newGiant(finst->cp->maxDigits); + finst->xaux = newGiant(finst->cp->maxDigits); + finst->rand = NULL; + finst->randData = NULL; + finst->randFcn = randFcn; + finst->randRef = randRef; + return finst; +} + +void feeFEEDExpFree(feeFEEDExp feed) +{ + feedInst *finst = (feedInst *) feed; + + free_key(finst->plus); + free_key(finst->minus); + freeGiant(finst->xc); + clearGiant(finst->xp); freeGiant(finst->xp); + clearGiant(finst->xq); freeGiant(finst->xq); + freeGiant(finst->xm); + clearGiant(finst->xaux); freeGiant(finst->xaux); + if(finst->gPriv) { + clearGiant(finst->gPriv); + freeGiant(finst->gPriv); + } + if(finst->rand) { + feeRandFree(finst->rand); + } + if(finst->randData) { + ffree(finst->randData); + } + if(finst->cp) { + freeCurveParams(finst->cp); + } + ffree(finst); +} + +unsigned feeFEEDExpPlainBlockSize(feeFEEDExp feed) +{ + feedInst *finst = (feedInst *) feed; + + return finst->plainBlockSize; +} + +unsigned feeFEEDExpCipherBlockSize(feeFEEDExp feed) +{ + feedInst *finst = (feedInst *) feed; + + return finst->cipherBlockSize; +} + +unsigned feeFEEDExpCipherBufSize(feeFEEDExp feed) +{ + feedInst *finst = (feedInst *) feed; + + return 2 * finst->cipherBlockSize; +} + +/* + * Return the size of ciphertext to hold specified size of plaintext. + */ +unsigned feeFEEDExpCipherTextSize(feeFEEDExp feed, unsigned plainTextSize) +{ + /* + * Normal case is one block of ciphertext for each block of + * plaintext. Add one cipherBlock if + * plainTextSize % plainBlockSize == 0. + */ + feedInst *finst = (feedInst *) feed; + unsigned blocks = (plainTextSize + finst->plainBlockSize - 1) / + finst->plainBlockSize; + + if((plainTextSize % finst->plainBlockSize) == 0) { + blocks++; + } + return blocks * finst->cipherBlockSize; +} + +/* + * Return the size of plaintext to hold specified size of decrypted ciphertext. + */ +unsigned feeFEEDExpPlainTextSize(feeFEEDExp feed, unsigned cipherTextSize) +{ + feedInst *finst = (feedInst *) feed; + unsigned blocks = (cipherTextSize + finst->cipherBlockSize - 1) / + finst->cipherBlockSize; + + return blocks * finst->plainBlockSize; +} + +/* + * Encrypt a block or less of data. Caller malloc's cipherText. + */ +feeReturn feeFEEDExpEncryptBlock(feeFEEDExp feed, + const unsigned char *plainText, + unsigned plainTextLen, + unsigned char *cipherText, + unsigned *cipherTextLen, // RETURNED + int finalBlock) +{ + feedInst *finst = (feedInst *) feed; + int index; /* which curve (+/- 1) */ + char g = 0; /* parity, which_curve bits in ciphertext */ + key B; + unsigned char *ptext; /* for final block */ + unsigned ctextLen; + feeReturn frtn = FR_Success; + giant x1; + unsigned randLen; + curveParams *cp = finst->cp; + + if(plainTextLen > finst->plainBlockSize) { + return FR_IllegalArg; + } + else if ((plainTextLen < finst->plainBlockSize) && !finalBlock) { + return FR_IllegalArg; + } + + /* + * Init only on first encrypt + */ + if((finst->randFcn == NULL) && (finst->rand == NULL)) { + finst->rand = feeRandAlloc(); + } + if(finst->randData == NULL) { + finst->randData = (unsigned char*) fmalloc(finst->cp->minBytes); + } + + /* + * plaintext as giant xp + */ + if(finalBlock) { + ptext = (unsigned char*) fmalloc(finst->plainBlockSize); + bzero(ptext, finst->plainBlockSize); + if(plainTextLen) { + /* + * 0 for empty block with resid length 0 + */ + bcopy(plainText, ptext, plainTextLen); + } + if(plainTextLen < finst->plainBlockSize) { + if(plainTextLen == 0) { + /* + * Special case - can't actually write zero here; + * it screws up deserializing the giant during + * decrypt + */ + ptext[finst->plainBlockSize - 1] = RESID_ZERO; + } + else { + ptext[finst->plainBlockSize - 1] = plainTextLen; + } + #if FEED_DEBUG + printf("encrypt: resid 0x%x\n", ptext[finst->plainBlockSize - 1]); + #endif + } + /* + * else handle evenly aligned case below... + */ + deserializeGiant(ptext, finst->xp, finst->plainBlockSize); + ffree(ptext); + } + else { + deserializeGiant(plainText, finst->xp, plainTextLen); + } + #if FEED_DEBUG + printf("encrypt:\n"); + printf(" xp : "); PRINT_GIANT(finst->xp); + #endif // FEED_DEBUG + + /* + * pick curve B? that data lies upon + */ + index = which_curve(finst->xp, finst->cp); + if(index == CURVE_PLUS) { + B = finst->plus; + x1 = finst->cp->x1Plus; + } + else { + B = finst->minus; + x1 = finst->cp->x1Minus; + } + #if FEED_DEBUG + printf(" which_curve: %s\n", + (index == CURVE_PLUS) ? "CURVE_PLUS" : "CURVE_MINUS"); + #endif + + /* + * random number as giant xaux + */ + randLen = cp->minBytes; + if(finst->randFcn != NULL) { + finst->randFcn(finst->randRef, finst->randData, randLen); + } + else { + feeRandBytes(finst->rand, finst->randData, randLen); + } + deserializeGiant(finst->randData, finst->xaux, randLen); + + #if FEE_DEBUG + if(isZero(finst->xaux)) { + printf("feeFEEDExpEncryptBlock: random xaux = 0!\n"); + } + #endif // FEE_DEBUG + /* + * Justify random # to be in [2, minimumX1Order]. + */ + lesserX1OrderJustify(finst->xaux, cp); + #if FEED_DEBUG + printf(" xaux: "); PRINT_GIANT(finst->xaux); + #endif // FEED_DEBUG + + gtog(B->x, finst->xq); // xq = pubB? + elliptic_simple(finst->xq, finst->xaux, cp); + // xq = r(pubB?) + #if FEED_DEBUG + printf(" r(pubB?): "); PRINT_GIANT(finst->xq); + #endif + elliptic_add(finst->xp, finst->xq, finst->xm, cp, SIGN_PLUS); + // xm = data + r(pubB?) + gtog(x1, finst->xc); + elliptic_simple(finst->xc, finst->xaux, cp); + // xc = r(P1?) + elliptic_add(finst->xm, finst->xq, finst->xaux, cp, SIGN_PLUS); + // xaux = xm + xq (for curve +1) + // = (data + r(pubB?)) + r(pubB?) + if(gcompg(finst->xaux, finst->xp) == 0) { + g |= CLUE_ELL_ADD_SIGN_PLUS; + } + else { + g |= CLUE_ELL_ADD_SIGN_MINUS; + #if FEED_DEBUG + /* this better be true.... */ + elliptic_add(finst->xm, finst->xq, finst->xaux, cp, SIGN_MINUS); + if(gcompg(finst->xaux, finst->xp)) { + printf("*******elliptic_add(xm, xq, -1) != xp! *************\n"); + printf(" xq : "); PRINT_GIANT(finst->xq); + printf(" ell_add(xm, xq, -1) : "); PRINT_GIANT(finst->xaux); + } + #endif + } // g = (xaux == data) ? add : subtract + + /* + * Ciphertext = (xm, xc, g) + */ + serializeGiant(finst->xm, cipherText, cp->minBytes); + cipherText += cp->minBytes; + serializeGiant(finst->xc, cipherText, cp->minBytes); + cipherText += cp->minBytes; + *cipherText++ = g; + ctextLen = finst->cipherBlockSize; + #if FEED_DEBUG + printf(" xm : "); PRINT_GIANT(finst->xm); + printf(" xc : "); PRINT_GIANT(finst->xc); + printf(" g : %d\n", g); + #endif // FEED_DEBUG + if(finalBlock && (plainTextLen == finst->plainBlockSize)) { + /* + * Special case: finalBlock true, plainTextLen == blockSize. + * In this case we generate one more block of ciphertext, + * with a resid length of zero. + */ + unsigned moreCipher; // additional cipherLen + + #if FEED_DEBUG + printf("encrypt: one more empty block\n"); + #endif + frtn = feeFEEDExpEncryptBlock(feed, + NULL, // plainText not used + 0, // resid + cipherText, // append... + &moreCipher, + 1); + if(frtn == FR_Success) { + ctextLen += moreCipher; + } + } + + *cipherTextLen = ctextLen; + return frtn; +} + +/* + * Decrypt (exactly) a block of data. Caller malloc's plainText. Always + * generates feeFEEDExpPlainBlockSize of plaintext, unless finalBlock is + * non-zero (in which case feeFEEDExpPlainBlockSize or less bytes of + * plainText are generated). + */ +feeReturn feeFEEDExpDecryptBlock(feeFEEDExp feed, + const unsigned char *cipherText, + unsigned cipherTextLen, + unsigned char *plainText, + unsigned *plainTextLen, // RETURNED + int finalBlock) +{ + feedInst *finst = (feedInst *) feed; + char g; + int s; + feeReturn frtn = FR_Success; + curveParams *cp = finst->cp; + + if(finst->gPriv == NULL) { + /* + * Can't decrypt without private data + */ + return FR_BadPubKey; + } + + /* + * grab xm, xc, and g from cipherText + */ + deserializeGiant(cipherText, finst->xm, finst->cp->minBytes); + cipherText += finst->cp->minBytes; + deserializeGiant(cipherText, finst->xc, finst->cp->minBytes); + cipherText += finst->cp->minBytes; + g = *cipherText; + #if FEED_DEBUG + printf("decrypt g=%d\n", g); + printf(" privKey : "); PRINT_GIANT(finst->gPriv); + printf(" xm : "); PRINT_GIANT(finst->xm); + printf(" xc : "); PRINT_GIANT(finst->xc); + #endif // FEED_DEBUG + + if((g & CLUE_ELL_ADD_SIGN) == CLUE_ELL_ADD_SIGN_PLUS) { + s = SIGN_PLUS; + } + else { + s = SIGN_MINUS; + } + + /* + * xc = r(P1?) + * xc := r(P1?)(pri) = xq + * xp = data + r(priB+) +/- pri(rB?) + */ + elliptic_simple(finst->xc, finst->gPriv, cp); + #if FEED_DEBUG + printf(" xc1 : "); PRINT_GIANT(finst->xc); + #endif + elliptic_add(finst->xm, finst->xc, finst->xp, cp, s); + + /* + * plaintext in xp + */ + #if FEED_DEBUG + printf(" xp : "); PRINT_GIANT(finst->xp); + #endif // FEED_DEBUG + + if(finalBlock) { + /* + * Snag data from xp in order to find out how much to move to + * *plainText + */ + unsigned char *ptext = (unsigned char*) fmalloc(finst->plainBlockSize); + + serializeGiant(finst->xp, ptext, finst->plainBlockSize); + *plainTextLen = ptext[finst->plainBlockSize - 1]; + #if FEED_DEBUG + printf("decrypt: resid 0x%x\n", *plainTextLen); + #endif + if(*plainTextLen == RESID_ZERO) { + *plainTextLen = 0; + } + else if(*plainTextLen > (finst->plainBlockSize - 1)) { + dbgLog(("feeFEEDExpDecryptBlock: ptext overflow!\n")); + frtn = FR_BadCipherText; + } + else { + bcopy(ptext, plainText, *plainTextLen); + } + ffree(ptext); + } + else { + *plainTextLen = finst->plainBlockSize; + serializeGiant(finst->xp, plainText, *plainTextLen); + } + return frtn; +} + +/* + * Convenience routines to encrypt & decrypt multi-block data. + */ +feeReturn feeFEEDExpEncrypt(feeFEEDExp feed, + const unsigned char *plainText, + unsigned plainTextLen, + unsigned char **cipherText, // malloc'd and RETURNED + unsigned *cipherTextLen) // RETURNED +{ + const unsigned char *ptext; // per block + unsigned ptextLen; // total to go + unsigned thisPtextLen; // per block + unsigned char *ctext; // per block + unsigned ctextLen; // per block + unsigned char *ctextResult; // to return + unsigned ctextResultLen; + unsigned char *ctextPtr; + unsigned ctextLenTotal; // running total + feeReturn frtn; + int finalBlock; + unsigned numBlocks; + unsigned plainBlockSize; + + if(plainTextLen == 0) { + dbgLog(("feeFEEDExpDecrypt: NULL plainText\n")); + return FR_IllegalArg; + } + + ptext = plainText; + ptextLen = plainTextLen; + ctext = (unsigned char*) fmalloc(feeFEEDExpCipherBufSize(feed)); + plainBlockSize = feeFEEDExpPlainBlockSize(feed); + numBlocks = (plainTextLen + plainBlockSize - 1)/plainBlockSize; + ctextResultLen = (numBlocks + 1) * feeFEEDExpCipherBlockSize(feed); + ctextResult = (unsigned char*) fmalloc(ctextResultLen); + ctextPtr = ctextResult; + ctextLenTotal = 0; + + while(1) { + if(ptextLen <= plainBlockSize) { + finalBlock = 1; + thisPtextLen = ptextLen; + } + else { + finalBlock = 0; + thisPtextLen = plainBlockSize; + } + frtn = feeFEEDExpEncryptBlock(feed, + ptext, + thisPtextLen, + ctext, + &ctextLen, + finalBlock); + if(frtn) { + dbgLog(("feeFEEDExpEncrypt: encrypt error: %s\n", + feeReturnString(frtn))); + break; + } + if(ctextLen == 0) { + dbgLog(("feeFEEDExpEncrypt: null ciphertext\n")); + frtn = FR_Internal; + break; + } + bcopy(ctext, ctextPtr, ctextLen); + ctextLenTotal += ctextLen; + if(ctextLenTotal > ctextResultLen) { + dbgLog(("feeFEEDExpEncrypt: ciphertext overflow\n")); + frtn = FR_Internal; + break; + } + if(finalBlock) { + break; + } + ctextPtr += ctextLen; + ptext += thisPtextLen; + ptextLen -= thisPtextLen; + } + + ffree(ctext); + if(frtn) { + ffree(ctextResult); + *cipherText = NULL; + *cipherTextLen = 0; + } + else { + *cipherText = ctextResult; + *cipherTextLen = ctextLenTotal; + #if FEE_DEBUG + if(feeFEEDExpCipherTextSize(feed, plainTextLen) != + ctextLenTotal) { + printf("feeFEEDExpEncrypt: feeFEEDCipherTextSize " + "error!\n"); + printf("ptext %d exp ctext %d actual ctext %d\n", + plainTextLen, + feeFEEDExpCipherTextSize(feed, plainTextLen), + ctextLenTotal); + } + #endif // FEE_DEBUG + } + return frtn; + +} + +feeReturn feeFEEDExpDecrypt(feeFEEDExp feed, + const unsigned char *cipherText, + unsigned cipherTextLen, + unsigned char **plainText, // malloc'd and RETURNED + unsigned *plainTextLen) // RETURNED +{ + const unsigned char *ctext; + unsigned ctextLen; // total to go + unsigned char *ptext; // per block + unsigned ptextLen; // per block + unsigned char *ptextResult; // to return + unsigned char *ptextPtr; + unsigned ptextLenTotal; // running total + feeReturn frtn = FR_Success; + int finalBlock; + unsigned numBlocks; + unsigned plainBlockSize = + feeFEEDExpPlainBlockSize(feed); + unsigned cipherBlockSize = + feeFEEDExpCipherBlockSize(feed); + + if(cipherTextLen % cipherBlockSize) { + dbgLog(("feeFEEDExpDecrypt: unaligned cipherText\n")); + return FR_BadCipherText; + } + if(cipherTextLen == 0) { + dbgLog(("feeFEEDExpDecrypt: NULL cipherText\n")); + return FR_BadCipherText; + } + + ptext = (unsigned char*) fmalloc(plainBlockSize); + ctext = cipherText; + ctextLen = cipherTextLen; + numBlocks = cipherTextLen / cipherBlockSize; + ptextResult = (unsigned char*) fmalloc(plainBlockSize * numBlocks); + ptextPtr = ptextResult; + ptextLenTotal = 0; + + while(ctextLen) { + if(ctextLen == cipherBlockSize) { + finalBlock = 1; + } + else { + finalBlock = 0; + } + frtn = feeFEEDExpDecryptBlock(feed, + ctext, + cipherBlockSize, + ptext, + &ptextLen, + finalBlock); + if(frtn) { + dbgLog(("feeFEEDExpDecryptBlock: %s\n", + feeReturnString(frtn))); + break; + } + if(ptextLen == 0) { + /* + * Normal termination case for + * plainTextLen % plainBlockSize == 0 + */ + if(!finalBlock) { + dbgLog(("feeFEEDExpDecrypt: decrypt sync" + " error!\n")); + frtn = FR_BadCipherText; + } + break; + } + else if(ptextLen > plainBlockSize) { + dbgLog(("feeFEEDExpDecrypt: ptext overflow!\n")); + frtn = FR_Internal; + break; + } + else { + bcopy(ptext, ptextPtr, ptextLen); + ptextPtr += ptextLen; + ptextLenTotal += ptextLen; + } + ctext += cipherBlockSize; + ctextLen -= cipherBlockSize; + } + + ffree(ptext); + if(frtn) { + ffree(ptextResult); + *plainText = NULL; + *plainTextLen = 0; + } + else { + *plainText = ptextResult; + *plainTextLen = ptextLenTotal; + } + return frtn; + +} + +#endif /* CRYPTKIT_ASYMMETRIC_ENABLE */ diff --git a/libsecurity_cryptkit/lib/feeFEEDExp.h b/libsecurity_cryptkit/lib/feeFEEDExp.h new file mode 100644 index 00000000..e20d2689 --- /dev/null +++ b/libsecurity_cryptkit/lib/feeFEEDExp.h @@ -0,0 +1,126 @@ +/* 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. + *************************************************************************** + * + * feeFEEDExp.h - generic FEED encryption object using 2:1 expansion + * + * Revision History + * ---------------- + * 28 Aug 96 Doug Mitchell at NeXT + * Created. + */ + +#ifndef _CK_FEEFEEDEXP_H_ +#define _CK_FEEFEEDEXP_H_ + +#if !defined(__MACH__) +#include +#include +#include +#else +#include +#include +#include +#endif + +#if CRYPTKIT_ASYMMETRIC_ENABLE + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Opaque object handle. + */ +typedef void *feeFEEDExp; + +/* + * Alloc and init a feeFEEDExp object associated with specified feePubKey. + */ +feeFEEDExp feeFEEDExpNewWithPubKey( + feePubKey pubKey, + feeRandFcn randFcn, // optional + void *randRef); + +void feeFEEDExpFree(feeFEEDExp feed); + +/* + * Plaintext block size. + */ +unsigned feeFEEDExpPlainBlockSize(feeFEEDExp feed); + +/* + * Ciphertext block size used for decryption. + */ +unsigned feeFEEDExpCipherBlockSize(feeFEEDExp feed); + +/* + * Required size of buffer for ciphertext, upon encrypting one + * block of plaintext. + */ +unsigned feeFEEDExpCipherBufSize(feeFEEDExp feed); + +/* + * Return the size of ciphertext to hold specified size of encrypted plaintext. + */ +unsigned feeFEEDExpCipherTextSize(feeFEEDExp feed, unsigned plainTextSize); + +/* + * Return the size of plaintext to hold specified size of decrypted ciphertext. + */ +unsigned feeFEEDExpPlainTextSize(feeFEEDExp feed, unsigned cipherTextSize); + +/* + * Encrypt a block or less of data. Caller malloc's cipherText. Generates + * feeFEEDExpCipherBlockSize() bytes of cipherText if finalBlock is false; + * if finalBlock is true it could produce twice as much ciphertext. + * If plainTextLen is less than feeFEEDExpPlainBlockSize(), finalBlock must be true. + */ +feeReturn feeFEEDExpEncryptBlock(feeFEEDExp feed, + const unsigned char *plainText, + unsigned plainTextLen, + unsigned char *cipherText, + unsigned *cipherTextLen, // RETURNED + int finalBlock); + +/* + * Decrypt (exactly) a block of data. Caller malloc's plainText. Always + * generates feeFEEDExpBlockSize bytes of plainText, unless 'finalBlock' is + * non-zero (in which case feeFEEDExpBlockSize or less bytes of plainText are + * generated). + */ +feeReturn feeFEEDExpDecryptBlock(feeFEEDExp feed, + const unsigned char *cipherText, + unsigned cipherTextLen, + unsigned char *plainText, + unsigned *plainTextLen, // RETURNED + int finalBlock); + +/* + * Convenience routines to encrypt & decrypt multi-block data. + */ +feeReturn feeFEEDExpEncrypt(feeFEEDExp feed, + const unsigned char *plainText, + unsigned plainTextLen, + unsigned char **cipherText, // malloc'd and RETURNED + unsigned *cipherTextLen); // RETURNED + +feeReturn feeFEEDExpDecrypt(feeFEEDExp feed, + const unsigned char *cipherText, + unsigned cipherTextLen, + unsigned char **plainText, // malloc'd and RETURNED + unsigned *plainTextLen); // RETURNED + +#ifdef __cplusplus +} +#endif + +#endif /* CRYPTKIT_ASYMMETRIC_ENABLE */ + +#endif /*_CK_FEEFEEDEXP_H_*/ diff --git a/libsecurity_cryptkit/lib/feeFunctions.h b/libsecurity_cryptkit/lib/feeFunctions.h new file mode 100644 index 00000000..11617b12 --- /dev/null +++ b/libsecurity_cryptkit/lib/feeFunctions.h @@ -0,0 +1,69 @@ +/* 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. + *************************************************************************** + * + * feeFunctions.h - general public function declarations + * + * Revision History + * ---------------- + * 8/25/98 ap + * Fixed previous check-in comment. + * 8/24/98 ap + * Added tags around #endif comment. + * 23 Mar 98 Doug Mitchell at Apple + * Added initCryptKit(). + * 27 Aug 96 Doug Mitchell at NeXT + * Created. + */ + +#ifndef _CK_FEEFUNCTIONS_H_ +#define _CK_FEEFUNCTIONS_H_ + +#ifdef macintosh +#include +#else +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * One-time only init of CryptKit library. + */ +void initCryptKit(void); + +/* + * Shutdown. + */ +void terminateCryptKit(); + +#if defined(NeXT) && !defined(WIN32) + +#define PHRASELEN 128 + +/* + * Prompt for password, get it in secure manner. Max password length is + * PHRASELEN. NEXTSTEP only. + */ +extern void getpassword(const char *prompt, char *pbuf); + +#endif /* NeXT */ + +/* + * obtain a string describing a feeReturn. + */ +extern const char *feeReturnString(feeReturn frtn); + +#ifdef __cplusplus +} +#endif + +#endif /*_CK_FEEFUNCTIONS_H_*/ diff --git a/libsecurity_cryptkit/lib/feeHash.c b/libsecurity_cryptkit/lib/feeHash.c new file mode 100644 index 00000000..2eef6431 --- /dev/null +++ b/libsecurity_cryptkit/lib/feeHash.c @@ -0,0 +1,110 @@ +/* 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. + *************************************************************************** + * + * FeeHash.c - generic, portable MD5 hash object + * + * Revision History + * ---------------- + * 10/06/98 ap + * Changed to compile with C++. + * 22 Aug 96 Doug Mitchell at NeXT + * Created. + */ + +#include "ckconfig.h" + +#if CRYPTKIT_MD5_ENABLE + +#include "feeTypes.h" +#include "feeHash.h" +#include "ckMD5.h" +#include "falloc.h" +#include "platform.h" + +/* + * Private data for this object. A feeHash handle is cast to aa pointer + * to one of these. + */ +typedef struct { + MD5Context context; + int isDone; + unsigned char digest[MD5_DIGEST_SIZE]; +} hashInst; + +/* + * Alloc and init an empty hash object. + */ +feeHash feeHashAlloc(void) +{ + hashInst *hinst; + + hinst = (hashInst *) fmalloc(sizeof(hashInst)); + MD5Init(&hinst->context); + hinst->isDone = 0; + return hinst; +} + +void feeHashReinit(feeHash hash) +{ + hashInst *hinst = (hashInst *) hash; + + MD5Init(&hinst->context); + hinst->isDone = 0; +} + +/* + * Free a hash object. + */ +void feeHashFree(feeHash hash) +{ + hashInst *hinst = (hashInst *) hash; + + memset(hinst, 0, sizeof(hashInst)); + ffree(hinst); +} + +/* + * Add some data to the hash object. + */ +void feeHashAddData(feeHash hash, + const unsigned char *data, + unsigned dataLen) +{ + hashInst *hinst = (hashInst *) hash; + + if(hinst->isDone) { + /* + * Log some kind of error here... + */ + return; + } + MD5Update(&hinst->context, data, dataLen); +} + +/* + * Obtain a pointer to completed message digest, and the length of the digest. + */ +unsigned char *feeHashDigest(feeHash hash) +{ + hashInst *hinst = (hashInst *) hash; + + if(!hinst->isDone) { + MD5Final(&hinst->context, hinst->digest); + hinst->isDone = 1; + } + return hinst->digest; +} + +unsigned feeHashDigestLen(void) +{ + return MD5_DIGEST_SIZE; +} + +#endif /* CRYPTKIT_MD5_ENABLE*/ diff --git a/libsecurity_cryptkit/lib/feeHash.h b/libsecurity_cryptkit/lib/feeHash.h new file mode 100644 index 00000000..8cab22fc --- /dev/null +++ b/libsecurity_cryptkit/lib/feeHash.h @@ -0,0 +1,81 @@ +/* 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. + *************************************************************************** + * + * FeeHash.h - generic, portable MD5 hash object + * + * Revision History + * ---------------- + * 22 Aug 96 Doug Mitchell at NeXT + * Created. + */ + +#ifndef _CK_FEEHASH_H_ +#define _CK_FEEHASH_H_ + +#if !defined(__MACH__) +#include +#include +#else +#include +#include +#endif + +#if CRYPTKIT_MD5_ENABLE + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Opaque hash object handle. + */ +typedef void *feeHash; + +/* + * Alloc and init an empty hash object. + */ +feeHash feeHashAlloc(void); + +/* + * reinitialize a hash object for reuse. + */ +void feeHashReinit(feeHash hash); + +/* + * Free a hash object. + */ +void feeHashFree(feeHash hash); + +/* + * Add some data to the hash object. + */ +void feeHashAddData(feeHash hash, + const unsigned char *data, + unsigned dataLen); + +/* + * Obtain a pointer to completed message digest. This disables further calls + * to feeHashAddData(). This pointer is NOT malloc'd; the associated data + * persists only as long as this object does. + */ +unsigned char *feeHashDigest(feeHash hash); + +/* + * Obtain the length of the message digest. + */ +unsigned feeHashDigestLen(void); + +#ifdef __cplusplus +} +#endif + +#endif /* CRYPTKIT_MD5_ENABLE */ + +#endif /*_CK_FEEHASH_H_*/ diff --git a/libsecurity_cryptkit/lib/feePublicKey.c b/libsecurity_cryptkit/lib/feePublicKey.c new file mode 100644 index 00000000..48e672d0 --- /dev/null +++ b/libsecurity_cryptkit/lib/feePublicKey.c @@ -0,0 +1,1608 @@ +/* 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. + *************************************************************************** + * + * feePublicKey.c - Portable FEE public key object. + * + * Revision History + * ---------------- + * 11/27/98 dmitch + * Added ECDSA_VERIFY_ONLY dependencies. + * 10/06/98 ap + * Changed to compile with C++. + * 9 Sep 98 Doug Mitchell at NeXT + * Major changes for IEEE P1363 compliance. + * 23 Mar 98 Doug Mitchell at Apple + * Added blob support. + * 21 Jan 98 Doug Mitchell at Apple + * Fixed feePubKeyBitsize bitlen bug for PT_GENERAL case. + * 05 Jan 98 Doug Mitchell at Apple + * ECDSA now uses SHA-1 hash. Imcompatible with old ECDSA signatures. + * 17 Jul 97 Doug Mitchell at Apple + * Added ECDSA signature routines. + * 12 Jun 97 Doug Mitchell at Apple + * Added feePubKeyInitGiants() + * Deleted obsolete code + * Changes for lesserX1OrderJustify (was curveOrderJustify) + * 31 Mar 97 Doug Mitchell at Apple + * Fixed leak in feePubKeyCreateKeyString() + * 15 Jan 97 Doug Mitchell 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 + * Added initFromEnc64KeyStr(). + * 20 Aug 96 Doug Mitchell at NeXT + * Ported to C. + * ???? 1994 Blaine Garst at NeXT + * Created. + */ + +#include "ckconfig.h" +#include "feePublicKey.h" +#include "feePublicKeyPrivate.h" +#include "ckutilities.h" +#include "giantIntegers.h" +#include "elliptic.h" +#include "curveParams.h" +#include "falloc.h" +#include "feeTypes.h" +#include "feeDebug.h" +#include "feeHash.h" +#include "ckSHA1.h" +#include "feeDigitalSignature.h" +#include "feeECDSA.h" +#include "platform.h" +#include "enc64.h" +#include "feeDES.h" +#include "byteRep.h" +#if CRYPTKIT_DER_ENABLE +#include "CryptKitDER.h" +#endif +#include + +/* + * 11/27/98 dmitch: The ECDSA_VERIFY_ONLY symbol, when #defined, disables all + * of the code in this module except that which is necessary for ECDSA + * siggnature verification. + */ + +#ifndef NULL +#define NULL ((void *)0) +#endif // NULL + +/* + * Magic number for a portable key blobs. Must be in sync with static + * final PUBLIC_KEY_STRING_MAGIC in JavaFee/PublicKey.java. + */ +#define PUBLIC_KEY_BLOB_MAGIC_PUB 0xfeeddeef +#define PUBLIC_KEY_BLOB_MAGIC_PRIV 0xfeeddeed +#define PUBLIC_KEY_BLOB_VERSION 6 +#define PUBLIC_KEY_BLOB_MINVERSION 6 + +#if CRYPTKIT_DER_ENABLE +#define PUBLIC_DER_KEY_BLOB_VERSION 1 +#endif + +/* + * Private data. All "instance" routines are passed a feePubKey (actually + * a void *) which is actually a pointer to one of these. + */ +typedef struct { + key plus; + key minus; // not needed for ECDSA + curveParams *cp; // common params shared by minus, plus + giant privGiant; // private key +} pubKeyInst; + +static feeReturn feeGenPrivate(pubKeyInst *pkinst, + const unsigned char *passwd, + unsigned passwdLen, + char hashPasswd); +static pubKeyInst *pubKeyInstAlloc(void); +static void pubKeyInstFree(pubKeyInst *pkinst); +#if GIANTS_VIA_STACK +static void feePubKeyInitGiants(void); +#endif +static feeReturn createKeyBlob(pubKeyInst *pkinst, + int isPrivate, // 0 : public 1 : private + unsigned char **keyBlob, // mallocd and RETURNED + unsigned *keyBlobLen); // RETURNED +static feeReturn feePubKeyInitFromKeyBlob(feePubKey pubKey, + unsigned char *keyBlob, + unsigned keyBlobLen); + +#pragma mark --- General public API function --- + +/* + * Obatin a newly allocated feePubKey. + */ +feePubKey feePubKeyAlloc(void) +{ + pubKeyInst *pkinst = pubKeyInstAlloc(); + + #if GIANTS_VIA_STACK + feePubKeyInitGiants(); + #endif + return pkinst; +} + +void feePubKeyFree(feePubKey pubKey) +{ + pubKeyInstFree((pubKeyInst*) pubKey); +} + +#ifndef ECDSA_VERIFY_ONLY +/* + * Init feePubKey from private key data. + */ +feeReturn feePubKeyInitFromPrivDataKeyBits(feePubKey pubKey, + const unsigned char *privData, + unsigned privDataLen, + unsigned keyBits, /* key size in bits */ + feePrimeType primeType, /* FPT_Fefault means "best one" */ + feeCurveType curveType, /* FCT_Default means "best one" */ + char hashPrivData) +{ + feeReturn frtn; + feeDepth depth; + + frtn = feeKeyBitsToDepth(keyBits, primeType, curveType, &depth); + if(frtn) { + return frtn; + } + return feePubKeyInitFromPrivDataDepth(pubKey, + privData, + privDataLen, + depth, + hashPrivData); +} + +feeReturn feePubKeyInitFromPrivDataDepth(feePubKey pubKey, + const unsigned char *privData, + unsigned privDataLen, + feeDepth depth, + char hashPrivData) +{ + pubKeyInst *pkinst = (pubKeyInst *) pubKey; + feeReturn frtn; + + #if ENGINE_127_BITS + if(depth != FEE_DEPTH_127_1) { + dbgLog(("Illegal Depth\n")); + return FR_IllegalDepth; + } + #endif // ENGINE_127_BITS + if(depth > FEE_DEPTH_MAX) { + dbgLog(("Illegal Depth\n")); + return FR_IllegalDepth; + } + + pkinst->cp = curveParamsForDepth(depth); + pkinst->plus = new_public(pkinst->cp, CURVE_PLUS); + if(pkinst->cp->x1Minus != NULL) { + pkinst->minus = new_public(pkinst->cp, CURVE_MINUS); + } + /* else only usable for ECDSA */ + + frtn = feeGenPrivate(pkinst, privData, privDataLen, hashPrivData); + if(frtn) { + return frtn; + } + set_priv_key_giant(pkinst->plus, pkinst->privGiant); + if(pkinst->cp->x1Minus != NULL) { + set_priv_key_giant(pkinst->minus, pkinst->privGiant); + } + return FR_Success; +} + +#endif /* ECDSA_VERIFY_ONLY */ + +/* + * Init feePubKey from curve parameters matching existing oldKey. + */ +feeReturn feePubKeyInitFromKey(feePubKey pubKey, + const unsigned char *privData, + unsigned privDataLen, + feePubKey oldKey, + char hashPrivData) +{ + pubKeyInst *pkinst = (pubKeyInst *) pubKey; + pubKeyInst *oldInst = (pubKeyInst *) oldKey; + feeReturn frtn; + + if(oldKey == NULL) { + dbgLog(("NULL existing key\n")); + return FR_BadPubKey; + } + + pkinst->cp = curveParamsCopy(oldInst->cp); + if(pkinst->cp->x1Minus != NULL) { + pkinst->minus = new_public(pkinst->cp, CURVE_MINUS); + if(pkinst->minus == NULL) { + goto abort; + } + } + /* else this curve only usable for ECDSA */ + + pkinst->plus = new_public(pkinst->cp, CURVE_PLUS); + if(pkinst->plus == NULL) { + goto abort; + } + frtn = feeGenPrivate(pkinst, privData, privDataLen, hashPrivData); + if(frtn) { + return frtn; + } + set_priv_key_giant(pkinst->plus, pkinst->privGiant); + if(pkinst->cp->x1Minus != NULL) { + set_priv_key_giant(pkinst->minus, pkinst->privGiant); + } + return FR_Success; + +abort: + dbgLog(("Bad Existing Public Key\n")); + return FR_BadPubKey; +} + +/*** + *** Public KeyString support. + ***/ +/* + * Init feePubKey from a public key string. + * + * See ByteRep.doc for info on the format of the public key string and blobs; + * PLEASE UPDATE THIS DOCUMENT WHEN YOU MAKE CHANGES TO THE STRING FORMAT. + */ +feeReturn feePubKeyInitFromKeyString(feePubKey pubKey, + const char *keyStr, + unsigned keyStrLen) +{ + unsigned char *blob = NULL; + unsigned blobLen; + feeReturn frtn; + + blob = dec64((unsigned char *)keyStr, keyStrLen, &blobLen); + if(blob == NULL) { + dbgLog(("Bad Public Key String (not enc64)\n")); + return FR_BadPubKeyString; + } + frtn = feePubKeyInitFromKeyBlob(pubKey, blob, blobLen); + ffree(blob); + return frtn; +} + +/* + * Create a public key in the form of a null-terminated C string. + * This string contains an encoded version of all of our ivars except for + * privGiant. + * + * See ByteRep.doc for info on the format of the public key string and blobs; + * PLEASE UPDATE THIS DOCUMENT WHEN YOU MAKE CHANGES TO THE STRING FORMAT. + */ +feeReturn feePubKeyCreateKeyString(feePubKey pubKey, + char **pubKeyString, /* RETURNED */ + unsigned *pubKeyStringLen) /* RETURNED */ +{ + unsigned char *blob; + unsigned blobLen; + feeReturn frtn; + pubKeyInst *pkinst = (pubKeyInst *)pubKey; + + /* get binary pub blob, encode the blob, free the blob */ + frtn = createKeyBlob(pkinst, + 0, // isPrivate + &blob, + &blobLen); + if(frtn) { + return frtn; + } + + *pubKeyString = (char *)enc64(blob, blobLen, pubKeyStringLen); + ffree(blob); + return FR_Success; +} + +/*** + *** Native key blob support. + ***/ + +#ifndef ECDSA_VERIFY_ONLY + +/* + * Obtain portable public and private key blobs from a key. + */ +feeReturn feePubKeyCreatePubBlob(feePubKey pubKey, + unsigned char **keyBlob, // mallocd and RETURNED + unsigned *keyBlobLen) // RETURNED +{ + pubKeyInst *pkinst = (pubKeyInst *)pubKey; + + return createKeyBlob(pkinst, + 0, + keyBlob, + keyBlobLen); +} + +feeReturn feePubKeyCreatePrivBlob(feePubKey pubKey, + unsigned char **keyBlob, // mallocd and RETURNED + unsigned *keyBlobLen) // RETURNED +{ + pubKeyInst *pkinst = (pubKeyInst *)pubKey; + + if(pkinst->privGiant == NULL) { + return FR_IncompatibleKey; + } + return createKeyBlob(pkinst, + 1, + keyBlob, + keyBlobLen); +} + +/* + * Given private-capable privKey, initialize pubKey to be its corresponding + * public key. + */ +feeReturn feePubKeyInitPubKeyFromPriv(feePubKey privKey, + feePubKey pubKey) +{ + pubKeyInst *privInst = (pubKeyInst *)privKey; + pubKeyInst *pubInst = (pubKeyInst *)pubKey; + + if((privInst == NULL) || (pubInst == NULL)) { + return FR_BadPubKey; + } + if(privInst->privGiant == NULL) { + return FR_IncompatibleKey; + } + pubInst->cp = curveParamsCopy(privInst->cp); + if(pubInst == NULL) { + return FR_Memory; + } + pubInst->plus = new_public_with_key(privInst->plus, pubInst->cp); + if(pubInst->plus == NULL) { + return FR_Memory; + } + if(pubInst->cp->x1Minus != NULL) { + pubInst->minus = new_public_with_key(privInst->minus, pubInst->cp); + if(pubInst->minus == NULL) { + return FR_Memory; + } + } + return FR_Success; +} + +#endif /* ECDSA_VERIFY_ONLY */ + +/* + * Returns non-zero if two keys are equivalent. + */ +int feePubKeyIsEqual(feePubKey key1, feePubKey key2) +{ + pubKeyInst *pkinst1 = (pubKeyInst *) key1; + pubKeyInst *pkinst2 = (pubKeyInst *) key2; + + if ((pkinst1 == NULL) || (pkinst2 == NULL)) { + return 0; + } + if((pkinst1->minus != NULL) && (pkinst2->minus != NULL)) { + if(key_equal(pkinst1->minus, pkinst2->minus) == 0) { + return 0; + } + } + if(key_equal(pkinst1->plus, pkinst2->plus) == 0) { + return 0; + } + return 1; +} + +/* + * Returns non-zero if key is private-capable (i.e., capable of signing + * and decrypting). + */ +int feePubKeyIsPrivate(feePubKey key) +{ + pubKeyInst *myPkinst = (pubKeyInst *)key; + + return ((myPkinst->privGiant != NULL) ? 1 : 0); +} + +#ifndef ECDSA_VERIFY_ONLY + +#if CRYPTKIT_KEY_EXCHANGE + +feeReturn feePubKeyCreatePad(feePubKey myKey, + feePubKey theirKey, + unsigned char **padData, /* RETURNED */ + unsigned *padDataLen) /* RETURNED padData length in bytes */ +{ + pubKeyInst *myPkinst = (pubKeyInst *) myKey; + pubKeyInst *theirPkinst = (pubKeyInst *) theirKey; + giant pad; + unsigned char *result; + unsigned padLen; + key pkey; + + /* + * Do some compatibility checking (myKey, theirKey) here...? + */ + if(DEFAULT_CURVE == CURVE_PLUS) { + pkey = theirPkinst->plus; + } + else { + pkey = theirPkinst->minus; + } + pad = make_pad(myPkinst->privGiant, pkey); + result = mem_from_giant(pad, &padLen); + freeGiant(pad); + + /* + * Ensure we have a the minimum necessary for DES. A bit of a hack, + * to be sure. + */ + if(padLen >= FEE_DES_MIN_STATE_SIZE) { + *padData = result; + *padDataLen = padLen; + } + else { + *padData = (unsigned char*) fmalloc(FEE_DES_MIN_STATE_SIZE); + *padDataLen = FEE_DES_MIN_STATE_SIZE; + bzero(*padData, FEE_DES_MIN_STATE_SIZE); + bcopy(result, *padData, padLen); + ffree(result); + } + return FR_Success; +} + +#endif /* CRYPTKIT_KEY_EXCHANGE */ + +#if CRYPTKIT_HIGH_LEVEL_SIG + +/* + * Generate digital signature, ElGamal style. + */ +feeReturn feePubKeyCreateSignature(feePubKey pubKey, + const unsigned char *data, + unsigned dataLen, + unsigned char **signature, /* fmalloc'd and RETURNED */ + unsigned *signatureLen) /* RETURNED */ +{ + pubKeyInst *pkinst = (pubKeyInst *) pubKey; + feeHash hash; + feeSig sig; + unsigned char *Pm = NULL; + unsigned PmLen; + feeReturn frtn; + + if(pkinst->privGiant == NULL) { + dbgLog(("feePubKeyCreateSignature: Attempt to Sign without" + " private data\n")); + return FR_BadPubKey; + } + hash = feeHashAlloc(); + sig = feeSigNewWithKey(pubKey, NULL, NULL); + if(sig == NULL) { + /* + * Shouldn't happen, but... + */ + feeHashFree(hash); + return FR_BadPubKey; + } + + /* + * Get Pm to salt hash object + */ + Pm = feeSigPm(sig, &PmLen); + feeHashAddData(hash, Pm, PmLen); + + /* + * Now hash the data proper, then sign the hash + */ + feeHashAddData(hash, data, dataLen); + frtn = feeSigSign(sig, + feeHashDigest(hash), + feeHashDigestLen(), + pubKey); + if(frtn == FR_Success) { + frtn = feeSigData(sig, signature, signatureLen); + } + feeHashFree(hash); + feeSigFree(sig); + ffree(Pm); + return frtn; +} + +/* + * Verify digital signature, ElGamal style. If the signature is ECDSA, + * we'll use that format for compatibility. + */ +feeReturn feePubKeyVerifySignature(feePubKey pubKey, + const unsigned char *data, + unsigned dataLen, + const unsigned char *signature, + unsigned signatureLen) +{ + feeHash hash; + feeSig sig; + unsigned char *Pm = NULL; + unsigned PmLen; + feeReturn frtn; + + hash = feeHashAlloc(); + frtn = feeSigParse(signature, signatureLen, &sig); + if(frtn) { + feeHashFree(hash); + #if CRYPTKIT_ECDSA_ENABLE + if(frtn == FR_WrongSignatureType) { + return feePubKeyVerifyECDSASignature(pubKey, + data, + dataLen, + signature, + signatureLen); + } + #endif /* CRYPTKIT_ECDSA_ENABLE */ + return frtn; + } + + /* + * Get PM as salt; eat salt, then hash data + */ + Pm = feeSigPm(sig, &PmLen); + feeHashAddData(hash, Pm, PmLen); + feeHashAddData(hash, data, dataLen); + frtn = feeSigVerify(sig, + feeHashDigest(hash), + feeHashDigestLen(), + pubKey); + + feeHashFree(hash); + feeSigFree(sig); + ffree(Pm); + return frtn; +} + +#pragma mark --- ECDSA signature: high level routines --- + +#if CRYPTKIT_ECDSA_ENABLE +/* + * Generate digital signature, ECDSA style. + */ +feeReturn feePubKeyCreateECDSASignature(feePubKey pubKey, + const unsigned char *data, + unsigned dataLen, + unsigned char **signature, /* fmalloc'd and RETURNED */ + unsigned *signatureLen) /* RETURNED */ +{ + pubKeyInst *pkinst = (pubKeyInst *) pubKey; + sha1Obj sha1; + feeReturn frtn; + + if(pkinst->privGiant == NULL) { + dbgLog(("feePubKeyCreateECDSASignature: Attempt to Sign " + "without private data\n")); + return FR_BadPubKey; + } + sha1 = sha1Alloc(); + sha1AddData(sha1, data, dataLen); + frtn = feeECDSASign(pubKey, + sha1Digest(sha1), + sha1DigestLen(), + NULL, // randFcn + NULL, + signature, + signatureLen); + sha1Free(sha1); + return frtn; +} +#endif /* CRYPTKIT_ECDSA_ENABLE */ +#endif /* ECDSA_VERIFY_ONLY */ + +#if CRYPTKIT_ECDSA_ENABLE + +/* + * Verify digital signature, ECDSA style. + */ +feeReturn feePubKeyVerifyECDSASignature(feePubKey pubKey, + const unsigned char *data, + unsigned dataLen, + const unsigned char *signature, + unsigned signatureLen) +{ + sha1Obj sha1; + feeReturn frtn; + + sha1 = sha1Alloc(); + sha1AddData(sha1, data, dataLen); + frtn = feeECDSAVerify(signature, + signatureLen, + sha1Digest(sha1), + sha1DigestLen(), + pubKey); + sha1Free(sha1); + return frtn; +} + +#endif /* CRYPTKIT_ECDSA_ENABLE */ + +#endif /* CRYPTKIT_HIGH_LEVEL_SIG */ + +#pragma mark --- ECDH --- + +/* + * Diffie-Hellman. Public key is specified either as a feePubKey or + * a ANSI X9.62 format public key string (0x04 | x | y). In either case + * the caller must ensure that the two keys are on the same curve. + * Output data is fmalloc'd here; caller must free. Output data is + * exactly the size of the curve's modulus in bytes. + */ +feeReturn feePubKeyECDH( + feePubKey privKey, + /* one of the following two is non-NULL */ + feePubKey pubKey, + const unsigned char *pubKeyStr, + unsigned pubKeyStrLen, + /* output fmallocd and RETURNED here */ + unsigned char **output, + unsigned *outputLen) +{ + feePubKey theirPub = pubKey; + feeReturn frtn = FR_Success; + pubKeyInst *privInst = (pubKeyInst *) privKey; + + if(privInst->privGiant == NULL) { + dbgLog(("feePubKeyECDH: privKey not a private key\n")); + return FR_IncompatibleKey; + } + + if(theirPub == NULL) { + if(pubKeyStr == NULL) { + return FR_IllegalArg; + } + + /* Cook up a public key with the same curveParams as the private key */ + feeDepth depth; + frtn = curveParamsDepth(privInst->cp, &depth); + if(frtn) { + return frtn; + } + theirPub = feePubKeyAlloc(); + if(theirPub == NULL) { + return FR_Memory; + } + frtn = feePubKeyInitFromECDSAPubBlob(theirPub, pubKeyStr, pubKeyStrLen, depth); + if(frtn) { + goto errOut; + } + } + + pubKeyInst *pubInst = (pubKeyInst *) theirPub; + + giant outputGiant = make_pad(privInst->privGiant, pubInst->plus); + if(outputGiant == NULL) { + dbgLog(("feePubKeyECDH: make_pad error\n")); + frtn = FR_Internal; + } + else { + *outputLen = (privInst->cp->q + 7) / 8; + *output = (unsigned char *)fmalloc(*outputLen); + if(*output == NULL) { + frtn = FR_Memory; + goto errOut; + } + serializeGiant(outputGiant, *output, *outputLen); + freeGiant(outputGiant); + } +errOut: + if((pubKey == NULL) && (theirPub != NULL)) { + feePubKeyFree(theirPub); + } + return frtn; +} + +#pragma mark --- feePubKey data accessors --- + +unsigned feePubKeyBitsize(feePubKey pubKey) +{ + pubKeyInst *pkinst = (pubKeyInst *) pubKey; + switch(pkinst->cp->primeType) { + case FPT_General: /* cp->q is here for just this purpose */ + case FPT_Mersenne: + return pkinst->cp->q; + case FPT_FEE: /* could be larger or smaller than 2^q-1 */ + default: + return bitlen(pkinst->cp->basePrime); + } + /* NOT REACHED */ + return 0; +} + +/* + * Accessor routines. + */ +/* private only...*/ +key feePubKeyPlusCurve(feePubKey pubKey) +{ + pubKeyInst *pkinst = (pubKeyInst *) pubKey; + + return pkinst->plus; +} + +key feePubKeyMinusCurve(feePubKey pubKey) +{ + pubKeyInst *pkinst = (pubKeyInst *) pubKey; + + return pkinst->minus; +} + +curveParams *feePubKeyCurveParams(feePubKey pubKey) +{ + pubKeyInst *pkinst = (pubKeyInst *) pubKey; + + return pkinst->cp; +} + +giant feePubKeyPrivData(feePubKey pubKey) +{ + pubKeyInst *pkinst = (pubKeyInst *) pubKey; + + return pkinst->privGiant; +} + +const char *feePubKeyAlgorithmName(void) +{ + return "Elliptic Curve - FEE by Apple Computer"; +} + +#pragma mark --- Private functions --- + +/* + * alloc, free pubKeyInst + */ +static pubKeyInst *pubKeyInstAlloc(void) +{ + pubKeyInst *pkinst = (pubKeyInst *) fmalloc(sizeof(pubKeyInst)); + + bzero(pkinst, sizeof(pubKeyInst)); + return pkinst; +} + +static void pubKeyInstFree(pubKeyInst *pkinst) +{ + if(pkinst->minus) { + free_key(pkinst->minus); + } + if(pkinst->plus) { + free_key(pkinst->plus); + } + if(pkinst->cp) { + freeCurveParams(pkinst->cp); + } + if(pkinst->privGiant) { + /* + * Zero out the private data... + */ + clearGiant(pkinst->privGiant); + freeGiant(pkinst->privGiant); + } + ffree(pkinst); +} + +#ifndef ECDSA_VERIFY_ONLY + +/* + * Create a pubKeyInst.privGiant given a password of + * arbitrary length. + * Currently, the only error is "private data too short" (FR_IllegalArg). + */ + +#define NO_PRIV_MUNGE 0 /* skip this step */ + +static feeReturn feeGenPrivate(pubKeyInst *pkinst, + const unsigned char *passwd, + unsigned passwdLen, + char hashPasswd) +{ + unsigned privLen; // desired size of pkinst->privData + feeHash *hash = NULL; // a malloc'd array + unsigned digestLen; // size of MD5 digest + unsigned dataSize; // min(privLen, passwdLen) + unsigned numDigests = 0; + unsigned i; + unsigned char *cp; + unsigned toMove; // for this digest + unsigned moved; // total digested + unsigned char *digest = NULL; + unsigned char *privData = NULL; // temp, before modg(curveOrder) + giant corder; // lesser of two curve orders + + /* + * generate privData which is just larger than the smaller + * curve order. + * We'll take the result mod the curve order when we're done. + * Note we do *not* have to free corder - it's a pointer to a giant + * in pkinst->cp. + */ + corder = lesserX1Order(pkinst->cp); + CKASSERT(!isZero(corder)); + privLen = (bitlen(corder) / 8) + 1; + + if(!hashPasswd) { + /* + * Caller trusts the incoming entropy. Verify it's big enough and proceed. + */ + if(passwdLen < privLen) { + return FR_ShortPrivData; + } + privLen = passwdLen; + privData = (unsigned char *)passwd; + goto finishUp; + } + if(passwdLen < 2) { + return FR_IllegalArg; + } + + + /* + * Calculate how many MD5 digests we'll generate. + */ + if(privLen > passwdLen) { + dataSize = passwdLen; + } + else { + dataSize = privLen; + } + digestLen = feeHashDigestLen(); + numDigests = (dataSize + digestLen - 1) / digestLen; + + hash = (void**) fmalloc(numDigests * sizeof(feeHash)); + for(i=0; i privLen), last digest will hash all + * remaining passwd data. + */ + cp = (unsigned char *)passwd; + moved = 0; + for(i=0; i privLen) { + toMove = privLen - moved; + } + else { + toMove = digestLen; + } + digest = feeHashDigest(hash[i++]); + bcopy(digest, cp, toMove); + cp += toMove; + moved += toMove; + if(i == numDigests) { + i = 0; // wrap to 0, start padding + } + } + +finishUp: + /* + * Convert to giant, justify result to within [2, lesserX1Order] + */ + pkinst->privGiant = giant_with_data(privData, privLen); + + #if FEE_DEBUG + if(isZero(pkinst->privGiant)) { + printf("feeGenPrivate: privData = 0!\n"); + } + #endif // FEE_DEBUG + + lesserX1OrderJustify(pkinst->privGiant, pkinst->cp); + if(hashPasswd) { + memset(privData, 0, privLen); + ffree(privData); + for(i=0; icp); + printf("plus:\n"); + printKey(pkinst->plus); + printf("minus:\n"); + printKey(pkinst->minus); + if(pkinst->privGiant != NULL) { + printf("privGiant : "); + printGiant(pkinst->privGiant); + } +} + +#else // FEE_DEBUG +void printPubKey(feePubKey pubKey) {} +#endif // FEE_DEBUG + +/* + * Prime the curveParams and giants modules for quick allocs of giants. + */ +#if GIANTS_VIA_STACK + +static int giantsInitd = 0; + +static void feePubKeyInitGiants(void) +{ + if(giantsInitd) { + return; + } + curveParamsInitGiants(); + giantsInitd = 1; +} +#endif + +#pragma mark --- Native (custom) key blob formatting --- + +/* + * Exported key blob support. New, 23 Mar 1998. + * + * Convert to public or private key blob. + */ + +#ifndef ECDSA_VERIFY_ONLY + +/*** + *** Common native blob support + ***/ +static feeReturn createKeyBlob(pubKeyInst *pkinst, + int isPrivate, // 0 : public 1 : private + unsigned char **keyBlob, // mallocd and RETURNED + unsigned *keyBlobLen) // RETURNED +{ + unsigned char *s; // running ptr into *origS + unsigned sLen; + int magic; + + /* common blob elements */ + sLen = (4 * sizeof(int)) + // magic, version, minVersion, + // spare + lengthOfByteRepCurveParams(pkinst->cp); + if(isPrivate) { + /* private only */ + sLen += lengthOfByteRepGiant(pkinst->privGiant); + magic = PUBLIC_KEY_BLOB_MAGIC_PRIV; + } + else { + /* public only */ + sLen += (lengthOfByteRepKey(pkinst->plus) + + lengthOfByteRepKey(pkinst->minus)); + magic = PUBLIC_KEY_BLOB_MAGIC_PUB; + } + *keyBlob = s = (unsigned char*) fmalloc(sLen); + s += intToByteRep(magic, s); + s += intToByteRep(PUBLIC_KEY_BLOB_VERSION, s); + s += intToByteRep(PUBLIC_KEY_BLOB_MINVERSION, s); + s += intToByteRep(0, s); // spare + s += curveParamsToByteRep(pkinst->cp, s); + if(isPrivate) { + s += giantToByteRep(pkinst->privGiant, s); + } + else { + /* keyToByteRep writes y for plus curve only */ + s += keyToByteRep(pkinst->plus, s); + if(pkinst->minus != NULL) { + s += keyToByteRep(pkinst->minus, s); + } + else { + /* TBD */ + dbgLog(("work needed here for blobs with no minus key\n")); + } + } + *keyBlobLen = sLen; + return FR_Success; +} + +#endif /* ECDSA_VERIFY_ONLY */ + +/* + * Init an empty feePubKey from a native blob (non-DER format). + */ +static feeReturn feePubKeyInitFromKeyBlob(feePubKey pubKey, + unsigned char *keyBlob, + unsigned keyBlobLen) +{ + pubKeyInst *pkinst = (pubKeyInst *) pubKey; + unsigned char *s; // running pointer + unsigned sLen; // bytes remaining in *s + int magic; + unsigned len; // for length of individual components + int minVersion; + int version; + int isPrivate; + + s = keyBlob; + sLen = keyBlobLen; + if(sLen < (4 * sizeof(int))) { // magic, version, minVersion, spare + /* + * Too short for all the ints we need + */ + dbgLog(("feePublicKey: key blob (1)\n")); + return FR_BadKeyBlob; + } + + magic = byteRepToInt(s); + s += sizeof(int); + sLen -= sizeof(int); + switch(magic) { + case PUBLIC_KEY_BLOB_MAGIC_PUB: + isPrivate = 0; + break; + case PUBLIC_KEY_BLOB_MAGIC_PRIV: + isPrivate = 1; + break; + default: + dbgLog(("feePublicKey: Bad Public Key Magic Number\n")); + return FR_BadKeyBlob; + } + + /* + * Switch on this for version-specific cases + */ + version = byteRepToInt(s); + s += sizeof(int); + sLen -= sizeof(int); + + minVersion = byteRepToInt(s); + s += sizeof(int); + sLen -= sizeof(int); + if(minVersion > PUBLIC_KEY_BLOB_VERSION) { + /* + * old code, newer key blob - can't parse + */ + dbgLog(("feePublicKey: Incompatible Public Key (1)\n")); + return FR_BadKeyBlob; + } + + s += sizeof(int); // skip spare + sLen -= sizeof(int); + + pkinst->cp = byteRepToCurveParams(s, sLen, &len); + if(pkinst->cp == NULL) { + dbgLog(("feePublicKey: Bad Key Blob(2)\n")); + return FR_BadKeyBlob; + } + s += len; + sLen -= len; + + /* + * Private key blob: privGiant. + * Public Key blob: plusX, minusX, plusY. + */ + if(isPrivate) { + pkinst->privGiant = byteRepToGiant(s, sLen, &len); + if(pkinst->privGiant == NULL) { + dbgLog(("feePublicKey: Bad Key Blob(3)\n")); + return FR_BadKeyBlob; + } + s += len; + sLen -= len; + } + else { + /* this writes x and y */ + pkinst->plus = byteRepToKey(s, + sLen, + CURVE_PLUS, // twist + pkinst->cp, + &len); + if(pkinst->plus == NULL) { + dbgLog(("feePublicKey: Bad Key Blob(4)\n")); + return FR_BadKeyBlob; + } + s += len; + sLen -= len; + + /* this only writes x */ + pkinst->minus = byteRepToKey(s, + sLen, + CURVE_MINUS, // twist + pkinst->cp, + &len); + if(pkinst->minus == NULL) { + dbgLog(("feePublicKey: Bad Key Blob(5)\n")); + return FR_BadKeyBlob; + } + s += len; + sLen -= len; + } + + /* + * One more thing: cook up public plusX and minusX for private key + * blob case. + */ + if(isPrivate) { + pkinst->plus = new_public(pkinst->cp, CURVE_PLUS); + pkinst->minus = new_public(pkinst->cp, CURVE_MINUS); + set_priv_key_giant(pkinst->plus, pkinst->privGiant); + set_priv_key_giant(pkinst->minus, pkinst->privGiant); + } + return FR_Success; + +} + +feeReturn feePubKeyInitFromPubBlob(feePubKey pubKey, + unsigned char *keyBlob, + unsigned keyBlobLen) +{ + return feePubKeyInitFromKeyBlob(pubKey, keyBlob, keyBlobLen); +} + +#ifndef ECDSA_VERIFY_ONLY + +feeReturn feePubKeyInitFromPrivBlob(feePubKey pubKey, + unsigned char *keyBlob, + unsigned keyBlobLen) +{ + return feePubKeyInitFromKeyBlob(pubKey, keyBlob, keyBlobLen); +} + +#endif /* ECDSA_VERIFY_ONLY */ + +#if CRYPTKIT_DER_ENABLE +#ifndef ECDSA_VERIFY_ONLY + +/* + * DER format support. + * Obtain portable public and private DER-encoded key blobs from a key. + */ +feeReturn feePubKeyCreateDERPubBlob(feePubKey pubKey, + unsigned char **keyBlob, // mallocd and RETURNED + unsigned *keyBlobLen) // RETURNED +{ + pubKeyInst *pkinst = (pubKeyInst *)pubKey; + + if(pkinst == NULL) { + return FR_BadPubKey; + } + if(pkinst->minus == NULL) { + /* Only ECDSA key formats supported */ + return FR_IncompatibleKey; + } + return feeDEREncodePublicKey(PUBLIC_DER_KEY_BLOB_VERSION, + pkinst->cp, + pkinst->plus->x, + pkinst->minus->x, + isZero(pkinst->plus->y) ? NULL : pkinst->plus->y, + keyBlob, + keyBlobLen); +} + +feeReturn feePubKeyCreateDERPrivBlob(feePubKey pubKey, + unsigned char **keyBlob, // mallocd and RETURNED + unsigned *keyBlobLen) // RETURNED +{ + pubKeyInst *pkinst = (pubKeyInst *)pubKey; + + if(pkinst == NULL) { + return FR_BadPubKey; + } + if(pkinst->privGiant == NULL) { + return FR_IncompatibleKey; + } + if(pkinst->minus == NULL) { + /* Only ECDSA key formats supported */ + return FR_IncompatibleKey; + } + return feeDEREncodePrivateKey(PUBLIC_DER_KEY_BLOB_VERSION, + pkinst->cp, + pkinst->privGiant, + keyBlob, + keyBlobLen); +} + +#endif /* ECDSA_VERIFY_ONLY */ + +/* + * Init an empty feePubKey from a DER-encoded blob, public and private key versions. + */ +feeReturn feePubKeyInitFromDERPubBlob(feePubKey pubKey, + unsigned char *keyBlob, + size_t keyBlobLen) +{ + pubKeyInst *pkinst = (pubKeyInst *) pubKey; + feeReturn frtn; + int version; + + if(pkinst == NULL) { + return FR_BadPubKey; + } + + /* kind of messy, maybe we should clean this up. But new_public() does too + * much - e.g., it allocates the x and y which we really don't want */ + memset(pkinst, 0, sizeof(pubKeyInst)); + pkinst->plus = (key) fmalloc(sizeof(keystruct)); + pkinst->minus = (key) fmalloc(sizeof(keystruct)); + if((pkinst->plus == NULL) || (pkinst->minus == NULL)) { + return FR_Memory; + } + memset(pkinst->plus, 0, sizeof(keystruct)); + memset(pkinst->minus, 0, sizeof(keystruct)); + pkinst->cp = NULL; + pkinst->privGiant = NULL; + pkinst->plus->twist = CURVE_PLUS; + pkinst->minus->twist = CURVE_MINUS; + frtn = feeDERDecodePublicKey(keyBlob, + keyBlobLen, + &version, // currently unused + &pkinst->cp, + &pkinst->plus->x, + &pkinst->minus->x, + &pkinst->plus->y); + if(frtn) { + return frtn; + } + /* minus curve, y is not used */ + pkinst->minus->y = newGiant(1); + int_to_giant(0, pkinst->minus->y); + pkinst->plus->cp = pkinst->minus->cp = pkinst->cp; + return FR_Success; +} + +#ifndef ECDSA_VERIFY_ONLY + +feeReturn feePubKeyInitFromDERPrivBlob(feePubKey pubKey, + unsigned char *keyBlob, + size_t keyBlobLen) +{ + pubKeyInst *pkinst = (pubKeyInst *) pubKey; + int version; + feeReturn frtn; + + if(pkinst == NULL) { + return FR_BadPubKey; + } + memset(pkinst, 0, sizeof(pubKeyInst)); + frtn = feeDERDecodePrivateKey(keyBlob, + keyBlobLen, + &version, // currently unused + &pkinst->cp, + &pkinst->privGiant); + if(frtn) { + return frtn; + } + + /* since this blob only had the private data, infer the remaining fields */ + pkinst->plus = new_public(pkinst->cp, CURVE_PLUS); + pkinst->minus = new_public(pkinst->cp, CURVE_MINUS); + set_priv_key_giant(pkinst->plus, pkinst->privGiant); + set_priv_key_giant(pkinst->minus, pkinst->privGiant); + return FR_Success; +} + +#endif /* ECDSA_VERIFY_ONLY */ + +#pragma mark --- X509 (public) and PKCS8 (private) key formatting --- + +feeReturn feePubKeyCreateX509Blob( + feePubKey pubKey, // public key + unsigned char **keyBlob, // mallocd and RETURNED + unsigned *keyBlobLen) // RETURNED +{ + pubKeyInst *pkinst = (pubKeyInst *) pubKey; + unsigned char *xyStr = NULL; + unsigned xyStrLen = 0; + feeReturn frtn = feeCreateECDSAPubBlob(pubKey, &xyStr, &xyStrLen); + if(frtn) { + return frtn; + } + frtn = feeDEREncodeX509PublicKey(xyStr, xyStrLen, pkinst->cp, keyBlob, keyBlobLen); + ffree(xyStr); + return frtn; +} + +feeReturn feePubKeyCreatePKCS8Blob( + feePubKey pubKey, // private key + unsigned char **keyBlob, // mallocd and RETURNED + unsigned *keyBlobLen) // RETURNED +{ + pubKeyInst *pkinst = (pubKeyInst *) pubKey; + unsigned char *privStr = NULL; + unsigned privStrLen = 0; + feeReturn frtn = feeCreateECDSAPrivBlob(pubKey, &privStr, &privStrLen); + if(frtn) { + return frtn; + } + unsigned char *pubStr = NULL; + unsigned pubStrLen = 0; + frtn = feeCreateECDSAPubBlob(pubKey, &pubStr, &pubStrLen); + if(frtn) { + goto errOut; + } + frtn = feeDEREncodePKCS8PrivateKey(privStr, privStrLen, + pubStr, pubStrLen, + pkinst->cp, keyBlob, keyBlobLen); +errOut: + if(privStr) { + ffree(privStr); + } + if(pubStr) { + ffree(pubStr); + } + return frtn; +} + +feeReturn feePubKeyInitFromX509Blob( + feePubKey pubKey, // public key + unsigned char *keyBlob, + size_t keyBlobLen) +{ + feeDepth depth; + unsigned char *xyStr = NULL; + unsigned xyStrLen = 0; + + /* obtain x/y and depth from X509 encoding */ + feeReturn frtn = feeDERDecodeX509PublicKey(keyBlob, keyBlobLen, &depth, + &xyStr, &xyStrLen); + if(frtn) { + return frtn; + } + + frtn = feePubKeyInitFromECDSAPubBlob(pubKey, xyStr, xyStrLen, depth); + ffree(xyStr); + return frtn; +} + + +feeReturn feePubKeyInitFromPKCS8Blob( + feePubKey pubKey, // private key + unsigned char *keyBlob, + size_t keyBlobLen) +{ + feeDepth depth; + unsigned char *privStr = NULL; + unsigned privStrLen = 0; + + /* obtain x/y and depth from PKCS8 encoding */ + /* For now we ignore the possible public key string */ + feeReturn frtn = feeDERDecodePKCS8PrivateKey(keyBlob, keyBlobLen, &depth, + &privStr, &privStrLen, NULL, NULL); + if(frtn) { + return frtn; + } + + frtn = feePubKeyInitFromECDSAPrivBlob(pubKey, privStr, privStrLen, depth); + ffree(privStr); + return frtn; +} + +#pragma mark --- OpenSSL key formatting --- + +/* + * The native OpenSSL ECDSA key format contains both the private and public + * components in one blob. This throws a bit of a monkey wrench into the API + * here, as we only have one encoder - which requires a private key - and one + * decoder, which can result in the decoding of either a public or a private + * key. + */ +feeReturn feePubKeyCreateOpenSSLBlob( + feePubKey pubKey, // private key + unsigned char **keyBlob, // mallocd and RETURNED + unsigned *keyBlobLen) // RETURNED +{ + pubKeyInst *pkinst = (pubKeyInst *) pubKey; + unsigned char *privStr = NULL; + unsigned privStrLen = 0; + feeReturn frtn = feeCreateECDSAPrivBlob(pubKey, &privStr, &privStrLen); + if(frtn) { + return frtn; + } + unsigned char *pubStr = NULL; + unsigned pubStrLen = 0; + frtn = feeCreateECDSAPubBlob(pubKey, &pubStr, &pubStrLen); + if(frtn) { + goto errOut; + } + frtn = feeDEREncodeOpenSSLPrivateKey(privStr, privStrLen, + pubStr, pubStrLen, + pkinst->cp, keyBlob, keyBlobLen); +errOut: + if(privStr) { + ffree(privStr); + } + if(pubStr) { + ffree(pubStr); + } + return frtn; +} + +feeReturn feePubKeyInitFromOpenSSLBlob( + feePubKey pubKey, // private or public key + int pubOnly, + unsigned char *keyBlob, + size_t keyBlobLen) +{ + feeDepth depth; + unsigned char *privStr = NULL; + unsigned privStrLen = 0; + unsigned char *pubStr = NULL; + unsigned pubStrLen = 0; + + /* obtain x/y, public bit string, and depth from PKCS8 encoding */ + feeReturn frtn = feeDERDecodeOpenSSLKey(keyBlob, keyBlobLen, &depth, + &privStr, &privStrLen, &pubStr, &pubStrLen); + if(frtn) { + return frtn; + } + + if(pubOnly) { + frtn = feePubKeyInitFromECDSAPubBlob(pubKey, pubStr, pubStrLen, depth); + } + else { + frtn = feePubKeyInitFromECDSAPrivBlob(pubKey, privStr, privStrLen, depth); + } + if(privStr) { + ffree(privStr); + } + if(pubStr) { + ffree(pubStr); + } + return frtn; +} + +#endif /* CRYPTKIT_DER_ENABLE */ + +/* + * ANSI X9.62/Certicom key support. + * Public key is 04 || x || y + * Private key is privData per Certicom SEC1 C.4. + */ +feeReturn feeCreateECDSAPubBlob(feePubKey pubKey, + unsigned char **keyBlob, + unsigned *keyBlobLen) +{ + pubKeyInst *pkinst = (pubKeyInst *)pubKey; + if(pkinst == NULL) { + return FR_BadPubKey; + } + + unsigned giantBytes = (pkinst->cp->q + 7) / 8; + unsigned blobSize = 1 + (2 * giantBytes); + unsigned char *blob = fmalloc(blobSize); + if(blob == NULL) { + return FR_Memory; + } + *blob = 0x04; + serializeGiant(pkinst->plus->x, blob+1, giantBytes); + serializeGiant(pkinst->plus->y, blob+1+giantBytes, giantBytes); + *keyBlob = blob; + *keyBlobLen = blobSize; + return FR_Success; +} + +feeReturn feeCreateECDSAPrivBlob(feePubKey pubKey, + unsigned char **keyBlob, + unsigned *keyBlobLen) +{ + pubKeyInst *pkinst = (pubKeyInst *)pubKey; + if(pkinst == NULL) { + return FR_BadPubKey; + } + if(pkinst->privGiant == NULL) { + return FR_IncompatibleKey; + } + + /* + * Return the raw private key bytes padded with zeroes in + * the m.s. end to fill exactly one prime-size byte array. + */ + unsigned giantBytes = (pkinst->cp->q + 7) / 8; + unsigned char *blob = fmalloc(giantBytes); + if(blob == NULL) { + return FR_Memory; + } + serializeGiant(pkinst->privGiant, blob, giantBytes); + *keyBlob = blob; + *keyBlobLen = giantBytes; + return FR_Success; +} + +/* Caller determines depth from other sources (e.g. AlgId.Params) */ +feeReturn feePubKeyInitFromECDSAPubBlob(feePubKey pubKey, + const unsigned char *keyBlob, + unsigned keyBlobLen, + feeDepth depth) +{ + pubKeyInst *pkinst = (pubKeyInst *)pubKey; + if(pkinst == NULL) { + return FR_BadPubKey; + } + curveParams *cp = curveParamsForDepth(depth); + if(cp == NULL) { + return FR_IllegalDepth; + } + unsigned giantBytes = (cp->q + 7) / 8; + unsigned blobSize = 1 + (2 * giantBytes); + if(keyBlobLen != blobSize) { + dbgLog(("feePubKeyInitFromECDSAPubBlob: bad blobLen\n")); + return FR_BadKeyBlob; + } + if(*keyBlob != 0x04) { + dbgLog(("feePubKeyInitFromECDSAPubBlob: bad blob leader\n")); + return FR_BadKeyBlob; + } + + pkinst->cp = cp; + pkinst->plus = new_public(cp, CURVE_PLUS); + deserializeGiant(keyBlob+1, pkinst->plus->x, giantBytes); + deserializeGiant(keyBlob+1+giantBytes, pkinst->plus->y, giantBytes); + return FR_Success; +} + +feeReturn feePubKeyInitFromECDSAPrivBlob(feePubKey pubKey, + const unsigned char *keyBlob, + unsigned keyBlobLen, + feeDepth depth) +{ + pubKeyInst *pkinst = (pubKeyInst *)pubKey; + if(pkinst == NULL) { + return FR_BadPubKey; + } + curveParams *cp = curveParamsForDepth(depth); + if(cp == NULL) { + return FR_IllegalDepth; + } + unsigned giantDigits = cp->basePrime->sign; + unsigned giantBytes = (cp->q + 7) / 8; + + /* + * The specified private key can be one byte smaller than the modulus */ + if((keyBlobLen > giantBytes) || (keyBlobLen < (giantBytes - 1))) { + dbgLog(("feePubKeyInitFromECDSAPrivBlob: bad blobLen\n")); + return FR_BadKeyBlob; + } + + pkinst->cp = cp; + + /* cook up a new private giant */ + pkinst->privGiant = newGiant(giantDigits); + if(pkinst->privGiant == NULL) { + return FR_Memory; + } + deserializeGiant(keyBlob, pkinst->privGiant, keyBlobLen); + + /* since this blob only had the private data, infer the remaining fields */ + pkinst->plus = new_public(pkinst->cp, CURVE_PLUS); + set_priv_key_giant(pkinst->plus, pkinst->privGiant); + return FR_Success; +} + diff --git a/libsecurity_cryptkit/lib/feePublicKey.h b/libsecurity_cryptkit/lib/feePublicKey.h new file mode 100644 index 00000000..e9a39815 --- /dev/null +++ b/libsecurity_cryptkit/lib/feePublicKey.h @@ -0,0 +1,341 @@ +/* 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. + *************************************************************************** + * + * feePublicKey.h + * + * Revision History + * ---------------- + * 23 Mar 98 Doug Mitchell at Apple + * Added blob support. + * 17 Jul 97 Doug Mitchell at Apple + * Added ECDSA signature routines. + * 20 Aug 96 Doug Mitchell at NeXT + * Created. + */ + +#ifndef _CK_FEEPUBLICKEY_H_ +#define _CK_FEEPUBLICKEY_H_ + +#include "ckconfig.h" + +#include /* size_t */ + +#if !defined(__MACH__) +#include +#else +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Obatin a newly allocated feePubKey. + */ +feePubKey feePubKeyAlloc(void); + +void feePubKeyFree(feePubKey pubKey); + +/* + * Init feePubKey from private "password" data. Incoming password data will + * be processed with digests before use if hashPrivData is true, otherwise + * it'll be used as is. In the 'as is' case, the privData must be at least + * as large as the key being created. + * + * Currently two versions - one in which the size of the key is specified as + * a feeDepth; one for key size in bits and optional primeType and curveType. + */ +feeReturn feePubKeyInitFromPrivDataDepth(feePubKey pubKey, + const unsigned char *privData, + unsigned privDataLen, + feeDepth depth, + char hashPrivData); + +feeReturn feePubKeyInitFromPrivDataKeyBits(feePubKey pubKey, + const unsigned char *privData, + unsigned privDataLen, + unsigned keyBits, /* key size in bits */ + feePrimeType primeType, /* FPT_Fefault means "best one" */ + feeCurveType curveType, /* FCT_Default means "best one" */ + char hashPrivData); + +/* + * Init feePubKey from private "password" and from data curve parameters + * matching existing oldKey. Incoming password data will + * be processed with digests before use if hashPrivData is true, otherwise + * it'll be used as is. In the 'as is' case, the privData must be at least + * as large as the key being created. + + */ +feeReturn feePubKeyInitFromKey(feePubKey pubKey, + const unsigned char *privData, + unsigned privDataLen, + feePubKey oldKey, + char hashPrivData); + +/*** + *** Exportable key blob support. + *** + *** Currently there are three different ways of representing a feePubKey in + *** an exportable format. + *** + *** Raw blob: basic native blob format. + *** DER blob: DER-encoded. Currently not available in ANSI C version of + *** CryptKit library without additional porting; the OS X version of + *** Apple implements this functionality via SNACC-generated C++ classes. + *** KeyString: NULL-terminated ASCII C string, suitable for application such as + *** distributing one's public key via email. Only public keys (not + *** private) can be exported and imported via KeyStrings. + ***/ + +/* + * Obtain portable public and private key blobs from a key. + */ +feeReturn feePubKeyCreatePubBlob(feePubKey pubKey, + unsigned char **keyBlob, // mallocd and RETURNED + unsigned *keyBlobLen); // RETURNED + +feeReturn feePubKeyCreatePrivBlob(feePubKey pubKey, + unsigned char **keyBlob, // mallocd and RETURNED + unsigned *keyBlobLen); // RETURNED + +/* + * Init an empty feePubKey from a blob, public and private key versions. + */ +feeReturn feePubKeyInitFromPubBlob(feePubKey pubKey, + unsigned char *keyBlob, + unsigned keyBlobLen); +feeReturn feePubKeyInitFromPrivBlob(feePubKey pubKey, + unsigned char *keyBlob, + unsigned keyBlobLen); + +/* + * Create a public key in the form of a null-terminated C string. + */ +feeReturn feePubKeyCreateKeyString(feePubKey pubKey, + char **pubKeyString, /* fmalloc'd & RETURNED */ + unsigned *pubKeyStringLen); /* RETURNED */ + +/* + * Init feePubKey from a public key string. + */ +feeReturn feePubKeyInitFromKeyString(feePubKey pubKey, + const char *keyStr, + unsigned keyStrLen); + +#if CRYPTKIT_DER_ENABLE + +/* + * DER format support. + * Obtain portable public and private DER-encoded key blobs from a key. + */ +feeReturn feePubKeyCreateDERPubBlob(feePubKey pubKey, + unsigned char **keyBlob, // mallocd and RETURNED + unsigned *keyBlobLen); // RETURNED + +feeReturn feePubKeyCreateDERPrivBlob(feePubKey pubKey, + unsigned char **keyBlob, // mallocd and RETURNED + unsigned *keyBlobLen); // RETURNED + +/* + * Init an empty feePubKey from a DER-encoded blob, public and private key versions. + */ +feeReturn feePubKeyInitFromDERPubBlob(feePubKey pubKey, + unsigned char *keyBlob, + size_t keyBlobLen); +feeReturn feePubKeyInitFromDERPrivBlob(feePubKey pubKey, + unsigned char *keyBlob, + size_t keyBlobLen); + +/* + * X509 (public) and PKCS8 (private) key formatting. + */ +feeReturn feePubKeyCreateX509Blob( + feePubKey pubKey, // public key + unsigned char **keyBlob, // mallocd and RETURNED + unsigned *keyBlobLen); // RETURNED + +feeReturn feePubKeyCreatePKCS8Blob( + feePubKey pubKey, // private key + unsigned char **keyBlob, // mallocd and RETURNED + unsigned *keyBlobLen); // RETURNED + +feeReturn feePubKeyInitFromX509Blob( + feePubKey pubKey, // public key + unsigned char *keyBlob, + size_t keyBlobLen); + +feeReturn feePubKeyInitFromPKCS8Blob( + feePubKey pubKey, // private key + unsigned char *keyBlob, + size_t keyBlobLen); + +/* + * The native OpenSSL ECDSA key format contains both the private and public + * components in one blob. This throws a bit of a monkey wrench into the API + * here, as we only have one encoder - which requires a private key - and one + * decoder, which can result in the decoding of either a public or a private + * key. + */ +feeReturn feePubKeyCreateOpenSSLBlob( + feePubKey pubKey, // private key + unsigned char **keyBlob, // mallocd and RETURNED + unsigned *keyBlobLen); // RETURNED + +feeReturn feePubKeyInitFromOpenSSLBlob( + feePubKey pubKey, // private or public key + int pubOnly, + unsigned char *keyBlob, + size_t keyBlobLen); + +#endif /* CRYPTKIT_DER_ENABLE */ + +/* + * ANSI X9.62/Certicom key support. + * Public key is 04 || x || y + * Private key is privData per Certicom SEC1 C.4. + */ +feeReturn feeCreateECDSAPubBlob(feePubKey pubKey, + unsigned char **keyBlob, + unsigned *keyBlobLen); + +feeReturn feeCreateECDSAPrivBlob(feePubKey pubKey, + unsigned char **keyBlob, + unsigned *keyBlobLen); + +/* Caller determines depth from other sources (e.g. AlgId.Params) */ +feeReturn feePubKeyInitFromECDSAPubBlob(feePubKey pubKey, + const unsigned char *keyBlob, + unsigned keyBlobLen, + feeDepth depth); + +feeReturn feePubKeyInitFromECDSAPrivBlob(feePubKey pubKey, + const unsigned char *keyBlob, + unsigned keyBlobLen, + feeDepth depth); + + +/*** + *** Miscellaneous feePubKey functions. + ***/ + +/* + * Given private-capable privKey, initialize pubKey to be its corresponding + * public key. + */ +feeReturn feePubKeyInitPubKeyFromPriv(feePubKey privKey, + feePubKey pubKey); + +/* + * Returns non-zero if two keys are equivalent. + */ +int feePubKeyIsEqual(feePubKey key1, + feePubKey key2); + +/* + * Returns non-zero if key is private-capable (i.e., capable of signing + * and decrypting). + */ +int feePubKeyIsPrivate(feePubKey key); + +#if CRYPTKIT_KEY_EXCHANGE + +/* + * Generate a pad, for use with symmetric encryption, derived from two keys. + * 'myKey' must be created with private data (via feePubKeyInitFromPrivData() + * or feePubKeyInitFromKey(). + */ +feeReturn feePubKeyCreatePad(feePubKey myKey, + feePubKey theirKey, + unsigned char **padData, /* fmalloc'd & RETURNED */ + unsigned *padDataLen); /* RETURNED padData length in bytes */ + +#endif /* CRYPTKIT_KEY_EXCHANGE */ + +#if CRYPTKIT_HIGH_LEVEL_SIG + +/* + * The following two routines are implemented using primitives in the + * feeHash and feeDigitalSignature objects. + * + * Generate digital signature, ElGamal style. + */ +feeReturn feePubKeyCreateSignature(feePubKey pubKey, + const unsigned char *data, + unsigned dataLen, + unsigned char **signature, /* fmalloc'd and RETURNED */ + unsigned *signatureLen); /* RETURNED */ + +/* + * Verify digital signature, ElGamal style. + */ +feeReturn feePubKeyVerifySignature(feePubKey pubKey, + const unsigned char *data, + unsigned dataLen, + const unsigned char *signature, + unsigned signatureLen); + +#if CRYPTKIT_ECDSA_ENABLE + +/* + * The following two routines are implemented using primitives in the + * feeHash and feeECDSA objects. + * + * Generate digital signature, ECDSA style. + */ +feeReturn feePubKeyCreateECDSASignature(feePubKey pubKey, + const unsigned char *data, + unsigned dataLen, + unsigned char **signature, /* fmalloc'd and RETURNED */ + unsigned *signatureLen); /* RETURNED */ + +/* + * Verify digital signature, ECDSA style. + */ +feeReturn feePubKeyVerifyECDSASignature(feePubKey pubKey, + const unsigned char *data, + unsigned dataLen, + const unsigned char *signature, + unsigned signatureLen); + +#endif /* CRYPTKIT_ECDSA_ENABLE */ + +#endif /* CRYPTKIT_HIGH_LEVEL_SIG */ + +/* + * Diffie-Hellman. Public key is specified either as a feePubKey or + * a ANSI X9.62 format public key string (0x04 | x | y). In either case + * the caller must ensure that the two keys are on the same curve. + * Output data is falloc'd here; caller must free. Output data is + * exactly the size of the curve's modulus in bytes. + */ +feeReturn feePubKeyECDH( + feePubKey privKey, + /* one of the following two is non-NULL */ + feePubKey pubKey, + const unsigned char *pubKeyStr, + unsigned pubKeyStrLen, + /* output fallocd and RETURNED here */ + unsigned char **output, + unsigned *outputLen); + +/* + * Accessor routines. + */ +const char *feePubKeyAlgorithmName(void); + +unsigned feePubKeyBitsize(feePubKey pubKey); + +#ifdef __cplusplus +} +#endif + +#endif /*_CK_FEEPUBLICKEY_H_*/ diff --git a/libsecurity_cryptkit/lib/feePublicKeyPrivate.h b/libsecurity_cryptkit/lib/feePublicKeyPrivate.h new file mode 100644 index 00000000..006deaf1 --- /dev/null +++ b/libsecurity_cryptkit/lib/feePublicKeyPrivate.h @@ -0,0 +1,43 @@ +/* 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. + *************************************************************************** + * + * feePublicKeyPrivate.h - feePublicKey private function declarations + * + * Revision History + * ---------------- + * 10/06/98 ap + * Changed to compile with C++. + * 28 Aug 96 Doug Mitchell at NeXT + * Created. + */ + +#ifndef _CK_FEEPUBKEYPRIV_H_ +#define _CK_FEEPUBKEYPRIV_H_ + +#include "feeTypes.h" +#include "feePublicKey.h" +#include "feeDebug.h" +#include "elliptic.h" + +#ifdef __cplusplus +extern "C" { +#endif + +key feePubKeyPlusCurve(feePubKey pubKey); +key feePubKeyMinusCurve(feePubKey pubKey); +curveParams *feePubKeyCurveParams(feePubKey pubKey); +giant feePubKeyPrivData(feePubKey pubKey); +void printPubKey(feePubKey pubKey); + +#ifdef __cplusplus +} +#endif + +#endif /*_CK_FEEPUBKEYPRIV_H_*/ diff --git a/libsecurity_cryptkit/lib/feeRandom.c b/libsecurity_cryptkit/lib/feeRandom.c new file mode 100644 index 00000000..0e11654f --- /dev/null +++ b/libsecurity_cryptkit/lib/feeRandom.c @@ -0,0 +1,206 @@ +/* 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. + *************************************************************************** + * + * FeeRandom.c - generic, portable random number generator object + * + * Revision History + * ---------------- + * 10/06/98 ap + * Changed to compile with C++. + * 19 Jun 97 Doug Mitchell at Apple + * Eliminated predictability of bytes 4 thru 15 of random data + * 18 Jun 97 Doug Mitchell at Apple + * Reduced size of per-instance giants from 128 to 32 shorts + * 23 Aug 96 Doug Mitchell at NeXT + * Created, based on Blaine Garst's NSRandomNumberGenerator class + */ + +#include "feeRandom.h" +#include "giantIntegers.h" +#include "elliptic.h" +#include "falloc.h" +#include "feeDebug.h" +#include "byteRep.h" +#include +#include "platform.h" + +/* + * 1 ==> do extra nextNum on feeRandAllocWithSeed() + */ +#define EXTRA_NEXT_NUM 0 + +#define RANDBITS 128 /* must be 0 mod GIANT_BITS_PER_DIGIT */ +#define RAND_GIANT_DIGITS (RANDBITS/GIANT_BITS_PER_DIGIT) + +typedef struct { + giant A; + giant C; + giant SEED; + giant x; +} randInst; + +#if GIANTS_VIA_STACK + +/* + * Prime the curveParams and giants modules for quick allocs of giants. + */ +static int giantsInitd = 0; + +static void feeRandInitGiants() +{ + if(giantsInitd) { + return; + } + curveParamsInitGiants(); + giantsInitd = 1; +} +#endif + +static void pmod(giant x, int bits) { + /* Force x to be x (mod 2^bits). */ + int j; + int digits = bits / GIANT_BITS_PER_DIGIT; + + for(j = (digits-1); j >= 0; j--) { + if(x->n[j] != 0) break; + } + x->sign = j+1; +} + + +feeRand feeRandAllocWithSeed(unsigned seed) +{ + randInst *rinst = (randInst *) fmalloc(sizeof(randInst)); + int digits = RAND_GIANT_DIGITS * 4; + unsigned j; + + #if GIANTS_VIA_STACK + feeRandInitGiants(); + #endif + rinst->SEED = newGiant(digits); + rinst->C = newGiant(digits); + rinst->A = newGiant(digits); + rinst->x = newGiant(digits); + rinst->C->sign = rinst->A->sign = rinst->SEED->sign = RAND_GIANT_DIGITS; + for(j=0; jC->n[j] = (giantDigit)(seed + 0xdddddddd - j); + rinst->A->n[j] = (giantDigit)(seed + 0xfff12223 + j); + rinst->SEED->n[j] = (giantDigit)(seed + j); + } + + /* + * on the first feeRandBytes or feeRandNextNum, bytes 4 and 5 of + * the result are duplicated 4.5 times (up to byte 15). Subsequent + * data is indeed random. Thus... + */ + #if EXTRA_NEXT_NUM + feeRandNextNum(rinst); + #endif // EXTRA_NEXT_NUM + return rinst; +} + +feeRand feeRandAlloc(void) +{ + return feeRandAllocWithSeed(createRandomSeed()); +} + +void feeRandFree(feeRand frand) +{ + randInst *rinst = (randInst *) frand; + + clearGiant(rinst->A); + freeGiant(rinst->A); + clearGiant(rinst->C); + freeGiant(rinst->C); + clearGiant(rinst->SEED); + freeGiant(rinst->SEED); + clearGiant(rinst->x); + freeGiant(rinst->x); + ffree(rinst); +} + +unsigned feeRandNextNum(feeRand frand) +{ + randInst *rinst = (randInst *) frand; + unsigned rtn; + + mulg(rinst->A, rinst->SEED); + addg(rinst->C, rinst->SEED); + pmod(rinst->SEED, RANDBITS); + gtog(rinst->SEED, rinst->x); + + /* + * FIXME - this is not quite correct; rinst->x only has 4 bytes + * of valid data if RANDBITS is known to be greater than or equal + * to 32. + */ + rtn = byteRepToInt((unsigned char *)&rinst->x->n); + return rtn; +} + +void feeRandBytes(feeRand frand, + unsigned char *bytes, /* must be alloc'd by caller */ + unsigned numBytes) +{ + randInst *rinst = (randInst *) frand; + int length; + unsigned toCopy; + unsigned char *cp = bytes; + + for (length = numBytes; length > 0; length -= RANDBITS/8) { + mulg(rinst->A, rinst->SEED); + addg(rinst->C, rinst->SEED); + pmod(rinst->SEED, RANDBITS); + gtog(rinst->SEED, rinst->x); + + toCopy = RANDBITS/8; + if(length < toCopy) { + toCopy = length; + } + + /* + * FIXME - not 100% platform independent.... + */ + bcopy(rinst->x->n, cp, toCopy); + cp += toCopy; + } +} + +/* new function, 5 March 1999 - dmitch */ +void feeRandAddEntropy(feeRand frand, unsigned entropy) +{ + randInst *rinst = (randInst *) frand; + giant tmp = borrowGiant(RAND_GIANT_DIGITS); + unsigned i; + + if(entropy == 0) { + /* boy would that be a mistake */ + entropy = 0x12345; + } + for(i=0; in[i] = (giantDigit)entropy; + } + tmp->sign = RAND_GIANT_DIGITS; + mulg(tmp, rinst->SEED); + addg(rinst->C, rinst->SEED); + pmod(rinst->SEED, RANDBITS); + entropy ^= 0xff0ff0ff; + if(entropy == 0) { + entropy = 0x12345; + } + for(i=0; in[i] = (giantDigit)entropy; + } + mulg(tmp, rinst->A); + addg(rinst->C, rinst->A); + pmod(rinst->A, RANDBITS); + /* leave C alone */ + returnGiant(tmp); +} diff --git a/libsecurity_cryptkit/lib/feeRandom.h b/libsecurity_cryptkit/lib/feeRandom.h new file mode 100644 index 00000000..a1953b3b --- /dev/null +++ b/libsecurity_cryptkit/lib/feeRandom.h @@ -0,0 +1,49 @@ +/* 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. + *************************************************************************** + * + * FeeRandom.h - generic, portable random number generator object + * + * Revision History + * ---------------- + * 8/25/98 ap + * Fixed previous check-in comment. + * 8/24/98 ap + * Added tags around #endif comment. + * 23 Aug 96 Doug Mitchell at NeXT + * Created. + */ + +#ifndef _CK_FEERANDOM_H_ +#define _CK_FEERANDOM_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void *feeRand; + +feeRand feeRandAllocWithSeed(unsigned seed); +feeRand feeRandAlloc(void); + +void feeRandFree(feeRand frand); + +unsigned feeRandNextNum(feeRand frand); + +void feeRandBytes(feeRand frand, + unsigned char *bytes, /* must be alloc'd by caller */ + unsigned numBytes); + +void feeRandAddEntropy(feeRand frand, unsigned entropy); + +#ifdef __cplusplus +} +#endif + +#endif /* _CK_FEERANDOM_H_ */ diff --git a/libsecurity_cryptkit/lib/feeTypes.h b/libsecurity_cryptkit/lib/feeTypes.h new file mode 100644 index 00000000..a10f4db1 --- /dev/null +++ b/libsecurity_cryptkit/lib/feeTypes.h @@ -0,0 +1,168 @@ +/* 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. + *************************************************************************** + * + * feeTypes.h - general purpose FEE typedefs and constants + * + * Revision History + * ---------------- + * 23 Mar 98 Doug Mitchell at Apple + * Added FR_BadKeyBlob. + * 20 Jan 98 Doug Mitchell at Apple + * New PT_GENERAL depth values. + * 09 Jan 98 Doug Mitchell at Apple + * Removed obsolete FEE_DEPTH_* values. + * 20 Aug 96 Doug Mitchell at NeXT + * Created. + */ + +#ifndef _CK_FEETYPES_H_ +#define _CK_FEETYPES_H_ + +/* + * Opaque public key object. + */ +typedef void *feePubKey; + +/* + * Standard return codes. + * Remember to update frtnStrings[] in utilities.c when adding new items. + */ +typedef enum { + FR_Success = 0, + FR_BadPubKey, + FR_BadPubKeyString, + FR_IncompatibleKey, /* incompatible key */ + FR_IllegalDepth, + FR_BadUsageName, /* bad usageName */ + FR_BadSignatureFormat, /* signature corrupted */ + FR_InvalidSignature, /* signature intact, but not valid */ + FR_IllegalArg, /* illegal argument */ + FR_BadCipherText, /* malformed ciphertext */ + FR_Unimplemented, /* unimplemented function */ + FR_BadCipherFile, + FR_BadEnc64, /* bad enc64() format */ + FR_WrongSignatureType, /* ElGamal vs. ECDSA */ + FR_BadKeyBlob, + FR_IllegalCurve, /* e.g., ECDSA with Montgomery curve */ + FR_Internal, /* internal library error */ + FR_Memory, /* out of memory */ + FR_ShortPrivData /* insufficient privData for creating + * private key */ + /* etc. */ +} feeReturn; + +/* + * The feeDepth parameter defines one of 'n' known curves. From a user's + * perspective, the most interesting parameter indicated by feeDepth is + * the size (in bits) of the key. + */ +typedef unsigned feeDepth; + +/* + * Prime and curve description parameters. + */ +typedef enum { + FPT_Default, /* default per key size */ + FPT_Mersenne, /* (2 ** q) - 1 */ + FPT_FEE, /* (2 ** q) - k */ + FPT_General /* random prime */ +} feePrimeType; + +typedef enum { + FCT_Default, /* default per key size */ + FCT_Montgomery, /* a==1, b==0 */ + FCT_Weierstrass, /* c==0. IEEE P1363 compliant. */ + FCT_ANSI, /* ANSI X9.62/Certicom, also FCT_Weierstrass */ + FCT_General /* Other */ +} feeCurveType; + +/* + * Some commonly used feeDepth values. In these definitions, q and k are + * from the expression (2^q - k), the base modulus of the curve. The case + * k=1 implies a Mersenne prime as the modulus. + */ +#define FEE_PROTOTYPE_CURVES 0 + +#if FEE_PROTOTYPE_CURVES + + /* q k a b c */ + /* ---- ---- ---- ---- ---- */ +#define FEE_DEPTH_31_1_W 0 /* 31 1 7 1 0 */ +#define FEE_DEPTH_31_1_M 1 /* 31 1 1 0 666 */ +#define FEE_DEPTH_31_1_P 2 /* 31 1 5824692 2067311435 0 */ +#define FEE_DEPTH_40_213 3 /* 40 213 1627500953 523907505 0 */ +#define FEE_DEPTH_127_1 4 /* 127 1 1 0 666 */ +#define FEE_DEPTH_127_1W 5 /* 127 1 666 1 0 */ +#define FEE_DEPTH_160_57 6 /* 160 57 0 3 0 */ +#define FEE_DEPTH_192_1425 7 /* 192 1425 0 -11 0 */ +#define FEE_DEPTH_192_M529891 8 /* 192 -529891 -152 722 0 */ + +/* + * The remaining curves are implemented as PT_GENERAL curves; modulo + * arithmetic does not utilize any FEE or Mersenne optimizations. These + * are here for performance measurements and DVT. + */ +#define FEE_DEPTH_127_GEN 9 /* 127 1 1 0 666 */ +#define FEE_DEPTH_160_GEN 10 /* 160 57 0 3 0 */ +#define FEE_DEPTH_161_GEN 11 /* 161 .. -152 722 0 */ + +/* + * The default depth. + */ +#define FEE_DEPTH_DEFAULT FEE_DEPTH_160_57 + +/* + * Last enumerated depth. + */ +#define FEE_DEPTH_MAX FEE_DEPTH_161_GEN + +#else /* FEE_PROTOTYPE_CURVES */ + +/* + * The real curves as of 4/9/2001. + * Note that ECDSA signatures can only be performed with curve of + * curveType FCT_Weierstrass. + * + * Default curveType for curves with same prime size is FCT_Weierstrass. + */ +#define FEE_DEPTH_31M 0 /* size=31 FPT_Mersenne FCT_Montgomery */ +#define FEE_DEPTH_31W 1 /* size=31 FPT_Mersenne FCT_Weierstrass */ +#define FEE_DEPTH_127M 2 /* size=127 FPT_Mersenne FCT_Montgomery */ +#define FEE_DEPTH_128W 3 /* size=128 FPT_FEE FCT_Weierstrass */ +#define FEE_DEPTH_161W 4 /* size=161 FPT_FEE FCT_Weierstrass */ +#define FEE_DEPTH_161G 5 /* size=161 FPT_General FCT_Weierstrass */ +#define FEE_DEPTH_192G 6 /* size=192 FPT_General FCT_Weierstrass */ + +/* ANSI X9.62/Certicom curves */ +#define FEE_DEPTH_secp192r1 7 /* size=192 FPT_General FCT_ANSI */ +#define FEE_DEPTH_secp256r1 8 /* size=256 FPT_General FCT_ANSI */ +#define FEE_DEPTH_secp384r1 9 /* size=384 FPT_General FCT_ANSI */ +#define FEE_DEPTH_secp521r1 10 /* size=521 FPT_General FCT_ANSI */ +/* + * The default depth. + */ +#define FEE_DEPTH_DEFAULT FEE_DEPTH_161W + +/* + * Last enumerated depth. + */ +#define FEE_DEPTH_MAX FEE_DEPTH_secp521r1 + +#endif /* FEE_PROTOTYPE_CURVES */ + +/* + * Random number generator callback function. + */ +typedef feeReturn (*feeRandFcn)( + void *ref, + unsigned char *bytes, /* must be alloc'd by caller */ + unsigned numBytes); + +#endif /* _CK_FEETYPES_H_ */ diff --git a/libsecurity_cryptkit/lib/giantFFT.c b/libsecurity_cryptkit/lib/giantFFT.c new file mode 100644 index 00000000..411a6d19 --- /dev/null +++ b/libsecurity_cryptkit/lib/giantFFT.c @@ -0,0 +1,520 @@ +/* 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. + *************************************************************************** + + giantFFT.c + 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 + Split off from NSGiantIntegers.c. + +*/ + +/* + * FIXME - make sure platform-specific math lib has floor(), fmod(), + * sin(), pow() + */ +#include +#include "NSGiantIntegers.h" + +#define AUTO_MUL 0 +#define GRAMMAR_MUL 1 +#define FFT_MUL 2 + +#define TWOPI (double)(2*3.1415926535897932384626433) +#define SQRT2 (double)(1.414213562373095048801688724209) +#define SQRTHALF (double)(0.707106781186547524400844362104) +#define TWO16 (double)(65536.0) +#define TWOM16 (double)(0.0000152587890625) +#define BREAK_SHORTS 400 // Number of shorts at which FFT breaks over. + +static int lpt(int n, int *lambda); +static void mul_hermitian(double *a, double *b, int n) ; +static void square_hermitian(double *b, int n); +static void addsignal(giant x, double *zs, int n); +static void scramble_real(double *x, int n); +static void fft_real_to_hermitian(double *zs, int n); +static void fftinv_hermitian_to_real(double *zs, int n); +static void GiantFFTSquare(giant gx); +static void GiantFFTMul(giant,giant); +static void giant_to_double(giant x, int sizex, double *zs, int L); + +static int mulmode = AUTO_MUL; + +void mulg(giant a, giant b) { /* b becomes a*b. */ + PROF_START; + INCR_MULGS; + GiantAuxMul(a,b); + #if FEE_DEBUG + (void)bitlen(b); // XXX + #endif FEE_DEBUG + PROF_END(mulgTime); + PROF_INCR(numMulg); +} + +static void GiantAuxMul(giant a, giant b) { +/* Optimized general multiply, b becomes a*b. Modes are: + AUTO_MUL: switch according to empirical speed criteria. + GRAMMAR_MUL: force grammar-school algorithm. + FFT_MUL: force floating point FFT method. +*/ + int square = (a==b); + + if (isZero(b)) return; + if (isZero(a)) { + gtog(a, b); + return; + } + switch(mulmode) { + case GRAMMAR_MUL: + GiantGrammarMul(a,b); + break; + case FFT_MUL: + if (square) { + GiantFFTSquare(b); + } + else { + GiantFFTMul(a,b); + } + break; + case AUTO_MUL: { + int sizea, sizeb; + float grammartime; + sizea = abs(a->sign); + sizeb = abs(b->sign); + grammartime = sizea; grammartime *= sizeb; + if(grammartime < BREAK_SHORTS*BREAK_SHORTS) { + GiantGrammarMul(a,b); + } + else { + if (square) GiantFFTSquare(b); + else GiantFFTMul(a,b); + } + break; + } + } +} + +/***************** Commence FFT multiply routines ****************/ + +static int CurrentRun = 0; +double *sincos = NULL; +static void init_sincos(int n) { + int j; + double e = TWOPI/n; + + if (n <= CurrentRun) return; + CurrentRun = n; + if (sincos) free(sincos); + sincos = (double *)malloc(sizeof(double)*(1+(n>>2))); + for(j=0;j<=(n>>2);j++) { + sincos[j] = sin(e*j); + } +} + +static double s_sin(int n) { + int seg = n/(CurrentRun>>2); + + switch(seg) { + case 0: return(sincos[n]); + case 1: return(sincos[(CurrentRun>>1)-n]); + case 2: return(-sincos[n-(CurrentRun>>1)]); + case 3: + default: return(-sincos[CurrentRun-n]); + } +} + +static double s_cos(int n) { + int quart = (CurrentRun>>2); + + if (n < quart) return(s_sin(n+quart)); + return(-s_sin(n-quart)); +} + + +static int lpt(int n, int *lambda) { +/* returns least power of two greater than n */ + register int i = 1; + + *lambda = 0; + while(imaxerr) maxerr = err; + */ + + zs[j] =0; + k = 0; + do{ + g = floor(f*TWOM16); + zs[j+k] += f-g*TWO16; + ++k; + f=g; + } while(f != 0.0); + } + car = 0; + for(j=0;jn[j] = m & 0xffff; + car = (m>>16); + } + if(car) x->n[j] = car; + else --j; + while(!(x->n[j])) --j; + x->sign = j+1; + if (abs(x->sign) > x->capacity) NSGiantRaise("addsignal overflow"); +} + +static void GiantFFTSquare(giant gx) { + int j,size = abs(gx->sign); + register int L; + + if(size<4) { GiantGrammarMul(gx,gx); return; } + L = lpt(size+size, &j); + { + //was...double doubles[L]; + //is... + double *doubles = malloc(sizeof(double) * L); + // end + giant_to_double(gx, size, doubles, L); + fft_real_to_hermitian(doubles, L); + square_hermitian(doubles, L); + fftinv_hermitian_to_real(doubles, L); + addsignal(gx, doubles, L); + // new + free(doubles); + } + gx->sign = abs(gx->sign); + bitlen(gx); // XXX + if (abs(gx->sign) > gx->capacity) NSGiantRaise("GiantFFTSquare overflow"); +} + +static void GiantFFTMul(giant y, giant x) { /* x becomes y*x. */ + int lambda, size, sizex = abs(x->sign), sizey = abs(y->sign); + int finalsign = gsign(x)*gsign(y); + register int L; + + if((sizex<=4)||(sizey<=4)) { GiantGrammarMul(y,x); return; } + size = sizex; if(sizesign = finalsign*abs(x->sign); + bitlen(x); // XXX + if (abs(x->sign) > x->capacity) NSGiantRaise("GiantFFTMul overflow"); +} + +static void scramble_real(double *x, int n) { + register int i,j,k; + register double tmp; + + for(i=0,j=0;i>=1; + } + j += k; + } +} + +static void fft_real_to_hermitian(double *zs, int n) { +/* Output is {Re(z^[0]),...,Re(z^[n/2),Im(z^[n/2-1]),...,Im(z^[1]). + This is a decimation-in-time, split-radix algorithm. + */ + register double cc1, ss1, cc3, ss3; + register int is, iD, i0, i1, i2, i3, i4, i5, i6, i7, i8, + a, a3, b, b3, nminus = n-1, dil, expand; + register double *x, e; + int nn = n>>1; + double t1, t2, t3, t4, t5, t6; + register int n2, n4, n8, i, j; + + init_sincos(n); + expand = CurrentRun/n; + scramble_real(zs, n); + x = zs-1; /* FORTRAN compatibility. */ + is = 1; + iD = 4; + do{ + for(i0=is;i0<=n;i0+=iD) { + i1 = i0+1; + e = x[i0]; + x[i0] = e + x[i1]; + x[i1] = e - x[i1]; + } + is = (iD<<1)-1; + iD <<= 2; + } while(is>=1) { + n2 <<= 1; + n4 = n2>>2; + n8 = n2>>3; + is = 0; + iD = n2<<1; + do { + for(i=is;i>1; + double t1, t2, t3, t4, t5; + int n2, n4, n8, i, j; + + init_sincos(n); + expand = CurrentRun/n; + x = zs-1; + n2 = n<<1; + while(nn >>= 1) { + is = 0; + iD = n2; + n2 >>= 1; + n4 = n2>>2; + n8 = n4>>1; + do { + for(i=is;i>1; + register double aa, bb, am, bm; + + b[0] *= a[0]; + b[half] *= a[half]; + for(k=1;k>1; + register double c, d; + + b[0] *= b[0]; + b[half] *= b[half]; + for(k=1;kn[j]; + } +} diff --git a/libsecurity_cryptkit/lib/giantIntegers.c b/libsecurity_cryptkit/lib/giantIntegers.c new file mode 100644 index 00000000..087323a3 --- /dev/null +++ b/libsecurity_cryptkit/lib/giantIntegers.c @@ -0,0 +1,1748 @@ +/* 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. + *************************************************************************** + + giantIntegers.c - library for large-integer arithmetic. + + 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 + 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 + Deleted FFT arithmetic; simplified mulg(). + 09 Jan 98 Doug Mitchell and Richard Crandall at Apple + gshiftright() optimization. + 08 Jan 98 Doug Mitchell at Apple + newGiant() returns NULL on malloc failure + 24 Dec 97 Doug Mitchell and Richard Crandall at Apple + New grammarSquare(); optimized modg_via_recip() + 11 Jun 97 Doug Mitchell and Richard Crandall at Apple + Added modg_via_recip(), divg_via_recip(), make_recip() + Added new multiple giant stack mechanism + Fixed potential packing/alignment bug in copyGiant() + Added profiling for borrowGiant(), returnGiant() + Deleted obsolete ifdef'd code + Deleted newgiant() + All calls to borrowGiant() now specify required size (no more + borrowGiant(0) calls) + 08 May 97 Doug Mitchell at Apple + Changed size of giantstruct.n to 1 for Mac build + 05 Feb 97 Doug Mitchell at Apple + newGiant() no longer modifies CurrentMaxShorts or giant stack + Added modg profiling + 01 Feb 97 Doug Mitchell at NeXT + Added iszero() check in gcompg + 17 Jan 97 Richard Crandall, Doug Mitchell 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 + Fixed --size underflow bug in normal_subg(). + 4 Sep 96 Doug Mitchell at NeXT + Fixed (b +#include +#include +#include "platform.h" +#include "giantIntegers.h" +#include "feeDebug.h" +#include "ckconfig.h" +#include "ellipticMeasure.h" +#include "falloc.h" +#include "giantPortCommon.h" + +#ifdef FEE_DEBUG +#if (GIANT_LOG2_BITS_PER_DIGIT == 4) +#warning Compiling with two-byte giantDigits +#endif +#endif + + +#if FEE_DEBUG +char printbuf1[200]; +char printbuf2[200]; +char printbuf3[200]; +void printGiantBuf(giant x) +{ + int i; + + sprintf(printbuf2, "sign=%d cap=%d n[]=", x->sign, x->capacity); + for(i=0; isign); i++) { + sprintf(printbuf3 + 10*i, "%u:", x->n[i]); + } +} + +char printbuf4[200]; +char printbuf5[200]; +void printGiantBuf2(giant x) +{ + int i; + + sprintf(printbuf4, "sign=%d cap=%d n[]=", x->sign, x->capacity); + for(i=0; isign); i++) { + sprintf(printbuf5 + 10*i, "%u:", x->n[i]); + } +} +#endif /* FEE_DEBUG */ + +/******** debugging flags *********/ + +/* + * Flag use of unoptimized divg, modg, binvg + */ +//#define WARN_UNOPTIMIZE FEE_DEBUG +#define WARN_UNOPTIMIZE 0 + +/* + * Log interesting giant stack events + */ +#define LOG_GIANT_STACK 0 + +/* + * Log allocation of giant larger than stack size + */ +#define LOG_GIANT_STACK_OVERFLOW 1 + +/* + * Flag newGiant(0) and borrowGiant(0) calls + */ +#define WARN_ZERO_GIANT_SIZE FEE_DEBUG + +/* temp mac-only giant initialization debug */ +#define GIANT_MAC_DEBUG 0 +#if GIANT_MAC_DEBUG + +#include +#include +#include + +/* this one needs a writable string */ +static void logCom(unsigned char *str) { + c2pstr((char *)str); + DebugStr(str); +} + +/* constant strings */ +void dblog0(const char *str) { + Str255 outStr; + strcpy((char *)outStr, str); + logCom(outStr); +} + +#else +#define dblog0(s) + +#endif /* GIANT_MAC_DEBUG */ + +#ifndef min +#define min(a,b) ((a)<(b)? (a) : (b)) +#endif // min +#ifndef max +#define max(a,b) ((a)>(b)? (a) : (b)) +#endif // max + +#ifndef TRUE +#define TRUE 1 +#endif // TRUE +#ifndef FALSE +#define FALSE 0 +#endif // FALSE + +static void absg(giant g); /* g := |g|. */ + +/************** globals *******************/ + + +/* ------ giant stack package ------ */ + +/* + * The giant stack package is a local cache which allows us to avoid calls + * to malloc() for borrowGiant(). On a 90 Mhz Pentium, enabling the + * giant stack package shows about a 1.35 speedup factor over an identical + * CryptKit without the giant stacks enabled. + */ + +#if GIANTS_VIA_STACK + +#if LOG_GIANT_STACK +#define gstackDbg(x) printf x +#else // LOG_GIANT_STACK +#define gstackDbg(x) +#endif // LOG_GIANT_STACK + +typedef struct { + unsigned numDigits; // capacity of giants in this stack + unsigned numFree; // number of free giants in stack + unsigned totalGiants; // total number in *stack + giant *stack; +} gstack; + +static gstack *gstacks = NULL; // array of stacks +static unsigned numGstacks = 0; // # of elements in gstacks +static int gstackInitd = 0; // this module has been init'd + +#define INIT_NUM_GIANTS 16 /* initial # of giants / stack */ +#define MIN_GIANT_SIZE 4 /* numDigits for gstack[0] */ +#define GIANT_SIZE_INCR 2 /* in << bits */ + +/* + * Initialize giant stacks, with up to specified max giant size. + */ +void initGiantStacks(unsigned maxDigits) +{ + unsigned curSize = MIN_GIANT_SIZE; + unsigned sz; + unsigned i; + + dblog0("initGiantStacks\n"); + + if(gstackInitd) { + /* + * Shouldn't be called more than once... + */ + printf("multiple initGiantStacks calls\n"); + return; + } + gstackDbg(("initGiantStacks(%d)\n", maxDigits)); + + /* + * How many stacks? + */ + numGstacks = 1; + while(curSize<=maxDigits) { + curSize <<= GIANT_SIZE_INCR; + numGstacks++; + } + + sz = sizeof(gstack) * numGstacks; + gstacks = (gstack*) fmalloc(sz); + bzero(gstacks, sz); + + curSize = MIN_GIANT_SIZE; + for(i=0; inumFree; j++) { + freeGiant(gs->stack[j]); + gs->stack[j] = NULL; + } + /* and the stack itself - may be null if this was never used */ + if(gs->stack != NULL) { + ffree(gs->stack); + gs->stack = NULL; + } + } + ffree(gstacks); + gstacks = NULL; + gstackInitd = 0; +} + +#endif // GIANTS_VIA_STACK + +giant borrowGiant(unsigned numDigits) +{ + giant result; + + #if GIANTS_VIA_STACK + + unsigned stackNum; + gstack *gs = gstacks; + + #if WARN_ZERO_GIANT_SIZE + if(numDigits == 0) { + printf("borrowGiant(0)\n"); + numDigits = gstacks[numGstacks-1].numDigits; + } + #endif // WARN_ZERO_GIANT_SIZE + + /* + * Find appropriate stack + */ + if(numDigits <= MIN_GIANT_SIZE) + stackNum = 0; + else if (numDigits <= (MIN_GIANT_SIZE << GIANT_SIZE_INCR)) + stackNum = 1; + else if (numDigits <= (MIN_GIANT_SIZE << (2 * GIANT_SIZE_INCR))) + stackNum = 2; + else if (numDigits <= (MIN_GIANT_SIZE << (3 * GIANT_SIZE_INCR))) + stackNum = 3; + else if (numDigits <= (MIN_GIANT_SIZE << (4 * GIANT_SIZE_INCR))) + stackNum = 4; + else + stackNum = numGstacks; + + if(stackNum >= numGstacks) { + /* + * out of bounds; just malloc + */ + #if LOG_GIANT_STACK_OVERFLOW + gstackDbg(("giantFromStack overflow; numDigits %d\n", + numDigits)); + #endif // LOG_GIANT_STACK_OVERFLOW + return newGiant(numDigits); + } + gs = &gstacks[stackNum]; + + #if GIANT_MAC_DEBUG + if((gs->numFree != 0) && (gs->stack == NULL)) { + dblog0("borrowGiant: null stack!\n"); + } + #endif + + if(gs->numFree != 0) { + result = gs->stack[--gs->numFree]; + } + else { + /* + * Stack empty; malloc + */ + result = newGiant(gs->numDigits); + } + + #else /* GIANTS_VIA_STACK */ + + result = newGiant(numDigits); + + #endif /* GIANTS_VIA_STACK */ + + PROF_INCR(numBorrows); + return result; +} + +void returnGiant(giant g) +{ + + #if GIANTS_VIA_STACK + + unsigned stackNum; + gstack *gs; + unsigned cap = g->capacity; + + + #if FEE_DEBUG + if(!gstackInitd) { + CKRaise("returnGiant before stacks initialized!"); + } + #endif // FEE_DEBUG + + #if GIANT_MAC_DEBUG + if(g == NULL) { + dblog0("returnGiant: null g!\n"); + } + #endif + + /* + * Find appropriate stack. Note we expect exact match of + * capacity and stack's giant size. + */ + /* + * Optimized unrolled loop. Just make sure there are enough cases + * to handle all of the stacks. Errors in this case will be flagged + * via LOG_GIANT_STACK_OVERFLOW. + */ + switch(cap) { + case MIN_GIANT_SIZE: + stackNum = 0; + break; + case MIN_GIANT_SIZE << GIANT_SIZE_INCR: + stackNum = 1; + break; + case MIN_GIANT_SIZE << (2 * GIANT_SIZE_INCR): + stackNum = 2; + break; + case MIN_GIANT_SIZE << (3 * GIANT_SIZE_INCR): + stackNum = 3; + break; + case MIN_GIANT_SIZE << (4 * GIANT_SIZE_INCR): + stackNum = 4; + break; + default: + stackNum = numGstacks; + break; + } + + if(stackNum >= numGstacks) { + /* + * out of bounds; just free + */ + #if LOG_GIANT_STACK_OVERFLOW + gstackDbg(("giantToStack overflow; numDigits %d\n", cap)); + #endif // LOG_GIANT_STACK_OVERFLOW + freeGiant(g); + return; + } + gs = &gstacks[stackNum]; + if(gs->numFree == gs->totalGiants) { + if(gs->totalGiants == 0) { + gstackDbg(("Initial alloc of gstack(%d)\n", + gs->numDigits)); + gs->totalGiants = INIT_NUM_GIANTS; + } + else { + gs->totalGiants *= 2; + gstackDbg(("Bumping gstack(%d) to %d\n", + gs->numDigits, gs->totalGiants)); + } + gs->stack = (giantstruct**) frealloc(gs->stack, gs->totalGiants*sizeof(giant)); + } + g->sign = 0; // not sure this is important... + gs->stack[gs->numFree++] = g; + + #if GIANT_MAC_DEBUG + if((gs->numFree != 0) && (gs->stack == NULL)) { + dblog0("borrowGiant: null stack!\n"); + } + #endif + + #else /* GIANTS_VIA_STACK */ + + freeGiant(g); + + #endif /* GIANTS_VIA_STACK */ +} + +void freeGiant(giant x) { + ffree(x); +} + +giant newGiant(unsigned numDigits) { + // giant sufficient for 2^numbits+16 sized ops + int size; + giant result; + + #if WARN_ZERO_GIANT_SIZE + if(numDigits == 0) { + printf("newGiant(0)\n"); + #if GIANTS_VIA_STACK + numDigits = gstacks[numGstacks-1].totalGiants; + #else + /* HACK */ + numDigits = 20; + #endif + } + #endif // WARN_ZERO_GIANT_SIZE + + size = (numDigits-1) * GIANT_BYTES_PER_DIGIT + sizeof(giantstruct); + result = (giant)fmalloc(size); + if(result == NULL) { + return NULL; + } + result->sign = 0; + result->capacity = numDigits; + return result; +} + +giant copyGiant(giant x) +{ + int bytes; + + giant result = newGiant(x->capacity); + + /* + * 13 Jun 1997 + * NO! this assumes packed alignment + */ + bytes = sizeof(giantstruct) + + ((x->capacity - 1) * GIANT_BYTES_PER_DIGIT); + bcopy(x, result, bytes); + return result; +} + +/* ------ initialization and utility routines ------ */ + + +unsigned bitlen(giant n) { + unsigned b = GIANT_BITS_PER_DIGIT; + giantDigit c = 1 << (GIANT_BITS_PER_DIGIT - 1); + giantDigit w; + + if (isZero(n)) { + return(0); + } + w = n->n[abs(n->sign) - 1]; + if (!w) { + CKRaise("bitlen - no bit set!"); + } + while((w&c) == 0) { + b--; + c >>= 1; + } + return(GIANT_BITS_PER_DIGIT * (abs(n->sign)-1) + b); +} + +int bitval(giant n, int pos) { + int i = abs(pos) >> GIANT_LOG2_BITS_PER_DIGIT; + giantDigit c = 1 << (pos & (GIANT_BITS_PER_DIGIT - 1)); + + return((n->n[i]) & c); +} + +int gsign(giant g) +/* returns the sign of g */ +{ + if (isZero(g)) return(0); + if (g->sign > 0) return(1); + return(-1); +} + +/* + * Adjust sign for possible leading (m.s.) zero digits + */ +void gtrimSign(giant g) +{ + int numDigits = abs(g->sign); + int i; + + for(i=numDigits-1; i>=0; i--) { + if(g->n[i] == 0) { + numDigits--; + } + else { + break; + } + } + if(g->sign < 0) { + g->sign = -numDigits; + } + else { + g->sign = numDigits; + } +} + + +int isone(giant g) { + return((g->sign==1)&&(g->n[0]==1)); +} + +int isZero(giant thegiant) { +/* Returns TRUE if thegiant == 0. */ + int count; + int length = abs(thegiant->sign); + giantDigit *numpointer; + + if (length) { + numpointer = thegiant->n; + + for(count = 0; countb, respectively */ +{ + int sa = a->sign; + int j; + int sb = b->sign; + giantDigit va; + giantDigit vb; + int sgn; + + if(isZero(a) && isZero(b)) return 0; + if(sa > sb) return(1); + if(sa < sb) return(-1); + if(sa < 0) { + sa = -sa; /* Take absolute value of sa */ + sgn = -1; + } else sgn = 1; + for(j = sa-1; j >= 0; j--) { + va = a->n[j]; vb = b->n[j]; + if (va > vb) return(sgn); + if (va < vb) return(-sgn); + } + return(0); +} + +/* destgiant becomes equal to srcgiant */ +void gtog(giant srcgiant, giant destgiant) { + + int numbytes; + + CKASSERT(srcgiant != NULL); + numbytes = abs(srcgiant->sign) * GIANT_BYTES_PER_DIGIT; + if (destgiant->capacity < abs(srcgiant->sign)) + CKRaise("gtog overflow!!"); + memcpy((char *)destgiant->n, (char *)srcgiant->n, numbytes); + destgiant->sign = srcgiant->sign; +} + +void int_to_giant(int i, giant g) { +/* The giant g becomes set to the integer value i. */ + int isneg = (i<0); + unsigned int j = abs(i); + unsigned dex; + + g->sign = 0; + if (i==0) { + g->n[0] = 0; + return; + } + + if(GIANT_BYTES_PER_DIGIT == sizeof(int)) { + g->n[0] = j; + g->sign = 1; + } + else { + /* one loop per digit */ + unsigned scnt = GIANT_BITS_PER_DIGIT; // fool compiler + + for(dex=0; dexn[dex] = j & GIANT_DIGIT_MASK; + j >>= scnt; + g->sign++; + if(j == 0) { + break; + } + } + } + if (isneg) { + g->sign = -(g->sign); + } +} + +/*------------- Arithmetic --------------*/ + +void negg(giant g) { +/* g becomes -g */ + g->sign = -g->sign; +} + +void iaddg(int i, giant g) { /* positive g becomes g + (int)i */ + int j; + giantDigit carry; + int size = abs(g->sign); + + if (isZero(g)) { + int_to_giant(i,g); + } + else { + carry = i; + for(j=0; ((jn[j] = giantAddDigits(g->n[j], carry, &carry); + } + if(carry) { + ++g->sign; + // realloc + if (g->sign > (int)g->capacity) CKRaise("iaddg overflow!"); + g->n[size] = carry; + } + } +} + +/* + * g *= (int n) + * + * FIXME - we can improve this... + */ +void imulg(unsigned n, giant g) +{ + giant tmp = borrowGiant(abs(g->sign) + sizeof(int)); + + int_to_giant(n, tmp); + mulg(tmp, g); + returnGiant(tmp); +} + +/* new addg, negg, and gcompg from Crandall 6/95 */ +static void normal_addg(giant a, giant b) +/* b := a + b, both a,b assumed non-negative. */ +{ + giantDigit carry1 = 0; + giantDigit carry2 = 0; + int asize = a->sign, bsize = b->sign; + giantDigit *an = a->n; + giantDigit *bn = b->n; + giantDigit tmp; + int j; + int comSize; + int maxSize; + + if(asize < bsize) { + comSize = asize; + maxSize = bsize; + } + else { + comSize = bsize; + maxSize = asize; + } + + /* first handle the common digits */ + for(j=0; jsign = maxSize; + if(carry1) { + // realloc? + bn[j] = 1; + b->sign++; + if (b->sign > (int)b->capacity) CKRaise("iaddg overflow!"); + } + +} + +static void normal_subg(giant a, giant b) +/* b := b - a; requires b, a non-negative and b >= a. */ +{ + int j; + int size = b->sign; + giantDigit tmp; + giantDigit borrow1 = 0; + giantDigit borrow2 = 0; + giantDigit *an = a->n; + giantDigit *bn = b->n; + + if(a->sign == 0) { + return; + } + + for (j=0; jsign; ++j) { + if(borrow1 || borrow2) { + tmp = giantSubDigits(bn[j], (giantDigit)1, &borrow1); + } + else { + tmp = bn[j]; + borrow1 = 0; + } + bn[j] = giantSubDigits(tmp, an[j], &borrow2); + } + if(borrow1 || borrow2) { + /* propagate borrow thru remainder of bn[] */ + borrow1 = 1; + for (j=a->sign; j 0) && (b->n[size] == 0)) + ; + b->sign = (b->n[size] == 0)? 0 : size+1; +} + +static void reverse_subg(giant a, giant b) +/* b := a - b; requires b, a non-negative and a >= b. */ +{ + int j; + int size = a->sign; + giantDigit tmp; + giantDigit borrow1 = 0; + giantDigit borrow2 = 0; + giantDigit *an = a->n; + giantDigit *bn = b->n; + + if(b->sign == 0) { + gtog(a, b); + return; + } + for (j=0; jsign; ++j) { + if(borrow1 || borrow2) { + tmp = giantSubDigits(an[j], (giantDigit)1, &borrow1); + } + else { + tmp = an[j]; + borrow1 = 0; + } + bn[j] = giantSubDigits(tmp, bn[j], &borrow2); + } + if(borrow1 || borrow2) { + /* propagate borrow thru remainder of bn[] */ + borrow1 = 1; + } + for (j=b->sign; jsign = size; /* REC, 21 Apr 1996. */ + while(!b->n[--size]); + b->sign = size+1; +} + + +void addg(giant a, giant b) +/* b := b + a, any signs any result. */ +{ int asgn = a->sign, bsgn = b->sign; + if(asgn == 0) return; + if(bsgn == 0) { + gtog(a,b); + return; + } + if((asgn < 0) == (bsgn < 0)) { + if(bsgn > 0) { + normal_addg(a,b); + return; + } + negg(a); if(a != b) negg(b); normal_addg(a,b); /* Fix REC 1 Dec 98. */ + negg(a); if(a != b) negg(b); return; /* Fix REC 1 Dec 98. */ + } + if(bsgn > 0) { + negg(a); + if(gcompg(b,a) >= 0) { + normal_subg(a,b); + negg(a); + return; + } + reverse_subg(a,b); + negg(a); + negg(b); + return; + } + negg(b); + if(gcompg(b,a) < 0) { + reverse_subg(a,b); + return; + } + normal_subg(a,b); + negg(b); + return; +} + +void subg(giant a, giant b) +/* b := b - a, any signs, any result. */ +{ + int asgn = a->sign, bsgn = b->sign; + if(asgn == 0) return; + if(bsgn == 0) { + gtog(a,b); + negg(b); + return; + } + if((asgn < 0) != (bsgn < 0)) { + if(bsgn > 0) { + negg(a); + normal_addg(a,b); + negg(a); + return; + } + negg(b); + normal_addg(a,b); + negg(b); + return; + } + if(bsgn > 0) { + if(gcompg(b,a) >= 0) { + normal_subg(a,b); + return; + } + reverse_subg(a,b); + negg(b); + return; + } + negg(a); negg(b); + if(gcompg(b,a) >= 0) { + normal_subg(a,b); + negg(a); + negg(b); + return; + } + reverse_subg(a,b); + negg(a); + return; +} + +static void bdivg(giant v, giant u) +/* u becomes greatest power of two not exceeding u/v. */ +{ + int diff = bitlen(u) - bitlen(v); + giant scratch7; + + if (diff<0) { + int_to_giant(0,u); + return; + } + scratch7 = borrowGiant(u->capacity); + gtog(v, scratch7); + gshiftleft(diff,scratch7); + if(gcompg(u,scratch7) < 0) diff--; + if(diff<0) { + int_to_giant(0,u); + returnGiant(scratch7); + return; + } + int_to_giant(1,u); + gshiftleft(diff,u); + returnGiant(scratch7); +} + +int binvaux(giant p, giant x) +/* Binary inverse method. + Returns zero if no inverse exists, in which case x becomes + GCD(x,p). */ +{ + giant scratch7; + giant u0; + giant u1; + giant v0; + giant v1; + int result = 1; + int giantSize; + PROF_START; + + if(isone(x)) return(result); + giantSize = 4 * abs(p->sign); + scratch7 = borrowGiant(giantSize); + u0 = borrowGiant(giantSize); + u1 = borrowGiant(giantSize); + v0 = borrowGiant(giantSize); + v1 = borrowGiant(giantSize); + int_to_giant(1, v0); gtog(x, v1); + int_to_giant(0,x); gtog(p, u1); + while(!isZero(v1)) { + gtog(u1, u0); bdivg(v1, u0); + gtog(x, scratch7); + gtog(v0, x); + mulg(u0, v0); + subg(v0,scratch7); + gtog(scratch7, v0); + + gtog(u1, scratch7); + gtog(v1, u1); + mulg(u0, v1); + subg(v1,scratch7); + gtog(scratch7, v1); + } + if (!isone(u1)) { + gtog(u1,x); + if(x->sign<0) addg(p, x); + result = 0; + goto done; + } + if (x->sign<0) addg(p, x); + done: + returnGiant(scratch7); + returnGiant(u0); + returnGiant(u1); + returnGiant(v0); + returnGiant(v1); + PROF_END(binvauxTime); + return(result); +} + +/* + * Superceded by binvg_cp() + */ +#if 0 +int binvg(giant p, giant x) +{ + modg(p, x); + return(binvaux(p,x)); +} +#endif + +static void absg(giant g) { +/* g becomes the absolute value of g */ + if (g->sign < 0) g->sign = -g->sign; +} + +void gshiftleft(int bits, giant g) { +/* shift g left bits bits. Equivalent to g = g*2^bits */ + int rem = bits & (GIANT_BITS_PER_DIGIT - 1); + int crem = GIANT_BITS_PER_DIGIT - rem; + int digits = 1 + (bits >> GIANT_LOG2_BITS_PER_DIGIT); + int size = abs(g->sign); + int j; + int k; + int sign = gsign(g); + giantDigit carry; + giantDigit dat; + + #if FEE_DEBUG + if(bits < 0) { + CKRaise("gshiftleft(-bits)\n"); + } + #endif /* FEE_DEBUG */ + + if(!bits) return; + if(!size) return; + if((size+digits) > (int)g->capacity) { + CKRaise("gshiftleft overflow"); + return; + } + k = size - 1 + digits; // (MSD of result + 1) + carry = 0; + + /* bug fix for 32-bit giantDigits; this is also an optimization for + * other sizes. rem=0 means we're shifting strictly by digits, no + * bit shifts. */ + if(rem == 0) { + g->n[k] = 0; // XXX hack - for sign fixup + for(j=size-1; j>=0; j--) { + g->n[--k] = g->n[j]; + } + do{ + g->n[--k] = 0; + } while(k>0); + } + else { + /* + * normal unaligned case + * FIXME - this writes past g->n[size-1] the first time thru! + */ + for(j=size-1; j>=0; j--) { + dat = g->n[j]; + g->n[k--] = (dat >> crem) | carry; + carry = (dat << rem); + } + do{ + g->n[k--] = carry; + carry = 0; + } while(k>=0); + } + k = size - 1 + digits; + if(g->n[k] == 0) --k; + g->sign = sign * (k+1); + if (abs(g->sign) > g->capacity) { + CKRaise("gshiftleft overflow"); + } +} + +void gshiftright(int bits, giant g) { +/* shift g right bits bits. Equivalent to g = g/2^bits */ + int j; + int size=abs(g->sign); + giantDigit carry; + int digits = bits >> GIANT_LOG2_BITS_PER_DIGIT; + int remain = bits & (GIANT_BITS_PER_DIGIT - 1); + int cremain = GIANT_BITS_PER_DIGIT - remain; + + #if FEE_DEBUG + if(bits < 0) { + CKRaise("gshiftright(-bits)\n"); + } + #endif /* FEE_DEBUG */ + if(bits==0) return; + if(isZero(g)) return; + if (digits >= size) { + g->sign = 0; + return; + } + + size -= digits; + +/* Begin OPT: 9 Jan 98 REC. */ + if(remain == 0) { + if(g->sign > 0) { + g->sign = size; + } + else { + g->sign = -size; + } + for(j=0; j < size; j++) { + g->n[j] = g->n[j+digits]; + } + return; + } +/* End OPT: 9 Jan 98 REC. */ + + for(j=0;jn[j+digits+1]) << cremain; + } + g->n[j] = ((g->n[j+digits]) >> remain ) | carry; + } + if (g->n[size-1] == 0) { + --size; + } + if(g->sign > 0) { + g->sign = size; + } + else { + g->sign = -size; + } + if (abs(g->sign) > g->capacity) { + CKRaise("gshiftright overflow"); + } +} + + +void extractbits(unsigned n, giant src, giant dest) { +/* dest becomes lowermost n bits of src. Equivalent to dest = src % 2^n */ + int digits = n >> GIANT_LOG2_BITS_PER_DIGIT; + int numbytes = digits * GIANT_BYTES_PER_DIGIT; + int bits = n & (GIANT_BITS_PER_DIGIT - 1); + + if (n <= 0) { + return; + } + if (dest->capacity * 8 * GIANT_BYTES_PER_DIGIT < n) { + CKRaise("extractbits - not enough room"); + } + if (digits >= abs(src->sign)) { + gtog(src,dest); + } + else { + memcpy((char *)(dest->n), (char *)(src->n), numbytes); + if (bits) { + dest->n[digits] = src->n[digits] & ((1<n[words-1] == 0) && (words > 0)) --words; + while((digits > 0) && (dest->n[digits-1] == 0)) { + --digits; + } + if(src->sign < 0) { + dest->sign = -digits; + } + else { + dest->sign = digits; + } + } + if (abs(dest->sign) > dest->capacity) { + CKRaise("extractbits overflow"); + } +} + +#define NEW_MERSENNE 0 + +/* + * New gmersennemod, 24 Dec 1997. This runs significantly slower than the + * original. + */ +#if NEW_MERSENNE + +void +gmersennemod( + int n, + giant g +) +/* g := g (mod 2^n - 1) */ +{ + int the_sign; + giant scratch3 = borrowGiant(g->capacity); + giant scratch4 = borrowGiant(1); + + if ((the_sign = gsign(g)) < 0) absg(g); + while (bitlen(g) > n) { + gtog(g,scratch3); + gshiftright(n,scratch3); + addg(scratch3,g); + gshiftleft(n,scratch3); + subg(scratch3,g); + } + if(isZero(g)) goto out; + int_to_giant(1,scratch3); + gshiftleft(n,scratch3); + int_to_giant(1,scratch4); + subg(scratch4,scratch3); + if(gcompg(g,scratch3) >= 0) subg(scratch3,g); + if (the_sign < 0) { + g->sign = -g->sign; + addg(scratch3,g); + } +out: + returnGiant(scratch3); + returnGiant(scratch4); +} + +#else /* NEW_MERSENNE */ + +void gmersennemod(int n, giant g) { +/* g becomes g mod ((2^n)-1) + 31 Jul 96 modified REC. + 17 Jan 97 modified REC. +*/ + unsigned bits = n & (GIANT_BITS_PER_DIGIT - 1); + unsigned digits = 1 + ((n-1) >> GIANT_LOG2_BITS_PER_DIGIT); + int isPositive = (g->sign > 0); + int j; + int b; + int size; + int foundzero; + giantDigit mask = (bits == 0) ? GIANT_DIGIT_MASK : (giantDigit)((1<> + GIANT_LOG2_BITS_PER_DIGIT; + giantDigit lastWord = 0; + giantDigit bits = 1; + + if(g->sign >= 0) return; + + /* + * Cons up ((2**n)-1), add to g. + */ + scratch1 = borrowGiant(numDigits + 1); + scratch1->sign = numDigits; + for(j=0; j<(int)(numDigits-1); j++) { + scratch1->n[j] = GIANT_DIGIT_MASK; + } + + /* + * Last word has lower (n & (GIANT_BITS_PER_DIGIT-1)) bits set. + */ + for(j=0; j < (int)(n & (GIANT_BITS_PER_DIGIT-1)); j++) { + lastWord |= bits; + bits <<= 1; + } + scratch1->n[numDigits-1] = lastWord; + addg(g, scratch1); /* One version. */ + gtog(scratch1, g); + returnGiant(scratch1); + return; + } + if(b == n) { + for(foundzero=0, j=0; jcapacity); + while ( ((unsigned)(g->sign) > digits) || + ( ((unsigned)(g->sign)==digits) && (g->n[digits-1] > mask))) { + extractbits(n, g, scratch1); + gshiftright(n, g); + addg(scratch1, g); + } + size = g->sign; + +/* Commence new negation routine - REC 17 Jan 1997. */ + if (!isPositive) { /* Mersenne negation is just bitwise complement. */ + for(j = digits-1; j >= size; j--) { + g->n[j] = GIANT_DIGIT_MASK; + } + for(j = size-1; j >= 0; j--) { + g->n[j] = ~g->n[j]; + } + g->n[digits-1] &= mask; + j = digits-1; + while((g->n[j] == 0) && (j > 0)) { + --j; + } + size = j+1; + } +/* End new negation routine. */ + + g->sign = size; + if (abs(g->sign) > g->capacity) { + CKRaise("gmersennemod overflow"); + } + if (size < (int)digits) { + goto bye; + } + if (g->n[size-1] != mask) { + goto bye; + } + mask = GIANT_DIGIT_MASK; + for(j=0; j<(size-1); j++) { + if (g->n[j] != mask) { + goto bye; + } + } + g->sign = 0; + bye: + returnGiant(scratch1); +} + +#endif /* NEW_MERSENNE */ + +void mulg(giant a, giant b) { /* b becomes a*b. */ + + int i; + int asize, bsize; + giantDigit *bptr = b->n; + giantDigit mult; + giant scratch1; + giantDigit carry; + giantDigit *scrPtr; + + + if (isZero(b)) { + return; + } + if (isZero(a)) { + gtog(a, b); + return; + } + if(a == b) { + grammarSquare(b); + return; + } + + bsize = abs(b->sign); + asize = abs(a->sign); + scratch1 = borrowGiant((asize+bsize)); + scrPtr = scratch1->n; + + for(i=0; in, + asize, + scrPtr); + /* handle MSD carry */ + scrPtr[asize] += carry; + } + } + bsize+=asize; + if(scratch1->n[bsize - 1] == 0) { + --bsize; + } + scratch1->sign = gsign(a) * gsign(b) * bsize; + if (abs(scratch1->sign) > scratch1->capacity) { + CKRaise("GiantGrammarMul overflow"); + } + gtog(scratch1,b); + returnGiant(scratch1); + + #if FEE_DEBUG + (void)bitlen(b); // Assertion.... + #endif /* FEE_DEBUG */ + PROF_INCR(numMulg); // for normal profiling + INCR_MULGS; // for ellipticMeasure +} + +void grammarSquare(giant a) { + /* + * For now, we're going to match the old implementation line for + * line by maintaining prod, carry, and temp as double precision + * giantDigits. There is probably a much better implementation.... + */ + giantDigit prodLo; + giantDigit prodHi; + giantDigit carryLo = 0; + giantDigit carryHi = 0; + giantDigit tempLo; + giantDigit tempHi; + unsigned int cur_term; + unsigned asize; + unsigned max; + giantDigit *ptr = a->n; + giantDigit *ptr1; + giantDigit *ptr2; + giant scratch; + + /* dmitch 11 Jan 1998 - special case for a == 0 */ + if(a->sign == 0) { + goto end; + } + /* end a == 0 case */ + asize = abs(a->sign); + max = asize * 2 - 1; + scratch = borrowGiant(2 * asize); + asize--; + + /* + * temp = *ptr; + * temp *= temp; + * scratch->n[0] = temp; + * carry = temp >> 16; + */ + giantMulDigits(*ptr, *ptr, &tempLo, &tempHi); + scratch->n[0] = tempLo; + carryLo = tempHi; + carryHi = 0; + + for (cur_term = 1; cur_term < max; cur_term++) { + ptr1 = ptr2 = ptr; + if (cur_term <= asize) { + ptr2 += cur_term; + } else { + ptr1 += cur_term - asize; + ptr2 += asize; + } + + /* + * prod = carry & 0xFFFF; + * carry >>= 16; + */ + prodLo = carryLo; + prodHi = 0; + carryLo = carryHi; + carryHi = 0; + while(ptr1 < ptr2) { + /* + * temp = *ptr1++ * *ptr2--; + */ + giantMulDigits(*ptr1++, *ptr2--, &tempLo, &tempHi); + + /* + * prod += (temp << 1) & 0xFFFF; + */ + giantAddDouble(&prodLo, &prodHi, (tempLo << 1)); + + /* + * carry += (temp >> 15); + * use bits from both product digits.. + */ + giantAddDouble(&carryLo, &carryHi, + (tempLo >> (GIANT_BITS_PER_DIGIT - 1))); + giantAddDouble(&carryLo, &carryHi, (tempHi << 1)); + + /* snag the msb from that last shift */ + carryHi += (tempHi >> (GIANT_BITS_PER_DIGIT - 1)); + } + if (ptr1 == ptr2) { + /* + * temp = *ptr1; + * temp *= temp; + */ + giantMulDigits(*ptr1, *ptr1, &tempLo, &tempHi); + + /* + * prod += temp & 0xFFFF; + */ + giantAddDouble(&prodLo, &prodHi, tempLo); + + /* + * carry += (temp >> 16); + */ + giantAddDouble(&carryLo, &carryHi, tempHi); + } + + /* + * carry += prod >> 16; + */ + giantAddDouble(&carryLo, &carryHi, prodHi); + + scratch->n[cur_term] = prodLo; + } + if (carryLo) { + scratch->n[cur_term] = carryLo; + scratch->sign = cur_term+1; + } else scratch->sign = cur_term; + + gtog(scratch,a); + returnGiant(scratch); +end: + PROF_INCR(numGsquare); +} + +/* + * Clear all of a giant's data fields, for secure erasure of sensitive data., + */ +void clearGiant(giant g) +{ + unsigned i; + + for(i=0; icapacity; i++) { + g->n[i] = 0; + } + g->sign = 0; +} + +#if ENGINE_127_BITS +/* + * only used by engineNSA127.c, which is obsolete as of 16 Jan 1997 + */ +int +scompg(int n, giant g) { + if((g->sign == 1) && (g->n[0] == n)) return(1); + return(0); +} + +#endif // ENGINE_127_BITS + +/* + * New modg() and divg() arithmetic, from R. Crandall, 11 June 1997. + */ + +/* + * Calculate the reciprocal of a demonimator used in divg_via_recip() and + * modg_via_recip(). + */ +void +make_recip(giant d, giant r) +/* r becomes the steady-state reciprocal + 2^(2b)/d, where b = bit-length of d-1. */ +{ + int b; + int giantSize = 4 * abs(d->sign); + giant tmp = borrowGiant(giantSize); + giant tmp2 = borrowGiant(giantSize); + + if (isZero(d) || (d->sign < 0)) + { + CKRaise("illegal argument to make_recip"); + } + int_to_giant(1, r); subg(r, d); b = bitlen(d); addg(r, d); + gshiftleft(b, r); gtog(r, tmp2); + while(1) { + gtog(r, tmp); + gsquare(tmp); + gshiftright(b, tmp); + mulg(d, tmp); + gshiftright(b, tmp); + addg(r, r); subg(tmp, r); + if(gcompg(r, tmp2) <= 0) break; + gtog(r, tmp2); + } + int_to_giant(1, tmp); + gshiftleft(2*b, tmp); + gtog(r, tmp2); mulg(d, tmp2); + subg(tmp2, tmp); + int_to_giant(1, tmp2); + while(tmp->sign < 0) { + subg(tmp2, r); + addg(d, tmp); + } + + returnGiant(tmp); + returnGiant(tmp2); + return; +} + +/* + * Optimized divg, when reciprocal of denominator is known. + */ +void +divg_via_recip(giant d, giant r, giant n) +/* n := n/d, where r is the precalculated + steady-state reciprocal of d. */ +{ + int s = 2*(bitlen(r)-1), sign = gsign(n); + int giantSize = (4 * abs(d->sign)) + abs(n->sign); + giant tmp = borrowGiant(giantSize); + giant tmp2 = borrowGiant(giantSize); + + if (isZero(d) || (d->sign < 0)) + { + CKRaise("illegal argument to divg_via_recip"); + } + n->sign = abs(n->sign); + int_to_giant(0, tmp2); + while(1) { + gtog(n, tmp); + mulg(r, tmp); + gshiftright(s, tmp); + addg(tmp, tmp2); + mulg(d, tmp); + subg(tmp, n); + if(gcompg(n,d) >= 0) { + subg(d,n); + iaddg(1, tmp2); + } + if(gcompg(n,d) < 0) break; + } + gtog(tmp2, n); + n->sign *= sign; + returnGiant(tmp); + returnGiant(tmp2); + return; +} + +/* + * Optimized modg, when reciprocal of denominator is known. + */ + +/* New version, 24 Dec 1997. */ + +void +modg_via_recip( + giant d, + giant r, + giant n +) +/* This is the fastest mod of the present collection. + n := n % d, where r is the precalculated + steady-state reciprocal of d. */ + +{ + int s = (bitlen(r)-1), sign = n->sign; + int giantSize = (4 * abs(d->sign)) + abs(n->sign); + giant tmp, tmp2; + + tmp = borrowGiant(giantSize); + tmp2 = borrowGiant(giantSize); + if (isZero(d) || (d->sign < 0)) + { + CKRaise("illegal argument to modg_via_recip"); + } + n->sign = abs(n->sign); + while (1) + { + gtog(n, tmp); + /* bug fix 13 Apr 1998 */ + if(s == 0) { + gshiftleft(1, tmp); + } + else { + gshiftright(s-1, tmp); + } + /* end fix */ + mulg(r, tmp); + gshiftright(s+1, tmp); + mulg(d, tmp); + subg(tmp, n); + if (gcompg(n,d) >= 0) + subg(d,n); + if (gcompg(n,d) < 0) + break; + } + if (sign >= 0) + goto done; + if (isZero(n)) + goto done; + negg(n); + addg(d,n); +done: + returnGiant(tmp); + returnGiant(tmp2); + return; +} + +/* + * Unoptimized, inefficient general modg, when reciprocal of denominator + * is not known. + */ +void +modg( + giant d, + giant n +) +{ + /* n becomes n%d. n is arbitrary, but the denominator d must be + * positive! */ + + /* + * 4/9/2001: seeing overflow on this recip. Alloc per + * d->capacity, not d->sign. + */ + //giant recip = borrowGiant(2 * abs(d->sign)); + giant recip = borrowGiant(2 * d->capacity); + + #if WARN_UNOPTIMIZE + dbgLog(("Warning: unoptimized modg!\n")); + #endif // WARN_UNOPTIMIZE + + make_recip(d, recip); + modg_via_recip(d, recip, n); + returnGiant(recip); +} + +/* + * Unoptimized, inefficient general divg, when reciprocal of denominator + * is not known. + */ +void +divg( + giant d, + giant n +) +{ + /* n becomes n/d. n is arbitrary, but the denominator d must be + * positive! + */ + + giant recip = borrowGiant(2 * abs(d->sign)); + + #if WARN_UNOPTIMIZE + dbgLog(("Warning: unoptimized divg!\n")); + #endif // WARN_UNOPTIMIZE + + make_recip(d, recip); + divg_via_recip(d, recip, n); + returnGiant(recip); +} diff --git a/libsecurity_cryptkit/lib/giantIntegers.h b/libsecurity_cryptkit/lib/giantIntegers.h new file mode 100644 index 00000000..fa2443b7 --- /dev/null +++ b/libsecurity_cryptkit/lib/giantIntegers.h @@ -0,0 +1,163 @@ +/* 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. + *************************************************************************** + * + * giantIntegers.h - large-integer arithmetic library. + * + * Revision History + * ---------------- + * 05 Oct 98 Doug Mitchell at Apple + * Default "unsigned int" giantDigit for __i386__ and __i486__ + * 08 May 97 Doug Mitchell at Apple + * Changed size of giantstruct.n to 1 for Mac build + * ? ? 1991 Richard Crandall at Next + * Created. + */ + +#ifndef _CK_NSGIANTINTS_H_ +#define _CK_NSGIANTINTS_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Size of giant digit. + */ +#if NeXT || __i386__ || __i486__ + +typedef unsigned int giantDigit; + +/* + * used to divide by GIANT_BITS_PER_DIGIT via shift - no easy way to get + * the compiler to calculate this. + */ +#define GIANT_LOG2_BITS_PER_DIGIT 5 + +#elif defined(macintosh) || defined(__ppc__) + +typedef unsigned int giantDigit; +#define GIANT_LOG2_BITS_PER_DIGIT 5 + +#else + +typedef unsigned short giantDigit; +#define GIANT_LOG2_BITS_PER_DIGIT 4 + +#endif + +/* platform-independent digit manipulation macros */ + +#define GIANT_BYTES_PER_DIGIT (sizeof(giantDigit)) +#define GIANT_BITS_PER_DIGIT (8 * GIANT_BYTES_PER_DIGIT) +#define GIANT_DIGIT_MASK ((giantDigit)~0) +#define BYTES_TO_GIANT_DIGITS(x) \ + ((x + GIANT_BYTES_PER_DIGIT - 1) / GIANT_BYTES_PER_DIGIT) + +#define MAX_DIGITS ((1<<18)+(1<<17)) + /* 2^(16*MAX_DIGITS)-1 will fit into a giant. */ + +/* + * The giant stack package is a local cache which allows us to avoid calls + * to malloc() for borrowGiant(). On a 90 Mhz Pentium, enabling the + * giant stack package shows about a 1.35 speedup factor over an identical + * CryptKit without the giant stacks enabled. + */ +#define GIANTS_VIA_STACK CRYPTKIT_GIANT_STACK_ENABLE + +typedef struct { + int sign; /* number of giantDigits = abs(sign) */ + unsigned capacity; /* largest possible number of giantDigits */ + giantDigit n[1]; /* n[0] is l.s. digit */ +} giantstruct; +typedef giantstruct *giant; + +#if GIANTS_VIA_STACK +/* + * For giant stack debug only + * Set default giant size (i.e., for newGiant(0) and borrowGiant(0)) + */ +void setGiantSize(unsigned numDigits); + +/* + * Initialize giant stacks, with up to specified max giant size. + */ +void initGiantStacks(unsigned maxDigits); + +/* + * Free giant stacks on shutdown. + */ +void freeGiantStacks(); + +#endif /* GIANTS_VIA_STACK */ + +giant newGiant(unsigned numDigits); +giant copyGiant(giant x); +void freeGiant(giant x); + +giant borrowGiant(unsigned numDigits); /* get a temporary */ +void returnGiant(giant); /* return it */ +unsigned bitlen(giant n); /* Returns the bit-length n; + * e.g. n=7 returns 3. */ +int bitval(giant n, int pos); /* Returns the value of bit pos of n */ +int isZero(giant g); /* Returns whether g is zero */ +int isone(giant g); /* Returns whether g is 1 */ +void gtog(giant src, giant dest); /* Copies one giant to another */ +void int_to_giant(int n, giant g); /* Gives a giant an int value */ +int gcompg(giant a, giant b); /* Returns 1, 0, -1 as a>b, a=b, a> GIANT_BITS_PER_DIGIT); + *lowProduct = (giantDigit)dprod; +} + +/* + * Multiply a vector of giantDigits, candVector, by a single giantDigit, + * plierDigit, adding results into prodVector. Returns m.s. digit from + * final multiply; only candLength digits of *prodVector will be written. + */ +static inline giantDigit VectorMultiply( + giantDigit plierDigit, + giantDigit *candVector, + unsigned candLength, + giantDigit *prodVector) +{ + unsigned candDex; // index into multiplicandVector + giantDigit lastCarry = 0; + giantDigit prodLo; + giantDigit prodHi; + + for(candDex=0; candDex> GIANT_BITS_PER_DIGIT); */ + stw r8, 0(hiProduct) + + /* *lowProduct = (giantDigit)dprod; */ + stw r7, 0(lowProduct) + blr +} + +asm giantDigit VectorMultiply( + register giantDigit plierDigit, /* r3 */ + register giantDigit *candVector, /* r4 */ + register unsigned candLength, /* r5 */ + register giantDigit *prodVector) /* r6 */ +{ + register unsigned candDex; /* index into multiplicandVector */ + register giantDigit lastCarry; + register giantDigit prodLo; + register giantDigit prodHi; + register unsigned scr1; + register unsigned sumLo; + + fralloc + + /* giantDigit lastCarry = 0; */ + li lastCarry,0 + + + /* for(candDex=0; candDex scr1 */ + addi candVector,candVector,4 /* candVector++ */ + + mullw prodLo,scr1,plierDigit /* prodLo = low(*candVector * plierDigit) */ + mulhwu prodHi,scr1,plierDigit /* prodHi = high(*candVector * plierDigit) */ + + /* giantAddDouble(&prodLo, &prodHi, *prodVector); */ + lwz scr1,0(prodVector) /* *prodVector --> r9 */ + add sumLo,prodLo,scr1 /* prodLo + *prodVector --> sumLo */ + cmpl crf0,0,sumLo,prodLo /* sumLo < prodLo? */ + bc 12,0,_carry1 + cmpl crf0,0,sumLo,scr1 /* sumLo < *prodVector? */ + bc 4,0,_noCar1 +_carry1: + addi prodHi,prodHi,1 /* prodHi++ */ +_noCar1: + mr. prodLo,sumLo /* prodLo := sumLo */ + + /* giantAddDouble(&prodLo, &prodHi, lastCarry); */ + add sumLo,sumLo,lastCarry /* sumLo += lastCarry */ + cmpl crf0,0,sumLo,prodLo /* sumLo < prodLo? */ + bc 12,0,_carry2 + cmpl crf0,0,sumLo,lastCarry /* sumLo < lastCarry? */ + bc 4,0,_noCar2 +_carry2: + addi prodHi,prodHi,1 /* prodHi++ */ +_noCar2: + mr. prodLo,sumLo /* prodLo := sumLo */ + + /* *(prodVector++) = prodLo; */ + stw prodLo,0(prodVector) /* prodLo --> *prodVector */ + addi prodVector,prodVector,4 /* prodVector++ */ + + /* lastCarry = prodHi; */ + mr. lastCarry,prodHi + + /* } */ + addi candDex,candDex,1 /* candDex++ */ +_endLoop: + cmpl crf0,0,candDex,candLength /* candDex < candLength? */ + bc 12,0,_topLoop + + /* return lastCarry; */ + mr. r3,lastCarry /* return lastCarry in r3 */ + frfree + blr +} + +#endif // PPC_GIANT_PORT_INLINE diff --git a/libsecurity_cryptkit/lib/giantPort_PPC.h b/libsecurity_cryptkit/lib/giantPort_PPC.h new file mode 100644 index 00000000..9a3d7bb4 --- /dev/null +++ b/libsecurity_cryptkit/lib/giantPort_PPC.h @@ -0,0 +1,119 @@ +/* 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. + *************************************************************************** + * + * giantPort_PPC.h - PPC-dependent giant definitions. + * + * Revision History + * ---------------- + * 10/06/98 ap + * Changed to compile with C++. + * 06 Apr 1998 Doug Mitchell at Apple + * Created. + */ + +#ifndef _CK_NSGIANT_PORT_PPC_H_ +#define _CK_NSGIANT_PORT_PPC_H_ + +#include "feeDebug.h" +#include "platform.h" +#include "giantIntegers.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/**** FIXME - implement asm giant digits! ****/ +/* + * 0 ==> use function declarations from this file and implementation + * in giantPort_PPC.c + * 1 ==> use static inline C function in giantPort_Generic.h + */ +/*@@@ HACK @@@ +#if defined NeXT +#define PPC_GIANT_PORT_INLINE 1 +#else +#define PPC_GIANT_PORT_INLINE 0 +#endif +*/ +#define PPC_GIANT_PORT_INLINE 1 + +#if PPC_GIANT_PORT_INLINE + +#include "giantPort_Generic.h" + +#else // PPC_GIANT_PORT_INLINE + +/* + * We'll be using the compiler's 64-bit long long for these routines. + * + * Mask for upper word. + */ +#define GIANT_UPPER_DIGIT_MASK (~(unsigned long long(GIANT_DIGIT_MASK))) + +/* + * Multiple-precision arithmetic routines/macros. C for now, eventually + * they'll be in assembly. + */ + +/* + * Add two digits, return sum. Carry bit returned as an out parameter. + * This should work any size giantDigits up to unsigned int. + */ +extern giantDigit giantAddDigits( + giantDigit dig1, + giantDigit dig2, + giantDigit *carry); /* RETURNED, 0 or 1 */ + +/* + * Add a single digit value to a double digit accumulator in place. + * Carry out of the MSD of the accumulator is not handled. + */ +void giantAddDouble( + giantDigit *accLow, /* IN/OUT */ + giantDigit *accHigh, /* IN/OUT */ + giantDigit val); + + +/* + * Subtract a - b, return difference. Borrow bit returned as an out parameter. + */ +giantDigit giantSubDigits( + giantDigit a, + giantDigit b, + giantDigit *borrow); /* RETURNED, 0 or 1 */ + + +/* + * Multiply two digits, return two digits. + */ +void giantMulDigits( + giantDigit dig1, + giantDigit dig2, + giantDigit *lowProduct, /* RETURNED, low digit */ + giantDigit *hiProduct); /* RETURNED, high digit */ + +/* + * Multiply a vector of giantDigits, candVector, by a single giantDigit, + * plierDigit, adding results into prodVector. Returns m.s. digit from + * final multiply; only candLength digits of *prodVector will be written. + */ +giantDigit VectorMultiply( + giantDigit plierDigit, + giantDigit *candVector, + unsigned candLength, + giantDigit *prodVector); + +#ifdef __cplusplus +} +#endif + +#endif /* !PPC_GIANT_PORT_INLINE */ + +#endif /*_CK_NSGIANT_PORT_PPC_H_*/ diff --git a/libsecurity_cryptkit/lib/giantPort_PPC_Gnu.h b/libsecurity_cryptkit/lib/giantPort_PPC_Gnu.h new file mode 100644 index 00000000..3676da99 --- /dev/null +++ b/libsecurity_cryptkit/lib/giantPort_PPC_Gnu.h @@ -0,0 +1,83 @@ +/* + * giantPort_PPC_Gnu.h - giant definitions, PPC/GNU version. + */ + +#ifndef _CK_NSGIANT_PORT_PPC_GNU_H_ +#define _CK_NSGIANT_PORT_PPC_GNU_H_ + +#include "feeDebug.h" +#include "platform.h" +#include "giantIntegers.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* define this true to disable this module and use generic C versions instead */ +#define PPC_GIANT_PORT_INLINE 0 + +#if PPC_GIANT_PORT_INLINE + +#include "giantPort_Generic.h" + +#else // PPC_GIANT_PORT_INLINE + +/* + * Multiple-precision arithmetic routines/macros implemented in + * giantPort_PPC_Gnu.s + */ + +/* + * Add two digits, return sum. Carry bit returned as an out parameter. + */ +extern giantDigit giantAddDigits( + giantDigit dig1, + giantDigit dig2, + giantDigit *carry); /* RETURNED, 0 or 1 */ + +/* + * Add a single digit value to a double digit accumulator in place. + * Carry out of the MSD of the accumulator is not handled. + */ +void giantAddDouble( + giantDigit *accLow, /* IN/OUT */ + giantDigit *accHigh, /* IN/OUT */ + giantDigit val); + + +/* + * Subtract a - b, return difference. Borrow bit returned as an out parameter. + */ +giantDigit giantSubDigits( + giantDigit a, + giantDigit b, + giantDigit *borrow); /* RETURNED, 0 or 1 */ + + +/* + * Multiply two digits, return two digits. + */ +void giantMulDigits( + giantDigit dig1, + giantDigit dig2, + giantDigit *lowProduct, /* RETURNED, low digit */ + giantDigit *hiProduct); /* RETURNED, high digit */ + +/* + * Multiply a vector of giantDigits, candVector, by a single giantDigit, + * plierDigit, adding results into prodVector. Returns m.s. digit from + * final multiply; only candLength digits of *prodVector will be written. + */ +giantDigit VectorMultiply( + giantDigit plierDigit, + giantDigit *candVector, + unsigned candLength, + giantDigit *prodVector); + +#ifdef __cplusplus +} +#endif + +#endif /* !PPC_GIANT_PORT_INLINE */ + +#endif /*_CK_NSGIANT_PORT_PPC_GNU_H_*/ diff --git a/libsecurity_cryptkit/lib/giantPort_PPC_Gnu.s b/libsecurity_cryptkit/lib/giantPort_PPC_Gnu.s new file mode 100644 index 00000000..96cbacd3 --- /dev/null +++ b/libsecurity_cryptkit/lib/giantPort_PPC_Gnu.s @@ -0,0 +1,282 @@ +/* + * giantPort_X_PPC.s - PPC/OS X giant port module + * + * Created 3/19/2001 by Doug Mitchell. + */ + +/* + * As of 3/19/2001, using this module results in no change in runtime + * performance compared to using the inline C functions in + * giantPort_Generic.h. Examination of the compiled code shows that + * the GNU C compiler, when configured for -O2, generates almost + * exactly the same code as we have here. + * We'll leave this code in, to protect against changes in gcc, changes + * in CFLAGS, and to serve as an example for other PPC implementations. + */ + +#if defined(__ppc__) && defined(__MACH__) + +/********************************************* + +Add two digits, return sum. Carry bit returned as an out parameter. + +giantDigit giantAddDigits( + register giantDigit dig1, + register giantDigit dig2, + register giantDigit *carry) ...RETURNED, 0 or 1 +**********************************************/ + .text + .align 2 +.globl _giantAddDigits +_giantAddDigits: + /* + * dig1 : r3 + * dig2 : r4 + * carry : r5 + * sum : r6 + */ + + /* sum = dig1 + dig2 */ + add r6, r3, r4; + + /* if((sum < dig1) || (sum < dig2)) */ + cmplw cr0,r6,r3 + blt L1 + cmplw cr0,r6,r4 + bge L2 + +L1: + /* *carry = 1; */ + li r7,1 + stw r7, 0(r5) + b L3 + +L2: + /* else *carry = 0; */ + li r7,0 + stw r7, 0(r5) + +L3: + /* return sum in r3 */ + mr. r3,r6 + blr + +/********************************************* + +Add a single digit value to a double digit accumulator in place. +Carry out of the MSD of the accumulator is not handled. + +void giantAddDouble( + giantDigit *accLow, -- IN/OUT + giantDigit *accHigh, -- IN/OUT + giantDigit val); +**********************************************/ + + .align 2 +.globl _giantAddDouble +_giantAddDouble: + /* + * r3 : accLow + * r4 : accHi + * r5 : val + * r6 : sumLo + * r7 : *accLow + */ + + /* giantDigit sumLo = *accLow + val; */ + lwz r7,0(r3) + add r6,r7,r5 + + /* if((sumLo < *accLow) || (sumLo < val)) { */ + cmplw cr0,r6,r7 + blt L10 + cmplw cr0,r6,r5 + bge L11 + +L10: + /* (*accHigh)++; */ + lwz r7, 0(r4) + addi r7,r7,1 + stw r7, 0(r4) + +L11: + /* *accLow = sumLo; */ + stw r6,0(r3) + blr + +/***************************************************************************** + +Subtract a - b, return difference. Borrow bit returned as an out parameter. + +giantDigit giantSubDigits( + giantDigit a, + giantDigit b, + giantDigit *borrow) -- RETURNED, 0 or 1 + +******************************************************************************/ + + .align 2 +.globl _giantSubDigits +_giantSubDigits: + + /* a : r3 + b : r4 + borrow : r5 + diff : r6 */ + + /* giantDigit diff = a - b; */ + subf r6, r4, r3; + + /* if(a < b) */ + cmplw cr0,r3,r4 + bge L20 + + /* *borrow = 1; */ + li r7,1 + stw r7, 0(r5) + b L21 + +L20: + /* else *borrow = 0; */ + li r7,0 + stw r7, 0(r5) + +L21: + /* return diff in r3 */ + mr. r3,r6 + blr + +/***************************************************************************** + +Multiply two digits, return two digits. + +void giantMulDigits( + giantDigit dig1, + giantDigit dig2, + giantDigit *lowProduct, -- RETURNED, low digit + giantDigit *hiProduct) -- RETURNED, high digit + +******************************************************************************/ + + .align 2 +.globl _giantMulDigits +_giantMulDigits: + + /* r3 : dig1 + r4 : dig2 + r5 : lowProduct + r6 : hiProduct */ + + /* dprod = (unsigned long long)dig1 * (unsigned long long)dig2; */ + mullw r7, r3, r4 /* r7 = low(dig1 * dig2) */ + mulhwu r8, r3, r4 /* r8 - hi(dig1 * dig2) */ + + /* *hiProduct = (giantDigit)(dprod >> GIANT_BITS_PER_DIGIT); */ + stw r8, 0(r6) + + /* *lowProduct = (giantDigit)dprod; */ + stw r7, 0(r5) + blr + + +/***************************************************************************** + +Multiply a vector of giantDigits, candVector, by a single giantDigit, +plierDigit, adding results into prodVector. Returns m.s. digit from +final multiply; only candLength digits of *prodVector will be written. + +giantDigit VectorMultiply( + giantDigit plierDigit, + giantDigit *candVector, + unsigned candLength, + giantDigit *prodVector) + +******************************************************************************/ + +/* + * Register definitions + * Input paramters: + */ +#define plierDigit r3 +#define candVector r4 +#define candLength r5 +#define prodVector r6 + +/* + * PPC ABI specifies: + * r3..r10 for parameter passing + * r11, r12 volatile (caller saved, we can write) + * + * We'll use the remainder of the registers normally used for parameter passing + * and also the other volatile register for local variables. + */ +#define candDex r7 +#define lastCarry r8 +#define prodLo r9 +#define prodHi r10 +#define scr1 r11 +#define sumLo r12 + + .align 2 +.globl _VectorMultiply +_VectorMultiply: + + /* giantDigit lastCarry = 0; */ + li lastCarry,0 + + + /* for(candDex=0; candDex scr1 */ + addi candVector,candVector,4 /* candVector++ */ + + mullw prodLo,scr1,plierDigit /* prodLo = low(*candVector * plierDigit) */ + mulhwu prodHi,scr1,plierDigit /* prodHi = high(*candVector * plierDigit) */ + + /* giantAddDouble(&prodLo, &prodHi, *prodVector); */ + lwz scr1,0(prodVector) /* *prodVector --> r9 */ + add sumLo,prodLo,scr1 /* prodLo + *prodVector --> sumLo */ + cmplw cr0,sumLo,prodLo /* sumLo < prodLo? */ + blt L_carry1 + cmplw cr0,sumLo,scr1 /* sumLo < *prodVector? */ + bge L_noCar1 +L_carry1: + addi prodHi,prodHi,1 /* prodHi++ */ +L_noCar1: + mr. prodLo,sumLo /* prodLo := sumLo */ + + /* giantAddDouble(&prodLo, &prodHi, lastCarry); */ + add sumLo,sumLo,lastCarry /* sumLo += lastCarry */ + cmplw cr0,sumLo,prodLo /* sumLo < prodLo? */ + blt L_carry2 + cmplw cr0,sumLo,lastCarry /* sumLo < lastCarry? */ + bge L_noCar2 +L_carry2: + addi prodHi,prodHi,1 /* prodHi++ */ +L_noCar2: + mr. prodLo,sumLo /* prodLo := sumLo */ + + /* *(prodVector++) = prodLo; */ + stw prodLo,0(prodVector) /* prodLo --> *prodVector */ + addi prodVector,prodVector,4 /* prodVector++ */ + + /* lastCarry = prodHi; */ + mr. lastCarry,prodHi + + /* } */ + addi candDex,candDex,1 /* candDex++ */ +L_endLoop: + cmplw cr0,candDex,candLength /* candDex < candLength? */ + blt L_topLoop + + /* return lastCarry; */ + mr. r3,lastCarry /* return lastCarry in r3 */ + blr + +#endif /* defined(__ppc__) && defined(__MACH__) */ diff --git a/libsecurity_cryptkit/lib/giantPort_i486.h b/libsecurity_cryptkit/lib/giantPort_i486.h new file mode 100644 index 00000000..9ca210d1 --- /dev/null +++ b/libsecurity_cryptkit/lib/giantPort_i486.h @@ -0,0 +1,126 @@ +/* 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. + *************************************************************************** + * + * giantPorti486.h - OpenStep-dependent giant definitions. + * + * Revision History + * ---------------- + * 06 Apr 1998 Doug Mitchell at Apple + * Created. + */ + +#ifndef _CK_NSGIANT_PORT_I486_H_ +#define _CK_NSGIANT_PORT_I486_H_ + +#include "giantIntegers.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Add two digits, return sum. Carry bit returned as an out parameter. + */ +static inline giantDigit giantAddDigits( + giantDigit dig1, + giantDigit dig2, + giantDigit *carry) /* RETURNED, 0 or 1 */ +{ + giantDigit _sum; /* r/w %0 */ + asm volatile( + "movl %2, %0 /* _sum = dig1 */ \n" + "addl %3, %0 /* _sum += dig2 */ \n" + "jc .+9 \n" + "movl $0, %1 /* carry = 0 */ \n" + "jmp .+7 \n" + "movl $1, %1 /* carry = 1 */ \n" + : "=&r" (_sum), "=&r" (*carry) + : "r" (dig1), "r" (dig2)); + return _sum; +} + +/* + * Add a single digit value to a double digit accumulator in place. + * Carry out of the MSD of the accumulator is not handled. + */ +static inline void giantAddDouble( + giantDigit *accLow, /* IN/OUT */ + giantDigit *accHigh, /* IN/OUT */ + giantDigit val) +{ + asm volatile( + "addl %4, %0 /* accLow += val */ \n" + "jnc .+3 \n" + "incl %1 /* accHigh++ */ \n" + : "=&r" (*accLow), "=&r" (*accHigh) + : "0" (*accLow), "1" (*accHigh), "r" (val)); +} + +/* + * Subtract a - b, return difference. Borrow bit returned as an out parameter. + */ +static inline giantDigit giantSubDigits( + giantDigit a, + giantDigit b, + giantDigit *borrow) /* RETURNED, 0 or 1 */ +{ + giantDigit _diff; /* r/w %0 */ + asm volatile( + "movl %2, %0 /* _diff = a */ \n" + "subl %3, %0 /* _diff -= b */ \n" + "jc .+9 \n" + "movl $0, %1 /* borrow = 0 */ \n" + "jmp .+7 \n" + "movl $1, %1 /* borrow = 1 */ \n" + : "=&r" (_diff), "=&r" (*borrow) + : "r" (a), "r" (b)); + return _diff; +} + +/* + * Multiply two digits, return two digits. + */ +static inline void giantMulDigits( + giantDigit dig1, + giantDigit dig2, + giantDigit *lowProduct, // RETURNED, low digit + giantDigit *hiProduct) // RETURNED, high digit + +{ + asm volatile( + "movl %2, %%eax /* eax = dig1 */ \n" + "movl %3, %%edx /* edx = dig2 */ \n" + "mull %%edx /* eax *= dig2 */ \n" + : "=&a" (*lowProduct), "=&d" (*hiProduct) + : "r" (dig1), "r" (dig2) + : "%eax", "%edx" ); +} + +/* + * Multiply a vector of giantDigits, candVector, by a single giantDigit, + * plierDigit, adding results into prodVector. Returns m.s. digit from + * final multiply; only candLength digits of *prodVector will be written. + * + * This one's implemented in a .s file. + */ +extern giantDigit vectorMult_x86( + giantDigit plierDigit, + giantDigit *candVector, + unsigned candLength, + giantDigit *prodVector); + +#define VectorMultiply(pd, cv, cl, pv) vectorMult_x86(pd, cv, cl, pv) + + +#ifdef __cplusplus +} +#endif + +#endif _CK_NSGIANT_PORT_I486_H_ diff --git a/libsecurity_cryptkit/lib/giantPort_i486.s b/libsecurity_cryptkit/lib/giantPort_i486.s new file mode 100644 index 00000000..4704de1e --- /dev/null +++ b/libsecurity_cryptkit/lib/giantPort_i486.s @@ -0,0 +1,149 @@ +/* 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. + *************************************************************************** + * + * giantPorti486.s - i486-specific assembly routines. + * + * Revision History + * ---------------- + * 17 Apr 1998 Doug Mitchell at Apple + * Created. + */ + +#if defined (i386) || defined(__i386__) +.text + +/* + * Multiply a vector a giantDigits, candVector, by a single giantDigit, + * plierDigit, adding results in prodVector. + * + * void VectorMultiply( + * giantDigit plierDigit, + * giantDigit *candVector, + * unsigned candLength, + * giantDigit *prodVector) + */ + +.align 2,0x90 +.globl _vectorMult_x86 + +/* + * Stack locations, relative to adjusted bp. + */ +#define LOCAL_SPACE 0x4 + +#define ARG_START (LOCAL_SPACE + 8) /* rtn ptr plus bp */ +#define ARG_PLIER_DIGIT (ARG_START + 0) +#define ARG_CAND_VECTOR (ARG_START + 4) /* cached in ecx */ +#define ARG_CAND_LENGTH (ARG_START + 8) +#define ARG_PROD_VECTOR (ARG_START + 12) /* cached in esi */ + +#define LOCAL_START (0) +#define LOC_CAND_DEX (LOCAL_START + 0) /* index into candVector */ + +/* + * ebx : lastCarry + * esi : prodVector + * ecx : candVector + */ +_vectorMult_x86: + + pushl %ebp + subl $LOCAL_SPACE,%esp + movl %esp,%ebp + pushl %edi + pushl %esi + pushl %ebx + + /* esp not used again 'til we pop these off stack */ + + /* prodVector = %esi */ + movl ARG_PROD_VECTOR(%ebp),%esi + + /* lastCarry = 0 */ + /* 0 --> candDex in 0xf0(%ebp) */ + xorl %ebx,%ebx + + /* candVector --> %ecx */ + movl ARG_CAND_VECTOR(%ebp),%ecx + + /* for(candDex=0; candDex 0 to start...*/ + cmpl %ebx,ARG_CAND_LENGTH(%ebp) + jbe _loopEnd + +_loopTop: + /* branch back to top of for loop */ + + /* *candVector--> %eax */ + movl (%ecx),%eax + + /* candVector++ */ + addl $0x04,%ecx + + /* plierDigit --> %edx */ + movl ARG_PLIER_DIGIT(%ebp),%edx + + /* eax = *candVector + * edx = plierDigit + * edx:eax := (plierDigit * *candVector) */ + mull %edx + + /* from here to end of loop: + prodLo : eax + prodHi : edx */ + + /* prodLo += *prodVector */ + addl (%esi),%eax + + /* add carry to hi digit */ + adc $0,%edx + + /* prodLo += lastCarry */ + addl %ebx,%eax + /* add carry to hi digit */ + adc $0,%edx + + /* *(prodVector++) = prodLo; */ + movl %eax,(%esi) + addl $0x04,%esi + + /* lastCarry = prodHi */ + movl %edx, %ebx + + /* candDex++ */ + incl LOC_CAND_DEX(%ebp) + + /* top of loop if candDex < candLength */ + movl ARG_CAND_LENGTH(%ebp),%eax + cmpl %eax,LOC_CAND_DEX(%ebp) + jb _loopTop + +_loopEnd: + /* out of for loop */ + /* *prodVector += lastCarry; */ +#if 0 + addl %ebx,(%esi) + + /* return carry from last addition */ + xorl %eax,%eax + adc $0,%eax +#else + /* return lastCarry */ + movl %ebx,%eax +#endif + popl %ebx + popl %esi + popl %edi + addl $LOCAL_SPACE,%esp + popl %ebp + ret +#endif /* i386 */ diff --git a/libsecurity_cryptkit/lib/mutils.h b/libsecurity_cryptkit/lib/mutils.h new file mode 100644 index 00000000..14b0fea4 --- /dev/null +++ b/libsecurity_cryptkit/lib/mutils.h @@ -0,0 +1,36 @@ +/* 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. + *************************************************************************** + * + * mutils.h - general private ObjC routine declarations + * + * Revision History + * ---------------- + * 2 Aug 96 Doug Mitchell at NeXT + * Broke out from Blaine Garst's original NSCryptors.m + */ + +#ifndef _CK_MUTILS_H_ +#define _CK_MUTILS_H_ + +#include +#include "giantIntegers.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern NSMutableData *data_with_giant(giant u); +extern void canonicalize_data(NSMutableData *data); + +#ifdef __cplusplus +} +#endif + +#endif /*_CK_MUTILS_H_*/ diff --git a/libsecurity_cryptkit/lib/mutils.m b/libsecurity_cryptkit/lib/mutils.m new file mode 100644 index 00000000..13137dbc --- /dev/null +++ b/libsecurity_cryptkit/lib/mutils.m @@ -0,0 +1,44 @@ +/* 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. + *************************************************************************** + * + * mutils.m - general private ObjC routine declarations + * + * Revision History + * ---------------- + * 2 Aug 96 Doug Mitchell at NeXT + * Broke out from Blaine Garst's original NSCryptors.m + */ + +#import +#import "giantIntegers.h" +#import "ckutilities.h" +#import "mutils.h" +#import "feeFunctions.h" +#import + +#if defined(NeXT) && !defined(WIN32) + +/* + * Public, declared in NSCryptors.h + */ +NSString *NSPromptForPassPhrase(NSString *prompt) { + // useful for command line (/dev/tty) programs + char buffer[PHRASELEN]; + NSString *result; + + getpassword([prompt cString], buffer); + if (buffer[0] == 0) return nil; + result = [NSString stringWithCString:buffer]; + bzero(buffer, PHRASELEN); + return result; +} + + +#endif NeXT diff --git a/libsecurity_cryptkit/lib/platform.c b/libsecurity_cryptkit/lib/platform.c new file mode 100644 index 00000000..50fb95f7 --- /dev/null +++ b/libsecurity_cryptkit/lib/platform.c @@ -0,0 +1,197 @@ +/* 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. + *************************************************************************** + * + * platform.c - platform-dependent C functions + * + * Revision History + * ---------------- + * 6 Sep 96 Doug Mitchell at NeXT + * Created. + */ + +#include "platform.h" +#include +#include "feeDebug.h" +#ifdef NeXT + +/* + * OpenStep.... + */ +void CKRaise(const char *reason) { + #if FEE_DEBUG + printf("CryptKit fatal error: %s\n", reason); + #endif + exit(1); +} + +#import "feeDebug.h" + +#if !defined(NeXT_PDO) && FEE_DEBUG + +/* + * Mach, private build. use quick microsecond-accurate system clock. + */ + +#include + +unsigned createRandomSeed() +{ + struct tsval tsp; + + (void)kern_timestamp(&tsp); + return tsp.low_val; +} + +#else + +/* + * OpenStep, normal case. + */ +#include +#include + +extern int getpid(); + +unsigned createRandomSeed(void) +{ + time_t curTime; + unsigned thisPid; + + time(&curTime); + thisPid = (unsigned)getpid(); + + return (unsigned)curTime ^ (unsigned)thisPid; +} + +#endif /* FEE_DEBUG */ + +#elif WIN32 + +/* + * OpenStep on Windows. + */ +#include /* for _getpid() */ + +void CKRaise(const char *reason) { + #if FEE_DEBUG + printf("CryptKit fatal error: %s\n", reason); + #endif + exit(1); +} + +extern void time(unsigned *tp); + +unsigned createRandomSeed() +{ + unsigned curTime; + unsigned thisPid; + + time(&curTime); + thisPid = _getpid(); + return (unsigned)curTime ^ (unsigned)thisPid; +} + + +#elif __MAC_BUILD__ + +/* + * Macintosh, all flavors. + */ +#include +#include + +void CKRaise(const char *reason) { + #if FEE_DEBUG + printf("CryptKit fatal error: %s\n", reason); + #endif + exit(1); +} + +/* for X, this isn't used except for testing when SecurityServer when + * Yarrow is not running. So let's strip it down so we don't have + * to link against CarbonCore. + */ +#define BARE_BONES_SEED 1 +#if BARE_BONES_SEED + +#include + +extern int getpid(); + +unsigned createRandomSeed() +{ + time_t curTime; + unsigned thisPid; + + time(&curTime); + thisPid = (unsigned)getpid(); + + return (unsigned)curTime ^ (unsigned)thisPid; +} + +#else /* BARE_BONES_SEED */ + +#include +#include + +// this is mighty pitiful anyway... +unsigned createRandomSeed() +{ + UnsignedWide curTime; + //unsigned ticks; /* use 16 bits */ + unsigned rtnHi; + unsigned rtnLo; + + /* FIXME - need a way to distinguish OS9x from Carbon. Carbon + * doesn't have LMGetTicks(). */ + + Microseconds(&curTime); /* low 16 bits are pretty good */ + + // Carbon hack + // rtnHi = LMGetTicks(); + rtnHi = 0x5a5aa5a5; + rtnLo = curTime.lo & 0xffff; + return (rtnHi ^ rtnLo); +} +#endif /* BARE_BONES_SEED */ + +#elif unix + +/* try for generic UNIX */ + +void CKRaise(const char *reason) { + #if FEE_DEBUG + printf("CryptKit fatal error: %s\n", reason); + #endif + exit(1); +} + +#include +#include + +extern int getpid(); + +unsigned createRandomSeed() +{ + time_t curTime; + unsigned thisPid; + + time(&curTime); + thisPid = (unsigned)getpid(); + + return (unsigned)curTime ^ (unsigned)thisPid; +} + + +#else + +#error platform-specific work needed in security_cryptkit/platform.c + +#endif diff --git a/libsecurity_cryptkit/lib/platform.h b/libsecurity_cryptkit/lib/platform.h new file mode 100644 index 00000000..0869d53d --- /dev/null +++ b/libsecurity_cryptkit/lib/platform.h @@ -0,0 +1,73 @@ +/* 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. + *************************************************************************** + * + * platform.h - platform-dependent C functions + * + * Revision History + * ---------------- + * 6 Sep 96 Doug Mitchell at NeXT + * Created. + */ + +#ifndef _CK_PLATFORM_H_ +#define _CK_PLATFORM_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +/* many ways to determin macintosh - different for 68k, PPC/OS9, X */ +#if defined(__POWERPC__) || defined(__CFM68K__) || defined(__APPLE__) + #undef __MAC_BUILD__ + #define __MAC_BUILD__ 1 +#endif + +/* + * Make sure endianness is defined... + */ +#if defined(__BIG_ENDIAN__) && defined(__LITTLE_ENDIAN__) +#error Hey! multiply defined endianness! +#endif +#if !defined(__BIG_ENDIAN__) && !defined(__LITTLE_ENDIAN__) + #if __MAC_BUILD__ + #define __BIG_ENDIAN__ 1 + #elif __i386__ || __i486__ + #define __LITTLE_ENDIAN__ 1 + #else + #error Platform dependent work needed + #endif +#endif /* endian */ + +#ifndef NeXT + #define bcopy(s, d, l) memmove(d, s, l) + #define bzero(s, l) memset(s, 0, l) + #define bcmp(s, d, l) memcmp(s, d, l) +#endif + +/* + * Other platform-dependent functions in platform.c. + */ + +extern void CKRaise(const char *reason); + +/* + * Come up with some kind of "really" random int with which to seed the + * random number generator. + */ +extern unsigned createRandomSeed(void); + +#ifdef __cplusplus +} +#endif + +#endif /*_CK_PLATFORM_H_*/ diff --git a/libsecurity_cryptkit/lib/unixMakefile b/libsecurity_cryptkit/lib/unixMakefile new file mode 100644 index 00000000..b3a976a8 --- /dev/null +++ b/libsecurity_cryptkit/lib/unixMakefile @@ -0,0 +1,102 @@ +# +# FEE library Makefile, generic UNIX version. +# +FEE_LIB=libFEE.a +# +CFILES=CipherFileDES.c CipherFileFEED.c ckDES.c ckMD5.c elliptic.c giantIntegers.c ckSHA1.c ckSHA1_priv.c byteRep.c curveParams.c enc64.c falloc.c feeCipherFile.c feeCipherFileAtom.c feeDES.c feeDigitalSignature.c feeECDSA.c feeFEED.c feeFEEDExp.c feeHash.c feePublicKey.c feeRandom.c platform.c ckutilities.c ellipticProj.c +# +SFILES=giantPort_PPC_Gnu.s +OFILES= $(CFILES:%.c=%.o) $(SFILES:%.s=%.o) +# +CFLAGS=-g -O -Wall -c -I.. +# +# set to platform-specific compiler (gcc, /bin/cc, etc.) +CC=cc +# +first all: $(FEE_LIB) +# +clean: + rm -f *.o *.a +# +$(FEE_LIB): $(OFILES) + rm -f $(FEE_LIB) + ar r ${FEE_LIB} $(OFILES) + ranlib ${FEE_LIB} +# +CipherFileDES.o: CipherFileDES.c + $(CC) $(CFLAGS) -o $@ CipherFileDES.c + +CipherFileFEED.o: CipherFileFEED.c + $(CC) $(CFLAGS) -o $@ CipherFileFEED.c + +DES.o: DES.c + $(CC) $(CFLAGS) -o $@ DES.c + +MD5.o: MD5.c + $(CC) $(CFLAGS) -o $@ MD5.c + +elliptic.o: elliptic.c + $(CC) $(CFLAGS) -o $@ elliptic.c + +giantIntegers.o: giantIntegers.c + $(CC) $(CFLAGS) -o $@ giantIntegers.c + +ckSHA1.o: ckSHA1.c + $(CC) $(CFLAGS) -o $@ ckSHA1.c + +ckSHA1_priv.o: ckSHA1_priv.c + $(CC) $(CFLAGS) -o $@ ckSHA1_priv.c + +byteRep.o: byteRep.c + $(CC) $(CFLAGS) -o $@ byteRep.c + +curveParams.o: curveParams.c + $(CC) $(CFLAGS) -o $@ curveParams.c + +enc64.o: enc64.c + $(CC) $(CFLAGS) -o $@ enc64.c + +falloc.o: falloc.c + $(CC) $(CFLAGS) -o $@ falloc.c + +feeCipherFile.o: feeCipherFile.c + $(CC) $(CFLAGS) -o $@ feeCipherFile.c + +feeCipherFileAtom.o: feeCipherFileAtom.c + $(CC) $(CFLAGS) -o $@ feeCipherFileAtom.c + +feeDES.o: feeDES.c + $(CC) $(CFLAGS) -o $@ feeDES.c + +feeDigitalSignature.o: feeDigitalSignature.c + $(CC) $(CFLAGS) -o $@ feeDigitalSignature.c + +feeECDSA.o: feeECDSA.c + $(CC) $(CFLAGS) -o $@ feeECDSA.c + +feeFEED.o: feeFEED.c + $(CC) $(CFLAGS) -o $@ feeFEED.c + +feeFEEDExp.o: feeFEEDExp.c + $(CC) $(CFLAGS) -o $@ feeFEEDExp.c + +feeHash.o: feeHash.c + $(CC) $(CFLAGS) -o $@ feeHash.c + +feePublicKey.o: feePublicKey.c + $(CC) $(CFLAGS) -o $@ feePublicKey.c + +feeRandom.o: feeRandom.c + $(CC) $(CFLAGS) -o $@ feeRandom.c + +platform.o: platform.c + $(CC) $(CFLAGS) -o $@ platform.c + +utilities.o: utilities.c + $(CC) $(CFLAGS) -o $@ utilities.c + +giantPort_PPC_Gnu.o: giantPort_PPC_Gnu.s + $(CC) $(CFLAGS) -o $@ giantPort_PPC_Gnu.s + +ellipticProj.o: ellipticProj.c + $(CC) $(CFLAGS) -o $@ ellipticProj.c diff --git a/libsecurity_cryptkit/libsecurity_cryptkit.xcodeproj/project.pbxproj b/libsecurity_cryptkit/libsecurity_cryptkit.xcodeproj/project.pbxproj new file mode 100644 index 00000000..990c57f3 --- /dev/null +++ b/libsecurity_cryptkit/libsecurity_cryptkit.xcodeproj/project.pbxproj @@ -0,0 +1,762 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 051A6865074BAFAF00A097D5 /* ckconfig.h in Headers */ = {isa = PBXBuildFile; fileRef = 7264323C00A8AF3B7F000001 /* ckconfig.h */; }; + 0536B29C074BC9A000F9F1AD /* byteRep.c in Sources */ = {isa = PBXBuildFile; fileRef = 7264328E00A8B0197F000001 /* byteRep.c */; }; + 0536B29D074BC9A100F9F1AD /* byteRep.h in Headers */ = {isa = PBXBuildFile; fileRef = 7264323800A8AF3B7F000001 /* byteRep.h */; }; + 0536B29E074BC9A200F9F1AD /* ckconfig.h in Headers */ = {isa = PBXBuildFile; fileRef = 7264323C00A8AF3B7F000001 /* ckconfig.h */; }; + 0536B29F074BC9A600F9F1AD /* ckMD5.c in Sources */ = {isa = PBXBuildFile; fileRef = 726432A700A8B0197F000001 /* ckMD5.c */; }; + 0536B2A0074BC9A700F9F1AD /* ckMD5.h in Headers */ = {isa = PBXBuildFile; fileRef = 7264325F00A8AF3B7F000001 /* ckMD5.h */; }; + 0536B2A1074BC9AA00F9F1AD /* ckSHA1.c in Sources */ = {isa = PBXBuildFile; fileRef = 726432AA00A8B0197F000001 /* ckSHA1.c */; }; + 0536B2A2074BC9AB00F9F1AD /* ckSHA1.h in Headers */ = {isa = PBXBuildFile; fileRef = 7264326200A8AF3B7F000001 /* ckSHA1.h */; }; + 0536B2A3074BC9AC00F9F1AD /* ckSHA1_priv.c in Sources */ = {isa = PBXBuildFile; fileRef = 726432A900A8B0197F000001 /* ckSHA1_priv.c */; }; + 0536B2A4074BC9AC00F9F1AD /* ckSHA1_priv.h in Headers */ = {isa = PBXBuildFile; fileRef = 7264326100A8AF3B7F000001 /* ckSHA1_priv.h */; }; + 0536B2A5074BC9AD00F9F1AD /* ckutilities.c in Sources */ = {isa = PBXBuildFile; fileRef = 7264329100A8B0197F000001 /* ckutilities.c */; }; + 0536B2A6074BC9AE00F9F1AD /* ckutilities.h in Headers */ = {isa = PBXBuildFile; fileRef = 7264323D00A8AF3B7F000001 /* ckutilities.h */; }; + 0536B2A7074BC9B000F9F1AD /* Crypt.h in Headers */ = {isa = PBXBuildFile; fileRef = 7264323E00A8AF3B7F000001 /* Crypt.h */; }; + 0536B2A8074BC9B200F9F1AD /* CryptKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 7264323F00A8AF3B7F000001 /* CryptKit.h */; }; + 0536B2A9074BC9B600F9F1AD /* CryptKitSA.h in Headers */ = {isa = PBXBuildFile; fileRef = 05B98785074A980600A63360 /* CryptKitSA.h */; }; + 0536B2AA074BC9B800F9F1AD /* curveParamData.h in Headers */ = {isa = PBXBuildFile; fileRef = 7264324100A8AF3B7F000001 /* curveParamData.h */; }; + 0536B2AB074BC9BA00F9F1AD /* curveParams.c in Sources */ = {isa = PBXBuildFile; fileRef = 7264329200A8B0197F000001 /* curveParams.c */; }; + 0536B2AC074BC9BB00F9F1AD /* curveParams.h in Headers */ = {isa = PBXBuildFile; fileRef = 7264324300A8AF3B7F000001 /* curveParams.h */; }; + 0536B2AD074BC9BD00F9F1AD /* elliptic.c in Sources */ = {isa = PBXBuildFile; fileRef = 7264329400A8B0197F000001 /* elliptic.c */; }; + 0536B2AE074BC9BF00F9F1AD /* elliptic.h in Headers */ = {isa = PBXBuildFile; fileRef = 7264324700A8AF3B7F000001 /* elliptic.h */; }; + 0536B2AF074BC9C200F9F1AD /* enc64.c in Sources */ = {isa = PBXBuildFile; fileRef = 7264329600A8B0197F000001 /* enc64.c */; }; + 0536B2B0074BC9C300F9F1AD /* enc64.h in Headers */ = {isa = PBXBuildFile; fileRef = 7264324A00A8AF3B7F000001 /* enc64.h */; }; + 0536B2B1074BC9C500F9F1AD /* falloc.c in Sources */ = {isa = PBXBuildFile; fileRef = 7264329800A8B0197F000001 /* falloc.c */; }; + 0536B2B2074BC9C500F9F1AD /* falloc.h in Headers */ = {isa = PBXBuildFile; fileRef = 7264324B00A8AF3B7F000001 /* falloc.h */; }; + 0536B2B3074BC9C900F9F1AD /* feeDebug.h in Headers */ = {isa = PBXBuildFile; fileRef = 7264324D00A8AF3B7F000001 /* feeDebug.h */; }; + 0536B2B4074BC9CB00F9F1AD /* feeDigitalSignature.c in Sources */ = {isa = PBXBuildFile; fileRef = 7264329C00A8B0197F000001 /* feeDigitalSignature.c */; }; + 0536B2B5074BC9CC00F9F1AD /* feeDigitalSignature.h in Headers */ = {isa = PBXBuildFile; fileRef = 7264324F00A8AF3B7F000001 /* feeDigitalSignature.h */; }; + 0536B2B6074BC9D000F9F1AD /* feeFunctions.h in Headers */ = {isa = PBXBuildFile; fileRef = 7264325300A8AF3B7F000001 /* feeFunctions.h */; }; + 0536B2B7074BC9D300F9F1AD /* feeHash.c in Sources */ = {isa = PBXBuildFile; fileRef = 726432A000A8B0197F000001 /* feeHash.c */; }; + 0536B2B8074BC9D400F9F1AD /* feeHash.h in Headers */ = {isa = PBXBuildFile; fileRef = 7264325400A8AF3B7F000001 /* feeHash.h */; }; + 0536B2B9074BC9D500F9F1AD /* feePublicKey.c in Sources */ = {isa = PBXBuildFile; fileRef = 726432A100A8B0197F000001 /* feePublicKey.c */; }; + 0536B2BA074BC9D600F9F1AD /* feePublicKey.h in Headers */ = {isa = PBXBuildFile; fileRef = 7264325500A8AF3B7F000001 /* feePublicKey.h */; }; + 0536B2BB074BC9D700F9F1AD /* feePublicKeyPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 7264325600A8AF3B7F000001 /* feePublicKeyPrivate.h */; }; + 0536B2BC074BC9D900F9F1AD /* giantIntegers.c in Sources */ = {isa = PBXBuildFile; fileRef = 726432A400A8B0197F000001 /* giantIntegers.c */; }; + 0536B2BD074BC9DA00F9F1AD /* giantIntegers.h in Headers */ = {isa = PBXBuildFile; fileRef = 7264325900A8AF3B7F000001 /* giantIntegers.h */; }; + 0536B2BE074BC9DC00F9F1AD /* feeRandom.h in Headers */ = {isa = PBXBuildFile; fileRef = 7264325700A8AF3B7F000001 /* feeRandom.h */; }; + 0536B2BF074BC9DD00F9F1AD /* feeRandom.c in Sources */ = {isa = PBXBuildFile; fileRef = 726432A200A8B0197F000001 /* feeRandom.c */; }; + 0536B2C0074BC9E100F9F1AD /* giantPort_Generic.h in Headers */ = {isa = PBXBuildFile; fileRef = 7264325A00A8AF3B7F000001 /* giantPort_Generic.h */; }; + 0536B2C1074BC9E200F9F1AD /* giantPort_PPC.c in Sources */ = {isa = PBXBuildFile; fileRef = 726432A600A8B0197F000001 /* giantPort_PPC.c */; }; + 0536B2C2074BC9E400F9F1AD /* giantPort_PPC.h in Headers */ = {isa = PBXBuildFile; fileRef = 7264325D00A8AF3B7F000001 /* giantPort_PPC.h */; }; + 0536B2C3074BC9E500F9F1AD /* giantPort_PPC_Gnu.h in Headers */ = {isa = PBXBuildFile; fileRef = 7264325C00A8AF3B7F000001 /* giantPort_PPC_Gnu.h */; }; + 0536B2C4074BC9E600F9F1AD /* giantPort_PPC_Gnu.s in Sources */ = {isa = PBXBuildFile; fileRef = 726432A500A8B0197F000001 /* giantPort_PPC_Gnu.s */; }; + 0536B2C5074BC9EA00F9F1AD /* giantPortCommon.h in Headers */ = {isa = PBXBuildFile; fileRef = 7264325E00A8AF3B7F000001 /* giantPortCommon.h */; }; + 0536B2C6074BC9ED00F9F1AD /* platform.c in Sources */ = {isa = PBXBuildFile; fileRef = 726432A800A8B0197F000001 /* platform.c */; }; + 0536B2C7074BC9EE00F9F1AD /* platform.h in Headers */ = {isa = PBXBuildFile; fileRef = 7264326000A8AF3B7F000001 /* platform.h */; }; + 054416BF074D5BAC00DD8A37 /* CipherFileDES.c in Sources */ = {isa = PBXBuildFile; fileRef = 054416BA074D5BAC00DD8A37 /* CipherFileDES.c */; }; + 054416C0074D5BAC00DD8A37 /* CipherFileDES.h in Headers */ = {isa = PBXBuildFile; fileRef = 054416BB074D5BAC00DD8A37 /* CipherFileDES.h */; }; + 054416C1074D5BAC00DD8A37 /* CipherFileFEED.c in Sources */ = {isa = PBXBuildFile; fileRef = 054416BC074D5BAC00DD8A37 /* CipherFileFEED.c */; }; + 054416C2074D5BAC00DD8A37 /* CipherFileFEED.h in Headers */ = {isa = PBXBuildFile; fileRef = 054416BD074D5BAC00DD8A37 /* CipherFileFEED.h */; }; + 054416C3074D5BAC00DD8A37 /* CipherFileTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = 054416BE074D5BAC00DD8A37 /* CipherFileTypes.h */; }; + 054416CC074D5BDA00DD8A37 /* feeCipherFile.c in Sources */ = {isa = PBXBuildFile; fileRef = 054416CA074D5BDA00DD8A37 /* feeCipherFile.c */; }; + 054416CD074D5BDA00DD8A37 /* feeCipherFileAtom.c in Sources */ = {isa = PBXBuildFile; fileRef = 054416CB074D5BDA00DD8A37 /* feeCipherFileAtom.c */; }; + 05B98735074A94E900A63360 /* byteRep.c in Sources */ = {isa = PBXBuildFile; fileRef = 7264328E00A8B0197F000001 /* byteRep.c */; }; + 05B98736074A94EA00A63360 /* byteRep.h in Headers */ = {isa = PBXBuildFile; fileRef = 7264323800A8AF3B7F000001 /* byteRep.h */; }; + 05B98737074A94EB00A63360 /* ckconfig.h in Headers */ = {isa = PBXBuildFile; fileRef = 7264323C00A8AF3B7F000001 /* ckconfig.h */; }; + 05B98738074A94EC00A63360 /* ckDES.c in Sources */ = {isa = PBXBuildFile; fileRef = 7264329300A8B0197F000001 /* ckDES.c */; }; + 05B98739074A94ED00A63360 /* ckDES.h in Headers */ = {isa = PBXBuildFile; fileRef = 7264324400A8AF3B7F000001 /* ckDES.h */; }; + 05B9873A074A94EE00A63360 /* ckMD5.c in Sources */ = {isa = PBXBuildFile; fileRef = 726432A700A8B0197F000001 /* ckMD5.c */; }; + 05B9873B074A94EF00A63360 /* ckMD5.h in Headers */ = {isa = PBXBuildFile; fileRef = 7264325F00A8AF3B7F000001 /* ckMD5.h */; }; + 05B9873D074A959B00A63360 /* ckSHA1.c in Sources */ = {isa = PBXBuildFile; fileRef = 726432AA00A8B0197F000001 /* ckSHA1.c */; }; + 05B9873E074A959C00A63360 /* ckSHA1.h in Headers */ = {isa = PBXBuildFile; fileRef = 7264326200A8AF3B7F000001 /* ckSHA1.h */; }; + 05B9873F074A959D00A63360 /* ckSHA1_priv.c in Sources */ = {isa = PBXBuildFile; fileRef = 726432A900A8B0197F000001 /* ckSHA1_priv.c */; }; + 05B98740074A959E00A63360 /* ckSHA1_priv.h in Headers */ = {isa = PBXBuildFile; fileRef = 7264326100A8AF3B7F000001 /* ckSHA1_priv.h */; }; + 05B98741074A959F00A63360 /* ckutilities.c in Sources */ = {isa = PBXBuildFile; fileRef = 7264329100A8B0197F000001 /* ckutilities.c */; }; + 05B98742074A95A000A63360 /* ckutilities.h in Headers */ = {isa = PBXBuildFile; fileRef = 7264323D00A8AF3B7F000001 /* ckutilities.h */; }; + 05B98743074A95A100A63360 /* Crypt.h in Headers */ = {isa = PBXBuildFile; fileRef = 7264323E00A8AF3B7F000001 /* Crypt.h */; }; + 05B98744074A95A200A63360 /* CryptKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 7264323F00A8AF3B7F000001 /* CryptKit.h */; }; + 05B98749074A95C700A63360 /* curveParamData.h in Headers */ = {isa = PBXBuildFile; fileRef = 7264324100A8AF3B7F000001 /* curveParamData.h */; }; + 05B9874A074A95C800A63360 /* curveParams.c in Sources */ = {isa = PBXBuildFile; fileRef = 7264329200A8B0197F000001 /* curveParams.c */; }; + 05B9874B074A95C900A63360 /* curveParams.h in Headers */ = {isa = PBXBuildFile; fileRef = 7264324300A8AF3B7F000001 /* curveParams.h */; }; + 05B9874D074A95D500A63360 /* ECDSA_Verify_Prefix.h in Headers */ = {isa = PBXBuildFile; fileRef = 7264324600A8AF3B7F000001 /* ECDSA_Verify_Prefix.h */; }; + 05B9874E074A95D600A63360 /* elliptic.c in Sources */ = {isa = PBXBuildFile; fileRef = 7264329400A8B0197F000001 /* elliptic.c */; }; + 05B9874F074A95D700A63360 /* elliptic.h in Headers */ = {isa = PBXBuildFile; fileRef = 7264324700A8AF3B7F000001 /* elliptic.h */; }; + 05B98750074A95D800A63360 /* ellipticMeasure.h in Headers */ = {isa = PBXBuildFile; fileRef = 7264324800A8AF3B7F000001 /* ellipticMeasure.h */; }; + 05B98751074A95D900A63360 /* ellipticProj.c in Sources */ = {isa = PBXBuildFile; fileRef = 7264329500A8B0197F000001 /* ellipticProj.c */; }; + 05B98752074A95DA00A63360 /* ellipticProj.h in Headers */ = {isa = PBXBuildFile; fileRef = 7264324900A8AF3B7F000001 /* ellipticProj.h */; }; + 05B98753074A95DB00A63360 /* enc64.c in Sources */ = {isa = PBXBuildFile; fileRef = 7264329600A8B0197F000001 /* enc64.c */; }; + 05B98754074A95DC00A63360 /* enc64.h in Headers */ = {isa = PBXBuildFile; fileRef = 7264324A00A8AF3B7F000001 /* enc64.h */; }; + 05B98755074A95DE00A63360 /* engineNSA127.c in Sources */ = {isa = PBXBuildFile; fileRef = 7264329700A8B0197F000001 /* engineNSA127.c */; }; + 05B98756074A95DF00A63360 /* falloc.c in Sources */ = {isa = PBXBuildFile; fileRef = 7264329800A8B0197F000001 /* falloc.c */; }; + 05B98757074A95E000A63360 /* falloc.h in Headers */ = {isa = PBXBuildFile; fileRef = 7264324B00A8AF3B7F000001 /* falloc.h */; }; + 05B98758074A95E100A63360 /* feeCipherFile.h in Headers */ = {isa = PBXBuildFile; fileRef = 7264324C00A8AF3B7F000001 /* feeCipherFile.h */; }; + 05B98759074A95E500A63360 /* feeDebug.h in Headers */ = {isa = PBXBuildFile; fileRef = 7264324D00A8AF3B7F000001 /* feeDebug.h */; }; + 05B9875A074A95E600A63360 /* feeDES.c in Sources */ = {isa = PBXBuildFile; fileRef = 7264329B00A8B0197F000001 /* feeDES.c */; }; + 05B9875B074A95E700A63360 /* feeDES.h in Headers */ = {isa = PBXBuildFile; fileRef = 7264324E00A8AF3B7F000001 /* feeDES.h */; }; + 05B9875C074A95E800A63360 /* feeDigitalSignature.c in Sources */ = {isa = PBXBuildFile; fileRef = 7264329C00A8B0197F000001 /* feeDigitalSignature.c */; }; + 05B9875D074A95E900A63360 /* feeDigitalSignature.h in Headers */ = {isa = PBXBuildFile; fileRef = 7264324F00A8AF3B7F000001 /* feeDigitalSignature.h */; }; + 05B9875E074A95EA00A63360 /* feeECDSA.c in Sources */ = {isa = PBXBuildFile; fileRef = 7264329D00A8B0197F000001 /* feeECDSA.c */; }; + 05B9875F074A95EB00A63360 /* feeECDSA.h in Headers */ = {isa = PBXBuildFile; fileRef = 7264325000A8AF3B7F000001 /* feeECDSA.h */; }; + 05B98760074A95EB00A63360 /* feeFEED.c in Sources */ = {isa = PBXBuildFile; fileRef = 7264329E00A8B0197F000001 /* feeFEED.c */; }; + 05B98761074A95ED00A63360 /* feeFEED.h in Headers */ = {isa = PBXBuildFile; fileRef = 7264325100A8AF3B7F000001 /* feeFEED.h */; }; + 05B98762074A95ED00A63360 /* feeFEEDExp.c in Sources */ = {isa = PBXBuildFile; fileRef = 7264329F00A8B0197F000001 /* feeFEEDExp.c */; }; + 05B98763074A95EE00A63360 /* feeFEEDExp.h in Headers */ = {isa = PBXBuildFile; fileRef = 7264325200A8AF3B7F000001 /* feeFEEDExp.h */; }; + 05B98764074A95EF00A63360 /* feeFunctions.h in Headers */ = {isa = PBXBuildFile; fileRef = 7264325300A8AF3B7F000001 /* feeFunctions.h */; }; + 05B98765074A95F000A63360 /* feeHash.c in Sources */ = {isa = PBXBuildFile; fileRef = 726432A000A8B0197F000001 /* feeHash.c */; }; + 05B98766074A95F300A63360 /* feeHash.h in Headers */ = {isa = PBXBuildFile; fileRef = 7264325400A8AF3B7F000001 /* feeHash.h */; }; + 05B98767074A95F400A63360 /* feePublicKey.c in Sources */ = {isa = PBXBuildFile; fileRef = 726432A100A8B0197F000001 /* feePublicKey.c */; }; + 05B98768074A95F500A63360 /* feePublicKey.h in Headers */ = {isa = PBXBuildFile; fileRef = 7264325500A8AF3B7F000001 /* feePublicKey.h */; }; + 05B98769074A95F600A63360 /* feePublicKeyPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 7264325600A8AF3B7F000001 /* feePublicKeyPrivate.h */; }; + 05B9876A074A95F700A63360 /* feeRandom.c in Sources */ = {isa = PBXBuildFile; fileRef = 726432A200A8B0197F000001 /* feeRandom.c */; }; + 05B9876B074A95F800A63360 /* feeRandom.h in Headers */ = {isa = PBXBuildFile; fileRef = 7264325700A8AF3B7F000001 /* feeRandom.h */; }; + 05B9876C074A95F900A63360 /* feeTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = 7264325800A8AF3B7F000001 /* feeTypes.h */; }; + 05B9876D074A95FA00A63360 /* giantIntegers.c in Sources */ = {isa = PBXBuildFile; fileRef = 726432A400A8B0197F000001 /* giantIntegers.c */; }; + 05B9876E074A95FB00A63360 /* giantIntegers.h in Headers */ = {isa = PBXBuildFile; fileRef = 7264325900A8AF3B7F000001 /* giantIntegers.h */; }; + 05B9876F074A95FC00A63360 /* giantPort_Generic.h in Headers */ = {isa = PBXBuildFile; fileRef = 7264325A00A8AF3B7F000001 /* giantPort_Generic.h */; }; + 05B98770074A95FD00A63360 /* giantPort_i486.h in Headers */ = {isa = PBXBuildFile; fileRef = 7264325B00A8AF3B7F000001 /* giantPort_i486.h */; }; + 05B98771074A95FE00A63360 /* giantPort_PPC.c in Sources */ = {isa = PBXBuildFile; fileRef = 726432A600A8B0197F000001 /* giantPort_PPC.c */; }; + 05B98772074A95FF00A63360 /* giantPort_PPC.h in Headers */ = {isa = PBXBuildFile; fileRef = 7264325D00A8AF3B7F000001 /* giantPort_PPC.h */; }; + 05B98773074A960000A63360 /* giantPort_PPC_Gnu.h in Headers */ = {isa = PBXBuildFile; fileRef = 7264325C00A8AF3B7F000001 /* giantPort_PPC_Gnu.h */; }; + 05B98774074A960200A63360 /* giantPort_PPC_Gnu.s in Sources */ = {isa = PBXBuildFile; fileRef = 726432A500A8B0197F000001 /* giantPort_PPC_Gnu.s */; }; + 05B98775074A960300A63360 /* giantPortCommon.h in Headers */ = {isa = PBXBuildFile; fileRef = 7264325E00A8AF3B7F000001 /* giantPortCommon.h */; }; + 05B98777074A960A00A63360 /* platform.c in Sources */ = {isa = PBXBuildFile; fileRef = 726432A800A8B0197F000001 /* platform.c */; }; + 05B98778074A960C00A63360 /* platform.h in Headers */ = {isa = PBXBuildFile; fileRef = 7264326000A8AF3B7F000001 /* platform.h */; }; + 05B98786074A980600A63360 /* CryptKitSA.h in Headers */ = {isa = PBXBuildFile; fileRef = 05B98785074A980600A63360 /* CryptKitSA.h */; }; + 05DBE17705CF09EE00CA0562 /* ckSHA1.h in Headers */ = {isa = PBXBuildFile; fileRef = 7264326200A8AF3B7F000001 /* ckSHA1.h */; }; + 05F64B6205D01ADA007D1D8E /* ckDES.h in Headers */ = {isa = PBXBuildFile; fileRef = 7264324400A8AF3B7F000001 /* ckDES.h */; }; + 05F64B7505D01C0D007D1D8E /* ckSHA1.c in Sources */ = {isa = PBXBuildFile; fileRef = 726432AA00A8B0197F000001 /* ckSHA1.c */; }; + 4C3EA7F1056AE8BE003C066F /* CryptKitAsn1.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C3EA7EE056AE8BE003C066F /* CryptKitAsn1.cpp */; }; + 4C3EA7F2056AE8BE003C066F /* CryptKitAsn1.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C3EA7EF056AE8BE003C066F /* CryptKitAsn1.h */; }; + 4C3EA7F3056AE8BE003C066F /* CryptKitDER.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C3EA7F0056AE8BE003C066F /* CryptKitDER.cpp */; }; + 726432AC00A8B0197F000001 /* byteRep.c in Sources */ = {isa = PBXBuildFile; fileRef = 7264328E00A8B0197F000001 /* byteRep.c */; }; + 726432AF00A8B0197F000001 /* ckutilities.c in Sources */ = {isa = PBXBuildFile; fileRef = 7264329100A8B0197F000001 /* ckutilities.c */; }; + 726432B000A8B0197F000001 /* curveParams.c in Sources */ = {isa = PBXBuildFile; fileRef = 7264329200A8B0197F000001 /* curveParams.c */; }; + 726432B200A8B0197F000001 /* elliptic.c in Sources */ = {isa = PBXBuildFile; fileRef = 7264329400A8B0197F000001 /* elliptic.c */; }; + 726432B300A8B0197F000001 /* ellipticProj.c in Sources */ = {isa = PBXBuildFile; fileRef = 7264329500A8B0197F000001 /* ellipticProj.c */; }; + 726432B400A8B0197F000001 /* enc64.c in Sources */ = {isa = PBXBuildFile; fileRef = 7264329600A8B0197F000001 /* enc64.c */; }; + 726432B500A8B0197F000001 /* engineNSA127.c in Sources */ = {isa = PBXBuildFile; fileRef = 7264329700A8B0197F000001 /* engineNSA127.c */; }; + 726432B600A8B0197F000001 /* falloc.c in Sources */ = {isa = PBXBuildFile; fileRef = 7264329800A8B0197F000001 /* falloc.c */; }; + 726432B900A8B0197F000001 /* feeDES.c in Sources */ = {isa = PBXBuildFile; fileRef = 7264329B00A8B0197F000001 /* feeDES.c */; }; + 726432BA00A8B0197F000001 /* feeDigitalSignature.c in Sources */ = {isa = PBXBuildFile; fileRef = 7264329C00A8B0197F000001 /* feeDigitalSignature.c */; }; + 726432BB00A8B0197F000001 /* feeECDSA.c in Sources */ = {isa = PBXBuildFile; fileRef = 7264329D00A8B0197F000001 /* feeECDSA.c */; }; + 726432BC00A8B0197F000001 /* feeFEED.c in Sources */ = {isa = PBXBuildFile; fileRef = 7264329E00A8B0197F000001 /* feeFEED.c */; }; + 726432BD00A8B0197F000001 /* feeFEEDExp.c in Sources */ = {isa = PBXBuildFile; fileRef = 7264329F00A8B0197F000001 /* feeFEEDExp.c */; }; + 726432BE00A8B0197F000001 /* feeHash.c in Sources */ = {isa = PBXBuildFile; fileRef = 726432A000A8B0197F000001 /* feeHash.c */; }; + 726432BF00A8B0197F000001 /* feePublicKey.c in Sources */ = {isa = PBXBuildFile; fileRef = 726432A100A8B0197F000001 /* feePublicKey.c */; }; + 726432C000A8B0197F000001 /* feeRandom.c in Sources */ = {isa = PBXBuildFile; fileRef = 726432A200A8B0197F000001 /* feeRandom.c */; }; + 726432C200A8B0197F000001 /* giantIntegers.c in Sources */ = {isa = PBXBuildFile; fileRef = 726432A400A8B0197F000001 /* giantIntegers.c */; }; + 726432C300A8B0197F000001 /* giantPort_PPC_Gnu.s in Sources */ = {isa = PBXBuildFile; fileRef = 726432A500A8B0197F000001 /* giantPort_PPC_Gnu.s */; }; + 726432C400A8B0197F000001 /* giantPort_PPC.c in Sources */ = {isa = PBXBuildFile; fileRef = 726432A600A8B0197F000001 /* giantPort_PPC.c */; }; + 726432C600A8B0197F000001 /* platform.c in Sources */ = {isa = PBXBuildFile; fileRef = 726432A800A8B0197F000001 /* platform.c */; }; + 9D3503C400C6EA9100A17CE7 /* HmacSha1Legacy.c in Sources */ = {isa = PBXBuildFile; fileRef = 9D3503C100C6EA9100A17CE7 /* HmacSha1Legacy.c */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 0535DCBE074A944D00805B04 /* libCryptKit.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libCryptKit.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 0536B295074BC91A00F9F1AD /* CryptKitSignature.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = CryptKitSignature.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 054416BA074D5BAC00DD8A37 /* CipherFileDES.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = CipherFileDES.c; path = lib/CipherFileDES.c; sourceTree = SOURCE_ROOT; }; + 054416BB074D5BAC00DD8A37 /* CipherFileDES.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = CipherFileDES.h; path = lib/CipherFileDES.h; sourceTree = SOURCE_ROOT; }; + 054416BC074D5BAC00DD8A37 /* CipherFileFEED.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = CipherFileFEED.c; path = lib/CipherFileFEED.c; sourceTree = SOURCE_ROOT; }; + 054416BD074D5BAC00DD8A37 /* CipherFileFEED.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = CipherFileFEED.h; path = lib/CipherFileFEED.h; sourceTree = SOURCE_ROOT; }; + 054416BE074D5BAC00DD8A37 /* CipherFileTypes.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = CipherFileTypes.h; path = lib/CipherFileTypes.h; sourceTree = SOURCE_ROOT; }; + 054416CA074D5BDA00DD8A37 /* feeCipherFile.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = feeCipherFile.c; path = lib/feeCipherFile.c; sourceTree = SOURCE_ROOT; }; + 054416CB074D5BDA00DD8A37 /* feeCipherFileAtom.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = feeCipherFileAtom.c; path = lib/feeCipherFileAtom.c; sourceTree = SOURCE_ROOT; }; + 05B98785074A980600A63360 /* CryptKitSA.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CryptKitSA.h; path = lib/CryptKitSA.h; sourceTree = SOURCE_ROOT; }; + 182BB1F8146EF983000BF1F3 /* base.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = base.xcconfig; sourceTree = ""; }; + 182BB1F9146EF983000BF1F3 /* debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = debug.xcconfig; sourceTree = ""; }; + 182BB1FA146EF983000BF1F3 /* lib.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = lib.xcconfig; sourceTree = ""; }; + 182BB1FB146EF983000BF1F3 /* release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = release.xcconfig; sourceTree = ""; }; + 4C3EA7EE056AE8BE003C066F /* CryptKitAsn1.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = CryptKitAsn1.cpp; sourceTree = ""; }; + 4C3EA7EF056AE8BE003C066F /* CryptKitAsn1.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = CryptKitAsn1.h; sourceTree = ""; }; + 4C3EA7F0056AE8BE003C066F /* CryptKitDER.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = CryptKitDER.cpp; sourceTree = ""; }; + 7264321600A8AD0A7F000001 /* libsecurity_cryptkit.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libsecurity_cryptkit.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 7264323800A8AF3B7F000001 /* byteRep.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = byteRep.h; sourceTree = ""; }; + 7264323C00A8AF3B7F000001 /* ckconfig.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ckconfig.h; sourceTree = ""; }; + 7264323D00A8AF3B7F000001 /* ckutilities.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ckutilities.h; sourceTree = ""; }; + 7264323E00A8AF3B7F000001 /* Crypt.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Crypt.h; sourceTree = ""; }; + 7264323F00A8AF3B7F000001 /* CryptKit.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = CryptKit.h; sourceTree = ""; }; + 7264324000A8AF3B7F000001 /* CryptKitDER.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = CryptKitDER.h; sourceTree = ""; }; + 7264324100A8AF3B7F000001 /* curveParamData.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = curveParamData.h; sourceTree = ""; }; + 7264324200A8AF3B7F000001 /* curveParamDataOld.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = curveParamDataOld.h; sourceTree = ""; }; + 7264324300A8AF3B7F000001 /* curveParams.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = curveParams.h; sourceTree = ""; }; + 7264324400A8AF3B7F000001 /* ckDES.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ckDES.h; sourceTree = ""; }; + 7264324500A8AF3B7F000001 /* ECDSA_Profile.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ECDSA_Profile.h; sourceTree = ""; }; + 7264324600A8AF3B7F000001 /* ECDSA_Verify_Prefix.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ECDSA_Verify_Prefix.h; sourceTree = ""; }; + 7264324700A8AF3B7F000001 /* elliptic.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = elliptic.h; sourceTree = ""; }; + 7264324800A8AF3B7F000001 /* ellipticMeasure.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ellipticMeasure.h; sourceTree = ""; }; + 7264324900A8AF3B7F000001 /* ellipticProj.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ellipticProj.h; sourceTree = ""; }; + 7264324A00A8AF3B7F000001 /* enc64.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = enc64.h; sourceTree = ""; }; + 7264324B00A8AF3B7F000001 /* falloc.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = falloc.h; sourceTree = ""; }; + 7264324C00A8AF3B7F000001 /* feeCipherFile.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = feeCipherFile.h; sourceTree = ""; }; + 7264324D00A8AF3B7F000001 /* feeDebug.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = feeDebug.h; sourceTree = ""; }; + 7264324E00A8AF3B7F000001 /* feeDES.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = feeDES.h; sourceTree = ""; }; + 7264324F00A8AF3B7F000001 /* feeDigitalSignature.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = feeDigitalSignature.h; sourceTree = ""; }; + 7264325000A8AF3B7F000001 /* feeECDSA.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = feeECDSA.h; sourceTree = ""; }; + 7264325100A8AF3B7F000001 /* feeFEED.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = feeFEED.h; sourceTree = ""; }; + 7264325200A8AF3B7F000001 /* feeFEEDExp.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = feeFEEDExp.h; sourceTree = ""; }; + 7264325300A8AF3B7F000001 /* feeFunctions.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = feeFunctions.h; sourceTree = ""; }; + 7264325400A8AF3B7F000001 /* feeHash.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = feeHash.h; sourceTree = ""; }; + 7264325500A8AF3B7F000001 /* feePublicKey.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = feePublicKey.h; sourceTree = ""; }; + 7264325600A8AF3B7F000001 /* feePublicKeyPrivate.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = feePublicKeyPrivate.h; sourceTree = ""; }; + 7264325700A8AF3B7F000001 /* feeRandom.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = feeRandom.h; sourceTree = ""; }; + 7264325800A8AF3B7F000001 /* feeTypes.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = feeTypes.h; sourceTree = ""; }; + 7264325900A8AF3B7F000001 /* giantIntegers.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = giantIntegers.h; sourceTree = ""; }; + 7264325A00A8AF3B7F000001 /* giantPort_Generic.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = giantPort_Generic.h; sourceTree = ""; }; + 7264325B00A8AF3B7F000001 /* giantPort_i486.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = giantPort_i486.h; sourceTree = ""; }; + 7264325C00A8AF3B7F000001 /* giantPort_PPC_Gnu.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = giantPort_PPC_Gnu.h; sourceTree = ""; }; + 7264325D00A8AF3B7F000001 /* giantPort_PPC.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = giantPort_PPC.h; sourceTree = ""; }; + 7264325E00A8AF3B7F000001 /* giantPortCommon.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = giantPortCommon.h; sourceTree = ""; }; + 7264325F00A8AF3B7F000001 /* ckMD5.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ckMD5.h; sourceTree = ""; }; + 7264326000A8AF3B7F000001 /* platform.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = platform.h; sourceTree = ""; }; + 7264326100A8AF3B7F000001 /* ckSHA1_priv.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ckSHA1_priv.h; sourceTree = ""; }; + 7264326200A8AF3B7F000001 /* ckSHA1.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ckSHA1.h; sourceTree = ""; }; + 7264328E00A8B0197F000001 /* byteRep.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = byteRep.c; sourceTree = ""; }; + 7264329100A8B0197F000001 /* ckutilities.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = ckutilities.c; sourceTree = ""; }; + 7264329200A8B0197F000001 /* curveParams.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = curveParams.c; sourceTree = ""; }; + 7264329300A8B0197F000001 /* ckDES.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = ckDES.c; sourceTree = ""; }; + 7264329400A8B0197F000001 /* elliptic.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = elliptic.c; sourceTree = ""; }; + 7264329500A8B0197F000001 /* ellipticProj.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = ellipticProj.c; sourceTree = ""; }; + 7264329600A8B0197F000001 /* enc64.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = enc64.c; sourceTree = ""; }; + 7264329700A8B0197F000001 /* engineNSA127.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = engineNSA127.c; sourceTree = ""; }; + 7264329800A8B0197F000001 /* falloc.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = falloc.c; sourceTree = ""; }; + 7264329B00A8B0197F000001 /* feeDES.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = feeDES.c; sourceTree = ""; }; + 7264329C00A8B0197F000001 /* feeDigitalSignature.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = feeDigitalSignature.c; sourceTree = ""; }; + 7264329D00A8B0197F000001 /* feeECDSA.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = feeECDSA.c; sourceTree = ""; }; + 7264329E00A8B0197F000001 /* feeFEED.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = feeFEED.c; sourceTree = ""; }; + 7264329F00A8B0197F000001 /* feeFEEDExp.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = feeFEEDExp.c; sourceTree = ""; }; + 726432A000A8B0197F000001 /* feeHash.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = feeHash.c; sourceTree = ""; }; + 726432A100A8B0197F000001 /* feePublicKey.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = feePublicKey.c; sourceTree = ""; }; + 726432A200A8B0197F000001 /* feeRandom.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = feeRandom.c; sourceTree = ""; }; + 726432A400A8B0197F000001 /* giantIntegers.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = giantIntegers.c; sourceTree = ""; }; + 726432A500A8B0197F000001 /* giantPort_PPC_Gnu.s */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.asm; path = giantPort_PPC_Gnu.s; sourceTree = ""; }; + 726432A600A8B0197F000001 /* giantPort_PPC.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = giantPort_PPC.c; sourceTree = ""; }; + 726432A700A8B0197F000001 /* ckMD5.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = ckMD5.c; sourceTree = ""; }; + 726432A800A8B0197F000001 /* platform.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = platform.c; sourceTree = ""; }; + 726432A900A8B0197F000001 /* ckSHA1_priv.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = ckSHA1_priv.c; sourceTree = ""; }; + 726432AA00A8B0197F000001 /* ckSHA1.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = ckSHA1.c; sourceTree = ""; }; + 9D3503C100C6EA9100A17CE7 /* HmacSha1Legacy.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = HmacSha1Legacy.c; sourceTree = ""; }; + 9D3503C200C6EA9100A17CE7 /* HmacSha1Legacy.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = HmacSha1Legacy.h; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 0535DCBC074A944D00805B04 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 0536B293074BC91A00F9F1AD /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 7264322B00A8AD0A7F000001 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 0FD07C9EFE8A174411CD283A = { + isa = PBXGroup; + children = ( + 7264321100A8ACCB7F000001 /* lib */, + 182BB1F7146EF983000BF1F3 /* config */, + 31DBE9B3FEEEE8F611CD283A /* Products */, + ); + sourceTree = ""; + }; + 182BB1F7146EF983000BF1F3 /* config */ = { + isa = PBXGroup; + children = ( + 182BB1F8146EF983000BF1F3 /* base.xcconfig */, + 182BB1F9146EF983000BF1F3 /* debug.xcconfig */, + 182BB1FA146EF983000BF1F3 /* lib.xcconfig */, + 182BB1FB146EF983000BF1F3 /* release.xcconfig */, + ); + name = config; + path = ../config; + sourceTree = ""; + }; + 31DBE9B3FEEEE8F611CD283A /* Products */ = { + isa = PBXGroup; + children = ( + 7264321600A8AD0A7F000001 /* libsecurity_cryptkit.a */, + 0535DCBE074A944D00805B04 /* libCryptKit.a */, + 0536B295074BC91A00F9F1AD /* CryptKitSignature.a */, + ); + name = Products; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 7264321100A8ACCB7F000001 /* lib */ = { + isa = PBXGroup; + children = ( + 054416CA074D5BDA00DD8A37 /* feeCipherFile.c */, + 054416CB074D5BDA00DD8A37 /* feeCipherFileAtom.c */, + 7264328E00A8B0197F000001 /* byteRep.c */, + 7264323800A8AF3B7F000001 /* byteRep.h */, + 054416BA074D5BAC00DD8A37 /* CipherFileDES.c */, + 054416BB074D5BAC00DD8A37 /* CipherFileDES.h */, + 054416BC074D5BAC00DD8A37 /* CipherFileFEED.c */, + 054416BD074D5BAC00DD8A37 /* CipherFileFEED.h */, + 054416BE074D5BAC00DD8A37 /* CipherFileTypes.h */, + 7264323C00A8AF3B7F000001 /* ckconfig.h */, + 7264329300A8B0197F000001 /* ckDES.c */, + 7264324400A8AF3B7F000001 /* ckDES.h */, + 726432A700A8B0197F000001 /* ckMD5.c */, + 7264325F00A8AF3B7F000001 /* ckMD5.h */, + 726432AA00A8B0197F000001 /* ckSHA1.c */, + 7264326200A8AF3B7F000001 /* ckSHA1.h */, + 726432A900A8B0197F000001 /* ckSHA1_priv.c */, + 7264326100A8AF3B7F000001 /* ckSHA1_priv.h */, + 7264329100A8B0197F000001 /* ckutilities.c */, + 7264323D00A8AF3B7F000001 /* ckutilities.h */, + 7264323E00A8AF3B7F000001 /* Crypt.h */, + 05B98785074A980600A63360 /* CryptKitSA.h */, + 7264323F00A8AF3B7F000001 /* CryptKit.h */, + 4C3EA7EE056AE8BE003C066F /* CryptKitAsn1.cpp */, + 4C3EA7EF056AE8BE003C066F /* CryptKitAsn1.h */, + 4C3EA7F0056AE8BE003C066F /* CryptKitDER.cpp */, + 7264324000A8AF3B7F000001 /* CryptKitDER.h */, + 7264324100A8AF3B7F000001 /* curveParamData.h */, + 7264324200A8AF3B7F000001 /* curveParamDataOld.h */, + 7264329200A8B0197F000001 /* curveParams.c */, + 7264324300A8AF3B7F000001 /* curveParams.h */, + 7264324500A8AF3B7F000001 /* ECDSA_Profile.h */, + 7264324600A8AF3B7F000001 /* ECDSA_Verify_Prefix.h */, + 7264329400A8B0197F000001 /* elliptic.c */, + 7264324700A8AF3B7F000001 /* elliptic.h */, + 7264324800A8AF3B7F000001 /* ellipticMeasure.h */, + 7264329500A8B0197F000001 /* ellipticProj.c */, + 7264324900A8AF3B7F000001 /* ellipticProj.h */, + 7264329600A8B0197F000001 /* enc64.c */, + 7264324A00A8AF3B7F000001 /* enc64.h */, + 7264329700A8B0197F000001 /* engineNSA127.c */, + 7264329800A8B0197F000001 /* falloc.c */, + 7264324B00A8AF3B7F000001 /* falloc.h */, + 7264324C00A8AF3B7F000001 /* feeCipherFile.h */, + 7264324D00A8AF3B7F000001 /* feeDebug.h */, + 7264329B00A8B0197F000001 /* feeDES.c */, + 7264324E00A8AF3B7F000001 /* feeDES.h */, + 7264329C00A8B0197F000001 /* feeDigitalSignature.c */, + 7264324F00A8AF3B7F000001 /* feeDigitalSignature.h */, + 7264329D00A8B0197F000001 /* feeECDSA.c */, + 7264325000A8AF3B7F000001 /* feeECDSA.h */, + 7264329E00A8B0197F000001 /* feeFEED.c */, + 7264325100A8AF3B7F000001 /* feeFEED.h */, + 7264329F00A8B0197F000001 /* feeFEEDExp.c */, + 7264325200A8AF3B7F000001 /* feeFEEDExp.h */, + 7264325300A8AF3B7F000001 /* feeFunctions.h */, + 726432A000A8B0197F000001 /* feeHash.c */, + 7264325400A8AF3B7F000001 /* feeHash.h */, + 726432A100A8B0197F000001 /* feePublicKey.c */, + 7264325500A8AF3B7F000001 /* feePublicKey.h */, + 7264325600A8AF3B7F000001 /* feePublicKeyPrivate.h */, + 726432A200A8B0197F000001 /* feeRandom.c */, + 7264325700A8AF3B7F000001 /* feeRandom.h */, + 7264325800A8AF3B7F000001 /* feeTypes.h */, + 726432A400A8B0197F000001 /* giantIntegers.c */, + 7264325900A8AF3B7F000001 /* giantIntegers.h */, + 7264325A00A8AF3B7F000001 /* giantPort_Generic.h */, + 7264325B00A8AF3B7F000001 /* giantPort_i486.h */, + 726432A600A8B0197F000001 /* giantPort_PPC.c */, + 7264325D00A8AF3B7F000001 /* giantPort_PPC.h */, + 7264325C00A8AF3B7F000001 /* giantPort_PPC_Gnu.h */, + 726432A500A8B0197F000001 /* giantPort_PPC_Gnu.s */, + 7264325E00A8AF3B7F000001 /* giantPortCommon.h */, + 9D3503C100C6EA9100A17CE7 /* HmacSha1Legacy.c */, + 9D3503C200C6EA9100A17CE7 /* HmacSha1Legacy.h */, + 726432A800A8B0197F000001 /* platform.c */, + 7264326000A8AF3B7F000001 /* platform.h */, + ); + path = lib; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 0535DCBA074A944D00805B04 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 05B98736074A94EA00A63360 /* byteRep.h in Headers */, + 05B98737074A94EB00A63360 /* ckconfig.h in Headers */, + 05B98739074A94ED00A63360 /* ckDES.h in Headers */, + 05B9873B074A94EF00A63360 /* ckMD5.h in Headers */, + 05B9873E074A959C00A63360 /* ckSHA1.h in Headers */, + 05B98740074A959E00A63360 /* ckSHA1_priv.h in Headers */, + 05B98742074A95A000A63360 /* ckutilities.h in Headers */, + 05B98743074A95A100A63360 /* Crypt.h in Headers */, + 05B98744074A95A200A63360 /* CryptKit.h in Headers */, + 05B98749074A95C700A63360 /* curveParamData.h in Headers */, + 05B9874B074A95C900A63360 /* curveParams.h in Headers */, + 05B9874D074A95D500A63360 /* ECDSA_Verify_Prefix.h in Headers */, + 05B9874F074A95D700A63360 /* elliptic.h in Headers */, + 05B98750074A95D800A63360 /* ellipticMeasure.h in Headers */, + 05B98752074A95DA00A63360 /* ellipticProj.h in Headers */, + 05B98754074A95DC00A63360 /* enc64.h in Headers */, + 05B98757074A95E000A63360 /* falloc.h in Headers */, + 05B98758074A95E100A63360 /* feeCipherFile.h in Headers */, + 05B98759074A95E500A63360 /* feeDebug.h in Headers */, + 05B9875B074A95E700A63360 /* feeDES.h in Headers */, + 05B9875D074A95E900A63360 /* feeDigitalSignature.h in Headers */, + 05B9875F074A95EB00A63360 /* feeECDSA.h in Headers */, + 05B98761074A95ED00A63360 /* feeFEED.h in Headers */, + 05B98763074A95EE00A63360 /* feeFEEDExp.h in Headers */, + 05B98764074A95EF00A63360 /* feeFunctions.h in Headers */, + 05B98766074A95F300A63360 /* feeHash.h in Headers */, + 05B98768074A95F500A63360 /* feePublicKey.h in Headers */, + 05B98769074A95F600A63360 /* feePublicKeyPrivate.h in Headers */, + 05B9876B074A95F800A63360 /* feeRandom.h in Headers */, + 05B9876C074A95F900A63360 /* feeTypes.h in Headers */, + 05B9876E074A95FB00A63360 /* giantIntegers.h in Headers */, + 05B9876F074A95FC00A63360 /* giantPort_Generic.h in Headers */, + 05B98770074A95FD00A63360 /* giantPort_i486.h in Headers */, + 05B98772074A95FF00A63360 /* giantPort_PPC.h in Headers */, + 05B98773074A960000A63360 /* giantPort_PPC_Gnu.h in Headers */, + 05B98775074A960300A63360 /* giantPortCommon.h in Headers */, + 05B98778074A960C00A63360 /* platform.h in Headers */, + 05B98786074A980600A63360 /* CryptKitSA.h in Headers */, + 054416C0074D5BAC00DD8A37 /* CipherFileDES.h in Headers */, + 054416C2074D5BAC00DD8A37 /* CipherFileFEED.h in Headers */, + 054416C3074D5BAC00DD8A37 /* CipherFileTypes.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 0536B291074BC91A00F9F1AD /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 0536B29D074BC9A100F9F1AD /* byteRep.h in Headers */, + 0536B29E074BC9A200F9F1AD /* ckconfig.h in Headers */, + 0536B2A0074BC9A700F9F1AD /* ckMD5.h in Headers */, + 0536B2A2074BC9AB00F9F1AD /* ckSHA1.h in Headers */, + 0536B2A4074BC9AC00F9F1AD /* ckSHA1_priv.h in Headers */, + 0536B2A6074BC9AE00F9F1AD /* ckutilities.h in Headers */, + 0536B2A7074BC9B000F9F1AD /* Crypt.h in Headers */, + 0536B2A8074BC9B200F9F1AD /* CryptKit.h in Headers */, + 0536B2A9074BC9B600F9F1AD /* CryptKitSA.h in Headers */, + 0536B2AA074BC9B800F9F1AD /* curveParamData.h in Headers */, + 0536B2AC074BC9BB00F9F1AD /* curveParams.h in Headers */, + 0536B2AE074BC9BF00F9F1AD /* elliptic.h in Headers */, + 0536B2B0074BC9C300F9F1AD /* enc64.h in Headers */, + 0536B2B2074BC9C500F9F1AD /* falloc.h in Headers */, + 0536B2B3074BC9C900F9F1AD /* feeDebug.h in Headers */, + 0536B2B5074BC9CC00F9F1AD /* feeDigitalSignature.h in Headers */, + 0536B2B6074BC9D000F9F1AD /* feeFunctions.h in Headers */, + 0536B2B8074BC9D400F9F1AD /* feeHash.h in Headers */, + 0536B2BA074BC9D600F9F1AD /* feePublicKey.h in Headers */, + 0536B2BB074BC9D700F9F1AD /* feePublicKeyPrivate.h in Headers */, + 0536B2BD074BC9DA00F9F1AD /* giantIntegers.h in Headers */, + 0536B2BE074BC9DC00F9F1AD /* feeRandom.h in Headers */, + 0536B2C0074BC9E100F9F1AD /* giantPort_Generic.h in Headers */, + 0536B2C2074BC9E400F9F1AD /* giantPort_PPC.h in Headers */, + 0536B2C3074BC9E500F9F1AD /* giantPort_PPC_Gnu.h in Headers */, + 0536B2C5074BC9EA00F9F1AD /* giantPortCommon.h in Headers */, + 0536B2C7074BC9EE00F9F1AD /* platform.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 7264322900A8AD0A7F000001 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 4C3EA7F2056AE8BE003C066F /* CryptKitAsn1.h in Headers */, + 05DBE17705CF09EE00CA0562 /* ckSHA1.h in Headers */, + 05F64B6205D01ADA007D1D8E /* ckDES.h in Headers */, + 051A6865074BAFAF00A097D5 /* ckconfig.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 0535DCBD074A944D00805B04 /* libCryptKit */ = { + isa = PBXNativeTarget; + buildConfigurationList = C27AD3320987FCDE001272E0 /* Build configuration list for PBXNativeTarget "libCryptKit" */; + buildPhases = ( + 0535DCBA074A944D00805B04 /* Headers */, + 0535DCBB074A944D00805B04 /* Sources */, + 0535DCBC074A944D00805B04 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = libCryptKit; + productName = libCryptKit; + productReference = 0535DCBE074A944D00805B04 /* libCryptKit.a */; + productType = "com.apple.product-type.library.static"; + }; + 0536B294074BC91A00F9F1AD /* CryptKitSignature */ = { + isa = PBXNativeTarget; + buildConfigurationList = C27AD3360987FCDE001272E0 /* Build configuration list for PBXNativeTarget "CryptKitSignature" */; + buildPhases = ( + 0536B291074BC91A00F9F1AD /* Headers */, + 0536B292074BC91A00F9F1AD /* Sources */, + 0536B293074BC91A00F9F1AD /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = CryptKitSignature; + productName = CryptKitSignature; + productReference = 0536B295074BC91A00F9F1AD /* CryptKitSignature.a */; + productType = "com.apple.product-type.library.static"; + }; + 7264322800A8AD0A7F000001 /* libsecurity_cryptkit */ = { + isa = PBXNativeTarget; + buildConfigurationList = C27AD32E0987FCDE001272E0 /* Build configuration list for PBXNativeTarget "libsecurity_cryptkit" */; + buildPhases = ( + 7264322900A8AD0A7F000001 /* Headers */, + 7264322A00A8AD0A7F000001 /* Sources */, + 7264322B00A8AD0A7F000001 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = libsecurity_cryptkit; + productInstallPath = /usr/local/lib; + productName = CryptKit; + productReference = 7264321600A8AD0A7F000001 /* libsecurity_cryptkit.a */; + productType = "com.apple.product-type.library.static"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 0FD07C9DFE8A174411CD283A /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0420; + }; + buildConfigurationList = C27AD33A0987FCDE001272E0 /* Build configuration list for PBXProject "libsecurity_cryptkit" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 1; + knownRegions = ( + en, + ); + mainGroup = 0FD07C9EFE8A174411CD283A; + productRefGroup = 0FD07C9EFE8A174411CD283A; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 7264322800A8AD0A7F000001 /* libsecurity_cryptkit */, + 0535DCBD074A944D00805B04 /* libCryptKit */, + 0536B294074BC91A00F9F1AD /* CryptKitSignature */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXSourcesBuildPhase section */ + 0535DCBB074A944D00805B04 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 05B98735074A94E900A63360 /* byteRep.c in Sources */, + 05B98738074A94EC00A63360 /* ckDES.c in Sources */, + 05B9873A074A94EE00A63360 /* ckMD5.c in Sources */, + 05B9873D074A959B00A63360 /* ckSHA1.c in Sources */, + 05B9873F074A959D00A63360 /* ckSHA1_priv.c in Sources */, + 05B98741074A959F00A63360 /* ckutilities.c in Sources */, + 05B9874A074A95C800A63360 /* curveParams.c in Sources */, + 05B9874E074A95D600A63360 /* elliptic.c in Sources */, + 05B98751074A95D900A63360 /* ellipticProj.c in Sources */, + 05B98753074A95DB00A63360 /* enc64.c in Sources */, + 05B98755074A95DE00A63360 /* engineNSA127.c in Sources */, + 05B98756074A95DF00A63360 /* falloc.c in Sources */, + 05B9875A074A95E600A63360 /* feeDES.c in Sources */, + 05B9875C074A95E800A63360 /* feeDigitalSignature.c in Sources */, + 05B9875E074A95EA00A63360 /* feeECDSA.c in Sources */, + 05B98760074A95EB00A63360 /* feeFEED.c in Sources */, + 05B98762074A95ED00A63360 /* feeFEEDExp.c in Sources */, + 05B98765074A95F000A63360 /* feeHash.c in Sources */, + 05B98767074A95F400A63360 /* feePublicKey.c in Sources */, + 05B9876A074A95F700A63360 /* feeRandom.c in Sources */, + 05B9876D074A95FA00A63360 /* giantIntegers.c in Sources */, + 05B98771074A95FE00A63360 /* giantPort_PPC.c in Sources */, + 05B98774074A960200A63360 /* giantPort_PPC_Gnu.s in Sources */, + 05B98777074A960A00A63360 /* platform.c in Sources */, + 054416BF074D5BAC00DD8A37 /* CipherFileDES.c in Sources */, + 054416C1074D5BAC00DD8A37 /* CipherFileFEED.c in Sources */, + 054416CC074D5BDA00DD8A37 /* feeCipherFile.c in Sources */, + 054416CD074D5BDA00DD8A37 /* feeCipherFileAtom.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 0536B292074BC91A00F9F1AD /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 0536B29C074BC9A000F9F1AD /* byteRep.c in Sources */, + 0536B29F074BC9A600F9F1AD /* ckMD5.c in Sources */, + 0536B2A1074BC9AA00F9F1AD /* ckSHA1.c in Sources */, + 0536B2A3074BC9AC00F9F1AD /* ckSHA1_priv.c in Sources */, + 0536B2A5074BC9AD00F9F1AD /* ckutilities.c in Sources */, + 0536B2AB074BC9BA00F9F1AD /* curveParams.c in Sources */, + 0536B2AD074BC9BD00F9F1AD /* elliptic.c in Sources */, + 0536B2AF074BC9C200F9F1AD /* enc64.c in Sources */, + 0536B2B1074BC9C500F9F1AD /* falloc.c in Sources */, + 0536B2B4074BC9CB00F9F1AD /* feeDigitalSignature.c in Sources */, + 0536B2B7074BC9D300F9F1AD /* feeHash.c in Sources */, + 0536B2B9074BC9D500F9F1AD /* feePublicKey.c in Sources */, + 0536B2BC074BC9D900F9F1AD /* giantIntegers.c in Sources */, + 0536B2BF074BC9DD00F9F1AD /* feeRandom.c in Sources */, + 0536B2C1074BC9E200F9F1AD /* giantPort_PPC.c in Sources */, + 0536B2C4074BC9E600F9F1AD /* giantPort_PPC_Gnu.s in Sources */, + 0536B2C6074BC9ED00F9F1AD /* platform.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 7264322A00A8AD0A7F000001 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 726432AC00A8B0197F000001 /* byteRep.c in Sources */, + 726432AF00A8B0197F000001 /* ckutilities.c in Sources */, + 4C3EA7F1056AE8BE003C066F /* CryptKitAsn1.cpp in Sources */, + 4C3EA7F3056AE8BE003C066F /* CryptKitDER.cpp in Sources */, + 726432B000A8B0197F000001 /* curveParams.c in Sources */, + 726432B200A8B0197F000001 /* elliptic.c in Sources */, + 726432B300A8B0197F000001 /* ellipticProj.c in Sources */, + 726432B400A8B0197F000001 /* enc64.c in Sources */, + 726432B500A8B0197F000001 /* engineNSA127.c in Sources */, + 726432B600A8B0197F000001 /* falloc.c in Sources */, + 726432B900A8B0197F000001 /* feeDES.c in Sources */, + 726432BA00A8B0197F000001 /* feeDigitalSignature.c in Sources */, + 726432BB00A8B0197F000001 /* feeECDSA.c in Sources */, + 726432BC00A8B0197F000001 /* feeFEED.c in Sources */, + 726432BD00A8B0197F000001 /* feeFEEDExp.c in Sources */, + 726432BE00A8B0197F000001 /* feeHash.c in Sources */, + 726432BF00A8B0197F000001 /* feePublicKey.c in Sources */, + 726432C000A8B0197F000001 /* feeRandom.c in Sources */, + 726432C200A8B0197F000001 /* giantIntegers.c in Sources */, + 726432C400A8B0197F000001 /* giantPort_PPC.c in Sources */, + 726432C300A8B0197F000001 /* giantPort_PPC_Gnu.s in Sources */, + 9D3503C400C6EA9100A17CE7 /* HmacSha1Legacy.c in Sources */, + 726432C600A8B0197F000001 /* platform.c in Sources */, + 05F64B7505D01C0D007D1D8E /* ckSHA1.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + C27AD32F0987FCDE001272E0 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 182BB1F9146EF983000BF1F3 /* debug.xcconfig */; + buildSettings = { + OTHER_CFLAGS = ( + "$(inherited)", + "-DCK_SECURITY_BUILD", + ); + }; + name = Debug; + }; + C27AD3310987FCDE001272E0 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 182BB1FB146EF983000BF1F3 /* release.xcconfig */; + buildSettings = { + OTHER_CFLAGS = ( + "$(inherited)", + "-DCK_SECURITY_BUILD", + ); + }; + name = Release; + }; + C27AD3330987FCDE001272E0 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 182BB1F9146EF983000BF1F3 /* debug.xcconfig */; + buildSettings = { + OTHER_CFLAGS = "-DCK_STANDALONE_BUILD"; + }; + name = Debug; + }; + C27AD3350987FCDE001272E0 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 182BB1FB146EF983000BF1F3 /* release.xcconfig */; + buildSettings = { + OTHER_CFLAGS = "-DCK_STANDALONE_BUILD"; + }; + name = Release; + }; + C27AD3370987FCDE001272E0 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 182BB1F9146EF983000BF1F3 /* debug.xcconfig */; + buildSettings = { + OTHER_CFLAGS = "-DCK_MINIMUM_SIG_BUILD"; + }; + name = Debug; + }; + C27AD3390987FCDE001272E0 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 182BB1FB146EF983000BF1F3 /* release.xcconfig */; + buildSettings = { + OTHER_CFLAGS = "-DCK_MINIMUM_SIG_BUILD"; + }; + name = Release; + }; + C27AD33B0987FCDE001272E0 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 182BB1FA146EF983000BF1F3 /* lib.xcconfig */; + buildSettings = { + }; + name = Debug; + }; + C27AD33D0987FCDE001272E0 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 182BB1FA146EF983000BF1F3 /* lib.xcconfig */; + buildSettings = { + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + C27AD32E0987FCDE001272E0 /* Build configuration list for PBXNativeTarget "libsecurity_cryptkit" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C27AD32F0987FCDE001272E0 /* Debug */, + C27AD3310987FCDE001272E0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C27AD3320987FCDE001272E0 /* Build configuration list for PBXNativeTarget "libCryptKit" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C27AD3330987FCDE001272E0 /* Debug */, + C27AD3350987FCDE001272E0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C27AD3360987FCDE001272E0 /* Build configuration list for PBXNativeTarget "CryptKitSignature" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C27AD3370987FCDE001272E0 /* Debug */, + C27AD3390987FCDE001272E0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C27AD33A0987FCDE001272E0 /* Build configuration list for PBXProject "libsecurity_cryptkit" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C27AD33B0987FCDE001272E0 /* Debug */, + C27AD33D0987FCDE001272E0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 0FD07C9DFE8A174411CD283A /* Project object */; +} diff --git a/libsecurity_cssm/APPLE_LICENSE b/libsecurity_cssm/APPLE_LICENSE new file mode 100644 index 00000000..71fe6fd7 --- /dev/null +++ b/libsecurity_cssm/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/libsecurity_cssm/Info-security_cssm.plist b/libsecurity_cssm/Info-security_cssm.plist new file mode 100644 index 00000000..0c67376e --- /dev/null +++ b/libsecurity_cssm/Info-security_cssm.plist @@ -0,0 +1,5 @@ + + + + + diff --git a/libsecurity_cssm/lib/attachfactory.cpp b/libsecurity_cssm/lib/attachfactory.cpp new file mode 100644 index 00000000..2c0edcee --- /dev/null +++ b/libsecurity_cssm/lib/attachfactory.cpp @@ -0,0 +1,111 @@ +/* + * 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@ + */ + + +// +// attachfactory - industrial grade production of Attachment objects +// +#ifdef __MWERKS__ +#define _CPP_ATTACHFACTORY +#endif +#include "attachfactory.h" + +#include "cspattachment.h" +#include +#include +#include +#include +#include +#include + + +// +// A template to generate AttachmentMakers for the standard plugin types. +// +template +class StandardAttachmentMaker : public AttachmentMaker { +public: + StandardAttachmentMaker() : AttachmentMaker(type) + { + for (unsigned n = 0; n < sizeof(nameTable) / sizeof(nameTable[0]); n++) + nameMap.insert(typename NameMap::value_type(nameTable[n], n)); + } + + Attachment *make(Module *module, + const CSSM_VERSION &version, + uint32 subserviceId, + CSSM_SERVICE_TYPE subserviceType, + const CSSM_API_MEMORY_FUNCS &memoryOps, + CSSM_ATTACH_FLAGS attachFlags, + CSSM_KEY_HIERARCHY keyHierarchy, + CSSM_FUNC_NAME_ADDR *FunctionTable, + uint32 NumFunctions) + { + StandardAttachment *attachment = + new StandardAttachment(module, + nameMap, + version, + subserviceId, + subserviceType, + memoryOps, + attachFlags, + keyHierarchy); + attachment->resolveSymbols(FunctionTable, NumFunctions); + return attachment; + } + +private: + typedef typename StandardAttachment::NameMap NameMap; + NameMap nameMap; +}; + + +// +// Implementation of an attachment factory +// +AttachmentFactory::AttachmentFactory() +{ + // generate explicitly known attachment types + factories[CSSM_SERVICE_AC] = new StandardAttachmentMaker; + factories[CSSM_SERVICE_CL] = new StandardAttachmentMaker; + factories[CSSM_SERVICE_CSP] = new StandardAttachmentMaker; + factories[CSSM_SERVICE_DL] = new StandardAttachmentMaker; + factories[CSSM_SERVICE_TP] = new StandardAttachmentMaker; +} + + +AttachmentMaker *AttachmentFactory::attachmentMakerFor(CSSM_SERVICE_TYPE type) const +{ + AttachFactories::const_iterator it = factories.find(type); + if (it == factories.end()) + CssmError::throwMe(CSSMERR_CSSM_INVALID_SERVICE_MASK); + return it->second; +} + + +// +// Manage an AttachmentMaker +// +AttachmentMaker::~AttachmentMaker() +{ +} diff --git a/libsecurity_cssm/lib/attachfactory.h b/libsecurity_cssm/lib/attachfactory.h new file mode 100644 index 00000000..8588004d --- /dev/null +++ b/libsecurity_cssm/lib/attachfactory.h @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2000-2001,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@ + */ + + +// +// attachfactory - industrial grade production of Attachment objects +// +#ifndef _H_ATTACHFACTORY +#define _H_ATTACHFACTORY + +#include "cssmint.h" +#include "attachment.h" + +#ifdef _CPP_ATTACHFACTORY +# pragma export on +#endif + + +// +// An AttachmentMaker can create an Attachment object for a particular service +// type when asked nicely. +// +class AttachmentMaker { +public: + AttachmentMaker(CSSM_SERVICE_TYPE type) : mType(type) { } + virtual ~AttachmentMaker(); + + virtual Attachment *make(Module *module, + const CSSM_VERSION &version, + uint32 subserviceId, + CSSM_SERVICE_TYPE subserviceType, + const CSSM_API_MEMORY_FUNCS &memoryOps, + CSSM_ATTACH_FLAGS attachFlags, + CSSM_KEY_HIERARCHY keyHierarchy, + CSSM_FUNC_NAME_ADDR *functionTable, + uint32 functionTableSize) = 0; + + CSSM_SERVICE_TYPE factoryType() const { return mType; } + +private: + CSSM_SERVICE_TYPE mType; +}; + + +// +// An AttachmentFactory contains a registry of AttachmentMakers for different +// service types, and produces the needed one on request. +// +class AttachmentFactory { +public: + AttachmentFactory(); + + AttachmentMaker *attachmentMakerFor(CSSM_SERVICE_TYPE type) const; + +private: + typedef map AttachFactories; + AttachFactories factories; +}; + +#ifdef _CPP_ATTACHFACTORY +# pragma export off +#endif + + +#endif //_H_ATTACHFACTORY diff --git a/libsecurity_cssm/lib/attachment.cpp b/libsecurity_cssm/lib/attachment.cpp new file mode 100644 index 00000000..a0493131 --- /dev/null +++ b/libsecurity_cssm/lib/attachment.cpp @@ -0,0 +1,205 @@ +/* + * 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@ + */ + + +// +// attachment - CSSM module attachment objects +// +#include "attachment.h" +#include "module.h" +#include "manager.h" +#include "cssmcontext.h" +#include + +// +// Construct an Attachment object. +// This constructor does almost all the work: it initializes the Attachment +// object, calls the plugin's attach function, and initializes everything. +// The only job left for the subclass's constructor is to take the spiFunctionTable +// field and extract from it the plugin's dispatch table in suitable form. +// +Attachment::Attachment(Module *parent, + const CSSM_VERSION &version, + uint32 ssId, + CSSM_SERVICE_TYPE ssType, + const CSSM_API_MEMORY_FUNCS &memoryOps, + CSSM_ATTACH_FLAGS attachFlags, + CSSM_KEY_HIERARCHY keyHierarchy) + : CssmMemoryFunctionsAllocator(memoryOps), module(*parent) +{ + // record our origins + mVersion = version; + mSubserviceId = ssId; + mSubserviceType = ssType; + mAttachFlags = attachFlags; + mKeyHierarchy = keyHierarchy; + + // we are not (yet) attached to our plugin + mIsActive = false; + + // build the upcalls table + // (we could do this once in a static, but then we'd have to lock on it) + upcalls.malloc_func = upcallMalloc; + upcalls.free_func = upcallFree; + upcalls.realloc_func = upcallRealloc; + upcalls.calloc_func = upcallCalloc; + upcalls.CcToHandle_func = upcallCcToHandle; + upcalls.GetModuleInfo_func = upcallGetModuleInfo; + + // tell the module to create an attachment + spiFunctionTable = NULL; // preset invalid + if (CSSM_RETURN err = module.plugin->attach(&module.myGuid(), + &mVersion, + mSubserviceId, + mSubserviceType, + mAttachFlags, + handle(), + mKeyHierarchy, + &gGuidCssm, // CSSM's Guid + &gGuidCssm, // module manager Guid + &module.cssm.callerGuid(), // caller Guid + &upcalls, + &spiFunctionTable)) { + // attach rejected by module + secdebug("cssm", "attach of module %p(%s) failed", + &module, module.name().c_str()); + CssmError::throwMe(err); + } + try { + if (spiFunctionTable == NULL || spiFunctionTable->ServiceType != subserviceType()) + CssmError::throwMe(CSSMERR_CSSM_INVALID_ADDIN_FUNCTION_TABLE); + mIsActive = true; // now officially attached to plugin + secdebug("cssm", "%p attached module %p(%s) (ssid %ld type %ld)", + this, parent, parent->name().c_str(), (long)ssId, (long)ssType); + // subclass is responsible for taking spiFunctionTable and build + // whatever dispatch is needed + } catch (...) { + module.plugin->detach(handle()); // with extreme prejudice + throw; + } +} + + +// +// Detach an attachment. +// This is the polite way to detach from the plugin. It may be refused safely +// (though perhaps not meaningfully). +// THREADS: mLock is locked on entry IFF isLocked, and will be unlocked on exit. +// +void Attachment::detach(bool isLocked) +{ + StLock locker(*this, isLocked); // pre-state locker + locker.lock(); // make sure it's locked + + if (mIsActive) { + if (!isIdle()) + CssmError::throwMe(CSSM_ERRCODE_FUNCTION_FAILED); //@#attachment busy + if (CSSM_RETURN error = module.plugin->detach(handle())) + CssmError::throwMe(error); // I'm sorry Dave, ... + secdebug("cssm", "%p detach module %p(%s)", this, + &module, module.name().c_str()); + mIsActive = false; + module.detach(this); + } +} + + +// +// Destroy the Attachment object +// +Attachment::~Attachment() +{ + try { + detach(false); + } catch (...) { + // too bad - you're dead + } +} + + +// +// Upcall relays. +// These do not lock the attachment object. The attachment can't go away +// because we incremented the busy count on entry to the plugin; and these +// fields are quite constant for the life of the Attachment. +// +void *Attachment::upcallMalloc(CSSM_HANDLE handle, size_t size) +{ + BEGIN_API + return HandleObject::find(handle, CSSMERR_CSSM_INVALID_ADDIN_HANDLE).malloc(size); + END_API1(NULL) +} + +void Attachment::upcallFree(CSSM_HANDLE handle, void *mem) +{ + BEGIN_API + return HandleObject::find(handle, CSSMERR_CSSM_INVALID_ADDIN_HANDLE).free(mem); + END_API0 +} + +void *Attachment::upcallRealloc(CSSM_HANDLE handle, void *mem, size_t size) +{ + BEGIN_API + return HandleObject::find(handle, CSSMERR_CSSM_INVALID_ADDIN_HANDLE).realloc(mem, size); + END_API1(NULL) +} + +void *Attachment::upcallCalloc(CSSM_HANDLE handle, size_t num, size_t size) +{ + BEGIN_API + return HandleObject::find(handle, CSSMERR_CSSM_INVALID_ADDIN_HANDLE).calloc(num, size); + END_API1(NULL) +} + +CSSM_RETURN Attachment::upcallCcToHandle(CSSM_CC_HANDLE handle, + CSSM_MODULE_HANDLE *modHandle) +{ + BEGIN_API + Required(modHandle) = HandleObject::find(handle, CSSMERR_CSSM_INVALID_ADDIN_HANDLE).attachment.handle(); + END_API(CSP) +} + +CSSM_RETURN Attachment::upcallGetModuleInfo(CSSM_MODULE_HANDLE handle, + CSSM_GUID_PTR guid, + CSSM_VERSION_PTR version, + uint32 *subserviceId, + CSSM_SERVICE_TYPE *subserviceType, + CSSM_ATTACH_FLAGS *attachFlags, + CSSM_KEY_HIERARCHY *keyHierarchy, + CSSM_API_MEMORY_FUNCS_PTR memoryOps, + CSSM_FUNC_NAME_ADDR_PTR FunctionTable, + uint32 NumFunctions) +{ + BEGIN_API + Attachment &attachment = HandleObject::find(handle, CSSMERR_CSSM_INVALID_ADDIN_HANDLE); + Required(guid) = attachment.myGuid(); + Required(version) = attachment.mVersion; + Required(subserviceId) = attachment.mSubserviceId; + Required(subserviceType) = attachment.mSubserviceType; + Required(attachFlags) = attachment.mAttachFlags; + Required(keyHierarchy) = attachment.mKeyHierarchy; + Required(memoryOps) = attachment; + if (FunctionTable) + attachment.resolveSymbols(FunctionTable, NumFunctions); + END_API(CSSM) +} diff --git a/libsecurity_cssm/lib/attachment.h b/libsecurity_cssm/lib/attachment.h new file mode 100644 index 00000000..0fd0e46b --- /dev/null +++ b/libsecurity_cssm/lib/attachment.h @@ -0,0 +1,199 @@ +/* + * 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@ + */ + + +// +// attachment - CSSM module attachment objects +// +#ifndef _H_ATTACHMENT +#define _H_ATTACHMENT + +#include "cssmint.h" +#include "module.h" +#include +#include + + +// +// This type represents a single Attachment of any kind. +// Attachments are formed by the CSSM_ModuleAttach call and represent a "session" +// between a caller client and a particular plugin module. Any number of attachments +// can exist for a particular caller and a particular module. +// Attachment is an abstract class. You must subclass it to implement a concrete +// type of plugin. For the standard ones, see the end of this header. +// Key recovery does not use Attachments. +// EMMs are not Attachments, but the plugins they manage are. +// And yes, an Attachment *is* a lock. The API transition layer functions need +// to lock Attachments from the "outside", so there's no point in being coy about it. +// Locking the Attachment is equivalent to locking all its members except for +// instance-constant ones. +// +class Attachment : public HandleObject, // has a handle + public CssmMemoryFunctionsAllocator, // is an allocator + public CountingMutex { // is a counting lock + NOCOPY(Attachment) +public: + Attachment(Module *theModule, + const CSSM_VERSION &version, + uint32 subserviceId, + CSSM_SERVICE_TYPE subserviceType, + const CSSM_API_MEMORY_FUNCS &memoryOps, + CSSM_ATTACH_FLAGS attachFlags, + CSSM_KEY_HIERARCHY keyHierarchy); + virtual ~Attachment(); + + Module &module; + + // feature inquiries. These features are constant for the life of the Attachment + const Guid &myGuid() const { return module.myGuid(); } + CSSM_SERVICE_TYPE subserviceType() const { return mSubserviceType; } + uint32 subserviceId() const { return mSubserviceId; } + const CSSM_VERSION &pluginVersion() const { return mVersion; } + CSSM_ATTACH_FLAGS attachFlags() const { return mAttachFlags; } + + bool isThreadSafe() const { return module.isThreadSafe(); } + + // service a symbol table inquiry against our attachment + virtual void resolveSymbols(CSSM_FUNC_NAME_ADDR *FunctionTable, + uint32 NumFunctions) = 0; + + // terminate the live attachment and prepare to die + void detach(bool isLocked); + + template friend Sub &enterAttachment(CSSM_HANDLE); + + // need to redefine lock/trylock to implement HandleObject protocol + void lock() { CountingMutex::lock(); } + bool tryLock() { return CountingMutex::tryLock(); } + +private: + bool mIsActive; // successfully attached to plugin + + uint32 mSubserviceId; // subservice ID in use + CSSM_SERVICE_TYPE mSubserviceType; // service type + + // how we were created + CSSM_VERSION mVersion; // plugin version requested + CSSM_ATTACH_FLAGS mAttachFlags; // attach flags requested + CSSM_KEY_HIERARCHY mKeyHierarchy; // key hierarchy verified + +protected: + CSSM_MODULE_FUNCS *spiFunctionTable; // entry table as returned by plugin on attach + +private: + CSSM_UPCALLS upcalls; // upcall functions for our module + + // upcall implementors - these are handed to the plugin in `upcalls' + static void *upcallMalloc(CSSM_HANDLE handle, size_t size); + static void upcallFree(CSSM_HANDLE handle, void *mem); + static void *upcallRealloc(CSSM_HANDLE handle, void *mem, size_t size); + static void *upcallCalloc(CSSM_HANDLE handle, size_t num, size_t size); + static CSSM_RETURN upcallCcToHandle(CSSM_CC_HANDLE handle, CSSM_MODULE_HANDLE *modHandle); + static CSSM_RETURN upcallGetModuleInfo(CSSM_MODULE_HANDLE Module, + CSSM_GUID_PTR Guid, + CSSM_VERSION_PTR Version, + uint32 *SubServiceId, + CSSM_SERVICE_TYPE *SubServiceType, + CSSM_ATTACH_FLAGS *AttachFlags, + CSSM_KEY_HIERARCHY *KeyHierarchy, + CSSM_API_MEMORY_FUNCS_PTR AttachedMemFuncs, + CSSM_FUNC_NAME_ADDR_PTR FunctionTable, + uint32 NumFunctions); +}; + +// this should be a member template, but egcs barfs on its invocation +// @@@ pass module code in to get better "invalid handle" diag? +// @@@ or use template specializations here? +template +inline AttachmentSubclass &enterAttachment(CSSM_HANDLE h) +{ + AttachmentSubclass &attachment = HandleObject::findAndLock(h, CSSMERR_CSSM_INVALID_ADDIN_HANDLE); + attachment.finishEnter(); + return attachment; +} + + +// +// For the standard attachment types, function dispatch to the plugin +// is done based on the CSSM_SPI_xxx_FUNCS structures describing the +// types and ordering of entry points. The StandardAttachment class +// implements this by holding a copy of these tables for the use of +// the transition layer. +// You are free to subclass from Attachment directly if that makes better +// sense to your kind of plugin. +// +template +class StandardAttachment : public Attachment { +public: + typedef map NameMap; + + StandardAttachment(Module *theModule, + const NameMap &names, + const CSSM_VERSION &version, + uint32 subserviceId, + CSSM_SERVICE_TYPE subserviceType, + const CSSM_API_MEMORY_FUNCS &memoryOps, + CSSM_ATTACH_FLAGS attachFlags, + CSSM_KEY_HIERARCHY keyHierarchy) + : Attachment(theModule, version, subserviceId, subserviceType, + memoryOps, attachFlags, keyHierarchy), + nameMap(names) + { + try { + if (spiFunctionTable->NumberOfServiceFuncs < + sizeof(FunctionTable) / sizeof(CSSM_PROC_ADDR)) + CssmError::throwMe(CSSMERR_CSSM_INVALID_ADDIN_FUNCTION_TABLE); + // tolerate a table that's TOO large - perhaps it's a newer version + // @@@ with the new spec, we could just store the pointer + memcpy(&downcalls, spiFunctionTable->ServiceFuncs, sizeof(downcalls)); + } catch (...) { + // we are attached to the plugin, so tell it the show is off + detach(false); + throw; + } + } + + void resolveSymbols(CSSM_FUNC_NAME_ADDR *inFunctionTable, + uint32 NumFunctions) + { + for (unsigned n = 0; n < NumFunctions; n++) { + NameMap::const_iterator it = nameMap.find(inFunctionTable[n].Name); + inFunctionTable[n].Address = + (it == nameMap.end()) ? NULL : downcallNumber(it->second); + } + } + + FunctionTable downcalls; + + CSSM_PROC_ADDR downcallNumber(uint32 index) const + { + assert(index < sizeof(downcalls) / sizeof(CSSM_PROC_ADDR)); + return reinterpret_cast(&downcalls)[index]; + } + +private: + const NameMap &nameMap; +}; + + +#endif //_H_ATTACHMENT diff --git a/libsecurity_cssm/lib/certextensions.h b/libsecurity_cssm/lib/certextensions.h new file mode 100644 index 00000000..79e25af4 --- /dev/null +++ b/libsecurity_cssm/lib/certextensions.h @@ -0,0 +1,640 @@ +/* + * 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/cspattachment.cpp b/libsecurity_cssm/lib/cspattachment.cpp new file mode 100644 index 00000000..c35f6329 --- /dev/null +++ b/libsecurity_cssm/lib/cspattachment.cpp @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2000-2001,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@ + */ + + +// +// cspattachment - cryptographic plugin attachment type +// +#ifdef __MWERKS__ +#define _CPP_CSPATTACHMENT +#endif +#include "cspattachment.h" diff --git a/libsecurity_cssm/lib/cspattachment.h b/libsecurity_cssm/lib/cspattachment.h new file mode 100644 index 00000000..4255ce4d --- /dev/null +++ b/libsecurity_cssm/lib/cspattachment.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2000-2001,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@ + */ + + +// +// cspattachment - cryptographic plugin attachment type +// +#ifndef _H_CSPATTACHMENT +#define _H_CSPATTACHMENT + +#include "attachment.h" +#include + +#ifdef _CPP_CSPATTACHMENT +# pragma export on +#endif + + +typedef StandardAttachment CSPAttachment; + +#ifdef _CPP_CSPATTACHMENT +# pragma export off +#endif + +#endif //_H_CSPATTACHMENT diff --git a/libsecurity_cssm/lib/cssm.cpp b/libsecurity_cssm/lib/cssm.cpp new file mode 100644 index 00000000..67d6dccf --- /dev/null +++ b/libsecurity_cssm/lib/cssm.cpp @@ -0,0 +1,224 @@ +/* + * 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@ + */ + + +// +// This file contains the core CSSM public functions. +// Note that hardly anything happens in here; we just hand off requests +// to the various objects representing CSSM state. +// +#include "manager.h" +#include "module.h" +#include +#include + + +// +// We currently use exactly one instance of CssmManager. +// +static ModuleNexus gManager; + + +// +// Public API: (Re)Intiailize CSSM +// +CSSM_RETURN CSSMAPI +CSSM_Init (const CSSM_VERSION *Version, + CSSM_PRIVILEGE_SCOPE Scope, + const CSSM_GUID *CallerGuid, + CSSM_KEY_HIERARCHY KeyHierarchy, + CSSM_PVC_MODE *PvcPolicy, + const void *) +{ + BEGIN_API + gManager().initialize(Required(Version), + Scope, + Guid::required(CallerGuid), + KeyHierarchy, + Required(PvcPolicy)); + END_API(CSSM) +} + + +// +// Public API: Terminate CSSM. +// +CSSM_RETURN CSSMAPI +CSSM_Terminate (void) +{ + BEGIN_API + gManager().terminate(); + END_API(CSSM) +} + + +// +// Public API: Load a CSSM module +// +CSSM_RETURN CSSMAPI +CSSM_ModuleLoad (const CSSM_GUID *ModuleGuid, + CSSM_KEY_HIERARCHY KeyHierarchy, + CSSM_API_ModuleEventHandler AppNotifyCallback, + void *AppNotifyCallbackCtx) +{ + BEGIN_API + gManager().loadModule(Guid::required(ModuleGuid), + KeyHierarchy, + ModuleCallback(AppNotifyCallback, AppNotifyCallbackCtx)); + END_API(CSSM) +} + + +// +// Public API: Unload a module +// +CSSM_RETURN CSSMAPI +CSSM_ModuleUnload (const CSSM_GUID *ModuleGuid, + CSSM_API_ModuleEventHandler AppNotifyCallback, + void *AppNotifyCallbackCtx) +{ + BEGIN_API + gManager().unloadModule(Guid::required(ModuleGuid), + ModuleCallback(AppNotifyCallback, AppNotifyCallbackCtx)); + END_API(CSSM) +} + + +CSSM_RETURN CSSMAPI +CSSM_Introduce (const CSSM_GUID *ModuleID, + CSSM_KEY_HIERARCHY KeyHierarchy) +{ + BEGIN_API + gManager().introduce(Guid::required(ModuleID), KeyHierarchy); + END_API(CSSM) +} + +CSSM_RETURN CSSMAPI +CSSM_Unintroduce (const CSSM_GUID *ModuleID) +{ + BEGIN_API + gManager().unIntroduce(Guid::required(ModuleID)); + END_API(CSSM) +} + + +CSSM_RETURN CSSMAPI +CSSM_ModuleAttach (const CSSM_GUID *ModuleGuid, + const CSSM_VERSION *Version, + const CSSM_API_MEMORY_FUNCS *MemoryFuncs, + uint32 SubserviceID, + CSSM_SERVICE_TYPE SubServiceType, + CSSM_ATTACH_FLAGS AttachFlags, + CSSM_KEY_HIERARCHY KeyHierarchy, + CSSM_FUNC_NAME_ADDR *FunctionTable, + uint32 NumFunctionTable, + const void *, + CSSM_MODULE_HANDLE_PTR NewModuleHandle) +{ + BEGIN_API + Required(NewModuleHandle) = gManager().getModule(Guid::required(ModuleGuid))->attach( + Required(Version), + SubserviceID, SubServiceType, + Required(MemoryFuncs), + AttachFlags, + KeyHierarchy, + FunctionTable, NumFunctionTable + ); + END_API(CSSM) +} + +CSSM_RETURN CSSMAPI +CSSM_ModuleDetach (CSSM_MODULE_HANDLE ModuleHandle) +{ + BEGIN_API + Attachment *attachment = &HandleObject::findAndKill(ModuleHandle, CSSMERR_CSSM_INVALID_ADDIN_HANDLE); + attachment->detach(true); // expect locked, will unlock + // the attachment is now off the maps, known idle, and unhooked + delete attachment; + END_API(CSSM) +} + + +CSSM_RETURN CSSMAPI +CSSM_SetPrivilege (CSSM_PRIVILEGE Privilege) +{ + BEGIN_API + gManager().setPrivilege(Privilege); + END_API(CSSM) +} + +CSSM_RETURN CSSMAPI +CSSM_GetPrivilege (CSSM_PRIVILEGE *Privilege) +{ + BEGIN_API + Required(Privilege) = gManager().getPrivilege(); + END_API(CSSM) +} + + +CSSM_RETURN CSSMAPI +CSSM_GetModuleGUIDFromHandle (CSSM_MODULE_HANDLE ModuleHandle, + CSSM_GUID_PTR ModuleGUID) +{ + BEGIN_API + Attachment &attachment = HandleObject::findAndLock(ModuleHandle, CSSMERR_CSSM_INVALID_ADDIN_HANDLE); + StLock _(attachment, true); + Required(ModuleGUID) = attachment.module.myGuid(); + END_API(CSSM) +} + +CSSM_RETURN CSSMAPI +CSSM_GetSubserviceUIDFromHandle (CSSM_MODULE_HANDLE ModuleHandle, + CSSM_SUBSERVICE_UID_PTR SubserviceUID) +{ + BEGIN_API + Attachment &attachment = HandleObject::findAndLock(ModuleHandle, CSSMERR_CSSM_INVALID_ADDIN_HANDLE); + StLock _(attachment, true); + CSSM_SUBSERVICE_UID &result = Required(SubserviceUID); + result.Guid = attachment.module.myGuid(); + result.Version = attachment.pluginVersion(); + result.SubserviceId = attachment.subserviceId(); + result.SubserviceType = attachment.subserviceType(); + END_API(CSSM) +} + + +CSSM_RETURN CSSMAPI +CSSM_ListAttachedModuleManagers (uint32 *NumberOfModuleManagers, + CSSM_GUID_PTR) +{ + BEGIN_API + *NumberOfModuleManagers = 0; // EMMs not implemented + END_API(CSSM) +} + +CSSM_RETURN CSSMAPI +CSSM_GetAPIMemoryFunctions (CSSM_MODULE_HANDLE AddInHandle, + CSSM_API_MEMORY_FUNCS_PTR AppMemoryFuncs) +{ + BEGIN_API + Attachment &attachment = HandleObject::findAndLock(AddInHandle, CSSMERR_CSSM_INVALID_ADDIN_HANDLE); + StLock _(attachment, true); + Required(AppMemoryFuncs) = attachment; + END_API(CSSM) +} diff --git a/libsecurity_cssm/lib/cssm.h b/libsecurity_cssm/lib/cssm.h new file mode 100644 index 00000000..27f7084d --- /dev/null +++ b/libsecurity_cssm/lib/cssm.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 1999-2001,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.h -- Common Security Services Manager Interface + */ + +#ifndef _CSSM_H_ +#define _CSSM_H_ 1 + +#include +#include +#include +#include +#include + +#endif /* _CSSM_H_ */ diff --git a/libsecurity_cssm/lib/cssmaci.h b/libsecurity_cssm/lib/cssmaci.h new file mode 100644 index 00000000..7a81d6fe --- /dev/null +++ b/libsecurity_cssm/lib/cssmaci.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 1999-2001,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@ + * + * cssmaci.h -- Sevice Provider Interface for Access Control Module + */ + +#ifndef _CSSMACI_H_ +#define _CSSMACI_H_ 1 + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct cssm_spi_ac_funcs { + CSSM_RETURN (CSSMACI *AuthCompute) + (CSSM_AC_HANDLE ACHandle, + const CSSM_TUPLEGROUP *BaseAuthorizations, + const CSSM_TUPLEGROUP *Credentials, + uint32 NumberOfRequestors, + const CSSM_LIST *Requestors, + const CSSM_LIST *RequestedAuthorizationPeriod, + const CSSM_LIST *RequestedAuthorization, + CSSM_TUPLEGROUP_PTR AuthorizationResult); + CSSM_RETURN (CSSMACI *PassThrough) + (CSSM_AC_HANDLE ACHandle, + CSSM_TP_HANDLE TPHandle, + CSSM_CL_HANDLE CLHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_DL_DB_LIST *DBList, + uint32 PassThroughId, + const void *InputParams, + void **OutputParams); +} CSSM_SPI_AC_FUNCS DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_SPI_AC_FUNCS_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +#ifdef __cplusplus +} +#endif + +#endif /* _CSSMACI_H_ */ diff --git a/libsecurity_cssm/lib/cssmapi.h b/libsecurity_cssm/lib/cssmapi.h new file mode 100644 index 00000000..f1de11cb --- /dev/null +++ b/libsecurity_cssm/lib/cssmapi.h @@ -0,0 +1,2212 @@ +/* + * Copyright (c) 1999-2001,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@ + * + * cssmapi.h -- Application Programmers Interfaces for CSSM + */ + +#ifndef _CSSMAPI_H_ +#define _CSSMAPI_H_ 1 + +#include + +/* ========================================================================== + W A R N I N G : CDSA has been deprecated starting with 10.7. While the + APIs will continue to work, developers should update their code to use + the APIs that are suggested and NOT use the CDSA APIs + ========================================================================== */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Core Functions */ + +/* -------------------------------------------------------------------------- + CSSM_Init has been deprecated in 10.7 and later. There is no alternate + API as this call is only needed when calling CDSA APIs + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_Init (const CSSM_VERSION *Version, + CSSM_PRIVILEGE_SCOPE Scope, + const CSSM_GUID *CallerGuid, + CSSM_KEY_HIERARCHY KeyHierarchy, + CSSM_PVC_MODE *PvcPolicy, + const void *Reserved) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_Terminate has been deprecated in 10.7 and later. There is no alternate + API as this call is only needed when calling CDSA APIs + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_Terminate (void) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_ModuleLoad has been deprecated in 10.7 and later. There is no + alternate API as this call is only needed when calling CDSA APIs + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_ModuleLoad (const CSSM_GUID *ModuleGuid, + CSSM_KEY_HIERARCHY KeyHierarchy, + CSSM_API_ModuleEventHandler AppNotifyCallback, + void *AppNotifyCallbackCtx) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_ModuleUnload has been deprecated in 10.7 and later. There is no + alternate API as this call is only needed when calling CDSA APIs + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_ModuleUnload (const CSSM_GUID *ModuleGuid, + CSSM_API_ModuleEventHandler AppNotifyCallback, + void *AppNotifyCallbackCtx) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_Introduce has been deprecated in 10.7 and later. There is no + alternate API as this call is only needed when calling CDSA APIs + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_Introduce (const CSSM_GUID *ModuleID, + CSSM_KEY_HIERARCHY KeyHierarchy) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_Unintroduce has been deprecated in 10.7 and later. There is no + alternate API as this call is only needed when calling CDSA APIs + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_Unintroduce (const CSSM_GUID *ModuleID) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_ModuleAttach has been deprecated in 10.7 and later. There is no + alternate API as this call is only needed when calling CDSA APIs + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_ModuleAttach (const CSSM_GUID *ModuleGuid, + const CSSM_VERSION *Version, + const CSSM_API_MEMORY_FUNCS *MemoryFuncs, + uint32 SubserviceID, + CSSM_SERVICE_TYPE SubServiceType, + CSSM_ATTACH_FLAGS AttachFlags, + CSSM_KEY_HIERARCHY KeyHierarchy, + CSSM_FUNC_NAME_ADDR *FunctionTable, + uint32 NumFunctionTable, + const void *Reserved, + CSSM_MODULE_HANDLE_PTR NewModuleHandle) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_ModuleDetach has been deprecated in 10.7 and later. There is no + alternate API as this call is only needed when calling CDSA APIs + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_ModuleDetach (CSSM_MODULE_HANDLE ModuleHandle) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_SetPrivilege has been deprecated in 10.7 and later. There is no alternate + API as this call is only needed when calling CDSA APIs + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_SetPrivilege (CSSM_PRIVILEGE Privilege) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_GetPrivilege has been deprecated in 10.7 and later. There is no + alternate API as this call is only needed when calling CDSA APIs + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_GetPrivilege (CSSM_PRIVILEGE *Privilege) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_GetModuleGUIDFromHandle has been deprecated in 10.7 and later. + There is no alternate API as this call is only needed when calling CDSA + APIs + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_GetModuleGUIDFromHandle (CSSM_MODULE_HANDLE ModuleHandle, + CSSM_GUID_PTR ModuleGUID) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_GetSubserviceUIDFromHandle has been deprecated in 10.7 and later. + There is no alternate API as this call is only needed when calling CDSA + APIs + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_GetSubserviceUIDFromHandle (CSSM_MODULE_HANDLE ModuleHandle, + CSSM_SUBSERVICE_UID_PTR SubserviceUID) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_ListAttachedModuleManagers has been deprecated in 10.7 and later. + There is no alternate API as this call is only needed when calling CDSA + APIs + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_ListAttachedModuleManagers (uint32 *NumberOfModuleManagers, + CSSM_GUID_PTR ModuleManagerGuids) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_GetAPIMemoryFunctions has been deprecated in 10.7 and later. + There is no alternate API as this call is only needed when calling CDSA + APIs + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_GetAPIMemoryFunctions (CSSM_MODULE_HANDLE AddInHandle, + CSSM_API_MEMORY_FUNCS_PTR AppMemoryFuncs) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + + +/* Cryptographic Context Operations */ + +/* -------------------------------------------------------------------------- + CSSM_CSP_CreateSignatureContext has been deprecated in 10.7 and later. + The replacement API for this is SecSignTransformCreate in the + SecSignVerifyTransform.h file. + -------------------------------------------------------------------------- */ +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) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_CSP_CreateSignatureContext has been deprecated in 10.7 and later. + The replacement API for this is SecSignTransformCreate in the + SecSignVerifyTransform.h file. + -------------------------------------------------------------------------- */ +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) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_CSP_CreateDigestContext has been deprecated in 10.7 and later. + The replacement API for this is SecDigestTransformCreate in the + SecDigestTransform.h file. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_CSP_CreateDigestContext (CSSM_CSP_HANDLE CSPHandle, + CSSM_ALGORITHMS AlgorithmID, + CSSM_CC_HANDLE *NewContextHandle) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_CSP_CreateMacContext has been deprecated in 10.7 and later. + The replacement API for this is SecDigestTransformCreate in the + SecDigestTransform.h file. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_CSP_CreateMacContext (CSSM_CSP_HANDLE CSPHandle, + CSSM_ALGORITHMS AlgorithmID, + const CSSM_KEY *Key, + CSSM_CC_HANDLE *NewContextHandle) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_CSP_CreateRandomGenContext has been deprecated in 10.7 and later. + There is no replacement API as this API is only needed with CDSA. Please + see the SecRandom.h file to get random numbers + -------------------------------------------------------------------------- */ +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) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_CSP_CreateAsymmetricContext has been deprecated in 10.7 and later. + There is no direct replacement of this API as it is only needed by CDSA. + For asymmertical encryption/decryption use the SecEncryptTransformCreate + or SecDecryptTransformCreate with a asymmertical key. + -------------------------------------------------------------------------- */ +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) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_CSP_CreateDeriveKeyContext has been deprecated in 10.7 and later. + The replacement for this API would be the SecKeyDeriveFromPassword API + in the SecKey.h file + -------------------------------------------------------------------------- */ +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) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_CSP_CreateKeyGenContext has been deprecated in 10.7 and later. + The replacement for this API would be either the SecKeyGeneratePair API + or the SecKeyGenerateSymmetric API in the SecKey.h file + -------------------------------------------------------------------------- */ +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) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_CSP_CreatePassThroughContext has been deprecated in 10.7 and later. + There is no alternate API as this call is only needed when calling + CDSA APIs + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_CSP_CreatePassThroughContext (CSSM_CSP_HANDLE CSPHandle, + const CSSM_KEY *Key, + CSSM_CC_HANDLE *NewContextHandle) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_GetContext has been deprecated in 10.7 and later. + There is no alternate API as this call is only needed when calling + CDSA APIs + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_GetContext (CSSM_CC_HANDLE CCHandle, + CSSM_CONTEXT_PTR *Context) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_FreeContext has been deprecated in 10.7 and later. + There is no alternate API as this call is only needed when calling + CDSA APIs + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_FreeContext (CSSM_CONTEXT_PTR Context) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_SetContext has been deprecated in 10.7 and later. + There is no alternate API as this call is only needed when calling + CDSA APIs + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_SetContext (CSSM_CC_HANDLE CCHandle, + const CSSM_CONTEXT *Context) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_DeleteContext has been deprecated in 10.7 and later. + There is no alternate API as this call is only needed when calling + CDSA APIs + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_DeleteContext (CSSM_CC_HANDLE CCHandle) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_GetContextAttribute has been deprecated in 10.7 and later. + There is no alternate API as this call is only needed when calling + CDSA APIs + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_GetContextAttribute (const CSSM_CONTEXT *Context, + uint32 AttributeType, + CSSM_CONTEXT_ATTRIBUTE_PTR *ContextAttribute) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_UpdateContextAttributes has been deprecated in 10.7 and later. + There is no alternate API as this call is only needed when calling + CDSA APIs + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_UpdateContextAttributes (CSSM_CC_HANDLE CCHandle, + uint32 NumberOfAttributes, + const CSSM_CONTEXT_ATTRIBUTE *ContextAttributes) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_DeleteContextAttributes has been deprecated in 10.7 and later. + There is no alternate API as this call is only needed when calling + CDSA APIs + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_DeleteContextAttributes (CSSM_CC_HANDLE CCHandle, + uint32 NumberOfAttributes, + const CSSM_CONTEXT_ATTRIBUTE *ContextAttributes) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + + +/* Cryptographic Sessions and Controlled Access to Keys */ +/* -------------------------------------------------------------------------- + CSSM_CSP_Login has been deprecated in 10.7 and later. + There is no alternate API as this call is only needed when calling + CDSA APIs + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_CSP_Login (CSSM_CSP_HANDLE CSPHandle, + const CSSM_ACCESS_CREDENTIALS *AccessCred, + const CSSM_DATA *LoginName, + const void *Reserved) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_CSP_Logout has been deprecated in 10.7 and later. + There is no alternate API as this call is only needed when calling + CDSA APIs + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_CSP_Logout (CSSM_CSP_HANDLE CSPHandle) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_CSP_GetLoginAcl has been deprecated in 10.7 and later. + There is no alternate API as this call is only needed when calling + CDSA APIs + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_CSP_GetLoginAcl (CSSM_CSP_HANDLE CSPHandle, + const CSSM_STRING *SelectionTag, + uint32 *NumberOfAclInfos, + CSSM_ACL_ENTRY_INFO_PTR *AclInfos) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_CSP_ChangeLoginAcl has been deprecated in 10.7 and later. + There is no alternate API as this call is only needed when calling + CDSA APIs + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_CSP_ChangeLoginAcl (CSSM_CSP_HANDLE CSPHandle, + const CSSM_ACCESS_CREDENTIALS *AccessCred, + const CSSM_ACL_EDIT *AclEdit) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_GetKeyAcl has been deprecated in 10.7 and later. + If the key in question is in a keychain then the ACL for the key can be + aquired by using the SecItemCopyMatching API specifically + kSecReturnAttributes with a value of kCFBooleanTrue. In the attributes + dictionary is kSecAttrAccess key with a value of a SecAccessRef. With + a SecAccessRef the ACL for the key can be gotten using either the + SecAccessCopyACLList API. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_GetKeyAcl (CSSM_CSP_HANDLE CSPHandle, + const CSSM_KEY *Key, + const CSSM_STRING *SelectionTag, + uint32 *NumberOfAclInfos, + CSSM_ACL_ENTRY_INFO_PTR *AclInfos) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_ChangeKeyAcl has been deprecated in 10.7 and later. + If the key in question is in a keychain then the ACL for the key can be + changed by using the SecItemUpdate API. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_ChangeKeyAcl (CSSM_CSP_HANDLE CSPHandle, + const CSSM_ACCESS_CREDENTIALS *AccessCred, + const CSSM_ACL_EDIT *AclEdit, + const CSSM_KEY *Key) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_GetKeyOwner has been deprecated in 10.7 and later. + If the key in question is in a keychain then the ACL for the key can be + aquired by using the SecItemCopyMatching API specifically + kSecReturnAttributes with a value of kCFBooleanTrue. In the attributes + dictionary is kSecAttrAccess key with a value of a SecAccessRef. With + a SecAccessRef the ACL for the key can be gotten using either the + SecAccessCopyOwnerAndACL API. + -------------------------------------------------------------------------- */ + +CSSM_RETURN CSSMAPI +CSSM_GetKeyOwner (CSSM_CSP_HANDLE CSPHandle, + const CSSM_KEY *Key, + CSSM_ACL_OWNER_PROTOTYPE_PTR Owner) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_ChangeKeyOwner has been deprecated in 10.7 and later. + If the key in question is in a keychain then the ACL for the key can be + changed by using the SecItemUpdate API. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_ChangeKeyOwner (CSSM_CSP_HANDLE CSPHandle, + const CSSM_ACCESS_CREDENTIALS *AccessCred, + const CSSM_KEY *Key, + const CSSM_ACL_OWNER_PROTOTYPE *NewOwner) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_CSP_GetLoginOwner has been deprecated in 10.7 and later. + There is no alternate API as this call is only needed when calling + CDSA APIs + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_CSP_GetLoginOwner (CSSM_CSP_HANDLE CSPHandle, + CSSM_ACL_OWNER_PROTOTYPE_PTR Owner) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_CSP_ChangeLoginOwner has been deprecated in 10.7 and later. + There is no alternate API as this call is only needed when calling + CDSA APIs + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_CSP_ChangeLoginOwner (CSSM_CSP_HANDLE CSPHandle, + const CSSM_ACCESS_CREDENTIALS *AccessCred, + const CSSM_ACL_OWNER_PROTOTYPE *NewOwner) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_SignData has been deprecated in 10.7 and later. + To sign data use the SecSignTransformCreate API to create the transform + and the SecTransform APIs to set the data and to execute the transform. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_SignData (CSSM_CC_HANDLE CCHandle, + const CSSM_DATA *DataBufs, + uint32 DataBufCount, + CSSM_ALGORITHMS DigestAlgorithm, + CSSM_DATA_PTR Signature) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_SignDataInit has been deprecated in 10.7 and later. + To sign data use the SecSignTransformCreate API to create the transform + and the SecTransform APIs to set the data and to execute the transform. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_SignDataInit (CSSM_CC_HANDLE CCHandle) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_SignDataUpdate has been deprecated in 10.7 and later. + To sign data use the SecSignTransformCreate API to create the transform + and the SecTransform APIs to set the data and to execute the transform. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_SignDataUpdate (CSSM_CC_HANDLE CCHandle, + const CSSM_DATA *DataBufs, + uint32 DataBufCount) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_SignDataFinal has been deprecated in 10.7 and later. + To sign data use the SecSignTransformCreate API to create the transform + and the SecTransform APIs to set the data and to execute the transform. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_SignDataFinal (CSSM_CC_HANDLE CCHandle, + CSSM_DATA_PTR Signature) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_VerifyData has been deprecated in 10.7 and later. + To sign data use the SecVerifyTransformCreate API to create the transform + and the SecTransform APIs to set the data and to execute the transform. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_VerifyData (CSSM_CC_HANDLE CCHandle, + const CSSM_DATA *DataBufs, + uint32 DataBufCount, + CSSM_ALGORITHMS DigestAlgorithm, + const CSSM_DATA *Signature) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_VerifyDataInit has been deprecated in 10.7 and later. + To sign data use the SecVerifyTransformCreate API to create the transform + and the SecTransform APIs to set the data and to execute the transform. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_VerifyDataInit (CSSM_CC_HANDLE CCHandle) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_VerifyDataUpdate has been deprecated in 10.7 and later. + To sign data use the SecVerifyTransformCreate API to create the transform + and the SecTransform APIs to set the data and to execute the transform. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_VerifyDataUpdate (CSSM_CC_HANDLE CCHandle, + const CSSM_DATA *DataBufs, + uint32 DataBufCount) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_VerifyDataFinal has been deprecated in 10.7 and later. + To sign data use the SecVerifyTransformCreate API to create the transform + and the SecTransform APIs to set the data and to execute the transform. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_VerifyDataFinal (CSSM_CC_HANDLE CCHandle, + const CSSM_DATA *Signature) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_DigestData has been deprecated in 10.7 and later. + To sign data use the SecDigestTransformCreate API to create the transform + and the SecTransform APIs to set the data and to execute the transform. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_DigestData (CSSM_CC_HANDLE CCHandle, + const CSSM_DATA *DataBufs, + uint32 DataBufCount, + CSSM_DATA_PTR Digest) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_DigestDataInit has been deprecated in 10.7 and later. + To sign data use the SecDigestTransformCreate API to create the transform + and the SecTransform APIs to set the data and to execute the transform. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_DigestDataInit (CSSM_CC_HANDLE CCHandle) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_DigestDataUpdate has been deprecated in 10.7 and later. + To sign data use the SecDigestTransformCreate API to create the transform + and the SecTransform APIs to set the data and to execute the transform. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_DigestDataUpdate (CSSM_CC_HANDLE CCHandle, + const CSSM_DATA *DataBufs, + uint32 DataBufCount) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_DigestDataClone has been deprecated in 10.7 and later. + Given that transforms can have be connected into chains, this + functionality is no longer needed. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_DigestDataClone (CSSM_CC_HANDLE CCHandle, + CSSM_CC_HANDLE *ClonednewCCHandle) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_DigestDataFinal has been deprecated in 10.7 and later. + To sign data use the SecDigestTransformCreate API to create the transform + and the SecTransform APIs to set the data and to execute the transform. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_DigestDataFinal (CSSM_CC_HANDLE CCHandle, + CSSM_DATA_PTR Digest) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_GenerateMac has been deprecated in 10.7 and later. + To sign data use the SecDigestTransformCreate API to create the transform + and the SecTransform APIs to set the data and to execute the transform. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_GenerateMac (CSSM_CC_HANDLE CCHandle, + const CSSM_DATA *DataBufs, + uint32 DataBufCount, + CSSM_DATA_PTR Mac) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_GenerateMacInit has been deprecated in 10.7 and later. + To sign data use the SecDigestTransformCreate API to create the transform + and the SecTransform APIs to set the data and to execute the transform. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_GenerateMacInit (CSSM_CC_HANDLE CCHandle) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_GenerateMacUpdate has been deprecated in 10.7 and later. + To sign data use the SecDigestTransformCreate API to create the transform + and the SecTransform APIs to set the data and to execute the transform. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_GenerateMacUpdate (CSSM_CC_HANDLE CCHandle, + const CSSM_DATA *DataBufs, + uint32 DataBufCount) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_GenerateMacFinal has been deprecated in 10.7 and later. + To sign data use the SecDigestTransformCreate API to create the transform + and the SecTransform APIs to set the data and to execute the transform. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_GenerateMacFinal (CSSM_CC_HANDLE CCHandle, + CSSM_DATA_PTR Mac) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_VerifyMac has been deprecated in 10.7 and later. + To sign data use the SecVerifyTransformCreate API to create the transform + and the SecTransform APIs to set the data and to execute the transform. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_VerifyMac (CSSM_CC_HANDLE CCHandle, + const CSSM_DATA *DataBufs, + uint32 DataBufCount, + const CSSM_DATA *Mac) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_VerifyMacInit has been deprecated in 10.7 and later. + To sign data use the SecVerifyTransformCreate API to create the transform + and the SecTransform APIs to set the data and to execute the transform. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_VerifyMacInit (CSSM_CC_HANDLE CCHandle) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_VerifyMacUpdate has been deprecated in 10.7 and later. + To sign data use the SecVerifyTransformCreate API to create the transform + and the SecTransform APIs to set the data and to execute the transform. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_VerifyMacUpdate (CSSM_CC_HANDLE CCHandle, + const CSSM_DATA *DataBufs, + uint32 DataBufCount) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_VerifyMacFinal has been deprecated in 10.7 and later. + To sign data use the SecVerifyTransformCreate API to create the transform + and the SecTransform APIs to set the data and to execute the transform. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_VerifyMacFinal (CSSM_CC_HANDLE CCHandle, + const CSSM_DATA *Mac) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_QuerySize has been deprecated in 10.7 and later. + Given that transforms buffer data into queues, this functionality is no + longer needed. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_QuerySize (CSSM_CC_HANDLE CCHandle, + CSSM_BOOL Encrypt, + uint32 QuerySizeCount, + CSSM_QUERY_SIZE_DATA_PTR DataBlockSizes) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + + +/* -------------------------------------------------------------------------- + CSSM_EncryptData has been deprecated in 10.7 and later. + To sign data use the SecEncryptTransformCreate API to create the transform + and the SecTransform APIs to set the data and to execute the transform. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_EncryptData (CSSM_CC_HANDLE CCHandle, + const CSSM_DATA *ClearBufs, + uint32 ClearBufCount, + CSSM_DATA_PTR CipherBufs, + uint32 CipherBufCount, + CSSM_SIZE *bytesEncrypted, + CSSM_DATA_PTR RemData) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_EncryptDataP has been deprecated in 10.7 and later. + To sign data use the SecEncryptTransformCreate API to create the transform + and the SecTransform APIs to set the data and to execute the transform. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_EncryptDataP (CSSM_CC_HANDLE CCHandle, + const CSSM_DATA *ClearBufs, + uint32 ClearBufCount, + CSSM_DATA_PTR CipherBufs, + uint32 CipherBufCount, + CSSM_SIZE *bytesEncrypted, + CSSM_DATA_PTR RemData, + CSSM_PRIVILEGE Privilege) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_EncryptDataInit has been deprecated in 10.7 and later. + To sign data use the SecEncryptTransformCreate API to create the transform + and the SecTransform APIs to set the data and to execute the transform. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_EncryptDataInit (CSSM_CC_HANDLE CCHandle) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_EncryptDataInitP has been deprecated in 10.7 and later. + To sign data use the SecEncryptTransformCreate API to create the transform + and the SecTransform APIs to set the data and to execute the transform. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_EncryptDataInitP (CSSM_CC_HANDLE CCHandle, + CSSM_PRIVILEGE Privilege) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_EncryptDataUpdate has been deprecated in 10.7 and later. + To sign data use the SecEncryptTransformCreate API to create the transform + and the SecTransform APIs to set the data and to execute the transform. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_EncryptDataUpdate (CSSM_CC_HANDLE CCHandle, + const CSSM_DATA *ClearBufs, + uint32 ClearBufCount, + CSSM_DATA_PTR CipherBufs, + uint32 CipherBufCount, + CSSM_SIZE *bytesEncrypted) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_EncryptDataFinal has been deprecated in 10.7 and later. + To sign data use the SecEncryptTransformCreate API to create the transform + and the SecTransform APIs to set the data and to execute the transform. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_EncryptDataFinal (CSSM_CC_HANDLE CCHandle, + CSSM_DATA_PTR RemData) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_DecryptData has been deprecated in 10.7 and later. + To sign data use the SecDecryptTransformCreate API to create the transform + and the SecTransform APIs to set the data and to execute the transform. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_DecryptData (CSSM_CC_HANDLE CCHandle, + const CSSM_DATA *CipherBufs, + uint32 CipherBufCount, + CSSM_DATA_PTR ClearBufs, + uint32 ClearBufCount, + CSSM_SIZE *bytesDecrypted, + CSSM_DATA_PTR RemData) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_DecryptDataP has been deprecated in 10.7 and later. + To sign data use the SecDecryptTransformCreate API to create the transform + and the SecTransform APIs to set the data and to execute the transform. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_DecryptDataP (CSSM_CC_HANDLE CCHandle, + const CSSM_DATA *CipherBufs, + uint32 CipherBufCount, + CSSM_DATA_PTR ClearBufs, + uint32 ClearBufCount, + CSSM_SIZE *bytesDecrypted, + CSSM_DATA_PTR RemData, + CSSM_PRIVILEGE Privilege) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_DecryptDataInit has been deprecated in 10.7 and later. + To sign data use the SecDecryptTransformCreate API to create the transform + and the SecTransform APIs to set the data and to execute the transform. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_DecryptDataInit (CSSM_CC_HANDLE CCHandle) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_DecryptDataInitP has been deprecated in 10.7 and later. + To sign data use the SecDecryptTransformCreate API to create the transform + and the SecTransform APIs to set the data and to execute the transform. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_DecryptDataInitP (CSSM_CC_HANDLE CCHandle, + CSSM_PRIVILEGE Privilege) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_DecryptDataUpdate has been deprecated in 10.7 and later. + To sign data use the SecDecryptTransformCreate API to create the transform + and the SecTransform APIs to set the data and to execute the transform. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_DecryptDataUpdate (CSSM_CC_HANDLE CCHandle, + const CSSM_DATA *CipherBufs, + uint32 CipherBufCount, + CSSM_DATA_PTR ClearBufs, + uint32 ClearBufCount, + CSSM_SIZE *bytesDecrypted) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_DecryptDataFinal has been deprecated in 10.7 and later. + To sign data use the SecDecryptTransformCreate API to create the transform + and the SecTransform APIs to set the data and to execute the transform. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_DecryptDataFinal (CSSM_CC_HANDLE CCHandle, + CSSM_DATA_PTR RemData) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_QueryKeySizeInBits has been deprecated in 10.7 and later. + Given that a SecKeyRef abstracts the usage of a key this API so no longer + needed. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_QueryKeySizeInBits (CSSM_CSP_HANDLE CSPHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_KEY *Key, + CSSM_KEY_SIZE_PTR KeySize) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_GenerateKey has been deprecated in 10.7 and later. + To create a symmetrical key call SecKeyGenerateSymmetric. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_GenerateKey (CSSM_CC_HANDLE CCHandle, + uint32 KeyUsage, + uint32 KeyAttr, + const CSSM_DATA *KeyLabel, + const CSSM_RESOURCE_CONTROL_CONTEXT *CredAndAclEntry, + CSSM_KEY_PTR Key) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_GenerateKeyP has been deprecated in 10.7 and later. + To create a symmetrical key call SecKeyGenerateSymmetric. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_GenerateKeyP (CSSM_CC_HANDLE CCHandle, + uint32 KeyUsage, + uint32 KeyAttr, + const CSSM_DATA *KeyLabel, + const CSSM_RESOURCE_CONTROL_CONTEXT *CredAndAclEntry, + CSSM_KEY_PTR Key, + CSSM_PRIVILEGE Privilege) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_GenerateKeyPair has been deprecated in 10.7 and later. + To create an asymmetrical key call SecKeyGeneratePair. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_GenerateKeyPair (CSSM_CC_HANDLE CCHandle, + uint32 PublicKeyUsage, + uint32 PublicKeyAttr, + const CSSM_DATA *PublicKeyLabel, + CSSM_KEY_PTR PublicKey, + uint32 PrivateKeyUsage, + uint32 PrivateKeyAttr, + const CSSM_DATA *PrivateKeyLabel, + const CSSM_RESOURCE_CONTROL_CONTEXT *CredAndAclEntry, + CSSM_KEY_PTR PrivateKey) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_GenerateKeyPairP has been deprecated in 10.7 and later. + To create an asymmetrical key call SecKeyGeneratePair. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_GenerateKeyPairP (CSSM_CC_HANDLE CCHandle, + uint32 PublicKeyUsage, + uint32 PublicKeyAttr, + const CSSM_DATA *PublicKeyLabel, + CSSM_KEY_PTR PublicKey, + uint32 PrivateKeyUsage, + uint32 PrivateKeyAttr, + const CSSM_DATA *PrivateKeyLabel, + const CSSM_RESOURCE_CONTROL_CONTEXT *CredAndAclEntry, + CSSM_KEY_PTR PrivateKey, + CSSM_PRIVILEGE Privilege) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_GenerateRandom has been deprecated in 10.7 and later. + To get random data call SecRandomCopyBytes + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_GenerateRandom (CSSM_CC_HANDLE CCHandle, + CSSM_DATA_PTR RandomNumber) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_CSP_ObtainPrivateKeyFromPublicKey has been deprecated in 10.7 and later. + There is not currently a direct replacement for this API + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_CSP_ObtainPrivateKeyFromPublicKey (CSSM_CSP_HANDLE CSPHandle, + const CSSM_KEY *PublicKey, + CSSM_KEY_PTR PrivateKey) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_WrapKey has been deprecated in 10.7 and later. + This is replaced with the SecKeyWrapSymmetric API. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_WrapKey (CSSM_CC_HANDLE CCHandle, + const CSSM_ACCESS_CREDENTIALS *AccessCred, + const CSSM_KEY *Key, + const CSSM_DATA *DescriptiveData, + CSSM_WRAP_KEY_PTR WrappedKey) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_UnwrapKey has been deprecated in 10.7 and later. + This is replaced with the SecKeyUnwrapSymmetric API. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_UnwrapKey (CSSM_CC_HANDLE CCHandle, + const CSSM_KEY *PublicKey, + const CSSM_WRAP_KEY *WrappedKey, + uint32 KeyUsage, + uint32 KeyAttr, + const CSSM_DATA *KeyLabel, + const CSSM_RESOURCE_CONTROL_CONTEXT *CredAndAclEntry, + CSSM_KEY_PTR UnwrappedKey, + CSSM_DATA_PTR DescriptiveData) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_WrapKeyP has been deprecated in 10.7 and later. + This is replaced with the SecKeyWrapSymmetric API. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_WrapKeyP (CSSM_CC_HANDLE CCHandle, + const CSSM_ACCESS_CREDENTIALS *AccessCred, + const CSSM_KEY *Key, + const CSSM_DATA *DescriptiveData, + CSSM_WRAP_KEY_PTR WrappedKey, + CSSM_PRIVILEGE Privilege) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_WrapKeyP has been deprecated in 10.7 and later. + This is replaced with the SecKeyUnwrapSymmetric API. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_UnwrapKeyP (CSSM_CC_HANDLE CCHandle, + const CSSM_KEY *PublicKey, + const CSSM_WRAP_KEY *WrappedKey, + uint32 KeyUsage, + uint32 KeyAttr, + const CSSM_DATA *KeyLabel, + const CSSM_RESOURCE_CONTROL_CONTEXT *CredAndAclEntry, + CSSM_KEY_PTR UnwrappedKey, + CSSM_DATA_PTR DescriptiveData, + CSSM_PRIVILEGE Privilege) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_DeriveKey has been deprecated in 10.7 and later. + This is replaced with the SecKeyDeriveFromPassword API. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_DeriveKey (CSSM_CC_HANDLE CCHandle, + CSSM_DATA_PTR Param, + uint32 KeyUsage, + uint32 KeyAttr, + const CSSM_DATA *KeyLabel, + const CSSM_RESOURCE_CONTROL_CONTEXT *CredAndAclEntry, + CSSM_KEY_PTR DerivedKey) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_FreeKey has been deprecated in 10.7 and later. There is no + alternate API. If the key in question is in a keychain calling + SecItemDelete will delete the key. If it is just a free standing key + calling CFRelease on the SecKeyRef will delete the key. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_FreeKey (CSSM_CSP_HANDLE CSPHandle, + const CSSM_ACCESS_CREDENTIALS *AccessCred, + CSSM_KEY_PTR KeyPtr, + CSSM_BOOL Delete) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_GenerateAlgorithmParams has been deprecated in 10.7 and later. + There is no alternate API as this call is only needed when calling + CDSA APIs + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_GenerateAlgorithmParams (CSSM_CC_HANDLE CCHandle, + uint32 ParamBits, + CSSM_DATA_PTR Param) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + + +/* Miscellaneous Functions for Cryptographic Services */ + +/* -------------------------------------------------------------------------- + CSSM_CSP_GetOperationalStatistics has been deprecated in 10.7 and later. + There is no alternate API as this call is only needed when calling + CDSA APIs + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_CSP_GetOperationalStatistics (CSSM_CSP_HANDLE CSPHandle, + CSSM_CSP_OPERATIONAL_STATISTICS *Statistics) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + + +/* -------------------------------------------------------------------------- + CSSM_GetTimeValue has been deprecated in 10.7 and later. + There is no alternate API as this call is only needed when calling + CDSA APIs + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_GetTimeValue (CSSM_CSP_HANDLE CSPHandle, + CSSM_ALGORITHMS TimeAlgorithm, + CSSM_DATA *TimeData) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_RetrieveUniqueId has been deprecated in 10.7 and later. + There is no alternate API as this call is only needed when calling + CDSA APIs. One could call CFUUIDCreate to create a unique ID. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_RetrieveUniqueId (CSSM_CSP_HANDLE CSPHandle, + CSSM_DATA_PTR UniqueID) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_RetrieveCounter has been deprecated in 10.7 and later. + There is no alternate API as this call is only needed when calling + CDSA APIs + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_RetrieveCounter (CSSM_CSP_HANDLE CSPHandle, + CSSM_DATA_PTR Counter) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_VerifyDevice has been deprecated in 10.7 and later. + There is no alternate API as this call is only needed when calling + CDSA APIs + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_VerifyDevice (CSSM_CSP_HANDLE CSPHandle, + const CSSM_DATA *DeviceCert) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + + +/* Extensibility Functions for Cryptographic Services */ + +/* -------------------------------------------------------------------------- + CSSM_CSP_PassThrough has been deprecated in 10.7 and later. + There is no alternate API as this call is only needed when calling + CDSA APIs + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_CSP_PassThrough (CSSM_CC_HANDLE CCHandle, + uint32 PassThroughId, + const void *InData, + void **OutData) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + + +/* Trust Policy Operations */ + +/* -------------------------------------------------------------------------- + CSSM_TP_SubmitCredRequest has been deprecated in 10.7 and later. + There is currently no direct replacement. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_TP_SubmitCredRequest (CSSM_TP_HANDLE TPHandle, + const CSSM_TP_AUTHORITY_ID *PreferredAuthority, + CSSM_TP_AUTHORITY_REQUEST_TYPE RequestType, + const CSSM_TP_REQUEST_SET *RequestInput, + const CSSM_TP_CALLERAUTH_CONTEXT *CallerAuthContext, + sint32 *EstimatedTime, + CSSM_DATA_PTR ReferenceIdentifier) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_TP_RetrieveCredResult has been deprecated in 10.7 and later. + There is currently no direct replacement. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_TP_RetrieveCredResult (CSSM_TP_HANDLE TPHandle, + const CSSM_DATA *ReferenceIdentifier, + const CSSM_TP_CALLERAUTH_CONTEXT *CallerAuthCredentials, + sint32 *EstimatedTime, + CSSM_BOOL *ConfirmationRequired, + CSSM_TP_RESULT_SET_PTR *RetrieveOutput) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_TP_ConfirmCredResult has been deprecated in 10.7 and later. + There is currently no direct replacement. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_TP_ConfirmCredResult (CSSM_TP_HANDLE TPHandle, + const CSSM_DATA *ReferenceIdentifier, + const CSSM_TP_CALLERAUTH_CONTEXT *CallerAuthCredentials, + const CSSM_TP_CONFIRM_RESPONSE *Responses, + const CSSM_TP_AUTHORITY_ID *PreferredAuthority) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_TP_ReceiveConfirmation has been deprecated in 10.7 and later. + There is currently no direct replacement. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_TP_ReceiveConfirmation (CSSM_TP_HANDLE TPHandle, + const CSSM_DATA *ReferenceIdentifier, + CSSM_TP_CONFIRM_RESPONSE_PTR *Responses, + sint32 *ElapsedTime) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_TP_CertReclaimKey has been deprecated in 10.7 and later. + There is currently no direct replacement. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_TP_CertReclaimKey (CSSM_TP_HANDLE TPHandle, + const CSSM_CERTGROUP *CertGroup, + uint32 CertIndex, + CSSM_LONG_HANDLE KeyCacheHandle, + CSSM_CSP_HANDLE CSPHandle, + const CSSM_RESOURCE_CONTROL_CONTEXT *CredAndAclEntry) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_TP_CertReclaimAbort has been deprecated in 10.7 and later. + There is currently no direct replacement. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_TP_CertReclaimAbort (CSSM_TP_HANDLE TPHandle, + CSSM_LONG_HANDLE KeyCacheHandle) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_TP_FormRequest has been deprecated in 10.7 and later. + There is currently no direct replacement. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_TP_FormRequest (CSSM_TP_HANDLE TPHandle, + const CSSM_TP_AUTHORITY_ID *PreferredAuthority, + CSSM_TP_FORM_TYPE FormType, + CSSM_DATA_PTR BlankForm) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_TP_FormSubmit has been deprecated in 10.7 and later. + There is currently no direct replacement. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_TP_FormSubmit (CSSM_TP_HANDLE TPHandle, + CSSM_TP_FORM_TYPE FormType, + const CSSM_DATA *Form, + const CSSM_TP_AUTHORITY_ID *ClearanceAuthority, + const CSSM_TP_AUTHORITY_ID *RepresentedAuthority, + CSSM_ACCESS_CREDENTIALS_PTR Credentials) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_TP_CertGroupVerify has been deprecated in 10.7 and later. + There is currently no direct replacement. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_TP_CertGroupVerify (CSSM_TP_HANDLE TPHandle, + CSSM_CL_HANDLE CLHandle, + CSSM_CSP_HANDLE CSPHandle, + const CSSM_CERTGROUP *CertGroupToBeVerified, + const CSSM_TP_VERIFY_CONTEXT *VerifyContext, + CSSM_TP_VERIFY_CONTEXT_RESULT_PTR VerifyContextResult) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_TP_CertCreateTemplate has been deprecated in 10.7 and later. + There is currently no direct replacement. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_TP_CertCreateTemplate (CSSM_TP_HANDLE TPHandle, + CSSM_CL_HANDLE CLHandle, + uint32 NumberOfFields, + const CSSM_FIELD *CertFields, + CSSM_DATA_PTR CertTemplate) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_TP_CertGetAllTemplateFields has been deprecated in 10.7 and later. + There is currently no direct replacement. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_TP_CertGetAllTemplateFields (CSSM_TP_HANDLE TPHandle, + CSSM_CL_HANDLE CLHandle, + const CSSM_DATA *CertTemplate, + uint32 *NumberOfFields, + CSSM_FIELD_PTR *CertFields) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_TP_CertSign has been deprecated in 10.7 and later. + The replacement API is SecSignTransformCreate. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_TP_CertSign (CSSM_TP_HANDLE TPHandle, + CSSM_CL_HANDLE CLHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_DATA *CertTemplateToBeSigned, + const CSSM_CERTGROUP *SignerCertGroup, + const CSSM_TP_VERIFY_CONTEXT *SignerVerifyContext, + CSSM_TP_VERIFY_CONTEXT_RESULT_PTR SignerVerifyResult, + CSSM_DATA_PTR SignedCert) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_TP_CrlVerify has been deprecated in 10.7 and later. + The replacement API is SecVerifyTransformCreate. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_TP_CrlVerify (CSSM_TP_HANDLE TPHandle, + CSSM_CL_HANDLE CLHandle, + CSSM_CSP_HANDLE CSPHandle, + const CSSM_ENCODED_CRL *CrlToBeVerified, + const CSSM_CERTGROUP *SignerCertGroup, + const CSSM_TP_VERIFY_CONTEXT *VerifyContext, + CSSM_TP_VERIFY_CONTEXT_RESULT_PTR RevokerVerifyResult) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_TP_CrlCreateTemplate has been deprecated in 10.7 and later. + There is currently no direct replacement. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_TP_CrlCreateTemplate (CSSM_TP_HANDLE TPHandle, + CSSM_CL_HANDLE CLHandle, + uint32 NumberOfFields, + const CSSM_FIELD *CrlFields, + CSSM_DATA_PTR NewCrlTemplate) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_TP_CertRevoke has been deprecated in 10.7 and later. + There is currently no direct replacement. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_TP_CertRevoke (CSSM_TP_HANDLE TPHandle, + CSSM_CL_HANDLE CLHandle, + CSSM_CSP_HANDLE CSPHandle, + const CSSM_DATA *OldCrlTemplate, + const CSSM_CERTGROUP *CertGroupToBeRevoked, + const CSSM_CERTGROUP *RevokerCertGroup, + const CSSM_TP_VERIFY_CONTEXT *RevokerVerifyContext, + CSSM_TP_VERIFY_CONTEXT_RESULT_PTR RevokerVerifyResult, + CSSM_TP_CERTCHANGE_REASON Reason, + CSSM_DATA_PTR NewCrlTemplate) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_TP_CertRemoveFromCrlTemplate has been deprecated in 10.7 and later. + There is currently no direct replacement. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_TP_CertRemoveFromCrlTemplate (CSSM_TP_HANDLE TPHandle, + CSSM_CL_HANDLE CLHandle, + CSSM_CSP_HANDLE CSPHandle, + const CSSM_DATA *OldCrlTemplate, + const CSSM_CERTGROUP *CertGroupToBeRemoved, + const CSSM_CERTGROUP *RevokerCertGroup, + const CSSM_TP_VERIFY_CONTEXT *RevokerVerifyContext, + CSSM_TP_VERIFY_CONTEXT_RESULT_PTR RevokerVerifyResult, + CSSM_DATA_PTR NewCrlTemplate) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_TP_CrlSign has been deprecated in 10.7 and later. + The replacement API is SecVerifyTransformCreate. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_TP_CrlSign (CSSM_TP_HANDLE TPHandle, + CSSM_CL_HANDLE CLHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_ENCODED_CRL *CrlToBeSigned, + const CSSM_CERTGROUP *SignerCertGroup, + const CSSM_TP_VERIFY_CONTEXT *SignerVerifyContext, + CSSM_TP_VERIFY_CONTEXT_RESULT_PTR SignerVerifyResult, + CSSM_DATA_PTR SignedCrl) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_TP_ApplyCrlToDb has been deprecated in 10.7 and later. + There is currently no direct replacement. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_TP_ApplyCrlToDb (CSSM_TP_HANDLE TPHandle, + CSSM_CL_HANDLE CLHandle, + CSSM_CSP_HANDLE CSPHandle, + const CSSM_ENCODED_CRL *CrlToBeApplied, + const CSSM_CERTGROUP *SignerCertGroup, + const CSSM_TP_VERIFY_CONTEXT *ApplyCrlVerifyContext, + CSSM_TP_VERIFY_CONTEXT_RESULT_PTR ApplyCrlVerifyResult) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_TP_CertGroupConstruct has been deprecated in 10.7 and later. + There is currently no direct replacement. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_TP_CertGroupConstruct (CSSM_TP_HANDLE TPHandle, + CSSM_CL_HANDLE CLHandle, + CSSM_CSP_HANDLE CSPHandle, + const CSSM_DL_DB_LIST *DBList, + const void *ConstructParams, + const CSSM_CERTGROUP *CertGroupFrag, + CSSM_CERTGROUP_PTR *CertGroup) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_TP_CertGroupPrune has been deprecated in 10.7 and later. + There is currently no direct replacement. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_TP_CertGroupPrune (CSSM_TP_HANDLE TPHandle, + CSSM_CL_HANDLE CLHandle, + const CSSM_DL_DB_LIST *DBList, + const CSSM_CERTGROUP *OrderedCertGroup, + CSSM_CERTGROUP_PTR *PrunedCertGroup) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_TP_CertGroupToTupleGroup has been deprecated in 10.7 and later. + There is currently no direct replacement. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_TP_CertGroupToTupleGroup (CSSM_TP_HANDLE TPHandle, + CSSM_CL_HANDLE CLHandle, + const CSSM_CERTGROUP *CertGroup, + CSSM_TUPLEGROUP_PTR *TupleGroup) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_TP_TupleGroupToCertGroup has been deprecated in 10.7 and later. + There is currently no direct replacement. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_TP_TupleGroupToCertGroup (CSSM_TP_HANDLE TPHandle, + CSSM_CL_HANDLE CLHandle, + const CSSM_TUPLEGROUP *TupleGroup, + CSSM_CERTGROUP_PTR *CertTemplates) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_TP_PassThrough has been deprecated in 10.7 and later. + There is no alternate API as this call is only needed when calling + CDSA APIs + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_TP_PassThrough (CSSM_TP_HANDLE TPHandle, + CSSM_CL_HANDLE CLHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_DL_DB_LIST *DBList, + uint32 PassThroughId, + const void *InputParams, + void **OutputParams) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + + +/* Authorization Computation Operations */ + +/* -------------------------------------------------------------------------- + CSSM_AC_AuthCompute has been deprecated in 10.7 and later. + Please see the APIs in the SecAccess.h file for a replacement. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_AC_AuthCompute (CSSM_AC_HANDLE ACHandle, + const CSSM_TUPLEGROUP *BaseAuthorizations, + const CSSM_TUPLEGROUP *Credentials, + uint32 NumberOfRequestors, + const CSSM_LIST *Requestors, + const CSSM_LIST *RequestedAuthorizationPeriod, + const CSSM_LIST *RequestedAuthorization, + CSSM_TUPLEGROUP_PTR AuthorizationResult) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_AC_PassThrough has been deprecated in 10.7 and later. + Please see the APIs in the SecAccess.h file for a replacement. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_AC_PassThrough (CSSM_AC_HANDLE ACHandle, + CSSM_TP_HANDLE TPHandle, + CSSM_CL_HANDLE CLHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_DL_DB_LIST *DBList, + uint32 PassThroughId, + const void *InputParams, + void **OutputParams) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + + +/* Certificate Library Operations */ + +/* -------------------------------------------------------------------------- + CSSM_CL_CertCreateTemplate has been deprecated in 10.7 and later. + There is currently no direct replacement. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_CL_CertCreateTemplate (CSSM_CL_HANDLE CLHandle, + uint32 NumberOfFields, + const CSSM_FIELD *CertFields, + CSSM_DATA_PTR CertTemplate) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_CL_CertGetAllTemplateFields has been deprecated in 10.7 and later. + There is currently no direct replacement. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_CL_CertGetAllTemplateFields (CSSM_CL_HANDLE CLHandle, + const CSSM_DATA *CertTemplate, + uint32 *NumberOfFields, + CSSM_FIELD_PTR *CertFields) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_CL_CertSign has been deprecated in 10.7 and later. + There is currently no direct replacement. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_CL_CertSign (CSSM_CL_HANDLE CLHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_DATA *CertTemplate, + const CSSM_FIELD *SignScope, + uint32 ScopeSize, + CSSM_DATA_PTR SignedCert) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_CL_CertVerify has been deprecated in 10.7 and later. + There is currently no direct replacement. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_CL_CertVerify (CSSM_CL_HANDLE CLHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_DATA *CertToBeVerified, + const CSSM_DATA *SignerCert, + const CSSM_FIELD *VerifyScope, + uint32 ScopeSize) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_CL_CertVerifyWithKey has been deprecated in 10.7 and later. + There is currently no direct replacement. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_CL_CertVerifyWithKey (CSSM_CL_HANDLE CLHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_DATA *CertToBeVerified) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_CL_CertVerifyWithKey has been deprecated in 10.7 and later. + This is replaced with the SecCertificateCopyValues API. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_CL_CertGetFirstFieldValue (CSSM_CL_HANDLE CLHandle, + const CSSM_DATA *Cert, + const CSSM_OID *CertField, + CSSM_HANDLE_PTR ResultsHandle, + uint32 *NumberOfMatchedFields, + CSSM_DATA_PTR *Value) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_CL_CertGetNextFieldValue has been deprecated in 10.7 and later. + This is replaced with the SecCertificateCopyValues API. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_CL_CertGetNextFieldValue (CSSM_CL_HANDLE CLHandle, + CSSM_HANDLE ResultsHandle, + CSSM_DATA_PTR *Value) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_CL_CertAbortQuery has been deprecated in 10.7 and later. + There is no alternate API as this call is only needed when calling + CDSA APIs. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_CL_CertAbortQuery (CSSM_CL_HANDLE CLHandle, + CSSM_HANDLE ResultsHandle) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_CL_CertGetKeyInfo has been deprecated in 10.7 and later. + This is replaced with the SecCertificateCopyValues API. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_CL_CertGetKeyInfo (CSSM_CL_HANDLE CLHandle, + const CSSM_DATA *Cert, + CSSM_KEY_PTR *Key) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_CL_CertGetAllFields has been deprecated in 10.7 and later. + This is replaced with the SecCertificateCopyValues API. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_CL_CertGetAllFields (CSSM_CL_HANDLE CLHandle, + const CSSM_DATA *Cert, + uint32 *NumberOfFields, + CSSM_FIELD_PTR *CertFields) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_CL_FreeFields has been deprecated in 10.7 and later. + There is no alternate API as this call is only needed when calling + CDSA APIs. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_CL_FreeFields (CSSM_CL_HANDLE CLHandle, + uint32 NumberOfFields, + CSSM_FIELD_PTR *Fields) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_CL_FreeFieldValue has been deprecated in 10.7 and later. + There is no alternate API as this call is only needed when calling + CDSA APIs. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_CL_FreeFieldValue (CSSM_CL_HANDLE CLHandle, + const CSSM_OID *CertOrCrlOid, + CSSM_DATA_PTR Value) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_CL_CertCache has been deprecated in 10.7 and later. + There is no alternate API as this call is only needed when calling + CDSA APIs. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_CL_CertCache (CSSM_CL_HANDLE CLHandle, + const CSSM_DATA *Cert, + CSSM_HANDLE_PTR CertHandle) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_CL_CertGetFirstCachedFieldValue has been deprecated in 10.7 and later. + This is replaced with the SecCertificateCopyValues API + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_CL_CertGetFirstCachedFieldValue (CSSM_CL_HANDLE CLHandle, + CSSM_HANDLE CertHandle, + const CSSM_OID *CertField, + CSSM_HANDLE_PTR ResultsHandle, + uint32 *NumberOfMatchedFields, + CSSM_DATA_PTR *Value) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_CL_CertGetNextCachedFieldValue has been deprecated in 10.7 and later. + This is replaced with the SecCertificateCopyValues API + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_CL_CertGetNextCachedFieldValue (CSSM_CL_HANDLE CLHandle, + CSSM_HANDLE ResultsHandle, + CSSM_DATA_PTR *Value) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_CL_CertAbortCache has been deprecated in 10.7 and later. + There is no alternate API as this call is only needed when calling + CDSA APIs. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_CL_CertAbortCache (CSSM_CL_HANDLE CLHandle, + CSSM_HANDLE CertHandle) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_CL_CertGroupToSignedBundle has been deprecated in 10.7 and later. + There is no alternate API as this call is only needed when calling + CDSA APIs. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_CL_CertGroupToSignedBundle (CSSM_CL_HANDLE CLHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_CERTGROUP *CertGroupToBundle, + const CSSM_CERT_BUNDLE_HEADER *BundleInfo, + CSSM_DATA_PTR SignedBundle) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_CL_CertGroupFromVerifiedBundle has been deprecated in 10.7 and later. + There is no alternate API as this call is only needed when calling + CDSA APIs. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_CL_CertGroupFromVerifiedBundle (CSSM_CL_HANDLE CLHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_CERT_BUNDLE *CertBundle, + const CSSM_DATA *SignerCert, + CSSM_CERTGROUP_PTR *CertGroup) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_CL_CertDescribeFormat has been deprecated in 10.7 and later. + There is no alternate API as this call is only needed when calling + CDSA APIs. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_CL_CertDescribeFormat (CSSM_CL_HANDLE CLHandle, + uint32 *NumberOfFields, + CSSM_OID_PTR *OidList) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_CL_CrlCreateTemplate has been deprecated in 10.7 and later. + There is no alternate API as this call is only needed when calling + CDSA APIs. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_CL_CrlCreateTemplate (CSSM_CL_HANDLE CLHandle, + uint32 NumberOfFields, + const CSSM_FIELD *CrlTemplate, + CSSM_DATA_PTR NewCrl) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_CL_CrlSetFields has been deprecated in 10.7 and later. + There is no alternate API as this call is only needed when calling + CDSA APIs. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_CL_CrlSetFields (CSSM_CL_HANDLE CLHandle, + uint32 NumberOfFields, + const CSSM_FIELD *CrlTemplate, + const CSSM_DATA *OldCrl, + CSSM_DATA_PTR ModifiedCrl) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_CL_CrlAddCert has been deprecated in 10.7 and later. + There is currently no direct replacement. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_CL_CrlAddCert (CSSM_CL_HANDLE CLHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_DATA *Cert, + uint32 NumberOfFields, + const CSSM_FIELD *CrlEntryFields, + const CSSM_DATA *OldCrl, + CSSM_DATA_PTR NewCrl) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_CL_CrlRemoveCert has been deprecated in 10.7 and later. + There is currently no direct replacement. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_CL_CrlRemoveCert (CSSM_CL_HANDLE CLHandle, + const CSSM_DATA *Cert, + const CSSM_DATA *OldCrl, + CSSM_DATA_PTR NewCrl) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_CL_CrlSign has been deprecated in 10.7 and later. + The replacement API would be to use the SecSignTransformCreate transform. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_CL_CrlSign (CSSM_CL_HANDLE CLHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_DATA *UnsignedCrl, + const CSSM_FIELD *SignScope, + uint32 ScopeSize, + CSSM_DATA_PTR SignedCrl) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_CL_CrlVerify has been deprecated in 10.7 and later. + The replacement API would be to use the SecVerifyTransformCreate transform. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_CL_CrlVerify (CSSM_CL_HANDLE CLHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_DATA *CrlToBeVerified, + const CSSM_DATA *SignerCert, + const CSSM_FIELD *VerifyScope, + uint32 ScopeSize) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_CL_CrlVerifyWithKey has been deprecated in 10.7 and later. + The replacement API would be to use the SecVerifyTransformCreate transform. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_CL_CrlVerifyWithKey (CSSM_CL_HANDLE CLHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_DATA *CrlToBeVerified) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_CL_IsCertInCrl has been deprecated in 10.7 and later. + There is no alternate API as this call is only needed when calling + CDSA APIs. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_CL_IsCertInCrl (CSSM_CL_HANDLE CLHandle, + const CSSM_DATA *Cert, + const CSSM_DATA *Crl, + CSSM_BOOL *CertFound) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_CL_CrlGetFirstFieldValue has been deprecated in 10.7 and later. + This is replaced with the SecCertificateCopyValues API + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_CL_CrlGetFirstFieldValue (CSSM_CL_HANDLE CLHandle, + const CSSM_DATA *Crl, + const CSSM_OID *CrlField, + CSSM_HANDLE_PTR ResultsHandle, + uint32 *NumberOfMatchedFields, + CSSM_DATA_PTR *Value) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_CL_CrlGetNextFieldValue has been deprecated in 10.7 and later. + This is replaced with the SecCertificateCopyValues API + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_CL_CrlGetNextFieldValue (CSSM_CL_HANDLE CLHandle, + CSSM_HANDLE ResultsHandle, + CSSM_DATA_PTR *Value) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_CL_CrlAbortQuery has been deprecated in 10.7 and later. + There is no alternate API as this call is only needed when calling + CDSA APIs. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_CL_CrlAbortQuery (CSSM_CL_HANDLE CLHandle, + CSSM_HANDLE ResultsHandle) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_CL_CrlGetAllFields has been deprecated in 10.7 and later. + This is replaced with the SecCertificateCopyValues API + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_CL_CrlGetAllFields (CSSM_CL_HANDLE CLHandle, + const CSSM_DATA *Crl, + uint32 *NumberOfCrlFields, + CSSM_FIELD_PTR *CrlFields) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_CL_CrlCache has been deprecated in 10.7 and later. + There is no alternate API as this call is only needed when calling + CDSA APIs. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_CL_CrlCache (CSSM_CL_HANDLE CLHandle, + const CSSM_DATA *Crl, + CSSM_HANDLE_PTR CrlHandle) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_CL_IsCertInCachedCrl has been deprecated in 10.7 and later. + There is no alternate API as this call is only needed when calling + CDSA APIs. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_CL_IsCertInCachedCrl (CSSM_CL_HANDLE CLHandle, + const CSSM_DATA *Cert, + CSSM_HANDLE CrlHandle, + CSSM_BOOL *CertFound, + CSSM_DATA_PTR CrlRecordIndex) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_CL_CrlGetFirstCachedFieldValue has been deprecated in 10.7 and later. + This is replaced with the SecCertificateCopyValues API + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_CL_CrlGetFirstCachedFieldValue (CSSM_CL_HANDLE CLHandle, + CSSM_HANDLE CrlHandle, + const CSSM_DATA *CrlRecordIndex, + const CSSM_OID *CrlField, + CSSM_HANDLE_PTR ResultsHandle, + uint32 *NumberOfMatchedFields, + CSSM_DATA_PTR *Value) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_CL_CrlGetNextCachedFieldValue has been deprecated in 10.7 and later. + This is replaced with the SecCertificateCopyValues API + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_CL_CrlGetNextCachedFieldValue (CSSM_CL_HANDLE CLHandle, + CSSM_HANDLE ResultsHandle, + CSSM_DATA_PTR *Value) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_CL_CrlGetAllCachedRecordFields has been deprecated in 10.7 and later. + This is replaced with the SecCertificateCopyValues API + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_CL_CrlGetAllCachedRecordFields (CSSM_CL_HANDLE CLHandle, + CSSM_HANDLE CrlHandle, + const CSSM_DATA *CrlRecordIndex, + uint32 *NumberOfFields, + CSSM_FIELD_PTR *CrlFields) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_CL_CrlAbortCache has been deprecated in 10.7 and later. + There is no alternate API as this call is only needed when calling + CDSA APIs. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_CL_CrlAbortCache (CSSM_CL_HANDLE CLHandle, + CSSM_HANDLE CrlHandle) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_CL_CrlDescribeFormat has been deprecated in 10.7 and later. + There is no alternate API as this call is only needed when calling + CDSA APIs. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_CL_CrlDescribeFormat (CSSM_CL_HANDLE CLHandle, + uint32 *NumberOfFields, + CSSM_OID_PTR *OidList) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_CL_PassThrough has been deprecated in 10.7 and later. + There is no alternate API as this call is only needed when calling + CDSA APIs. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_CL_PassThrough (CSSM_CL_HANDLE CLHandle, + CSSM_CC_HANDLE CCHandle, + uint32 PassThroughId, + const void *InputParams, + void **OutputParams) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + + +/* Data Storage Library Operations */ + +/* -------------------------------------------------------------------------- + CSSM_DL_DbOpen has been deprecated in 10.7 and later. + The replacement API is SecKeychainOpen + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_DL_DbOpen (CSSM_DL_HANDLE DLHandle, + const char *DbName, + const CSSM_NET_ADDRESS *DbLocation, + CSSM_DB_ACCESS_TYPE AccessRequest, + const CSSM_ACCESS_CREDENTIALS *AccessCred, + const void *OpenParameters, + CSSM_DB_HANDLE *DbHandle) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_DL_DbClose has been deprecated in 10.7 and later. There is no alternate + API as this call is only needed when calling CDSA APIs + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_DL_DbClose (CSSM_DL_DB_HANDLE DLDBHandle) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_DL_DbCreate has been deprecated in 10.7 and later. + The replacement API is SecKeychainCreate + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_DL_DbCreate (CSSM_DL_HANDLE DLHandle, + const char *DbName, + const CSSM_NET_ADDRESS *DbLocation, + const CSSM_DBINFO *DBInfo, + CSSM_DB_ACCESS_TYPE AccessRequest, + const CSSM_RESOURCE_CONTROL_CONTEXT *CredAndAclEntry, + const void *OpenParameters, + CSSM_DB_HANDLE *DbHandle) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_DL_DbDelete has been deprecated in 10.7 and later. + The replacement API is SecKeychainDelete + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_DL_DbDelete (CSSM_DL_HANDLE DLHandle, + const char *DbName, + const CSSM_NET_ADDRESS *DbLocation, + const CSSM_ACCESS_CREDENTIALS *AccessCred) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_DL_CreateRelation has been deprecated in 10.7 and later. + There is no alternate API as this call is only needed when calling + CDSA APIs + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_DL_CreateRelation (CSSM_DL_DB_HANDLE DLDBHandle, + CSSM_DB_RECORDTYPE RelationID, + const char *RelationName, + uint32 NumberOfAttributes, + const CSSM_DB_SCHEMA_ATTRIBUTE_INFO *pAttributeInfo, + uint32 NumberOfIndexes, + const CSSM_DB_SCHEMA_INDEX_INFO *pIndexInfo) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_DL_DestroyRelation has been deprecated in 10.7 and later. + There is no alternate API as this call is only needed when calling + CDSA APIs + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_DL_DestroyRelation (CSSM_DL_DB_HANDLE DLDBHandle, + CSSM_DB_RECORDTYPE RelationID) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_DL_Authenticate has been deprecated in 10.7 and later. + The replacement API is SecKeychainUnlock + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_DL_Authenticate (CSSM_DL_DB_HANDLE DLDBHandle, + CSSM_DB_ACCESS_TYPE AccessRequest, + const CSSM_ACCESS_CREDENTIALS *AccessCred) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_DL_GetDbAcl has been deprecated in 10.7 and later. + There is no alternate API as this call is only needed when calling + CDSA APIs + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_DL_GetDbAcl (CSSM_DL_DB_HANDLE DLDBHandle, + const CSSM_STRING *SelectionTag, + uint32 *NumberOfAclInfos, + CSSM_ACL_ENTRY_INFO_PTR *AclInfos) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_DL_ChangeDbAcl has been deprecated in 10.7 and later. + There is no alternate API as this call is only needed when calling + CDSA APIs + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_DL_ChangeDbAcl (CSSM_DL_DB_HANDLE DLDBHandle, + const CSSM_ACCESS_CREDENTIALS *AccessCred, + const CSSM_ACL_EDIT *AclEdit) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_DL_GetDbOwner has been deprecated in 10.7 and later. + There is no alternate API as this call is only needed when calling + CDSA APIs + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_DL_GetDbOwner (CSSM_DL_DB_HANDLE DLDBHandle, + CSSM_ACL_OWNER_PROTOTYPE_PTR Owner) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_DL_ChangeDbOwner has been deprecated in 10.7 and later. + There is no alternate API as this call is only needed when calling + CDSA APIs + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_DL_ChangeDbOwner (CSSM_DL_DB_HANDLE DLDBHandle, + const CSSM_ACCESS_CREDENTIALS *AccessCred, + const CSSM_ACL_OWNER_PROTOTYPE *NewOwner) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_DL_GetDbNames has been deprecated in 10.7 and later. + There is no alternate API as this call is only needed when calling + CDSA APIs + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_DL_GetDbNames (CSSM_DL_HANDLE DLHandle, + CSSM_NAME_LIST_PTR *NameList) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_DL_GetDbNameFromHandle has been deprecated in 10.7 and later. + There is no alternate API as this call is only needed when calling + CDSA APIs + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_DL_GetDbNameFromHandle (CSSM_DL_DB_HANDLE DLDBHandle, + char **DbName) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_DL_FreeNameList has been deprecated in 10.7 and later. + There is no alternate API as this call is only needed when calling + CDSA APIs + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_DL_FreeNameList (CSSM_DL_HANDLE DLHandle, + CSSM_NAME_LIST_PTR NameList) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_DL_Authenticate has been deprecated in 10.7 and later. + The replacement API are SecKeychainAddInternetPassword, + SecKeychainAddGenericPassword, SecItemAdd + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_DL_DataInsert (CSSM_DL_DB_HANDLE DLDBHandle, + CSSM_DB_RECORDTYPE RecordType, + const CSSM_DB_RECORD_ATTRIBUTE_DATA *Attributes, + const CSSM_DATA *Data, + CSSM_DB_UNIQUE_RECORD_PTR *UniqueId) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_DL_Authenticate has been deprecated in 10.7 and later. + The replacement API is SecItemDelete + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_DL_DataDelete (CSSM_DL_DB_HANDLE DLDBHandle, + const CSSM_DB_UNIQUE_RECORD *UniqueRecordIdentifier) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_DL_Authenticate has been deprecated in 10.7 and later. + The replacement API is SecItemUpdate + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_DL_DataModify (CSSM_DL_DB_HANDLE DLDBHandle, + CSSM_DB_RECORDTYPE RecordType, + CSSM_DB_UNIQUE_RECORD_PTR UniqueRecordIdentifier, + const CSSM_DB_RECORD_ATTRIBUTE_DATA *AttributesToBeModified, + const CSSM_DATA *DataToBeModified, + CSSM_DB_MODIFY_MODE ModifyMode) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_DL_DataGetFirst has been deprecated in 10.7 and later. + There is no alternate API as this call is only needed when calling + CDSA APIs. SecItemCopyMatching may return multiple items if specified to + do so. The user could then retrieve the first in the list of items. + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_DL_DataGetFirst (CSSM_DL_DB_HANDLE DLDBHandle, + const CSSM_QUERY *Query, + CSSM_HANDLE_PTR ResultsHandle, + CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR Attributes, + CSSM_DATA_PTR Data, + CSSM_DB_UNIQUE_RECORD_PTR *UniqueId) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_DL_DataGetNext has been deprecated in 10.7 and later. + There is no alternate API as this call is only needed when calling + CDSA APIs. SecItemCopyMatching may return multiple items if specified to + do so. The user could then retrieve the items in the list + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_DL_DataGetNext (CSSM_DL_DB_HANDLE DLDBHandle, + CSSM_HANDLE ResultsHandle, + CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR Attributes, + CSSM_DATA_PTR Data, + CSSM_DB_UNIQUE_RECORD_PTR *UniqueId) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_DL_DataAbortQuery has been deprecated in 10.7 and later. + There is no alternate API as this call is only needed when calling + CDSA APIs + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_DL_DataAbortQuery (CSSM_DL_DB_HANDLE DLDBHandle, + CSSM_HANDLE ResultsHandle) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_DL_DataGetFromUniqueRecordId has been deprecated in 10.7 and later. + There is no alternate API as this call is only needed when calling + CDSA APIs + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_DL_DataGetFromUniqueRecordId (CSSM_DL_DB_HANDLE DLDBHandle, + const CSSM_DB_UNIQUE_RECORD *UniqueRecord, + CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR Attributes, + CSSM_DATA_PTR Data) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_DL_FreeUniqueRecord has been deprecated in 10.7 and later. + There is no alternate API as this call is only needed when calling + CDSA APIs + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_DL_FreeUniqueRecord (CSSM_DL_DB_HANDLE DLDBHandle, + CSSM_DB_UNIQUE_RECORD_PTR UniqueRecord) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* -------------------------------------------------------------------------- + CSSM_DL_PassThrough has been deprecated in 10.7 and later. + There is no alternate API as this call is only needed when calling + CDSA APIs + -------------------------------------------------------------------------- */ +CSSM_RETURN CSSMAPI +CSSM_DL_PassThrough (CSSM_DL_DB_HANDLE DLDBHandle, + uint32 PassThroughId, + const void *InputParams, + void **OutputParams) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +#ifdef __cplusplus +} +#endif + +#endif /* _CSSMAPI_H_ */ diff --git a/libsecurity_cssm/lib/cssmapple.h b/libsecurity_cssm/lib/cssmapple.h new file mode 100644 index 00000000..4a1e954d --- /dev/null +++ b/libsecurity_cssm/lib/cssmapple.h @@ -0,0 +1,1154 @@ +/* + * 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 + +#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 +}; + +/* 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, + + /* 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/libsecurity_cssm/lib/cssmapplePriv.h new file mode 100644 index 00000000..a60479d3 --- /dev/null +++ b/libsecurity_cssm/lib/cssmapplePriv.h @@ -0,0 +1,153 @@ +/* + * 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@ + * + * cssmapplePriv.h -- Private CSSM features specific to Apple's Implementation + */ + +#ifndef _CSSMAPPLE_PRIV_H_ +#define _CSSMAPPLE_PRIV_H_ 1 + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Options for X509TP's CSSM_TP_CertGroupVerify for policy + * CSSMOID_APPLE_TP_REVOCATION_OCSP. 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_OCSP_OPTS_VERSION 0 + +typedef uint32 CSSM_APPLE_TP_OCSP_OPT_FLAGS; +enum { + // require OCSP verification for each cert; default is "try" + CSSM_TP_ACTION_OCSP_REQUIRE_PER_CERT = 0x00000001, + // require OCSP verification for certs which claim an OCSP responder + CSSM_TP_ACTION_OCSP_REQUIRE_IF_RESP_PRESENT = 0x00000002, + // disable network OCSP transactions + CSSM_TP_ACTION_OCSP_DISABLE_NET = 0x00000004, + // disable reads from local OCSP cache + CSSM_TP_ACTION_OCSP_CACHE_READ_DISABLE = 0x00000008, + // disable reads from local OCSP cache + CSSM_TP_ACTION_OCSP_CACHE_WRITE_DISABLE = 0x00000010, + // if set and positive OCSP verify for given cert, no further revocation + // checking need be done on that cert + CSSM_TP_ACTION_OCSP_SUFFICIENT = 0x00000020, + // generate nonce in OCSP request + CSSM_TP_OCSP_GEN_NONCE = 0x00000040, + // when generating nonce, require matching nonce in response + CSSM_TP_OCSP_REQUIRE_RESP_NONCE = 0x00000080 +}; + +typedef struct { + uint32 Version; + CSSM_APPLE_TP_OCSP_OPT_FLAGS Flags; + CSSM_DATA_PTR LocalResponder; /* URI */ + CSSM_DATA_PTR LocalResponderCert; /* X509 DER encoded cert */ +} CSSM_APPLE_TP_OCSP_OPTIONS; + +enum +{ + /* Given a "master" and dependent keychain, make the dependent "syncable" to the master's secrets */ + CSSM_APPLECSPDL_CSP_RECODE = CSSM_APPLE_PRIVATE_CSPDL_CODE_8, + + /* Given a keychain item, return a record identifier */ + CSSM_APPLECSPDL_DB_GET_RECORD_IDENTIFIER = CSSM_APPLE_PRIVATE_CSPDL_CODE_9, + + // Get the blob for a database + CSSM_APPLECSPDL_DB_COPY_BLOB = CSSM_APPLE_PRIVATE_CSPDL_CODE_10, + + // enforce a bypass of crypto operations on insert + CSSM_APPLECSPDL_DB_INSERT_WITHOUT_ENCRYPTION = CSSM_APPLE_PRIVATE_CSPDL_CODE_11, + + // enforce a bypass of crypto operations on modify + CSSM_APPLECSPDL_DB_MODIFY_WITHOUT_ENCRYPTION = CSSM_APPLE_PRIVATE_CSPDL_CODE_12, + + // enforce a bypass of crypto operations on get + CSSM_APPLECSPDL_DB_GET_WITHOUT_ENCRYPTION = CSSM_APPLE_PRIVATE_CSPDL_CODE_13, + + // convert a record identifier to a CSSM_DB_RECORD_IDENTIFIER for the CSP/DL + CSSM_APPLECSPDL_DB_CONVERT_RECORD_IDENTIFIER = CSSM_APPLE_PRIVATE_CSPDL_CODE_14, + + // create the default records in a "blank" database + CSSM_APPLECSPDL_DB_CREATE_WITH_BLOB = CSSM_APPLE_PRIVATE_CSPDL_CODE_15, + + // query a DB to see if a relation exists + CSSM_APPLECSPDL_DB_RELATION_EXISTS = CSSM_APPLE_PRIVATE_CSPDL_CODE_16, + +}; + +/* AppleCSPDL passthrough parameters */ +typedef struct cssm_applecspdl_db_recode_parameters +{ + CSSM_DATA dbBlob; + CSSM_DATA extraData; +} CSSM_APPLECSPDL_RECODE_PARAMETERS, *CSSM_APPLECSPDL_RECODE_PARAMETERS_PTR; + +typedef struct cssm_applecspdl_db_copy_blob_parameters +{ + CSSM_DATA blob; +} CSSM_APPLECSPDL_DB_COPY_BLOB_PARAMETERS; + +typedef struct cssm_applecspdl_db_insert_without_encryption_parameters +{ + CSSM_DB_RECORDTYPE recordType; + CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR attributes; + CSSM_DATA data; +} CSSM_APPLECSPDL_DB_INSERT_WITHOUT_ENCRYPTION_PARAMETERS; + +typedef struct cssm_applecspdl_db_modify_without_encryption_parameters +{ + CSSM_DB_RECORDTYPE recordType; + CSSM_DB_UNIQUE_RECORD_PTR uniqueID; + CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR attributes; + CSSM_DATA *data; + CSSM_DB_MODIFY_MODE modifyMode; +} CSSM_APPLECSPDL_DB_MODIFY_WITHOUT_ENCRYPTION_PARAMETERS; + +typedef struct cssm_applecspdl_db_get_without_encryption_parameters +{ + CSSM_DB_UNIQUE_RECORD_PTR uniqueID; + CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR attributes; +} CSSM_APPLECSPDL_DB_GET_WITHOUT_ENCRYPTION_PARAMETERS; + +typedef struct cssm_applecspdl_db_create_with_blob_parameters +{ + const char *dbName; + const CSSM_NET_ADDRESS *dbLocation; + const CSSM_DBINFO *dbInfo; + CSSM_DB_ACCESS_TYPE accessRequest; + const CSSM_RESOURCE_CONTROL_CONTEXT *credAndAclEntry; + const void *openParameters; + const CSSM_DATA *blob; +} CSSM_APPLE_CSPDL_DB_CREATE_WITH_BLOB_PARAMETERS; + +#ifdef __cplusplus +} +#endif + +#endif /* _CSSMAPPLE_PRIV_H_ */ diff --git a/libsecurity_cssm/lib/cssmcli.h b/libsecurity_cssm/lib/cssmcli.h new file mode 100644 index 00000000..5fdffbc8 --- /dev/null +++ b/libsecurity_cssm/lib/cssmcli.h @@ -0,0 +1,242 @@ +/* + * Copyright (c) 1999-2001,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@ + * + * cssmcli.h -- Service Provider Interface for Certificate Library Modules + */ + +#ifndef _CSSMCLI_H_ +#define _CSSMCLI_H_ 1 + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct cssm_spi_cl_funcs { + CSSM_RETURN (CSSMCLI *CertCreateTemplate) + (CSSM_CL_HANDLE CLHandle, + uint32 NumberOfFields, + const CSSM_FIELD *CertFields, + CSSM_DATA_PTR CertTemplate); + CSSM_RETURN (CSSMCLI *CertGetAllTemplateFields) + (CSSM_CL_HANDLE CLHandle, + const CSSM_DATA *CertTemplate, + uint32 *NumberOfFields, + CSSM_FIELD_PTR *CertFields); + CSSM_RETURN (CSSMCLI *CertSign) + (CSSM_CL_HANDLE CLHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_DATA *CertTemplate, + const CSSM_FIELD *SignScope, + uint32 ScopeSize, + CSSM_DATA_PTR SignedCert); + CSSM_RETURN (CSSMCLI *CertVerify) + (CSSM_CL_HANDLE CLHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_DATA *CertToBeVerified, + const CSSM_DATA *SignerCert, + const CSSM_FIELD *VerifyScope, + uint32 ScopeSize); + CSSM_RETURN (CSSMCLI *CertVerifyWithKey) + (CSSM_CL_HANDLE CLHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_DATA *CertToBeVerified); + CSSM_RETURN (CSSMCLI *CertGetFirstFieldValue) + (CSSM_CL_HANDLE CLHandle, + const CSSM_DATA *Cert, + const CSSM_OID *CertField, + CSSM_HANDLE_PTR ResultsHandle, + uint32 *NumberOfMatchedFields, + CSSM_DATA_PTR *Value); + CSSM_RETURN (CSSMCLI *CertGetNextFieldValue) + (CSSM_CL_HANDLE CLHandle, + CSSM_HANDLE ResultsHandle, + CSSM_DATA_PTR *Value); + CSSM_RETURN (CSSMCLI *CertAbortQuery) + (CSSM_CL_HANDLE CLHandle, + CSSM_HANDLE ResultsHandle); + CSSM_RETURN (CSSMCLI *CertGetKeyInfo) + (CSSM_CL_HANDLE CLHandle, + const CSSM_DATA *Cert, + CSSM_KEY_PTR *Key); + CSSM_RETURN (CSSMCLI *CertGetAllFields) + (CSSM_CL_HANDLE CLHandle, + const CSSM_DATA *Cert, + uint32 *NumberOfFields, + CSSM_FIELD_PTR *CertFields); + CSSM_RETURN (CSSMCLI *FreeFields) + (CSSM_CL_HANDLE CLHandle, + uint32 NumberOfFields, + CSSM_FIELD_PTR *FieldArray); + CSSM_RETURN (CSSMCLI *FreeFieldValue) + (CSSM_CL_HANDLE CLHandle, + const CSSM_OID *CertOrCrlOid, + CSSM_DATA_PTR Value); + CSSM_RETURN (CSSMCLI *CertCache) + (CSSM_CL_HANDLE CLHandle, + const CSSM_DATA *Cert, + CSSM_HANDLE_PTR CertHandle); + CSSM_RETURN (CSSMCLI *CertGetFirstCachedFieldValue) + (CSSM_CL_HANDLE CLHandle, + CSSM_HANDLE CertHandle, + const CSSM_OID *CertField, + CSSM_HANDLE_PTR ResultsHandle, + uint32 *NumberOfMatchedFields, + CSSM_DATA_PTR *Value); + CSSM_RETURN (CSSMCLI *CertGetNextCachedFieldValue) + (CSSM_CL_HANDLE CLHandle, + CSSM_HANDLE ResultsHandle, + CSSM_DATA_PTR *Value); + CSSM_RETURN (CSSMCLI *CertAbortCache) + (CSSM_CL_HANDLE CLHandle, + CSSM_HANDLE CertHandle); + CSSM_RETURN (CSSMCLI *CertGroupToSignedBundle) + (CSSM_CL_HANDLE CLHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_CERTGROUP *CertGroupToBundle, + const CSSM_CERT_BUNDLE_HEADER *BundleInfo, + CSSM_DATA_PTR SignedBundle); + CSSM_RETURN (CSSMCLI *CertGroupFromVerifiedBundle) + (CSSM_CL_HANDLE CLHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_CERT_BUNDLE *CertBundle, + const CSSM_DATA *SignerCert, + CSSM_CERTGROUP_PTR *CertGroup); + CSSM_RETURN (CSSMCLI *CertDescribeFormat) + (CSSM_CL_HANDLE CLHandle, + uint32 *NumberOfFields, + CSSM_OID_PTR *OidList); + CSSM_RETURN (CSSMCLI *CrlCreateTemplate) + (CSSM_CL_HANDLE CLHandle, + uint32 NumberOfFields, + const CSSM_FIELD *CrlTemplate, + CSSM_DATA_PTR NewCrl); + CSSM_RETURN (CSSMCLI *CrlSetFields) + (CSSM_CL_HANDLE CLHandle, + uint32 NumberOfFields, + const CSSM_FIELD *CrlTemplate, + const CSSM_DATA *OldCrl, + CSSM_DATA_PTR ModifiedCrl); + CSSM_RETURN (CSSMCLI *CrlAddCert) + (CSSM_CL_HANDLE CLHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_DATA *Cert, + uint32 NumberOfFields, + const CSSM_FIELD *CrlEntryFields, + const CSSM_DATA *OldCrl, + CSSM_DATA_PTR NewCrl); + CSSM_RETURN (CSSMCLI *CrlRemoveCert) + (CSSM_CL_HANDLE CLHandle, + const CSSM_DATA *Cert, + const CSSM_DATA *OldCrl, + CSSM_DATA_PTR NewCrl); + CSSM_RETURN (CSSMCLI *CrlSign) + (CSSM_CL_HANDLE CLHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_DATA *UnsignedCrl, + const CSSM_FIELD *SignScope, + uint32 ScopeSize, + CSSM_DATA_PTR SignedCrl); + CSSM_RETURN (CSSMCLI *CrlVerify) + (CSSM_CL_HANDLE CLHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_DATA *CrlToBeVerified, + const CSSM_DATA *SignerCert, + const CSSM_FIELD *VerifyScope, + uint32 ScopeSize); + CSSM_RETURN (CSSMCLI *CrlVerifyWithKey) + (CSSM_CL_HANDLE CLHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_DATA *CrlToBeVerified); + CSSM_RETURN (CSSMCLI *IsCertInCrl) + (CSSM_CL_HANDLE CLHandle, + const CSSM_DATA *Cert, + const CSSM_DATA *Crl, + CSSM_BOOL *CertFound); + CSSM_RETURN (CSSMCLI *CrlGetFirstFieldValue) + (CSSM_CL_HANDLE CLHandle, + const CSSM_DATA *Crl, + const CSSM_OID *CrlField, + CSSM_HANDLE_PTR ResultsHandle, + uint32 *NumberOfMatchedFields, + CSSM_DATA_PTR *Value); + CSSM_RETURN (CSSMCLI *CrlGetNextFieldValue) + (CSSM_CL_HANDLE CLHandle, + CSSM_HANDLE ResultsHandle, + CSSM_DATA_PTR *Value); + CSSM_RETURN (CSSMCLI *CrlAbortQuery) + (CSSM_CL_HANDLE CLHandle, + CSSM_HANDLE ResultsHandle); + CSSM_RETURN (CSSMCLI *CrlGetAllFields) + (CSSM_CL_HANDLE CLHandle, + const CSSM_DATA *Crl, + uint32 *NumberOfCrlFields, + CSSM_FIELD_PTR *CrlFields); + CSSM_RETURN (CSSMCLI *CrlCache) + (CSSM_CL_HANDLE CLHandle, + const CSSM_DATA *Crl, + CSSM_HANDLE_PTR CrlHandle); + CSSM_RETURN (CSSMCLI *IsCertInCachedCrl) + (CSSM_CL_HANDLE CLHandle, + const CSSM_DATA *Cert, + CSSM_HANDLE CrlHandle, + CSSM_BOOL *CertFound, + CSSM_DATA_PTR CrlRecordIndex); + CSSM_RETURN (CSSMCLI *CrlGetFirstCachedFieldValue) + (CSSM_CL_HANDLE CLHandle, + CSSM_HANDLE CrlHandle, + const CSSM_DATA *CrlRecordIndex, + const CSSM_OID *CrlField, + CSSM_HANDLE_PTR ResultsHandle, + uint32 *NumberOfMatchedFields, + CSSM_DATA_PTR *Value); + CSSM_RETURN (CSSMCLI *CrlGetNextCachedFieldValue) + (CSSM_CL_HANDLE CLHandle, + CSSM_HANDLE ResultsHandle, + CSSM_DATA_PTR *Value); + CSSM_RETURN (CSSMCLI *CrlGetAllCachedRecordFields) + (CSSM_CL_HANDLE CLHandle, + CSSM_HANDLE CrlHandle, + const CSSM_DATA *CrlRecordIndex, + uint32 *NumberOfFields, + CSSM_FIELD_PTR *CrlFields); + CSSM_RETURN (CSSMCLI *CrlAbortCache) + (CSSM_CL_HANDLE CLHandle, + CSSM_HANDLE CrlHandle); + CSSM_RETURN (CSSMCLI *CrlDescribeFormat) + (CSSM_CL_HANDLE CLHandle, + uint32 *NumberOfFields, + CSSM_OID_PTR *OidList); + CSSM_RETURN (CSSMCLI *PassThrough) + (CSSM_CL_HANDLE CLHandle, + CSSM_CC_HANDLE CCHandle, + uint32 PassThroughId, + const void *InputParams, + void **OutputParams); +} CSSM_SPI_CL_FUNCS DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_SPI_CL_FUNCS_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +#ifdef __cplusplus +} +#endif + +#endif /* _CSSMCLI_H_ */ diff --git a/libsecurity_cssm/lib/cssmconfig.h b/libsecurity_cssm/lib/cssmconfig.h new file mode 100644 index 00000000..f1fcd5fa --- /dev/null +++ b/libsecurity_cssm/lib/cssmconfig.h @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2000-2001,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@ + * + * cssmconfig.h -- Platform specific defines and typedefs for cdsa. + */ + +#ifndef _CSSMCONFIG_H_ +#define _CSSMCONFIG_H_ 1 + +#include +#include +#include + + +/* #if defined(TARGET_API_MAC_OS8) || defined(TARGET_API_MAC_CARBON) || defined(TARGET_API_MAC_OSX) */ +#if defined(TARGET_OS_MAC) +#include +#include +#else +#error Unknown API architecture. +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _SINT64 +typedef int64_t sint64; +#define _SINT64 +#endif +#ifndef _UINT64 +typedef uint64_t uint64; +#define _UINT64 +#endif +#ifndef _SINT32 +typedef int32_t sint32; +#define _SINT32 +#endif +#ifndef _SINT16 +typedef int16_t sint16; +#define _SINT16 +#endif +#ifndef _SINT8 +typedef int8_t sint8; +#define _SINT8 +#endif +#ifndef _UINT32 +typedef uint32_t uint32; +#define _UINT32 +#endif +#ifndef _UINT16 +typedef uint16_t uint16; +#define _UINT16 +#endif +#ifndef _UINT8 +typedef uint8_t uint8; +#define _UINT8 +#endif + +typedef intptr_t CSSM_INTPTR; +typedef size_t CSSM_SIZE; + +#define CSSMACI +#define CSSMAPI +#define CSSMCLI +#define CSSMCSPI +#define CSSMDLI +#define CSSMKRI +#define CSSMSPI +#define CSSMTPI + +#ifdef __cplusplus +} +#endif + +#endif /* _CSSMCONFIG_H_ */ diff --git a/libsecurity_cssm/lib/cssmcontext.cpp b/libsecurity_cssm/lib/cssmcontext.cpp new file mode 100644 index 00000000..14f09861 --- /dev/null +++ b/libsecurity_cssm/lib/cssmcontext.cpp @@ -0,0 +1,204 @@ +/* + * Copyright (c) 2000-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@ + */ + + +// +// context - manage CSSM (cryptographic) contexts every which way. +// +// A note on memory management: +// Context attributes are allocated from application memory in big chunks comprising +// many attributes as well as the attribute array itself. The CSSM_CONTEXT fields +// NumberOfAttributes and ContextAttributes are handled as a group. Context::Builder +// and Context::copyFrom assume these fields are undefined and fill them. Context::clear +// assumes they are valid and invalides them, freeing memory. +// +#ifdef __MWERKS__ +#define _CPP_CSSMCONTEXT +#endif +#include "cssmcontext.h" + + +// +// Destroy a HandleContext. +// +HandleContext::~HandleContext() +{ + attachment.free(extent); + attachment.free(ContextAttributes); +} + + +// +// Locking protocol for HandleContexts +// +void HandleContext::lock() +{ attachment.enter(); } + +bool HandleContext::tryLock() +{ return attachment.tryEnter(); } + + +// +// Merge a new set of attributes into an existing HandleContext, copying +// the new values deeply while releasing corresponding old values. +// +// NOTE: This is a HandleContext method; it does not work on bare Contexts. +// +void HandleContext::mergeAttributes(const CSSM_CONTEXT_ATTRIBUTE *attributes, uint32 count) +{ + // attempt to fast-path some simple or frequent cases + if (count == 1) { + if (Attr *attr = find(attributes[0].AttributeType)) { + if (attr->baseType() == CSSM_ATTRIBUTE_DATA_UINT32) { + // try quick replacement + Attr oldAttr = *attr; + *attr = attributes[0]; + if (CSSM_RETURN err = validateChange(CSSM_CONTEXT_EVENT_UPDATE)) { + // roll back and fail + *attr = oldAttr; + CssmError::throwMe(err); + } + return; // all done + } else { + // pointer value - does it fit into the space of the current value? + size_t oldSize = size(*attr); + size_t newSize = size(attributes[0]); + Attr oldAttr = *attr; + if (newSize <= oldSize) { // give it a try... + *attr = attributes[0]; + // NOTE that the CSP is getting a "temporary" pointer set to validate; + // If we commit, the final copy will be elsewhere. CSP writer beware! + if (CSSM_RETURN err = validateChange(CSSM_CONTEXT_EVENT_UPDATE)) { + // roll back and fail + *attr = oldAttr; + CssmError::throwMe(err); + } + // commit new value + CopyWalker copier(oldAttr.Attribute.String); + walk(copier, *attr); + return; + } + } + } else { // single change, new attribute + if (Attr *slot = find(CSSM_ATTRIBUTE_NONE)) { + const Attr *attr = static_cast(&attributes[0]); + if (attr->baseType() == CSSM_ATTRIBUTE_DATA_UINT32) { // trivial + Attr oldSlot = *slot; + *slot = *attr; + if (CSSM_RETURN err = validateChange(CSSM_CONTEXT_EVENT_UPDATE)) { + *slot = oldSlot; + CssmError::throwMe(err); + } + // already ok + return; + } else if (extent == NULL) { // pointer value, allocate into extent + void *data = attachment.malloc(size(*attr)); + try { + Attr oldSlot = *slot; + *slot = attributes[0]; + CopyWalker copier(data); + walk(copier, *slot); + if (CSSM_RETURN err = validateChange(CSSM_CONTEXT_EVENT_UPDATE)) { + *slot = oldSlot; + CssmError::throwMe(err); + } + } catch (...) { + attachment.free(data); + throw; + } + extent = data; + return; + } + } + } + } + + // slow form: build a new value table and get rid of the old one + Context::Builder builder(attachment); + for (unsigned n = 0; n < count; n++) + builder.setup(attributes[n]); + for (unsigned n = 0; n < attributesInUse(); n++) + if (!find(ContextAttributes[n].AttributeType, attributes, count)) + builder.setup(ContextAttributes[n]); + builder.make(); + for (unsigned n = 0; n < count; n++) + builder.put(attributes[n]); + for (unsigned n = 0; n < attributesInUse(); n++) + if (!find(ContextAttributes[n].AttributeType, attributes, count)) + builder.put(ContextAttributes[n]); + + // Carefully, now! The CSP may yet tell us to back out. + // First, save the old values... + CSSM_CONTEXT_ATTRIBUTE *oldAttributes = ContextAttributes; + uint32 oldCount = NumberOfAttributes; + + // ...install new blob into the context... + builder.done(ContextAttributes, NumberOfAttributes); + + // ...and ask the CSP whether this is okay + if (CSSM_RETURN err = validateChange(CSSM_CONTEXT_EVENT_UPDATE)) { + // CSP refused; put everything back where it belongs + attachment.free(ContextAttributes); + ContextAttributes = oldAttributes; + NumberOfAttributes = oldCount; + CssmError::throwMe(err); + } + + // we succeeded, so NOW delete the old attributes blob + attachment.free(oldAttributes); +} + + +// +// Ask the CSP to validate a proposed (and already implemented) change +// +CSSM_RETURN HandleContext::validateChange(CSSM_CONTEXT_EVENT event) +{ + // lock down the module if it is not thread-safe + StLock _(attachment.module); + return attachment.downcalls.EventNotify(attachment.handle(), + event, handle(), this); +} + + +// +// Wrap up a deluxe context creation operation and return the new CC handle. +// +CSSM_CC_HANDLE HandleContext::Maker::operator () (CSSM_CONTEXT_TYPE type, + CSSM_ALGORITHMS algorithm) +{ + // construct the HandleContext object + HandleContext &context = *new(attachment) HandleContext(attachment, type, algorithm); + context.CSPHandle = attachment.handle(); + done(context.ContextAttributes, context.NumberOfAttributes); + + // ask the CSP for consent + if (CSSM_RETURN err = context.validateChange(CSSM_CONTEXT_EVENT_CREATE)) { + // CSP refused; clean up and fail + context.destroy(&context, context.attachment); + CssmError::throwMe(err); + } + + // return the new handle (we have succeeded) + return context.handle(); +} diff --git a/libsecurity_cssm/lib/cssmcontext.h b/libsecurity_cssm/lib/cssmcontext.h new file mode 100644 index 00000000..3b016365 --- /dev/null +++ b/libsecurity_cssm/lib/cssmcontext.h @@ -0,0 +1,123 @@ +/* + * 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@ + */ + + +// +// context - manage CSSM (cryptographic) contexts every which way +// +#ifndef _H_CSSMCONTEXT +#define _H_CSSMCONTEXT + +#include "cssmint.h" +#include "cspattachment.h" +#include + +#ifdef _CPP_CSSMCONTEXT +# pragma export on +#endif + + +// +// A HandleContext adds handle semantics to the Context object. +// Note that not every Context is a HandleContext - the Contexts we hand +// to our API customers for fondling are not. Also note that a HandleContext +// not a PODWrapper. +// HandleContext has an allocation method taking a Allocator. To destroy +// a HandleObject, call HandleObject::destroy(the-context, the-allocator). +// You are responsible for picking the same allocator used on construction. +// +// THREADS: HandleContexts are assumed to have single-thread use. That means that +// operations on HandleContexts are NOT interlocked automatically; two users of +// the same context must do any arbitration themselves. A HandleContext is howerver +// safely interlocked against other objects, in particular its CSPAttachment. +// The upshot is that you're safe using a HandleContext unless someone else is trying +// to use the same context in parallel. +// +class HandleContext : public HandleObject, public Context { +public: + HandleContext(CSPAttachment &attach, + CSSM_CONTEXT_TYPE type, + CSSM_ALGORITHMS algorithmId) + : Context(type, algorithmId), attachment(attach), extent(0) { } + virtual ~HandleContext(); + + CSPAttachment &attachment; + + using Context::find; // guard against HandleObjec::find + + void mergeAttributes(const CSSM_CONTEXT_ATTRIBUTE *attributes, uint32 count); + CSSM_RETURN validateChange(CSSM_CONTEXT_EVENT event); + + void *operator new (size_t size, Allocator &alloc) throw(std::bad_alloc) + { return alloc.malloc(size); } + void operator delete (void *addr, size_t, Allocator &alloc) throw() + { return alloc.free(addr); } + static void destroy(HandleContext *context, Allocator &alloc) throw() + { context->~HandleContext(); alloc.free(context); } + + class Maker; // deluxe builder + +#if __GNUC__ > 2 +private: + void operator delete (void *addr) throw() { assert(0); } +#endif + +protected: + // Locking protocol, courtesy of HandleObject. + // This locks the underlying attachment. + void lock(); + bool tryLock(); + +private: + void *extent; // extra storage extent in use +}; + +inline HandleContext &enterContext(CSSM_CC_HANDLE h) +{ + return HandleObject::findAndLock(h, CSSM_ERRCODE_INVALID_CONTEXT_HANDLE); +} + + +// +// A Maker is a deluxe wrapper around Builder. It creates whole HandleContext +// objects in one swell foop, handling object locking, construction, error +// recovery, and all that jazz. A Maker cannot create plain Context objects. +// +class HandleContext::Maker : public Context::Builder { +public: + Maker(CSSM_CSP_HANDLE handle) + : Context::Builder(HandleObject::findAndLock(handle, CSSM_ERRCODE_INVALID_CSP_HANDLE)), + attachment(static_cast(allocator)), // order dependency(!) + locker(attachment, true) + { attachment.finishEnter(); } + + CSPAttachment &attachment; + + CSSM_CC_HANDLE operator () (CSSM_CONTEXT_TYPE type, + CSSM_ALGORITHMS algorithm); + +private: + StLock locker; +}; + +#endif //_H_CSSMCONTEXT diff --git a/libsecurity_cssm/lib/cssmcspi.h b/libsecurity_cssm/lib/cssmcspi.h new file mode 100644 index 00000000..ac989941 --- /dev/null +++ b/libsecurity_cssm/lib/cssmcspi.h @@ -0,0 +1,367 @@ +/* + * Copyright (c) 1999-2001,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@ + * + * cssmcspi.h -- Service Provider Interface for + * Cryptographic Service Provider Modules + */ + +#ifndef _CSSMCSPI_H_ +#define _CSSMCSPI_H_ 1 + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct cssm_spi_csp_funcs { + CSSM_RETURN (CSSMCSPI *EventNotify) + (CSSM_CSP_HANDLE CSPHandle, + CSSM_CONTEXT_EVENT Event, + CSSM_CC_HANDLE CCHandle, + const CSSM_CONTEXT *Context); + CSSM_RETURN (CSSMCSPI *QuerySize) + (CSSM_CSP_HANDLE CSPHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_CONTEXT *Context, + CSSM_BOOL Encrypt, + uint32 QuerySizeCount, + CSSM_QUERY_SIZE_DATA_PTR DataBlock); + CSSM_RETURN (CSSMCSPI *SignData) + (CSSM_CSP_HANDLE CSPHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_CONTEXT *Context, + const CSSM_DATA *DataBufs, + uint32 DataBufCount, + CSSM_ALGORITHMS DigestAlgorithm, + CSSM_DATA_PTR Signature); + CSSM_RETURN (CSSMCSPI *SignDataInit) + (CSSM_CSP_HANDLE CSPHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_CONTEXT *Context); + CSSM_RETURN (CSSMCSPI *SignDataUpdate) + (CSSM_CSP_HANDLE CSPHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_DATA *DataBufs, + uint32 DataBufCount); + CSSM_RETURN (CSSMCSPI *SignDataFinal) + (CSSM_CSP_HANDLE CSPHandle, + CSSM_CC_HANDLE CCHandle, + CSSM_DATA_PTR Signature); + CSSM_RETURN (CSSMCSPI *VerifyData) + (CSSM_CSP_HANDLE CSPHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_CONTEXT *Context, + const CSSM_DATA *DataBufs, + uint32 DataBufCount, + CSSM_ALGORITHMS DigestAlgorithm, + const CSSM_DATA *Signature); + CSSM_RETURN (CSSMCSPI *VerifyDataInit) + (CSSM_CSP_HANDLE CSPHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_CONTEXT *Context); + CSSM_RETURN (CSSMCSPI *VerifyDataUpdate) + (CSSM_CSP_HANDLE CSPHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_DATA *DataBufs, + uint32 DataBufCount); + CSSM_RETURN (CSSMCSPI *VerifyDataFinal) + (CSSM_CSP_HANDLE CSPHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_DATA *Signature); + CSSM_RETURN (CSSMCSPI *DigestData) + (CSSM_CSP_HANDLE CSPHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_CONTEXT *Context, + const CSSM_DATA *DataBufs, + uint32 DataBufCount, + CSSM_DATA_PTR Digest); + CSSM_RETURN (CSSMCSPI *DigestDataInit) + (CSSM_CSP_HANDLE CSPHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_CONTEXT *Context); + CSSM_RETURN (CSSMCSPI *DigestDataUpdate) + (CSSM_CSP_HANDLE CSPHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_DATA *DataBufs, + uint32 DataBufCount); + CSSM_RETURN (CSSMCSPI *DigestDataClone) + (CSSM_CSP_HANDLE CSPHandle, + CSSM_CC_HANDLE CCHandle, + CSSM_CC_HANDLE ClonedCCHandle); + CSSM_RETURN (CSSMCSPI *DigestDataFinal) + (CSSM_CSP_HANDLE CSPHandle, + CSSM_CC_HANDLE CCHandle, + CSSM_DATA_PTR Digest); + CSSM_RETURN (CSSMCSPI *GenerateMac) + (CSSM_CSP_HANDLE CSPHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_CONTEXT *Context, + const CSSM_DATA *DataBufs, + uint32 DataBufCount, + CSSM_DATA_PTR Mac); + CSSM_RETURN (CSSMCSPI *GenerateMacInit) + (CSSM_CSP_HANDLE CSPHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_CONTEXT *Context); + CSSM_RETURN (CSSMCSPI *GenerateMacUpdate) + (CSSM_CSP_HANDLE CSPHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_DATA *DataBufs, + uint32 DataBufCount); + CSSM_RETURN (CSSMCSPI *GenerateMacFinal) + (CSSM_CSP_HANDLE CSPHandle, + CSSM_CC_HANDLE CCHandle, + CSSM_DATA_PTR Mac); + CSSM_RETURN (CSSMCSPI *VerifyMac) + (CSSM_CSP_HANDLE CSPHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_CONTEXT *Context, + const CSSM_DATA *DataBufs, + uint32 DataBufCount, + const CSSM_DATA *Mac); + CSSM_RETURN (CSSMCSPI *VerifyMacInit) + (CSSM_CSP_HANDLE CSPHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_CONTEXT *Context); + CSSM_RETURN (CSSMCSPI *VerifyMacUpdate) + (CSSM_CSP_HANDLE CSPHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_DATA *DataBufs, + uint32 DataBufCount); + CSSM_RETURN (CSSMCSPI *VerifyMacFinal) + (CSSM_CSP_HANDLE CSPHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_DATA *Mac); + CSSM_RETURN (CSSMCSPI *EncryptData) + (CSSM_CSP_HANDLE CSPHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_CONTEXT *Context, + const CSSM_DATA *ClearBufs, + uint32 ClearBufCount, + CSSM_DATA_PTR CipherBufs, + uint32 CipherBufCount, + CSSM_SIZE *bytesEncrypted, + CSSM_DATA_PTR RemData, + CSSM_PRIVILEGE Privilege); + CSSM_RETURN (CSSMCSPI *EncryptDataInit) + (CSSM_CSP_HANDLE CSPHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_CONTEXT *Context, + CSSM_PRIVILEGE Privilege); + CSSM_RETURN (CSSMCSPI *EncryptDataUpdate) + (CSSM_CSP_HANDLE CSPHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_DATA *ClearBufs, + uint32 ClearBufCount, + CSSM_DATA_PTR CipherBufs, + uint32 CipherBufCount, + CSSM_SIZE *bytesEncrypted); + CSSM_RETURN (CSSMCSPI *EncryptDataFinal) + (CSSM_CSP_HANDLE CSPHandle, + CSSM_CC_HANDLE CCHandle, + CSSM_DATA_PTR RemData); + CSSM_RETURN (CSSMCSPI *DecryptData) + (CSSM_CSP_HANDLE CSPHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_CONTEXT *Context, + const CSSM_DATA *CipherBufs, + uint32 CipherBufCount, + CSSM_DATA_PTR ClearBufs, + uint32 ClearBufCount, + CSSM_SIZE *bytesDecrypted, + CSSM_DATA_PTR RemData, + CSSM_PRIVILEGE Privilege); + CSSM_RETURN (CSSMCSPI *DecryptDataInit) + (CSSM_CSP_HANDLE CSPHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_CONTEXT *Context, + CSSM_PRIVILEGE Privilege); + CSSM_RETURN (CSSMCSPI *DecryptDataUpdate) + (CSSM_CSP_HANDLE CSPHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_DATA *CipherBufs, + uint32 CipherBufCount, + CSSM_DATA_PTR ClearBufs, + uint32 ClearBufCount, + CSSM_SIZE *bytesDecrypted); + CSSM_RETURN (CSSMCSPI *DecryptDataFinal) + (CSSM_CSP_HANDLE CSPHandle, + CSSM_CC_HANDLE CCHandle, + CSSM_DATA_PTR RemData); + CSSM_RETURN (CSSMCSPI *QueryKeySizeInBits) + (CSSM_CSP_HANDLE CSPHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_CONTEXT *Context, + const CSSM_KEY *Key, + CSSM_KEY_SIZE_PTR KeySize); + CSSM_RETURN (CSSMCSPI *GenerateKey) + (CSSM_CSP_HANDLE CSPHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_CONTEXT *Context, + uint32 KeyUsage, + uint32 KeyAttr, + const CSSM_DATA *KeyLabel, + const CSSM_RESOURCE_CONTROL_CONTEXT *CredAndAclEntry, + CSSM_KEY_PTR Key, + CSSM_PRIVILEGE Privilege); + CSSM_RETURN (CSSMCSPI *GenerateKeyPair) + (CSSM_CSP_HANDLE CSPHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_CONTEXT *Context, + uint32 PublicKeyUsage, + uint32 PublicKeyAttr, + const CSSM_DATA *PublicKeyLabel, + CSSM_KEY_PTR PublicKey, + uint32 PrivateKeyUsage, + uint32 PrivateKeyAttr, + const CSSM_DATA *PrivateKeyLabel, + const CSSM_RESOURCE_CONTROL_CONTEXT *CredAndAclEntry, + CSSM_KEY_PTR PrivateKey, + CSSM_PRIVILEGE Privilege); + CSSM_RETURN (CSSMCSPI *GenerateRandom) + (CSSM_CSP_HANDLE CSPHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_CONTEXT *Context, + CSSM_DATA_PTR RandomNumber); + CSSM_RETURN (CSSMCSPI *GenerateAlgorithmParams) + (CSSM_CSP_HANDLE CSPHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_CONTEXT *Context, + uint32 ParamBits, + CSSM_DATA_PTR Param, + uint32 *NumberOfUpdatedAttibutes, + CSSM_CONTEXT_ATTRIBUTE_PTR *UpdatedAttributes); + CSSM_RETURN (CSSMCSPI *WrapKey) + (CSSM_CSP_HANDLE CSPHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_CONTEXT *Context, + const CSSM_ACCESS_CREDENTIALS *AccessCred, + const CSSM_KEY *Key, + const CSSM_DATA *DescriptiveData, + CSSM_WRAP_KEY_PTR WrappedKey, + CSSM_PRIVILEGE Privilege); + CSSM_RETURN (CSSMCSPI *UnwrapKey) + (CSSM_CSP_HANDLE CSPHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_CONTEXT *Context, + const CSSM_KEY *PublicKey, + const CSSM_WRAP_KEY *WrappedKey, + uint32 KeyUsage, + uint32 KeyAttr, + const CSSM_DATA *KeyLabel, + const CSSM_RESOURCE_CONTROL_CONTEXT *CredAndAclEntry, + CSSM_KEY_PTR UnwrappedKey, + CSSM_DATA_PTR DescriptiveData, + CSSM_PRIVILEGE Privilege); + CSSM_RETURN (CSSMCSPI *DeriveKey) + (CSSM_CSP_HANDLE CSPHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_CONTEXT *Context, + CSSM_DATA_PTR Param, + uint32 KeyUsage, + uint32 KeyAttr, + const CSSM_DATA *KeyLabel, + const CSSM_RESOURCE_CONTROL_CONTEXT *CredAndAclEntry, + CSSM_KEY_PTR DerivedKey); + CSSM_RETURN (CSSMCSPI *FreeKey) + (CSSM_CSP_HANDLE CSPHandle, + const CSSM_ACCESS_CREDENTIALS *AccessCred, + CSSM_KEY_PTR KeyPtr, + CSSM_BOOL Delete); + CSSM_RETURN (CSSMCSPI *PassThrough) + (CSSM_CSP_HANDLE CSPHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_CONTEXT *Context, + uint32 PassThroughId, + const void *InData, + void **OutData); + CSSM_RETURN (CSSMCSPI *Login) + (CSSM_CSP_HANDLE CSPHandle, + const CSSM_ACCESS_CREDENTIALS *AccessCred, + const CSSM_DATA *LoginName, + const void *Reserved); + CSSM_RETURN (CSSMCSPI *Logout) + (CSSM_CSP_HANDLE CSPHandle); + CSSM_RETURN (CSSMCSPI *ChangeLoginAcl) + (CSSM_CSP_HANDLE CSPHandle, + const CSSM_ACCESS_CREDENTIALS *AccessCred, + const CSSM_ACL_EDIT *AclEdit); + CSSM_RETURN (CSSMCSPI *ObtainPrivateKeyFromPublicKey) + (CSSM_CSP_HANDLE CSPHandle, + const CSSM_KEY *PublicKey, + CSSM_KEY_PTR PrivateKey); + CSSM_RETURN (CSSMCSPI *RetrieveUniqueId) + (CSSM_CSP_HANDLE CSPHandle, + CSSM_DATA_PTR UniqueID); + CSSM_RETURN (CSSMCSPI *RetrieveCounter) + (CSSM_CSP_HANDLE CSPHandle, + CSSM_DATA_PTR Counter); + CSSM_RETURN (CSSMCSPI *VerifyDevice) + (CSSM_CSP_HANDLE CSPHandle, + const CSSM_DATA *DeviceCert); + CSSM_RETURN (CSSMCSPI *GetTimeValue) + (CSSM_CSP_HANDLE CSPHandle, + CSSM_ALGORITHMS TimeAlgorithm, + CSSM_DATA *TimeData); + CSSM_RETURN (CSSMCSPI *GetOperationalStatistics) + (CSSM_CSP_HANDLE CSPHandle, + CSSM_CSP_OPERATIONAL_STATISTICS *Statistics); + CSSM_RETURN (CSSMCSPI *GetLoginAcl) + (CSSM_CSP_HANDLE CSPHandle, + const CSSM_STRING *SelectionTag, + uint32 *NumberOfAclInfos, + CSSM_ACL_ENTRY_INFO_PTR *AclInfos); + CSSM_RETURN (CSSMCSPI *GetKeyAcl) + (CSSM_CSP_HANDLE CSPHandle, + const CSSM_KEY *Key, + const CSSM_STRING *SelectionTag, + uint32 *NumberOfAclInfos, + CSSM_ACL_ENTRY_INFO_PTR *AclInfos); + CSSM_RETURN (CSSMCSPI *ChangeKeyAcl) + (CSSM_CSP_HANDLE CSPHandle, + const CSSM_ACCESS_CREDENTIALS *AccessCred, + const CSSM_ACL_EDIT *AclEdit, + const CSSM_KEY *Key); + CSSM_RETURN (CSSMCSPI *GetKeyOwner) + (CSSM_CSP_HANDLE CSPHandle, + const CSSM_KEY *Key, + CSSM_ACL_OWNER_PROTOTYPE_PTR Owner); + CSSM_RETURN (CSSMCSPI *ChangeKeyOwner) + (CSSM_CSP_HANDLE CSPHandle, + const CSSM_ACCESS_CREDENTIALS *AccessCred, + const CSSM_KEY *Key, + const CSSM_ACL_OWNER_PROTOTYPE *NewOwner); + CSSM_RETURN (CSSMCSPI *GetLoginOwner) + (CSSM_CSP_HANDLE CSPHandle, + CSSM_ACL_OWNER_PROTOTYPE_PTR Owner); + CSSM_RETURN (CSSMCSPI *ChangeLoginOwner) + (CSSM_CSP_HANDLE CSPHandle, + const CSSM_ACCESS_CREDENTIALS *AccessCred, + const CSSM_ACL_OWNER_PROTOTYPE *NewOwner); +} CSSM_SPI_CSP_FUNCS DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_SPI_CSP_FUNCS_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +#ifdef __cplusplus +} +#endif + +#endif /* _CSSMCSPI_H_ */ diff --git a/libsecurity_cssm/lib/cssmdli.h b/libsecurity_cssm/lib/cssmdli.h new file mode 100644 index 00000000..a62fe845 --- /dev/null +++ b/libsecurity_cssm/lib/cssmdli.h @@ -0,0 +1,151 @@ +/* + * Copyright (c) 1999-2001,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@ + * + * cssmdli.h -- Service Provider Interface for Data Store Modules + */ + +#ifndef _CSSMDLI_H_ +#define _CSSMDLI_H_ 1 + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct cssm_spi_dl_funcs { + CSSM_RETURN (CSSMDLI *DbOpen) + (CSSM_DL_HANDLE DLHandle, + const char *DbName, + const CSSM_NET_ADDRESS *DbLocation, + CSSM_DB_ACCESS_TYPE AccessRequest, + const CSSM_ACCESS_CREDENTIALS *AccessCred, + const void *OpenParameters, + CSSM_DB_HANDLE *DbHandle); + CSSM_RETURN (CSSMDLI *DbClose) + (CSSM_DL_DB_HANDLE DLDBHandle); + CSSM_RETURN (CSSMDLI *DbCreate) + (CSSM_DL_HANDLE DLHandle, + const char *DbName, + const CSSM_NET_ADDRESS *DbLocation, + const CSSM_DBINFO *DBInfo, + CSSM_DB_ACCESS_TYPE AccessRequest, + const CSSM_RESOURCE_CONTROL_CONTEXT *CredAndAclEntry, + const void *OpenParameters, + CSSM_DB_HANDLE *DbHandle); + CSSM_RETURN (CSSMDLI *DbDelete) + (CSSM_DL_HANDLE DLHandle, + const char *DbName, + const CSSM_NET_ADDRESS *DbLocation, + const CSSM_ACCESS_CREDENTIALS *AccessCred); + CSSM_RETURN (CSSMDLI *CreateRelation) + (CSSM_DL_DB_HANDLE DLDBHandle, + CSSM_DB_RECORDTYPE RelationID, + const char *RelationName, + uint32 NumberOfAttributes, + const CSSM_DB_SCHEMA_ATTRIBUTE_INFO *pAttributeInfo, + uint32 NumberOfIndexes, + const CSSM_DB_SCHEMA_INDEX_INFO *pIndexInfo); + CSSM_RETURN (CSSMDLI *DestroyRelation) + (CSSM_DL_DB_HANDLE DLDBHandle, + CSSM_DB_RECORDTYPE RelationID); + CSSM_RETURN (CSSMDLI *Authenticate) + (CSSM_DL_DB_HANDLE DLDBHandle, + CSSM_DB_ACCESS_TYPE AccessRequest, + const CSSM_ACCESS_CREDENTIALS *AccessCred); + CSSM_RETURN (CSSMDLI *GetDbAcl) + (CSSM_DL_DB_HANDLE DLDBHandle, + const CSSM_STRING *SelectionTag, + uint32 *NumberOfAclInfos, + CSSM_ACL_ENTRY_INFO_PTR *AclInfos); + CSSM_RETURN (CSSMDLI *ChangeDbAcl) + (CSSM_DL_DB_HANDLE DLDBHandle, + const CSSM_ACCESS_CREDENTIALS *AccessCred, + const CSSM_ACL_EDIT *AclEdit); + CSSM_RETURN (CSSMDLI *GetDbOwner) + (CSSM_DL_DB_HANDLE DLDBHandle, + CSSM_ACL_OWNER_PROTOTYPE_PTR Owner); + CSSM_RETURN (CSSMDLI *ChangeDbOwner) + (CSSM_DL_DB_HANDLE DLDBHandle, + const CSSM_ACCESS_CREDENTIALS *AccessCred, + const CSSM_ACL_OWNER_PROTOTYPE *NewOwner); + CSSM_RETURN (CSSMDLI *GetDbNames) + (CSSM_DL_HANDLE DLHandle, + CSSM_NAME_LIST_PTR *NameList); + CSSM_RETURN (CSSMDLI *GetDbNameFromHandle) + (CSSM_DL_DB_HANDLE DLDBHandle, + char **DbName); + CSSM_RETURN (CSSMDLI *FreeNameList) + (CSSM_DL_HANDLE DLHandle, + CSSM_NAME_LIST_PTR NameList); + CSSM_RETURN (CSSMDLI *DataInsert) + (CSSM_DL_DB_HANDLE DLDBHandle, + CSSM_DB_RECORDTYPE RecordType, + const CSSM_DB_RECORD_ATTRIBUTE_DATA *Attributes, + const CSSM_DATA *Data, + CSSM_DB_UNIQUE_RECORD_PTR *UniqueId); + CSSM_RETURN (CSSMDLI *DataDelete) + (CSSM_DL_DB_HANDLE DLDBHandle, + const CSSM_DB_UNIQUE_RECORD *UniqueRecordIdentifier); + CSSM_RETURN (CSSMDLI *DataModify) + (CSSM_DL_DB_HANDLE DLDBHandle, + CSSM_DB_RECORDTYPE RecordType, + CSSM_DB_UNIQUE_RECORD_PTR UniqueRecordIdentifier, + const CSSM_DB_RECORD_ATTRIBUTE_DATA *AttributesToBeModified, + const CSSM_DATA *DataToBeModified, + CSSM_DB_MODIFY_MODE ModifyMode); + CSSM_RETURN (CSSMDLI *DataGetFirst) + (CSSM_DL_DB_HANDLE DLDBHandle, + const CSSM_QUERY *Query, + CSSM_HANDLE_PTR ResultsHandle, + CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR Attributes, + CSSM_DATA_PTR Data, + CSSM_DB_UNIQUE_RECORD_PTR *UniqueId); + CSSM_RETURN (CSSMDLI *DataGetNext) + (CSSM_DL_DB_HANDLE DLDBHandle, + CSSM_HANDLE ResultsHandle, + CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR Attributes, + CSSM_DATA_PTR Data, + CSSM_DB_UNIQUE_RECORD_PTR *UniqueId); + CSSM_RETURN (CSSMDLI *DataAbortQuery) + (CSSM_DL_DB_HANDLE DLDBHandle, + CSSM_HANDLE ResultsHandle); + CSSM_RETURN (CSSMDLI *DataGetFromUniqueRecordId) + (CSSM_DL_DB_HANDLE DLDBHandle, + const CSSM_DB_UNIQUE_RECORD *UniqueRecord, + CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR Attributes, + CSSM_DATA_PTR Data); + CSSM_RETURN (CSSMDLI *FreeUniqueRecord) + (CSSM_DL_DB_HANDLE DLDBHandle, + CSSM_DB_UNIQUE_RECORD_PTR UniqueRecord); + CSSM_RETURN (CSSMDLI *PassThrough) + (CSSM_DL_DB_HANDLE DLDBHandle, + uint32 PassThroughId, + const void *InputParams, + void **OutputParams); +} CSSM_SPI_DL_FUNCS DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_SPI_DL_FUNCS_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +#ifdef __cplusplus +} +#endif + +#endif /* _CSSMDLI_H_ */ diff --git a/libsecurity_cssm/lib/cssmerr.h b/libsecurity_cssm/lib/cssmerr.h new file mode 100644 index 00000000..047380ea --- /dev/null +++ b/libsecurity_cssm/lib/cssmerr.h @@ -0,0 +1,823 @@ +/* + * Copyright (c) 1999-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@ + * + * cssmerr.h -- Error Code Definitions for CSSM + */ + +#ifndef _CSSMERR_H_ +#define _CSSMERR_H_ 1 + +#ifdef __cplusplus +extern "C" { +#endif + + +/* + * NOTE: To translate CSSM error codes into something vaguely + * human-readable, use the cssmPerror function in cssmapple.h. + * This function will also decode other Security layer errors + * (i.e. those with names like kSec...). + */ + + +/* Common error codes. */ +enum { + CSSM_BASE_ERROR = -0x7FFF0000 /* 0x80010000 */ +}; + +enum { + CSSM_ERRORCODE_MODULE_EXTENT = 0x00000800, + CSSM_ERRORCODE_CUSTOM_OFFSET = 0x00000400, + CSSM_ERRORCODE_COMMON_EXTENT = 0x100 +}; + +/* Macros for convertible error code manipulation. */ +#define CSSM_ERRCODE(CODE) \ + (((CODE) - CSSM_BASE_ERROR) & (CSSM_ERRORCODE_MODULE_EXTENT - 1)) + +#define CSSM_ERRBASE(CODE) \ + ((((CODE) - CSSM_BASE_ERROR) & ~(CSSM_ERRORCODE_MODULE_EXTENT - 1)) + CSSM_BASE_ERROR) + +#define CSSM_ERR_IS_CONVERTIBLE(CODE) \ + (CSSM_ERRCODE(CODE) < CSSM_ERRORCODE_COMMON_EXTENT) + +#define CSSM_ERR_TAG(CODE, BASE) \ + (CSSM_ERRCODE(CODE) + (BASE)) + +/* Error Bases for different module types. */ +enum { + CSSM_CSSM_BASE_ERROR = CSSM_BASE_ERROR, + CSSM_CSSM_PRIVATE_ERROR = CSSM_BASE_ERROR + CSSM_ERRORCODE_CUSTOM_OFFSET, + CSSM_CSP_BASE_ERROR = CSSM_CSSM_BASE_ERROR + CSSM_ERRORCODE_MODULE_EXTENT, + CSSM_CSP_PRIVATE_ERROR = CSSM_CSP_BASE_ERROR + CSSM_ERRORCODE_CUSTOM_OFFSET, + CSSM_DL_BASE_ERROR = CSSM_CSP_BASE_ERROR + CSSM_ERRORCODE_MODULE_EXTENT, + CSSM_DL_PRIVATE_ERROR = CSSM_DL_BASE_ERROR + CSSM_ERRORCODE_CUSTOM_OFFSET, + CSSM_CL_BASE_ERROR = CSSM_DL_BASE_ERROR + CSSM_ERRORCODE_MODULE_EXTENT, + CSSM_CL_PRIVATE_ERROR = CSSM_CL_BASE_ERROR + CSSM_ERRORCODE_CUSTOM_OFFSET, + CSSM_TP_BASE_ERROR = CSSM_CL_BASE_ERROR + CSSM_ERRORCODE_MODULE_EXTENT, + CSSM_TP_PRIVATE_ERROR = CSSM_TP_BASE_ERROR + CSSM_ERRORCODE_CUSTOM_OFFSET , + CSSM_KR_BASE_ERROR = CSSM_TP_BASE_ERROR + CSSM_ERRORCODE_MODULE_EXTENT, + CSSM_KR_PRIVATE_ERROR = CSSM_KR_BASE_ERROR + CSSM_ERRORCODE_CUSTOM_OFFSET, + CSSM_AC_BASE_ERROR = CSSM_KR_BASE_ERROR + CSSM_ERRORCODE_MODULE_EXTENT, + CSSM_AC_PRIVATE_ERROR = CSSM_AC_BASE_ERROR + CSSM_ERRORCODE_CUSTOM_OFFSET +}; + +/* XXX @@@ MDS Error Bases same as DL for now. */ +enum { + CSSM_MDS_BASE_ERROR = CSSM_CSP_BASE_ERROR + CSSM_ERRORCODE_MODULE_EXTENT, + CSSM_MDS_PRIVATE_ERROR = CSSM_MDS_BASE_ERROR + CSSM_ERRORCODE_CUSTOM_OFFSET +}; + +/* General Error Values. */ +enum { + CSSMERR_CSSM_INVALID_ADDIN_HANDLE = + CSSM_CSSM_BASE_ERROR + CSSM_ERRORCODE_COMMON_EXTENT + 1, + CSSMERR_CSSM_NOT_INITIALIZED = + CSSM_CSSM_BASE_ERROR + CSSM_ERRORCODE_COMMON_EXTENT + 2, + CSSMERR_CSSM_INVALID_HANDLE_USAGE = + CSSM_CSSM_BASE_ERROR + CSSM_ERRORCODE_COMMON_EXTENT + 3, + CSSMERR_CSSM_PVC_REFERENT_NOT_FOUND = + CSSM_CSSM_BASE_ERROR + CSSM_ERRORCODE_COMMON_EXTENT + 4, + CSSMERR_CSSM_FUNCTION_INTEGRITY_FAIL = + CSSM_CSSM_BASE_ERROR + CSSM_ERRORCODE_COMMON_EXTENT + 5 +}; + +/* Common Error Codes For All Module Types. */ +enum { + CSSM_ERRCODE_INTERNAL_ERROR = 0x0001, + CSSM_ERRCODE_MEMORY_ERROR = 0x0002, + CSSM_ERRCODE_MDS_ERROR = 0x0003, + CSSM_ERRCODE_INVALID_POINTER = 0x0004, + CSSM_ERRCODE_INVALID_INPUT_POINTER = 0x0005, + CSSM_ERRCODE_INVALID_OUTPUT_POINTER = 0x0006, + CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED = 0x0007, + CSSM_ERRCODE_SELF_CHECK_FAILED = 0x0008, + CSSM_ERRCODE_OS_ACCESS_DENIED = 0x0009, + CSSM_ERRCODE_FUNCTION_FAILED = 0x000A, + CSSM_ERRCODE_MODULE_MANIFEST_VERIFY_FAILED = 0x000B, + CSSM_ERRCODE_INVALID_GUID = 0x000C +}; + +/* Common Error Codes for ACLs */ +enum { + CSSM_ERRCODE_OPERATION_AUTH_DENIED = 0x0020, + CSSM_ERRCODE_OBJECT_USE_AUTH_DENIED = 0x0021, + CSSM_ERRCODE_OBJECT_MANIP_AUTH_DENIED = 0x0022, + CSSM_ERRCODE_OBJECT_ACL_NOT_SUPPORTED = 0x0023, + CSSM_ERRCODE_OBJECT_ACL_REQUIRED = 0x0024, + CSSM_ERRCODE_INVALID_ACCESS_CREDENTIALS = 0x0025, + CSSM_ERRCODE_INVALID_ACL_BASE_CERTS = 0x0026, + CSSM_ERRCODE_ACL_BASE_CERTS_NOT_SUPPORTED = 0x0027, + CSSM_ERRCODE_INVALID_SAMPLE_VALUE = 0x0028, + CSSM_ERRCODE_SAMPLE_VALUE_NOT_SUPPORTED = 0x0029, + CSSM_ERRCODE_INVALID_ACL_SUBJECT_VALUE = 0x002A, + CSSM_ERRCODE_ACL_SUBJECT_TYPE_NOT_SUPPORTED = 0x002B, + CSSM_ERRCODE_INVALID_ACL_CHALLENGE_CALLBACK = 0x002C, + CSSM_ERRCODE_ACL_CHALLENGE_CALLBACK_FAILED = 0x002D, + CSSM_ERRCODE_INVALID_ACL_ENTRY_TAG = 0x002E, + CSSM_ERRCODE_ACL_ENTRY_TAG_NOT_FOUND = 0x002F, + CSSM_ERRCODE_INVALID_ACL_EDIT_MODE = 0x0030, + CSSM_ERRCODE_ACL_CHANGE_FAILED = 0x0031, + CSSM_ERRCODE_INVALID_NEW_ACL_ENTRY = 0x0032, + CSSM_ERRCODE_INVALID_NEW_ACL_OWNER = 0x0033, + CSSM_ERRCODE_ACL_DELETE_FAILED = 0x0034, + CSSM_ERRCODE_ACL_REPLACE_FAILED = 0x0035, + CSSM_ERRCODE_ACL_ADD_FAILED = 0x0036 +}; + +/* Common Error Codes for Specific Data Types */ +enum { + CSSM_ERRCODE_INVALID_CONTEXT_HANDLE = 0x0040, + CSSM_ERRCODE_INCOMPATIBLE_VERSION = 0x0041, + CSSM_ERRCODE_INVALID_CERTGROUP_POINTER = 0x0042, + CSSM_ERRCODE_INVALID_CERT_POINTER = 0x0043, + CSSM_ERRCODE_INVALID_CRL_POINTER = 0x0044, + CSSM_ERRCODE_INVALID_FIELD_POINTER = 0x0045, + CSSM_ERRCODE_INVALID_DATA = 0x0046, + CSSM_ERRCODE_CRL_ALREADY_SIGNED = 0x0047, + CSSM_ERRCODE_INVALID_NUMBER_OF_FIELDS = 0x0048, + CSSM_ERRCODE_VERIFICATION_FAILURE = 0x0049, + CSSM_ERRCODE_INVALID_DB_HANDLE = 0x004A, + CSSM_ERRCODE_PRIVILEGE_NOT_GRANTED = 0x004B, + CSSM_ERRCODE_INVALID_DB_LIST = 0x004C, + CSSM_ERRCODE_INVALID_DB_LIST_POINTER = 0x004D, + CSSM_ERRCODE_UNKNOWN_FORMAT = 0x004E, + CSSM_ERRCODE_UNKNOWN_TAG = 0x004F, + CSSM_ERRCODE_INVALID_CSP_HANDLE = 0x0050, + CSSM_ERRCODE_INVALID_DL_HANDLE = 0x0051, + CSSM_ERRCODE_INVALID_CL_HANDLE = 0x0052, + CSSM_ERRCODE_INVALID_TP_HANDLE = 0x0053, + CSSM_ERRCODE_INVALID_KR_HANDLE = 0x0054, + CSSM_ERRCODE_INVALID_AC_HANDLE = 0x0055, + CSSM_ERRCODE_INVALID_PASSTHROUGH_ID = 0x0056, + CSSM_ERRCODE_INVALID_NETWORK_ADDR = 0x0057, + CSSM_ERRCODE_INVALID_CRYPTO_DATA = 0x0058 +}; + +/* CSSM Error Values Derived from Common Error Codes For All Module Types. */ +enum { + CSSMERR_CSSM_INTERNAL_ERROR = + CSSM_CSSM_BASE_ERROR + CSSM_ERRCODE_INTERNAL_ERROR, + CSSMERR_CSSM_MEMORY_ERROR = + CSSM_CSSM_BASE_ERROR + CSSM_ERRCODE_MEMORY_ERROR, + CSSMERR_CSSM_MDS_ERROR = + CSSM_CSSM_BASE_ERROR + CSSM_ERRCODE_MDS_ERROR, + CSSMERR_CSSM_INVALID_POINTER = + CSSM_CSSM_BASE_ERROR + CSSM_ERRCODE_INVALID_POINTER, + CSSMERR_CSSM_INVALID_INPUT_POINTER = + CSSM_CSSM_BASE_ERROR + CSSM_ERRCODE_INVALID_INPUT_POINTER, + CSSMERR_CSSM_INVALID_OUTPUT_POINTER = + CSSM_CSSM_BASE_ERROR + CSSM_ERRCODE_INVALID_OUTPUT_POINTER, + CSSMERR_CSSM_FUNCTION_NOT_IMPLEMENTED = + CSSM_CSSM_BASE_ERROR + CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED, + CSSMERR_CSSM_SELF_CHECK_FAILED = + CSSM_CSSM_BASE_ERROR + CSSM_ERRCODE_SELF_CHECK_FAILED, + CSSMERR_CSSM_OS_ACCESS_DENIED = + CSSM_CSSM_BASE_ERROR + CSSM_ERRCODE_OS_ACCESS_DENIED, + CSSMERR_CSSM_FUNCTION_FAILED = + CSSM_CSSM_BASE_ERROR + CSSM_ERRCODE_FUNCTION_FAILED, + CSSMERR_CSSM_MODULE_MANIFEST_VERIFY_FAILED = + CSSM_CSSM_BASE_ERROR + CSSM_ERRCODE_MODULE_MANIFEST_VERIFY_FAILED, + CSSMERR_CSSM_INVALID_GUID = + CSSM_CSSM_BASE_ERROR + CSSM_ERRCODE_INVALID_GUID +}; + +/* CSSM Error Values for Specific Data Types. */ +enum { + CSSMERR_CSSM_INVALID_CONTEXT_HANDLE = + CSSM_CSSM_BASE_ERROR + CSSM_ERRCODE_INVALID_CONTEXT_HANDLE, + CSSMERR_CSSM_INCOMPATIBLE_VERSION = + CSSM_CSSM_BASE_ERROR + CSSM_ERRCODE_INCOMPATIBLE_VERSION, + CSSMERR_CSSM_PRIVILEGE_NOT_GRANTED = + CSSM_CSSM_BASE_ERROR + CSSM_ERRCODE_PRIVILEGE_NOT_GRANTED +}; + +/* CSSM Module-Specific Error Values */ +enum { + 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, + CSSMERR_CSSM_PVC_ALREADY_CONFIGURED = CSSM_CSSM_BASE_CSSM_ERROR + 2, + CSSMERR_CSSM_INVALID_PVC = CSSM_CSSM_BASE_CSSM_ERROR + 3, + CSSMERR_CSSM_EMM_LOAD_FAILED = CSSM_CSSM_BASE_CSSM_ERROR + 4, + CSSMERR_CSSM_EMM_UNLOAD_FAILED = CSSM_CSSM_BASE_CSSM_ERROR + 5, + CSSMERR_CSSM_ADDIN_LOAD_FAILED = CSSM_CSSM_BASE_CSSM_ERROR + 6, + CSSMERR_CSSM_INVALID_KEY_HIERARCHY = CSSM_CSSM_BASE_CSSM_ERROR + 7, + CSSMERR_CSSM_ADDIN_UNLOAD_FAILED = CSSM_CSSM_BASE_CSSM_ERROR + 8, + CSSMERR_CSSM_LIB_REF_NOT_FOUND = CSSM_CSSM_BASE_CSSM_ERROR + 9, + CSSMERR_CSSM_INVALID_ADDIN_FUNCTION_TABLE = CSSM_CSSM_BASE_CSSM_ERROR + 10, + CSSMERR_CSSM_EMM_AUTHENTICATE_FAILED = CSSM_CSSM_BASE_CSSM_ERROR + 11, + CSSMERR_CSSM_ADDIN_AUTHENTICATE_FAILED = CSSM_CSSM_BASE_CSSM_ERROR + 12, + CSSMERR_CSSM_INVALID_SERVICE_MASK = CSSM_CSSM_BASE_CSSM_ERROR + 13, + CSSMERR_CSSM_MODULE_NOT_LOADED = CSSM_CSSM_BASE_CSSM_ERROR + 14, + CSSMERR_CSSM_INVALID_SUBSERVICEID = CSSM_CSSM_BASE_CSSM_ERROR + 15, + CSSMERR_CSSM_BUFFER_TOO_SMALL = CSSM_CSSM_BASE_CSSM_ERROR + 16, + CSSMERR_CSSM_INVALID_ATTRIBUTE = CSSM_CSSM_BASE_CSSM_ERROR + 17, + CSSMERR_CSSM_ATTRIBUTE_NOT_IN_CONTEXT = CSSM_CSSM_BASE_CSSM_ERROR + 18, + CSSMERR_CSSM_MODULE_MANAGER_INITIALIZE_FAIL = CSSM_CSSM_BASE_CSSM_ERROR + 19, + CSSMERR_CSSM_MODULE_MANAGER_NOT_FOUND = CSSM_CSSM_BASE_CSSM_ERROR + 20, + CSSMERR_CSSM_EVENT_NOTIFICATION_CALLBACK_NOT_FOUND = CSSM_CSSM_BASE_CSSM_ERROR + 21 +}; + +/* CSP Error Values Derived from Common Error Codes For All Module Types. */ +enum { + CSSMERR_CSP_INTERNAL_ERROR = + CSSM_CSP_BASE_ERROR + CSSM_ERRCODE_INTERNAL_ERROR, + CSSMERR_CSP_MEMORY_ERROR = + CSSM_CSP_BASE_ERROR + CSSM_ERRCODE_MEMORY_ERROR, + CSSMERR_CSP_MDS_ERROR = + CSSM_CSP_BASE_ERROR + CSSM_ERRCODE_MDS_ERROR, + CSSMERR_CSP_INVALID_POINTER = + CSSM_CSP_BASE_ERROR + CSSM_ERRCODE_INVALID_POINTER, + CSSMERR_CSP_INVALID_INPUT_POINTER = + CSSM_CSP_BASE_ERROR + CSSM_ERRCODE_INVALID_INPUT_POINTER, + CSSMERR_CSP_INVALID_OUTPUT_POINTER = + CSSM_CSP_BASE_ERROR + CSSM_ERRCODE_INVALID_OUTPUT_POINTER, + CSSMERR_CSP_FUNCTION_NOT_IMPLEMENTED = + CSSM_CSP_BASE_ERROR + CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED, + CSSMERR_CSP_SELF_CHECK_FAILED = + CSSM_CSP_BASE_ERROR + CSSM_ERRCODE_SELF_CHECK_FAILED, + CSSMERR_CSP_OS_ACCESS_DENIED = + CSSM_CSP_BASE_ERROR + CSSM_ERRCODE_OS_ACCESS_DENIED, + CSSMERR_CSP_FUNCTION_FAILED = + CSSM_CSP_BASE_ERROR + CSSM_ERRCODE_FUNCTION_FAILED +}; + +/* CSP Error Values Derived from ACL-based Error Codes. */ +enum { + CSSMERR_CSP_OPERATION_AUTH_DENIED = + CSSM_CSP_BASE_ERROR + CSSM_ERRCODE_OPERATION_AUTH_DENIED, + CSSMERR_CSP_OBJECT_USE_AUTH_DENIED = + CSSM_CSP_BASE_ERROR + CSSM_ERRCODE_OBJECT_USE_AUTH_DENIED, + CSSMERR_CSP_OBJECT_MANIP_AUTH_DENIED = + CSSM_CSP_BASE_ERROR + CSSM_ERRCODE_OBJECT_MANIP_AUTH_DENIED, + CSSMERR_CSP_OBJECT_ACL_NOT_SUPPORTED = + CSSM_CSP_BASE_ERROR + CSSM_ERRCODE_OBJECT_ACL_NOT_SUPPORTED, + CSSMERR_CSP_OBJECT_ACL_REQUIRED = + CSSM_CSP_BASE_ERROR + CSSM_ERRCODE_OBJECT_ACL_REQUIRED, + CSSMERR_CSP_INVALID_ACCESS_CREDENTIALS = + CSSM_CSP_BASE_ERROR + CSSM_ERRCODE_INVALID_ACCESS_CREDENTIALS, + CSSMERR_CSP_INVALID_ACL_BASE_CERTS = + CSSM_CSP_BASE_ERROR + CSSM_ERRCODE_INVALID_ACL_BASE_CERTS, + CSSMERR_CSP_ACL_BASE_CERTS_NOT_SUPPORTED = + CSSM_CSP_BASE_ERROR + CSSM_ERRCODE_ACL_BASE_CERTS_NOT_SUPPORTED, + CSSMERR_CSP_INVALID_SAMPLE_VALUE = + CSSM_CSP_BASE_ERROR + CSSM_ERRCODE_INVALID_SAMPLE_VALUE, + CSSMERR_CSP_SAMPLE_VALUE_NOT_SUPPORTED = + CSSM_CSP_BASE_ERROR + CSSM_ERRCODE_SAMPLE_VALUE_NOT_SUPPORTED, + CSSMERR_CSP_INVALID_ACL_SUBJECT_VALUE = + CSSM_CSP_BASE_ERROR + CSSM_ERRCODE_INVALID_ACL_SUBJECT_VALUE, + CSSMERR_CSP_ACL_SUBJECT_TYPE_NOT_SUPPORTED = + CSSM_CSP_BASE_ERROR + CSSM_ERRCODE_ACL_SUBJECT_TYPE_NOT_SUPPORTED, + CSSMERR_CSP_INVALID_ACL_CHALLENGE_CALLBACK = + CSSM_CSP_BASE_ERROR + CSSM_ERRCODE_INVALID_ACL_CHALLENGE_CALLBACK, + CSSMERR_CSP_ACL_CHALLENGE_CALLBACK_FAILED = + CSSM_CSP_BASE_ERROR + CSSM_ERRCODE_ACL_CHALLENGE_CALLBACK_FAILED, + CSSMERR_CSP_INVALID_ACL_ENTRY_TAG = + CSSM_CSP_BASE_ERROR + CSSM_ERRCODE_INVALID_ACL_ENTRY_TAG, + CSSMERR_CSP_ACL_ENTRY_TAG_NOT_FOUND = + CSSM_CSP_BASE_ERROR + CSSM_ERRCODE_ACL_ENTRY_TAG_NOT_FOUND, + CSSMERR_CSP_INVALID_ACL_EDIT_MODE = + CSSM_CSP_BASE_ERROR + CSSM_ERRCODE_INVALID_ACL_EDIT_MODE, + CSSMERR_CSP_ACL_CHANGE_FAILED = + CSSM_CSP_BASE_ERROR + CSSM_ERRCODE_ACL_CHANGE_FAILED, + CSSMERR_CSP_INVALID_NEW_ACL_ENTRY = + CSSM_CSP_BASE_ERROR + CSSM_ERRCODE_INVALID_NEW_ACL_ENTRY, + CSSMERR_CSP_INVALID_NEW_ACL_OWNER = + CSSM_CSP_BASE_ERROR + CSSM_ERRCODE_INVALID_NEW_ACL_OWNER, + CSSMERR_CSP_ACL_DELETE_FAILED = + CSSM_CSP_BASE_ERROR + CSSM_ERRCODE_ACL_DELETE_FAILED, + CSSMERR_CSP_ACL_REPLACE_FAILED = + CSSM_CSP_BASE_ERROR + CSSM_ERRCODE_ACL_REPLACE_FAILED, + CSSMERR_CSP_ACL_ADD_FAILED = + CSSM_CSP_BASE_ERROR + CSSM_ERRCODE_ACL_ADD_FAILED +}; + +/* CSP Error Values for Specific Data Types. */ +enum { + CSSMERR_CSP_INVALID_CONTEXT_HANDLE = + CSSM_CSP_BASE_ERROR + CSSM_ERRCODE_INVALID_CONTEXT_HANDLE, + CSSMERR_CSP_PRIVILEGE_NOT_GRANTED = + CSSM_CSP_BASE_ERROR + CSSM_ERRCODE_PRIVILEGE_NOT_GRANTED, + CSSMERR_CSP_INVALID_DATA = + CSSM_CSP_BASE_ERROR + CSSM_ERRCODE_INVALID_DATA, + CSSMERR_CSP_INVALID_PASSTHROUGH_ID = + CSSM_CSP_BASE_ERROR + CSSM_ERRCODE_INVALID_PASSTHROUGH_ID, + CSSMERR_CSP_INVALID_CRYPTO_DATA = + CSSM_CSP_BASE_ERROR + CSSM_ERRCODE_INVALID_CRYPTO_DATA +}; + +/* CSP Module-Specific Error Values */ +enum { + /* General CSP Error Values */ + CSSM_CSP_BASE_CSP_ERROR = + CSSM_CSP_BASE_ERROR + CSSM_ERRORCODE_COMMON_EXTENT, + CSSMERR_CSP_INPUT_LENGTH_ERROR = CSSM_CSP_BASE_CSP_ERROR + 1, + CSSMERR_CSP_OUTPUT_LENGTH_ERROR = CSSM_CSP_BASE_CSP_ERROR + 2, + CSSMERR_CSP_PRIVILEGE_NOT_SUPPORTED = CSSM_CSP_BASE_CSP_ERROR + 3, + CSSMERR_CSP_DEVICE_ERROR = CSSM_CSP_BASE_CSP_ERROR + 4, + CSSMERR_CSP_DEVICE_MEMORY_ERROR = CSSM_CSP_BASE_CSP_ERROR + 5, + CSSMERR_CSP_ATTACH_HANDLE_BUSY = CSSM_CSP_BASE_CSP_ERROR + 6, + CSSMERR_CSP_NOT_LOGGED_IN = CSSM_CSP_BASE_CSP_ERROR + 7, + CSSMERR_CSP_INVALID_KEY = CSSM_CSP_BASE_CSP_ERROR + 16, + CSSMERR_CSP_INVALID_KEY_REFERENCE = CSSM_CSP_BASE_CSP_ERROR + 17, + CSSMERR_CSP_INVALID_KEY_CLASS = CSSM_CSP_BASE_CSP_ERROR + 18, + CSSMERR_CSP_ALGID_MISMATCH = CSSM_CSP_BASE_CSP_ERROR + 19, + CSSMERR_CSP_KEY_USAGE_INCORRECT = CSSM_CSP_BASE_CSP_ERROR + 20, + CSSMERR_CSP_KEY_BLOB_TYPE_INCORRECT = CSSM_CSP_BASE_CSP_ERROR + 21, + CSSMERR_CSP_KEY_HEADER_INCONSISTENT = CSSM_CSP_BASE_CSP_ERROR + 22, + CSSMERR_CSP_UNSUPPORTED_KEY_FORMAT = CSSM_CSP_BASE_CSP_ERROR + 23, + CSSMERR_CSP_UNSUPPORTED_KEY_SIZE = CSSM_CSP_BASE_CSP_ERROR + 24, + CSSMERR_CSP_INVALID_KEY_POINTER = CSSM_CSP_BASE_CSP_ERROR + 25, + CSSMERR_CSP_INVALID_KEYUSAGE_MASK = CSSM_CSP_BASE_CSP_ERROR + 26, + CSSMERR_CSP_UNSUPPORTED_KEYUSAGE_MASK = CSSM_CSP_BASE_CSP_ERROR + 27, + CSSMERR_CSP_INVALID_KEYATTR_MASK = CSSM_CSP_BASE_CSP_ERROR + 28, + CSSMERR_CSP_UNSUPPORTED_KEYATTR_MASK = CSSM_CSP_BASE_CSP_ERROR + 29, + CSSMERR_CSP_INVALID_KEY_LABEL = CSSM_CSP_BASE_CSP_ERROR + 30, + CSSMERR_CSP_UNSUPPORTED_KEY_LABEL = CSSM_CSP_BASE_CSP_ERROR + 31, + CSSMERR_CSP_INVALID_KEY_FORMAT = CSSM_CSP_BASE_CSP_ERROR + 32, + + /* CSP Vector of Buffers Error Values. */ + CSSMERR_CSP_INVALID_DATA_COUNT = CSSM_CSP_BASE_CSP_ERROR + 40, + CSSMERR_CSP_VECTOR_OF_BUFS_UNSUPPORTED = CSSM_CSP_BASE_CSP_ERROR + 41, + CSSMERR_CSP_INVALID_INPUT_VECTOR = CSSM_CSP_BASE_CSP_ERROR + 42, + CSSMERR_CSP_INVALID_OUTPUT_VECTOR = CSSM_CSP_BASE_CSP_ERROR + 43, + + /* CSP Cryptographic Context Error Values. */ + CSSMERR_CSP_INVALID_CONTEXT = CSSM_CSP_BASE_CSP_ERROR + 48, + CSSMERR_CSP_INVALID_ALGORITHM = CSSM_CSP_BASE_CSP_ERROR + 49, + CSSMERR_CSP_INVALID_ATTR_KEY = CSSM_CSP_BASE_CSP_ERROR + 54, + CSSMERR_CSP_MISSING_ATTR_KEY = CSSM_CSP_BASE_CSP_ERROR + 55, + CSSMERR_CSP_INVALID_ATTR_INIT_VECTOR = CSSM_CSP_BASE_CSP_ERROR + 56, + CSSMERR_CSP_MISSING_ATTR_INIT_VECTOR = CSSM_CSP_BASE_CSP_ERROR + 57, + CSSMERR_CSP_INVALID_ATTR_SALT = CSSM_CSP_BASE_CSP_ERROR + 58, + CSSMERR_CSP_MISSING_ATTR_SALT = CSSM_CSP_BASE_CSP_ERROR + 59, + CSSMERR_CSP_INVALID_ATTR_PADDING = CSSM_CSP_BASE_CSP_ERROR + 60, + CSSMERR_CSP_MISSING_ATTR_PADDING = CSSM_CSP_BASE_CSP_ERROR + 61, + CSSMERR_CSP_INVALID_ATTR_RANDOM = CSSM_CSP_BASE_CSP_ERROR + 62, + CSSMERR_CSP_MISSING_ATTR_RANDOM = CSSM_CSP_BASE_CSP_ERROR + 63, + CSSMERR_CSP_INVALID_ATTR_SEED = CSSM_CSP_BASE_CSP_ERROR + 64, + CSSMERR_CSP_MISSING_ATTR_SEED = CSSM_CSP_BASE_CSP_ERROR + 65, + CSSMERR_CSP_INVALID_ATTR_PASSPHRASE = CSSM_CSP_BASE_CSP_ERROR + 66, + CSSMERR_CSP_MISSING_ATTR_PASSPHRASE = CSSM_CSP_BASE_CSP_ERROR + 67, + CSSMERR_CSP_INVALID_ATTR_KEY_LENGTH = CSSM_CSP_BASE_CSP_ERROR + 68, + CSSMERR_CSP_MISSING_ATTR_KEY_LENGTH = CSSM_CSP_BASE_CSP_ERROR + 69, + CSSMERR_CSP_INVALID_ATTR_BLOCK_SIZE = CSSM_CSP_BASE_CSP_ERROR + 70, + CSSMERR_CSP_MISSING_ATTR_BLOCK_SIZE = CSSM_CSP_BASE_CSP_ERROR + 71, + CSSMERR_CSP_INVALID_ATTR_OUTPUT_SIZE = CSSM_CSP_BASE_CSP_ERROR + 100, + CSSMERR_CSP_MISSING_ATTR_OUTPUT_SIZE = CSSM_CSP_BASE_CSP_ERROR + 101, + CSSMERR_CSP_INVALID_ATTR_ROUNDS = CSSM_CSP_BASE_CSP_ERROR + 102, + CSSMERR_CSP_MISSING_ATTR_ROUNDS = CSSM_CSP_BASE_CSP_ERROR + 103, + CSSMERR_CSP_INVALID_ATTR_ALG_PARAMS = CSSM_CSP_BASE_CSP_ERROR + 104, + CSSMERR_CSP_MISSING_ATTR_ALG_PARAMS = CSSM_CSP_BASE_CSP_ERROR + 105, + CSSMERR_CSP_INVALID_ATTR_LABEL = CSSM_CSP_BASE_CSP_ERROR + 106, + CSSMERR_CSP_MISSING_ATTR_LABEL = CSSM_CSP_BASE_CSP_ERROR + 107, + CSSMERR_CSP_INVALID_ATTR_KEY_TYPE = CSSM_CSP_BASE_CSP_ERROR + 108, + CSSMERR_CSP_MISSING_ATTR_KEY_TYPE = CSSM_CSP_BASE_CSP_ERROR + 109, + CSSMERR_CSP_INVALID_ATTR_MODE = CSSM_CSP_BASE_CSP_ERROR + 110, + CSSMERR_CSP_MISSING_ATTR_MODE = CSSM_CSP_BASE_CSP_ERROR + 111, + CSSMERR_CSP_INVALID_ATTR_EFFECTIVE_BITS = CSSM_CSP_BASE_CSP_ERROR + 112, + CSSMERR_CSP_MISSING_ATTR_EFFECTIVE_BITS = CSSM_CSP_BASE_CSP_ERROR + 113, + CSSMERR_CSP_INVALID_ATTR_START_DATE = CSSM_CSP_BASE_CSP_ERROR + 114, + CSSMERR_CSP_MISSING_ATTR_START_DATE = CSSM_CSP_BASE_CSP_ERROR + 115, + CSSMERR_CSP_INVALID_ATTR_END_DATE = CSSM_CSP_BASE_CSP_ERROR + 116, + CSSMERR_CSP_MISSING_ATTR_END_DATE = CSSM_CSP_BASE_CSP_ERROR + 117, + CSSMERR_CSP_INVALID_ATTR_VERSION = CSSM_CSP_BASE_CSP_ERROR + 118, + CSSMERR_CSP_MISSING_ATTR_VERSION = CSSM_CSP_BASE_CSP_ERROR + 119, + CSSMERR_CSP_INVALID_ATTR_PRIME = CSSM_CSP_BASE_CSP_ERROR + 120, + CSSMERR_CSP_MISSING_ATTR_PRIME = CSSM_CSP_BASE_CSP_ERROR + 121, + CSSMERR_CSP_INVALID_ATTR_BASE = CSSM_CSP_BASE_CSP_ERROR + 122, + CSSMERR_CSP_MISSING_ATTR_BASE = CSSM_CSP_BASE_CSP_ERROR + 123, + CSSMERR_CSP_INVALID_ATTR_SUBPRIME = CSSM_CSP_BASE_CSP_ERROR + 124, + CSSMERR_CSP_MISSING_ATTR_SUBPRIME = CSSM_CSP_BASE_CSP_ERROR + 125, + CSSMERR_CSP_INVALID_ATTR_ITERATION_COUNT = CSSM_CSP_BASE_CSP_ERROR + 126, + CSSMERR_CSP_MISSING_ATTR_ITERATION_COUNT = CSSM_CSP_BASE_CSP_ERROR + 127, + CSSMERR_CSP_INVALID_ATTR_DL_DB_HANDLE = CSSM_CSP_BASE_CSP_ERROR + 128, + CSSMERR_CSP_MISSING_ATTR_DL_DB_HANDLE = CSSM_CSP_BASE_CSP_ERROR + 129, + CSSMERR_CSP_INVALID_ATTR_ACCESS_CREDENTIALS = CSSM_CSP_BASE_CSP_ERROR + 130, + CSSMERR_CSP_MISSING_ATTR_ACCESS_CREDENTIALS = CSSM_CSP_BASE_CSP_ERROR + 131, + CSSMERR_CSP_INVALID_ATTR_PUBLIC_KEY_FORMAT = CSSM_CSP_BASE_CSP_ERROR + 132, + CSSMERR_CSP_MISSING_ATTR_PUBLIC_KEY_FORMAT = CSSM_CSP_BASE_CSP_ERROR + 133, + CSSMERR_CSP_INVALID_ATTR_PRIVATE_KEY_FORMAT = CSSM_CSP_BASE_CSP_ERROR + 134, + CSSMERR_CSP_MISSING_ATTR_PRIVATE_KEY_FORMAT = CSSM_CSP_BASE_CSP_ERROR + 135, + CSSMERR_CSP_INVALID_ATTR_SYMMETRIC_KEY_FORMAT = CSSM_CSP_BASE_CSP_ERROR + 136, + CSSMERR_CSP_MISSING_ATTR_SYMMETRIC_KEY_FORMAT = CSSM_CSP_BASE_CSP_ERROR + 137, + CSSMERR_CSP_INVALID_ATTR_WRAPPED_KEY_FORMAT = CSSM_CSP_BASE_CSP_ERROR + 138, + CSSMERR_CSP_MISSING_ATTR_WRAPPED_KEY_FORMAT = CSSM_CSP_BASE_CSP_ERROR + 139, + + /* CSP Staged Cryptographic API Error Values. */ + CSSMERR_CSP_STAGED_OPERATION_IN_PROGRESS = CSSM_CSP_BASE_CSP_ERROR + 72, + CSSMERR_CSP_STAGED_OPERATION_NOT_STARTED = CSSM_CSP_BASE_CSP_ERROR + 73, + CSSMERR_CSP_VERIFY_FAILED = CSSM_CSP_BASE_CSP_ERROR + 74, + CSSMERR_CSP_INVALID_SIGNATURE = CSSM_CSP_BASE_CSP_ERROR + 75, + CSSMERR_CSP_QUERY_SIZE_UNKNOWN = CSSM_CSP_BASE_CSP_ERROR + 76, + CSSMERR_CSP_BLOCK_SIZE_MISMATCH = CSSM_CSP_BASE_CSP_ERROR + 77, + CSSMERR_CSP_PRIVATE_KEY_NOT_FOUND = CSSM_CSP_BASE_CSP_ERROR + 78, + CSSMERR_CSP_PUBLIC_KEY_INCONSISTENT = CSSM_CSP_BASE_CSP_ERROR + 79, + CSSMERR_CSP_DEVICE_VERIFY_FAILED = CSSM_CSP_BASE_CSP_ERROR + 80, + CSSMERR_CSP_INVALID_LOGIN_NAME = CSSM_CSP_BASE_CSP_ERROR + 81, + CSSMERR_CSP_ALREADY_LOGGED_IN = CSSM_CSP_BASE_CSP_ERROR + 82, + CSSMERR_CSP_PRIVATE_KEY_ALREADY_EXISTS = CSSM_CSP_BASE_CSP_ERROR + 83, + CSSMERR_CSP_KEY_LABEL_ALREADY_EXISTS = CSSM_CSP_BASE_CSP_ERROR + 84, + CSSMERR_CSP_INVALID_DIGEST_ALGORITHM = CSSM_CSP_BASE_CSP_ERROR + 85, + CSSMERR_CSP_CRYPTO_DATA_CALLBACK_FAILED = CSSM_CSP_BASE_CSP_ERROR + 86 +}; + + +/* TP Error Values Derived from Common Error Codes For All Module Types. */ +enum { + CSSMERR_TP_INTERNAL_ERROR = + CSSM_TP_BASE_ERROR + CSSM_ERRCODE_INTERNAL_ERROR, + CSSMERR_TP_MEMORY_ERROR = + CSSM_TP_BASE_ERROR + CSSM_ERRCODE_MEMORY_ERROR, + CSSMERR_TP_MDS_ERROR = + CSSM_TP_BASE_ERROR + CSSM_ERRCODE_MDS_ERROR, + CSSMERR_TP_INVALID_POINTER = + CSSM_TP_BASE_ERROR + CSSM_ERRCODE_INVALID_POINTER, + CSSMERR_TP_INVALID_INPUT_POINTER = + CSSM_TP_BASE_ERROR + CSSM_ERRCODE_INVALID_INPUT_POINTER, + CSSMERR_TP_INVALID_OUTPUT_POINTER = + CSSM_TP_BASE_ERROR + CSSM_ERRCODE_INVALID_OUTPUT_POINTER, + CSSMERR_TP_FUNCTION_NOT_IMPLEMENTED = + CSSM_TP_BASE_ERROR + CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED, + CSSMERR_TP_SELF_CHECK_FAILED = + CSSM_TP_BASE_ERROR + CSSM_ERRCODE_SELF_CHECK_FAILED, + CSSMERR_TP_OS_ACCESS_DENIED = + CSSM_TP_BASE_ERROR + CSSM_ERRCODE_OS_ACCESS_DENIED, + CSSMERR_TP_FUNCTION_FAILED = + CSSM_TP_BASE_ERROR + CSSM_ERRCODE_FUNCTION_FAILED, + CSSMERR_TP_INVALID_CONTEXT_HANDLE = + CSSM_TP_BASE_ERROR + CSSM_ERRCODE_INVALID_CONTEXT_HANDLE, + CSSMERR_TP_INVALID_DATA = + CSSM_TP_BASE_ERROR + CSSM_ERRCODE_INVALID_DATA, + CSSMERR_TP_INVALID_DB_LIST = + CSSM_TP_BASE_ERROR + CSSM_ERRCODE_INVALID_DB_LIST, + CSSMERR_TP_INVALID_CERTGROUP_POINTER = + CSSM_TP_BASE_ERROR + CSSM_ERRCODE_INVALID_CERTGROUP_POINTER, + CSSMERR_TP_INVALID_CERT_POINTER = + CSSM_TP_BASE_ERROR + CSSM_ERRCODE_INVALID_CERT_POINTER, + CSSMERR_TP_INVALID_CRL_POINTER = + CSSM_TP_BASE_ERROR + CSSM_ERRCODE_INVALID_CRL_POINTER, + CSSMERR_TP_INVALID_FIELD_POINTER = + CSSM_TP_BASE_ERROR + CSSM_ERRCODE_INVALID_FIELD_POINTER, + CSSMERR_TP_INVALID_NETWORK_ADDR = + CSSM_TP_BASE_ERROR + CSSM_ERRCODE_INVALID_NETWORK_ADDR, + CSSMERR_TP_CRL_ALREADY_SIGNED = + CSSM_TP_BASE_ERROR + CSSM_ERRCODE_CRL_ALREADY_SIGNED, + CSSMERR_TP_INVALID_NUMBER_OF_FIELDS = + CSSM_TP_BASE_ERROR + CSSM_ERRCODE_INVALID_NUMBER_OF_FIELDS, + CSSMERR_TP_VERIFICATION_FAILURE = + CSSM_TP_BASE_ERROR + CSSM_ERRCODE_VERIFICATION_FAILURE, + CSSMERR_TP_INVALID_DB_HANDLE = + CSSM_TP_BASE_ERROR + CSSM_ERRCODE_INVALID_DB_HANDLE, + CSSMERR_TP_UNKNOWN_FORMAT = + CSSM_TP_BASE_ERROR + CSSM_ERRCODE_UNKNOWN_FORMAT, + CSSMERR_TP_UNKNOWN_TAG = + CSSM_TP_BASE_ERROR + CSSM_ERRCODE_UNKNOWN_TAG, + CSSMERR_TP_INVALID_PASSTHROUGH_ID = + CSSM_TP_BASE_ERROR + CSSM_ERRCODE_INVALID_PASSTHROUGH_ID, + CSSMERR_TP_INVALID_CSP_HANDLE = + CSSM_TP_BASE_ERROR + CSSM_ERRCODE_INVALID_CSP_HANDLE, + CSSMERR_TP_INVALID_DL_HANDLE = + CSSM_TP_BASE_ERROR + CSSM_ERRCODE_INVALID_DL_HANDLE, + CSSMERR_TP_INVALID_CL_HANDLE = + CSSM_TP_BASE_ERROR + CSSM_ERRCODE_INVALID_CL_HANDLE, + CSSMERR_TP_INVALID_DB_LIST_POINTER = + CSSM_TP_BASE_ERROR + CSSM_ERRCODE_INVALID_DB_LIST_POINTER +}; + +/* TP Module-Specific Error Values */ +enum { + CSSM_TP_BASE_TP_ERROR = + CSSM_TP_BASE_ERROR + CSSM_ERRORCODE_COMMON_EXTENT, + CSSMERR_TP_INVALID_CALLERAUTH_CONTEXT_POINTER = CSSM_TP_BASE_TP_ERROR + 1, + CSSMERR_TP_INVALID_IDENTIFIER_POINTER = CSSM_TP_BASE_TP_ERROR + 2, + CSSMERR_TP_INVALID_KEYCACHE_HANDLE = CSSM_TP_BASE_TP_ERROR + 3, + CSSMERR_TP_INVALID_CERTGROUP = CSSM_TP_BASE_TP_ERROR + 4, + CSSMERR_TP_INVALID_CRLGROUP = CSSM_TP_BASE_TP_ERROR + 5, + CSSMERR_TP_INVALID_CRLGROUP_POINTER = CSSM_TP_BASE_TP_ERROR + 6, + CSSMERR_TP_AUTHENTICATION_FAILED = CSSM_TP_BASE_TP_ERROR + 7, + CSSMERR_TP_CERTGROUP_INCOMPLETE = CSSM_TP_BASE_TP_ERROR + 8, + CSSMERR_TP_CERTIFICATE_CANT_OPERATE = CSSM_TP_BASE_TP_ERROR + 9, + CSSMERR_TP_CERT_EXPIRED = CSSM_TP_BASE_TP_ERROR + 10, + CSSMERR_TP_CERT_NOT_VALID_YET = CSSM_TP_BASE_TP_ERROR + 11, + CSSMERR_TP_CERT_REVOKED = CSSM_TP_BASE_TP_ERROR + 12, + CSSMERR_TP_CERT_SUSPENDED = CSSM_TP_BASE_TP_ERROR + 13, + CSSMERR_TP_INSUFFICIENT_CREDENTIALS = CSSM_TP_BASE_TP_ERROR + 14, + CSSMERR_TP_INVALID_ACTION = CSSM_TP_BASE_TP_ERROR + 15, + CSSMERR_TP_INVALID_ACTION_DATA = CSSM_TP_BASE_TP_ERROR + 16, + CSSMERR_TP_INVALID_ANCHOR_CERT = CSSM_TP_BASE_TP_ERROR + 18, + CSSMERR_TP_INVALID_AUTHORITY = CSSM_TP_BASE_TP_ERROR + 19, + CSSMERR_TP_VERIFY_ACTION_FAILED = CSSM_TP_BASE_TP_ERROR + 20, + CSSMERR_TP_INVALID_CERTIFICATE = CSSM_TP_BASE_TP_ERROR + 21, + CSSMERR_TP_INVALID_CERT_AUTHORITY = CSSM_TP_BASE_TP_ERROR + 22, + CSSMERR_TP_INVALID_CRL_AUTHORITY = CSSM_TP_BASE_TP_ERROR + 23, + CSSMERR_TP_INVALID_CRL_ENCODING = CSSM_TP_BASE_TP_ERROR + 24, + CSSMERR_TP_INVALID_CRL_TYPE = CSSM_TP_BASE_TP_ERROR + 25, + CSSMERR_TP_INVALID_CRL = CSSM_TP_BASE_TP_ERROR + 26, + CSSMERR_TP_INVALID_FORM_TYPE = CSSM_TP_BASE_TP_ERROR + 27, + CSSMERR_TP_INVALID_ID = CSSM_TP_BASE_TP_ERROR + 28, + CSSMERR_TP_INVALID_IDENTIFIER = CSSM_TP_BASE_TP_ERROR + 29, + CSSMERR_TP_INVALID_INDEX = CSSM_TP_BASE_TP_ERROR + 30, + CSSMERR_TP_INVALID_NAME = CSSM_TP_BASE_TP_ERROR + 31, + CSSMERR_TP_INVALID_POLICY_IDENTIFIERS = CSSM_TP_BASE_TP_ERROR + 32, + CSSMERR_TP_INVALID_TIMESTRING = CSSM_TP_BASE_TP_ERROR + 33, + CSSMERR_TP_INVALID_REASON = CSSM_TP_BASE_TP_ERROR + 34, + CSSMERR_TP_INVALID_REQUEST_INPUTS = CSSM_TP_BASE_TP_ERROR + 35, + CSSMERR_TP_INVALID_RESPONSE_VECTOR = CSSM_TP_BASE_TP_ERROR + 36, + CSSMERR_TP_INVALID_SIGNATURE = CSSM_TP_BASE_TP_ERROR + 37, + CSSMERR_TP_INVALID_STOP_ON_POLICY = CSSM_TP_BASE_TP_ERROR + 38, + CSSMERR_TP_INVALID_CALLBACK = CSSM_TP_BASE_TP_ERROR + 39, + CSSMERR_TP_INVALID_TUPLE = CSSM_TP_BASE_TP_ERROR + 40, + CSSMERR_TP_NOT_SIGNER = CSSM_TP_BASE_TP_ERROR + 41, + CSSMERR_TP_NOT_TRUSTED = CSSM_TP_BASE_TP_ERROR + 42, + CSSMERR_TP_NO_DEFAULT_AUTHORITY = CSSM_TP_BASE_TP_ERROR + 43, + CSSMERR_TP_REJECTED_FORM = CSSM_TP_BASE_TP_ERROR + 44, + CSSMERR_TP_REQUEST_LOST = CSSM_TP_BASE_TP_ERROR + 45, + CSSMERR_TP_REQUEST_REJECTED = CSSM_TP_BASE_TP_ERROR + 46, + CSSMERR_TP_UNSUPPORTED_ADDR_TYPE = CSSM_TP_BASE_TP_ERROR + 47, + CSSMERR_TP_UNSUPPORTED_SERVICE = CSSM_TP_BASE_TP_ERROR + 48, + CSSMERR_TP_INVALID_TUPLEGROUP_POINTER = CSSM_TP_BASE_TP_ERROR + 49, + CSSMERR_TP_INVALID_TUPLEGROUP = CSSM_TP_BASE_TP_ERROR + 50 +}; + +/* AC Error Values Derived from Common Error Codes For All Module Types. */ +enum { + CSSMERR_AC_INTERNAL_ERROR = + CSSM_AC_BASE_ERROR + CSSM_ERRCODE_INTERNAL_ERROR, + CSSMERR_AC_MEMORY_ERROR = + CSSM_AC_BASE_ERROR + CSSM_ERRCODE_MEMORY_ERROR, + CSSMERR_AC_MDS_ERROR = + CSSM_AC_BASE_ERROR + CSSM_ERRCODE_MDS_ERROR, + CSSMERR_AC_INVALID_POINTER = + CSSM_AC_BASE_ERROR + CSSM_ERRCODE_INVALID_POINTER, + CSSMERR_AC_INVALID_INPUT_POINTER = + CSSM_AC_BASE_ERROR + CSSM_ERRCODE_INVALID_INPUT_POINTER, + CSSMERR_AC_INVALID_OUTPUT_POINTER = + CSSM_AC_BASE_ERROR + CSSM_ERRCODE_INVALID_OUTPUT_POINTER, + CSSMERR_AC_FUNCTION_NOT_IMPLEMENTED = + CSSM_AC_BASE_ERROR + CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED, + CSSMERR_AC_SELF_CHECK_FAILED = + CSSM_AC_BASE_ERROR + CSSM_ERRCODE_SELF_CHECK_FAILED, + CSSMERR_AC_OS_ACCESS_DENIED = + CSSM_AC_BASE_ERROR + CSSM_ERRCODE_OS_ACCESS_DENIED, + CSSMERR_AC_FUNCTION_FAILED = + CSSM_AC_BASE_ERROR + CSSM_ERRCODE_FUNCTION_FAILED, + CSSMERR_AC_INVALID_CONTEXT_HANDLE = + CSSM_AC_BASE_ERROR + CSSM_ERRCODE_INVALID_CONTEXT_HANDLE, + CSSMERR_AC_INVALID_DATA = + CSSM_AC_BASE_ERROR + CSSM_ERRCODE_INVALID_DATA, + CSSMERR_AC_INVALID_DB_LIST = + CSSM_AC_BASE_ERROR + CSSM_ERRCODE_INVALID_DB_LIST, + CSSMERR_AC_INVALID_PASSTHROUGH_ID = + CSSM_AC_BASE_ERROR + CSSM_ERRCODE_INVALID_PASSTHROUGH_ID, + CSSMERR_AC_INVALID_DL_HANDLE = + CSSM_AC_BASE_ERROR + CSSM_ERRCODE_INVALID_DL_HANDLE, + CSSMERR_AC_INVALID_CL_HANDLE = + CSSM_AC_BASE_ERROR + CSSM_ERRCODE_INVALID_CL_HANDLE, + CSSMERR_AC_INVALID_TP_HANDLE = + CSSM_AC_BASE_ERROR + CSSM_ERRCODE_INVALID_TP_HANDLE, + CSSMERR_AC_INVALID_DB_HANDLE = + CSSM_AC_BASE_ERROR + CSSM_ERRCODE_INVALID_DB_HANDLE, + CSSMERR_AC_INVALID_DB_LIST_POINTER = + CSSM_AC_BASE_ERROR + CSSM_ERRCODE_INVALID_DB_LIST_POINTER +}; + +/* AC Module-Specific Error Values */ +enum { + CSSM_AC_BASE_AC_ERROR = + CSSM_AC_BASE_ERROR + CSSM_ERRORCODE_COMMON_EXTENT, + CSSMERR_AC_INVALID_BASE_ACLS = CSSM_AC_BASE_AC_ERROR + 1, + CSSMERR_AC_INVALID_TUPLE_CREDENTIALS = CSSM_AC_BASE_AC_ERROR + 2, + CSSMERR_AC_INVALID_ENCODING = CSSM_AC_BASE_AC_ERROR + 3, + CSSMERR_AC_INVALID_VALIDITY_PERIOD = CSSM_AC_BASE_AC_ERROR + 4, + CSSMERR_AC_INVALID_REQUESTOR = CSSM_AC_BASE_AC_ERROR + 5, + CSSMERR_AC_INVALID_REQUEST_DESCRIPTOR = CSSM_AC_BASE_AC_ERROR + 6 +}; + +/* CL Error Values Derived from Common Error Codes For All Module Types. */ +enum { + CSSMERR_CL_INTERNAL_ERROR = + CSSM_CL_BASE_ERROR + CSSM_ERRCODE_INTERNAL_ERROR, + CSSMERR_CL_MEMORY_ERROR = + CSSM_CL_BASE_ERROR + CSSM_ERRCODE_MEMORY_ERROR, + CSSMERR_CL_MDS_ERROR = + CSSM_CL_BASE_ERROR + CSSM_ERRCODE_MDS_ERROR, + CSSMERR_CL_INVALID_POINTER = + CSSM_CL_BASE_ERROR + CSSM_ERRCODE_INVALID_POINTER, + CSSMERR_CL_INVALID_INPUT_POINTER = + CSSM_CL_BASE_ERROR + CSSM_ERRCODE_INVALID_INPUT_POINTER, + CSSMERR_CL_INVALID_OUTPUT_POINTER = + CSSM_CL_BASE_ERROR + CSSM_ERRCODE_INVALID_OUTPUT_POINTER, + CSSMERR_CL_FUNCTION_NOT_IMPLEMENTED = + CSSM_CL_BASE_ERROR + CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED, + CSSMERR_CL_SELF_CHECK_FAILED = + CSSM_CL_BASE_ERROR + CSSM_ERRCODE_SELF_CHECK_FAILED, + CSSMERR_CL_OS_ACCESS_DENIED = + CSSM_CL_BASE_ERROR + CSSM_ERRCODE_OS_ACCESS_DENIED, + CSSMERR_CL_FUNCTION_FAILED = + CSSM_CL_BASE_ERROR + CSSM_ERRCODE_FUNCTION_FAILED, + CSSMERR_CL_INVALID_CONTEXT_HANDLE = + CSSM_CL_BASE_ERROR + CSSM_ERRCODE_INVALID_CONTEXT_HANDLE, + CSSMERR_CL_INVALID_CERTGROUP_POINTER = + CSSM_CL_BASE_ERROR + CSSM_ERRCODE_INVALID_CERTGROUP_POINTER, + CSSMERR_CL_INVALID_CERT_POINTER = + CSSM_CL_BASE_ERROR + CSSM_ERRCODE_INVALID_CERT_POINTER, + CSSMERR_CL_INVALID_CRL_POINTER = + CSSM_CL_BASE_ERROR + CSSM_ERRCODE_INVALID_CRL_POINTER, + CSSMERR_CL_INVALID_FIELD_POINTER = + CSSM_CL_BASE_ERROR + CSSM_ERRCODE_INVALID_FIELD_POINTER, + CSSMERR_CL_INVALID_DATA = + CSSM_CL_BASE_ERROR + CSSM_ERRCODE_INVALID_DATA, + CSSMERR_CL_CRL_ALREADY_SIGNED = + CSSM_CL_BASE_ERROR + CSSM_ERRCODE_CRL_ALREADY_SIGNED, + CSSMERR_CL_INVALID_NUMBER_OF_FIELDS = + CSSM_CL_BASE_ERROR + CSSM_ERRCODE_INVALID_NUMBER_OF_FIELDS, + CSSMERR_CL_VERIFICATION_FAILURE = + CSSM_CL_BASE_ERROR + CSSM_ERRCODE_VERIFICATION_FAILURE, + CSSMERR_CL_UNKNOWN_FORMAT = + CSSM_CL_BASE_ERROR + CSSM_ERRCODE_UNKNOWN_FORMAT, + CSSMERR_CL_UNKNOWN_TAG = + CSSM_CL_BASE_ERROR + CSSM_ERRCODE_UNKNOWN_TAG, + CSSMERR_CL_INVALID_PASSTHROUGH_ID = + CSSM_CL_BASE_ERROR + CSSM_ERRCODE_INVALID_PASSTHROUGH_ID +}; + +/* CL Module-Specific Error Values */ +enum { + CSSM_CL_BASE_CL_ERROR = + CSSM_CL_BASE_ERROR + CSSM_ERRORCODE_COMMON_EXTENT, + CSSMERR_CL_INVALID_BUNDLE_POINTER = CSSM_CL_BASE_CL_ERROR + 1, + CSSMERR_CL_INVALID_CACHE_HANDLE = CSSM_CL_BASE_CL_ERROR + 2, + CSSMERR_CL_INVALID_RESULTS_HANDLE = CSSM_CL_BASE_CL_ERROR + 3, + CSSMERR_CL_INVALID_BUNDLE_INFO = CSSM_CL_BASE_CL_ERROR + 4, + CSSMERR_CL_INVALID_CRL_INDEX = CSSM_CL_BASE_CL_ERROR + 5, + CSSMERR_CL_INVALID_SCOPE = CSSM_CL_BASE_CL_ERROR + 6, + CSSMERR_CL_NO_FIELD_VALUES = CSSM_CL_BASE_CL_ERROR + 7, + CSSMERR_CL_SCOPE_NOT_SUPPORTED = CSSM_CL_BASE_CL_ERROR + 8 +}; + +/* DL Error Values Derived from Common Error Codes For All Module Types. */ +enum { + CSSMERR_DL_INTERNAL_ERROR = + CSSM_DL_BASE_ERROR + CSSM_ERRCODE_INTERNAL_ERROR, + CSSMERR_DL_MEMORY_ERROR = + CSSM_DL_BASE_ERROR + CSSM_ERRCODE_MEMORY_ERROR, + CSSMERR_DL_MDS_ERROR = + CSSM_DL_BASE_ERROR + CSSM_ERRCODE_MDS_ERROR, + CSSMERR_DL_INVALID_POINTER = + CSSM_DL_BASE_ERROR + CSSM_ERRCODE_INVALID_POINTER, + CSSMERR_DL_INVALID_INPUT_POINTER = + CSSM_DL_BASE_ERROR + CSSM_ERRCODE_INVALID_INPUT_POINTER, + CSSMERR_DL_INVALID_OUTPUT_POINTER = + CSSM_DL_BASE_ERROR + CSSM_ERRCODE_INVALID_OUTPUT_POINTER, + CSSMERR_DL_FUNCTION_NOT_IMPLEMENTED = + CSSM_DL_BASE_ERROR + CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED, + CSSMERR_DL_SELF_CHECK_FAILED = + CSSM_DL_BASE_ERROR + CSSM_ERRCODE_SELF_CHECK_FAILED, + CSSMERR_DL_OS_ACCESS_DENIED = + CSSM_DL_BASE_ERROR + CSSM_ERRCODE_OS_ACCESS_DENIED, + CSSMERR_DL_FUNCTION_FAILED = + CSSM_DL_BASE_ERROR + CSSM_ERRCODE_FUNCTION_FAILED, + CSSMERR_DL_INVALID_CSP_HANDLE = + CSSM_DL_BASE_ERROR + CSSM_ERRCODE_INVALID_CSP_HANDLE, + CSSMERR_DL_INVALID_DL_HANDLE = + CSSM_DL_BASE_ERROR + CSSM_ERRCODE_INVALID_DL_HANDLE, + CSSMERR_DL_INVALID_CL_HANDLE = + CSSM_DL_BASE_ERROR + CSSM_ERRCODE_INVALID_CL_HANDLE, + CSSMERR_DL_INVALID_DB_LIST_POINTER = + CSSM_DL_BASE_ERROR + CSSM_ERRCODE_INVALID_DB_LIST_POINTER +}; + +/* DL Error Values Derived from ACL-based Error Codes. */ +enum { + CSSMERR_DL_OPERATION_AUTH_DENIED = + CSSM_DL_BASE_ERROR + CSSM_ERRCODE_OPERATION_AUTH_DENIED, + CSSMERR_DL_OBJECT_USE_AUTH_DENIED = + CSSM_DL_BASE_ERROR + CSSM_ERRCODE_OBJECT_USE_AUTH_DENIED, + CSSMERR_DL_OBJECT_MANIP_AUTH_DENIED = + CSSM_DL_BASE_ERROR + CSSM_ERRCODE_OBJECT_MANIP_AUTH_DENIED, + CSSMERR_DL_OBJECT_ACL_NOT_SUPPORTED = + CSSM_DL_BASE_ERROR + CSSM_ERRCODE_OBJECT_ACL_NOT_SUPPORTED, + CSSMERR_DL_OBJECT_ACL_REQUIRED = + CSSM_DL_BASE_ERROR + CSSM_ERRCODE_OBJECT_ACL_REQUIRED, + CSSMERR_DL_INVALID_ACCESS_CREDENTIALS = + CSSM_DL_BASE_ERROR + CSSM_ERRCODE_INVALID_ACCESS_CREDENTIALS, + CSSMERR_DL_INVALID_ACL_BASE_CERTS = + CSSM_DL_BASE_ERROR + CSSM_ERRCODE_INVALID_ACL_BASE_CERTS, + CSSMERR_DL_ACL_BASE_CERTS_NOT_SUPPORTED = + CSSM_DL_BASE_ERROR + CSSM_ERRCODE_ACL_BASE_CERTS_NOT_SUPPORTED, + CSSMERR_DL_INVALID_SAMPLE_VALUE = + CSSM_DL_BASE_ERROR + CSSM_ERRCODE_INVALID_SAMPLE_VALUE, + CSSMERR_DL_SAMPLE_VALUE_NOT_SUPPORTED = + CSSM_DL_BASE_ERROR + CSSM_ERRCODE_SAMPLE_VALUE_NOT_SUPPORTED, + CSSMERR_DL_INVALID_ACL_SUBJECT_VALUE = + CSSM_DL_BASE_ERROR + CSSM_ERRCODE_INVALID_ACL_SUBJECT_VALUE, + CSSMERR_DL_ACL_SUBJECT_TYPE_NOT_SUPPORTED = + CSSM_DL_BASE_ERROR + CSSM_ERRCODE_ACL_SUBJECT_TYPE_NOT_SUPPORTED, + CSSMERR_DL_INVALID_ACL_CHALLENGE_CALLBACK = + CSSM_DL_BASE_ERROR + CSSM_ERRCODE_INVALID_ACL_CHALLENGE_CALLBACK, + CSSMERR_DL_ACL_CHALLENGE_CALLBACK_FAILED = + CSSM_DL_BASE_ERROR + CSSM_ERRCODE_ACL_CHALLENGE_CALLBACK_FAILED, + CSSMERR_DL_INVALID_ACL_ENTRY_TAG = + CSSM_DL_BASE_ERROR + CSSM_ERRCODE_INVALID_ACL_ENTRY_TAG, + CSSMERR_DL_ACL_ENTRY_TAG_NOT_FOUND = + CSSM_DL_BASE_ERROR + CSSM_ERRCODE_ACL_ENTRY_TAG_NOT_FOUND, + CSSMERR_DL_INVALID_ACL_EDIT_MODE = + CSSM_DL_BASE_ERROR + CSSM_ERRCODE_INVALID_ACL_EDIT_MODE, + CSSMERR_DL_ACL_CHANGE_FAILED = + CSSM_DL_BASE_ERROR + CSSM_ERRCODE_ACL_CHANGE_FAILED, + CSSMERR_DL_INVALID_NEW_ACL_ENTRY = + CSSM_DL_BASE_ERROR + CSSM_ERRCODE_INVALID_NEW_ACL_ENTRY, + CSSMERR_DL_INVALID_NEW_ACL_OWNER = + CSSM_DL_BASE_ERROR + CSSM_ERRCODE_INVALID_NEW_ACL_OWNER, + CSSMERR_DL_ACL_DELETE_FAILED = + CSSM_DL_BASE_ERROR + CSSM_ERRCODE_ACL_DELETE_FAILED, + CSSMERR_DL_ACL_REPLACE_FAILED = + CSSM_DL_BASE_ERROR + CSSM_ERRCODE_ACL_REPLACE_FAILED, + CSSMERR_DL_ACL_ADD_FAILED = + CSSM_DL_BASE_ERROR + CSSM_ERRCODE_ACL_ADD_FAILED +}; + +/* DL Error Values for Specific Data Types. */ +enum { + CSSMERR_DL_INVALID_DB_HANDLE = + CSSM_DL_BASE_ERROR + CSSM_ERRCODE_INVALID_DB_HANDLE, + CSSMERR_DL_INVALID_PASSTHROUGH_ID = + CSSM_DL_BASE_ERROR + CSSM_ERRCODE_INVALID_PASSTHROUGH_ID, + CSSMERR_DL_INVALID_NETWORK_ADDR = + CSSM_DL_BASE_ERROR + CSSM_ERRCODE_INVALID_NETWORK_ADDR +}; + +/* DL Module-Specific Error Values */ +enum { + CSSM_DL_BASE_DL_ERROR = + CSSM_DL_BASE_ERROR + CSSM_ERRORCODE_COMMON_EXTENT, + CSSMERR_DL_DATABASE_CORRUPT = CSSM_DL_BASE_DL_ERROR + 1, + CSSMERR_DL_INVALID_RECORD_INDEX = CSSM_DL_BASE_DL_ERROR + 8, + CSSMERR_DL_INVALID_RECORDTYPE = CSSM_DL_BASE_DL_ERROR + 9, + CSSMERR_DL_INVALID_FIELD_NAME = CSSM_DL_BASE_DL_ERROR + 10, + CSSMERR_DL_UNSUPPORTED_FIELD_FORMAT = CSSM_DL_BASE_DL_ERROR + 11, + CSSMERR_DL_UNSUPPORTED_INDEX_INFO = CSSM_DL_BASE_DL_ERROR + 12, + CSSMERR_DL_UNSUPPORTED_LOCALITY = CSSM_DL_BASE_DL_ERROR + 13, + CSSMERR_DL_UNSUPPORTED_NUM_ATTRIBUTES = CSSM_DL_BASE_DL_ERROR + 14, + CSSMERR_DL_UNSUPPORTED_NUM_INDEXES = CSSM_DL_BASE_DL_ERROR + 15, + CSSMERR_DL_UNSUPPORTED_NUM_RECORDTYPES = CSSM_DL_BASE_DL_ERROR + 16, + CSSMERR_DL_UNSUPPORTED_RECORDTYPE = CSSM_DL_BASE_DL_ERROR + 17, + CSSMERR_DL_FIELD_SPECIFIED_MULTIPLE = CSSM_DL_BASE_DL_ERROR + 18, + CSSMERR_DL_INCOMPATIBLE_FIELD_FORMAT = CSSM_DL_BASE_DL_ERROR + 19, + CSSMERR_DL_INVALID_PARSING_MODULE = CSSM_DL_BASE_DL_ERROR + 20, + CSSMERR_DL_INVALID_DB_NAME = CSSM_DL_BASE_DL_ERROR + 22, + CSSMERR_DL_DATASTORE_DOESNOT_EXIST = CSSM_DL_BASE_DL_ERROR + 23, + CSSMERR_DL_DATASTORE_ALREADY_EXISTS = CSSM_DL_BASE_DL_ERROR + 24, + CSSMERR_DL_DB_LOCKED = CSSM_DL_BASE_DL_ERROR + 25, + CSSMERR_DL_DATASTORE_IS_OPEN = CSSM_DL_BASE_DL_ERROR + 26, + CSSMERR_DL_RECORD_NOT_FOUND = CSSM_DL_BASE_DL_ERROR + 27, + CSSMERR_DL_MISSING_VALUE = CSSM_DL_BASE_DL_ERROR + 28, + CSSMERR_DL_UNSUPPORTED_QUERY = CSSM_DL_BASE_DL_ERROR + 29, + CSSMERR_DL_UNSUPPORTED_QUERY_LIMITS = CSSM_DL_BASE_DL_ERROR + 30, + CSSMERR_DL_UNSUPPORTED_NUM_SELECTION_PREDS = CSSM_DL_BASE_DL_ERROR + 31, + CSSMERR_DL_UNSUPPORTED_OPERATOR = CSSM_DL_BASE_DL_ERROR + 33, + CSSMERR_DL_INVALID_RESULTS_HANDLE = CSSM_DL_BASE_DL_ERROR + 34, + CSSMERR_DL_INVALID_DB_LOCATION = CSSM_DL_BASE_DL_ERROR + 35, + CSSMERR_DL_INVALID_ACCESS_REQUEST = CSSM_DL_BASE_DL_ERROR + 36, + CSSMERR_DL_INVALID_INDEX_INFO = CSSM_DL_BASE_DL_ERROR + 37, + CSSMERR_DL_INVALID_SELECTION_TAG = CSSM_DL_BASE_DL_ERROR + 38, + CSSMERR_DL_INVALID_NEW_OWNER = CSSM_DL_BASE_DL_ERROR + 39, + CSSMERR_DL_INVALID_RECORD_UID = CSSM_DL_BASE_DL_ERROR + 40, + CSSMERR_DL_INVALID_UNIQUE_INDEX_DATA = CSSM_DL_BASE_DL_ERROR + 41, + CSSMERR_DL_INVALID_MODIFY_MODE = CSSM_DL_BASE_DL_ERROR + 42, + CSSMERR_DL_INVALID_OPEN_PARAMETERS = CSSM_DL_BASE_DL_ERROR + 43, + CSSMERR_DL_RECORD_MODIFIED = CSSM_DL_BASE_DL_ERROR + 44, + CSSMERR_DL_ENDOFDATA = CSSM_DL_BASE_DL_ERROR + 45, + CSSMERR_DL_INVALID_QUERY = CSSM_DL_BASE_DL_ERROR + 46, + CSSMERR_DL_INVALID_VALUE = CSSM_DL_BASE_DL_ERROR + 47, + CSSMERR_DL_MULTIPLE_VALUES_UNSUPPORTED = CSSM_DL_BASE_DL_ERROR + 48, + CSSMERR_DL_STALE_UNIQUE_RECORD = CSSM_DL_BASE_DL_ERROR + 49 +}; + + +#ifdef __cplusplus +} +#endif + +#endif /* _CSSMERR_H_ */ diff --git a/libsecurity_cssm/lib/cssmint.h b/libsecurity_cssm/lib/cssmint.h new file mode 100644 index 00000000..b682653a --- /dev/null +++ b/libsecurity_cssm/lib/cssmint.h @@ -0,0 +1,80 @@ +/* + * 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@ + */ + + +// +// cssmint - cssm combined internal headers +// +#ifndef _H_CSSMINT +#define _H_CSSMINT + +#include +#include +#include +#include +#include + + +// +// Forward types +// +class CssmManager; +class Module; +class Attachment; + + +// +// Typedefs for fixed SPI entries +// +typedef CSSM_RETURN CSSMSPI +CSSM_SPI_ModuleLoadFunction (const CSSM_GUID *CssmGuid, + const CSSM_GUID *ModuleGuid, + CSSM_SPI_ModuleEventHandler CssmNotifyCallback, + void *CssmNotifyCallbackCtx); + +typedef CSSM_RETURN CSSMSPI +CSSM_SPI_ModuleUnloadFunction (const CSSM_GUID *CssmGuid, + const CSSM_GUID *ModuleGuid, + CSSM_SPI_ModuleEventHandler CssmNotifyCallback, + void *CssmNotifyCallbackCtx); + +typedef CSSM_RETURN CSSMSPI +CSSM_SPI_ModuleAttachFunction (const CSSM_GUID *ModuleGuid, + const CSSM_VERSION *Version, + uint32 SubserviceID, + CSSM_SERVICE_TYPE SubServiceType, + CSSM_ATTACH_FLAGS AttachFlags, + CSSM_MODULE_HANDLE ModuleHandle, + CSSM_KEY_HIERARCHY KeyHierarchy, + const CSSM_GUID *CssmGuid, + const CSSM_GUID *ModuleManagerGuid, + const CSSM_GUID *CallerGuid, + const CSSM_UPCALLS *Upcalls, + CSSM_MODULE_FUNCS_PTR *FuncTbl); + +typedef CSSM_RETURN CSSMSPI +CSSM_SPI_ModuleDetachFunction (CSSM_MODULE_HANDLE ModuleHandle); + + + +#endif //_H_CSSMINT diff --git a/libsecurity_cssm/lib/cssmkrapi.h b/libsecurity_cssm/lib/cssmkrapi.h new file mode 100644 index 00000000..a60add52 --- /dev/null +++ b/libsecurity_cssm/lib/cssmkrapi.h @@ -0,0 +1,243 @@ +/* + * Copyright (c) 1999-2001,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@ + * + * cssmkrapi.h -- Application Programmers Interface for Key Recovery Modules + */ + +#ifndef _CSSMKRAPI_H_ +#define _CSSMKRAPI_H_ 1 + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef uint32 CSSM_KRSP_HANDLE; /* Key Recovery Service Provider Handle */ + +typedef struct cssm_kr_name { + uint8 Type; /* namespace type */ + uint8 Length; /* name string length */ + char *Name; /* name string */ +} CSSM_KR_NAME DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef struct cssm_kr_profile { + CSSM_KR_NAME UserName; /* name of the user */ + CSSM_CERTGROUP_PTR UserCertificate; /* public key certificate of the user */ + CSSM_CERTGROUP_PTR KRSCertChain; /* cert chain for the KRSP coordinator */ + uint8 LE_KRANum; /* number of KRA cert chains in the following list */ + CSSM_CERTGROUP_PTR LE_KRACertChainList; /* list of Law enforcement KRA certificate chains */ + uint8 ENT_KRANum; /* number of KRA cert chains in the following list */ + CSSM_CERTGROUP_PTR ENT_KRACertChainList; /* list of Enterprise KRA certificate chains */ + uint8 INDIV_KRANum; /* number of KRA cert chains in the following list */ + CSSM_CERTGROUP_PTR INDIV_KRACertChainList; /* list of Individual KRA certificate chains */ + CSSM_DATA_PTR INDIV_AuthenticationInfo; /* authentication information for individual key recovery */ + uint32 KRSPFlags; /* flag values to be interpreted by KRSP */ + CSSM_DATA_PTR KRSPExtensions; /* reserved for extensions specific to KRSPs */ +} CSSM_KR_PROFILE DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_KR_PROFILE_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef struct cssm_kr_wrappedproductinfo { + CSSM_VERSION StandardVersion; + CSSM_STRING StandardDescription; + CSSM_VERSION ProductVersion; + CSSM_STRING ProductDescription; + CSSM_STRING ProductVendor; + uint32 ProductFlags; +} CSSM_KR_WRAPPEDPRODUCT_INFO DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_KR_WRAPPEDPRODUCT_INFO_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef struct cssm_krsubservice { + uint32 SubServiceId; + char *Description; /* Description of this sub service */ + CSSM_KR_WRAPPEDPRODUCT_INFO WrappedProduct; +} CSSM_KRSUBSERVICE, *CSSM_KRSUBSERVICE_PTR; + +typedef uint32 CSSM_KR_POLICY_TYPE; +#define CSSM_KR_INDIV_POLICY (0x00000001) +#define CSSM_KR_ENT_POLICY (0x00000002) +#define CSSM_KR_LE_MAN_POLICY (0x00000003) +#define CSSM_KR_LE_USE_POLICY (0x00000004) + +typedef uint32 CSSM_KR_POLICY_FLAGS; + +#define CSSM_KR_INDIV (0x00000001) +#define CSSM_KR_ENT (0x00000002) +#define CSSM_KR_LE_MAN (0x00000004) +#define CSSM_KR_LE_USE (0x00000008) +#define CSSM_KR_LE (CSSM_KR_LE_MAN | CSSM_KR_LE_USE) +#define CSSM_KR_OPTIMIZE (0x00000010) +#define CSSM_KR_DROP_WORKFACTOR (0x00000020) + +typedef struct cssm_kr_policy_list_item { + struct kr_policy_list_item *next; + CSSM_ALGORITHMS AlgorithmId; + CSSM_ENCRYPT_MODE Mode; + uint32 MaxKeyLength; + uint32 MaxRounds; + uint8 WorkFactor; + CSSM_KR_POLICY_FLAGS PolicyFlags; + CSSM_CONTEXT_TYPE AlgClass; +} CSSM_KR_POLICY_LIST_ITEM DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_KR_POLICY_LIST_ITEM_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef struct cssm_kr_policy_info { + CSSM_BOOL krbNotAllowed; + uint32 numberOfEntries; + CSSM_KR_POLICY_LIST_ITEM *policyEntry; +} CSSM_KR_POLICY_INFO DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_KR_POLICY_INFO_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + + +/* Key Recovery Module Mangement Operations */ + +CSSM_RETURN CSSMAPI +CSSM_KR_SetEnterpriseRecoveryPolicy (const CSSM_DATA *RecoveryPolicyFileName, + const CSSM_ACCESS_CREDENTIALS *OldPassPhrase, + const CSSM_ACCESS_CREDENTIALS *NewPassPhrase) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + + +/* Key Recovery Context Operations */ + +CSSM_RETURN CSSMAPI +CSSM_KR_CreateRecoveryRegistrationContext (CSSM_KRSP_HANDLE KRSPHandle, + CSSM_CC_HANDLE *NewContext) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +CSSM_RETURN CSSMAPI +CSSM_KR_CreateRecoveryEnablementContext (CSSM_KRSP_HANDLE KRSPHandle, + const CSSM_KR_PROFILE *LocalProfile, + const CSSM_KR_PROFILE *RemoteProfile, + CSSM_CC_HANDLE *NewContext) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +CSSM_RETURN CSSMAPI +CSSM_KR_CreateRecoveryRequestContext (CSSM_KRSP_HANDLE KRSPHandle, + const CSSM_KR_PROFILE *LocalProfile, + CSSM_CC_HANDLE *NewContext) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +CSSM_RETURN CSSMAPI +CSSM_KR_GetPolicyInfo (CSSM_CC_HANDLE CCHandle, + CSSM_KR_POLICY_FLAGS *EncryptionProhibited, + uint32 *WorkFactor) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + + +/* Key Recovery Registration Operations */ + +CSSM_RETURN CSSMAPI +CSSM_KR_RegistrationRequest (CSSM_CC_HANDLE RecoveryRegistrationContext, + const CSSM_DATA *KRInData, + const CSSM_ACCESS_CREDENTIALS *AccessCredentials, + CSSM_KR_POLICY_FLAGS KRFlags, + sint32 *EstimatedTime, + CSSM_HANDLE_PTR ReferenceHandle) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +CSSM_RETURN CSSMAPI +CSSM_KR_RegistrationRetrieve (CSSM_KRSP_HANDLE KRSPHandle, + CSSM_HANDLE ReferenceHandle, + const CSSM_ACCESS_CREDENTIALS *AccessCredentials, + sint32 *EstimatedTime, + CSSM_KR_PROFILE_PTR KRProfile) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + + +/* Key Recovery Enablement Operations */ + +CSSM_RETURN CSSMAPI +CSSM_KR_GenerateRecoveryFields (CSSM_CC_HANDLE KeyRecoveryContext, + CSSM_CC_HANDLE CCHandle, + const CSSM_DATA *KRSPOptions, + CSSM_KR_POLICY_FLAGS KRFlags, + CSSM_DATA_PTR KRFields, + CSSM_CC_HANDLE *NewCCHandle) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +CSSM_RETURN CSSMAPI +CSSM_KR_ProcessRecoveryFields (CSSM_CC_HANDLE KeyRecoveryContext, + CSSM_CC_HANDLE CryptoContext, + const CSSM_DATA *KRSPOptions, + CSSM_KR_POLICY_FLAGS KRFlags, + const CSSM_DATA *KRFields, + CSSM_CC_HANDLE *NewCryptoContext) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + + +/* Key Recovery Request Operations */ + +CSSM_RETURN CSSMAPI +CSSM_KR_RecoveryRequest (CSSM_CC_HANDLE RecoveryRequestContext, + const CSSM_DATA *KRInData, + const CSSM_ACCESS_CREDENTIALS *AccessCredentials, + sint32 *EstimatedTime, + CSSM_HANDLE_PTR ReferenceHandle) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +CSSM_RETURN CSSMAPI +CSSM_KR_RecoveryRetrieve (CSSM_KRSP_HANDLE KRSPHandle, + CSSM_HANDLE ReferenceHandle, + const CSSM_ACCESS_CREDENTIALS *AccessCredentials, + sint32 *EstimatedTime, + CSSM_HANDLE_PTR CacheHandle, + uint32 *NumberOfRecoveredKeys) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +CSSM_RETURN CSSMAPI +CSSM_KR_GetRecoveredObject (CSSM_KRSP_HANDLE KRSPHandle, + CSSM_HANDLE CacheHandle, + uint32 IndexInResults, + CSSM_CSP_HANDLE CSPHandle, + const CSSM_RESOURCE_CONTROL_CONTEXT *CredAndAclEntry, + uint32 Flags, + CSSM_KEY_PTR RecoveredKey, + CSSM_DATA_PTR OtherInfo) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +CSSM_RETURN CSSMAPI +CSSM_KR_RecoveryRequestAbort (CSSM_KRSP_HANDLE KRSPHandle, + CSSM_HANDLE CacheHandle) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +CSSM_RETURN CSSMAPI +CSSM_KR_QueryPolicyInfo (CSSM_KRSP_HANDLE KRSPHandle, + CSSM_ALGORITHMS AlgorithmID, + CSSM_ENCRYPT_MODE Mode, + CSSM_CONTEXT_TYPE Class, + CSSM_KR_POLICY_INFO_PTR *PolicyInfoData) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + + +/* Extensibility Functions */ + +CSSM_RETURN CSSMAPI +CSSM_KR_PassThrough (CSSM_KRSP_HANDLE KRSPHandle, + CSSM_CC_HANDLE KeyRecoveryContext, + CSSM_CC_HANDLE CryptoContext, + uint32 PassThroughId, + const void *InputParams, + void **OutputParams) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +#ifdef __cplusplus +} +#endif + +#endif /* _CSSMKRAPI_H_ */ diff --git a/libsecurity_cssm/lib/cssmkrspi.h b/libsecurity_cssm/lib/cssmkrspi.h new file mode 100644 index 00000000..8e5bf5c8 --- /dev/null +++ b/libsecurity_cssm/lib/cssmkrspi.h @@ -0,0 +1,111 @@ +/* + * Copyright (c) 1999-2001,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@ + * + * cssmkrspi.h -- Service Provider Interface for Key Recovery Modules + */ + +#ifndef _CSSMKRSPI_H_ +#define _CSSMKRSPI_H_ 1 + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Data types for Key Recovery SPI */ + +typedef struct cssm_spi_kr_funcs { + CSSM_RETURN (CSSMKRI *RegistrationRequest) + (CSSM_KRSP_HANDLE KRSPHandle, + CSSM_CC_HANDLE KRRegistrationContextHandle, + const CSSM_CONTEXT *KRRegistrationContext, + const CSSM_DATA *KRInData, + const CSSM_ACCESS_CREDENTIALS *AccessCredentials, + CSSM_KR_POLICY_FLAGS KRFlags, + sint32 *EstimatedTime, + CSSM_HANDLE_PTR ReferenceHandle); + CSSM_RETURN (CSSMKRI *RegistrationRetrieve) + (CSSM_KRSP_HANDLE KRSPHandle, + CSSM_HANDLE ReferenceHandle, + sint32 *EstimatedTime, + CSSM_KR_PROFILE_PTR KRProfile); + CSSM_RETURN (CSSMKRI *GenerateRecoveryFields) + (CSSM_KRSP_HANDLE KRSPHandle, + CSSM_CC_HANDLE KREnablementContextHandle, + const CSSM_CONTEXT *KREnablementContext, + CSSM_CC_HANDLE CryptoContextHandle, + const CSSM_CONTEXT *CryptoContext, + const CSSM_DATA *KRSPOptions, + CSSM_KR_POLICY_FLAGS KRFlags, + CSSM_DATA_PTR KRFields); + CSSM_RETURN (CSSMKRI *ProcessRecoveryFields) + (CSSM_KRSP_HANDLE KRSPHandle, + CSSM_CC_HANDLE KREnablementContextHandle, + const CSSM_CONTEXT *KREnablementContext, + CSSM_CC_HANDLE CryptoContextHandle, + const CSSM_CONTEXT *CryptoContext, + const CSSM_DATA *KRSPOptions, + CSSM_KR_POLICY_FLAGS KRFlags, + const CSSM_DATA *KRFields); + CSSM_RETURN (CSSMKRI *RecoveryRequest) + (CSSM_KRSP_HANDLE KRSPHandle, + CSSM_CC_HANDLE KRRequestContextHandle, + const CSSM_CONTEXT *KRRequestContext, + const CSSM_DATA *KRInData, + const CSSM_ACCESS_CREDENTIALS *AccessCredentials, + sint32 *EstimatedTime, + CSSM_HANDLE_PTR ReferenceHandle); + CSSM_RETURN (CSSMKRI *RecoveryRetrieve) + (CSSM_KRSP_HANDLE KRSPHandle, + CSSM_HANDLE ReferenceHandle, + sint32 *EstimatedTime, + CSSM_HANDLE_PTR CacheHandle, + uint32 *NumberOfRecoveredKeys); + CSSM_RETURN (CSSMKRI *GetRecoveredObject) + (CSSM_KRSP_HANDLE KRSPHandle, + CSSM_HANDLE CacheHandle, + uint32 IndexInResults, + CSSM_CSP_HANDLE CSPHandle, + const CSSM_RESOURCE_CONTROL_CONTEXT *CredAndAclEntry, + uint32 Flags, + CSSM_KEY_PTR RecoveredKey, + CSSM_DATA_PTR OtherInfo); + CSSM_RETURN (CSSMKRI *RecoveryRequestAbort) + (CSSM_KRSP_HANDLE KRSPHandle, + CSSM_HANDLE ResultsHandle); + CSSM_RETURN (CSSMKRI *PassThrough) + (CSSM_KRSP_HANDLE KRSPHandle, + CSSM_CC_HANDLE KeyRecoveryContextHandle, + const CSSM_CONTEXT *KeyRecoveryContext, + CSSM_CC_HANDLE CryptoContextHandle, + const CSSM_CONTEXT *CryptoContext, + uint32 PassThroughId, + const void *InputParams, + void **OutputParams); +} CSSM_SPI_KR_FUNCS DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_SPI_KR_FUNCS_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +#ifdef __cplusplus +} +#endif + +#endif /* _CSSMKRSPI_H_ */ diff --git a/libsecurity_cssm/lib/cssmmds.cpp b/libsecurity_cssm/lib/cssmmds.cpp new file mode 100644 index 00000000..2b3c2c5d --- /dev/null +++ b/libsecurity_cssm/lib/cssmmds.cpp @@ -0,0 +1,46 @@ +/* + * 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@ + */ + + +// +// cssmmds - MDS interface for CSSM & friends +// +#include "cssmmds.h" +#include +#include + + +// +// Construct a MdsComponent. +// This will perform an MDS lookup in the Common table +// +MdsComponent::MdsComponent(const Guid &guid) : mMyGuid(guid) +{ + using namespace MDSClient; + Table common(mds()); // MDS "CDSA Common" table + mCommon = common.fetch(Attribute("ModuleID") == mMyGuid, CSSMERR_CSSM_MDS_ERROR); +} + +MdsComponent::~MdsComponent() +{ +} diff --git a/libsecurity_cssm/lib/cssmmds.h b/libsecurity_cssm/lib/cssmmds.h new file mode 100644 index 00000000..0286fa1c --- /dev/null +++ b/libsecurity_cssm/lib/cssmmds.h @@ -0,0 +1,57 @@ +/* + * 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@ + */ + + +// +// cssmmds - MDS interface for CSSM & friends +// +#ifndef _H_CSSMMDS +#define _H_CSSMMDS + +#include "cssmint.h" +#include +#include +#include + + +class MdsComponent { +public: + MdsComponent(const Guid &guid); + virtual ~MdsComponent(); + + const Guid &myGuid() const { return mMyGuid; } + + CSSM_SERVICE_MASK services() const { return mCommon->serviceMask(); } + bool supportsService(CSSM_SERVICE_TYPE t) const { return t & services(); } + bool isThreadSafe() const { return !mCommon->singleThreaded(); } + string path() const { return mCommon->path(); } + string name() const { return mCommon->moduleName(); } + string description() const { return mCommon->description(); } + +private: + const Guid mMyGuid; // GUID of the component + RefPointer mCommon; // MDS common record for this module +}; + + +#endif //_H_CSSMMDS diff --git a/libsecurity_cssm/lib/cssmspi.h b/libsecurity_cssm/lib/cssmspi.h new file mode 100644 index 00000000..2a911b01 --- /dev/null +++ b/libsecurity_cssm/lib/cssmspi.h @@ -0,0 +1,132 @@ +/* + * Copyright (c) 1999-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@ + * + * cssmspi.h -- Service Provider Interface for CSSM Modules + */ + +#ifndef _CSSMSPI_H_ +#define _CSSMSPI_H_ 1 + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef CSSM_RETURN (CSSMAPI *CSSM_SPI_ModuleEventHandler) + (const CSSM_GUID *ModuleGuid, + void *CssmNotifyCallbackCtx, + uint32 SubserviceId, + CSSM_SERVICE_TYPE ServiceType, + CSSM_MODULE_EVENT EventType); + +typedef uint32 CSSM_CONTEXT_EVENT; +enum { + CSSM_CONTEXT_EVENT_CREATE = 1, + CSSM_CONTEXT_EVENT_DELETE = 2, + CSSM_CONTEXT_EVENT_UPDATE = 3 +}; + +typedef struct cssm_module_funcs { + CSSM_SERVICE_TYPE ServiceType; + uint32 NumberOfServiceFuncs; + const CSSM_PROC_ADDR *ServiceFuncs; +} CSSM_MODULE_FUNCS DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_MODULE_FUNCS_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef void *(CSSMAPI *CSSM_UPCALLS_MALLOC) + (CSSM_HANDLE AddInHandle, + size_t size) DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef void (CSSMAPI *CSSM_UPCALLS_FREE) + (CSSM_HANDLE AddInHandle, + void *memblock) DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef void *(CSSMAPI *CSSM_UPCALLS_REALLOC) + (CSSM_HANDLE AddInHandle, + void *memblock, + size_t size) DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef void *(CSSMAPI *CSSM_UPCALLS_CALLOC) + (CSSM_HANDLE AddInHandle, + size_t num, + size_t size) DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef struct cssm_upcalls { + CSSM_UPCALLS_MALLOC malloc_func; + CSSM_UPCALLS_FREE free_func; + CSSM_UPCALLS_REALLOC realloc_func; + CSSM_UPCALLS_CALLOC calloc_func; + CSSM_RETURN (CSSMAPI *CcToHandle_func) + (CSSM_CC_HANDLE Cc, + CSSM_MODULE_HANDLE_PTR ModuleHandle); + CSSM_RETURN (CSSMAPI *GetModuleInfo_func) + (CSSM_MODULE_HANDLE Module, + CSSM_GUID_PTR Guid, + CSSM_VERSION_PTR Version, + uint32 *SubServiceId, + CSSM_SERVICE_TYPE *SubServiceType, + CSSM_ATTACH_FLAGS *AttachFlags, + CSSM_KEY_HIERARCHY *KeyHierarchy, + CSSM_API_MEMORY_FUNCS_PTR AttachedMemFuncs, + CSSM_FUNC_NAME_ADDR_PTR FunctionTable, + uint32 NumFunctions); +} CSSM_UPCALLS DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_UPCALLS_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +CSSM_RETURN CSSMSPI +CSSM_SPI_ModuleLoad (const CSSM_GUID *CssmGuid, + const CSSM_GUID *ModuleGuid, + CSSM_SPI_ModuleEventHandler CssmNotifyCallback, + void *CssmNotifyCallbackCtx) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +CSSM_RETURN CSSMSPI +CSSM_SPI_ModuleUnload (const CSSM_GUID *CssmGuid, + const CSSM_GUID *ModuleGuid, + CSSM_SPI_ModuleEventHandler CssmNotifyCallback, + void *CssmNotifyCallbackCtx) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +CSSM_RETURN CSSMSPI +CSSM_SPI_ModuleAttach (const CSSM_GUID *ModuleGuid, + const CSSM_VERSION *Version, + uint32 SubserviceID, + CSSM_SERVICE_TYPE SubServiceType, + CSSM_ATTACH_FLAGS AttachFlags, + CSSM_MODULE_HANDLE ModuleHandle, + CSSM_KEY_HIERARCHY KeyHierarchy, + const CSSM_GUID *CssmGuid, + const CSSM_GUID *ModuleManagerGuid, + const CSSM_GUID *CallerGuid, + const CSSM_UPCALLS *Upcalls, + CSSM_MODULE_FUNCS_PTR *FuncTbl) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +CSSM_RETURN CSSMSPI +CSSM_SPI_ModuleDetach (CSSM_MODULE_HANDLE ModuleHandle) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + + +#ifdef __cplusplus +} +#endif + +#endif /* _CSSMSPI_H_ */ diff --git a/libsecurity_cssm/lib/cssmtpi.h b/libsecurity_cssm/lib/cssmtpi.h new file mode 100644 index 00000000..81be4eea --- /dev/null +++ b/libsecurity_cssm/lib/cssmtpi.h @@ -0,0 +1,202 @@ +/* + * Copyright (c) 1999-2001,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@ + * + * cssmtpi.h -- Service Provider Interface for Trust Policy Modules + */ + +#ifndef _CSSMTPI_H_ +#define _CSSMTPI_H_ 1 + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct cssm_spi_tp_funcs { + CSSM_RETURN (CSSMTPI *SubmitCredRequest) + (CSSM_TP_HANDLE TPHandle, + const CSSM_TP_AUTHORITY_ID *PreferredAuthority, + CSSM_TP_AUTHORITY_REQUEST_TYPE RequestType, + const CSSM_TP_REQUEST_SET *RequestInput, + const CSSM_TP_CALLERAUTH_CONTEXT *CallerAuthContext, + sint32 *EstimatedTime, + CSSM_DATA_PTR ReferenceIdentifier); + CSSM_RETURN (CSSMTPI *RetrieveCredResult) + (CSSM_TP_HANDLE TPHandle, + const CSSM_DATA *ReferenceIdentifier, + const CSSM_TP_CALLERAUTH_CONTEXT *CallerAuthCredentials, + sint32 *EstimatedTime, + CSSM_BOOL *ConfirmationRequired, + CSSM_TP_RESULT_SET_PTR *RetrieveOutput); + CSSM_RETURN (CSSMTPI *ConfirmCredResult) + (CSSM_TP_HANDLE TPHandle, + const CSSM_DATA *ReferenceIdentifier, + const CSSM_TP_CALLERAUTH_CONTEXT *CallerAuthCredentials, + const CSSM_TP_CONFIRM_RESPONSE *Responses, + const CSSM_TP_AUTHORITY_ID *PreferredAuthority); + CSSM_RETURN (CSSMTPI *ReceiveConfirmation) + (CSSM_TP_HANDLE TPHandle, + const CSSM_DATA *ReferenceIdentifier, + CSSM_TP_CONFIRM_RESPONSE_PTR *Responses, + sint32 *ElapsedTime); + CSSM_RETURN (CSSMTPI *CertReclaimKey) + (CSSM_TP_HANDLE TPHandle, + const CSSM_CERTGROUP *CertGroup, + uint32 CertIndex, + CSSM_LONG_HANDLE KeyCacheHandle, + CSSM_CSP_HANDLE CSPHandle, + const CSSM_RESOURCE_CONTROL_CONTEXT *CredAndAclEntry); + CSSM_RETURN (CSSMTPI *CertReclaimAbort) + (CSSM_TP_HANDLE TPHandle, + CSSM_LONG_HANDLE KeyCacheHandle); + CSSM_RETURN (CSSMTPI *FormRequest) + (CSSM_TP_HANDLE TPHandle, + const CSSM_TP_AUTHORITY_ID *PreferredAuthority, + CSSM_TP_FORM_TYPE FormType, + CSSM_DATA_PTR BlankForm); + CSSM_RETURN (CSSMTPI *FormSubmit) + (CSSM_TP_HANDLE TPHandle, + CSSM_TP_FORM_TYPE FormType, + const CSSM_DATA *Form, + const CSSM_TP_AUTHORITY_ID *ClearanceAuthority, + const CSSM_TP_AUTHORITY_ID *RepresentedAuthority, + CSSM_ACCESS_CREDENTIALS_PTR Credentials); + CSSM_RETURN (CSSMTPI *CertGroupVerify) + (CSSM_TP_HANDLE TPHandle, + CSSM_CL_HANDLE CLHandle, + CSSM_CSP_HANDLE CSPHandle, + const CSSM_CERTGROUP *CertGroupToBeVerified, + const CSSM_TP_VERIFY_CONTEXT *VerifyContext, + CSSM_TP_VERIFY_CONTEXT_RESULT_PTR VerifyContextResult); + CSSM_RETURN (CSSMTPI *CertCreateTemplate) + (CSSM_TP_HANDLE TPHandle, + CSSM_CL_HANDLE CLHandle, + uint32 NumberOfFields, + const CSSM_FIELD *CertFields, + CSSM_DATA_PTR CertTemplate); + CSSM_RETURN (CSSMTPI *CertGetAllTemplateFields) + (CSSM_TP_HANDLE TPHandle, + CSSM_CL_HANDLE CLHandle, + const CSSM_DATA *CertTemplate, + uint32 *NumberOfFields, + CSSM_FIELD_PTR *CertFields); + CSSM_RETURN (CSSMTPI *CertSign) + (CSSM_TP_HANDLE TPHandle, + CSSM_CL_HANDLE CLHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_DATA *CertTemplateToBeSigned, + const CSSM_CERTGROUP *SignerCertGroup, + const CSSM_TP_VERIFY_CONTEXT *SignerVerifyContext, + CSSM_TP_VERIFY_CONTEXT_RESULT_PTR SignerVerifyResult, + CSSM_DATA_PTR SignedCert); + CSSM_RETURN (CSSMTPI *CrlVerify) + (CSSM_TP_HANDLE TPHandle, + CSSM_CL_HANDLE CLHandle, + CSSM_CSP_HANDLE CSPHandle, + const CSSM_ENCODED_CRL *CrlToBeVerified, + const CSSM_CERTGROUP *SignerCertGroup, + const CSSM_TP_VERIFY_CONTEXT *VerifyContext, + CSSM_TP_VERIFY_CONTEXT_RESULT_PTR RevokerVerifyResult); + CSSM_RETURN (CSSMTPI *CrlCreateTemplate) + (CSSM_TP_HANDLE TPHandle, + CSSM_CL_HANDLE CLHandle, + uint32 NumberOfFields, + const CSSM_FIELD *CrlFields, + CSSM_DATA_PTR NewCrlTemplate); + CSSM_RETURN (CSSMTPI *CertRevoke) + (CSSM_TP_HANDLE TPHandle, + CSSM_CL_HANDLE CLHandle, + CSSM_CSP_HANDLE CSPHandle, + const CSSM_DATA *OldCrlTemplate, + const CSSM_CERTGROUP *CertGroupToBeRevoked, + const CSSM_CERTGROUP *RevokerCertGroup, + const CSSM_TP_VERIFY_CONTEXT *RevokerVerifyContext, + CSSM_TP_VERIFY_CONTEXT_RESULT_PTR RevokerVerifyResult, + CSSM_TP_CERTCHANGE_REASON Reason, + CSSM_DATA_PTR NewCrlTemplate); + CSSM_RETURN (CSSMTPI *CertRemoveFromCrlTemplate) + (CSSM_TP_HANDLE TPHandle, + CSSM_CL_HANDLE CLHandle, + CSSM_CSP_HANDLE CSPHandle, + const CSSM_DATA *OldCrlTemplate, + const CSSM_CERTGROUP *CertGroupToBeRemoved, + const CSSM_CERTGROUP *RevokerCertGroup, + const CSSM_TP_VERIFY_CONTEXT *RevokerVerifyContext, + CSSM_TP_VERIFY_CONTEXT_RESULT_PTR RevokerVerifyResult, + CSSM_DATA_PTR NewCrlTemplate); + CSSM_RETURN (CSSMTPI *CrlSign) + (CSSM_TP_HANDLE TPHandle, + CSSM_CL_HANDLE CLHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_ENCODED_CRL *CrlToBeSigned, + const CSSM_CERTGROUP *SignerCertGroup, + const CSSM_TP_VERIFY_CONTEXT *SignerVerifyContext, + CSSM_TP_VERIFY_CONTEXT_RESULT_PTR SignerVerifyResult, + CSSM_DATA_PTR SignedCrl); + CSSM_RETURN (CSSMTPI *ApplyCrlToDb) + (CSSM_TP_HANDLE TPHandle, + CSSM_CL_HANDLE CLHandle, + CSSM_CSP_HANDLE CSPHandle, + const CSSM_ENCODED_CRL *CrlToBeApplied, + const CSSM_CERTGROUP *SignerCertGroup, + const CSSM_TP_VERIFY_CONTEXT *ApplyCrlVerifyContext, + CSSM_TP_VERIFY_CONTEXT_RESULT_PTR ApplyCrlVerifyResult); + CSSM_RETURN (CSSMTPI *CertGroupConstruct) + (CSSM_TP_HANDLE TPHandle, + CSSM_CL_HANDLE CLHandle, + CSSM_CSP_HANDLE CSPHandle, + const CSSM_DL_DB_LIST *DBList, + const void *ConstructParams, + const CSSM_CERTGROUP *CertGroupFrag, + CSSM_CERTGROUP_PTR *CertGroup); + CSSM_RETURN (CSSMTPI *CertGroupPrune) + (CSSM_TP_HANDLE TPHandle, + CSSM_CL_HANDLE CLHandle, + const CSSM_DL_DB_LIST *DBList, + const CSSM_CERTGROUP *OrderedCertGroup, + CSSM_CERTGROUP_PTR *PrunedCertGroup); + CSSM_RETURN (CSSMTPI *CertGroupToTupleGroup) + (CSSM_TP_HANDLE TPHandle, + CSSM_CL_HANDLE CLHandle, + const CSSM_CERTGROUP *CertGroup, + CSSM_TUPLEGROUP_PTR *TupleGroup); + CSSM_RETURN (CSSMTPI *TupleGroupToCertGroup) + (CSSM_TP_HANDLE TPHandle, + CSSM_CL_HANDLE CLHandle, + const CSSM_TUPLEGROUP *TupleGroup, + CSSM_CERTGROUP_PTR *CertTemplates); + CSSM_RETURN (CSSMTPI *PassThrough) + (CSSM_TP_HANDLE TPHandle, + CSSM_CL_HANDLE CLHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_DL_DB_LIST *DBList, + uint32 PassThroughId, + const void *InputParams, + void **OutputParams); +} CSSM_SPI_TP_FUNCS DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_SPI_TP_FUNCS_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +#ifdef __cplusplus +} +#endif + +#endif /* _CSSMTPI_H_ */ diff --git a/libsecurity_cssm/lib/cssmtype.h b/libsecurity_cssm/lib/cssmtype.h new file mode 100644 index 00000000..aaf17466 --- /dev/null +++ b/libsecurity_cssm/lib/cssmtype.h @@ -0,0 +1,2079 @@ +/* + * Copyright (c) 1999-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@ + * + * cssmtype.h -- Common Security Services Manager Common Data Types + */ + +#ifndef _CSSMTYPE_H_ +#define _CSSMTYPE_H_ 1 + +#include + +/* ========================================================================== + W A R N I N G : CDSA has been deprecated starting with 10.7. While the + APIs will continue to work, developers should update their code to use + the APIs that are suggested and NOT use the CDSA APIs + ========================================================================== */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Handle types. */ + +typedef CSSM_INTPTR CSSM_HANDLE, *CSSM_HANDLE_PTR; + +typedef uint64 CSSM_LONG_HANDLE, *CSSM_LONG_HANDLE_PTR; + +typedef CSSM_HANDLE CSSM_MODULE_HANDLE, *CSSM_MODULE_HANDLE_PTR; + +typedef CSSM_LONG_HANDLE CSSM_CC_HANDLE; /* Cryptographic Context Handle */ + +typedef CSSM_MODULE_HANDLE CSSM_CSP_HANDLE; /* Cryptographic Service Provider Handle */ + +typedef CSSM_MODULE_HANDLE CSSM_TP_HANDLE; /* Trust Policy Handle */ + +typedef CSSM_MODULE_HANDLE CSSM_AC_HANDLE; /* Authorization Computation Handle */ + +typedef CSSM_MODULE_HANDLE CSSM_CL_HANDLE; /* Certificate Library Handle */ + +typedef CSSM_MODULE_HANDLE CSSM_DL_HANDLE; /* Data Storage Library Handle */ + +typedef CSSM_MODULE_HANDLE CSSM_DB_HANDLE; /* Data Storage Database Handle */ + + +/* invalid or NULL value for any CSSM_HANDLE type */ +enum { + CSSM_INVALID_HANDLE = 0 +}; + + +/* Data Types for Core Services */ + +typedef sint32 CSSM_BOOL; +enum { + CSSM_FALSE = 0, + CSSM_TRUE = !CSSM_FALSE +}; + +/* The standard declares this as uint32 but we changed it to sint32 to match OSStatus. */ +typedef sint32 CSSM_RETURN; +enum { + CSSM_OK = 0 +}; + +enum { + CSSM_MODULE_STRING_SIZE = 64 +}; +typedef char CSSM_STRING [CSSM_MODULE_STRING_SIZE + 4]; + +typedef struct cssm_data { + CSSM_SIZE Length; /* in bytes */ + uint8 *Data; +} CSSM_DATA DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_DATA_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef struct cssm_guid { + uint32 Data1; + uint16 Data2; + uint16 Data3; + uint8 Data4[8]; +} CSSM_GUID DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_GUID_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef uint32 CSSM_BITMASK; +typedef CSSM_BITMASK CSSM_KEY_HIERARCHY; +enum { + CSSM_KEY_HIERARCHY_NONE = 0, + CSSM_KEY_HIERARCHY_INTEG = 1, + CSSM_KEY_HIERARCHY_EXPORT = 2 +}; + +typedef CSSM_BITMASK CSSM_PVC_MODE; +enum { + CSSM_PVC_NONE = 0, + CSSM_PVC_APP = 1, + CSSM_PVC_SP = 2 +}; + +typedef uint32 CSSM_PRIVILEGE_SCOPE; +enum { + CSSM_PRIVILEGE_SCOPE_NONE = 0, + CSSM_PRIVILEGE_SCOPE_PROCESS = 1, + CSSM_PRIVILEGE_SCOPE_THREAD = 2 +}; + +typedef struct cssm_version { + uint32 Major; + uint32 Minor; +} CSSM_VERSION DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_VERSION_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef uint32 CSSM_SERVICE_MASK; +enum { + CSSM_SERVICE_CSSM = 0x1, + CSSM_SERVICE_CSP = 0x2, + CSSM_SERVICE_DL = 0x4, + CSSM_SERVICE_CL = 0x8, + CSSM_SERVICE_TP = 0x10, + CSSM_SERVICE_AC = 0x20, + CSSM_SERVICE_KR = 0x40 +}; + +typedef CSSM_SERVICE_MASK CSSM_SERVICE_TYPE; + +typedef struct cssm_subservice_uid { + CSSM_GUID Guid; + CSSM_VERSION Version; + uint32 SubserviceId; + CSSM_SERVICE_TYPE SubserviceType; +} CSSM_SUBSERVICE_UID DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_SUBSERVICE_UID_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef uint32 CSSM_MODULE_EVENT, *CSSM_MODULE_EVENT_PTR; +enum { + CSSM_NOTIFY_INSERT = 1, + CSSM_NOTIFY_REMOVE = 2, + CSSM_NOTIFY_FAULT = 3 +}; + +typedef CSSM_RETURN (CSSMAPI *CSSM_API_ModuleEventHandler) + (const CSSM_GUID *ModuleGuid, + void* AppNotifyCallbackCtx, + uint32 SubserviceId, + CSSM_SERVICE_TYPE ServiceType, + CSSM_MODULE_EVENT EventType); + +typedef uint32 CSSM_ATTACH_FLAGS; +enum { + CSSM_ATTACH_READ_ONLY = 0x00000001 +}; + +/* Non-export privilege range: (0x00000000 - 0x7FFFFFFF) */ +/* Vendor specific range: (0x80000000 - 0xFFFFFFFF) */ +typedef uint64 CSSM_PRIVILEGE; +typedef CSSM_PRIVILEGE CSSM_USEE_TAG; +enum { + CSSM_USEE_LAST = 0xFF, + CSSM_USEE_NONE = 0, + CSSM_USEE_DOMESTIC = 1, + CSSM_USEE_FINANCIAL = 2, + CSSM_USEE_KRLE = 3, + CSSM_USEE_KRENT = 4, + CSSM_USEE_SSL = 5, + CSSM_USEE_AUTHENTICATION = 6, + CSSM_USEE_KEYEXCH = 7, + CSSM_USEE_MEDICAL = 8, + CSSM_USEE_INSURANCE = 9, + CSSM_USEE_WEAK = 10 +}; + +typedef uint32 CSSM_NET_ADDRESS_TYPE; +enum { + CSSM_ADDR_NONE = 0, + CSSM_ADDR_CUSTOM = 1, + CSSM_ADDR_URL = 2, /* char* */ + CSSM_ADDR_SOCKADDR = 3, + CSSM_ADDR_NAME = 4 /* char* - qualified by access method */ +}; + +typedef struct cssm_net_address { + CSSM_NET_ADDRESS_TYPE AddressType; + CSSM_DATA Address; +} CSSM_NET_ADDRESS DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_NET_ADDRESS_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef uint32 CSSM_NET_PROTOCOL; +enum { + CSSM_NET_PROTO_NONE = 0, /* local */ + CSSM_NET_PROTO_CUSTOM = 1, /* proprietary implementation */ + CSSM_NET_PROTO_UNSPECIFIED = 2, /* implementation default */ + CSSM_NET_PROTO_LDAP = 3, /* light weight directory access protocol */ + CSSM_NET_PROTO_LDAPS = 4, /* ldap/ssl where SSL initiates the connection */ + CSSM_NET_PROTO_LDAPNS = 5, /* ldap where ldap negotiates an SSL session */ + CSSM_NET_PROTO_X500DAP = 6, /* x.500 Directory access protocol */ + CSSM_NET_PROTO_FTP = 7, /* ftp for cert/crl fetch */ + CSSM_NET_PROTO_FTPS = 8, /* ftp/ssl/tls where SSL/TLS initiates the connection */ + CSSM_NET_PROTO_OCSP = 9, /* online certificate status protocol */ + CSSM_NET_PROTO_CMP = 10, /* the cert request protocol in PKIX3 */ + CSSM_NET_PROTO_CMPS = 11 /* The ssl/tls derivative of CMP */ +}; + +typedef CSSM_RETURN (CSSMAPI *CSSM_CALLBACK) + (CSSM_DATA_PTR OutData, void *CallerCtx); + +typedef struct cssm_crypto_data { + CSSM_DATA Param; + CSSM_CALLBACK Callback; + void *CallerCtx; +} CSSM_CRYPTO_DATA DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_CRYPTO_DATA_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef sint32 CSSM_WORDID_TYPE; +enum { + CSSM_WORDID__UNK_ = -1, /* not in dictionary */ + CSSM_WORDID__NLU_ = 0, /* not yet looked up */ + CSSM_WORDID__STAR_ = 1, + CSSM_WORDID_A = 2, + CSSM_WORDID_ACL = 3, + CSSM_WORDID_ALPHA = 4, + CSSM_WORDID_B = 5, + CSSM_WORDID_BER = 6, + CSSM_WORDID_BINARY = 7, + CSSM_WORDID_BIOMETRIC = 8, + CSSM_WORDID_C = 9, + CSSM_WORDID_CANCELED = 10, + CSSM_WORDID_CERT = 11, + CSSM_WORDID_COMMENT = 12, + CSSM_WORDID_CRL = 13, + CSSM_WORDID_CUSTOM = 14, + CSSM_WORDID_D = 15, + CSSM_WORDID_DATE = 16, + CSSM_WORDID_DB_DELETE = 17, + CSSM_WORDID_DB_EXEC_STORED_QUERY = 18, + CSSM_WORDID_DB_INSERT = 19, + CSSM_WORDID_DB_MODIFY = 20, + CSSM_WORDID_DB_READ = 21, + CSSM_WORDID_DBS_CREATE = 22, + CSSM_WORDID_DBS_DELETE = 23, + CSSM_WORDID_DECRYPT = 24, + CSSM_WORDID_DELETE = 25, + CSSM_WORDID_DELTA_CRL = 26, + CSSM_WORDID_DER = 27, + CSSM_WORDID_DERIVE = 28, + CSSM_WORDID_DISPLAY = 29, + CSSM_WORDID_DO = 30, + CSSM_WORDID_DSA = 31, + CSSM_WORDID_DSA_SHA1 = 32, + CSSM_WORDID_E = 33, + CSSM_WORDID_ELGAMAL = 34, + CSSM_WORDID_ENCRYPT = 35, + CSSM_WORDID_ENTRY = 36, + CSSM_WORDID_EXPORT_CLEAR = 37, + CSSM_WORDID_EXPORT_WRAPPED = 38, + CSSM_WORDID_G = 39, + CSSM_WORDID_GE = 40, + CSSM_WORDID_GENKEY = 41, + CSSM_WORDID_HASH = 42, + CSSM_WORDID_HASHED_PASSWORD = 43, + CSSM_WORDID_HASHED_SUBJECT = 44, + CSSM_WORDID_HAVAL = 45, + CSSM_WORDID_IBCHASH = 46, + CSSM_WORDID_IMPORT_CLEAR = 47, + CSSM_WORDID_IMPORT_WRAPPED = 48, + CSSM_WORDID_INTEL = 49, + CSSM_WORDID_ISSUER = 50, + CSSM_WORDID_ISSUER_INFO = 51, + CSSM_WORDID_K_OF_N = 52, + CSSM_WORDID_KEA = 53, + CSSM_WORDID_KEYHOLDER = 54, + CSSM_WORDID_L = 55, + CSSM_WORDID_LE = 56, + CSSM_WORDID_LOGIN = 57, + CSSM_WORDID_LOGIN_NAME = 58, + CSSM_WORDID_MAC = 59, + CSSM_WORDID_MD2 = 60, + CSSM_WORDID_MD2WITHRSA = 61, + CSSM_WORDID_MD4 = 62, + CSSM_WORDID_MD5 = 63, + CSSM_WORDID_MD5WITHRSA = 64, + CSSM_WORDID_N = 65, + CSSM_WORDID_NAME = 66, + CSSM_WORDID_NDR = 67, + CSSM_WORDID_NHASH = 68, + CSSM_WORDID_NOT_AFTER = 69, + CSSM_WORDID_NOT_BEFORE = 70, + CSSM_WORDID_NULL = 71, + CSSM_WORDID_NUMERIC = 72, + CSSM_WORDID_OBJECT_HASH = 73, + CSSM_WORDID_ONE_TIME = 74, + CSSM_WORDID_ONLINE = 75, + CSSM_WORDID_OWNER = 76, + CSSM_WORDID_P = 77, + CSSM_WORDID_PAM_NAME = 78, + CSSM_WORDID_PASSWORD = 79, + CSSM_WORDID_PGP = 80, + CSSM_WORDID_PREFIX = 81, + CSSM_WORDID_PRIVATE_KEY = 82, + CSSM_WORDID_PROMPTED_BIOMETRIC = 83, + CSSM_WORDID_PROMPTED_PASSWORD = 84, + CSSM_WORDID_PROPAGATE = 85, + CSSM_WORDID_PROTECTED_BIOMETRIC = 86, + CSSM_WORDID_PROTECTED_PASSWORD = 87, + CSSM_WORDID_PROTECTED_PIN = 88, + CSSM_WORDID_PUBLIC_KEY = 89, + CSSM_WORDID_PUBLIC_KEY_FROM_CERT = 90, + CSSM_WORDID_Q = 91, + CSSM_WORDID_RANGE = 92, + CSSM_WORDID_REVAL = 93, + CSSM_WORDID_RIPEMAC = 94, + CSSM_WORDID_RIPEMD = 95, + CSSM_WORDID_RIPEMD160 = 96, + CSSM_WORDID_RSA = 97, + CSSM_WORDID_RSA_ISO9796 = 98, + CSSM_WORDID_RSA_PKCS = 99, + CSSM_WORDID_RSA_PKCS_MD5 = 100, + CSSM_WORDID_RSA_PKCS_SHA1 = 101, + CSSM_WORDID_RSA_PKCS1 = 102, + CSSM_WORDID_RSA_PKCS1_MD5 = 103, + CSSM_WORDID_RSA_PKCS1_SHA1 = 104, + CSSM_WORDID_RSA_PKCS1_SIG = 105, + CSSM_WORDID_RSA_RAW = 106, + CSSM_WORDID_SDSIV1 = 107, + CSSM_WORDID_SEQUENCE = 108, + CSSM_WORDID_SET = 109, + CSSM_WORDID_SEXPR = 110, + CSSM_WORDID_SHA1 = 111, + CSSM_WORDID_SHA1WITHDSA = 112, + CSSM_WORDID_SHA1WITHECDSA = 113, + CSSM_WORDID_SHA1WITHRSA = 114, + CSSM_WORDID_SIGN = 115, + CSSM_WORDID_SIGNATURE = 116, + CSSM_WORDID_SIGNED_NONCE = 117, + CSSM_WORDID_SIGNED_SECRET = 118, + CSSM_WORDID_SPKI = 119, + CSSM_WORDID_SUBJECT = 120, + CSSM_WORDID_SUBJECT_INFO = 121, + CSSM_WORDID_TAG = 122, + CSSM_WORDID_THRESHOLD = 123, + CSSM_WORDID_TIME = 124, + CSSM_WORDID_URI = 125, + CSSM_WORDID_VERSION = 126, + CSSM_WORDID_X509_ATTRIBUTE = 127, + CSSM_WORDID_X509V1 = 128, + CSSM_WORDID_X509V2 = 129, + CSSM_WORDID_X509V3 = 130, + CSSM_WORDID_X9_ATTRIBUTE = 131, + CSSM_WORDID_VENDOR_START = 0x00010000, + CSSM_WORDID_VENDOR_END = 0x7FFF0000 +}; + +typedef uint32 CSSM_LIST_ELEMENT_TYPE, *CSSM_LIST_ELEMENT_TYPE_PTR; +enum { + CSSM_LIST_ELEMENT_DATUM = 0x00, + CSSM_LIST_ELEMENT_SUBLIST = 0x01, + CSSM_LIST_ELEMENT_WORDID = 0x02 +}; + +typedef uint32 CSSM_LIST_TYPE, *CSSM_LIST_TYPE_PTR; +enum { + CSSM_LIST_TYPE_UNKNOWN = 0, + CSSM_LIST_TYPE_CUSTOM = 1, + CSSM_LIST_TYPE_SEXPR = 2 +}; + +typedef struct cssm_list_element *CSSM_LIST_ELEMENT_PTR; + +typedef struct cssm_list { + CSSM_LIST_TYPE ListType; /* type of this list */ + CSSM_LIST_ELEMENT_PTR Head; /* head of the list */ + CSSM_LIST_ELEMENT_PTR Tail; /* tail of the list */ +} CSSM_LIST DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_LIST_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef struct cssm_list_element { + struct cssm_list_element *NextElement; /* next list element */ + CSSM_WORDID_TYPE WordID; /* integer identifier associated */ + /* with a Word value */ + CSSM_LIST_ELEMENT_TYPE ElementType; + union { + CSSM_LIST Sublist; /* sublist */ + CSSM_DATA Word; /* a byte-string */ + } Element; +} CSSM_LIST_ELEMENT; + +typedef struct { /* 5-tuple definition */ + CSSM_LIST Issuer; /* issuer, or empty if ACL */ + CSSM_LIST Subject; /* subject */ + CSSM_BOOL Delegate; /* permission to delegate */ + CSSM_LIST AuthorizationTag; /* authorization field */ + CSSM_LIST ValidityPeriod; /* validity information (dates) */ +} CSSM_TUPLE DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_TUPLE_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef struct cssm_tuplegroup { + uint32 NumberOfTuples; + CSSM_TUPLE_PTR Tuples; +} CSSM_TUPLEGROUP DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_TUPLEGROUP_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef CSSM_WORDID_TYPE CSSM_SAMPLE_TYPE; +enum { + CSSM_SAMPLE_TYPE_PASSWORD = CSSM_WORDID_PASSWORD, + CSSM_SAMPLE_TYPE_HASHED_PASSWORD = CSSM_WORDID_HASHED_PASSWORD, + CSSM_SAMPLE_TYPE_PROTECTED_PASSWORD = CSSM_WORDID_PROTECTED_PASSWORD, + CSSM_SAMPLE_TYPE_PROMPTED_PASSWORD = CSSM_WORDID_PROMPTED_PASSWORD, + CSSM_SAMPLE_TYPE_SIGNED_NONCE = CSSM_WORDID_SIGNED_NONCE, + CSSM_SAMPLE_TYPE_SIGNED_SECRET = CSSM_WORDID_SIGNED_SECRET, + CSSM_SAMPLE_TYPE_BIOMETRIC = CSSM_WORDID_BIOMETRIC, + CSSM_SAMPLE_TYPE_PROTECTED_BIOMETRIC = CSSM_WORDID_PROTECTED_BIOMETRIC, + CSSM_SAMPLE_TYPE_PROMPTED_BIOMETRIC = CSSM_WORDID_PROMPTED_BIOMETRIC, + CSSM_SAMPLE_TYPE_THRESHOLD = CSSM_WORDID_THRESHOLD +}; + +typedef struct cssm_sample { + CSSM_LIST TypedSample; + const CSSM_SUBSERVICE_UID *Verifier; +} CSSM_SAMPLE DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_SAMPLE_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef struct cssm_samplegroup { + uint32 NumberOfSamples; + const CSSM_SAMPLE *Samples; +} CSSM_SAMPLEGROUP DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_SAMPLEGROUP_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef void *(CSSMAPI *CSSM_MALLOC) + (CSSM_SIZE size, + void *allocref); + +typedef void (CSSMAPI *CSSM_FREE) + (void *memblock, + void *allocref); + +typedef void *(CSSMAPI *CSSM_REALLOC) + (void *memblock, + CSSM_SIZE size, + void *allocref); + +typedef void *(CSSMAPI *CSSM_CALLOC) + (uint32 num, + CSSM_SIZE size, + void *allocref); + +typedef struct cssm_memory_funcs { + CSSM_MALLOC malloc_func; + CSSM_FREE free_func; + CSSM_REALLOC realloc_func; + CSSM_CALLOC calloc_func; + void *AllocRef; +} CSSM_MEMORY_FUNCS DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_MEMORY_FUNCS_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef CSSM_MEMORY_FUNCS CSSM_API_MEMORY_FUNCS; +typedef CSSM_API_MEMORY_FUNCS *CSSM_API_MEMORY_FUNCS_PTR; + +typedef CSSM_RETURN (CSSMAPI * CSSM_CHALLENGE_CALLBACK) + (const CSSM_LIST *Challenge, + CSSM_SAMPLEGROUP_PTR Response, + void *CallerCtx, + const CSSM_MEMORY_FUNCS *MemFuncs); + +typedef uint32 CSSM_CERT_TYPE, *CSSM_CERT_TYPE_PTR; +enum { + CSSM_CERT_UNKNOWN = 0x00, + CSSM_CERT_X_509v1 = 0x01, + CSSM_CERT_X_509v2 = 0x02, + CSSM_CERT_X_509v3 = 0x03, + CSSM_CERT_PGP = 0x04, + CSSM_CERT_SPKI = 0x05, + CSSM_CERT_SDSIv1 = 0x06, + CSSM_CERT_Intel = 0x08, + CSSM_CERT_X_509_ATTRIBUTE = 0x09, /* X.509 attribute cert */ + CSSM_CERT_X9_ATTRIBUTE = 0x0A, /* X9 attribute cert */ + CSSM_CERT_TUPLE = 0x0B, + CSSM_CERT_ACL_ENTRY = 0x0C, + CSSM_CERT_MULTIPLE = 0x7FFE, + CSSM_CERT_LAST = 0x7FFF, + /* Applications wishing to define their own custom certificate + type should define and publicly document a uint32 value greater + than the CSSM_CL_CUSTOM_CERT_TYPE */ + CSSM_CL_CUSTOM_CERT_TYPE = 0x08000 +}; + +typedef uint32 CSSM_CERT_ENCODING, *CSSM_CERT_ENCODING_PTR; +enum { + CSSM_CERT_ENCODING_UNKNOWN = 0x00, + CSSM_CERT_ENCODING_CUSTOM = 0x01, + CSSM_CERT_ENCODING_BER = 0x02, + CSSM_CERT_ENCODING_DER = 0x03, + CSSM_CERT_ENCODING_NDR = 0x04, + CSSM_CERT_ENCODING_SEXPR = 0x05, + CSSM_CERT_ENCODING_PGP = 0x06, + CSSM_CERT_ENCODING_MULTIPLE = 0x7FFE, + CSSM_CERT_ENCODING_LAST = 0x7FFF, + /* Applications wishing to define their own custom certificate + encoding should create a uint32 value greater than the + CSSM_CL_CUSTOM_CERT_ENCODING */ + CSSM_CL_CUSTOM_CERT_ENCODING = 0x8000 +}; + +typedef struct cssm_encoded_cert { + CSSM_CERT_TYPE CertType; /* type of certificate */ + CSSM_CERT_ENCODING CertEncoding; /* encoding for this packed cert */ + CSSM_DATA CertBlob; /* packed cert */ +} CSSM_ENCODED_CERT DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_ENCODED_CERT_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef uint32 CSSM_CERT_PARSE_FORMAT, *CSSM_CERT_PARSE_FORMAT_PTR; +enum { + CSSM_CERT_PARSE_FORMAT_NONE = 0x00, + CSSM_CERT_PARSE_FORMAT_CUSTOM = 0x01, /* void* */ + CSSM_CERT_PARSE_FORMAT_SEXPR = 0x02, /* CSSM_LIST */ + CSSM_CERT_PARSE_FORMAT_COMPLEX = 0x03, /* void* */ + CSSM_CERT_PARSE_FORMAT_OID_NAMED = 0x04, /* CSSM_FIELDGROUP */ + CSSM_CERT_PARSE_FORMAT_TUPLE = 0x05, /* CSSM_TUPLE */ + CSSM_CERT_PARSE_FORMAT_MULTIPLE = 0x7FFE, +/* multiple forms, each cert carries a + parse format indicator */ + CSSM_CERT_PARSE_FORMAT_LAST = 0x7FFF, +/* Applications wishing to define their + own custom parse format should create + a * uint32 value greater than the + CSSM_CL_CUSTOM_CERT_PARSE_FORMAT */ + CSSM_CL_CUSTOM_CERT_PARSE_FORMAT = 0x8000 +}; + +typedef struct cssm_parsed_cert { + CSSM_CERT_TYPE CertType; /* certificate type */ + CSSM_CERT_PARSE_FORMAT ParsedCertFormat; + /* struct of ParsedCert */ + void *ParsedCert; /* parsed cert (to be typecast) */ +} CSSM_PARSED_CERT DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_PARSED_CERT_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef struct cssm_cert_pair { + CSSM_ENCODED_CERT EncodedCert; /* an encoded certificate blob */ + CSSM_PARSED_CERT ParsedCert; /* equivalent parsed certificate */ +} CSSM_CERT_PAIR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_CERT_PAIR_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef uint32 CSSM_CERTGROUP_TYPE, *CSSM_CERTGROUP_TYPE_PTR; +enum { + CSSM_CERTGROUP_DATA = 0x00, + CSSM_CERTGROUP_ENCODED_CERT = 0x01, + CSSM_CERTGROUP_PARSED_CERT = 0x02, + CSSM_CERTGROUP_CERT_PAIR = 0x03 +}; + +typedef struct cssm_certgroup { + CSSM_CERT_TYPE CertType; + CSSM_CERT_ENCODING CertEncoding; + uint32 NumCerts; /* # of certificates in this list */ + union { + CSSM_DATA_PTR CertList; /* legacy list of single type certificate blobs */ + CSSM_ENCODED_CERT_PTR EncodedCertList; + /* list of multi-type certificate blobs */ + CSSM_PARSED_CERT_PTR ParsedCertList; + /* list of multi-type parsed certs */ + CSSM_CERT_PAIR_PTR PairCertList; + /*list of single or multi-type certs with two representations: blob and parsed */ + } GroupList; + CSSM_CERTGROUP_TYPE CertGroupType; + /* type of structure in the GroupList */ + void *Reserved; /* reserved for implementation dependent use */ +} CSSM_CERTGROUP, *CSSM_CERTGROUP_PTR; + +typedef struct cssm_base_certs { + CSSM_TP_HANDLE TPHandle; + CSSM_CL_HANDLE CLHandle; + CSSM_CERTGROUP Certs; +} CSSM_BASE_CERTS DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_BASE_CERTS_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef struct cssm_access_credentials { + CSSM_STRING EntryTag; + CSSM_BASE_CERTS BaseCerts; + CSSM_SAMPLEGROUP Samples; + CSSM_CHALLENGE_CALLBACK Callback; + void *CallerCtx; +} CSSM_ACCESS_CREDENTIALS DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_ACCESS_CREDENTIALS_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef sint32 CSSM_ACL_SUBJECT_TYPE; +enum { + CSSM_ACL_SUBJECT_TYPE_ANY = CSSM_WORDID__STAR_, + CSSM_ACL_SUBJECT_TYPE_THRESHOLD = CSSM_WORDID_THRESHOLD, + CSSM_ACL_SUBJECT_TYPE_PASSWORD = CSSM_WORDID_PASSWORD, + CSSM_ACL_SUBJECT_TYPE_PROTECTED_PASSWORD = CSSM_WORDID_PROTECTED_PASSWORD, + CSSM_ACL_SUBJECT_TYPE_PROMPTED_PASSWORD = CSSM_WORDID_PROMPTED_PASSWORD, + CSSM_ACL_SUBJECT_TYPE_PUBLIC_KEY = CSSM_WORDID_PUBLIC_KEY, + CSSM_ACL_SUBJECT_TYPE_HASHED_SUBJECT = CSSM_WORDID_HASHED_SUBJECT, + CSSM_ACL_SUBJECT_TYPE_BIOMETRIC = CSSM_WORDID_BIOMETRIC, + CSSM_ACL_SUBJECT_TYPE_PROTECTED_BIOMETRIC = CSSM_WORDID_PROTECTED_BIOMETRIC, + CSSM_ACL_SUBJECT_TYPE_PROMPTED_BIOMETRIC = CSSM_WORDID_PROMPTED_BIOMETRIC, + CSSM_ACL_SUBJECT_TYPE_LOGIN_NAME = CSSM_WORDID_LOGIN_NAME, + CSSM_ACL_SUBJECT_TYPE_EXT_PAM_NAME = CSSM_WORDID_PAM_NAME +}; + +/* Authorization tag type */ +typedef sint32 CSSM_ACL_AUTHORIZATION_TAG; +enum { + /* All vendor specific constants must be in the number range + starting at CSSM_ACL_AUTHORIZATION_TAG_VENDOR_DEFINED_START */ + CSSM_ACL_AUTHORIZATION_TAG_VENDOR_DEFINED_START = 0x00010000, + /* No restrictions. Permission to perform all operations on + the resource or available to an ACL owner. */ + CSSM_ACL_AUTHORIZATION_ANY = CSSM_WORDID__STAR_, + /* Defined authorization tag values for CSPs */ + CSSM_ACL_AUTHORIZATION_LOGIN = CSSM_WORDID_LOGIN, + CSSM_ACL_AUTHORIZATION_GENKEY = CSSM_WORDID_GENKEY, + CSSM_ACL_AUTHORIZATION_DELETE = CSSM_WORDID_DELETE, + CSSM_ACL_AUTHORIZATION_EXPORT_WRAPPED = CSSM_WORDID_EXPORT_WRAPPED, + CSSM_ACL_AUTHORIZATION_EXPORT_CLEAR = CSSM_WORDID_EXPORT_CLEAR, + CSSM_ACL_AUTHORIZATION_IMPORT_WRAPPED = CSSM_WORDID_IMPORT_WRAPPED, + CSSM_ACL_AUTHORIZATION_IMPORT_CLEAR = CSSM_WORDID_IMPORT_CLEAR, + CSSM_ACL_AUTHORIZATION_SIGN = CSSM_WORDID_SIGN, + CSSM_ACL_AUTHORIZATION_ENCRYPT = CSSM_WORDID_ENCRYPT, + CSSM_ACL_AUTHORIZATION_DECRYPT = CSSM_WORDID_DECRYPT, + CSSM_ACL_AUTHORIZATION_MAC = CSSM_WORDID_MAC, + CSSM_ACL_AUTHORIZATION_DERIVE = CSSM_WORDID_DERIVE, + /* Defined authorization tag values for DLs */ + CSSM_ACL_AUTHORIZATION_DBS_CREATE = CSSM_WORDID_DBS_CREATE, + CSSM_ACL_AUTHORIZATION_DBS_DELETE = CSSM_WORDID_DBS_DELETE, + CSSM_ACL_AUTHORIZATION_DB_READ = CSSM_WORDID_DB_READ, + CSSM_ACL_AUTHORIZATION_DB_INSERT = CSSM_WORDID_DB_INSERT, + CSSM_ACL_AUTHORIZATION_DB_MODIFY = CSSM_WORDID_DB_MODIFY, + CSSM_ACL_AUTHORIZATION_DB_DELETE = CSSM_WORDID_DB_DELETE +}; + +typedef struct cssm_authorizationgroup { + uint32 NumberOfAuthTags; + CSSM_ACL_AUTHORIZATION_TAG *AuthTags; +} CSSM_AUTHORIZATIONGROUP DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_AUTHORIZATIONGROUP_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef struct cssm_acl_validity_period { + CSSM_DATA StartDate; + CSSM_DATA EndDate; +} CSSM_ACL_VALIDITY_PERIOD DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_ACL_VALIDITY_PERIOD_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef struct cssm_acl_entry_prototype { + CSSM_LIST TypedSubject; + CSSM_BOOL Delegate; + CSSM_AUTHORIZATIONGROUP Authorization; + CSSM_ACL_VALIDITY_PERIOD TimeRange; + CSSM_STRING EntryTag; +} CSSM_ACL_ENTRY_PROTOTYPE DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_ACL_ENTRY_PROTOTYPE_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef struct cssm_acl_owner_prototype { + CSSM_LIST TypedSubject; + CSSM_BOOL Delegate; +} CSSM_ACL_OWNER_PROTOTYPE DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_ACL_OWNER_PROTOTYPE_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef CSSM_RETURN (CSSMAPI * CSSM_ACL_SUBJECT_CALLBACK) + (const CSSM_LIST *SubjectRequest, + CSSM_LIST_PTR SubjectResponse, + void *CallerContext, + const CSSM_MEMORY_FUNCS *MemFuncs); + +typedef struct cssm_acl_entry_input { + CSSM_ACL_ENTRY_PROTOTYPE Prototype; + CSSM_ACL_SUBJECT_CALLBACK Callback; + void *CallerContext; +} CSSM_ACL_ENTRY_INPUT DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_ACL_ENTRY_INPUT_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef struct cssm_resource_control_context { + CSSM_ACCESS_CREDENTIALS_PTR AccessCred; + CSSM_ACL_ENTRY_INPUT InitialAclEntry; +} CSSM_RESOURCE_CONTROL_CONTEXT DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_RESOURCE_CONTROL_CONTEXT_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef CSSM_HANDLE CSSM_ACL_HANDLE; + +typedef struct cssm_acl_entry_info { + CSSM_ACL_ENTRY_PROTOTYPE EntryPublicInfo; + CSSM_ACL_HANDLE EntryHandle; +} CSSM_ACL_ENTRY_INFO DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_ACL_ENTRY_INFO_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef uint32 CSSM_ACL_EDIT_MODE; +enum { + CSSM_ACL_EDIT_MODE_ADD = 1, + CSSM_ACL_EDIT_MODE_DELETE = 2, + CSSM_ACL_EDIT_MODE_REPLACE = 3 +}; + +typedef struct cssm_acl_edit { + CSSM_ACL_EDIT_MODE EditMode; + CSSM_ACL_HANDLE OldEntryHandle; + const CSSM_ACL_ENTRY_INPUT *NewEntry; +} CSSM_ACL_EDIT DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_ACL_EDIT_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +#if defined(WIN32) +typedef FARPROC CSSM_PROC_ADDR; +#else +typedef void (CSSMAPI *CSSM_PROC_ADDR) (); +#endif +typedef CSSM_PROC_ADDR *CSSM_PROC_ADDR_PTR; + +typedef struct cssm_func_name_addr { + CSSM_STRING Name; + CSSM_PROC_ADDR Address; +} CSSM_FUNC_NAME_ADDR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_FUNC_NAME_ADDR_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + + +/* Data Types for Cryptographic Services */ + +typedef struct cssm_date { + uint8 Year[4]; + uint8 Month[2]; + uint8 Day[2]; +} CSSM_DATE DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_DATE_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef struct cssm_range { + uint32 Min; /* inclusive minimum value */ + uint32 Max; /* inclusive maximum value */ +} CSSM_RANGE DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_RANGE_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef struct cssm_query_size_data { + uint32 SizeInputBlock; /* size of input data block */ + uint32 SizeOutputBlock; /* size of resulting output data block */ +} CSSM_QUERY_SIZE_DATA DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_QUERY_SIZE_DATA_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef uint32 CSSM_HEADERVERSION; +enum { + CSSM_KEYHEADER_VERSION = 2 +}; + +typedef struct cssm_key_size { + uint32 LogicalKeySizeInBits; /* Logical key size in bits */ + uint32 EffectiveKeySizeInBits; /* Effective key size in bits */ +} CSSM_KEY_SIZE DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_KEY_SIZE_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef uint32 CSSM_KEYBLOB_TYPE; +enum { + CSSM_KEYBLOB_RAW = 0, /* The blob is a clear, raw key */ + CSSM_KEYBLOB_REFERENCE = 2, /* The blob is a reference to a key */ + CSSM_KEYBLOB_WRAPPED = 3, /* The blob is a wrapped RAW key */ + CSSM_KEYBLOB_OTHER = 0xFFFFFFFF +}; + +typedef uint32 CSSM_KEYBLOB_FORMAT; +enum { + /* Raw Format */ + CSSM_KEYBLOB_RAW_FORMAT_NONE = 0, + /* No further conversion need to be done */ + CSSM_KEYBLOB_RAW_FORMAT_PKCS1 = 1, /* RSA PKCS1 V1.5 */ + CSSM_KEYBLOB_RAW_FORMAT_PKCS3 = 2, /* RSA PKCS3 V1.5 */ + CSSM_KEYBLOB_RAW_FORMAT_MSCAPI = 3, /* Microsoft CAPI V2.0 */ + CSSM_KEYBLOB_RAW_FORMAT_PGP = 4, /* PGP V */ + CSSM_KEYBLOB_RAW_FORMAT_FIPS186 = 5, /* US Gov. FIPS 186 - DSS V */ + CSSM_KEYBLOB_RAW_FORMAT_BSAFE = 6, /* RSA Bsafe V3.0 */ + CSSM_KEYBLOB_RAW_FORMAT_CCA = 9, /* CCA clear public key blob */ + CSSM_KEYBLOB_RAW_FORMAT_PKCS8 = 10, /* RSA PKCS8 V1.2 */ + CSSM_KEYBLOB_RAW_FORMAT_SPKI = 11, /* SPKI Specification */ + CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING = 12, + CSSM_KEYBLOB_RAW_FORMAT_OTHER = 0xFFFFFFFF /* Other, CSP defined */ +}; +enum { + /* Wrapped Format */ + CSSM_KEYBLOB_WRAPPED_FORMAT_NONE = 0, + /* No further conversion need to be done */ + CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS8 = 1, /* RSA PKCS8 V1.2 */ + CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS7 = 2, + CSSM_KEYBLOB_WRAPPED_FORMAT_MSCAPI = 3, + CSSM_KEYBLOB_WRAPPED_FORMAT_OTHER = 0xFFFFFFFF /* Other, CSP defined */ +}; +enum { + /* Reference Format */ + CSSM_KEYBLOB_REF_FORMAT_INTEGER = 0, /* Reference is a number or handle */ + CSSM_KEYBLOB_REF_FORMAT_STRING = 1, /* Reference is a string or label */ + CSSM_KEYBLOB_REF_FORMAT_SPKI = 2, /* Reference is an SPKI S-expression */ + /* to be evaluated to locate the key */ + CSSM_KEYBLOB_REF_FORMAT_OTHER = 0xFFFFFFFF /* Other, CSP defined */ +}; + +typedef uint32 CSSM_KEYCLASS; +enum { + CSSM_KEYCLASS_PUBLIC_KEY = 0, /* Key is public key */ + CSSM_KEYCLASS_PRIVATE_KEY = 1, /* Key is private key */ + CSSM_KEYCLASS_SESSION_KEY = 2, /* Key is session or symmetric key */ + CSSM_KEYCLASS_SECRET_PART = 3, /* Key is part of secret key */ + CSSM_KEYCLASS_OTHER = 0xFFFFFFFF /* Other */ +}; + +typedef uint32 CSSM_KEYATTR_FLAGS; +enum { + /* Valid only during call to an API. Will never be valid when set in a key header */ + CSSM_KEYATTR_RETURN_DEFAULT = 0x00000000, + CSSM_KEYATTR_RETURN_DATA = 0x10000000, + CSSM_KEYATTR_RETURN_REF = 0x20000000, + CSSM_KEYATTR_RETURN_NONE = 0x40000000, + /* Valid during an API call and in a key header */ + CSSM_KEYATTR_PERMANENT = 0x00000001, + CSSM_KEYATTR_PRIVATE = 0x00000002, + CSSM_KEYATTR_MODIFIABLE = 0x00000004, + CSSM_KEYATTR_SENSITIVE = 0x00000008, + CSSM_KEYATTR_EXTRACTABLE = 0x00000020, + /* Valid only in a key header generated by a CSP, not valid during an API call */ + CSSM_KEYATTR_ALWAYS_SENSITIVE = 0x00000010, + CSSM_KEYATTR_NEVER_EXTRACTABLE = 0x00000040 +}; + +typedef uint32 CSSM_KEYUSE; +enum { + CSSM_KEYUSE_ANY = 0x80000000, + CSSM_KEYUSE_ENCRYPT = 0x00000001, + CSSM_KEYUSE_DECRYPT = 0x00000002, + CSSM_KEYUSE_SIGN = 0x00000004, + CSSM_KEYUSE_VERIFY = 0x00000008, + CSSM_KEYUSE_SIGN_RECOVER = 0x00000010, + CSSM_KEYUSE_VERIFY_RECOVER = 0x00000020, + CSSM_KEYUSE_WRAP = 0x00000040, + CSSM_KEYUSE_UNWRAP = 0x00000080, + CSSM_KEYUSE_DERIVE = 0x00000100 +}; + +typedef uint32 CSSM_ALGORITHMS; +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 +}; + +typedef uint32 CSSM_ENCRYPT_MODE; +enum { + CSSM_ALGMODE_NONE = 0, + CSSM_ALGMODE_CUSTOM = CSSM_ALGMODE_NONE + 1, + CSSM_ALGMODE_ECB = CSSM_ALGMODE_NONE + 2, + CSSM_ALGMODE_ECBPad = CSSM_ALGMODE_NONE + 3, + CSSM_ALGMODE_CBC = CSSM_ALGMODE_NONE + 4, + CSSM_ALGMODE_CBC_IV8 = CSSM_ALGMODE_NONE + 5, + CSSM_ALGMODE_CBCPadIV8 = CSSM_ALGMODE_NONE + 6, + CSSM_ALGMODE_CFB = CSSM_ALGMODE_NONE + 7, + CSSM_ALGMODE_CFB_IV8 = CSSM_ALGMODE_NONE + 8, + CSSM_ALGMODE_CFBPadIV8 = CSSM_ALGMODE_NONE + 9, + CSSM_ALGMODE_OFB = CSSM_ALGMODE_NONE + 10, + CSSM_ALGMODE_OFB_IV8 = CSSM_ALGMODE_NONE + 11, + CSSM_ALGMODE_OFBPadIV8 = CSSM_ALGMODE_NONE + 12, + CSSM_ALGMODE_COUNTER = CSSM_ALGMODE_NONE + 13, + CSSM_ALGMODE_BC = CSSM_ALGMODE_NONE + 14, + CSSM_ALGMODE_PCBC = CSSM_ALGMODE_NONE + 15, + CSSM_ALGMODE_CBCC = CSSM_ALGMODE_NONE + 16, + CSSM_ALGMODE_OFBNLF = CSSM_ALGMODE_NONE + 17, + CSSM_ALGMODE_PBC = CSSM_ALGMODE_NONE + 18, + CSSM_ALGMODE_PFB = CSSM_ALGMODE_NONE + 19, + CSSM_ALGMODE_CBCPD = CSSM_ALGMODE_NONE + 20, + CSSM_ALGMODE_PUBLIC_KEY = CSSM_ALGMODE_NONE + 21, + CSSM_ALGMODE_PRIVATE_KEY = CSSM_ALGMODE_NONE + 22, + CSSM_ALGMODE_SHUFFLE = CSSM_ALGMODE_NONE + 23, + CSSM_ALGMODE_ECB64 = CSSM_ALGMODE_NONE + 24, + CSSM_ALGMODE_CBC64 = CSSM_ALGMODE_NONE + 25, + CSSM_ALGMODE_OFB64 = CSSM_ALGMODE_NONE + 26, + CSSM_ALGMODE_CFB32 = CSSM_ALGMODE_NONE + 28, + CSSM_ALGMODE_CFB16 = CSSM_ALGMODE_NONE + 29, + CSSM_ALGMODE_CFB8 = CSSM_ALGMODE_NONE + 30, + CSSM_ALGMODE_WRAP = CSSM_ALGMODE_NONE + 31, + CSSM_ALGMODE_PRIVATE_WRAP = CSSM_ALGMODE_NONE + 32, + CSSM_ALGMODE_RELAYX = CSSM_ALGMODE_NONE + 33, + CSSM_ALGMODE_ECB128 = CSSM_ALGMODE_NONE + 34, + CSSM_ALGMODE_ECB96 = CSSM_ALGMODE_NONE + 35, + CSSM_ALGMODE_CBC128 = CSSM_ALGMODE_NONE + 36, + CSSM_ALGMODE_OAEP_HASH = CSSM_ALGMODE_NONE + 37, + CSSM_ALGMODE_PKCS1_EME_V15 = CSSM_ALGMODE_NONE + 38, + CSSM_ALGMODE_PKCS1_EME_OAEP = CSSM_ALGMODE_NONE + 39, + CSSM_ALGMODE_PKCS1_EMSA_V15 = CSSM_ALGMODE_NONE + 40, + CSSM_ALGMODE_ISO_9796 = CSSM_ALGMODE_NONE + 41, + CSSM_ALGMODE_X9_31 = CSSM_ALGMODE_NONE + 42, + CSSM_ALGMODE_LAST = CSSM_ALGMODE_NONE + 0x7FFFFFFF, +/* All algorithms modes that are vendor specific, and + not part of the CSSM specification should be defined + relative to CSSM_ALGMODE_VENDOR_DEFINED. */ + CSSM_ALGMODE_VENDOR_DEFINED = CSSM_ALGMODE_NONE + 0x80000000 +}; + +typedef struct cssm_keyheader { + CSSM_HEADERVERSION HeaderVersion; /* Key header version */ + CSSM_GUID CspId; /* GUID of CSP generating the key */ + CSSM_KEYBLOB_TYPE BlobType; /* See BlobType enum */ + CSSM_KEYBLOB_FORMAT Format; /* Raw or Reference format */ + CSSM_ALGORITHMS AlgorithmId; /* Algorithm ID of key */ + CSSM_KEYCLASS KeyClass; /* Public/Private/Secret, etc. */ + uint32 LogicalKeySizeInBits; /* Logical key size in bits */ + CSSM_KEYATTR_FLAGS KeyAttr; /* Attribute flags */ + CSSM_KEYUSE KeyUsage; /* Key use flags */ + CSSM_DATE StartDate; /* Effective date of key */ + CSSM_DATE EndDate; /* Expiration date of key */ + CSSM_ALGORITHMS WrapAlgorithmId; /* == CSSM_ALGID_NONE if clear key */ + CSSM_ENCRYPT_MODE WrapMode; /* if alg supports multiple wrapping modes */ + uint32 Reserved; +} CSSM_KEYHEADER DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_KEYHEADER_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef struct cssm_key { + CSSM_KEYHEADER KeyHeader; /* Fixed length key header */ + CSSM_DATA KeyData; /* Variable length key data */ +} CSSM_KEY DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_KEY_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef CSSM_KEY CSSM_WRAP_KEY, *CSSM_WRAP_KEY_PTR; + +typedef uint32 CSSM_CSPTYPE; +enum { + CSSM_CSP_SOFTWARE = 1, + CSSM_CSP_HARDWARE = CSSM_CSP_SOFTWARE + 1, + CSSM_CSP_HYBRID = CSSM_CSP_SOFTWARE + 2 +}; + +/* From DL. */ +typedef struct cssm_dl_db_handle { + CSSM_DL_HANDLE DLHandle; + CSSM_DB_HANDLE DBHandle; +} CSSM_DL_DB_HANDLE DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_DL_DB_HANDLE_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef uint32 CSSM_CONTEXT_TYPE; +enum { + CSSM_ALGCLASS_NONE = 0, + CSSM_ALGCLASS_CUSTOM = CSSM_ALGCLASS_NONE + 1, + CSSM_ALGCLASS_SIGNATURE = CSSM_ALGCLASS_NONE + 2, + CSSM_ALGCLASS_SYMMETRIC = CSSM_ALGCLASS_NONE + 3, + CSSM_ALGCLASS_DIGEST = CSSM_ALGCLASS_NONE + 4, + CSSM_ALGCLASS_RANDOMGEN = CSSM_ALGCLASS_NONE + 5, + CSSM_ALGCLASS_UNIQUEGEN = CSSM_ALGCLASS_NONE + 6, + CSSM_ALGCLASS_MAC = CSSM_ALGCLASS_NONE + 7, + CSSM_ALGCLASS_ASYMMETRIC = CSSM_ALGCLASS_NONE + 8, + CSSM_ALGCLASS_KEYGEN = CSSM_ALGCLASS_NONE + 9, + CSSM_ALGCLASS_DERIVEKEY = CSSM_ALGCLASS_NONE + 10 +}; + +/* Attribute data type tags */ +enum { + CSSM_ATTRIBUTE_DATA_NONE = 0x00000000, + CSSM_ATTRIBUTE_DATA_UINT32 = 0x10000000, + CSSM_ATTRIBUTE_DATA_CSSM_DATA = 0x20000000, + CSSM_ATTRIBUTE_DATA_CRYPTO_DATA = 0x30000000, + CSSM_ATTRIBUTE_DATA_KEY = 0x40000000, + CSSM_ATTRIBUTE_DATA_STRING = 0x50000000, + CSSM_ATTRIBUTE_DATA_DATE = 0x60000000, + CSSM_ATTRIBUTE_DATA_RANGE = 0x70000000, + CSSM_ATTRIBUTE_DATA_ACCESS_CREDENTIALS = 0x80000000, + CSSM_ATTRIBUTE_DATA_VERSION = 0x01000000, + CSSM_ATTRIBUTE_DATA_DL_DB_HANDLE = 0x02000000, + CSSM_ATTRIBUTE_DATA_KR_PROFILE = 0x03000000, + CSSM_ATTRIBUTE_TYPE_MASK = 0xFF000000 +}; + +typedef uint32 CSSM_ATTRIBUTE_TYPE; +enum { + CSSM_ATTRIBUTE_NONE = 0, + CSSM_ATTRIBUTE_CUSTOM = CSSM_ATTRIBUTE_DATA_CSSM_DATA | 1, + CSSM_ATTRIBUTE_DESCRIPTION = CSSM_ATTRIBUTE_DATA_STRING | 2, + CSSM_ATTRIBUTE_KEY = CSSM_ATTRIBUTE_DATA_KEY | 3, + CSSM_ATTRIBUTE_INIT_VECTOR = CSSM_ATTRIBUTE_DATA_CSSM_DATA | 4, + CSSM_ATTRIBUTE_SALT = CSSM_ATTRIBUTE_DATA_CSSM_DATA | 5, + CSSM_ATTRIBUTE_PADDING = CSSM_ATTRIBUTE_DATA_UINT32 | 6, + CSSM_ATTRIBUTE_RANDOM = CSSM_ATTRIBUTE_DATA_CSSM_DATA | 7, + CSSM_ATTRIBUTE_SEED = CSSM_ATTRIBUTE_DATA_CRYPTO_DATA | 8, + CSSM_ATTRIBUTE_PASSPHRASE = CSSM_ATTRIBUTE_DATA_CRYPTO_DATA | 9, + CSSM_ATTRIBUTE_KEY_LENGTH = CSSM_ATTRIBUTE_DATA_UINT32 | 10, + CSSM_ATTRIBUTE_KEY_LENGTH_RANGE = CSSM_ATTRIBUTE_DATA_RANGE | 11, + CSSM_ATTRIBUTE_BLOCK_SIZE = CSSM_ATTRIBUTE_DATA_UINT32 | 12, + CSSM_ATTRIBUTE_OUTPUT_SIZE = CSSM_ATTRIBUTE_DATA_UINT32 | 13, + CSSM_ATTRIBUTE_ROUNDS = CSSM_ATTRIBUTE_DATA_UINT32 | 14, + CSSM_ATTRIBUTE_IV_SIZE = CSSM_ATTRIBUTE_DATA_UINT32 | 15, + CSSM_ATTRIBUTE_ALG_PARAMS = CSSM_ATTRIBUTE_DATA_CSSM_DATA | 16, + CSSM_ATTRIBUTE_LABEL = CSSM_ATTRIBUTE_DATA_CSSM_DATA | 17, + CSSM_ATTRIBUTE_KEY_TYPE = CSSM_ATTRIBUTE_DATA_UINT32 | 18, + CSSM_ATTRIBUTE_MODE = CSSM_ATTRIBUTE_DATA_UINT32 | 19, + CSSM_ATTRIBUTE_EFFECTIVE_BITS = CSSM_ATTRIBUTE_DATA_UINT32 | 20, + CSSM_ATTRIBUTE_START_DATE = CSSM_ATTRIBUTE_DATA_DATE | 21, + CSSM_ATTRIBUTE_END_DATE = CSSM_ATTRIBUTE_DATA_DATE | 22, + CSSM_ATTRIBUTE_KEYUSAGE = CSSM_ATTRIBUTE_DATA_UINT32 | 23, + CSSM_ATTRIBUTE_KEYATTR = CSSM_ATTRIBUTE_DATA_UINT32 | 24, + CSSM_ATTRIBUTE_VERSION = CSSM_ATTRIBUTE_DATA_VERSION | 25, + CSSM_ATTRIBUTE_PRIME = CSSM_ATTRIBUTE_DATA_CSSM_DATA | 26, + CSSM_ATTRIBUTE_BASE = CSSM_ATTRIBUTE_DATA_CSSM_DATA | 27, + CSSM_ATTRIBUTE_SUBPRIME = CSSM_ATTRIBUTE_DATA_CSSM_DATA | 28, + CSSM_ATTRIBUTE_ALG_ID = CSSM_ATTRIBUTE_DATA_UINT32 | 29, + CSSM_ATTRIBUTE_ITERATION_COUNT = CSSM_ATTRIBUTE_DATA_UINT32 | 30, + CSSM_ATTRIBUTE_ROUNDS_RANGE = CSSM_ATTRIBUTE_DATA_RANGE | 31, + CSSM_ATTRIBUTE_KRPROFILE_LOCAL = CSSM_ATTRIBUTE_DATA_KR_PROFILE | 32, + CSSM_ATTRIBUTE_KRPROFILE_REMOTE = CSSM_ATTRIBUTE_DATA_KR_PROFILE | 33, + CSSM_ATTRIBUTE_CSP_HANDLE = CSSM_ATTRIBUTE_DATA_UINT32 | 34, + CSSM_ATTRIBUTE_DL_DB_HANDLE = CSSM_ATTRIBUTE_DATA_DL_DB_HANDLE | 35, + CSSM_ATTRIBUTE_ACCESS_CREDENTIALS = CSSM_ATTRIBUTE_DATA_ACCESS_CREDENTIALS | 36, + CSSM_ATTRIBUTE_PUBLIC_KEY_FORMAT = CSSM_ATTRIBUTE_DATA_UINT32 | 37, + CSSM_ATTRIBUTE_PRIVATE_KEY_FORMAT = CSSM_ATTRIBUTE_DATA_UINT32 | 38, + CSSM_ATTRIBUTE_SYMMETRIC_KEY_FORMAT=CSSM_ATTRIBUTE_DATA_UINT32 | 39, + CSSM_ATTRIBUTE_WRAPPED_KEY_FORMAT = CSSM_ATTRIBUTE_DATA_UINT32 | 40 +}; + +typedef uint32 CSSM_PADDING; +enum { + CSSM_PADDING_NONE = 0, + CSSM_PADDING_CUSTOM = CSSM_PADDING_NONE + 1, + CSSM_PADDING_ZERO = CSSM_PADDING_NONE + 2, + CSSM_PADDING_ONE = CSSM_PADDING_NONE + 3, + CSSM_PADDING_ALTERNATE = CSSM_PADDING_NONE + 4, + CSSM_PADDING_FF = CSSM_PADDING_NONE + 5, + CSSM_PADDING_PKCS5 = CSSM_PADDING_NONE + 6, + CSSM_PADDING_PKCS7 = CSSM_PADDING_NONE + 7, + CSSM_PADDING_CIPHERSTEALING = CSSM_PADDING_NONE + 8, + CSSM_PADDING_RANDOM = CSSM_PADDING_NONE + 9, + CSSM_PADDING_PKCS1 = CSSM_PADDING_NONE + 10, +/* All padding types that are vendor specific, and not + part of the CSSM specification should be defined + relative to CSSM_PADDING_VENDOR_DEFINED. */ + CSSM_PADDING_VENDOR_DEFINED = CSSM_PADDING_NONE + 0x80000000 +}; + +typedef CSSM_ALGORITHMS CSSM_KEY_TYPE; + +typedef struct cssm_context_attribute { + CSSM_ATTRIBUTE_TYPE AttributeType; + uint32 AttributeLength; + union cssm_context_attribute_value { + char *String; + uint32 Uint32; + CSSM_ACCESS_CREDENTIALS_PTR AccessCredentials; + CSSM_KEY_PTR Key; + CSSM_DATA_PTR Data; + CSSM_PADDING Padding; + CSSM_DATE_PTR Date; + CSSM_RANGE_PTR Range; + CSSM_CRYPTO_DATA_PTR CryptoData; + CSSM_VERSION_PTR Version; + CSSM_DL_DB_HANDLE_PTR DLDBHandle; + struct cssm_kr_profile *KRProfile; + } Attribute; +} CSSM_CONTEXT_ATTRIBUTE, *CSSM_CONTEXT_ATTRIBUTE_PTR; + +typedef struct cssm_context { + CSSM_CONTEXT_TYPE ContextType; + CSSM_ALGORITHMS AlgorithmType; + uint32 NumberOfAttributes; + CSSM_CONTEXT_ATTRIBUTE_PTR ContextAttributes; + CSSM_CSP_HANDLE CSPHandle; + CSSM_BOOL Privileged; + uint32 /*CSSM_KR_POLICY_FLAGS*/ EncryptionProhibited; + uint32 WorkFactor; + uint32 Reserved; /* reserved for future use */ +} CSSM_CONTEXT DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_CONTEXT_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef uint32 CSSM_SC_FLAGS; +enum { + CSSM_CSP_TOK_RNG = 0x00000001, + CSSM_CSP_TOK_CLOCK_EXISTS = 0x00000040 +}; + +typedef uint32 CSSM_CSP_READER_FLAGS; +enum { + CSSM_CSP_RDR_TOKENPRESENT = 0x00000001, + /* Token is present in reader/slot */ + CSSM_CSP_RDR_EXISTS = 0x00000002, + /* Device is a reader with a + removable token */ + CSSM_CSP_RDR_HW = 0x00000004 + /* Slot is a hardware slot */ +}; + +typedef uint32 CSSM_CSP_FLAGS; +enum { + CSSM_CSP_TOK_WRITE_PROTECTED = 0x00000002, + CSSM_CSP_TOK_LOGIN_REQUIRED = 0x00000004, + CSSM_CSP_TOK_USER_PIN_INITIALIZED = 0x00000008, + CSSM_CSP_TOK_PROT_AUTHENTICATION = 0x00000100, + CSSM_CSP_TOK_USER_PIN_EXPIRED = 0x00100000, + CSSM_CSP_TOK_SESSION_KEY_PASSWORD = 0x00200000, + CSSM_CSP_TOK_PRIVATE_KEY_PASSWORD = 0x00400000, + CSSM_CSP_STORES_PRIVATE_KEYS = 0x01000000, + CSSM_CSP_STORES_PUBLIC_KEYS = 0x02000000, + CSSM_CSP_STORES_SESSION_KEYS = 0x04000000, + CSSM_CSP_STORES_CERTIFICATES = 0x08000000, + CSSM_CSP_STORES_GENERIC = 0x10000000 +}; + +typedef uint32 CSSM_PKCS_OAEP_MGF; +enum { + CSSM_PKCS_OAEP_MGF_NONE = 0, + CSSM_PKCS_OAEP_MGF1_SHA1 = CSSM_PKCS_OAEP_MGF_NONE + 1, + CSSM_PKCS_OAEP_MGF1_MD5 = CSSM_PKCS_OAEP_MGF_NONE + 2 +}; + +typedef uint32 CSSM_PKCS_OAEP_PSOURCE; +enum { + CSSM_PKCS_OAEP_PSOURCE_NONE = 0, + CSSM_PKCS_OAEP_PSOURCE_Pspecified = CSSM_PKCS_OAEP_PSOURCE_NONE + 1 +}; + +typedef struct cssm_pkcs1_oaep_params { + uint32 HashAlgorithm; + CSSM_DATA HashParams; + CSSM_PKCS_OAEP_MGF MGF; + CSSM_DATA MGFParams; + CSSM_PKCS_OAEP_PSOURCE PSource; + CSSM_DATA PSourceParams; +} CSSM_PKCS1_OAEP_PARAMS DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_PKCS1_OAEP_PARAMS_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef struct cssm_csp_operational_statistics { + CSSM_BOOL UserAuthenticated; + /* CSSM_TRUE if the user is logged in to the token, CSSM_FALSE otherwise. */ + CSSM_CSP_FLAGS DeviceFlags; + uint32 TokenMaxSessionCount; /* Exported by Cryptoki modules. */ + uint32 TokenOpenedSessionCount; + uint32 TokenMaxRWSessionCount; + uint32 TokenOpenedRWSessionCount; + uint32 TokenTotalPublicMem; /* Storage space statistics. */ + uint32 TokenFreePublicMem; + uint32 TokenTotalPrivateMem; + uint32 TokenFreePrivateMem; +} CSSM_CSP_OPERATIONAL_STATISTICS DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_CSP_OPERATIONAL_STATISTICS_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* Indicates that the statistical value can not be revealed or is not + relevant for a CSP */ +enum { + CSSM_VALUE_NOT_AVAILABLE = (uint32)(~0) +}; + +typedef struct cssm_pkcs5_pbkdf1_params { + CSSM_DATA Passphrase; + CSSM_DATA InitVector; +} CSSM_PKCS5_PBKDF1_PARAMS DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_PKCS5_PBKDF1_PARAMS_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef uint32 CSSM_PKCS5_PBKDF2_PRF; +enum { + CSSM_PKCS5_PBKDF2_PRF_HMAC_SHA1 = 0 +}; + +typedef struct cssm_pkcs5_pbkdf2_params { + CSSM_DATA Passphrase; + CSSM_PKCS5_PBKDF2_PRF PseudoRandomFunction; +} CSSM_PKCS5_PBKDF2_PARAMS DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_PKCS5_PBKDF2_PARAMS_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef struct cssm_kea_derive_params { + CSSM_DATA Rb; + CSSM_DATA Yb; +} CSSM_KEA_DERIVE_PARAMS DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_KEA_DERIVE_PARAMS_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + + +/* Data Types for Trust Policy Services */ + +typedef struct cssm_tp_authority_id { + CSSM_DATA *AuthorityCert; + CSSM_NET_ADDRESS_PTR AuthorityLocation; +} CSSM_TP_AUTHORITY_ID DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_TP_AUTHORITY_ID_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef uint32 CSSM_TP_AUTHORITY_REQUEST_TYPE, *CSSM_TP_AUTHORITY_REQUEST_TYPE_PTR; +enum { + CSSM_TP_AUTHORITY_REQUEST_CERTISSUE = 0x01, + CSSM_TP_AUTHORITY_REQUEST_CERTREVOKE = 0x02, + CSSM_TP_AUTHORITY_REQUEST_CERTSUSPEND = 0x03, + CSSM_TP_AUTHORITY_REQUEST_CERTRESUME = 0x04, + CSSM_TP_AUTHORITY_REQUEST_CERTVERIFY = 0x05, + CSSM_TP_AUTHORITY_REQUEST_CERTNOTARIZE = 0x06, + CSSM_TP_AUTHORITY_REQUEST_CERTUSERECOVER = 0x07, + CSSM_TP_AUTHORITY_REQUEST_CRLISSUE = 0x100 +}; + +typedef CSSM_RETURN (CSSMAPI * CSSM_TP_VERIFICATION_RESULTS_CALLBACK) + (CSSM_MODULE_HANDLE ModuleHandle, + void *CallerCtx, + CSSM_DATA_PTR VerifiedCert); + +/* From CL */ +typedef CSSM_DATA CSSM_OID, *CSSM_OID_PTR; + +typedef struct cssm_field { + CSSM_OID FieldOid; + CSSM_DATA FieldValue; +} CSSM_FIELD DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_FIELD_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* TP Again. */ +typedef struct cssm_tp_policyinfo { + uint32 NumberOfPolicyIds; + CSSM_FIELD_PTR PolicyIds; + void *PolicyControl; +} CSSM_TP_POLICYINFO DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_TP_POLICYINFO_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef uint32 CSSM_TP_SERVICES; +enum { + /* bit masks for additional Authority services available through TP */ + CSSM_TP_KEY_ARCHIVE = 0x0001, /* archive cert & keys */ + CSSM_TP_CERT_PUBLISH = 0x0002, /* register cert in directory */ + CSSM_TP_CERT_NOTIFY_RENEW = 0x0004, /* notify at renewal time */ + CSSM_TP_CERT_DIR_UPDATE = 0x0008, /* update cert registry entry */ + CSSM_TP_CRL_DISTRIBUTE = 0x0010 /* push CRL to everyone */ +}; + +typedef uint32 CSSM_TP_ACTION; +enum { + CSSM_TP_ACTION_DEFAULT = 0 +}; + +typedef uint32 CSSM_TP_STOP_ON; +enum { + CSSM_TP_STOP_ON_POLICY = 0, /* use the pre-defined stopping criteria */ + CSSM_TP_STOP_ON_NONE = 1, /* evaluate all condition whether TRUE or FALSE */ + CSSM_TP_STOP_ON_FIRST_PASS = 2, /* stop evaluation at first TRUE */ + CSSM_TP_STOP_ON_FIRST_FAIL = 3 /* stop evaluation at first FALSE */ +}; + +typedef char *CSSM_TIMESTRING; + +/* From DL. */ +typedef struct cssm_dl_db_list { + uint32 NumHandles; + CSSM_DL_DB_HANDLE_PTR DLDBHandle; +} CSSM_DL_DB_LIST DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_DL_DB_LIST_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* TP Again. */ +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 DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_TP_CALLERAUTH_CONTEXT_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef uint32 CSSM_CRL_PARSE_FORMAT, * CSSM_CRL_PARSE_FORMAT_PTR; +enum { + CSSM_CRL_PARSE_FORMAT_NONE = 0x00, + CSSM_CRL_PARSE_FORMAT_CUSTOM = 0x01, + CSSM_CRL_PARSE_FORMAT_SEXPR = 0x02, + CSSM_CRL_PARSE_FORMAT_COMPLEX = 0x03, + CSSM_CRL_PARSE_FORMAT_OID_NAMED = 0x04, + CSSM_CRL_PARSE_FORMAT_TUPLE = 0x05, + CSSM_CRL_PARSE_FORMAT_MULTIPLE = 0x7FFE, + CSSM_CRL_PARSE_FORMAT_LAST = 0x7FFF, + /* Applications wishing to define their own custom parse + format should create a uint32 value greater than the + CSSM_CL_CUSTOM_CRL_PARSE_FORMAT */ + CSSM_CL_CUSTOM_CRL_PARSE_FORMAT = 0x8000 +}; + +/* From CL. */ +typedef uint32 CSSM_CRL_TYPE, *CSSM_CRL_TYPE_PTR; +enum { + CSSM_CRL_TYPE_UNKNOWN = 0x00, + CSSM_CRL_TYPE_X_509v1 = 0x01, + CSSM_CRL_TYPE_X_509v2 = 0x02, + CSSM_CRL_TYPE_SPKI = 0x03, + CSSM_CRL_TYPE_MULTIPLE = 0x7FFE +}; + +typedef uint32 CSSM_CRL_ENCODING, *CSSM_CRL_ENCODING_PTR; +enum { + CSSM_CRL_ENCODING_UNKNOWN = 0x00, + CSSM_CRL_ENCODING_CUSTOM = 0x01, + CSSM_CRL_ENCODING_BER = 0x02, + CSSM_CRL_ENCODING_DER = 0x03, + CSSM_CRL_ENCODING_BLOOM = 0x04, + CSSM_CRL_ENCODING_SEXPR = 0x05, + CSSM_CRL_ENCODING_MULTIPLE = 0x7FFE +}; + +typedef struct cssm_encoded_crl { + CSSM_CRL_TYPE CrlType; /* type of CRL */ + CSSM_CRL_ENCODING CrlEncoding; /* encoding for this packed CRL */ + CSSM_DATA CrlBlob; /* packed CRL */ +} CSSM_ENCODED_CRL DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_ENCODED_CRL_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* TP Again. */ +typedef struct cssm_parsed_crl { + CSSM_CRL_TYPE CrlType; /* CRL type */ + CSSM_CRL_PARSE_FORMAT ParsedCrlFormat; + /* struct of ParsedCrl */ + void *ParsedCrl; /* parsed CRL (to be typecast) */ +} CSSM_PARSED_CRL DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_PARSED_CRL_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef struct cssm_crl_pair { + CSSM_ENCODED_CRL EncodedCrl; /* an encoded CRL blob */ + CSSM_PARSED_CRL ParsedCrl; /* equivalent parsed CRL */ +} CSSM_CRL_PAIR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_CRL_PAIR_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef uint32 CSSM_CRLGROUP_TYPE, * CSSM_CRLGROUP_TYPE_PTR; +enum { + CSSM_CRLGROUP_DATA = 0x00, + CSSM_CRLGROUP_ENCODED_CRL = 0x01, + CSSM_CRLGROUP_PARSED_CRL = 0x02, + CSSM_CRLGROUP_CRL_PAIR = 0x03 +}; + +typedef struct cssm_crlgroup { + CSSM_CRL_TYPE CrlType; + CSSM_CRL_ENCODING CrlEncoding; + uint32 NumberOfCrls; + union { + CSSM_DATA_PTR CrlList; /* CRL blob */ + CSSM_ENCODED_CRL_PTR EncodedCrlList; /* CRL blob w/ separate type */ + CSSM_PARSED_CRL_PTR ParsedCrlList; /* bushy, parsed CRL */ + CSSM_CRL_PAIR_PTR PairCrlList; + } GroupCrlList; + CSSM_CRLGROUP_TYPE CrlGroupType; +} CSSM_CRLGROUP, *CSSM_CRLGROUP_PTR; + +typedef struct cssm_fieldgroup { + int NumberOfFields; /* number of fields in the array */ + CSSM_FIELD_PTR Fields; /* array of fields */ +} CSSM_FIELDGROUP DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_FIELDGROUP_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef uint32 CSSM_EVIDENCE_FORM; +enum { + CSSM_EVIDENCE_FORM_UNSPECIFIC = 0x0, + CSSM_EVIDENCE_FORM_CERT = 0x1, + CSSM_EVIDENCE_FORM_CRL = 0x2, + CSSM_EVIDENCE_FORM_CERT_ID = 0x3, + CSSM_EVIDENCE_FORM_CRL_ID = 0x4, + CSSM_EVIDENCE_FORM_VERIFIER_TIME = 0x5, + CSSM_EVIDENCE_FORM_CRL_THISTIME = 0x6, + CSSM_EVIDENCE_FORM_CRL_NEXTTIME = 0x7, + CSSM_EVIDENCE_FORM_POLICYINFO = 0x8, + CSSM_EVIDENCE_FORM_TUPLEGROUP = 0x9 +}; + +typedef struct cssm_evidence { + CSSM_EVIDENCE_FORM EvidenceForm; + void *Evidence; /* Evidence content */ +} CSSM_EVIDENCE DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_EVIDENCE_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef struct cssm_tp_verify_context { + CSSM_TP_ACTION Action; + CSSM_DATA ActionData; + CSSM_CRLGROUP Crls; + CSSM_TP_CALLERAUTH_CONTEXT_PTR Cred; +} CSSM_TP_VERIFY_CONTEXT DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_TP_VERIFY_CONTEXT_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef struct cssm_tp_verify_context_result { + uint32 NumberOfEvidences; + CSSM_EVIDENCE_PTR Evidence; +} CSSM_TP_VERIFY_CONTEXT_RESULT DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_TP_VERIFY_CONTEXT_RESULT_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef struct cssm_tp_request_set { + uint32 NumberOfRequests; + void *Requests; +} CSSM_TP_REQUEST_SET DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_TP_REQUEST_SET_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef struct cssm_tp_result_set { + uint32 NumberOfResults; + void *Results; +} CSSM_TP_RESULT_SET DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_TP_RESULT_SET_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef uint32 CSSM_TP_CONFIRM_STATUS, *CSSM_TP_CONFIRM_STATUS_PTR; +enum { + CSSM_TP_CONFIRM_STATUS_UNKNOWN = 0x0, + /* indeterminate */ + CSSM_TP_CONFIRM_ACCEPT = 0x1, + /* accept results of executing a + submit-retrieve function pair */ + CSSM_TP_CONFIRM_REJECT = 0x2 + /* reject results of executing a + submit-retrieve function pair */ +}; + +typedef struct cssm_tp_confirm_response { + uint32 NumberOfResponses; + CSSM_TP_CONFIRM_STATUS_PTR Responses; +} CSSM_TP_CONFIRM_RESPONSE DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_TP_CONFIRM_RESPONSE_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +enum { + CSSM_ESTIMATED_TIME_UNKNOWN = -1 +}; + +enum { + CSSM_ELAPSED_TIME_UNKNOWN = -1, + CSSM_ELAPSED_TIME_COMPLETE = -2 +}; + +typedef struct cssm_tp_certissue_input { + CSSM_SUBSERVICE_UID CSPSubserviceUid; + CSSM_CL_HANDLE CLHandle; + uint32 NumberOfTemplateFields; + CSSM_FIELD_PTR SubjectCertFields; + CSSM_TP_SERVICES MoreServiceRequests; + uint32 NumberOfServiceControls; + CSSM_FIELD_PTR ServiceControls; + CSSM_ACCESS_CREDENTIALS_PTR UserCredentials; +} CSSM_TP_CERTISSUE_INPUT DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_TP_CERTISSUE_INPUT_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef uint32 CSSM_TP_CERTISSUE_STATUS; +enum { + CSSM_TP_CERTISSUE_STATUS_UNKNOWN = 0x0, + /* indeterminate */ + CSSM_TP_CERTISSUE_OK = 0x1, + /* cert issued as requested */ + CSSM_TP_CERTISSUE_OKWITHCERTMODS = 0x2, + /* cert issued but cert contents were + updated by the issuing authority */ + CSSM_TP_CERTISSUE_OKWITHSERVICEMODS = 0x3, + /* cert issued but some requested backend + services were not performed by the + issuing authority */ + CSSM_TP_CERTISSUE_REJECTED = 0x4, + /* cert was not issued due to some error + condition */ + CSSM_TP_CERTISSUE_NOT_AUTHORIZED = 0x5, + /* cert was not issued, the request was + not authorized */ + CSSM_TP_CERTISSUE_WILL_BE_REVOKED = 0x6 + /* cert was issued, but TP has initiated + a revocation of the certificate */ +}; + +typedef struct cssm_tp_certissue_output { + CSSM_TP_CERTISSUE_STATUS IssueStatus; + CSSM_CERTGROUP_PTR CertGroup; + CSSM_TP_SERVICES PerformedServiceRequests; +} CSSM_TP_CERTISSUE_OUTPUT DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_TP_CERTISSUE_OUTPUT_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef uint32 CSSM_TP_CERTCHANGE_ACTION; +enum { + CSSM_TP_CERTCHANGE_NONE = 0x0, /* no change */ + CSSM_TP_CERTCHANGE_REVOKE = 0x1, /* Revoke the certificate */ +/* This action type indicates a request to revoke a single + certificate. Notice of the revocation operation remains + in affect until the certificate itself expires. Revocation + should be used to permanently remove a certificate from use. */ + CSSM_TP_CERTCHANGE_HOLD = 0x2, /* Hold/suspend the certificate */ +/* This action type indicates a request to suspend a + single certificate. A suspension operation implies + that the requester intends, at some time in the future, + to request that the certificate be released from hold, + making it available for use again. Placing a hold on + a certificate does not obligate the requester to + request a release. In practice, a certificate may + remain on hold until the certificate itself expires. + Revocation should be used to permanently remove a + certificate from use. */ + CSSM_TP_CERTCHANGE_RELEASE = 0x3 /* Release the held certificate */ +/* This action type indicates a request to release a + single certificate currently on hold. A release + operation makes a certificate available for use again. + Revocation should be used to permanently remove a + certificate from use. */ +}; + +typedef uint32 CSSM_TP_CERTCHANGE_REASON; +enum { + CSSM_TP_CERTCHANGE_REASON_UNKNOWN = 0x0, + /* unspecified */ + CSSM_TP_CERTCHANGE_REASON_KEYCOMPROMISE = 0x1, + /* Subject key believed to be compromised */ + CSSM_TP_CERTCHANGE_REASON_CACOMPROMISE = 0x2, + /* CA’s key believed to be compromised */ + CSSM_TP_CERTCHANGE_REASON_CEASEOPERATION = 0x3, + /* certificate holder ceases operation under + the jurisdiction of this certificate */ + CSSM_TP_CERTCHANGE_REASON_AFFILIATIONCHANGE = 0x4, + /* certificate holder has moved from this + jurisdiction */ + CSSM_TP_CERTCHANGE_REASON_SUPERCEDED = 0x5, + /* certificate holder as issued a new, superceding + certificate */ + CSSM_TP_CERTCHANGE_REASON_SUSPECTEDCOMPROMISE = 0x6, + /* certificate could be compromised */ + CSSM_TP_CERTCHANGE_REASON_HOLDRELEASE = 0x7 + /* certificate holder resumes operation under the + jurisdiction of this certificate */ +}; + +typedef struct cssm_tp_certchange_input { + CSSM_TP_CERTCHANGE_ACTION Action; + CSSM_TP_CERTCHANGE_REASON Reason; + CSSM_CL_HANDLE CLHandle; + CSSM_DATA_PTR Cert; + CSSM_FIELD_PTR ChangeInfo; + CSSM_TIMESTRING StartTime; + CSSM_ACCESS_CREDENTIALS_PTR CallerCredentials; +} CSSM_TP_CERTCHANGE_INPUT DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_TP_CERTCHANGE_INPUT_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef uint32 CSSM_TP_CERTCHANGE_STATUS; +enum { + CSSM_TP_CERTCHANGE_STATUS_UNKNOWN = 0x0, + /* indeterminate */ + CSSM_TP_CERTCHANGE_OK = 0x1, + /* cert state was successfully changed + beginning at the specified time */ + CSSM_TP_CERTCHANGE_OKWITHNEWTIME = 0x2, + /* cert state was successfully changed, + at a modified effective time */ + CSSM_TP_CERTCHANGE_WRONGCA = 0x3, + /* cert state was not changed, the + selected CA is not authorized to + change the cert state */ + CSSM_TP_CERTCHANGE_REJECTED = 0x4, + /* cert state was not changed due to some + error condition */ + CSSM_TP_CERTCHANGE_NOT_AUTHORIZED = 0x5 + /* cert state was not changed, the + requester is not authorized to change + the cert state */ +}; + +typedef struct cssm_tp_certchange_output { + CSSM_TP_CERTCHANGE_STATUS ActionStatus; + CSSM_FIELD RevokeInfo; +} CSSM_TP_CERTCHANGE_OUTPUT DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_TP_CERTCHANGE_OUTPUT_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef struct cssm_tp_certverify_input { + CSSM_CL_HANDLE CLHandle; + CSSM_DATA_PTR Cert; + CSSM_TP_VERIFY_CONTEXT_PTR VerifyContext; +} CSSM_TP_CERTVERIFY_INPUT DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_TP_CERTVERIFY_INPUT_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef uint32 CSSM_TP_CERTVERIFY_STATUS; +enum { + CSSM_TP_CERTVERIFY_UNKNOWN = 0x0, + CSSM_TP_CERTVERIFY_VALID = 0x1, + CSSM_TP_CERTVERIFY_INVALID = 0x2, + CSSM_TP_CERTVERIFY_REVOKED = 0x3, + CSSM_TP_CERTVERIFY_SUSPENDED = 0x4, + CSSM_TP_CERTVERIFY_EXPIRED = 0x5, + CSSM_TP_CERTVERIFY_NOT_VALID_YET = 0x6, + CSSM_TP_CERTVERIFY_INVALID_AUTHORITY = 0x7, + CSSM_TP_CERTVERIFY_INVALID_SIGNATURE = 0x8, + CSSM_TP_CERTVERIFY_INVALID_CERT_VALUE = 0x9, + CSSM_TP_CERTVERIFY_INVALID_CERTGROUP = 0xA, + CSSM_TP_CERTVERIFY_INVALID_POLICY = 0xB, + CSSM_TP_CERTVERIFY_INVALID_POLICY_IDS = 0xC, + CSSM_TP_CERTVERIFY_INVALID_BASIC_CONSTRAINTS = 0xD, + CSSM_TP_CERTVERIFY_INVALID_CRL_DIST_PT = 0xE, + CSSM_TP_CERTVERIFY_INVALID_NAME_TREE = 0xF, + CSSM_TP_CERTVERIFY_UNKNOWN_CRITICAL_EXT = 0x10 +}; + +typedef struct cssm_tp_certverify_output { + CSSM_TP_CERTVERIFY_STATUS VerifyStatus; + uint32 NumberOfEvidence; + CSSM_EVIDENCE_PTR Evidence; +} CSSM_TP_CERTVERIFY_OUTPUT DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_TP_CERTVERIFY_OUTPUT_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef struct cssm_tp_certnotarize_input { + CSSM_CL_HANDLE CLHandle; + uint32 NumberOfFields; + CSSM_FIELD_PTR MoreFields; + CSSM_FIELD_PTR SignScope; + uint32 ScopeSize; + CSSM_TP_SERVICES MoreServiceRequests; + uint32 NumberOfServiceControls; + CSSM_FIELD_PTR ServiceControls; + CSSM_ACCESS_CREDENTIALS_PTR UserCredentials; +} CSSM_TP_CERTNOTARIZE_INPUT DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_TP_CERTNOTARIZE_INPUT_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef uint32 CSSM_TP_CERTNOTARIZE_STATUS; +enum { + CSSM_TP_CERTNOTARIZE_STATUS_UNKNOWN = 0x0, + /* indeterminate */ + CSSM_TP_CERTNOTARIZE_OK = 0x1, + /* cert fields were added and the result was + notarized as requested */ + CSSM_TP_CERTNOTARIZE_OKWITHOUTFIELDS = 0x2, + /* non-conflicting cert fields were added, + conflicting cert fields were ignored, + and the result was notarized as requested */ + CSSM_TP_CERTNOTARIZE_OKWITHSERVICEMODS = 0x3, + /* cert fields were added and the result was + notarized as requested, but some requested + backend services were not performed by the + notary */ + CSSM_TP_CERTNOTARIZE_REJECTED = 0x4, + /* cert was not notarized due to some error + condition */ + CSSM_TP_CERTNOTARIZE_NOT_AUTHORIZED = 0x5 + /* cert was not notarized, the request was + not authorized */ +}; + +typedef struct cssm_tp_certnotarize_output { + CSSM_TP_CERTNOTARIZE_STATUS NotarizeStatus; + CSSM_CERTGROUP_PTR NotarizedCertGroup; + CSSM_TP_SERVICES PerformedServiceRequests; +} CSSM_TP_CERTNOTARIZE_OUTPUT DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_TP_CERTNOTARIZE_OUTPUT_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef struct cssm_tp_certreclaim_input { + CSSM_CL_HANDLE CLHandle; + uint32 NumberOfSelectionFields; + CSSM_FIELD_PTR SelectionFields; + CSSM_ACCESS_CREDENTIALS_PTR UserCredentials; +} CSSM_TP_CERTRECLAIM_INPUT DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_TP_CERTRECLAIM_INPUT_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef uint32 CSSM_TP_CERTRECLAIM_STATUS; +enum { + CSSM_TP_CERTRECLAIM_STATUS_UNKNOWN = 0x0, + /* indeterminate */ + CSSM_TP_CERTRECLAIM_OK = 0x1, + /* a set of one or more certificates were + returned by the CA for local recovery + of the associated private key */ + CSSM_TP_CERTRECLAIM_NOMATCH = 0x2, + /* no certificates owned by the requester + were found matching the specified + selection fields */ + CSSM_TP_CERTRECLAIM_REJECTED = 0x3, + /* certificate reclamation failed due + to some error condition */ + CSSM_TP_CERTRECLAIM_NOT_AUTHORIZED = 0x4 + /* certificate reclamation was not + performed, the request was not + authorized */ +}; + +typedef struct cssm_tp_certreclaim_output { + CSSM_TP_CERTRECLAIM_STATUS ReclaimStatus; + CSSM_CERTGROUP_PTR ReclaimedCertGroup; + CSSM_LONG_HANDLE KeyCacheHandle; +} CSSM_TP_CERTRECLAIM_OUTPUT DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_TP_CERTRECLAIM_OUTPUT_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef struct cssm_tp_crlissue_input { + CSSM_CL_HANDLE CLHandle; + uint32 CrlIdentifier; + CSSM_TIMESTRING CrlThisTime; + CSSM_FIELD_PTR PolicyIdentifier; + CSSM_ACCESS_CREDENTIALS_PTR CallerCredentials; +} CSSM_TP_CRLISSUE_INPUT DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_TP_CRLISSUE_INPUT_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef uint32 CSSM_TP_CRLISSUE_STATUS; +enum { + CSSM_TP_CRLISSUE_STATUS_UNKNOWN = 0x0, + /* indeterminate */ + CSSM_TP_CRLISSUE_OK = 0x1, + /* a copy of the most current CRL was + issued as requested and the time for + issuing the next CRL is also returned */ + CSSM_TP_CRLISSUE_NOT_CURRENT = 0x2, + /* either no CRL has been issued since + the CRL identified in the request, or + it is not time to issue an updated CRL. + no CRL has been returned, but the time + for issuing the next CRL is included + in the results */ + CSSM_TP_CRLISSUE_INVALID_DOMAIN = 0x3, + /* CRL domain was not recognized or was + outside the CA jurisdiction, no CRL or + time for the next CRL has been + returned. */ + CSSM_TP_CRLISSUE_UNKNOWN_IDENTIFIER = 0x4, + /* unrecognized CRL identifier, no CRL or + time for the next CRL has been + returned. */ + CSSM_TP_CRLISSUE_REJECTED = 0x5, + /* CRL was not issued due to some error + condition, no CRL or time for the next + CRL has been returned. */ + CSSM_TP_CRLISSUE_NOT_AUTHORIZED = 0x6 + /* CRL was not issued, the request was + not authorized, no CRL or time for the + next CRL has been returned. */ +}; + +typedef struct cssm_tp_crlissue_output { + CSSM_TP_CRLISSUE_STATUS IssueStatus; + CSSM_ENCODED_CRL_PTR Crl; + CSSM_TIMESTRING CrlNextTime; +} CSSM_TP_CRLISSUE_OUTPUT DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_TP_CRLISSUE_OUTPUT_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef uint32 CSSM_TP_FORM_TYPE; +enum { + CSSM_TP_FORM_TYPE_GENERIC = 0x0, + CSSM_TP_FORM_TYPE_REGISTRATION = 0x1 +}; + +/* Data Types for Certificate Library Services */ + +typedef uint32 CSSM_CL_TEMPLATE_TYPE; +enum { + CSSM_CL_TEMPLATE_INTERMEDIATE_CERT = 1, + /* for X509 certificates, a fully-formed + encoded certificate with empty signature field */ + CSSM_CL_TEMPLATE_PKIX_CERTTEMPLATE = 2 + /* as defined in RFC2511, section 5 CertTemplate */ +}; + +typedef uint32 CSSM_CERT_BUNDLE_TYPE; +enum { + CSSM_CERT_BUNDLE_UNKNOWN = 0x00, + CSSM_CERT_BUNDLE_CUSTOM = 0x01, + CSSM_CERT_BUNDLE_PKCS7_SIGNED_DATA = 0x02, + CSSM_CERT_BUNDLE_PKCS7_SIGNED_ENVELOPED_DATA = 0x03, + CSSM_CERT_BUNDLE_PKCS12 = 0x04, + CSSM_CERT_BUNDLE_PFX = 0x05, + CSSM_CERT_BUNDLE_SPKI_SEQUENCE = 0x06, + CSSM_CERT_BUNDLE_PGP_KEYRING = 0x07, + CSSM_CERT_BUNDLE_LAST = 0x7FFF, + /* Applications wishing to define their own custom certificate + bundle type should define and publicly document a uint32 + value greater than CSSM_CL_CUSTOM_CERT_BUNDLE_TYPE */ + CSSM_CL_CUSTOM_CERT_BUNDLE_TYPE = 0x8000 +}; + +typedef uint32 CSSM_CERT_BUNDLE_ENCODING; +enum { + CSSM_CERT_BUNDLE_ENCODING_UNKNOWN = 0x00, + CSSM_CERT_BUNDLE_ENCODING_CUSTOM = 0x01, + CSSM_CERT_BUNDLE_ENCODING_BER = 0x02, + CSSM_CERT_BUNDLE_ENCODING_DER = 0x03, + CSSM_CERT_BUNDLE_ENCODING_SEXPR = 0x04, + CSSM_CERT_BUNDLE_ENCODING_PGP = 0x05 +}; + +typedef struct cssm_cert_bundle_header { + CSSM_CERT_BUNDLE_TYPE BundleType; + CSSM_CERT_BUNDLE_ENCODING BundleEncoding; +} CSSM_CERT_BUNDLE_HEADER DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_CERT_BUNDLE_HEADER_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef struct cssm_cert_bundle { + CSSM_CERT_BUNDLE_HEADER BundleHeader; + CSSM_DATA Bundle; +} CSSM_CERT_BUNDLE DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_CERT_BUNDLE_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +enum { + CSSM_FIELDVALUE_COMPLEX_DATA_TYPE = 0xFFFFFFFF +}; + +/* Data Types for Data Storage Library Services */ + +typedef uint32 CSSM_DB_ATTRIBUTE_NAME_FORMAT, *CSSM_DB_ATTRIBUTE_NAME_FORMAT_PTR; +enum { + CSSM_DB_ATTRIBUTE_NAME_AS_STRING = 0, + CSSM_DB_ATTRIBUTE_NAME_AS_OID = 1, + CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER = 2 +}; + +typedef uint32 CSSM_DB_ATTRIBUTE_FORMAT, *CSSM_DB_ATTRIBUTE_FORMAT_PTR; +enum { + CSSM_DB_ATTRIBUTE_FORMAT_STRING = 0, + CSSM_DB_ATTRIBUTE_FORMAT_SINT32 = 1, + CSSM_DB_ATTRIBUTE_FORMAT_UINT32 = 2, + CSSM_DB_ATTRIBUTE_FORMAT_BIG_NUM = 3, + CSSM_DB_ATTRIBUTE_FORMAT_REAL = 4, + CSSM_DB_ATTRIBUTE_FORMAT_TIME_DATE = 5, + CSSM_DB_ATTRIBUTE_FORMAT_BLOB = 6, + CSSM_DB_ATTRIBUTE_FORMAT_MULTI_UINT32 = 7, + CSSM_DB_ATTRIBUTE_FORMAT_COMPLEX = 8 +}; + +typedef struct cssm_db_attribute_info { + CSSM_DB_ATTRIBUTE_NAME_FORMAT AttributeNameFormat; + union cssm_db_attribute_label { + char *AttributeName; /* e.g., "record label" */ + CSSM_OID AttributeOID; /* e.g., CSSMOID_RECORDLABEL */ + uint32 AttributeID; /* e.g., FOUR_CHAR_CODE('recl') */ + } Label; + CSSM_DB_ATTRIBUTE_FORMAT AttributeFormat; +} CSSM_DB_ATTRIBUTE_INFO, *CSSM_DB_ATTRIBUTE_INFO_PTR; + +typedef struct cssm_db_attribute_data { + CSSM_DB_ATTRIBUTE_INFO Info; + uint32 NumberOfValues; + CSSM_DATA_PTR Value; +} CSSM_DB_ATTRIBUTE_DATA DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_DB_ATTRIBUTE_DATA_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef uint32 CSSM_DB_RECORDTYPE; +enum { + /* Schema Management Name Space Range Definition*/ + CSSM_DB_RECORDTYPE_SCHEMA_START = 0x00000000, + CSSM_DB_RECORDTYPE_SCHEMA_END = CSSM_DB_RECORDTYPE_SCHEMA_START + 4, + /* Open Group Application Name Space Range Definition*/ + CSSM_DB_RECORDTYPE_OPEN_GROUP_START = 0x0000000A, + CSSM_DB_RECORDTYPE_OPEN_GROUP_END = CSSM_DB_RECORDTYPE_OPEN_GROUP_START + 8, + /* Industry At Large Application Name Space Range Definition */ + CSSM_DB_RECORDTYPE_APP_DEFINED_START = 0x80000000, + CSSM_DB_RECORDTYPE_APP_DEFINED_END = 0xffffffff, + /* Record Types defined in the Schema Management Name Space */ + CSSM_DL_DB_SCHEMA_INFO = CSSM_DB_RECORDTYPE_SCHEMA_START + 0, + CSSM_DL_DB_SCHEMA_INDEXES = CSSM_DB_RECORDTYPE_SCHEMA_START + 1, + CSSM_DL_DB_SCHEMA_ATTRIBUTES = CSSM_DB_RECORDTYPE_SCHEMA_START + 2, + CSSM_DL_DB_SCHEMA_PARSING_MODULE = CSSM_DB_RECORDTYPE_SCHEMA_START + 3, + /* Record Types defined in the Open Group Application Name Space */ + CSSM_DL_DB_RECORD_ANY = CSSM_DB_RECORDTYPE_OPEN_GROUP_START + 0, + CSSM_DL_DB_RECORD_CERT = CSSM_DB_RECORDTYPE_OPEN_GROUP_START + 1, + CSSM_DL_DB_RECORD_CRL = CSSM_DB_RECORDTYPE_OPEN_GROUP_START + 2, + CSSM_DL_DB_RECORD_POLICY = CSSM_DB_RECORDTYPE_OPEN_GROUP_START + 3, + CSSM_DL_DB_RECORD_GENERIC = CSSM_DB_RECORDTYPE_OPEN_GROUP_START + 4, + CSSM_DL_DB_RECORD_PUBLIC_KEY = CSSM_DB_RECORDTYPE_OPEN_GROUP_START + 5, + CSSM_DL_DB_RECORD_PRIVATE_KEY = CSSM_DB_RECORDTYPE_OPEN_GROUP_START + 6, + CSSM_DL_DB_RECORD_SYMMETRIC_KEY = CSSM_DB_RECORDTYPE_OPEN_GROUP_START + 7, + CSSM_DL_DB_RECORD_ALL_KEYS = CSSM_DB_RECORDTYPE_OPEN_GROUP_START + 8 +}; + +enum { + CSSM_DB_CERT_USE_TRUSTED = 0x00000001, /* application-defined as trusted */ + CSSM_DB_CERT_USE_SYSTEM = 0x00000002, /* the CSSM system cert */ + CSSM_DB_CERT_USE_OWNER = 0x00000004, /* private key owned by system user*/ + CSSM_DB_CERT_USE_REVOKED = 0x00000008, /* revoked cert -15913 used w CRL APIs */ + CSSM_DB_CERT_USE_SIGNING = 0x00000010, /* use cert for signing only */ + CSSM_DB_CERT_USE_PRIVACY = 0x00000020 /* use cert for confidentiality only */ +}; + +typedef struct cssm_db_record_attribute_info { + CSSM_DB_RECORDTYPE DataRecordType; + uint32 NumberOfAttributes; + CSSM_DB_ATTRIBUTE_INFO_PTR AttributeInfo; +} CSSM_DB_RECORD_ATTRIBUTE_INFO DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_DB_RECORD_ATTRIBUTE_INFO_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef struct cssm_db_record_attribute_data { + CSSM_DB_RECORDTYPE DataRecordType; + uint32 SemanticInformation; + uint32 NumberOfAttributes; + CSSM_DB_ATTRIBUTE_DATA_PTR AttributeData; +} CSSM_DB_RECORD_ATTRIBUTE_DATA DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef struct cssm_db_parsing_module_info { + CSSM_DB_RECORDTYPE RecordType; + CSSM_SUBSERVICE_UID ModuleSubserviceUid; +} CSSM_DB_PARSING_MODULE_INFO DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_DB_PARSING_MODULE_INFO_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef uint32 CSSM_DB_INDEX_TYPE; +enum { + CSSM_DB_INDEX_UNIQUE = 0, + CSSM_DB_INDEX_NONUNIQUE = 1 +}; + +typedef uint32 CSSM_DB_INDEXED_DATA_LOCATION; +enum { + CSSM_DB_INDEX_ON_UNKNOWN = 0, + CSSM_DB_INDEX_ON_ATTRIBUTE = 1, + CSSM_DB_INDEX_ON_RECORD = 2 +}; + +typedef struct cssm_db_index_info { + CSSM_DB_INDEX_TYPE IndexType; + CSSM_DB_INDEXED_DATA_LOCATION IndexedDataLocation; + CSSM_DB_ATTRIBUTE_INFO Info; +} CSSM_DB_INDEX_INFO DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_DB_INDEX_INFO_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef struct cssm_db_unique_record { + CSSM_DB_INDEX_INFO RecordLocator; + CSSM_DATA RecordIdentifier; +} CSSM_DB_UNIQUE_RECORD DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_DB_UNIQUE_RECORD_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef struct cssm_db_record_index_info { + CSSM_DB_RECORDTYPE DataRecordType; + uint32 NumberOfIndexes; + CSSM_DB_INDEX_INFO_PTR IndexInfo; +} CSSM_DB_RECORD_INDEX_INFO DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_DB_RECORD_INDEX_INFO_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef uint32 CSSM_DB_ACCESS_TYPE, *CSSM_DB_ACCESS_TYPE_PTR; +enum { + CSSM_DB_ACCESS_READ = 0x00001, + CSSM_DB_ACCESS_WRITE = 0x00002, + CSSM_DB_ACCESS_PRIVILEGED = 0x00004 /* versus user mode */ +}; + +typedef uint32 CSSM_DB_MODIFY_MODE; +enum { + CSSM_DB_MODIFY_ATTRIBUTE_NONE = 0, + CSSM_DB_MODIFY_ATTRIBUTE_ADD = CSSM_DB_MODIFY_ATTRIBUTE_NONE + 1, + CSSM_DB_MODIFY_ATTRIBUTE_DELETE = CSSM_DB_MODIFY_ATTRIBUTE_NONE + 2, + CSSM_DB_MODIFY_ATTRIBUTE_REPLACE = CSSM_DB_MODIFY_ATTRIBUTE_NONE + 3 +}; + +typedef struct cssm_dbinfo { + /* meta information about each record type stored in this + data store including meta information about record + attributes and indexes */ + uint32 NumberOfRecordTypes; + CSSM_DB_PARSING_MODULE_INFO_PTR DefaultParsingModules; + CSSM_DB_RECORD_ATTRIBUTE_INFO_PTR RecordAttributeNames; + CSSM_DB_RECORD_INDEX_INFO_PTR RecordIndexes; + /* access restrictions for opening this data store */ + CSSM_BOOL IsLocal; + char *AccessPath; /* URL, dir path, etc. */ + void *Reserved; +} CSSM_DBINFO DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_DBINFO_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef uint32 CSSM_DB_OPERATOR, *CSSM_DB_OPERATOR_PTR; +enum { + CSSM_DB_EQUAL = 0, + CSSM_DB_NOT_EQUAL = 1, + CSSM_DB_LESS_THAN = 2, + CSSM_DB_GREATER_THAN = 3, + CSSM_DB_CONTAINS = 4, + CSSM_DB_CONTAINS_INITIAL_SUBSTRING = 5, + CSSM_DB_CONTAINS_FINAL_SUBSTRING = 6 +}; + +typedef uint32 CSSM_DB_CONJUNCTIVE, *CSSM_DB_CONJUNCTIVE_PTR; +enum { + CSSM_DB_NONE = 0, + CSSM_DB_AND = 1, + CSSM_DB_OR = 2 +}; + +typedef struct cssm_selection_predicate { + CSSM_DB_OPERATOR DbOperator; + CSSM_DB_ATTRIBUTE_DATA Attribute; +} CSSM_SELECTION_PREDICATE DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_SELECTION_PREDICATE_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +enum { + CSSM_QUERY_TIMELIMIT_NONE = 0 +}; + +enum { + CSSM_QUERY_SIZELIMIT_NONE = 0 +}; + +typedef struct cssm_query_limits { + uint32 TimeLimit; /* in seconds */ + uint32 SizeLimit; /* max. number of records to return */ +} CSSM_QUERY_LIMITS DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_QUERY_LIMITS_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef uint32 CSSM_QUERY_FLAGS; +enum { + CSSM_QUERY_RETURN_DATA = 0x01 +}; + +typedef struct cssm_query { + CSSM_DB_RECORDTYPE RecordType; + CSSM_DB_CONJUNCTIVE Conjunctive; + uint32 NumSelectionPredicates; + CSSM_SELECTION_PREDICATE_PTR SelectionPredicate; + CSSM_QUERY_LIMITS QueryLimits; + CSSM_QUERY_FLAGS QueryFlags; +} CSSM_QUERY DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_QUERY_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef uint32 CSSM_DLTYPE, *CSSM_DLTYPE_PTR; +enum { + CSSM_DL_UNKNOWN = 0, + CSSM_DL_CUSTOM = 1, + CSSM_DL_LDAP = 2, + CSSM_DL_ODBC = 3, + CSSM_DL_PKCS11 = 4, + CSSM_DL_FFS = 5, /* flat file system */ + CSSM_DL_MEMORY = 6, + CSSM_DL_REMOTEDIR = 7 +}; + +typedef void *CSSM_DL_CUSTOM_ATTRIBUTES; +typedef void *CSSM_DL_LDAP_ATTRIBUTES; +typedef void *CSSM_DL_ODBC_ATTRIBUTES; +typedef void *CSSM_DL_FFS_ATTRIBUTES; + +typedef struct cssm_dl_pkcs11_attributes { + uint32 DeviceAccessFlags; +} *CSSM_DL_PKCS11_ATTRIBUTE, *CSSM_DL_PKCS11_ATTRIBUTE_PTR; + +enum { + CSSM_DB_DATASTORES_UNKNOWN = 0xFFFFFFFF +}; + +typedef struct cssm_name_list { + uint32 NumStrings; + char **String; +} CSSM_NAME_LIST DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_NAME_LIST_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef uint32 CSSM_DB_RETRIEVAL_MODES; +enum { + CSSM_DB_TRANSACTIONAL_MODE = 0, + CSSM_DB_FILESYSTEMSCAN_MODE = 1 +}; + +typedef struct cssm_db_schema_attribute_info { + uint32 AttributeId; + char *AttributeName; + CSSM_OID AttributeNameID; + CSSM_DB_ATTRIBUTE_FORMAT DataType; +} CSSM_DB_SCHEMA_ATTRIBUTE_INFO DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_DB_SCHEMA_ATTRIBUTE_INFO_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef struct cssm_db_schema_index_info { + uint32 AttributeId; + uint32 IndexId; + CSSM_DB_INDEX_TYPE IndexType; + CSSM_DB_INDEXED_DATA_LOCATION IndexedDataLocation; +} CSSM_DB_SCHEMA_INDEX_INFO DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_DB_SCHEMA_INDEX_INFO_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +#ifdef __cplusplus +} +#endif + +#endif /* _CSSMTYPE_H_ */ diff --git a/libsecurity_cssm/lib/eisl.h b/libsecurity_cssm/lib/eisl.h new file mode 100644 index 00000000..48d44fca --- /dev/null +++ b/libsecurity_cssm/lib/eisl.h @@ -0,0 +1,326 @@ +/* + * Copyright (c) 1999-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@ + * + * eisl.h -- Embedded Integrity Services Library Interface + */ + +#ifndef _EISL_H_ +#define _EISL_H_ 1 + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Data Types for Embedded Integrity Services Library */ + +typedef const void *ISL_ITERATOR_PTR; + +typedef const void *ISL_VERIFIED_SIGNATURE_ROOT_PTR; + +typedef const void *ISL_VERIFIED_CERTIFICATE_CHAIN_PTR; + +typedef const void *ISL_VERIFIED_CERTIFICATE_PTR; + +typedef const void *ISL_MANIFEST_SECTION_PTR; + +typedef const void *ISL_VERIFIED_MODULE_PTR; + +typedef void (*ISL_FUNCTION_PTR)(void); + +typedef struct isl_data { + CSSM_SIZE Length; /* in bytes */ + uint8 *Data; +} ISL_DATA, *ISL_DATA_PTR; + +typedef struct isl_const_data { + CSSM_SIZE Length; /* in bytes */ + const uint8 *Data; +} ISL_CONST_DATA, *ISL_CONST_DATA_PTR; + +typedef enum isl_status { + ISL_OK = 0, + ISL_FAIL = -1 +} ISL_STATUS; + + +/* Embedded Integrity Services Library Functions */ + +ISL_VERIFIED_MODULE_PTR +EISL_SelfCheck (); + +ISL_VERIFIED_MODULE_PTR +EISL_VerifyAndLoadModuleAndCredentialData (const ISL_CONST_DATA CredentialsImage, + const ISL_CONST_DATA ModuleSearchPath, + const ISL_CONST_DATA Name, + const ISL_CONST_DATA Signer, + const ISL_CONST_DATA PublicKey); + +ISL_VERIFIED_MODULE_PTR +EISL_VerifyAndLoadModuleAndCredentialDataWithCertificate (const ISL_CONST_DATA CredentialsImage, + const ISL_CONST_DATA ModuleSearchPath, + const ISL_CONST_DATA Name, + const ISL_CONST_DATA Signer, + const ISL_CONST_DATA Certificate); + +ISL_VERIFIED_MODULE_PTR +EISL_VerifyAndLoadModuleAndCredentials (ISL_CONST_DATA Credentials, + ISL_CONST_DATA Name, + ISL_CONST_DATA Signer, + ISL_CONST_DATA PublicKey); + +ISL_VERIFIED_MODULE_PTR +EISL_VerifyAndLoadModuleAndCredentialsWithCertificate (const ISL_CONST_DATA Credentials, + const ISL_CONST_DATA Name, + const ISL_CONST_DATA Signer, + const ISL_CONST_DATA Certificate); + +ISL_VERIFIED_MODULE_PTR +EISL_VerifyLoadedModuleAndCredentialData (const ISL_CONST_DATA CredentialsImage, + const ISL_CONST_DATA ModuleSearchPath, + const ISL_CONST_DATA Name, + const ISL_CONST_DATA Signer, + const ISL_CONST_DATA PublicKey); + +ISL_VERIFIED_MODULE_PTR +EISL_VerifyLoadedModuleAndCredentialDataWithCertificate (const ISL_CONST_DATA CredentialsImage, + const ISL_CONST_DATA ModuleSearchPath, + const ISL_CONST_DATA Name, + const ISL_CONST_DATA Signer, + const ISL_CONST_DATA Certificate); + +ISL_VERIFIED_MODULE_PTR +EISL_VerifyLoadedModuleAndCredentials (ISL_CONST_DATA Credentials, + ISL_CONST_DATA Name, + ISL_CONST_DATA Signer, + ISL_CONST_DATA PublicKey); + +ISL_VERIFIED_MODULE_PTR +EISL_VerifyLoadedModuleAndCredentialsWithCertificate (const ISL_CONST_DATA Credentials, + const ISL_CONST_DATA Name, + const ISL_CONST_DATA Signer, + const ISL_CONST_DATA Certificate); + +ISL_VERIFIED_CERTIFICATE_CHAIN_PTR +EISL_GetCertificateChain (ISL_VERIFIED_MODULE_PTR Module); + +uint32 +EISL_ContinueVerification (ISL_VERIFIED_MODULE_PTR Module, + uint32 WorkFactor); + +ISL_VERIFIED_MODULE_PTR +EISL_DuplicateVerifiedModulePtr (ISL_VERIFIED_MODULE_PTR Module); + +ISL_STATUS +EISL_RecycleVerifiedModuleCredentials (ISL_VERIFIED_MODULE_PTR Verification); + + +/* Signature Root Methods */ + +ISL_VERIFIED_SIGNATURE_ROOT_PTR +EISL_CreateVerifiedSignatureRootWithCredentialData (const ISL_CONST_DATA CredentialsImage, + const ISL_CONST_DATA ModuleSearchPath, + const ISL_CONST_DATA Signer, + const ISL_CONST_DATA PublicKey); + +ISL_VERIFIED_SIGNATURE_ROOT_PTR +EISL_CreateVerifiedSignatureRootWithCredentialDataAndCertificate (const ISL_CONST_DATA CredentialsImage, + const ISL_CONST_DATA ModuleSearchPath, + ISL_VERIFIED_CERTIFICATE_PTR Cert); + +ISL_VERIFIED_SIGNATURE_ROOT_PTR +EISL_CreateVerfiedSignatureRoot (ISL_CONST_DATA Credentials, + ISL_CONST_DATA Signer, + ISL_CONST_DATA PublicKey); + +ISL_VERIFIED_SIGNATURE_ROOT_PTR +EISL_CreateVerfiedSignatureRootWithCertificate (ISL_CONST_DATA Credentials, + ISL_VERIFIED_CERTIFICATE_PTR Cert); + +ISL_MANIFEST_SECTION_PTR +EISL_FindManifestSection (ISL_VERIFIED_SIGNATURE_ROOT_PTR Root, + ISL_CONST_DATA Name); + +ISL_ITERATOR_PTR +EISL_CreateManifestSectionEnumerator (ISL_VERIFIED_SIGNATURE_ROOT_PTR Root); + +ISL_MANIFEST_SECTION_PTR +EISL_GetNextManifestSection (ISL_ITERATOR_PTR Iterator); + +ISL_STATUS +EISL_RecycleManifestSectionEnumerator (ISL_ITERATOR_PTR Iterator); + +ISL_STATUS +EISL_FindManifestAttribute (ISL_VERIFIED_SIGNATURE_ROOT_PTR Context, + ISL_CONST_DATA Name, + ISL_CONST_DATA_PTR Value); + +ISL_ITERATOR_PTR +EISL_CreateManifestAttributeEnumerator (ISL_VERIFIED_SIGNATURE_ROOT_PTR Context); + +ISL_STATUS +EISL_FindSignerInfoAttribute (ISL_VERIFIED_SIGNATURE_ROOT_PTR Context, + ISL_CONST_DATA Name, + ISL_CONST_DATA_PTR Value); + +ISL_ITERATOR_PTR +EISL_CreateSignerInfoAttributeEnumerator (ISL_VERIFIED_SIGNATURE_ROOT_PTR Context); + +ISL_STATUS +EISL_GetNextAttribute (ISL_ITERATOR_PTR Iterator, + ISL_CONST_DATA_PTR Name, + ISL_CONST_DATA_PTR Value); + +ISL_STATUS +EISL_RecycleAttributeEnumerator (ISL_ITERATOR_PTR Iterator); + +ISL_STATUS +EISL_FindSignatureAttribute (ISL_VERIFIED_SIGNATURE_ROOT_PTR Root, + ISL_CONST_DATA Name, + ISL_CONST_DATA_PTR Value); + +ISL_ITERATOR_PTR +EISL_CreateSignatureAttributeEnumerator (ISL_VERIFIED_SIGNATURE_ROOT_PTR Root); + +ISL_STATUS +EISL_GetNextSignatureAttribute (ISL_ITERATOR_PTR Iterator, + ISL_CONST_DATA_PTR Name, + ISL_CONST_DATA_PTR Value); + +ISL_STATUS +EISL_RecycleSignatureAttributeEnumerator (ISL_ITERATOR_PTR Iterator); + +ISL_STATUS +EISL_RecycleVerifiedSignatureRoot (ISL_VERIFIED_SIGNATURE_ROOT_PTR Root); + + +/* Certificate Chain Methods */ + +const ISL_VERIFIED_CERTIFICATE_CHAIN_PTR +EISL_CreateCertificateChainWithCredentialData (const ISL_CONST_DATA RootIssuer, + const ISL_CONST_DATA PublicKey, + const ISL_CONST_DATA CredentialsImage, + const ISL_CONST_DATA ModuleSearchPath); + +ISL_VERIFIED_CERTIFICATE_CHAIN_PTR +EISL_CreateCertificateChainWithCredentialDataAndCertificate (const ISL_CONST_DATA Certificate, + const ISL_CONST_DATA CredentialsImage, + const ISL_CONST_DATA ModuleSearchPath); + +ISL_VERIFIED_CERTIFICATE_CHAIN_PTR +EISL_CreateCertificateChain (ISL_CONST_DATA RootIssuer, + ISL_CONST_DATA PublicKey, + ISL_CONST_DATA Credential); + +ISL_VERIFIED_CERTIFICATE_CHAIN_PTR +EISL_CreateCertificateChainWithCertificate (const ISL_CONST_DATA Certificate, + const ISL_CONST_DATA Credential); + +uint32 +EISL_CopyCertificateChain (ISL_VERIFIED_CERTIFICATE_CHAIN_PTR Verification, + ISL_VERIFIED_CERTIFICATE_PTR Certs[], + uint32 MaxCertificates); + +ISL_STATUS +EISL_RecycleVerifiedCertificateChain (ISL_VERIFIED_CERTIFICATE_CHAIN_PTR Chain); + + +/* Certificate Attribute Methods */ + +ISL_STATUS +EISL_FindCertificateAttribute (ISL_VERIFIED_CERTIFICATE_PTR Cert, + ISL_CONST_DATA Name, + ISL_CONST_DATA_PTR Value); + +ISL_ITERATOR_PTR +EISL_CreateCertificateAttributeEnumerator (ISL_VERIFIED_CERTIFICATE_PTR Cert); + +ISL_STATUS +EISL_GetNextCertificateAttribute (ISL_ITERATOR_PTR CertIterator, + ISL_CONST_DATA_PTR Name, + ISL_CONST_DATA_PTR Value); + +ISL_STATUS +EISL_RecycleCertificateAttributeEnumerator (ISL_ITERATOR_PTR CertIterator); + + +/* Manifest Section Object Methods */ + +ISL_VERIFIED_SIGNATURE_ROOT_PTR +EISL_GetManifestSignatureRoot (ISL_MANIFEST_SECTION_PTR Section); + +ISL_VERIFIED_MODULE_PTR +EISL_VerifyAndLoadModule (ISL_MANIFEST_SECTION_PTR Section); + +ISL_VERIFIED_MODULE_PTR +EISL_VerifyLoadedModule (ISL_MANIFEST_SECTION_PTR Section); + +ISL_STATUS +EISL_FindManifestSectionAttribute (ISL_MANIFEST_SECTION_PTR Section, + ISL_CONST_DATA Name, + ISL_CONST_DATA_PTR Value); + +ISL_ITERATOR_PTR +EISL_CreateManifestSectionAttributeEnumerator (ISL_MANIFEST_SECTION_PTR Section); + +ISL_STATUS +EISL_GetNextManifestSectionAttribute (ISL_ITERATOR_PTR Iterator, + ISL_CONST_DATA_PTR Name, + ISL_CONST_DATA_PTR Value); + +ISL_STATUS +EISL_RecycleManifestSectionAttributeEnumerator (ISL_ITERATOR_PTR Iterator); + +ISL_MANIFEST_SECTION_PTR +EISL_GetModuleManifestSection (ISL_VERIFIED_MODULE_PTR Module); + + +/* Secure Linkage Services */ + +ISL_FUNCTION_PTR +EISL_LocateProcedureAddress (ISL_VERIFIED_MODULE_PTR Module, + ISL_CONST_DATA Name); + +#ifdef MACOSX +#define EISL_GetReturnAddress(Address) \ +{\ + /* Platform specific code in here */ +} +#endif + +ISL_STATUS +EISL_CheckAddressWithinModule (ISL_VERIFIED_MODULE_PTR Verification, + ISL_FUNCTION_PTR Address); + +ISL_STATUS +EISL_CheckDataAddressWithinModule (ISL_VERIFIED_MODULE_PTR Verification, + const void *Address); + +void * +EISL_GetLibHandle (ISL_VERIFIED_MODULE_PTR Verification); + +#ifdef __cplusplus +} +#endif + +#endif /* _EISL_H_ */ diff --git a/libsecurity_cssm/lib/emmspi.h b/libsecurity_cssm/lib/emmspi.h new file mode 100644 index 00000000..4a8b4247 --- /dev/null +++ b/libsecurity_cssm/lib/emmspi.h @@ -0,0 +1,94 @@ +/* + * Copyright (c) 1999-2001,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@ + * + * emmspi.h -- Service Provider Interface for Elective Module Managers + */ + +#ifndef _EMMSPI_H_ +#define _EMMSPI_H_ 1 + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct cssm_state_funcs { + CSSM_RETURN (CSSMAPI *cssm_GetAttachFunctions) + (CSSM_MODULE_HANDLE hAddIn, + CSSM_SERVICE_MASK AddinType, + void **SPFunctions, + CSSM_GUID_PTR Guid, + CSSM_BOOL *Serialized); + CSSM_RETURN (CSSMAPI *cssm_ReleaseAttachFunctions) + (CSSM_MODULE_HANDLE hAddIn); + CSSM_RETURN (CSSMAPI *cssm_GetAppMemoryFunctions) + (CSSM_MODULE_HANDLE hAddIn, + CSSM_UPCALLS_PTR UpcallTable); + CSSM_RETURN (CSSMAPI *cssm_IsFuncCallValid) + (CSSM_MODULE_HANDLE hAddin, + CSSM_PROC_ADDR SrcAddress, + CSSM_PROC_ADDR DestAddress, + CSSM_PRIVILEGE InPriv, + CSSM_PRIVILEGE *OutPriv, + CSSM_BITMASK Hints, + CSSM_BOOL *IsOK); + CSSM_RETURN (CSSMAPI *cssm_DeregisterManagerServices) + (const CSSM_GUID *GUID); + CSSM_RETURN (CSSMAPI *cssm_DeliverModuleManagerEvent) + (const CSSM_MANAGER_EVENT_NOTIFICATION *EventDescription); +} CSSM_STATE_FUNCS DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_STATE_FUNCS_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef struct cssm_manager_registration_info { + /* loading, unloading, dispatch table, and event notification */ + CSSM_RETURN (CSSMAPI *Initialize) + (uint32 VerMajor, + uint32 VerMinor); + CSSM_RETURN (CSSMAPI *Terminate) (void); + CSSM_RETURN (CSSMAPI *RegisterDispatchTable) + (CSSM_STATE_FUNCS_PTR CssmStateCallTable); + CSSM_RETURN (CSSMAPI *DeregisterDispatchTable) (void); + CSSM_RETURN (CSSMAPI *EventNotifyManager) + (const CSSM_MANAGER_EVENT_NOTIFICATION *EventDescription); + CSSM_RETURN (CSSMAPI *RefreshFunctionTable) + (CSSM_FUNC_NAME_ADDR_PTR FuncNameAddrPtr, + uint32 NumOfFuncNameAddr); +} CSSM_MANAGER_REGISTRATION_INFO DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_MANAGER_REGISTRATION_INFO_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +enum { + CSSM_HINT_NONE = 0, + CSSM_HINT_ADDRESS_APP = 1 << 0, + CSSM_HINT_ADDRESS_SP = 1 << 1 +}; + +CSSM_RETURN CSSMAPI +ModuleManagerAuthenticate (CSSM_KEY_HIERARCHY KeyHierarchy, + const CSSM_GUID *CssmGuid, + const CSSM_GUID *AppGuid, + CSSM_MANAGER_REGISTRATION_INFO_PTR FunctionTable) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +#ifdef __cplusplus +} +#endif + +#endif /* _EMMSPI_H_ */ diff --git a/libsecurity_cssm/lib/emmtype.h b/libsecurity_cssm/lib/emmtype.h new file mode 100644 index 00000000..3ed3a60b --- /dev/null +++ b/libsecurity_cssm/lib/emmtype.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 1999-2001,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@ + * + * emmtype.h -- Data Structures for Elective Module Managers + */ + +#ifndef _EMMTYPE_H_ +#define _EMMTYPE_H_ 1 + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define CSSM_HINT_CALLBACK (1) + +typedef uint32 CSSM_MANAGER_EVENT_TYPES; +#define CSSM_MANAGER_SERVICE_REQUEST 1 +#define CSSM_MANAGER_REPLY 2 + +typedef struct cssm_manager_event_notification { + CSSM_SERVICE_MASK DestinationModuleManagerType; + CSSM_SERVICE_MASK SourceModuleManagerType; + CSSM_MANAGER_EVENT_TYPES Event; + uint32 EventId; + CSSM_DATA EventData; +} CSSM_MANAGER_EVENT_NOTIFICATION DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_MANAGER_EVENT_NOTIFICATION_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +#ifdef __cplusplus +} +#endif + +#endif /* _EMMTYPE_H_ */ diff --git a/libsecurity_cssm/lib/generator.cfg b/libsecurity_cssm/lib/generator.cfg new file mode 100644 index 00000000..8ec67fa2 --- /dev/null +++ b/libsecurity_cssm/lib/generator.cfg @@ -0,0 +1,13 @@ +# +# transition.cfg +# +# Configuration file for generating the CSSM API/SPI transition layer. +# + + +# +# Functions with irregular operation that need hand-coded implementations +# +CSSM_DigestDataClone custom +CSSM_QueryKeySizeInBits custom +CSSM_GenerateAlgorithmParams custom diff --git a/libsecurity_cssm/lib/generator.mk b/libsecurity_cssm/lib/generator.mk new file mode 100644 index 00000000..55aeb165 --- /dev/null +++ b/libsecurity_cssm/lib/generator.mk @@ -0,0 +1,33 @@ +# +# Copyright (c) 2001,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@ +# +# generator.mk -- Makefile for generated files. + +$(TARGET)/cssmexports.gen $(TARGET)/funcnames.gen $(TARGET)/generator.rpt $(TARGET)/transition.gen: \ + $(SOURCEDIR)/cssmapi.h \ + $(SOURCEDIR)/cssmaci.h \ + $(SOURCEDIR)/cssmcspi.h \ + $(SOURCEDIR)/cssmdli.h \ + $(SOURCEDIR)/cssmcli.h \ + $(SOURCEDIR)/cssmtpi.h + mkdir -p $(TARGET) + /usr/bin/perl lib/generator.pl $(SOURCEDIR) $(CONFIG) $(TARGET) diff --git a/libsecurity_cssm/lib/generator.pl b/libsecurity_cssm/lib/generator.pl new file mode 100644 index 00000000..db6ad204 --- /dev/null +++ b/libsecurity_cssm/lib/generator.pl @@ -0,0 +1,250 @@ +#!/usr/bin/perl +# +# Copyright (c) 2001-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@ +# +# generator.pl - derive various and sundry C++ code from the CDSA header files +# +# Usage: +# perl generator.pl input-directory config-file output-directory +# +# Perry The Cynic, Fall 1999. +# +@API_H=("cssmapi.h"); +%SPI_H=("AC" => "cssmaci.h", "CSP" => "cssmcspi.h", "DL" => "cssmdli.h", + "CL" => "cssmcli.h", "TP" => "cssmtpi.h"); +@OIDS_H=("oidscert.h", "oidscrl.h"); +@OIDS_H2=("oidsattr.h", "oidsalg.h"); + +$SOURCEDIR=$ARGV[0]; # directory with inputs +$APICFG=$ARGV[1]; # configuration file +$TARGETDIR=$ARGV[2]; # directory for outputs + + +$TRANSITION="$TARGETDIR/transition.gen"; # C++ code for transition layer +$TABLES="$TARGETDIR/funcnames.gen"; # function name tables +$REPORT="$TARGETDIR/generator.rpt"; # report file +$EXPORTS="$TARGETDIR/cssmexports.gen"; # Exports file + +$tabs = "\t\t\t"; # argument indentation (noncritical) +$warning = "This file was automatically generated. Do not edit on penalty of futility!"; + + +# +# Parse API headers and extract function names and argument lists +# +# Jim Muprhy I added [^;]* to the end of the %formals variable to +# allow for deprecation macros. +# +$/=undef; # big gulp mode +foreach $_ (@API_H) { + open(API_H, "$SOURCEDIR/$_") or die "Cannot open $SOURCEDIR/$_: $^E"; + $_ = ; # glglgl... aaaaah + %formals = /CSSM_RETURN CSSMAPI\s*([A-Za-z_]+)\s+\(([^)]*)\)[^;]*;/gs; + while (($name, $args) = each %formals) { + $args =~ s/^.*[ *]([A-Za-z_]+,?)$/$tabs$1/gm; # remove type declarators + $args =~ s/^$tabs//o; # chop intial tabs # so now we have... + $actuals{$name} = $args; # ...an actual argument list + }; +}; +close(API_H); + + +# +# Slurp SPI headers into memory for future use +# +$/=undef; # slurp files +while (($key, $file) = each %SPI_H) { + open(SPI_H, "$SOURCEDIR/$file") or die "Cannot open $SOURCEDIR/$file: $^E"; + $spi{$key} = ; +}; +close(SPI_H); + + +# +# Open and read the configuration file +# +$/=undef; # gulp yet again +open(APICFG, $APICFG) or die "Cannot open $APICFG: $^E"; +$_=; +close(APICFG); +%config = /^\s*(\w+)\s+(.*)$/gm; + + +# +# Now we will generate the API transition layer. +# The idea here is that for each function in the API, we try to +# figure out what type of plugin it belongs to, and then look up +# its evil twin in that type's header. If that works, we generate +# a function for the transition, taking care of various oddities +# and endities in the process. +# +open(OUT, ">$TRANSITION") or die "Cannot write $TRANSITION: $^E"; +select OUT; +open(REPORT, ">$REPORT") or die "Cannot write $REPORT: $^E"; + +sub ignored { + my ($reason) = @_; + $ignored++; + print REPORT "$name $reason\n"; +}; + +print "// +// $warning +//"; + +for $name (sort keys %formals) { + $config = $config{$name}; + do { ignored "has custom implementation"; next; } if $config =~ /custom/; + + ($barename) = $name =~ /^CSSM.*_([A-Za-z]+$)/; + die "Can't fathom SPI name for $name" unless $barename; + $actuals = $actuals{$name}; + + # key off the type code in the first argument: CSSM_type_HANDLE + ($type, $handle) = $formals{$name} =~ /CSSM_([A-Z_]+)_HANDLE\s+([A-Za-z0-9_]+)/; + $type = "CSP" if $type eq "CC"; # CSP methods may have CC (context) handles + $type = "DL" if $type eq "DL_DB"; # DL methods may have DL_DB handles + $type = "KR" if $type eq "KRSP"; # KR methods have KRSP handles + $Type = $type . "Attachment"; + do { ignored "has no module type"; next; } unless defined $SPI_H{$type}; + + # $prefix will hold code to be generated before the actual call + $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) + or do { ignored "not in $SPI_H{$type}"; next; }; + + # take care of CSP calls taking context handles + $handletype = $type; + $type eq "CSP" && $actuals =~ /CCHandle/ && do { + $actuals =~ s/CCHandle/context.CSPHandle, CCHandle/; + $args =~ /CSSM_CONTEXT/ && + $actuals =~ s/CCHandle/CCHandle, &context/; + $handletype = "CC"; + }; + + # add the default privilege argument to non-P functions taking privileges + $args =~ /CSSM_PRIVILEGE/ && ! ($name =~ /P$/) && # add privilege argument (last) + ($actuals .= ",\n${tabs}attachment.module.cssm.getPrivilege()"); + + # finally translate DLDBHandles into their DL component + $handle =~ s/DLDBHandle/DLDBHandle.DLHandle/; + + # payoff time + print " +CSSM_RETURN CSSMAPI +$name ($formals{$name}) +{ + BEGIN_API"; + if ($handletype eq "CC") { + print " + HandleContext &context = enterContext($handle); + CSPAttachment &attachment = context.attachment;"; + } else { + print " + $Type &attachment = enterAttachment<$Type>($handle);"; + }; + print " + TransitLock _(attachment); + ${prefix}return attachment.downcalls.$barename($actuals); + END_API($type) +} +"; + $written++; +}; +close(OUT); +select(STDOUT); + + +# +# Now peruse the SPI headers for a list of function names +# and build in-memory translation tables for runtime. +# +open(OUT, ">$TABLES") or die "Cannot write $TABLES: $^E"; +select OUT; + +print "// +// Standard plugin name tables +// $warning +// +"; +while (($name, $_) = each %spi) { + print "extern const char *const ${name}NameTable[] = {"; + s/^.*struct cssm_spi.*{(.*)} CSSM_SPI.*$/$1/s + or die "bad format in $SPI_H{$name}"; + s/CSSM_RETURN \(CSSM[A-Z]*I \*([A-Za-z_]+)\)\s+\([^)]+\)[^;]*;/\t"$1",/g; + print; + print "};\n\n"; +}; +close(OUT); +select(STDOUT); + +# +# Finally, generate linker export file to avoid leaking internal symbols +# +open(OUT, ">$EXPORTS") or die "Cannot write $EXPORTS: $^E"; +select(OUT); + +# entry point names (functions) +for $name (keys %formals) { + $symbols{$name} = 1; +}; + +# OID-related data symbols +$/=undef; +foreach $_ (@OIDS_H) { + open(OIDS_H, "$SOURCEDIR/$_") or die "Cannot open $SOURCEDIR/$_: $^E"; + $_ = ; # glglgl... aaaaah + s/\/\*.*\*\///gm; # remove comments + + foreach $name (/\s+(CSSMOID_[A-Za-z0-9_]+)/gs) { + $symbols{$name} = 1; + }; +}; +close(OIDS_H); + +foreach $_ (@OIDS_H2) { + open(OIDS_H2, "$SOURCEDIR/../../libsecurity_asn1/lib/$_") or die "Cannot open $SOURCEDIR/$_: $^E"; + $_ = ; # glglgl... aaaaah + s/\/\*.*\*\///gm; # remove comments + + foreach $name (/\s+(CSSMOID_[A-Za-z0-9_]+)/gs) { + $symbols{$name} = 1; + }; +}; +close(OIDS_H2); + +foreach $name (keys %symbols) { + print "_$name\n"; +}; + +close(OUT); +select(STDOUT); + + +close(EXPORTS); +close(REPORT); +print "$written API functions generated; $ignored ignored (see $REPORT)\n"; diff --git a/libsecurity_cssm/lib/guids.cpp b/libsecurity_cssm/lib/guids.cpp new file mode 100644 index 00000000..e3e6be7b --- /dev/null +++ b/libsecurity_cssm/lib/guids.cpp @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2000-2001,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@ + */ + + +#include +#include + +// {87191ca0-0fc9-11d4-849a-000502b52122} +const CSSM_GUID gGuidCssm = +{ + OSSwapHostToBigConstInt32(0x87191ca0), + OSSwapHostToBigConstInt16(0x0fc9), + OSSwapHostToBigConstInt16(0x11d4), + { 0x84, 0x9a, 0x00, 0x05, 0x02, 0xb5, 0x21, 0x22 } +}; + +// {87191ca1-0fc9-11d4-849a-000502b52122} +const CSSM_GUID gGuidAppleFileDL = +{ + OSSwapHostToBigConstInt32(0x87191ca1), + OSSwapHostToBigConstInt16(0x0fc9), + OSSwapHostToBigConstInt16(0x11d4), + { 0x84, 0x9a, 0x00, 0x05, 0x02, 0xb5, 0x21, 0x22 } +}; + +// {87191ca2-0fc9-11d4-849a-000502b52122} +const CSSM_GUID gGuidAppleCSP = +{ + OSSwapHostToBigConstInt32(0x87191ca2), + OSSwapHostToBigConstInt16(0x0fc9), + OSSwapHostToBigConstInt16(0x11d4), + { 0x84, 0x9a, 0x00, 0x05, 0x02, 0xb5, 0x21, 0x22 } +}; + +// {87191ca3-0fc9-11d4-849a-000502b52122} +const CSSM_GUID gGuidAppleCSPDL = +{ + OSSwapHostToBigConstInt32(0x87191ca3), + OSSwapHostToBigConstInt16(0x0fc9), + OSSwapHostToBigConstInt16(0x11d4), + { 0x84, 0x9a, 0x00, 0x05, 0x02, 0xb5, 0x21, 0x22 } +}; + +// {87191ca4-0fc9-11d4-849a-000502b52122} +const CSSM_GUID gGuidAppleX509CL = +{ + OSSwapHostToBigConstInt32(0x87191ca4), + OSSwapHostToBigConstInt16(0x0fc9), + OSSwapHostToBigConstInt16(0x11d4), + { 0x84, 0x9a, 0x00, 0x05, 0x02, 0xb5, 0x21, 0x22 } +}; + +// {87191ca5-0fc9-11d4-849a-000502b52122} +const CSSM_GUID gGuidAppleX509TP = +{ + OSSwapHostToBigConstInt32(0x87191ca5), + OSSwapHostToBigConstInt16(0x0fc9), + OSSwapHostToBigConstInt16(0x11d4), + { 0x84, 0x9a, 0x00, 0x05, 0x02, 0xb5, 0x21, 0x22 } +}; + +// {87191ca6-0fc9-11d4-849a-000502b52122} +const CSSM_GUID gGuidAppleLDAPDL = +{ + OSSwapHostToBigConstInt32(0x87191ca6), + OSSwapHostToBigConstInt16(0x0fc9), + OSSwapHostToBigConstInt16(0x11d4), + { 0x84, 0x9a, 0x00, 0x05, 0x02, 0xb5, 0x21, 0x22 } +}; + +// {87191ca7-0fc9-11d4-849a-000502b52122} +const CSSM_GUID gGuidAppleDotMacTP = +{ + OSSwapHostToBigConstInt32(0x87191ca7), + OSSwapHostToBigConstInt16(0x0fc9), + OSSwapHostToBigConstInt16(0x11d4), + { 0x84, 0x9a, 0x00, 0x05, 0x02, 0xb5, 0x21, 0x22 } +}; + +// 87191ca8-0fc9-11d4-849a000502b52122 +const CSSM_GUID gGuidAppleSdCSPDL = +{ + OSSwapHostToBigConstInt32(0x87191ca8), + OSSwapHostToBigConstInt16(0x0fc9), + OSSwapHostToBigConstInt16(0x11d4), + { 0x84, 0x9a, 0x00, 0x05, 0x02, 0xb5, 0x21, 0x22 } +}; + +// {87191ca9-0fc9-11d4-849a-000502b52122} +const CSSM_GUID gGuidAppleDotMacDL = +{ + OSSwapHostToBigConstInt32(0x87191ca9), + OSSwapHostToBigConstInt16(0x0fc9), + OSSwapHostToBigConstInt16(0x11d4), + { 0x84, 0x9a, 0x00, 0x05, 0x02, 0xb5, 0x21, 0x22 } +}; diff --git a/libsecurity_cssm/lib/manager.cpp b/libsecurity_cssm/lib/manager.cpp new file mode 100644 index 00000000..1441e71b --- /dev/null +++ b/libsecurity_cssm/lib/manager.cpp @@ -0,0 +1,220 @@ +/* + * 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@ + */ + + +// +// manager - CSSM manager/supervisor objects. +// +#include "manager.h" +#include "module.h" +#include + + +// +// Constructing a CssmManager instance. +// This does almost nothing - the actual intialization happens in the initialize() method. +// +CssmManager::CssmManager() +{ + initCount = 0; // not yet initialized +} + +CssmManager::~CssmManager() +{ + if (initCount > 0) + secdebug("cssm", "CSSM forcibly shutting down"); +} + + +// +// CSSM initialization. +// THREADS: This function must run in an uncontested environment. +// +void CssmManager::initialize (const CSSM_VERSION &version, + CSSM_PRIVILEGE_SCOPE scope, + const Guid &callerGuid, + CSSM_KEY_HIERARCHY keyHierarchy, + CSSM_PVC_MODE &pvcPolicy) +{ + StLock _(mLock); + + // check version first + checkVersion(version); + + if (initCount) { + // re-initialization processing as per CSSM spec + if (pvcPolicy != mPvcPolicy) { + pvcPolicy = mPvcPolicy; // return old value + CssmError::throwMe(CSSMERR_CSSM_PVC_ALREADY_CONFIGURED); + } + initCount++; + secdebug("cssm", "re-initializing CSSM (%d levels)", initCount); + return; + } + + // we don't support thread scope privileges + if (scope == CSSM_PRIVILEGE_SCOPE_THREAD) + CssmError::throwMe(CSSMERR_CSSM_SCOPE_NOT_SUPPORTED); + + // keep the init arguments for future use - these become instance constants + mPrivilegeScope = scope; + mKeyHierarchy = keyHierarchy; + mPvcPolicy = pvcPolicy; + mCallerGuid = callerGuid; + + // we are ready now + initCount = 1; + secdebug("cssm", "CSSM initialized"); +} + + +// +// CSSM Termination processing. +// Returns true if this was the final (true) termination, false if a nested Init was undone. +// +bool CssmManager::terminate() +{ + StLock _(mLock); + switch (initCount) { + case 0: + CssmError::throwMe(CSSMERR_CSSM_NOT_INITIALIZED); + case 1: + secdebug("cssm", "Terminating CSSM"); + if (!moduleMap.empty()) + CssmError::throwMe(CSSM_ERRCODE_FUNCTION_FAILED); // @#can't terminate with modules loaded + initCount = 0; // mark uninitialized + return true; + default: + initCount--; // nested INIT, just count down + secdebug("cssm", "CSSM nested termination (%d remaining)", initCount); + return false; + } +} + + +#if defined(RESTRICTED_CSP_LOADING) +static const char * const allowedCSPs[] = { + "/System/Library/Security/AppleCSP.bundle", + "/System/Library/Security/AppleCSPDL.bundle", + NULL +}; +#endif + + +// +// Load a module (well, try). +// +void CssmManager::loadModule(const Guid &guid, + CSSM_KEY_HIERARCHY, + const ModuleCallback &callback) +{ + StLock _(mLock); + ModuleMap::iterator it = moduleMap.find(guid); + Module *module; + if (it == moduleMap.end()) { + MdsComponent info(guid); +#if defined(RESTRICTED_CSP_LOADING) + // An abominable temporary hack for legal reasons. They made me do it! + if (info.supportsService(CSSM_SERVICE_CSP)) { + string loadPath = info.path(); + for (const char * const *pp = allowedCSPs; *pp; pp++) + if (loadPath == *pp) + goto allowed; + CssmError::throwMe(CSSM_ERRCODE_MODULE_MANIFEST_VERIFY_FAILED); + allowed: ; + } +#endif + secdebug("cssm", "loading module %s(%s) from %s", + info.name().c_str(), info.description().c_str(), info.path().c_str()); + module = new Module(this, info, loader(info.path())); + moduleMap[guid] = module; + } else { + module = it->second; + secdebug("cssm", "%p reloaded module %s(%s) at %s", + module, module->name().c_str(), module->description().c_str(), + module->path().c_str()); + } + + // We are not playing the "key hierarchy" game around here. + // if we did, this is where we'd check the manifest. + + module->add(callback); +} + + +// +// Unload a module. +// THREADS: Locking Manager(1), Module(2). +// +void CssmManager::unloadModule(const Guid &guid, + const ModuleCallback &callback) +{ + StLock _(mLock); + Module *module = getModule(guid); + if (module->unload(callback)) { + secdebug("cssm", "%p module %s(%s) final unload", + module, module->name().c_str(), module->description().c_str()); + moduleMap.erase(guid); + delete module; + } else + secdebug("cssm", "%p module %s(%s) load count now %u", module, + module->name().c_str(), module->description().c_str(), module->callbackCount()); +} + + +// +// Introductions +// +void CssmManager::introduce(const Guid &, + CSSM_KEY_HIERARCHY) +{ + StLock _(mLock); + CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); +} + +void CssmManager::unIntroduce(const Guid &) +{ + StLock _(mLock); + CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); +} + + +// +// Support. +// THREADS: These utilities run under lock protection by the caller. +// +void CssmManager::checkVersion(const CSSM_VERSION &version) +{ + if (version.Major != 2) + CssmError::throwMe(CSSM_ERRCODE_INCOMPATIBLE_VERSION); + if (version.Minor != 0) + CssmError::throwMe(CSSM_ERRCODE_INCOMPATIBLE_VERSION); +} + +Module *CssmManager::getModule(const Guid &guid) +{ + ModuleMap::iterator it = moduleMap.find(guid); + if (it == moduleMap.end()) + CssmError::throwMe(CSSMERR_CSSM_MODULE_NOT_LOADED); + return it->second; +} diff --git a/libsecurity_cssm/lib/manager.h b/libsecurity_cssm/lib/manager.h new file mode 100644 index 00000000..e4c634eb --- /dev/null +++ b/libsecurity_cssm/lib/manager.h @@ -0,0 +1,115 @@ +/* + * 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@ + */ + + +// +// manager - CSSM manager/supervisor objects. +// +#ifndef _H_MANAGER +#define _H_MANAGER + +#include "modloader.h" +#include +#include "cssmmds.h" +#include "attachfactory.h" + + +// +// The CssmManager class embodies one instance of CSSM. It can interact with multiple +// callers in multiple threads. +// As far as CssmManager is concerned, it doesn't mind for multiple instances of it to +// exist. Such instances are strictly separated; they do not share anything (module info, +// attachments, callbacks, etc.) and live their lives in splendid isolation. Of course, +// other subsystems they deal with (e.g. the ModuleLoader) may multiplex them, but such +// components should take pains not to "leak" information from one CssmManager instance +// to another. +// +class CssmManager : public AttachmentFactory { + NOCOPY(CssmManager) + static const CSSM_GUID theGuidForCssmItself; +public: + CssmManager(); + virtual ~CssmManager(); + + void initialize (const CSSM_VERSION &version, + CSSM_PRIVILEGE_SCOPE scope, + const Guid &callerGuid, + CSSM_KEY_HIERARCHY keyHierarchy, + CSSM_PVC_MODE &pvcPolicy); + bool terminate(); + + void loadModule (const Guid &guid, + CSSM_KEY_HIERARCHY keyHierarchy, + const ModuleCallback &callback); + void unloadModule (const Guid &guid, + const ModuleCallback &callback); + + void introduce(const Guid &guid, CSSM_KEY_HIERARCHY keyHierarchy); + void unIntroduce(const Guid &guid); + + // + // Polite inquiries + // + + // these values are constant (after init time) and need no locking + const Guid &callerGuid() const { return mCallerGuid; } + CSSM_PRIVILEGE_SCOPE privilegeScope() const { return mPrivilegeScope; } + CSSM_KEY_HIERARCHY keyHierarchy() const { return mKeyHierarchy; } + CSSM_PVC_MODE pvcMode() const { return mPvcPolicy; } + + //@@@ for these two, consider locking (as of the C shims AND the transition layer use) + const CSSM_PRIVILEGE &getPrivilege() const { return mPrivilege; } + void setPrivilege(const CSSM_PRIVILEGE &priv) { mPrivilege = priv; } + +public: + Module *getModule(const Guid &guid); + +private: + typedef map ModuleMap; + ModuleMap moduleMap; + + Mutex mLock; // object lock + unsigned int initCount; // number of times successfully initialized + +private: + ModuleLoader loader; // our ticket to module land + +private: + // state acquired from initialize (instance constants - not guarded) + CSSM_PRIVILEGE_SCOPE mPrivilegeScope; + CSSM_KEY_HIERARCHY mKeyHierarchy; + CSSM_PVC_MODE mPvcPolicy; + Guid mCallerGuid; + + // persistent state of the CSSM (guarded by module lock) + CSSM_PRIVILEGE mPrivilege; // established privileges + +private: + void checkVersion(const CSSM_VERSION &version); +}; + +#ifdef _CPP_MANAGER +# pragma export off +#endif + +#endif //_H_MANAGER diff --git a/libsecurity_cssm/lib/modload_plugin.cpp b/libsecurity_cssm/lib/modload_plugin.cpp new file mode 100644 index 00000000..61770ad7 --- /dev/null +++ b/libsecurity_cssm/lib/modload_plugin.cpp @@ -0,0 +1,118 @@ +/* + * 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@ + */ + + +// +// modload_plugin - loader interface for dynamically loaded plugin modules +// +#include "modload_plugin.h" + + +namespace Security { + + +// +// During construction, a LoadablePlugin loads itself into memory and locates +// the canonical (CDSA defined) four entrypoints. If anything fails, we throw. +// +LoadablePlugin::LoadablePlugin(const char *path) : LoadableBundle(path) +{ + secdebug("cssm", "LoadablePlugin(%s)", path); + load(); +} + + +// +// Loading and unloading devolves directly onto LoadableBundle +// +void LoadablePlugin::load() +{ + secdebug("cssm", "LoadablePlugin::load() path %s", path().c_str()); + LoadableBundle::load(); + findFunction(mFunctions.load, "CSSM_SPI_ModuleLoad"); + findFunction(mFunctions.attach, "CSSM_SPI_ModuleAttach"); + findFunction(mFunctions.detach, "CSSM_SPI_ModuleDetach"); + findFunction(mFunctions.unload, "CSSM_SPI_ModuleUnload"); +} + +void LoadablePlugin::unload() +{ + secdebug("cssm", "LoadablePlugin::unload() path %s", path().c_str()); + /* skipping for workaround for radar 3774226 + LoadableBundle::unload(); */ +} + +bool LoadablePlugin::isLoaded() const +{ + return LoadableBundle::isLoaded(); +} + + +// +// Pass module entry points to the statically linked functions +// +CSSM_RETURN LoadablePlugin::load(const CSSM_GUID *CssmGuid, + const CSSM_GUID *ModuleGuid, + CSSM_SPI_ModuleEventHandler CssmNotifyCallback, + void *CssmNotifyCallbackCtx) +{ + secdebug("cssm", "LoadablePlugin::load(guid,...) path %s", path().c_str()); + return mFunctions.load(CssmGuid, ModuleGuid, + CssmNotifyCallback, CssmNotifyCallbackCtx); +} + +CSSM_RETURN LoadablePlugin::unload(const CSSM_GUID *CssmGuid, + const CSSM_GUID *ModuleGuid, + CSSM_SPI_ModuleEventHandler CssmNotifyCallback, + void *CssmNotifyCallbackCtx) +{ + secdebug("cssm", "LoadablePlugin::unload(guid,...) path %s", path().c_str()); + return mFunctions.unload(CssmGuid, ModuleGuid, + CssmNotifyCallback, CssmNotifyCallbackCtx); +} + +CSSM_RETURN LoadablePlugin::attach(const CSSM_GUID *ModuleGuid, + const CSSM_VERSION *Version, + uint32 SubserviceID, + CSSM_SERVICE_TYPE SubServiceType, + CSSM_ATTACH_FLAGS AttachFlags, + CSSM_MODULE_HANDLE ModuleHandle, + CSSM_KEY_HIERARCHY KeyHierarchy, + const CSSM_GUID *CssmGuid, + const CSSM_GUID *ModuleManagerGuid, + const CSSM_GUID *CallerGuid, + const CSSM_UPCALLS *Upcalls, + CSSM_MODULE_FUNCS_PTR *FuncTbl) +{ + return mFunctions.attach(ModuleGuid, Version, SubserviceID, SubServiceType, + AttachFlags, ModuleHandle, KeyHierarchy, CssmGuid, ModuleManagerGuid, + CallerGuid, Upcalls, FuncTbl); +} + +CSSM_RETURN LoadablePlugin::detach(CSSM_MODULE_HANDLE ModuleHandle) +{ + return mFunctions.detach(ModuleHandle); +} + + +} // end namespace Security diff --git a/libsecurity_cssm/lib/modload_plugin.h b/libsecurity_cssm/lib/modload_plugin.h new file mode 100644 index 00000000..a834661c --- /dev/null +++ b/libsecurity_cssm/lib/modload_plugin.h @@ -0,0 +1,65 @@ +/* + * 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@ + */ + + +// +// modload_plugin - loader interface for dynamically loaded plugin modules +// +#ifndef _H_MODLOAD_PLUGIN +#define _H_MODLOAD_PLUGIN + +#include "modloader.h" + + +namespace Security { + + +// +// A LoadablePlugin implements itself as a LoadableBundle +// +class LoadablePlugin : public Plugin, public LoadableBundle { +public: + LoadablePlugin(const char *path); + + void load(); + void unload(); + bool isLoaded() const; + + CSSM_SPI_ModuleLoadFunction load; + CSSM_SPI_ModuleUnloadFunction unload; + CSSM_SPI_ModuleAttachFunction attach; + CSSM_SPI_ModuleDetachFunction detach; + +private: + PluginFunctions mFunctions; + + template + void findFunction(FunctionType * &func, const char *name) + { func = (FunctionType *)lookupSymbol(name); } +}; + + +} // end namespace Security + + +#endif //_H_MODLOAD_PLUGIN diff --git a/libsecurity_cssm/lib/modload_static.cpp b/libsecurity_cssm/lib/modload_static.cpp new file mode 100644 index 00000000..9db19169 --- /dev/null +++ b/libsecurity_cssm/lib/modload_static.cpp @@ -0,0 +1,79 @@ +/* + * 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@ + */ + + +// +// modload_static - pseudo-loading of statically linked plugins +// +#include "modload_static.h" + + +namespace Security { + + +// +// Pass module entry points to the statically linked functions +// +CSSM_RETURN StaticPlugin::load(const CSSM_GUID *CssmGuid, + const CSSM_GUID *ModuleGuid, + CSSM_SPI_ModuleEventHandler CssmNotifyCallback, + void *CssmNotifyCallbackCtx) +{ + return entries.load(CssmGuid, ModuleGuid, + CssmNotifyCallback, CssmNotifyCallbackCtx); +} + +CSSM_RETURN StaticPlugin::unload(const CSSM_GUID *CssmGuid, + const CSSM_GUID *ModuleGuid, + CSSM_SPI_ModuleEventHandler CssmNotifyCallback, + void *CssmNotifyCallbackCtx) +{ + return entries.unload(CssmGuid, ModuleGuid, + CssmNotifyCallback, CssmNotifyCallbackCtx); +} + +CSSM_RETURN StaticPlugin::attach(const CSSM_GUID *ModuleGuid, + const CSSM_VERSION *Version, + uint32 SubserviceID, + CSSM_SERVICE_TYPE SubServiceType, + CSSM_ATTACH_FLAGS AttachFlags, + CSSM_MODULE_HANDLE ModuleHandle, + CSSM_KEY_HIERARCHY KeyHierarchy, + const CSSM_GUID *CssmGuid, + const CSSM_GUID *ModuleManagerGuid, + const CSSM_GUID *CallerGuid, + const CSSM_UPCALLS *Upcalls, + CSSM_MODULE_FUNCS_PTR *FuncTbl) +{ + return entries.attach(ModuleGuid, Version, SubserviceID, SubServiceType, + AttachFlags, ModuleHandle, KeyHierarchy, CssmGuid, ModuleManagerGuid, + CallerGuid, Upcalls, FuncTbl); +} + +CSSM_RETURN StaticPlugin::detach(CSSM_MODULE_HANDLE ModuleHandle) +{ + return entries.detach(ModuleHandle); +} + + +} // end namespace Security diff --git a/libsecurity_cssm/lib/modload_static.h b/libsecurity_cssm/lib/modload_static.h new file mode 100644 index 00000000..4c0b5263 --- /dev/null +++ b/libsecurity_cssm/lib/modload_static.h @@ -0,0 +1,64 @@ +/* + * 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@ + */ + + +// +// modload_static - pseudo-loading of statically linked plugins +// +#ifndef _H_MODLOAD_STATIC +#define _H_MODLOAD_STATIC + +#include "modloader.h" +#include "cssmint.h" +#include +#include + + +namespace Security { + + +// +// A "plugin" implementation that uses statically linked entry points +// +class StaticPlugin : public Plugin { +public: + StaticPlugin(const PluginFunctions &funcs) : entries(funcs) { } + + void load() { } + void unload() { } + bool isLoaded() const { return true; } + + CSSM_SPI_ModuleLoadFunction load; + CSSM_SPI_ModuleUnloadFunction unload; + CSSM_SPI_ModuleAttachFunction attach; + CSSM_SPI_ModuleDetachFunction detach; + +private: + const PluginFunctions &entries; +}; + + +} // end namespace Security + + +#endif //_H_MODLOAD_STATIC diff --git a/libsecurity_cssm/lib/modloader.cpp b/libsecurity_cssm/lib/modloader.cpp new file mode 100644 index 00000000..1f80798f --- /dev/null +++ b/libsecurity_cssm/lib/modloader.cpp @@ -0,0 +1,105 @@ +/* + * 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@ + */ + + +// +// cssm module loader interface - MACOS X (CFBundle/DYLD) version. +// +// This file provides a C++-style interface to CFBundles as managed by the CF-style +// system interfaces. The implementation looks a bit, well, hybrid - but the visible +// interfaces are pure C++. +// +#include "modloader.h" +#include "modload_plugin.h" +# include "modload_static.h" + + +namespace Security { + + +// +// Pull in functions for built-in plugin modules +// +#define BUILTIN(suffix) \ + extern "C" CSSM_SPI_ModuleLoadFunction CSSM_SPI_ModuleLoad ## suffix; \ + extern "C" CSSM_SPI_ModuleUnloadFunction CSSM_SPI_ModuleUnload ## suffix; \ + extern "C" CSSM_SPI_ModuleAttachFunction CSSM_SPI_ModuleAttach ## suffix; \ + extern "C" CSSM_SPI_ModuleDetachFunction CSSM_SPI_ModuleDetach ## suffix; \ + static const PluginFunctions builtin ## suffix = { \ + CSSM_SPI_ModuleLoad ## suffix, CSSM_SPI_ModuleUnload ## suffix, \ + CSSM_SPI_ModuleAttach ## suffix, CSSM_SPI_ModuleDetach ## suffix \ + }; + +BUILTIN(__apple_csp) +BUILTIN(__apple_file_dl) +BUILTIN(__apple_cspdl) +BUILTIN(__apple_x509_cl) +BUILTIN(__apple_x509_tp) +BUILTIN(__sd_cspdl) + + +// +// Construct the canonical ModuleLoader object +// +ModuleLoader::ModuleLoader() +{ +#if !defined(NO_BUILTIN_PLUGINS) + mPlugins["*AppleCSP"] = new StaticPlugin(builtin__apple_csp); + mPlugins["*AppleDL"] = new StaticPlugin(builtin__apple_file_dl); + mPlugins["*AppleCSPDL"] = new StaticPlugin(builtin__apple_cspdl); + mPlugins["*AppleX509CL"] = new StaticPlugin(builtin__apple_x509_cl); + mPlugins["*AppleX509TP"] = new StaticPlugin(builtin__apple_x509_tp); + mPlugins["*SDCSPDL"] = new StaticPlugin(builtin__sd_cspdl); +#endif //NO_BUILTIN_PLUGINS +} + + +// +// "Load" a plugin, given its MDS path. At this layer, we are performing +// a purely physical load operation. No code in the plugin is called. +// If "built-in plugins" are enabled, the moduleTable will come pre-initialized +// with certain paths. Since we consult this table before going to disk, this +// means that we'll pick these up first *as long as the paths match exactly*. +// There is nothing magical in the path strings themselves, other than by +// convention. (The convention is "*NAME", which conveniently does not match +// any actual file path.) +// +Plugin *ModuleLoader::operator () (const string &path) +{ + Plugin * &plugin = mPlugins[path]; + if (!plugin) { + secdebug("cssm", "ModuleLoader(): creating plugin %s", path.c_str()); + plugin = new LoadablePlugin(path.c_str()); + } + else { + secdebug("cssm", "ModuleLoader(): FOUND plugin %s, isLoaded %s", + path.c_str(), plugin->isLoaded() ? "TRUE" : "FALSE"); + if(!plugin->isLoaded()) { + plugin->load(); + } + } + return plugin; +} + + +} // end namespace Security diff --git a/libsecurity_cssm/lib/modloader.h b/libsecurity_cssm/lib/modloader.h new file mode 100644 index 00000000..a34b2003 --- /dev/null +++ b/libsecurity_cssm/lib/modloader.h @@ -0,0 +1,99 @@ +/* + * 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@ + */ + + +// +// modloader.h - CSSM module loader interface +// +// This is a thin abstraction of plugin module loading/handling for CSSM. +// The resulting module ("Plugin") notion is specific to CSSM plugin modules. +// This implementation uses MacOS X bundles. +// +#ifndef _H_MODLOADER +#define _H_MODLOADER + +#include +#include +#include "cssmint.h" +#include +#include + + +namespace Security { + + +// +// A collection of canonical plugin entry points (aka CSSM module SPI) +// +struct PluginFunctions { + CSSM_SPI_ModuleLoadFunction *load; + CSSM_SPI_ModuleUnloadFunction *unload; + CSSM_SPI_ModuleAttachFunction *attach; + CSSM_SPI_ModuleDetachFunction *detach; +}; + + +// +// An abstract representation of a loadable plugin. +// Note that "loadable" doesn't mean that actual code loading +// is necessarily happening, but let's just assume it might. +// +class Plugin { + NOCOPY(Plugin) +public: + Plugin() { } + virtual ~Plugin() { } + + virtual void load() = 0; + virtual void unload() = 0; + virtual bool isLoaded() const = 0; + + virtual CSSM_SPI_ModuleLoadFunction load = 0; + virtual CSSM_SPI_ModuleUnloadFunction unload = 0; + virtual CSSM_SPI_ModuleAttachFunction attach = 0; + virtual CSSM_SPI_ModuleDetachFunction detach = 0; +}; + + +// +// The supervisor class that manages searching and loading. +// +class ModuleLoader { + NOCOPY(ModuleLoader) +public: + ModuleLoader(); + + Plugin *operator () (const string &path); + +private: + // the table of all loaded modules + typedef map PluginTable; + PluginTable mPlugins; +}; + + + +} // end namespace Security + + +#endif //_H_MODLOADER diff --git a/libsecurity_cssm/lib/module.cpp b/libsecurity_cssm/lib/module.cpp new file mode 100644 index 00000000..e7388ab3 --- /dev/null +++ b/libsecurity_cssm/lib/module.cpp @@ -0,0 +1,164 @@ +/* + * 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@ + */ + + +// +// module - CSSM Module objects +// +#include "module.h" +#include "manager.h" +#include "attachment.h" +#include + + +// +// Module object construction. +// +Module::Module(CssmManager *mgr, const MdsComponent &info, Plugin *plug) +: MdsComponent(info), cssm(*mgr), plugin(plug) +{ + // invoke module's load entry (tell it it's being loaded) + if (CSSM_RETURN err = plugin->load(&gGuidCssm, // CSSM's Guid + &myGuid(), // module's Guid + spiEventRelay, this)) { + plugin->unload(); + CssmError::throwMe(err); // self-destruct this module + } +} + + +// +// Destroy the module object. +// The unload() method must have succeeded and returned true before +// you get to delete a Module. A destructor is too precarious a place +// to negotiate with a plugin... +// +Module::~Module() +{ +} + + +bool Module::unload(const ModuleCallback &callback) +{ + StLock _(mLock); + // locked module - no more attachment creations possible + if (callbackCount() == 1) { + // would be last callback if successful, check for actual unload + if (attachmentCount() > 0) + CssmError::throwMe(CSSM_ERRCODE_FUNCTION_FAILED); // @# module is busy + // no attachments active - we are idle and ready to unload + if (CSSM_RETURN err = plugin->unload(&gGuidCssm, // CSSM's Guid + &myGuid(), // module's Guid + spiEventRelay, this)) // our callback + CssmError::throwMe(err); // tough... + // okay, commit + remove(callback); + plugin->unload(); + return true; + } else { + // more callbacks - we're not going to unload + remove(callback); + return false; + } +} + + +// +// Create a new attachment for this module +// +CSSM_HANDLE Module::attach(const CSSM_VERSION &version, + uint32 subserviceId, + CSSM_SERVICE_TYPE subserviceType, + const CSSM_API_MEMORY_FUNCS &memoryOps, + CSSM_ATTACH_FLAGS attachFlags, + CSSM_KEY_HIERARCHY keyHierarchy, + CSSM_FUNC_NAME_ADDR *functionTable, + uint32 functionTableSize) +{ + StLock _(mLock); + + // check if the module can do this kind of service + if (!supportsService(subserviceType)) + CssmError::throwMe(CSSMERR_CSSM_INVALID_SERVICE_MASK); + + Attachment *attachment = cssm.attachmentMakerFor(subserviceType)->make(this, + version, + subserviceId, subserviceType, + memoryOps, + attachFlags, + keyHierarchy, + functionTable, functionTableSize); + + try { + // add to module's attachment map + attachmentMap.insert(AttachmentMap::value_type(attachment->handle(), attachment)); + } catch (...) { + delete attachment; + throw; + } + + // all done + return attachment->handle(); +} + + +// +// Detach an Attachment from this module. +// THREADS: Requires the attachment to be idled out, i.e. caller +// is responsible for keeping more users from entering it. +// +void Module::detach(Attachment *attachment) +{ + StLock _(mLock); + attachmentMap.erase(attachment->handle()); +} + + +// +// Handle events sent by the loaded module. +// +void Module::spiEvent(CSSM_MODULE_EVENT event, + const Guid &guid, + uint32 subserviceId, + CSSM_SERVICE_TYPE serviceType) +{ + StLock _(mLock); + if (guid != myGuid()) + CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR); + callbackSet(event, guid, subserviceId, serviceType); +} + +// static shim +CSSM_RETURN Module::spiEventRelay(const CSSM_GUID *ModuleGuid, + void *Context, + uint32 SubserviceId, + CSSM_SERVICE_TYPE ServiceType, + CSSM_MODULE_EVENT EventType) +{ + BEGIN_API + static_cast(Context)->spiEvent(EventType, + Guid::required(ModuleGuid), + SubserviceId, + ServiceType); + END_API(CSSM) +} diff --git a/libsecurity_cssm/lib/module.h b/libsecurity_cssm/lib/module.h new file mode 100644 index 00000000..92a2a1f2 --- /dev/null +++ b/libsecurity_cssm/lib/module.h @@ -0,0 +1,103 @@ +/* + * 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@ + */ + + +// +// module - CSSM Module objects +// +#ifndef _H_MODULE +#define _H_MODULE + +#include "cssmint.h" +#include "cssmmds.h" +#include +#include "modloader.h" +#include + +#if __GNUC__ > 2 +#include +using __gnu_cxx::hash_map; +#else +#include +#endif + + +// +// This type represents a loaded plugin module of some kind. For each CssmManager +// instance and each one plugin, there is only (at most) one Module object to +// represent it. +// +class Module : public MdsComponent { + NOCOPY(Module) +public: + Module(CssmManager *mgr, const MdsComponent &info, Plugin *plugin); + virtual ~Module(); + + CssmManager &cssm; + + bool unload(const ModuleCallback &callback); + + CSSM_HANDLE attach(const CSSM_VERSION &version, + uint32 subserviceId, + CSSM_SERVICE_TYPE subserviceType, + const CSSM_API_MEMORY_FUNCS &memoryOps, + CSSM_ATTACH_FLAGS attachFlags, + CSSM_KEY_HIERARCHY keyHierarchy, + CSSM_FUNC_NAME_ADDR *functionTable, + uint32 functionTableSize); + void detach(Attachment *attachment); + + void add(const ModuleCallback &cb) { callbackSet.insert(cb); } + void remove(const ModuleCallback &cb) { callbackSet.erase(cb); } + + unsigned int callbackCount() const { return callbackSet.size(); } + unsigned int attachmentCount() const { return attachmentMap.size(); } + + void safeLock() { if (!isThreadSafe()) mLock.lock(); } + void safeUnlock() { if (!isThreadSafe()) mLock.unlock(); } + +public: + typedef hash_map AttachmentMap; + + Plugin *plugin; // our loader module + +private: + void spiEvent(CSSM_MODULE_EVENT event, + const Guid &guid, + uint32 subserviceId, + CSSM_SERVICE_TYPE serviceType); + + static CSSM_RETURN spiEventRelay(const CSSM_GUID *ModuleGuid, + void *Context, + uint32 SubserviceId, + CSSM_SERVICE_TYPE ServiceType, + CSSM_MODULE_EVENT EventType); + +private: + AttachmentMap attachmentMap; // map of all outstanding attachment handles + ModuleCallbackSet callbackSet; // set of registered callbacks + + Mutex mLock; +}; + +#endif //_H_MODULE diff --git a/libsecurity_cssm/lib/oidsalg.c b/libsecurity_cssm/lib/oidsalg.c new file mode 100644 index 00000000..23ec939f --- /dev/null +++ b/libsecurity_cssm/lib/oidsalg.c @@ -0,0 +1,158 @@ +/* + * 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 new file mode 100644 index 00000000..25d45ae3 --- /dev/null +++ b/libsecurity_cssm/lib/oidsbase.h @@ -0,0 +1,459 @@ +/* + * Copyright (c) 1999-2001,2003-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@ + * + * 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 + +/* -------------------------------------------------------------------------*/ + +/* + * 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_OID_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_OID_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_OID_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_OID_LENGTH + 1 + +/* + * 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/libsecurity_cssm/lib/oidscert.cpp new file mode 100644 index 00000000..6e533cc2 --- /dev/null +++ b/libsecurity_cssm/lib/oidscert.cpp @@ -0,0 +1,405 @@ +/* + * 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@ + */ + + +/* + + File: oidscert.cpp + + Contains: Object Identifiers for X509 Certificate Library + + Copyright (c) 1999,2001-2004 Apple Computer, Inc. All Rights Reserved. + + */ + +#include "oidsbase.h" +#include "oidscert.h" + +/* required until PR-3347430 Security/cdsa/cdsa/oidscert.h is checked + * into TOT - pending public API review */ +extern "C" { + extern const CSSM_OID CSSMOID_X509V1IssuerNameStd, + CSSMOID_X509V1SubjectNameStd; +} + +static const uint8 + + /* Certificate OID Fields */ + X509V3SignedCertificate[] = {INTEL_X509V3_CERT_R08, 0}, + X509V3SignedCertificateCStruct[] = {INTEL_X509V3_CERT_R08, 0, INTEL_X509_C_DATATYPE}, + X509V3Certificate[] = {INTEL_X509V3_CERT_R08, 1}, + X509V3CertificateCStruct[] = {INTEL_X509V3_CERT_R08, 1, INTEL_X509_C_DATATYPE}, + X509V1Version[] = {INTEL_X509V3_CERT_R08, 2}, + X509V1SerialNumber[] = {INTEL_X509V3_CERT_R08, 3}, + X509V1IssuerName[] = {INTEL_X509V3_CERT_R08, 5}, + X509V1IssuerNameCStruct[] = {INTEL_X509V3_CERT_R08, 5, INTEL_X509_C_DATATYPE}, + X509V1IssuerNameLDAP[] = {INTEL_X509V3_CERT_R08, 5, INTEL_X509_LDAPSTRING_DATATYPE}, + X509V1ValidityNotBefore[] = {INTEL_X509V3_CERT_R08, 6}, + X509V1ValidityNotAfter[] = {INTEL_X509V3_CERT_R08, 7}, + X509V1SubjectName[] = {INTEL_X509V3_CERT_R08, 8}, + X509V1SubjectNameCStruct[] = {INTEL_X509V3_CERT_R08, 8, INTEL_X509_C_DATATYPE}, + X509V1SubjectNameLDAP[] = {INTEL_X509V3_CERT_R08, 8, INTEL_X509_LDAPSTRING_DATATYPE}, + X509V1SubjectPublicKeyAlgorithm[] = {INTEL_X509V3_CERT_R08, 9}, + X509V1SubjectPublicKey[] = {INTEL_X509V3_CERT_R08, 10}, + X509V1CertificateIssuerUniqueId[] = {INTEL_X509V3_CERT_R08, 11}, + X509V1CertificateSubjectUniqueId[] = {INTEL_X509V3_CERT_R08, 12}, + X509V3CertificateExtensionStruct[] = {INTEL_X509V3_CERT_R08, 13}, + X509V3CertificateExtensionCStruct[] = {INTEL_X509V3_CERT_R08, 13, INTEL_X509_C_DATATYPE}, + X509V3CertificateNumberOfExtensions[] = {INTEL_X509V3_CERT_R08, 14}, + X509V3CertificateExtensionId[] = {INTEL_X509V3_CERT_R08, 15}, + X509V3CertificateExtensionCritical[] = {INTEL_X509V3_CERT_R08, 16}, + X509V3CertificateExtensionValue[] = {INTEL_X509V3_CERT_R08, 17}, + X509V1SubjectPublicKeyAlgorithmParameters[] = {INTEL_X509V3_CERT_R08, 18}, + X509V3CertificateExtensionType[] = {INTEL_X509V3_CERT_R08, 19}, + CSSMKeyStruct[] = {INTEL_X509V3_CERT_R08, 20}, + X509V1SubjectPublicKeyCStruct[] = {INTEL_X509V3_CERT_R08, 20, INTEL_X509_C_DATATYPE}, + X509V3CertificateExtensionsStruct[] = {INTEL_X509V3_CERT_R08, 21}, + X509V3CertificateExtensionsCStruct[] = {INTEL_X509V3_CERT_R08, 21, INTEL_X509_C_DATATYPE}, + X509V1SubjectNameStd[] = {INTEL_X509V3_CERT_R08, 22}, + X509V1IssuerNameStd[] = {INTEL_X509V3_CERT_R08, 23}, + + /* Signature OID Fields */ + X509V1SignatureStruct[] = {INTEL_X509V3_SIGN_R08, 0}, + X509V1SignatureCStruct[] = {INTEL_X509V3_SIGN_R08, 0, INTEL_X509_C_DATATYPE}, + /* for the algorithm ID in the cert proper */ + X509V1SignatureAlgorithm[] = {INTEL_X509V3_SIGN_R08, 1}, + /* for the one in TBSCert */ + X509V1SignatureAlgorithmTBS[] = {INTEL_X509V3_SIGN_R08, 10}, + X509V1SignatureAlgorithmParameters[] = {INTEL_X509V3_SIGN_R08, 3}, + X509V1Signature[] = {INTEL_X509V3_SIGN_R08, 2}, + + /* Extension OID Fields */ + SubjectSignatureBitmap[] = {INTEL_X509V3_CERT_PRIVATE_EXTENSIONS, 1}, + SubjectPicture[] = {INTEL_X509V3_CERT_PRIVATE_EXTENSIONS, 2}, + SubjectEmailAddress[] = {INTEL_X509V3_CERT_PRIVATE_EXTENSIONS, 3}, + UseExemptions[] = {INTEL_X509V3_CERT_PRIVATE_EXTENSIONS, 4}; + + +const CSSM_OID + + /* Certificate OIDS */ + CSSMOID_X509V3SignedCertificate = {INTEL_X509V3_CERT_R08_LENGTH+1, (uint8 *)X509V3SignedCertificate}, + CSSMOID_X509V3SignedCertificateCStruct = {INTEL_X509V3_CERT_R08_LENGTH+2, + (uint8 *)X509V3SignedCertificateCStruct}, + CSSMOID_X509V3Certificate = {INTEL_X509V3_CERT_R08_LENGTH+1, (uint8 *)X509V3Certificate}, + CSSMOID_X509V3CertificateCStruct = {INTEL_X509V3_CERT_R08_LENGTH+2, (uint8 *)X509V3CertificateCStruct}, + CSSMOID_X509V1Version = {INTEL_X509V3_CERT_R08_LENGTH+1, (uint8 *)X509V1Version}, + CSSMOID_X509V1SerialNumber = {INTEL_X509V3_CERT_R08_LENGTH+1, (uint8 *)X509V1SerialNumber}, + CSSMOID_X509V1IssuerName = {INTEL_X509V3_CERT_R08_LENGTH+1, (uint8 *)X509V1IssuerName}, + CSSMOID_X509V1IssuerNameStd = {INTEL_X509V3_CERT_R08_LENGTH+1, (uint8 *)X509V1IssuerNameStd}, + CSSMOID_X509V1IssuerNameCStruct = {INTEL_X509V3_CERT_R08_LENGTH+2, (uint8 *)X509V1IssuerNameCStruct}, + CSSMOID_X509V1IssuerNameLDAP = {INTEL_X509V3_CERT_R08_LENGTH+2, (uint8 *)X509V1IssuerNameLDAP}, + CSSMOID_X509V1ValidityNotBefore = {INTEL_X509V3_CERT_R08_LENGTH+1, (uint8 *)X509V1ValidityNotBefore}, + CSSMOID_X509V1ValidityNotAfter = {INTEL_X509V3_CERT_R08_LENGTH+1, (uint8 *)X509V1ValidityNotAfter}, + CSSMOID_X509V1SubjectName = {INTEL_X509V3_CERT_R08_LENGTH+1, (uint8 *)X509V1SubjectName}, + CSSMOID_X509V1SubjectNameStd = {INTEL_X509V3_CERT_R08_LENGTH+1, (uint8 *)X509V1SubjectNameStd}, + CSSMOID_X509V1SubjectNameCStruct = {INTEL_X509V3_CERT_R08_LENGTH+2, (uint8 *)X509V1SubjectNameCStruct}, + CSSMOID_X509V1SubjectNameLDAP = {INTEL_X509V3_CERT_R08_LENGTH+2, (uint8 *)X509V1SubjectNameLDAP}, + CSSMOID_CSSMKeyStruct = {INTEL_X509V3_CERT_R08_LENGTH+1, (uint8 *)CSSMKeyStruct}, + CSSMOID_X509V1SubjectPublicKeyCStruct = {INTEL_X509V3_CERT_R08_LENGTH+2, + (uint8 *)X509V1SubjectPublicKeyCStruct}, + CSSMOID_X509V1SubjectPublicKeyAlgorithm = {INTEL_X509V3_CERT_R08_LENGTH+1, + (uint8 *)X509V1SubjectPublicKeyAlgorithm}, + CSSMOID_X509V1SubjectPublicKeyAlgorithmParameters = {INTEL_X509V3_CERT_R08_LENGTH+1, + (uint8 *)X509V1SubjectPublicKeyAlgorithmParameters}, + CSSMOID_X509V1SubjectPublicKey = {INTEL_X509V3_CERT_R08_LENGTH+1, (uint8 *)X509V1SubjectPublicKey}, + CSSMOID_X509V1CertificateIssuerUniqueId = {INTEL_X509V3_CERT_R08_LENGTH+1, + (uint8 *)X509V1CertificateIssuerUniqueId}, + CSSMOID_X509V1CertificateSubjectUniqueId = {INTEL_X509V3_CERT_R08_LENGTH+1, + (uint8 *)X509V1CertificateSubjectUniqueId}, + CSSMOID_X509V3CertificateExtensionsStruct = {INTEL_X509V3_CERT_R08_LENGTH+1, + (uint8 *)X509V3CertificateExtensionsStruct}, + CSSMOID_X509V3CertificateExtensionsCStruct = {INTEL_X509V3_CERT_R08_LENGTH+2, + (uint8 *)X509V3CertificateExtensionsCStruct}, + CSSMOID_X509V3CertificateNumberOfExtensions = {INTEL_X509V3_CERT_R08_LENGTH+1, + (uint8 *)X509V3CertificateNumberOfExtensions}, + CSSMOID_X509V3CertificateExtensionStruct = {INTEL_X509V3_CERT_R08_LENGTH+1, + (uint8 *)X509V3CertificateExtensionStruct}, + CSSMOID_X509V3CertificateExtensionCStruct = {INTEL_X509V3_CERT_R08_LENGTH+2, + (uint8 *)X509V3CertificateExtensionCStruct}, + CSSMOID_X509V3CertificateExtensionId = {INTEL_X509V3_CERT_R08_LENGTH+1, + (uint8 *)X509V3CertificateExtensionId}, + CSSMOID_X509V3CertificateExtensionCritical = {INTEL_X509V3_CERT_R08_LENGTH+1, + (uint8 *)X509V3CertificateExtensionCritical}, + CSSMOID_X509V3CertificateExtensionType = {INTEL_X509V3_CERT_R08_LENGTH+1, + (uint8 *)X509V3CertificateExtensionType}, + CSSMOID_X509V3CertificateExtensionValue = {INTEL_X509V3_CERT_R08_LENGTH+1, + (uint8 *)X509V3CertificateExtensionValue}, + + /* Signature OID Fields */ + CSSMOID_X509V1SignatureStruct = {INTEL_X509V3_SIGN_R08_LENGTH+1, (uint8 *)X509V1SignatureStruct}, + CSSMOID_X509V1SignatureCStruct = {INTEL_X509V3_SIGN_R08_LENGTH+2, (uint8 *)X509V1SignatureCStruct}, + CSSMOID_X509V1SignatureAlgorithm = {INTEL_X509V3_SIGN_R08_LENGTH+1, (uint8 *)X509V1SignatureAlgorithm}, + CSSMOID_X509V1SignatureAlgorithmTBS = {INTEL_X509V3_SIGN_R08_LENGTH+1, (uint8 *)X509V1SignatureAlgorithmTBS}, + CSSMOID_X509V1SignatureAlgorithmParameters = {INTEL_X509V3_SIGN_R08_LENGTH+1, + (uint8 *)X509V1SignatureAlgorithmParameters}, + CSSMOID_X509V1Signature = {INTEL_X509V3_SIGN_R08_LENGTH+1, (uint8 *)X509V1Signature}, + + /* Extension OID Fields */ + CSSMOID_SubjectSignatureBitmap = {INTEL_X509V3_CERT_PRIVATE_EXTENSIONS_LENGTH+1, (uint8 *)SubjectSignatureBitmap}, + CSSMOID_SubjectPicture = {INTEL_X509V3_CERT_PRIVATE_EXTENSIONS_LENGTH+1, (uint8 *)SubjectPicture}, + CSSMOID_SubjectEmailAddress = {INTEL_X509V3_CERT_PRIVATE_EXTENSIONS_LENGTH+1, (uint8 *)SubjectEmailAddress}, + CSSMOID_UseExemptions = {INTEL_X509V3_CERT_PRIVATE_EXTENSIONS_LENGTH+1, (uint8 *)UseExemptions}; + + +/*** + *** Apple addenda. + ***/ + +/* + * Standard Cert extensions. + */ +static const uint8 + OID_SubjectDirectoryAttributes[] = { OID_EXTENSION, 9 }, + OID_SubjectKeyIdentifier[] = { OID_EXTENSION, 14 }, + OID_KeyUsage[] = { OID_EXTENSION, 15 }, + OID_PrivateKeyUsagePeriod[] = { OID_EXTENSION, 16 }, + OID_SubjectAltName[] = { OID_EXTENSION, 17 }, + OID_IssuerAltName[] = { OID_EXTENSION, 18 }, + OID_BasicConstraints[] = { OID_EXTENSION, 19 }, + OID_CrlNumber[] = { OID_EXTENSION, 20 }, + OID_CrlReason[] = { OID_EXTENSION, 21 }, + OID_HoldInstructionCode[] = { OID_EXTENSION, 23 }, + OID_InvalidityDate[] = { OID_EXTENSION, 24 }, + OID_DeltaCrlIndicator[] = { OID_EXTENSION, 27 }, + OID_IssuingDistributionPoint[] = { OID_EXTENSION, 28 }, + OID_CertIssuer[] = { OID_EXTENSION, 29 }, + OID_NameConstraints[] = { OID_EXTENSION, 30 }, + OID_CrlDistributionPoints[] = { OID_EXTENSION, 31 }, + OID_CertificatePolicies[] = { OID_EXTENSION, 32 }, + OID_PolicyMappings[] = { OID_EXTENSION, 33 }, + OID_AuthorityKeyIdentifier[] = { OID_EXTENSION, 35 }, + OID_PolicyConstraints[] = { OID_EXTENSION, 36 }, + OID_ExtendedKeyUsage[] = { OID_EXTENSION, 37 }, + OID_InhibitAnyPolicy[] = { OID_EXTENSION, 54 }, + OID_AuthorityInfoAccess[] = { OID_PE, 1 }, + OID_BiometricInfo[] = { OID_PE, 2 }, + OID_QC_Statements[] = { OID_PE, 3 }, + OID_SubjectInfoAccess[] = { OID_PE, 11 }, + + /* Individual OIDS appearing in an ExtendedKeyUsage extension */ + OID_ExtendedKeyUsageAny[] = { OID_EXTENSION, 37, 0 }, + OID_KP_ServerAuth[] = { OID_KP, 1 }, + OID_KP_ClientAuth[] = { OID_KP, 2 }, + OID_KP_ExtendedUseCodeSigning[] = { OID_KP, 3 }, + OID_KP_EmailProtection[] = { OID_KP, 4 }, + OID_KP_TimeStamping[] = { OID_KP, 8 }, + OID_KP_OCSPSigning[] = { OID_KP, 9 }, + /* Kerberos PKINIT Extended Key Use values */ + OID_KERBv5_PKINIT_KP_CLIENT_AUTH[] = { OID_KERBv5_PKINIT, 4 }, + OID_KERBv5_PKINIT_KP_KDC[] = { OID_KERBv5_PKINIT, 5 }, + /* IPSec */ + OID_EKU_IPSec[] = { 0x2B, 0x06, 0x01, 0x05, 0x05, 0x08, 0x02, 0x02 }, + + /* .mac Certificate Extended Key Use values */ + OID_DOTMAC_CERT_EXTENSION[] = { APPLE_DOTMAC_CERT_EXTEN_OID }, + OID_DOTMAC_CERT_IDENTITY[] = { APPLE_DOTMAC_CERT_EXTEN_OID, 1 }, + OID_DOTMAC_CERT_EMAIL_SIGN[] = { APPLE_DOTMAC_CERT_EXTEN_OID, 2 }, + OID_DOTMAC_CERT_EMAIL_ENCRYPT[] = { APPLE_DOTMAC_CERT_EXTEN_OID, 3 }, + /* Other Apple extended key usage values */ + OID_APPLE_EKU_CODE_SIGNING[] = { APPLE_EKU_CODE_SIGNING }, + OID_APPLE_EKU_CODE_SIGNING_DEV[] = { APPLE_EKU_CODE_SIGNING, 1 }, + OID_APPLE_EKU_RESOURCE_SIGNING[] = { APPLE_EKU_CODE_SIGNING, 4 }, + OID_APPLE_EKU_ICHAT_SIGNING[] = { APPLE_EKU_OID, 2 }, + OID_APPLE_EKU_ICHAT_ENCRYPTION[] = { APPLE_EKU_OID, 3 }, + OID_APPLE_EKU_SYSTEM_IDENTITY[] = { APPLE_EKU_OID, 4 }, + /* Apple cert policies */ + OID_APPLE_CERT_POLICY[] = { APPLE_CERT_POLICIES, 1 }, + OID_DOTMAC_CERT_POLICY[] = { APPLE_CERT_POLICIES, 2 }, + OID_ADC_CERT_POLICY[] = { APPLE_CERT_POLICIES, 3 }, + OID_APPLE_CERT_POLICY_MACAPPSTORE[] = { APPLE_CERT_POLICIES_MACAPPSTORE }, + OID_APPLE_CERT_POLICY_MACAPPSTORE_RECEIPT[] = { APPLE_CERT_POLICIES_MACAPPSTORE_RECEIPT }, + OID_APPLE_CERT_POLICY_APPLEID[] = { APPLE_CERT_POLICIES_APPLEID }, + OID_APPLE_CERT_POLICY_APPLEID_SHARING[] = { APPLE_CERT_POLICIES_APPLEID_SHARING }, + + /* Apple-specific extensions */ + OID_APPLE_EXTENSION[] = { APPLE_EXTENSION_OID }, + OID_APPLE_EXTENSION_CODE_SIGNING[] = { APPLE_EXTENSION_CODE_SIGNING }, + OID_APPLE_EXTENSION_APPLE_SIGNING[] = { APPLE_EXTENSION_CODE_SIGNING, 1 }, + OID_APPLE_EXTENSION_ADC_DEV_SIGNING[] = { APPLE_EXTENSION_CODE_SIGNING, 2 }, + OID_APPLE_EXTENSION_ADC_APPLE_SIGNING[] = { APPLE_EXTENSION_CODE_SIGNING, 3 }, + OID_APPLE_EXTENSION_MACAPPSTORE_RECEIPT[] = { APPLE_EXTENSION_MACAPPSTORE_RECEIPT }, + OID_APPLE_EXTENSION_INTERMEDIATE_MARKER[] = { APPLE_EXTENSION_INTERMEDIATE_MARKER }, + OID_APPLE_EXTENSION_WWDR_INTERMEDIATE[] = { APPLE_EXTENSION_WWDR_INTERMEDIATE }, + OID_APPLE_EXTENSION_ITMS_INTERMEDIATE[] = { APPLE_EXTENSION_ITMS_INTERMEDIATE }, + OID_APPLE_EXTENSION_AAI_INTERMEDIATE[] = { APPLE_EXTENSION_AAI_INTERMEDIATE }, + OID_APPLE_EXTENSION_APPLEID_INTERMEDIATE[] = { APPLE_EXTENSION_APPLEID_INTERMEDIATE }, + OID_APPLE_EXTENSION_APPLEID_SHARING[] = { APPLE_EXTENSION_APPLEID_SHARING } +; + +#define OID_PKCS_CE_LENGTH OID_EXTENSION_LENGTH + 1 + +const CSSM_OID +CSSMOID_SubjectDirectoryAttributes = { OID_PKCS_CE_LENGTH, (uint8 *)OID_SubjectDirectoryAttributes}, +CSSMOID_SubjectKeyIdentifier = { OID_PKCS_CE_LENGTH, (uint8 *)OID_SubjectKeyIdentifier}, +CSSMOID_KeyUsage = { OID_PKCS_CE_LENGTH, (uint8 *)OID_KeyUsage}, +CSSMOID_PrivateKeyUsagePeriod = { OID_PKCS_CE_LENGTH, (uint8 *)OID_PrivateKeyUsagePeriod}, +CSSMOID_SubjectAltName = { OID_PKCS_CE_LENGTH, (uint8 *)OID_SubjectAltName}, +CSSMOID_IssuerAltName = { OID_PKCS_CE_LENGTH, (uint8 *)OID_IssuerAltName}, +CSSMOID_BasicConstraints = { OID_PKCS_CE_LENGTH, (uint8 *)OID_BasicConstraints}, +CSSMOID_CrlNumber = { OID_PKCS_CE_LENGTH, (uint8 *)OID_CrlNumber}, +CSSMOID_CrlReason = { OID_PKCS_CE_LENGTH, (uint8 *)OID_CrlReason}, +CSSMOID_HoldInstructionCode = { OID_PKCS_CE_LENGTH, (uint8 *)OID_HoldInstructionCode}, +CSSMOID_InvalidityDate = { OID_PKCS_CE_LENGTH, (uint8 *)OID_InvalidityDate}, +CSSMOID_DeltaCrlIndicator = { OID_PKCS_CE_LENGTH, (uint8 *)OID_DeltaCrlIndicator}, +CSSMOID_IssuingDistributionPoint = { OID_PKCS_CE_LENGTH, (uint8 *)OID_IssuingDistributionPoint}, +/* for backwards compatibility... */ +CSSMOID_IssuingDistributionPoints = { OID_PKCS_CE_LENGTH, (uint8 *)OID_IssuingDistributionPoint}, +CSSMOID_CertIssuer = { OID_PKCS_CE_LENGTH, (uint8 *)OID_CertIssuer}, +CSSMOID_NameConstraints = { OID_PKCS_CE_LENGTH, (uint8 *)OID_NameConstraints}, +CSSMOID_CrlDistributionPoints = { OID_PKCS_CE_LENGTH, (uint8 *)OID_CrlDistributionPoints}, +CSSMOID_CertificatePolicies = { OID_PKCS_CE_LENGTH, (uint8 *)OID_CertificatePolicies}, +CSSMOID_PolicyMappings = { OID_PKCS_CE_LENGTH, (uint8 *)OID_PolicyMappings}, +CSSMOID_PolicyConstraints = { OID_PKCS_CE_LENGTH, (uint8 *)OID_PolicyConstraints}, +CSSMOID_AuthorityKeyIdentifier = { OID_PKCS_CE_LENGTH, (uint8 *)OID_AuthorityKeyIdentifier}, +CSSMOID_ExtendedKeyUsage = { OID_PKCS_CE_LENGTH, (uint8 *)OID_ExtendedKeyUsage}, +CSSMOID_InhibitAnyPolicy = { OID_PKCS_CE_LENGTH, (uint8 *)OID_InhibitAnyPolicy}, +CSSMOID_AuthorityInfoAccess = { OID_PE_LENGTH+1, (uint8 *)OID_AuthorityInfoAccess}, +CSSMOID_BiometricInfo = { OID_PE_LENGTH+1, (uint8 *)OID_BiometricInfo}, +CSSMOID_QC_Statements = { OID_PE_LENGTH+1, (uint8 *)OID_QC_Statements}, +CSSMOID_SubjectInfoAccess = { OID_PE_LENGTH+1, (uint8 *)OID_SubjectInfoAccess}, +CSSMOID_ExtendedKeyUsageAny = { OID_PKCS_CE_LENGTH+1, (uint8 *)OID_ExtendedKeyUsageAny}, +CSSMOID_ServerAuth = { OID_KP_LENGTH+1, (uint8 *)OID_KP_ServerAuth}, +CSSMOID_ClientAuth = { OID_KP_LENGTH+1, (uint8 *)OID_KP_ClientAuth}, +CSSMOID_ExtendedUseCodeSigning = { OID_KP_LENGTH+1, (uint8 *)OID_KP_ExtendedUseCodeSigning}, +CSSMOID_EmailProtection = { OID_KP_LENGTH+1, (uint8 *)OID_KP_EmailProtection}, +CSSMOID_TimeStamping = { OID_KP_LENGTH+1, (uint8 *)OID_KP_TimeStamping}, +CSSMOID_OCSPSigning = { OID_KP_LENGTH+1, (uint8 *)OID_KP_OCSPSigning}, +CSSMOID_KERBv5_PKINIT_KP_CLIENT_AUTH = { OID_KERBv5_PKINIT_LEN + 1, + (uint8 *)OID_KERBv5_PKINIT_KP_CLIENT_AUTH }, +CSSMOID_KERBv5_PKINIT_KP_KDC = { OID_KERBv5_PKINIT_LEN + 1, + (uint8 *)OID_KERBv5_PKINIT_KP_KDC }, +CSSMOID_EKU_IPSec = { 8, (uint8 *)OID_EKU_IPSec }, +CSSMOID_DOTMAC_CERT_EXTENSION = { APPLE_DOTMAC_CERT_EXTEN_OID_LENGTH, + (uint8 *)OID_DOTMAC_CERT_EXTENSION }, +CSSMOID_DOTMAC_CERT_IDENTITY = { APPLE_DOTMAC_CERT_EXTEN_OID_LENGTH + 1, + (uint8 *)OID_DOTMAC_CERT_IDENTITY }, +CSSMOID_DOTMAC_CERT_EMAIL_SIGN = { APPLE_DOTMAC_CERT_EXTEN_OID_LENGTH + 1, + (uint8 *)OID_DOTMAC_CERT_EMAIL_SIGN }, +CSSMOID_DOTMAC_CERT_EMAIL_ENCRYPT = { APPLE_DOTMAC_CERT_EXTEN_OID_LENGTH + 1, + (uint8 *)OID_DOTMAC_CERT_EMAIL_ENCRYPT }, +CSSMOID_APPLE_CERT_POLICY = { APPLE_CERT_POLICIES_LENGTH + 1, + (uint8 *)OID_APPLE_CERT_POLICY }, +CSSMOID_DOTMAC_CERT_POLICY = { APPLE_CERT_POLICIES_LENGTH + 1, + (uint8 *)OID_DOTMAC_CERT_POLICY }, +CSSMOID_ADC_CERT_POLICY = { APPLE_CERT_POLICIES_LENGTH + 1, + (uint8 *)OID_ADC_CERT_POLICY }, +CSSMOID_MACAPPSTORE_CERT_POLICY = { APPLE_CERT_POLICIES_MACAPPSTORE_LENGTH, + (uint8 *)OID_APPLE_CERT_POLICY_MACAPPSTORE }, +CSSMOID_MACAPPSTORE_RECEIPT_CERT_POLICY = { APPLE_CERT_POLICIES_MACAPPSTORE_RECEIPT_LENGTH, + (uint8 *)OID_APPLE_CERT_POLICY_MACAPPSTORE_RECEIPT }, +CSSMOID_APPLEID_CERT_POLICY = { APPLE_CERT_POLICIES_APPLEID_LENGTH, + (uint8 *)OID_APPLE_CERT_POLICY_APPLEID }, +CSSMOID_APPLEID_SHARING_CERT_POLICY = { APPLE_CERT_POLICIES_APPLEID_SHARING_LENGTH, + (uint8 *)OID_APPLE_CERT_POLICY_APPLEID_SHARING }, +CSSMOID_APPLE_EKU_CODE_SIGNING = { APPLE_EKU_CODE_SIGNING_LENGTH, + (uint8 *)OID_APPLE_EKU_CODE_SIGNING }, +CSSMOID_APPLE_EKU_CODE_SIGNING_DEV = { APPLE_EKU_CODE_SIGNING_LENGTH + 1, + (uint8 *)OID_APPLE_EKU_CODE_SIGNING_DEV }, +CSSMOID_APPLE_EKU_RESOURCE_SIGNING = { APPLE_EKU_CODE_SIGNING_LENGTH + 1, + (uint8 *)OID_APPLE_EKU_RESOURCE_SIGNING }, +CSSMOID_APPLE_EKU_ICHAT_SIGNING = { APPLE_EKU_OID_LENGTH + 1, + (uint8 *)OID_APPLE_EKU_ICHAT_SIGNING }, +CSSMOID_APPLE_EKU_ICHAT_ENCRYPTION = { APPLE_EKU_OID_LENGTH + 1, + (uint8 *)OID_APPLE_EKU_ICHAT_ENCRYPTION }, +CSSMOID_APPLE_EKU_SYSTEM_IDENTITY = { APPLE_EKU_OID_LENGTH + 1, + (uint8 *)OID_APPLE_EKU_SYSTEM_IDENTITY }, +CSSMOID_APPLE_EXTENSION = { APPLE_EXTENSION_OID_LENGTH, + (uint8 *)OID_APPLE_EXTENSION }, +CSSMOID_APPLE_EXTENSION_CODE_SIGNING = { APPLE_EXTENSION_CODE_SIGNING_LENGTH, + (uint8 *)OID_APPLE_EXTENSION_CODE_SIGNING }, +CSSMOID_APPLE_EXTENSION_APPLE_SIGNING = { APPLE_EXTENSION_CODE_SIGNING_LENGTH + 1, + (uint8 *)OID_APPLE_EXTENSION_APPLE_SIGNING }, +CSSMOID_APPLE_EXTENSION_ADC_DEV_SIGNING = { APPLE_EXTENSION_CODE_SIGNING_LENGTH + 2, + (uint8 *)OID_APPLE_EXTENSION_ADC_DEV_SIGNING }, +CSSMOID_APPLE_EXTENSION_ADC_APPLE_SIGNING = { APPLE_EXTENSION_CODE_SIGNING_LENGTH + 3, + (uint8 *)OID_APPLE_EXTENSION_ADC_DEV_SIGNING }, +CSSMOID_APPLE_EXTENSION_MACAPPSTORE_RECEIPT = { APPLE_EXTENSION_MACAPPSTORE_RECEIPT_LENGTH, + (uint8 *)OID_APPLE_EXTENSION_MACAPPSTORE_RECEIPT }, +CSSMOID_APPLE_EXTENSION_INTERMEDIATE_MARKER = { APPLE_EXTENSION_INTERMEDIATE_MARKER_LENGTH, + (uint8 *)OID_APPLE_EXTENSION_INTERMEDIATE_MARKER }, +CSSMOID_APPLE_EXTENSION_WWDR_INTERMEDIATE = { APPLE_EXTENSION_WWDR_INTERMEDIATE_LENGTH + 1, + (uint8 *)OID_APPLE_EXTENSION_WWDR_INTERMEDIATE }, +CSSMOID_APPLE_EXTENSION_ITMS_INTERMEDIATE = { APPLE_EXTENSION_ITMS_INTERMEDIATE_LENGTH + 1, + (uint8 *)OID_APPLE_EXTENSION_ITMS_INTERMEDIATE }, +CSSMOID_APPLE_EXTENSION_AAI_INTERMEDIATE = { APPLE_EXTENSION_AAI_INTERMEDIATE_LENGTH + 1, + (uint8 *)OID_APPLE_EXTENSION_AAI_INTERMEDIATE }, +CSSMOID_APPLE_EXTENSION_APPLEID_INTERMEDIATE = { APPLE_EXTENSION_APPLEID_INTERMEDIATE_LENGTH + 1, + (uint8 *)OID_APPLE_EXTENSION_APPLEID_INTERMEDIATE }, +CSSMOID_APPLE_EXTENSION_APPLEID_SHARING = { APPLE_EXTENSION_APPLEID_INTERMEDIATE_LENGTH + 1, + (uint8 *)OID_APPLE_EXTENSION_APPLEID_SHARING } +; + +/* Apple Intermediate Marker OIDs */ +#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 + * + * 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 + +/* + * Netscape extensions. + * + * netscape-cert-type OBJECT IDENTIFIER ::= + * { 2 16 840 1 113730 1 1 } + * + * BER = 06 08 60 86 48 01 86 F8 42 01 01 + */ +static const uint8 OID_NetscapeCertType[] = {NETSCAPE_CERT_EXTEN, 1}; +const CSSM_OID CSSMOID_NetscapeCertType = + {NETSCAPE_CERT_EXTEN_LENGTH + 1, (uint8 *)OID_NetscapeCertType}; + +/* + * netscape-cert-sequence ::= { 2 16 840 1 113730 2 5 } + * + * BER = 06 09 60 86 48 01 86 F8 42 02 05 + */ +static const uint8 OID_NetscapeCertSequence[] = { NETSCAPE_BASE_OID, 2, 5 }; +const CSSM_OID CSSMOID_NetscapeCertSequence = + { NETSCAPE_BASE_OID_LEN + 2, (uint8 *)OID_NetscapeCertSequence }; + +/* + * Netscape version of ServerGatedCrypto ExtendedKeyUse. + * OID { 2 16 840 1 113730 4 1 } + */ +static const uint8 OID_Netscape_SGC[] = {NETSCAPE_CERT_POLICY, 1}; +const CSSM_OID CSSMOID_NetscapeSGC = + {NETSCAPE_CERT_POLICY_LENGTH + 1, (uint8 *)OID_Netscape_SGC}; + +/* + * Microsoft version of ServerGatedCrypto ExtendedKeyUse. + * OID { 1 3 6 1 4 1 311 10 3 3 } + */ +static const uint8 OID_Microsoft_SGC[] = {0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x0A, 0x03, 0x03}; +const CSSM_OID CSSMOID_MicrosoftSGC = + {10, (uint8 *)OID_Microsoft_SGC}; + +/* + * .mac Certificate Extended Key Use values. + */ diff --git a/libsecurity_cssm/lib/oidscert.h b/libsecurity_cssm/lib/oidscert.h new file mode 100644 index 00000000..0731c7ca --- /dev/null +++ b/libsecurity_cssm/lib/oidscert.h @@ -0,0 +1,208 @@ +/* + * Copyright (c) 1999-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@ + * + * oidscert.h -- Object Identifiers for X509 Certificate Library + */ + +#ifndef _OIDSCERT_H_ +#define _OIDSCERT_H_ 1 + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define INTEL_X509V3_CERT_R08 INTEL_SEC_FORMATS, 1, 1 +#define INTEL_X509V3_CERT_R08_LENGTH INTEL_SEC_FORMATS_LENGTH + 2 + +/* Prefix for defining Certificate Extension field OIDs */ +#define INTEL_X509V3_CERT_PRIVATE_EXTENSIONS INTEL_X509V3_CERT_R08, 50 +#define INTEL_X509V3_CERT_PRIVATE_EXTENSIONS_LENGTH INTEL_X509V3_CERT_R08_LENGTH + 1 + +/* Prefix for defining signature field OIDs */ +#define INTEL_X509V3_SIGN_R08 INTEL_SEC_FORMATS, 3, 2 +#define INTEL_X509V3_SIGN_R08_LENGTH INTEL_SEC_FORMATS_LENGTH + 2 + +/* 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 + +/* Certificate OIDS */ +extern const CSSM_OID + + CSSMOID_X509V3SignedCertificate DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_X509V3SignedCertificateCStruct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_X509V3Certificate DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_X509V3CertificateCStruct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_X509V1Version DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_X509V1SerialNumber DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_X509V1IssuerName DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, // normalized & encoded + CSSMOID_X509V1IssuerNameStd DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, // encoded + CSSMOID_X509V1IssuerNameCStruct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, // CSSM_X509_NAME + CSSMOID_X509V1IssuerNameLDAP DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_X509V1ValidityNotBefore DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_X509V1ValidityNotAfter DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_X509V1SubjectName DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, // normalized & encoded + CSSMOID_X509V1SubjectNameStd DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, // encoded + CSSMOID_X509V1SubjectNameCStruct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, // CSSM_X509_NAME + CSSMOID_X509V1SubjectNameLDAP DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_CSSMKeyStruct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_X509V1SubjectPublicKeyCStruct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_X509V1SubjectPublicKeyAlgorithm DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_X509V1SubjectPublicKeyAlgorithmParameters DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_X509V1SubjectPublicKey DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_X509V1CertificateIssuerUniqueId DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_X509V1CertificateSubjectUniqueId DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_X509V3CertificateExtensionsStruct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_X509V3CertificateExtensionsCStruct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_X509V3CertificateNumberOfExtensions DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_X509V3CertificateExtensionStruct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_X509V3CertificateExtensionCStruct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_X509V3CertificateExtensionId DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_X509V3CertificateExtensionCritical DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_X509V3CertificateExtensionType DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_X509V3CertificateExtensionValue DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + + /* Signature OID Fields */ + CSSMOID_X509V1SignatureStruct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_X509V1SignatureCStruct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_X509V1SignatureAlgorithm DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_X509V1SignatureAlgorithmTBS DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_X509V1SignatureAlgorithmParameters DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_X509V1Signature DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + + /* Extension OID Fields */ + CSSMOID_SubjectSignatureBitmap DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_SubjectPicture DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_SubjectEmailAddress DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_UseExemptions DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/*** + *** Apple addenda + ***/ + +/* + * Standard Cert and CRL extensions. + */ +extern const CSSM_OID + CSSMOID_SubjectDirectoryAttributes DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_SubjectKeyIdentifier DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_KeyUsage DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_PrivateKeyUsagePeriod DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_SubjectAltName DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_IssuerAltName DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_BasicConstraints DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_CrlNumber DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_CrlReason DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_HoldInstructionCode DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_InvalidityDate DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_DeltaCrlIndicator DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_IssuingDistributionPoint DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_IssuingDistributionPoints DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_CertIssuer DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_NameConstraints DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_CrlDistributionPoints DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_CertificatePolicies DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_PolicyMappings DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_PolicyConstraints DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_AuthorityKeyIdentifier DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_ExtendedKeyUsage DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_InhibitAnyPolicy DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_AuthorityInfoAccess DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_BiometricInfo DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_QC_Statements DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_SubjectInfoAccess DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_ExtendedKeyUsageAny DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_ServerAuth DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_ClientAuth DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_ExtendedUseCodeSigning DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_EmailProtection DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_TimeStamping DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_OCSPSigning DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_KERBv5_PKINIT_KP_CLIENT_AUTH DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_KERBv5_PKINIT_KP_KDC DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_EKU_IPSec DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_DOTMAC_CERT_EXTENSION DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_DOTMAC_CERT_IDENTITY DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_DOTMAC_CERT_EMAIL_SIGN DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_DOTMAC_CERT_EMAIL_ENCRYPT DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_APPLE_CERT_POLICY DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_DOTMAC_CERT_POLICY DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_ADC_CERT_POLICY DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_MACAPPSTORE_CERT_POLICY DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_MACAPPSTORE_RECEIPT_CERT_POLICY DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_APPLEID_CERT_POLICY DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_APPLEID_SHARING_CERT_POLICY DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_APPLE_EKU_CODE_SIGNING DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_APPLE_EKU_CODE_SIGNING_DEV DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_APPLE_EKU_RESOURCE_SIGNING DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_APPLE_EKU_ICHAT_SIGNING DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_APPLE_EKU_ICHAT_ENCRYPTION DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_APPLE_EKU_SYSTEM_IDENTITY DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_APPLE_EXTENSION DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_APPLE_EXTENSION_CODE_SIGNING DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_APPLE_EXTENSION_APPLE_SIGNING DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_APPLE_EXTENSION_ADC_DEV_SIGNING DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_APPLE_EXTENSION_ADC_APPLE_SIGNING DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_APPLE_EXTENSION_MACAPPSTORE_RECEIPT DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_APPLE_EXTENSION_INTERMEDIATE_MARKER DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_APPLE_EXTENSION_WWDR_INTERMEDIATE DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_APPLE_EXTENSION_ITMS_INTERMEDIATE DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_APPLE_EXTENSION_AAI_INTERMEDIATE DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + 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 +; + +/* + * Netscape extensions. + */ +extern const CSSM_OID + CSSMOID_NetscapeCertType DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_NetscapeCertSequence DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_NetscapeSGC DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +extern const CSSM_OID CSSMOID_MicrosoftSGC DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* + * Field values for CSSMOID_NetscapeCertType DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, a bit string. + * Assumes a 16 bit field, even though currently only 8 bits + * are defined. + */ +#define CE_NCT_SSL_Client 0x8000 +#define CE_NCT_SSL_Server 0x4000 +#define CE_NCT_SMIME 0x2000 +#define CE_NCT_ObjSign 0x1000 +#define CE_NCT_Reserved 0x0800 +#define CE_NCT_SSL_CA 0x0400 +#define CE_NCT_SMIME_CA 0x0200 +#define CE_NCT_ObjSignCA 0x0100 + +#ifdef __cplusplus +} +#endif + +#endif /* _OIDSCERT_H_ */ diff --git a/libsecurity_cssm/lib/oidscrl.cpp b/libsecurity_cssm/lib/oidscrl.cpp new file mode 100644 index 00000000..6e6532a8 --- /dev/null +++ b/libsecurity_cssm/lib/oidscrl.cpp @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2000-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@ + */ + + +/* + + File: oidscrl.cpp + + Contains: Object Identifiers for X509 CRLs and OCSP + + Copyright (c) 1999,2001-2002,2004 Apple Computer, Inc. All Rights Reserved. + + */ + +#include + +static const uint8 + + /* CRL OIDs */ + X509V2CRLSignedCrlStruct[] = {INTEL_X509V2_CRL_R08, 0}, + X509V2CRLSignedCrlCStruct [] = {INTEL_X509V2_CRL_R08, 0, INTEL_X509_C_DATATYPE}, + X509V2CRLTbsCertListStruct [] = {INTEL_X509V2_CRL_R08, 1}, + X509V2CRLTbsCertListCStruct[] = {INTEL_X509V2_CRL_R08, 1, INTEL_X509_C_DATATYPE}, + X509V2CRLVersion [] = {INTEL_X509V2_CRL_R08, 2}, + X509V1CRLIssuerStruct[] = {INTEL_X509V2_CRL_R08, 3}, + X509V1CRLIssuerNameCStruct[] = {INTEL_X509V2_CRL_R08, 3, INTEL_X509_C_DATATYPE}, + X509V1CRLIssuerNameLDAP[] = {INTEL_X509V2_CRL_R08, 3, + INTEL_X509_LDAPSTRING_DATATYPE}, + X509V1CRLThisUpdate[] = {INTEL_X509V2_CRL_R08, 4}, + X509V1CRLNextUpdate[] = {INTEL_X509V2_CRL_R08, 5}, + + /* CRL Entry (CRL CertList) OIDS */ + X509V1CRLRevokedCertificatesStruct[] = {INTEL_X509V2_CRL_R08, 7}, + X509V1CRLRevokedCertificatesCStruct[] = {INTEL_X509V2_CRL_R08, 7, INTEL_X509_C_DATATYPE}, + X509V1CRLNumberOfRevokedCertEntries[] = {INTEL_X509V2_CRL_R08, 6}, + X509V1CRLRevokedEntryStruct[] = {INTEL_X509V2_CRL_R08, 15}, + X509V1CRLRevokedEntryCStruct[] = {INTEL_X509V2_CRL_R08, 15, INTEL_X509_C_DATATYPE}, + X509V1CRLRevokedEntrySerialNumber[] = {INTEL_X509V2_CRL_R08, 16}, + X509V1CRLRevokedEntryRevocationDate[] = {INTEL_X509V2_CRL_R08, 17}, + + /* CRL Entry (CRL CertList) Extension OIDs */ + X509V2CRLRevokedEntryAllExtensionsStruct[] = {INTEL_X509V2_CRL_R08, 18}, + X509V2CRLRevokedEntryAllExtensionsCStruct[] = {INTEL_X509V2_CRL_R08, 18, INTEL_X509_C_DATATYPE}, + X509V2CRLRevokedEntryNumberOfExtensions[] = {INTEL_X509V2_CRL_R08, 20}, + X509V2CRLRevokedEntrySingleExtensionStruct[]= {INTEL_X509V2_CRL_R08, 19}, + X509V2CRLRevokedEntrySingleExtensionCStruct[]= {INTEL_X509V2_CRL_R08, 19, INTEL_X509_C_DATATYPE}, + X509V2CRLRevokedEntryExtensionId[] = {INTEL_X509V2_CRL_R08, 21}, + X509V2CRLRevokedEntryExtensionCritical[] = {INTEL_X509V2_CRL_R08, 22}, + X509V2CRLRevokedEntryExtensionType[] = {INTEL_X509V2_CRL_R08, 23}, + X509V2CRLRevokedEntryExtensionValue[] = {INTEL_X509V2_CRL_R08, 24}, + + /* CRL Extension OIDs */ + X509V2CRLAllExtensionsStruct[] = {INTEL_X509V2_CRL_R08, 8}, + X509V2CRLAllExtensionsCStruct[] = {INTEL_X509V2_CRL_R08, 8, INTEL_X509_C_DATATYPE}, + X509V2CRLNumberOfExtensions[] = {INTEL_X509V2_CRL_R08, 10}, + X509V2CRLSingleExtensionStruct[] = {INTEL_X509V2_CRL_R08, 9}, + X509V2CRLSingleExtensionCStruct[] = {INTEL_X509V2_CRL_R08, 9, INTEL_X509_C_DATATYPE}, + X509V2CRLExtensionId[] = {INTEL_X509V2_CRL_R08, 11}, + X509V2CRLExtensionCritical[] = {INTEL_X509V2_CRL_R08, 12}, + X509V2CRLExtensionType[] = {INTEL_X509V2_CRL_R08, 13}, + + /* OCSP */ + OID_PKIX_OCSP[] = { OID_AD_OCSP }, + OID_PKIX_OCSP_BASIC[] = { OID_AD_OCSP, 1 }, + OID_PKIX_OCSP_NONCE[] = { OID_AD_OCSP, 2 }, + OID_PKIX_OCSP_CRL[] = { OID_AD_OCSP, 3 }, + OID_PKIX_OCSP_RESPONSE[] = { OID_AD_OCSP, 4 }, + OID_PKIX_OCSP_NOCHECK[] = { OID_AD_OCSP, 5 }, + OID_PKIX_OCSP_ARCHIVE_CUTOFF[] = { OID_AD_OCSP, 6 }, + OID_PKIX_OCSP_SERVICE_LOCATOR[] = { OID_AD_OCSP, 7 }; + +const CSSM_OID + + /* CRL OIDs */ + CSSMOID_X509V2CRLSignedCrlStruct = {INTEL_X509V2_CRL_R08_LENGTH+1, + (uint8 *)X509V2CRLSignedCrlStruct}, + CSSMOID_X509V2CRLSignedCrlCStruct = {INTEL_X509V2_CRL_R08_LENGTH+2, + (uint8 *)X509V2CRLSignedCrlCStruct}, + CSSMOID_X509V2CRLTbsCertListStruct = {INTEL_X509V2_CRL_R08_LENGTH+1, + (uint8 *)X509V2CRLTbsCertListStruct}, + CSSMOID_X509V2CRLTbsCertListCStruct = {INTEL_X509V2_CRL_R08_LENGTH+2, + (uint8 *)X509V2CRLTbsCertListCStruct}, + CSSMOID_X509V2CRLVersion = {INTEL_X509V2_CRL_R08_LENGTH+1, + (uint8 *)X509V2CRLVersion}, + CSSMOID_X509V1CRLIssuerStruct = {INTEL_X509V2_CRL_R08_LENGTH+1, + (uint8 *)X509V1CRLIssuerStruct}, + CSSMOID_X509V1CRLIssuerNameCStruct = {INTEL_X509V2_CRL_R08_LENGTH+2, + (uint8 *)X509V1CRLIssuerNameCStruct}, + CSSMOID_X509V1CRLIssuerNameLDAP = {INTEL_X509V2_CRL_R08_LENGTH+2, + (uint8 *)X509V1CRLIssuerNameLDAP}, + CSSMOID_X509V1CRLThisUpdate = {INTEL_X509V2_CRL_R08_LENGTH+1, + (uint8 *)X509V1CRLThisUpdate}, + CSSMOID_X509V1CRLNextUpdate = {INTEL_X509V2_CRL_R08_LENGTH+1, + (uint8 *)X509V1CRLNextUpdate}, + + /* CRL Entry (CRL CertList) OIDS */ + CSSMOID_X509V1CRLRevokedCertificatesStruct = {INTEL_X509V2_CRL_R08_LENGTH+1, + (uint8 *)X509V1CRLRevokedCertificatesStruct}, + CSSMOID_X509V1CRLRevokedCertificatesCStruct = {INTEL_X509V2_CRL_R08_LENGTH+2, + (uint8 *)X509V1CRLRevokedCertificatesCStruct}, + CSSMOID_X509V1CRLNumberOfRevokedCertEntries = {INTEL_X509V2_CRL_R08_LENGTH+1, + (uint8 *)X509V1CRLNumberOfRevokedCertEntries}, + CSSMOID_X509V1CRLRevokedEntryStruct = {INTEL_X509V2_CRL_R08_LENGTH+1, + (uint8 *)X509V1CRLRevokedEntryStruct}, + CSSMOID_X509V1CRLRevokedEntryCStruct = {INTEL_X509V2_CRL_R08_LENGTH+2, + (uint8 *)X509V1CRLRevokedEntryCStruct}, + CSSMOID_X509V1CRLRevokedEntrySerialNumber = {INTEL_X509V2_CRL_R08_LENGTH+1, + (uint8 *)X509V1CRLRevokedEntrySerialNumber}, + CSSMOID_X509V1CRLRevokedEntryRevocationDate = {INTEL_X509V2_CRL_R08_LENGTH+1, + (uint8 *)X509V1CRLRevokedEntryRevocationDate}, + + /* CRL Entry (CRL CertList) Extension OIDs */ + CSSMOID_X509V2CRLRevokedEntryAllExtensionsStruct = {INTEL_X509V2_CRL_R08_LENGTH+1, + (uint8 *)X509V2CRLRevokedEntryAllExtensionsStruct}, + CSSMOID_X509V2CRLRevokedEntryAllExtensionsCStruct = {INTEL_X509V2_CRL_R08_LENGTH+2, + (uint8 *)X509V2CRLRevokedEntryAllExtensionsCStruct}, + CSSMOID_X509V2CRLRevokedEntryNumberOfExtensions = {INTEL_X509V2_CRL_R08_LENGTH+1, + (uint8 *)X509V2CRLRevokedEntryNumberOfExtensions}, + CSSMOID_X509V2CRLRevokedEntrySingleExtensionStruct = {INTEL_X509V2_CRL_R08_LENGTH+1, + (uint8 *)X509V2CRLRevokedEntrySingleExtensionStruct}, + CSSMOID_X509V2CRLRevokedEntrySingleExtensionCStruct = {INTEL_X509V2_CRL_R08_LENGTH+2, + (uint8 *)X509V2CRLRevokedEntrySingleExtensionCStruct}, + CSSMOID_X509V2CRLRevokedEntryExtensionId = {INTEL_X509V2_CRL_R08_LENGTH+1, + (uint8 *)X509V2CRLRevokedEntryExtensionId}, + CSSMOID_X509V2CRLRevokedEntryExtensionCritical = {INTEL_X509V2_CRL_R08_LENGTH+1, + (uint8 *)X509V2CRLRevokedEntryExtensionCritical}, + CSSMOID_X509V2CRLRevokedEntryExtensionType = {INTEL_X509V2_CRL_R08_LENGTH+1, + (uint8 *)X509V2CRLRevokedEntryExtensionType}, + CSSMOID_X509V2CRLRevokedEntryExtensionValue = {INTEL_X509V2_CRL_R08_LENGTH+1, + (uint8 *)X509V2CRLRevokedEntryExtensionValue}, + + /* CRL Extension OIDs */ + CSSMOID_X509V2CRLAllExtensionsStruct = {INTEL_X509V2_CRL_R08_LENGTH+1, + (uint8 *)X509V2CRLAllExtensionsStruct}, + CSSMOID_X509V2CRLAllExtensionsCStruct = {INTEL_X509V2_CRL_R08_LENGTH+2, + (uint8 *)X509V2CRLAllExtensionsCStruct}, + CSSMOID_X509V2CRLNumberOfExtensions = {INTEL_X509V2_CRL_R08_LENGTH+1, + (uint8 *)X509V2CRLNumberOfExtensions}, + CSSMOID_X509V2CRLSingleExtensionStruct = {INTEL_X509V2_CRL_R08_LENGTH+1, + (uint8 *)X509V2CRLSingleExtensionStruct}, + CSSMOID_X509V2CRLSingleExtensionCStruct = {INTEL_X509V2_CRL_R08_LENGTH+2, + (uint8 *)X509V2CRLSingleExtensionCStruct}, + CSSMOID_X509V2CRLExtensionId = {INTEL_X509V2_CRL_R08_LENGTH+1, + (uint8 *)X509V2CRLExtensionId}, + CSSMOID_X509V2CRLExtensionCritical = {INTEL_X509V2_CRL_R08_LENGTH+1, + (uint8 *)X509V2CRLExtensionCritical}, + CSSMOID_X509V2CRLExtensionType = {INTEL_X509V2_CRL_R08_LENGTH+1, + (uint8 *)X509V2CRLExtensionType}; + +const CSSM_OID + /* OCSP OIDs */ + CSSMOID_PKIX_OCSP = { OID_AD_OCSP_LENGTH, (uint8 *)OID_PKIX_OCSP }, + CSSMOID_PKIX_OCSP_BASIC = { OID_AD_OCSP_LENGTH+1, (uint8 *)OID_PKIX_OCSP_BASIC}, + CSSMOID_PKIX_OCSP_NONCE = { OID_AD_OCSP_LENGTH+1, (uint8 *)OID_PKIX_OCSP_NONCE}, + CSSMOID_PKIX_OCSP_CRL = { OID_AD_OCSP_LENGTH+1, (uint8 *)OID_PKIX_OCSP_CRL}, + CSSMOID_PKIX_OCSP_RESPONSE = { OID_AD_OCSP_LENGTH+1, (uint8 *)OID_PKIX_OCSP_RESPONSE}, + CSSMOID_PKIX_OCSP_NOCHECK = { OID_AD_OCSP_LENGTH+1, (uint8 *)OID_PKIX_OCSP_NOCHECK}, + CSSMOID_PKIX_OCSP_ARCHIVE_CUTOFF = { OID_AD_OCSP_LENGTH+1, (uint8 *)OID_PKIX_OCSP_ARCHIVE_CUTOFF}, + CSSMOID_PKIX_OCSP_SERVICE_LOCATOR = { OID_AD_OCSP_LENGTH+1, (uint8 *)OID_PKIX_OCSP_SERVICE_LOCATOR}; diff --git a/libsecurity_cssm/lib/oidscrl.h b/libsecurity_cssm/lib/oidscrl.h new file mode 100644 index 00000000..65cbda54 --- /dev/null +++ b/libsecurity_cssm/lib/oidscrl.h @@ -0,0 +1,99 @@ +/* + * Copyright (c) 1999-2001,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@ + * + * oidscrl.h -- Object Identifiers for X509 CRLs and OCSP + */ + +#ifndef _OIDSCRL_H_ +#define _OIDSCRL_H_ 1 + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define INTEL_X509V2_CRL_R08 INTEL_SEC_FORMATS, 2, 1 +#define INTEL_X509V2_CRL_R08_LENGTH INTEL_SEC_FORMATS_LENGTH+2 + + +extern const CSSM_OID + /* CRL OIDs */ + CSSMOID_X509V2CRLSignedCrlStruct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_X509V2CRLSignedCrlCStruct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_X509V2CRLTbsCertListStruct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_X509V2CRLTbsCertListCStruct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_X509V2CRLVersion DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_X509V1CRLIssuerStruct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_X509V1CRLIssuerNameCStruct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_X509V1CRLIssuerNameLDAP DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_X509V1CRLThisUpdate DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_X509V1CRLNextUpdate DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + + /* CRL Entry (CRL CertList) OIDS */ + CSSMOID_X509V1CRLRevokedCertificatesStruct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_X509V1CRLRevokedCertificatesCStruct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_X509V1CRLNumberOfRevokedCertEntries DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_X509V1CRLRevokedEntryStruct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_X509V1CRLRevokedEntryCStruct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_X509V1CRLRevokedEntrySerialNumber DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_X509V1CRLRevokedEntryRevocationDate DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + + /* CRL Entry (CRL CertList) Extension OIDs */ + CSSMOID_X509V2CRLRevokedEntryAllExtensionsStruct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_X509V2CRLRevokedEntryAllExtensionsCStruct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_X509V2CRLRevokedEntryNumberOfExtensions DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_X509V2CRLRevokedEntrySingleExtensionStruct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_X509V2CRLRevokedEntrySingleExtensionCStruct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_X509V2CRLRevokedEntryExtensionId DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_X509V2CRLRevokedEntryExtensionCritical DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_X509V2CRLRevokedEntryExtensionType DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_X509V2CRLRevokedEntryExtensionValue DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + + /* CRL Extension OIDs */ + CSSMOID_X509V2CRLAllExtensionsStruct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_X509V2CRLAllExtensionsCStruct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_X509V2CRLNumberOfExtensions DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_X509V2CRLSingleExtensionStruct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_X509V2CRLSingleExtensionCStruct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_X509V2CRLExtensionId DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_X509V2CRLExtensionCritical DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_X509V2CRLExtensionType DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + + /* OCSP */ + CSSMOID_PKIX_OCSP DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_PKIX_OCSP_BASIC DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_PKIX_OCSP_NONCE DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_PKIX_OCSP_CRL DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_PKIX_OCSP_RESPONSE DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_PKIX_OCSP_NOCHECK DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_PKIX_OCSP_ARCHIVE_CUTOFF DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_PKIX_OCSP_SERVICE_LOCATOR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + + +#ifdef __cplusplus +} +#endif + +#endif /* _OIDSCRL_H_ */ diff --git a/libsecurity_cssm/lib/security_cssm.exp b/libsecurity_cssm/lib/security_cssm.exp new file mode 100644 index 00000000..95b1e137 --- /dev/null +++ b/libsecurity_cssm/lib/security_cssm.exp @@ -0,0 +1,643 @@ +# +# 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@ +# +_CSSMOID_ANSI_DH_EPHEM +_CSSMOID_ANSI_DH_EPHEM_SHA1 +_CSSMOID_ANSI_DH_HYBRID1 +_CSSMOID_ANSI_DH_HYBRID1_SHA1 +_CSSMOID_ANSI_DH_HYBRID2 +_CSSMOID_ANSI_DH_HYBRID2_SHA1 +_CSSMOID_ANSI_DH_HYBRID_ONEFLOW +_CSSMOID_ANSI_DH_ONE_FLOW +_CSSMOID_ANSI_DH_ONE_FLOW_SHA1 +_CSSMOID_ANSI_DH_PUB_NUMBER +_CSSMOID_ANSI_DH_STATIC +_CSSMOID_ANSI_DH_STATIC_SHA1 +_CSSMOID_ANSI_MQV1 +_CSSMOID_ANSI_MQV1_SHA1 +_CSSMOID_ANSI_MQV2 +_CSSMOID_ANSI_MQV2_SHA1 +_CSSMOID_APPLE_ASC +_CSSMOID_APPLE_ECDSA +_CSSMOID_APPLE_FEE +_CSSMOID_APPLE_FEED +_CSSMOID_APPLE_FEEDEXP +_CSSMOID_APPLE_FEE_MD5 +_CSSMOID_APPLE_FEE_SHA1 +_CSSMOID_APPLE_ISIGN +_CSSMOID_APPLE_TP_CSR_GEN +_CSSMOID_APPLE_TP_EAP +_CSSMOID_APPLE_TP_CODE_SIGN +_CSSMOID_APPLE_TP_SW_UPDATE_SIGNING +_CSSMOID_APPLE_TP_IP_SEC +_CSSMOID_APPLE_TP_LOCAL_CERT_GEN +_CSSMOID_APPLE_TP_REVOCATION_CRL +_CSSMOID_APPLE_TP_REVOCATION_OCSP +_CSSMOID_APPLE_TP_SMIME +_CSSMOID_APPLE_TP_SSL +_CSSMOID_APPLE_TP_ICHAT +_CSSMOID_APPLE_TP_RESOURCE_SIGN +_CSSMOID_APPLE_TP_PKINIT_CLIENT +_CSSMOID_APPLE_TP_PKINIT_SERVER +_CSSMOID_APPLE_TP_CODE_SIGNING +_CSSMOID_APPLE_TP_PACKAGE_SIGNING +_CSSMOID_APPLE_TP_MACAPPSTORE_RECEIPT +_CSSMOID_APPLE_TP_APPLEID_SHARING +_CSSMOID_APPLE_X509_BASIC +_CSSMOID_AliasedEntryName +_CSSMOID_AuthorityKeyIdentifier +_CSSMOID_AuthorityRevocationList +_CSSMOID_BasicConstraints +_CSSMOID_BusinessCategory +_CSSMOID_CACertificate +_CSSMOID_CSSMKeyStruct +_CSSMOID_CertIssuer +_CSSMOID_CertificatePolicies +_CSSMOID_CertificateRevocationList +_CSSMOID_ChallengePassword +_CSSMOID_ClientAuth +_CSSMOID_CollectiveFacsimileTelephoneNumber +_CSSMOID_CollectiveInternationalISDNNumber +_CSSMOID_CollectiveOrganizationName +_CSSMOID_CollectiveOrganizationalUnitName +_CSSMOID_CollectivePhysicalDeliveryOfficeName +_CSSMOID_CollectivePostOfficeBox +_CSSMOID_CollectivePostalAddress +_CSSMOID_CollectivePostalCode +_CSSMOID_CollectiveStateProvinceName +_CSSMOID_CollectiveStreetAddress +_CSSMOID_CollectiveTelephoneNumber +_CSSMOID_CollectiveTelexNumber +_CSSMOID_CollectiveTelexTerminalIdentifier +_CSSMOID_CommonName +_CSSMOID_ContentType +_CSSMOID_CounterSignature +_CSSMOID_CountryName +_CSSMOID_CrlDistributionPoints +_CSSMOID_CrlNumber +_CSSMOID_CrlReason +_CSSMOID_CrossCertificatePair +_CSSMOID_DH +_CSSMOID_DNQualifier +_CSSMOID_DSA +_CSSMOID_DSA_CMS +_CSSMOID_DSA_JDK +_CSSMOID_DeltaCrlIndicator +_CSSMOID_Description +_CSSMOID_DestinationIndicator +_CSSMOID_DistinguishedName +_CSSMOID_EmailAddress +_CSSMOID_EmailProtection +_CSSMOID_EnhancedSearchGuide +_CSSMOID_ExtendedCertificateAttributes +_CSSMOID_ExtendedKeyUsage +_CSSMOID_AuthorityInfoAccess +_CSSMOID_BiometricInfo +_CSSMOID_QC_Statements +_CSSMOID_SubjectInfoAccess +_CSSMOID_ExtendedKeyUsageAny +_CSSMOID_ExtendedUseCodeSigning +_CSSMOID_FacsimileTelephoneNumber +_CSSMOID_GenerationQualifier +_CSSMOID_GivenName +_CSSMOID_HoldInstructionCode +_CSSMOID_HouseIdentifier +_CSSMOID_Initials +_CSSMOID_InternationalISDNNumber +_CSSMOID_InvalidityDate +_CSSMOID_IssuerAltName +_CSSMOID_IssuingDistributionPoint +_CSSMOID_IssuingDistributionPoints +_CSSMOID_KeyUsage +_CSSMOID_KnowledgeInformation +_CSSMOID_LocalityName +_CSSMOID_MD2 +_CSSMOID_MD2WithRSA +_CSSMOID_MD4 +_CSSMOID_MD4WithRSA +_CSSMOID_MD5 +_CSSMOID_MD5WithRSA +_CSSMOID_Member +_CSSMOID_MessageDigest +_CSSMOID_Name +_CSSMOID_NameConstraints +_CSSMOID_NetscapeCertType +_CSSMOID_NetscapeCertSequence +_CSSMOID_NetscapeSGC +_CSSMOID_MicrosoftSGC +_CSSMOID_OCSPSigning +_CSSMOID_KERBv5_PKINIT_KP_CLIENT_AUTH +_CSSMOID_KERBv5_PKINIT_KP_KDC +_CSSMOID_EKU_IPSec +_CSSMOID_ObjectClass +_CSSMOID_OrganizationName +_CSSMOID_OrganizationalUnitName +_CSSMOID_Owner +_CSSMOID_PKCS12_certBag +_CSSMOID_PKCS12_crlBag +_CSSMOID_PKCS12_keyBag +_CSSMOID_PKCS12_pbeWithSHAAnd128BitRC2CBC +_CSSMOID_PKCS12_pbeWithSHAAnd128BitRC4 +_CSSMOID_PKCS12_pbeWithSHAAnd2Key3DESCBC +_CSSMOID_PKCS12_pbeWithSHAAnd3Key3DESCBC +_CSSMOID_PKCS12_pbeWithSHAAnd40BitRC4 +_CSSMOID_PKCS12_pbewithSHAAnd40BitRC2CBC +_CSSMOID_PKCS12_safeContentsBag +_CSSMOID_PKCS12_secretBag +_CSSMOID_PKCS12_shroudedKeyBag +_CSSMOID_KERBv5_PKINIT_AUTH_DATA +_CSSMOID_KERBv5_PKINIT_DH_KEY_DATA +_CSSMOID_KERBv5_PKINIT_RKEY_DATA +_CSSMOID_PKCS3 +_CSSMOID_PKCS7_Data +_CSSMOID_PKCS7_DataWithAttributes +_CSSMOID_PKCS7_DigestedData +_CSSMOID_PKCS7_EncryptedData +_CSSMOID_PKCS7_EncryptedPrivateKeyInfo +_CSSMOID_PKCS7_EnvelopedData +_CSSMOID_PKCS7_SignedAndEnvelopedData +_CSSMOID_PKCS7_SignedData +_CSSMOID_PKCS9_CertTypes +_CSSMOID_PKCS9_CrlTypes +_CSSMOID_PKCS9_FriendlyName +_CSSMOID_PKCS9_LocalKeyId +_CSSMOID_PKCS9_SdsiCertificate +_CSSMOID_PKCS9_X509Certificate +_CSSMOID_PKCS9_X509Crl +_CSSMOID_PKCS5_DIGEST_ALG +_CSSMOID_PKCS5_ENCRYPT_ALG +_CSSMOID_PKCS5_HMAC_SHA1 +_CSSMOID_PKCS5_pbeWithMD2AndDES +_CSSMOID_PKCS5_pbeWithMD5AndDES +_CSSMOID_PKCS5_pbeWithMD2AndRC2 +_CSSMOID_PKCS5_pbeWithMD5AndRC2 +_CSSMOID_PKCS5_pbeWithSHA1AndDES +_CSSMOID_PKCS5_pbeWithSHA1AndRC2 +_CSSMOID_PKCS5_PBKDF2 +_CSSMOID_PKCS5_PBES2 +_CSSMOID_PKCS5_PBMAC1 +_CSSMOID_PKCS5_RC2_CBC +_CSSMOID_PKCS5_DES_EDE3_CBC +_CSSMOID_PKCS5_RC5_CBC +_CSSMOID_PhysicalDeliveryOfficeName +_CSSMOID_PolicyConstraints +_CSSMOID_PolicyMappings +_CSSMOID_PostOfficeBox +_CSSMOID_PostalAddress +_CSSMOID_PostalCode +_CSSMOID_PreferredDeliveryMethod +_CSSMOID_PresentationAddress +_CSSMOID_PrivateKeyUsagePeriod +_CSSMOID_ProtocolInformation +_CSSMOID_QT_CPS +_CSSMOID_QT_UNOTICE +_CSSMOID_AD_OCSP +_CSSMOID_AD_CA_ISSUERS +_CSSMOID_AD_TIME_STAMPING +_CSSMOID_AD_CA_REPOSITORY +_CSSMOID_PDA_DATE_OF_BIRTH +_CSSMOID_PDA_PLACE_OF_BIRTH +_CSSMOID_PDA_GENDER +_CSSMOID_PDA_COUNTRY_CITIZEN +_CSSMOID_PDA_COUNTRY_RESIDENCE +_CSSMOID_OID_QCS_SYNTAX_V1 +_CSSMOID_OID_QCS_SYNTAX_V2 +_CSSMOID_ETSI_QCS_QC_COMPLIANCE +_CSSMOID_ETSI_QCS_QC_LIMIT_VALUE +_CSSMOID_ETSI_QCS_QC_RETENTION +_CSSMOID_ETSI_QCS_QC_SSCD +_CSSMOID_RSA +_CSSMOID_RegisteredAddress +_CSSMOID_RoleOccupant +_CSSMOID_SHA1 +_CSSMOID_SHA224 +_CSSMOID_SHA256 +_CSSMOID_SHA384 +_CSSMOID_SHA512 +_CSSMOID_SHA1WithDSA +_CSSMOID_SHA1WithDSA_CMS +_CSSMOID_SHA1WithDSA_JDK +_CSSMOID_SHA1WithRSA +_CSSMOID_SHA224WithRSA +_CSSMOID_SHA256WithRSA +_CSSMOID_SHA384WithRSA +_CSSMOID_SHA512WithRSA +_CSSMOID_SHA1WithRSA_OIW +_CSSMOID_RSAWithOAEP +_CSSMOID_OAEP_MGF1 +_CSSMOID_OAEP_ID_PSPECIFIED +_CSSMOID_SearchGuide +_CSSMOID_SeeAlso +_CSSMOID_SerialNumber +_CSSMOID_ServerAuth +_CSSMOID_SigningTime +_CSSMOID_StateProvinceName +_CSSMOID_StreetAddress +_CSSMOID_SubjectAltName +_CSSMOID_SubjectDirectoryAttributes +_CSSMOID_SubjectEmailAddress +_CSSMOID_SubjectKeyIdentifier +_CSSMOID_SubjectPicture +_CSSMOID_SubjectSignatureBitmap +_CSSMOID_SupportedApplicationContext +_CSSMOID_Surname +_CSSMOID_TelephoneNumber +_CSSMOID_TelexNumber +_CSSMOID_TelexTerminalIdentifier +_CSSMOID_TimeStamping +_CSSMOID_Title +_CSSMOID_UniqueIdentifier +_CSSMOID_UniqueMember +_CSSMOID_UnstructuredAddress +_CSSMOID_UnstructuredName +_CSSMOID_UseExemptions +_CSSMOID_UserCertificate +_CSSMOID_UserID +_CSSMOID_UserPassword +_CSSMOID_X509V1CRLIssuerNameCStruct +_CSSMOID_X509V1CRLIssuerNameLDAP +_CSSMOID_X509V1CRLIssuerStruct +_CSSMOID_X509V1CRLNextUpdate +_CSSMOID_X509V1CRLNumberOfRevokedCertEntries +_CSSMOID_X509V1CRLRevokedCertificatesCStruct +_CSSMOID_X509V1CRLRevokedCertificatesStruct +_CSSMOID_X509V1CRLRevokedEntryCStruct +_CSSMOID_X509V1CRLRevokedEntryRevocationDate +_CSSMOID_X509V1CRLRevokedEntrySerialNumber +_CSSMOID_X509V1CRLRevokedEntryStruct +_CSSMOID_X509V1CRLThisUpdate +_CSSMOID_X509V1CertificateIssuerUniqueId +_CSSMOID_X509V1CertificateSubjectUniqueId +_CSSMOID_X509V1IssuerName +_CSSMOID_X509V1IssuerNameCStruct +_CSSMOID_X509V1IssuerNameLDAP +_CSSMOID_X509V1IssuerNameStd +_CSSMOID_X509V1SerialNumber +_CSSMOID_X509V1Signature +_CSSMOID_X509V1SignatureAlgorithm +_CSSMOID_X509V1SignatureAlgorithmParameters +_CSSMOID_X509V1SignatureAlgorithmTBS +_CSSMOID_X509V1SignatureCStruct +_CSSMOID_X509V1SignatureStruct +_CSSMOID_X509V1SubjectName +_CSSMOID_X509V1SubjectNameCStruct +_CSSMOID_X509V1SubjectNameLDAP +_CSSMOID_X509V1SubjectNameStd +_CSSMOID_X509V1SubjectPublicKey +_CSSMOID_X509V1SubjectPublicKeyAlgorithm +_CSSMOID_X509V1SubjectPublicKeyAlgorithmParameters +_CSSMOID_X509V1SubjectPublicKeyCStruct +_CSSMOID_X509V1ValidityNotAfter +_CSSMOID_X509V1ValidityNotBefore +_CSSMOID_X509V1Version +_CSSMOID_X509V2CRLAllExtensionsCStruct +_CSSMOID_X509V2CRLAllExtensionsStruct +_CSSMOID_X509V2CRLExtensionCritical +_CSSMOID_X509V2CRLExtensionId +_CSSMOID_X509V2CRLExtensionType +_CSSMOID_X509V2CRLNumberOfExtensions +_CSSMOID_X509V2CRLRevokedEntryAllExtensionsCStruct +_CSSMOID_X509V2CRLRevokedEntryAllExtensionsStruct +_CSSMOID_X509V2CRLRevokedEntryExtensionCritical +_CSSMOID_X509V2CRLRevokedEntryExtensionId +_CSSMOID_X509V2CRLRevokedEntryExtensionType +_CSSMOID_X509V2CRLRevokedEntryExtensionValue +_CSSMOID_X509V2CRLRevokedEntryNumberOfExtensions +_CSSMOID_X509V2CRLRevokedEntrySingleExtensionCStruct +_CSSMOID_X509V2CRLRevokedEntrySingleExtensionStruct +_CSSMOID_X509V2CRLSignedCrlCStruct +_CSSMOID_X509V2CRLSignedCrlStruct +_CSSMOID_X509V2CRLSingleExtensionCStruct +_CSSMOID_X509V2CRLSingleExtensionStruct +_CSSMOID_X509V2CRLTbsCertListCStruct +_CSSMOID_X509V2CRLTbsCertListStruct +_CSSMOID_X509V2CRLVersion +_CSSMOID_X509V3Certificate +_CSSMOID_X509V3CertificateCStruct +_CSSMOID_X509V3CertificateExtensionCStruct +_CSSMOID_X509V3CertificateExtensionCritical +_CSSMOID_X509V3CertificateExtensionId +_CSSMOID_X509V3CertificateExtensionStruct +_CSSMOID_X509V3CertificateExtensionType +_CSSMOID_X509V3CertificateExtensionValue +_CSSMOID_X509V3CertificateExtensionsCStruct +_CSSMOID_X509V3CertificateExtensionsStruct +_CSSMOID_X509V3CertificateNumberOfExtensions +_CSSMOID_X509V3SignedCertificate +_CSSMOID_X509V3SignedCertificateCStruct +_CSSMOID_X_121Address +_CSSMOID_DOTMAC_CERT +_CSSMOID_DOTMAC_CERT_REQ +_CSSMOID_DOTMAC_CERT_REQ_IDENTITY +_CSSMOID_DOTMAC_CERT_REQ_EMAIL_SIGN +_CSSMOID_DOTMAC_CERT_REQ_EMAIL_ENCRYPT +_CSSMOID_DOTMAC_CERT_REQ_ARCHIVE_LIST +_CSSMOID_DOTMAC_CERT_REQ_ARCHIVE_STORE +_CSSMOID_DOTMAC_CERT_REQ_ARCHIVE_FETCH +_CSSMOID_DOTMAC_CERT_REQ_ARCHIVE_REMOVE +_CSSMOID_DOTMAC_CERT_REQ_SHARED_SERVICES +_CSSMOID_DOTMAC_CERT_REQ_VALUE_USERNAME +_CSSMOID_DOTMAC_CERT_REQ_VALUE_PASSWORD +_CSSMOID_DOTMAC_CERT_REQ_VALUE_HOSTNAME +_CSSMOID_DOTMAC_CERT_REQ_VALUE_RENEW +_CSSMOID_DOTMAC_CERT_REQ_VALUE_ASYNC +_CSSMOID_DOTMAC_CERT_REQ_VALUE_IS_PENDING +_CSSMOID_DOTMAC_CERT_EXTENSION +_CSSMOID_DOTMAC_CERT_IDENTITY +_CSSMOID_DOTMAC_CERT_EMAIL_SIGN +_CSSMOID_DOTMAC_CERT_EMAIL_ENCRYPT +_CSSMOID_APPLE_CERT_POLICY +_CSSMOID_DOTMAC_CERT_POLICY +_CSSMOID_ADC_CERT_POLICY +_CSSMOID_MACAPPSTORE_CERT_POLICY +_CSSMOID_MACAPPSTORE_RECEIPT_CERT_POLICY +_CSSMOID_APPLEID_CERT_POLICY +_CSSMOID_APPLEID_SHARING_CERT_POLICY +_CSSMOID_APPLE_EKU_CODE_SIGNING +_CSSMOID_APPLE_EKU_CODE_SIGNING_DEV +_CSSMOID_APPLE_EKU_RESOURCE_SIGNING +_CSSMOID_APPLE_EKU_ICHAT_SIGNING +_CSSMOID_APPLE_EKU_ICHAT_ENCRYPTION +_CSSMOID_APPLE_EKU_SYSTEM_IDENTITY +_CSSMOID_APPLE_EXTENSION +_CSSMOID_APPLE_EXTENSION_CODE_SIGNING +_CSSMOID_APPLE_EXTENSION_APPLE_SIGNING +_CSSMOID_APPLE_EXTENSION_ADC_DEV_SIGNING +_CSSMOID_APPLE_EXTENSION_ADC_APPLE_SIGNING +_CSSMOID_APPLE_EXTENSION_MACAPPSTORE_RECEIPT +_CSSMOID_APPLE_EXTENSION_INTERMEDIATE_MARKER +_CSSMOID_APPLE_EXTENSION_WWDR_INTERMEDIATE +_CSSMOID_APPLE_EXTENSION_ITMS_INTERMEDIATE +_CSSMOID_APPLE_EXTENSION_AAI_INTERMEDIATE +_CSSMOID_APPLE_EXTENSION_APPLEID_INTERMEDIATE +_CSSMOID_APPLE_EXTENSION_APPLEID_SHARING +_CSSMOID_PKIX_OCSP +_CSSMOID_PKIX_OCSP_ARCHIVE_CUTOFF +_CSSMOID_PKIX_OCSP_BASIC +_CSSMOID_PKIX_OCSP_CRL +_CSSMOID_PKIX_OCSP_NOCHECK +_CSSMOID_PKIX_OCSP_NONCE +_CSSMOID_PKIX_OCSP_RESPONSE +_CSSMOID_PKIX_OCSP_SERVICE_LOCATOR +_CSSM_AC_AuthCompute +_CSSM_AC_PassThrough +_CSSM_CL_CertAbortCache +_CSSM_CL_CertAbortQuery +_CSSM_CL_CertCache +_CSSM_CL_CertCreateTemplate +_CSSM_CL_CertDescribeFormat +_CSSM_CL_CertGetAllFields +_CSSM_CL_CertGetAllTemplateFields +_CSSM_CL_CertGetFirstCachedFieldValue +_CSSM_CL_CertGetFirstFieldValue +_CSSM_CL_CertGetKeyInfo +_CSSM_CL_CertGetNextCachedFieldValue +_CSSM_CL_CertGetNextFieldValue +_CSSM_CL_CertGroupFromVerifiedBundle +_CSSM_CL_CertGroupToSignedBundle +_CSSM_CL_CertSign +_CSSM_CL_CertVerify +_CSSM_CL_CertVerifyWithKey +_CSSM_CL_CrlAbortCache +_CSSM_CL_CrlAbortQuery +_CSSM_CL_CrlAddCert +_CSSM_CL_CrlCache +_CSSM_CL_CrlCreateTemplate +_CSSM_CL_CrlDescribeFormat +_CSSM_CL_CrlGetAllCachedRecordFields +_CSSM_CL_CrlGetAllFields +_CSSM_CL_CrlGetFirstCachedFieldValue +_CSSM_CL_CrlGetFirstFieldValue +_CSSM_CL_CrlGetNextCachedFieldValue +_CSSM_CL_CrlGetNextFieldValue +_CSSM_CL_CrlRemoveCert +_CSSM_CL_CrlSetFields +_CSSM_CL_CrlSign +_CSSM_CL_CrlVerify +_CSSM_CL_CrlVerifyWithKey +_CSSM_CL_FreeFieldValue +_CSSM_CL_FreeFields +_CSSM_CL_IsCertInCachedCrl +_CSSM_CL_IsCertInCrl +_CSSM_CL_PassThrough +_CSSM_CSP_ChangeLoginAcl +_CSSM_CSP_ChangeLoginOwner +_CSSM_CSP_CreateAsymmetricContext +_CSSM_CSP_CreateDeriveKeyContext +_CSSM_CSP_CreateDigestContext +_CSSM_CSP_CreateKeyGenContext +_CSSM_CSP_CreateMacContext +_CSSM_CSP_CreatePassThroughContext +_CSSM_CSP_CreateRandomGenContext +_CSSM_CSP_CreateSignatureContext +_CSSM_CSP_CreateSymmetricContext +_CSSM_CSP_GetLoginAcl +_CSSM_CSP_GetLoginOwner +_CSSM_CSP_GetOperationalStatistics +_CSSM_CSP_Login +_CSSM_CSP_Logout +_CSSM_CSP_ObtainPrivateKeyFromPublicKey +_CSSM_CSP_PassThrough +_CSSM_ChangeKeyAcl +_CSSM_ChangeKeyOwner +_CSSM_DL_Authenticate +_CSSM_DL_ChangeDbAcl +_CSSM_DL_ChangeDbOwner +_CSSM_DL_CreateRelation +_CSSM_DL_DataAbortQuery +_CSSM_DL_DataDelete +_CSSM_DL_DataGetFirst +_CSSM_DL_DataGetFromUniqueRecordId +_CSSM_DL_DataGetNext +_CSSM_DL_DataInsert +_CSSM_DL_DataModify +_CSSM_DL_DbClose +_CSSM_DL_DbCreate +_CSSM_DL_DbDelete +_CSSM_DL_DbOpen +_CSSM_DL_DestroyRelation +_CSSM_DL_FreeNameList +_CSSM_DL_FreeUniqueRecord +_CSSM_DL_GetDbAcl +_CSSM_DL_GetDbNameFromHandle +_CSSM_DL_GetDbNames +_CSSM_DL_GetDbOwner +_CSSM_DL_PassThrough +_CSSM_DecryptData +_CSSM_DecryptDataFinal +_CSSM_DecryptDataInit +_CSSM_DecryptDataInitP +_CSSM_DecryptDataP +_CSSM_DecryptDataUpdate +_CSSM_DeleteContext +_CSSM_DeleteContextAttributes +_CSSM_DeriveKey +_CSSM_DigestData +_CSSM_DigestDataClone +_CSSM_DigestDataFinal +_CSSM_DigestDataInit +_CSSM_DigestDataUpdate +_CSSM_EncryptData +_CSSM_EncryptDataFinal +_CSSM_EncryptDataInit +_CSSM_EncryptDataInitP +_CSSM_EncryptDataP +_CSSM_EncryptDataUpdate +_CSSM_FreeContext +_CSSM_FreeKey +_CSSM_GenerateAlgorithmParams +_CSSM_GenerateKey +_CSSM_GenerateKeyP +_CSSM_GenerateKeyPair +_CSSM_GenerateKeyPairP +_CSSM_GenerateMac +_CSSM_GenerateMacFinal +_CSSM_GenerateMacInit +_CSSM_GenerateMacUpdate +_CSSM_GenerateRandom +_CSSM_GetAPIMemoryFunctions +_CSSM_GetContext +_CSSM_GetContextAttribute +_CSSM_GetKeyAcl +_CSSM_GetKeyOwner +_CSSM_GetModuleGUIDFromHandle +_CSSM_GetPrivilege +_CSSM_GetSubserviceUIDFromHandle +_CSSM_GetTimeValue +_CSSM_Init +_CSSM_Introduce +_CSSM_ListAttachedModuleManagers +_CSSM_ModuleAttach +_CSSM_ModuleDetach +_CSSM_ModuleLoad +_CSSM_ModuleUnload +_CSSM_QueryKeySizeInBits +_CSSM_QuerySize +_CSSM_RetrieveCounter +_CSSM_RetrieveUniqueId +_CSSM_SetContext +_CSSM_SetPrivilege +_CSSM_SignData +_CSSM_SignDataFinal +_CSSM_SignDataInit +_CSSM_SignDataUpdate +_CSSM_TP_ApplyCrlToDb +_CSSM_TP_CertCreateTemplate +_CSSM_TP_CertGetAllTemplateFields +_CSSM_TP_CertGroupConstruct +_CSSM_TP_CertGroupPrune +_CSSM_TP_CertGroupToTupleGroup +_CSSM_TP_CertGroupVerify +_CSSM_TP_CertReclaimAbort +_CSSM_TP_CertReclaimKey +_CSSM_TP_CertRemoveFromCrlTemplate +_CSSM_TP_CertRevoke +_CSSM_TP_CertSign +_CSSM_TP_ConfirmCredResult +_CSSM_TP_CrlCreateTemplate +_CSSM_TP_CrlSign +_CSSM_TP_CrlVerify +_CSSM_TP_FormRequest +_CSSM_TP_FormSubmit +_CSSM_TP_PassThrough +_CSSM_TP_ReceiveConfirmation +_CSSM_TP_RetrieveCredResult +_CSSM_TP_SubmitCredRequest +_CSSM_TP_TupleGroupToCertGroup +_CSSM_Terminate +_CSSM_Unintroduce +_CSSM_UnwrapKey +_CSSM_UnwrapKeyP +_CSSM_UpdateContextAttributes +_CSSM_VerifyData +_CSSM_VerifyDataFinal +_CSSM_VerifyDataInit +_CSSM_VerifyDataUpdate +_CSSM_VerifyDevice +_CSSM_VerifyMac +_CSSM_VerifyMacFinal +_CSSM_VerifyMacInit +_CSSM_VerifyMacUpdate +_CSSM_WrapKey +_CSSM_WrapKeyP +_cssmAlgToOid +_cssmOidToAlg +_gGuidAppleCSP +_gGuidAppleCSPDL +_gGuidAppleFileDL +_gGuidAppleX509CL +_gGuidAppleX509TP +_gGuidAppleDotMacTP +_gGuidAppleSdCSPDL +_gGuidCssm +_gGuidAppleLDAPDL +_gGuidAppleDotMacDL +_CSSMOID_X9_62 +_CSSMOID_X9_62_FieldType +_CSSMOID_X9_62_PubKeyType +_CSSMOID_X9_62_EllCurve +_CSSMOID_X9_62_C_TwoCurve +_CSSMOID_X9_62_PrimeCurve +_CSSMOID_X9_62_SigType +_CSSMOID_secp192r1 +_CSSMOID_secp256r1 +_CSSMOID_Certicom +_CSSMOID_CerticomEllCurve +_CSSMOID_secp112r1 +_CSSMOID_secp112r2 +_CSSMOID_secp128r1 +_CSSMOID_secp128r2 +_CSSMOID_secp160k1 +_CSSMOID_secp160r1 +_CSSMOID_secp160r2 +_CSSMOID_secp192k1 +_CSSMOID_secp224k1 +_CSSMOID_secp224r1 +_CSSMOID_secp256k1 +_CSSMOID_secp384r1 +_CSSMOID_secp521r1 +_CSSMOID_sect113r1 +_CSSMOID_sect113r2 +_CSSMOID_sect131r1 +_CSSMOID_sect131r2 +_CSSMOID_sect163k1 +_CSSMOID_sect163r1 +_CSSMOID_sect163r2 +_CSSMOID_sect193r1 +_CSSMOID_sect193r2 +_CSSMOID_sect233k1 +_CSSMOID_sect233r1 +_CSSMOID_sect239k1 +_CSSMOID_sect283k1 +_CSSMOID_sect283r1 +_CSSMOID_sect409k1 +_CSSMOID_sect409r1 +_CSSMOID_sect571k1 +_CSSMOID_sect571r1 +_CSSMOID_ecPublicKey +_CSSMOID_ECDSA_WithSHA1 +_CSSMOID_ECDSA_WithSHA224 +_CSSMOID_ECDSA_WithSHA256 +_CSSMOID_ECDSA_WithSHA384 +_CSSMOID_ECDSA_WithSHA512 +_CSSMOID_ECDSA_WithSpecified + diff --git a/libsecurity_cssm/lib/transition.cpp b/libsecurity_cssm/lib/transition.cpp new file mode 100644 index 00000000..7b216581 --- /dev/null +++ b/libsecurity_cssm/lib/transition.cpp @@ -0,0 +1,514 @@ +/* + * 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, 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 + HandleContext &context = HandleObject::find(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); + HandleContext &context = HandleObject::find(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 + HandleContext &context = HandleObject::find(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 + HandleContext &context = HandleObject::find(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 + HandleContext &context = HandleObject::findAndLock(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/libsecurity_cssm/lib/x509defs.h new file mode 100644 index 00000000..b53e84ee --- /dev/null +++ b/libsecurity_cssm/lib/x509defs.h @@ -0,0 +1,230 @@ +/* + * Copyright (c) 1999-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@ + * + * x509defs.h -- Data structures for X509 Certificate Library field values + */ + +#ifndef _X509DEFS_H_ +#define _X509DEFS_H_ 1 + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef uint8 CSSM_BER_TAG; +#define BER_TAG_UNKNOWN 0 +#define BER_TAG_BOOLEAN 1 +#define BER_TAG_INTEGER 2 +#define BER_TAG_BIT_STRING 3 +#define BER_TAG_OCTET_STRING 4 +#define BER_TAG_NULL 5 +#define BER_TAG_OID 6 +#define BER_TAG_OBJECT_DESCRIPTOR 7 +#define BER_TAG_EXTERNAL 8 +#define BER_TAG_REAL 9 +#define BER_TAG_ENUMERATED 10 +/* 12 to 15 are reserved for future versions of the recommendation */ +#define BER_TAG_PKIX_UTF8_STRING 12 +#define BER_TAG_SEQUENCE 16 +#define BER_TAG_SET 17 +#define BER_TAG_NUMERIC_STRING 18 +#define BER_TAG_PRINTABLE_STRING 19 +#define BER_TAG_T61_STRING 20 +#define BER_TAG_TELETEX_STRING BER_TAG_T61_STRING +#define BER_TAG_VIDEOTEX_STRING 21 +#define BER_TAG_IA5_STRING 22 +#define BER_TAG_UTC_TIME 23 +#define BER_TAG_GENERALIZED_TIME 24 +#define BER_TAG_GRAPHIC_STRING 25 +#define BER_TAG_ISO646_STRING 26 +#define BER_TAG_GENERAL_STRING 27 +#define BER_TAG_VISIBLE_STRING BER_TAG_ISO646_STRING +/* 28 - are reserved for future versions of the recommendation */ +#define BER_TAG_PKIX_UNIVERSAL_STRING 28 +#define BER_TAG_PKIX_BMP_STRING 30 + + +/* Data Structures for X.509 Certificates */ + +typedef struct cssm_x509_algorithm_identifier { + CSSM_OID algorithm; + CSSM_DATA parameters; +} CSSM_X509_ALGORITHM_IDENTIFIER DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_X509_ALGORITHM_IDENTIFIER_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* X509 Distinguished name structure */ +typedef struct cssm_x509_type_value_pair { + CSSM_OID type; + CSSM_BER_TAG valueType; /* The Tag to be used when */ + /*this value is BER encoded */ + CSSM_DATA value; +} CSSM_X509_TYPE_VALUE_PAIR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_X509_TYPE_VALUE_PAIR_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef struct cssm_x509_rdn { + uint32 numberOfPairs; + CSSM_X509_TYPE_VALUE_PAIR_PTR AttributeTypeAndValue; +} CSSM_X509_RDN DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_X509_RDN_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef struct cssm_x509_name { + uint32 numberOfRDNs; + CSSM_X509_RDN_PTR RelativeDistinguishedName; +} CSSM_X509_NAME DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_X509_NAME_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* Public key info struct */ +typedef struct cssm_x509_subject_public_key_info { + CSSM_X509_ALGORITHM_IDENTIFIER algorithm; + CSSM_DATA subjectPublicKey; +} CSSM_X509_SUBJECT_PUBLIC_KEY_INFO DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_X509_SUBJECT_PUBLIC_KEY_INFO_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef struct cssm_x509_time { + CSSM_BER_TAG timeType; + CSSM_DATA time; +} CSSM_X509_TIME DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_X509_TIME_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* Validity struct */ +typedef struct x509_validity { + CSSM_X509_TIME notBefore; + CSSM_X509_TIME notAfter; +} CSSM_X509_VALIDITY DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_X509_VALIDITY_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +#define CSSM_X509_OPTION_PRESENT CSSM_TRUE +#define CSSM_X509_OPTION_NOT_PRESENT CSSM_FALSE +typedef CSSM_BOOL CSSM_X509_OPTION; + +typedef struct cssm_x509ext_basicConstraints { + CSSM_BOOL cA; + CSSM_X509_OPTION pathLenConstraintPresent; + uint32 pathLenConstraint; +} CSSM_X509EXT_BASICCONSTRAINTS DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_X509EXT_BASICCONSTRAINTS_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef enum extension_data_format { + CSSM_X509_DATAFORMAT_ENCODED = 0, + CSSM_X509_DATAFORMAT_PARSED, + CSSM_X509_DATAFORMAT_PAIR +} CSSM_X509EXT_DATA_FORMAT; + +typedef struct cssm_x509_extensionTagAndValue { + CSSM_BER_TAG type; + CSSM_DATA value; +} CSSM_X509EXT_TAGandVALUE DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_X509EXT_TAGandVALUE_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef struct cssm_x509ext_pair { + CSSM_X509EXT_TAGandVALUE tagAndValue; + void *parsedValue; +} CSSM_X509EXT_PAIR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_X509EXT_PAIR_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* Extension structure */ +typedef struct cssm_x509_extension { + CSSM_OID extnId; + CSSM_BOOL critical; + CSSM_X509EXT_DATA_FORMAT format; + union cssm_x509ext_value { + CSSM_X509EXT_TAGandVALUE *tagAndValue; + void *parsedValue; + CSSM_X509EXT_PAIR *valuePair; + } value; + CSSM_DATA BERvalue; +} CSSM_X509_EXTENSION DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_X509_EXTENSION_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef struct cssm_x509_extensions { + uint32 numberOfExtensions; + CSSM_X509_EXTENSION_PTR extensions; +} CSSM_X509_EXTENSIONS DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_X509_EXTENSIONS_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* X509V3 certificate structure */ +typedef struct cssm_x509_tbs_certificate { + CSSM_DATA version; + CSSM_DATA serialNumber; + CSSM_X509_ALGORITHM_IDENTIFIER signature; + CSSM_X509_NAME issuer; + CSSM_X509_VALIDITY validity; + CSSM_X509_NAME subject; + CSSM_X509_SUBJECT_PUBLIC_KEY_INFO subjectPublicKeyInfo; + CSSM_DATA issuerUniqueIdentifier; + CSSM_DATA subjectUniqueIdentifier; + CSSM_X509_EXTENSIONS extensions; +} CSSM_X509_TBS_CERTIFICATE DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_X509_TBS_CERTIFICATE_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* Signature structure */ +typedef struct cssm_x509_signature { + CSSM_X509_ALGORITHM_IDENTIFIER algorithmIdentifier; + CSSM_DATA encrypted; +} CSSM_X509_SIGNATURE DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_X509_SIGNATURE_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* Signed certificate structure */ +typedef struct cssm_x509_signed_certificate { + CSSM_X509_TBS_CERTIFICATE certificate; + CSSM_X509_SIGNATURE signature; +} CSSM_X509_SIGNED_CERTIFICATE DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_X509_SIGNED_CERTIFICATE_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef struct cssm_x509ext_policyQualifierInfo { + CSSM_OID policyQualifierId; + CSSM_DATA value; +} CSSM_X509EXT_POLICYQUALIFIERINFO DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_X509EXT_POLICYQUALIFIERINFO_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef struct cssm_x509ext_policyQualifiers { + uint32 numberOfPolicyQualifiers; + CSSM_X509EXT_POLICYQUALIFIERINFO *policyQualifier; +} CSSM_X509EXT_POLICYQUALIFIERS DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_X509EXT_POLICYQUALIFIERS_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef struct cssm_x509ext_policyInfo { + CSSM_OID policyIdentifier; + CSSM_X509EXT_POLICYQUALIFIERS policyQualifiers; +} CSSM_X509EXT_POLICYINFO DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_X509EXT_POLICYINFO_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + + +/* Data Structures for X.509 Certificate Revocations Lists */ + +/* x509V2 entry in the CRL revokedCertificates sequence */ +typedef struct cssm_x509_revoked_cert_entry { + CSSM_DATA certificateSerialNumber; + CSSM_X509_TIME revocationDate; + CSSM_X509_EXTENSIONS extensions; +} CSSM_X509_REVOKED_CERT_ENTRY DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_X509_REVOKED_CERT_ENTRY_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef struct cssm_x509_revoked_cert_list { + uint32 numberOfRevokedCertEntries; + CSSM_X509_REVOKED_CERT_ENTRY_PTR revokedCertEntry; +} CSSM_X509_REVOKED_CERT_LIST DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_X509_REVOKED_CERT_LIST_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* x509v2 Certificate Revocation List (CRL) (unsigned) structure */ +typedef struct cssm_x509_tbs_certlist { + CSSM_DATA version; + CSSM_X509_ALGORITHM_IDENTIFIER signature; + CSSM_X509_NAME issuer; + CSSM_X509_TIME thisUpdate; + CSSM_X509_TIME nextUpdate; + CSSM_X509_REVOKED_CERT_LIST_PTR revokedCertificates; + CSSM_X509_EXTENSIONS extensions; +} CSSM_X509_TBS_CERTLIST DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_X509_TBS_CERTLIST_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef struct cssm_x509_signed_crl { + CSSM_X509_TBS_CERTLIST tbsCertList; + CSSM_X509_SIGNATURE signature; +} CSSM_X509_SIGNED_CRL DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_X509_SIGNED_CRL_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +#ifdef __cplusplus +} +#endif + +#endif /* _X509DEFS_H_ */ diff --git a/libsecurity_cssm/libsecurity_cssm.xcodeproj/project.pbxproj b/libsecurity_cssm/libsecurity_cssm.xcodeproj/project.pbxproj new file mode 100644 index 00000000..3683c4ff --- /dev/null +++ b/libsecurity_cssm/libsecurity_cssm.xcodeproj/project.pbxproj @@ -0,0 +1,484 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 05D5BC2E0694857A00145F1E /* cssmapplePriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 05D5BC2D0694857A00145F1E /* cssmapplePriv.h */; settings = {ATTRIBUTES = (); }; }; + 18B647E514D9E72900F538BF /* oidsalg.c in Sources */ = {isa = PBXBuildFile; fileRef = C2F845AC052CA34400F4D742 /* oidsalg.c */; }; + 4CC62CE9058134E00020B996 /* certextensions.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CCBFE87057FF55900981D43 /* certextensions.h */; settings = {ATTRIBUTES = (); }; }; + 4CC62CEA058134E00020B996 /* cssm.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CCBFE88057FF55900981D43 /* cssm.h */; settings = {ATTRIBUTES = (); }; }; + 4CC62CEB058134E00020B996 /* cssmaci.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CCBFE89057FF55900981D43 /* cssmaci.h */; settings = {ATTRIBUTES = (); }; }; + 4CC62CEC058134E00020B996 /* cssmapi.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CCBFE8A057FF55900981D43 /* cssmapi.h */; settings = {ATTRIBUTES = (); }; }; + 4CC62CED058134E00020B996 /* cssmapple.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CCBFE8B057FF55900981D43 /* cssmapple.h */; settings = {ATTRIBUTES = (); }; }; + 4CC62CEE058134E00020B996 /* cssmcli.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CCBFE8C057FF55900981D43 /* cssmcli.h */; settings = {ATTRIBUTES = (); }; }; + 4CC62CEF058134E00020B996 /* cssmconfig.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CCBFE8D057FF55900981D43 /* cssmconfig.h */; settings = {ATTRIBUTES = (); }; }; + 4CC62CF0058134E00020B996 /* cssmcspi.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CCBFE8E057FF55900981D43 /* cssmcspi.h */; settings = {ATTRIBUTES = (); }; }; + 4CC62CF1058134E00020B996 /* cssmdli.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CCBFE8F057FF55900981D43 /* cssmdli.h */; settings = {ATTRIBUTES = (); }; }; + 4CC62CF2058134E00020B996 /* cssmerr.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CCBFE90057FF55900981D43 /* cssmerr.h */; settings = {ATTRIBUTES = (); }; }; + 4CC62CF3058134E00020B996 /* cssmkrapi.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CCBFE91057FF55900981D43 /* cssmkrapi.h */; settings = {ATTRIBUTES = (); }; }; + 4CC62CF4058134E00020B996 /* cssmkrspi.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CCBFE92057FF55900981D43 /* cssmkrspi.h */; settings = {ATTRIBUTES = (); }; }; + 4CC62CF5058134E00020B996 /* cssmspi.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CCBFE93057FF55900981D43 /* cssmspi.h */; settings = {ATTRIBUTES = (); }; }; + 4CC62CF6058134E00020B996 /* cssmtpi.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CCBFE94057FF55900981D43 /* cssmtpi.h */; settings = {ATTRIBUTES = (); }; }; + 4CC62CF7058134E00020B996 /* cssmtype.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CCBFE95057FF55900981D43 /* cssmtype.h */; settings = {ATTRIBUTES = (); }; }; + 4CC62CF8058134E00020B996 /* eisl.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CCBFE96057FF55900981D43 /* eisl.h */; settings = {ATTRIBUTES = (); }; }; + 4CC62CF9058134E00020B996 /* emmspi.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CCBFE97057FF55900981D43 /* emmspi.h */; settings = {ATTRIBUTES = (); }; }; + 4CC62CFA058134E00020B996 /* emmtype.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CCBFE98057FF55900981D43 /* emmtype.h */; settings = {ATTRIBUTES = (); }; }; + 4CC62CFD058134E00020B996 /* oidsbase.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CCBFE9D057FF55900981D43 /* oidsbase.h */; settings = {ATTRIBUTES = (); }; }; + 4CC62CFE058134E00020B996 /* oidscert.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CCBFE9E057FF55900981D43 /* oidscert.h */; settings = {ATTRIBUTES = (); }; }; + 4CC62CFF058134E00020B996 /* oidscrl.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CCBFE9F057FF55900981D43 /* oidscrl.h */; settings = {ATTRIBUTES = (); }; }; + 4CC62D00058134E00020B996 /* x509defs.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CCBFEA0057FF55900981D43 /* x509defs.h */; settings = {ATTRIBUTES = (); }; }; + C2F845B1052CA34400F4D742 /* attachfactory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2F84591052CA34400F4D742 /* attachfactory.cpp */; }; + C2F845B2052CA34400F4D742 /* attachfactory.h in Headers */ = {isa = PBXBuildFile; fileRef = C2F84592052CA34400F4D742 /* attachfactory.h */; }; + C2F845B3052CA34400F4D742 /* attachment.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2F84593052CA34400F4D742 /* attachment.cpp */; }; + C2F845B4052CA34400F4D742 /* attachment.h in Headers */ = {isa = PBXBuildFile; fileRef = C2F84594052CA34400F4D742 /* attachment.h */; }; + C2F845B6052CA34400F4D742 /* cspattachment.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2F84596052CA34400F4D742 /* cspattachment.cpp */; }; + C2F845B7052CA34400F4D742 /* cspattachment.h in Headers */ = {isa = PBXBuildFile; fileRef = C2F84597052CA34400F4D742 /* cspattachment.h */; }; + C2F845B8052CA34400F4D742 /* cssm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2F84598052CA34400F4D742 /* cssm.cpp */; }; + C2F845B9052CA34400F4D742 /* cssmcontext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2F84599052CA34400F4D742 /* cssmcontext.cpp */; }; + C2F845BA052CA34400F4D742 /* cssmcontext.h in Headers */ = {isa = PBXBuildFile; fileRef = C2F8459A052CA34400F4D742 /* cssmcontext.h */; }; + C2F845BB052CA34400F4D742 /* cssmint.h in Headers */ = {isa = PBXBuildFile; fileRef = C2F8459B052CA34400F4D742 /* cssmint.h */; }; + C2F845BC052CA34400F4D742 /* cssmmds.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2F8459C052CA34400F4D742 /* cssmmds.cpp */; }; + C2F845BD052CA34400F4D742 /* cssmmds.h in Headers */ = {isa = PBXBuildFile; fileRef = C2F8459D052CA34400F4D742 /* cssmmds.h */; }; + C2F845BE052CA34400F4D742 /* guids.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2F845A1052CA34400F4D742 /* guids.cpp */; }; + C2F845BF052CA34400F4D742 /* manager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2F845A2052CA34400F4D742 /* manager.cpp */; }; + C2F845C0052CA34400F4D742 /* manager.h in Headers */ = {isa = PBXBuildFile; fileRef = C2F845A3052CA34400F4D742 /* manager.h */; }; + C2F845C1052CA34400F4D742 /* modload_plugin.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2F845A4052CA34400F4D742 /* modload_plugin.cpp */; }; + C2F845C2052CA34400F4D742 /* modload_plugin.h in Headers */ = {isa = PBXBuildFile; fileRef = C2F845A5052CA34400F4D742 /* modload_plugin.h */; }; + C2F845C3052CA34400F4D742 /* modload_static.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2F845A6052CA34400F4D742 /* modload_static.cpp */; }; + C2F845C4052CA34400F4D742 /* modload_static.h in Headers */ = {isa = PBXBuildFile; fileRef = C2F845A7052CA34400F4D742 /* modload_static.h */; }; + C2F845C5052CA34400F4D742 /* modloader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2F845A8052CA34400F4D742 /* modloader.cpp */; }; + C2F845C6052CA34400F4D742 /* modloader.h in Headers */ = {isa = PBXBuildFile; fileRef = C2F845A9052CA34400F4D742 /* modloader.h */; }; + C2F845C7052CA34400F4D742 /* module.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2F845AA052CA34400F4D742 /* module.cpp */; }; + C2F845C8052CA34400F4D742 /* module.h in Headers */ = {isa = PBXBuildFile; fileRef = C2F845AB052CA34400F4D742 /* module.h */; }; + C2F845CB052CA34400F4D742 /* oidscert.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2F845AE052CA34400F4D742 /* oidscert.cpp */; }; + C2F845CC052CA34400F4D742 /* oidscrl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2F845AF052CA34400F4D742 /* oidscrl.cpp */; }; + C2F845CD052CA34400F4D742 /* transition.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2F845B0052CA34400F4D742 /* transition.cpp */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 182BB32E146F0FCB000BF1F3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 18446087146DF8FB00B12992 /* libsecurity_utilities.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = C2C9C69D0CECBE8400B3FE07; + remoteInfo = libsecurity_utilitiesDTrace; + }; + 1844608C146DF8FB00B12992 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 18446087146DF8FB00B12992 /* libsecurity_utilities.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 4CA2A53A0523D32800978A7B; + remoteInfo = libsecurity_utilities; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 05D5BC2D0694857A00145F1E /* cssmapplePriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cssmapplePriv.h; sourceTree = ""; }; + 18446087146DF8FB00B12992 /* libsecurity_utilities.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libsecurity_utilities.xcodeproj; path = ../libsecurity_utilities/libsecurity_utilities.xcodeproj; sourceTree = ""; }; + 1879B4A1146DAE33007E536C /* base.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = base.xcconfig; sourceTree = ""; }; + 1879B4A2146DAE33007E536C /* debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = debug.xcconfig; sourceTree = ""; }; + 1879B4A3146DAE33007E536C /* lib.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = lib.xcconfig; sourceTree = ""; }; + 1879B4A4146DAE33007E536C /* release.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = release.xcconfig; sourceTree = ""; }; + 4CA1FEBE052A3C8100F22E42 /* libsecurity_cssm.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libsecurity_cssm.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 4CCBFE87057FF55900981D43 /* certextensions.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = certextensions.h; sourceTree = ""; }; + 4CCBFE88057FF55900981D43 /* cssm.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cssm.h; sourceTree = ""; }; + 4CCBFE89057FF55900981D43 /* cssmaci.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cssmaci.h; sourceTree = ""; }; + 4CCBFE8A057FF55900981D43 /* cssmapi.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cssmapi.h; sourceTree = ""; }; + 4CCBFE8B057FF55900981D43 /* cssmapple.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cssmapple.h; sourceTree = ""; }; + 4CCBFE8C057FF55900981D43 /* cssmcli.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cssmcli.h; sourceTree = ""; }; + 4CCBFE8D057FF55900981D43 /* cssmconfig.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cssmconfig.h; sourceTree = ""; }; + 4CCBFE8E057FF55900981D43 /* cssmcspi.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cssmcspi.h; sourceTree = ""; }; + 4CCBFE8F057FF55900981D43 /* cssmdli.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cssmdli.h; sourceTree = ""; }; + 4CCBFE90057FF55900981D43 /* cssmerr.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cssmerr.h; sourceTree = ""; }; + 4CCBFE91057FF55900981D43 /* cssmkrapi.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cssmkrapi.h; sourceTree = ""; }; + 4CCBFE92057FF55900981D43 /* cssmkrspi.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cssmkrspi.h; sourceTree = ""; }; + 4CCBFE93057FF55900981D43 /* cssmspi.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cssmspi.h; sourceTree = ""; }; + 4CCBFE94057FF55900981D43 /* cssmtpi.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cssmtpi.h; sourceTree = ""; }; + 4CCBFE95057FF55900981D43 /* cssmtype.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cssmtype.h; sourceTree = ""; }; + 4CCBFE96057FF55900981D43 /* eisl.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = eisl.h; sourceTree = ""; }; + 4CCBFE97057FF55900981D43 /* emmspi.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = emmspi.h; sourceTree = ""; }; + 4CCBFE98057FF55900981D43 /* emmtype.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = emmtype.h; sourceTree = ""; }; + 4CCBFE9D057FF55900981D43 /* oidsbase.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = oidsbase.h; sourceTree = ""; }; + 4CCBFE9E057FF55900981D43 /* oidscert.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = oidscert.h; sourceTree = ""; }; + 4CCBFE9F057FF55900981D43 /* oidscrl.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = oidscrl.h; sourceTree = ""; }; + 4CCBFEA0057FF55900981D43 /* x509defs.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = x509defs.h; sourceTree = ""; }; + 4CCBFEF5057FF5BD00981D43 /* security_cssm.exp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.exports; path = security_cssm.exp; sourceTree = ""; }; + 4CE14B710537820F00840CC1 /* cssm.mdsinfo */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.xml; path = cssm.mdsinfo; sourceTree = ""; }; + C2F84591052CA34400F4D742 /* attachfactory.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = attachfactory.cpp; sourceTree = ""; }; + C2F84592052CA34400F4D742 /* attachfactory.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = attachfactory.h; sourceTree = ""; }; + C2F84593052CA34400F4D742 /* attachment.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = attachment.cpp; sourceTree = ""; }; + C2F84594052CA34400F4D742 /* attachment.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = attachment.h; sourceTree = ""; }; + C2F84596052CA34400F4D742 /* cspattachment.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = cspattachment.cpp; sourceTree = ""; }; + C2F84597052CA34400F4D742 /* cspattachment.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cspattachment.h; sourceTree = ""; }; + C2F84598052CA34400F4D742 /* cssm.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = cssm.cpp; sourceTree = ""; }; + C2F84599052CA34400F4D742 /* cssmcontext.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = cssmcontext.cpp; sourceTree = ""; }; + C2F8459A052CA34400F4D742 /* cssmcontext.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cssmcontext.h; sourceTree = ""; }; + C2F8459B052CA34400F4D742 /* cssmint.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cssmint.h; sourceTree = ""; }; + C2F8459C052CA34400F4D742 /* cssmmds.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = cssmmds.cpp; sourceTree = ""; }; + C2F8459D052CA34400F4D742 /* cssmmds.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cssmmds.h; sourceTree = ""; }; + C2F8459E052CA34400F4D742 /* generator.cfg */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = generator.cfg; sourceTree = ""; }; + C2F8459F052CA34400F4D742 /* generator.mk */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = generator.mk; sourceTree = ""; }; + C2F845A0052CA34400F4D742 /* generator.pl */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.script.perl; path = generator.pl; sourceTree = ""; }; + C2F845A1052CA34400F4D742 /* guids.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = guids.cpp; sourceTree = ""; }; + C2F845A2052CA34400F4D742 /* manager.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = manager.cpp; sourceTree = ""; }; + C2F845A3052CA34400F4D742 /* manager.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = manager.h; sourceTree = ""; }; + C2F845A4052CA34400F4D742 /* modload_plugin.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = modload_plugin.cpp; sourceTree = ""; }; + C2F845A5052CA34400F4D742 /* modload_plugin.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = modload_plugin.h; sourceTree = ""; }; + C2F845A6052CA34400F4D742 /* modload_static.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = modload_static.cpp; sourceTree = ""; }; + C2F845A7052CA34400F4D742 /* modload_static.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = modload_static.h; sourceTree = ""; }; + C2F845A8052CA34400F4D742 /* modloader.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = modloader.cpp; sourceTree = ""; }; + C2F845A9052CA34400F4D742 /* modloader.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = modloader.h; sourceTree = ""; }; + C2F845AA052CA34400F4D742 /* module.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = module.cpp; sourceTree = ""; }; + C2F845AB052CA34400F4D742 /* module.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = module.h; sourceTree = ""; }; + C2F845AC052CA34400F4D742 /* oidsalg.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = oidsalg.c; sourceTree = ""; }; + C2F845AE052CA34400F4D742 /* oidscert.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = oidscert.cpp; sourceTree = ""; }; + C2F845AF052CA34400F4D742 /* oidscrl.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = oidscrl.cpp; sourceTree = ""; }; + C2F845B0052CA34400F4D742 /* transition.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = transition.cpp; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 4CA1FEBB052A3C8100F22E42 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 18446088146DF8FB00B12992 /* Products */ = { + isa = PBXGroup; + children = ( + 1844608D146DF8FB00B12992 /* libsecurity_utilities.a */, + ); + name = Products; + sourceTree = ""; + }; + 1879B4A0146DAE33007E536C /* config */ = { + isa = PBXGroup; + children = ( + 1879B4A1146DAE33007E536C /* base.xcconfig */, + 1879B4A2146DAE33007E536C /* debug.xcconfig */, + 1879B4A3146DAE33007E536C /* lib.xcconfig */, + 1879B4A4146DAE33007E536C /* release.xcconfig */, + ); + name = config; + path = ../config; + sourceTree = ""; + }; + 4CA1FEA7052A3C3800F22E42 = { + isa = PBXGroup; + children = ( + 18446087146DF8FB00B12992 /* libsecurity_utilities.xcodeproj */, + 4CCBFE7C057FF50400981D43 /* cdsa headers */, + C2F84590052CA34400F4D742 /* lib */, + 1879B4A0146DAE33007E536C /* config */, + 4CE14B700537820F00840CC1 /* mds */, + 4CA1FEBF052A3C8100F22E42 /* Products */, + ); + sourceTree = ""; + }; + 4CA1FEBF052A3C8100F22E42 /* Products */ = { + isa = PBXGroup; + children = ( + 4CA1FEBE052A3C8100F22E42 /* libsecurity_cssm.a */, + ); + name = Products; + sourceTree = SOURCE_ROOT; + }; + 4CCBFE7C057FF50400981D43 /* cdsa headers */ = { + isa = PBXGroup; + children = ( + 4CCBFE87057FF55900981D43 /* certextensions.h */, + 4CCBFE88057FF55900981D43 /* cssm.h */, + 4CCBFE89057FF55900981D43 /* cssmaci.h */, + 4CCBFE8A057FF55900981D43 /* cssmapi.h */, + 4CCBFE8B057FF55900981D43 /* cssmapple.h */, + 05D5BC2D0694857A00145F1E /* cssmapplePriv.h */, + 4CCBFE8C057FF55900981D43 /* cssmcli.h */, + 4CCBFE8D057FF55900981D43 /* cssmconfig.h */, + 4CCBFE8E057FF55900981D43 /* cssmcspi.h */, + 4CCBFE8F057FF55900981D43 /* cssmdli.h */, + 4CCBFE90057FF55900981D43 /* cssmerr.h */, + 4CCBFE91057FF55900981D43 /* cssmkrapi.h */, + 4CCBFE92057FF55900981D43 /* cssmkrspi.h */, + 4CCBFE93057FF55900981D43 /* cssmspi.h */, + 4CCBFE94057FF55900981D43 /* cssmtpi.h */, + 4CCBFE95057FF55900981D43 /* cssmtype.h */, + 4CCBFE96057FF55900981D43 /* eisl.h */, + 4CCBFE97057FF55900981D43 /* emmspi.h */, + 4CCBFE98057FF55900981D43 /* emmtype.h */, + 4CCBFE9D057FF55900981D43 /* oidsbase.h */, + 4CCBFE9E057FF55900981D43 /* oidscert.h */, + 4CCBFE9F057FF55900981D43 /* oidscrl.h */, + 4CCBFEA0057FF55900981D43 /* x509defs.h */, + ); + name = "cdsa headers"; + path = lib; + sourceTree = ""; + }; + 4CE14B700537820F00840CC1 /* mds */ = { + isa = PBXGroup; + children = ( + 4CE14B710537820F00840CC1 /* cssm.mdsinfo */, + ); + path = mds; + sourceTree = SOURCE_ROOT; + }; + C2F84590052CA34400F4D742 /* lib */ = { + isa = PBXGroup; + children = ( + C2F84591052CA34400F4D742 /* attachfactory.cpp */, + C2F84592052CA34400F4D742 /* attachfactory.h */, + C2F84593052CA34400F4D742 /* attachment.cpp */, + C2F84594052CA34400F4D742 /* attachment.h */, + C2F84596052CA34400F4D742 /* cspattachment.cpp */, + C2F84597052CA34400F4D742 /* cspattachment.h */, + C2F84598052CA34400F4D742 /* cssm.cpp */, + C2F84599052CA34400F4D742 /* cssmcontext.cpp */, + C2F8459A052CA34400F4D742 /* cssmcontext.h */, + C2F8459B052CA34400F4D742 /* cssmint.h */, + C2F8459C052CA34400F4D742 /* cssmmds.cpp */, + C2F8459D052CA34400F4D742 /* cssmmds.h */, + C2F8459E052CA34400F4D742 /* generator.cfg */, + C2F8459F052CA34400F4D742 /* generator.mk */, + C2F845A0052CA34400F4D742 /* generator.pl */, + C2F845A1052CA34400F4D742 /* guids.cpp */, + C2F845A2052CA34400F4D742 /* manager.cpp */, + C2F845A3052CA34400F4D742 /* manager.h */, + C2F845A4052CA34400F4D742 /* modload_plugin.cpp */, + C2F845A5052CA34400F4D742 /* modload_plugin.h */, + C2F845A6052CA34400F4D742 /* modload_static.cpp */, + C2F845A7052CA34400F4D742 /* modload_static.h */, + C2F845A8052CA34400F4D742 /* modloader.cpp */, + C2F845A9052CA34400F4D742 /* modloader.h */, + C2F845AA052CA34400F4D742 /* module.cpp */, + C2F845AB052CA34400F4D742 /* module.h */, + C2F845AC052CA34400F4D742 /* oidsalg.c */, + C2F845AE052CA34400F4D742 /* oidscert.cpp */, + C2F845AF052CA34400F4D742 /* oidscrl.cpp */, + C2F845B0052CA34400F4D742 /* transition.cpp */, + 4CCBFEF5057FF5BD00981D43 /* security_cssm.exp */, + ); + path = lib; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 4CA1FEB9052A3C8100F22E42 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + C2F845B2052CA34400F4D742 /* attachfactory.h in Headers */, + C2F845B4052CA34400F4D742 /* attachment.h in Headers */, + C2F845B7052CA34400F4D742 /* cspattachment.h in Headers */, + C2F845BA052CA34400F4D742 /* cssmcontext.h in Headers */, + C2F845BB052CA34400F4D742 /* cssmint.h in Headers */, + C2F845BD052CA34400F4D742 /* cssmmds.h in Headers */, + C2F845C0052CA34400F4D742 /* manager.h in Headers */, + 05D5BC2E0694857A00145F1E /* cssmapplePriv.h in Headers */, + C2F845C2052CA34400F4D742 /* modload_plugin.h in Headers */, + C2F845C4052CA34400F4D742 /* modload_static.h in Headers */, + C2F845C6052CA34400F4D742 /* modloader.h in Headers */, + C2F845C8052CA34400F4D742 /* module.h in Headers */, + 4CC62CE9058134E00020B996 /* certextensions.h in Headers */, + 4CC62CEA058134E00020B996 /* cssm.h in Headers */, + 4CC62CEB058134E00020B996 /* cssmaci.h in Headers */, + 4CC62CEC058134E00020B996 /* cssmapi.h in Headers */, + 4CC62CED058134E00020B996 /* cssmapple.h in Headers */, + 4CC62CEE058134E00020B996 /* cssmcli.h in Headers */, + 4CC62CEF058134E00020B996 /* cssmconfig.h in Headers */, + 4CC62CF0058134E00020B996 /* cssmcspi.h in Headers */, + 4CC62CF1058134E00020B996 /* cssmdli.h in Headers */, + 4CC62CF2058134E00020B996 /* cssmerr.h in Headers */, + 4CC62CF3058134E00020B996 /* cssmkrapi.h in Headers */, + 4CC62CF4058134E00020B996 /* cssmkrspi.h in Headers */, + 4CC62CF5058134E00020B996 /* cssmspi.h in Headers */, + 4CC62CF6058134E00020B996 /* cssmtpi.h in Headers */, + 4CC62CF7058134E00020B996 /* cssmtype.h in Headers */, + 4CC62CF8058134E00020B996 /* eisl.h in Headers */, + 4CC62CF9058134E00020B996 /* emmspi.h in Headers */, + 4CC62CFA058134E00020B996 /* emmtype.h in Headers */, + 4CC62CFD058134E00020B996 /* oidsbase.h in Headers */, + 4CC62CFE058134E00020B996 /* oidscert.h in Headers */, + 4CC62CFF058134E00020B996 /* oidscrl.h in Headers */, + 4CC62D00058134E00020B996 /* x509defs.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 4CA1FEBD052A3C8100F22E42 /* libsecurity_cssm */ = { + isa = PBXNativeTarget; + buildConfigurationList = C27AD3440987FCDE001272E0 /* Build configuration list for PBXNativeTarget "libsecurity_cssm" */; + buildPhases = ( + 4CA1FEB9052A3C8100F22E42 /* Headers */, + 1879B4DD146DCB37007E536C /* ShellScript */, + 4CA1FEBA052A3C8100F22E42 /* Sources */, + 4CA1FEBB052A3C8100F22E42 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + 182BB32F146F0FCB000BF1F3 /* PBXTargetDependency */, + ); + name = libsecurity_cssm; + productName = libsecurity_cssm; + productReference = 4CA1FEBE052A3C8100F22E42 /* libsecurity_cssm.a */; + productType = "com.apple.product-type.library.static"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 4CA1FEAB052A3C3800F22E42 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0420; + }; + buildConfigurationList = C27AD3480987FCDE001272E0 /* Build configuration list for PBXProject "libsecurity_cssm" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 1; + knownRegions = ( + English, + Japanese, + French, + German, + ); + mainGroup = 4CA1FEA7052A3C3800F22E42; + productRefGroup = 4CA1FEBF052A3C8100F22E42 /* Products */; + projectDirPath = ""; + projectReferences = ( + { + ProductGroup = 18446088146DF8FB00B12992 /* Products */; + ProjectRef = 18446087146DF8FB00B12992 /* libsecurity_utilities.xcodeproj */; + }, + ); + projectRoot = ""; + targets = ( + 4CA1FEBD052A3C8100F22E42 /* libsecurity_cssm */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXReferenceProxy section */ + 1844608D146DF8FB00B12992 /* libsecurity_utilities.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libsecurity_utilities.a; + remoteRef = 1844608C146DF8FB00B12992 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; +/* End PBXReferenceProxy section */ + +/* Begin PBXShellScriptBuildPhase section */ + 1879B4DD146DCB37007E536C /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "export SOURCEDIR=\"$PROJECT_DIR/lib\"\nexport CONFIG=\"$PROJECT_DIR/lib/generator.cfg\"\nexport TARGET=\"$BUILT_PRODUCTS_DIR/derived_src\"\n\nmake -f $PROJECT_DIR/lib/generator.mk\n\n#mkdir -p \"$TARGET\"\n#/usr/bin/perl lib/generator.pl \"$SOURCEDIR\" \"$CONFIG\" \"$TARGET\""; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 4CA1FEBA052A3C8100F22E42 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + C2F845B1052CA34400F4D742 /* attachfactory.cpp in Sources */, + C2F845B3052CA34400F4D742 /* attachment.cpp in Sources */, + C2F845B6052CA34400F4D742 /* cspattachment.cpp in Sources */, + C2F845B8052CA34400F4D742 /* cssm.cpp in Sources */, + C2F845B9052CA34400F4D742 /* cssmcontext.cpp in Sources */, + C2F845BC052CA34400F4D742 /* cssmmds.cpp in Sources */, + C2F845BE052CA34400F4D742 /* guids.cpp in Sources */, + C2F845BF052CA34400F4D742 /* manager.cpp in Sources */, + C2F845C1052CA34400F4D742 /* modload_plugin.cpp in Sources */, + C2F845C3052CA34400F4D742 /* modload_static.cpp in Sources */, + C2F845C5052CA34400F4D742 /* modloader.cpp in Sources */, + C2F845C7052CA34400F4D742 /* module.cpp in Sources */, + C2F845CB052CA34400F4D742 /* oidscert.cpp in Sources */, + C2F845CC052CA34400F4D742 /* oidscrl.cpp in Sources */, + C2F845CD052CA34400F4D742 /* transition.cpp in Sources */, + 18B647E514D9E72900F538BF /* oidsalg.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 182BB32F146F0FCB000BF1F3 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = libsecurity_utilitiesDTrace; + targetProxy = 182BB32E146F0FCB000BF1F3 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + C27AD3450987FCDE001272E0 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1879B4A2146DAE33007E536C /* debug.xcconfig */; + buildSettings = { + }; + name = Debug; + }; + C27AD3470987FCDE001272E0 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1879B4A4146DAE33007E536C /* release.xcconfig */; + buildSettings = { + }; + name = Release; + }; + C27AD3490987FCDE001272E0 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1879B4A3146DAE33007E536C /* lib.xcconfig */; + buildSettings = { + }; + name = Debug; + }; + C27AD34B0987FCDE001272E0 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1879B4A3146DAE33007E536C /* lib.xcconfig */; + buildSettings = { + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + C27AD3440987FCDE001272E0 /* Build configuration list for PBXNativeTarget "libsecurity_cssm" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C27AD3450987FCDE001272E0 /* Debug */, + C27AD3470987FCDE001272E0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C27AD3480987FCDE001272E0 /* Build configuration list for PBXProject "libsecurity_cssm" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C27AD3490987FCDE001272E0 /* Debug */, + C27AD34B0987FCDE001272E0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 4CA1FEAB052A3C3800F22E42 /* Project object */; +} diff --git a/libsecurity_cssm/mds/cssm.mdsinfo b/libsecurity_cssm/mds/cssm.mdsinfo new file mode 100644 index 00000000..6d7ae78d --- /dev/null +++ b/libsecurity_cssm/mds/cssm.mdsinfo @@ -0,0 +1,24 @@ + + + + + CDSAVersion + 2.0 + Desc + Apple Standard CSSM + MdsFileDescription + Built-in CSSM Common info + MdsFileType + CSSM + ModuleID + {87191ca0-0fc9-11d4-849a-000502b52122} + ModuleName + Security.framework + NativeServices + CSSM_SERVICE_CSSM|CSSM_SERVICE_CSP|CSSM_SERVICE_DL|CSSM_SERVICE_CL|CSSM_SERVICE_TP|CSSM_SERVICE_AC + ProductVersion + 2.0 + Vendor + Apple Computer, Inc. + + diff --git a/libsecurity_filedb/Info-security_filedb.plist b/libsecurity_filedb/Info-security_filedb.plist new file mode 100644 index 00000000..0c67376e --- /dev/null +++ b/libsecurity_filedb/Info-security_filedb.plist @@ -0,0 +1,5 @@ + + + + + diff --git a/libsecurity_filedb/lib/AppleDatabase.cpp b/libsecurity_filedb/lib/AppleDatabase.cpp new file mode 100644 index 00000000..dbe9ecec --- /dev/null +++ b/libsecurity_filedb/lib/AppleDatabase.cpp @@ -0,0 +1,2561 @@ +/* + * Copyright (c) 2000-2001, 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. + */ + + +// +// AppleDatabase.cpp - Description t.b.d. +// +#include "AppleDatabase.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static const char *kAppleDatabaseChanged = "com.apple.AppleDatabaseChanged"; + +/* Number of seconds after which we open/pread/close a db to check it's + version number even if we didn't get any notifications. Note that we always + check just after we take a write lock and whenever we get a notification + that any db on the system has changed. */ +static const CFTimeInterval kForceReReadTime = 15.0; + +/* Token on which we receive notifications and the pthread_once_t protecting + it's initialization. */ +pthread_once_t gCommonInitMutex = PTHREAD_ONCE_INIT; + +/* Global counter of how many notifications we have received and a lock to + protect the counter. */ +static int kSegmentSize = 4; +int32_t* gSegment = NULL; + +/* Registration routine for notifcations. Called inside a pthread_once(). */ +static void initCommon(void) +{ + // open the file + int segmentDescriptor = shm_open (kAppleDatabaseChanged, O_RDWR | O_CREAT, S_IRWXU | S_IRWXG | S_IRWXO); + if (segmentDescriptor < 0) + { + 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); + + if (tmp == (int32_t*) -1) // can't map the memory? + { + gSegment = NULL; + } + else + { + gSegment = tmp; + } +} + +// +// Table +// +Table::Table(const ReadSection &inTableSection) : + mMetaRecord(inTableSection[OffsetId]), + mTableSection(inTableSection), + mRecordsCount(inTableSection[OffsetRecordsCount]), + mFreeListHead(inTableSection[OffsetFreeListHead]), + mRecordNumbersCount(inTableSection[OffsetRecordNumbersCount]) +{ + // can't easily initialize indexes here, since meta record is incomplete + // until much later... see DbVersion::open() +} + +Table::~Table() +{ + for_each_map_delete(mIndexMap.begin(), mIndexMap.end()); +} + +void +Table::readIndexSection() +{ + uint32 indexSectionOffset = mTableSection.at(OffsetIndexesOffset); + + uint32 numIndexes = mTableSection.at(indexSectionOffset + AtomSize); + + 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(); + } +} + +Cursor * +Table::createCursor(const CSSM_QUERY *inQuery, const DbVersion &inDbVersion) const +{ + // if an index matches the query, return a cursor which uses the index + + 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); + return cursor; + } + + // otherwise, return a cursor that iterates over all table records + + return new LinearCursor(inQuery, inDbVersion, *this); +} + +const ReadSection +Table::getRecordSection(uint32 inRecordNumber) const +{ + if (inRecordNumber >= mRecordNumbersCount) + CssmError::throwMe(CSSMERR_DL_INVALID_RECORD_UID); + + uint32 aRecordOffset = mTableSection[OffsetRecordNumbers + AtomSize + * inRecordNumber]; + + // Check if this RecordNumber has been deleted. + if (aRecordOffset & 1 || aRecordOffset == 0) + CssmError::throwMe(CSSMERR_DL_RECORD_NOT_FOUND); + + return MetaRecord::readSection(mTableSection, aRecordOffset); +} + +const RecordId +Table::getRecord(const RecordId &inRecordId, + CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR inoutAttributes, + CssmData *inoutData, + Allocator &inAllocator) const +{ + const ReadSection aRecordSection = getRecordSection(inRecordId.mRecordNumber); + const RecordId aRecordId = MetaRecord::unpackRecordId(aRecordSection); + + // Make sure the RecordNumber matches that in the RecordId we just retrived. + if (aRecordId.mRecordNumber != inRecordId.mRecordNumber) + CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT); + + if (aRecordId.mCreateVersion != inRecordId.mCreateVersion) + CssmError::throwMe(CSSMERR_DL_INVALID_RECORD_UID); + + // XXX Figure out which value to pass for inQueryFlags (5th) argument + mMetaRecord.unpackRecord(aRecordSection, inAllocator, inoutAttributes, + inoutData, 0); + return aRecordId; +} + +uint32 +Table::popFreeList(uint32 &aFreeListHead) const +{ + assert(aFreeListHead | 1); + uint32 anOffset = aFreeListHead ^ 1; + uint32 aRecordNumber = (anOffset - OffsetRecordNumbers) / AtomSize; + aFreeListHead = mTableSection[anOffset]; + return aRecordNumber; +} + +const ReadSection +Table::getRecordsSection() const +{ + return mTableSection.subsection(mTableSection[OffsetRecords]); +} + +bool +Table::matchesTableId(Id inTableId) const +{ + Id anId = mMetaRecord.dataRecordType(); + if (inTableId == CSSM_DL_DB_RECORD_ANY) // All non schema tables. + return !(CSSM_DB_RECORDTYPE_SCHEMA_START <= anId + && anId < CSSM_DB_RECORDTYPE_SCHEMA_END); + + if (inTableId == CSSM_DL_DB_RECORD_ALL_KEYS) // All key tables. + return (anId == CSSM_DL_DB_RECORD_PUBLIC_KEY + || anId == CSSM_DL_DB_RECORD_PRIVATE_KEY + || anId == CSSM_DL_DB_RECORD_SYMMETRIC_KEY); + + return inTableId == anId; // Only if exact match. +} + + +// +// ModifiedTable +// +ModifiedTable::ModifiedTable(const Table *inTable) : + mTable(inTable), + mNewMetaRecord(nil), + mRecordNumberCount(inTable->recordNumberCount()), + mFreeListHead(inTable->freeListHead()), + mIsModified(false) +{ +} + +ModifiedTable::ModifiedTable(MetaRecord *inMetaRecord) : + mTable(nil), + mNewMetaRecord(inMetaRecord), + mRecordNumberCount(0), + mFreeListHead(0), + mIsModified(true) +{ +} + +ModifiedTable::~ModifiedTable() +{ + for_each_map_delete(mIndexMap.begin(), mIndexMap.end()); + for_each_map_delete(mInsertedMap.begin(), mInsertedMap.end()); + + delete mNewMetaRecord; +} + +void +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++) + it->second->removeRecord(aRecordNumber); + + InsertedMap::iterator anIt = mInsertedMap.find(aRecordNumber); + if (anIt == mInsertedMap.end()) + { + // If we have no old table than this record can not exist yet. + if (!mTable) + CssmError::throwMe(CSSMERR_DL_RECORD_NOT_FOUND); + +#if RECORDVERSIONCHECK + const RecordId aRecordId = MetaRecord::unpackRecordId(mTable->getRecordSection(aRecordNumber)); + if (aRecordId.mRecordVersion != inRecordId.mRecordVersion) + CssmError::throwMe(CSSMERR_DL_RECORD_MODIFIED); +#endif + + // Schedule the record for deletion + if (!mDeletedSet.insert(aRecordNumber).second) + CssmError::throwMe(CSSMERR_DL_RECORD_NOT_FOUND); // It was already deleted + } + else + { + const RecordId aRecordId = MetaRecord::unpackRecordId(*anIt->second); + if (aRecordId.mCreateVersion != inRecordId.mCreateVersion) + CssmError::throwMe(CSSMERR_DL_RECORD_NOT_FOUND); + +#if RECORDVERSIONCHECK + if (aRecordId.mRecordVersion != inRecordId.mRecordVersion) + CssmError::throwMe(CSSMERR_DL_RECORD_MODIFIED); +#endif + + // Remove the inserted (but uncommited) record. It should already be in mDeletedSet + // if it existed previously in mTable. + delete anIt->second; + mInsertedMap.erase(anIt); + } +} + +const RecordId +ModifiedTable::insertRecord(uint32 inVersionId, + const CSSM_DB_RECORD_ATTRIBUTE_DATA *inAttributes, + 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; + for (it = mIndexMap.begin(); it != mIndexMap.end(); it++) + it->second->insertRecord(aRecordNumber, *(aWriteSection.get())); + + // schedule the record for insertion + RecordId aRecordId(aRecordNumber, inVersionId); + MetaRecord::packRecordId(aRecordId, *aWriteSection); + mInsertedMap.insert(InsertedMap::value_type(aRecordNumber, aWriteSection.get())); + + aWriteSection.release(); + + return aRecordId; +} + +const RecordId +ModifiedTable::updateRecord(const RecordId &inRecordId, + const CSSM_DB_RECORD_ATTRIBUTE_DATA *inAttributes, + const CssmData *inData, + CSSM_DB_MODIFY_MODE inModifyMode) +{ + modifyTable(); + + uint32 aRecordNumber = inRecordId.mRecordNumber; + InsertedMap::iterator anIt = mInsertedMap.find(aRecordNumber); + + // aReUpdate is true iff we are updating an already updated record. + bool aReUpdate = anIt != mInsertedMap.end(); + + // If we are not re-updating and there is no old table than this record does not exist yet. + if (!aReUpdate && !mTable) + CssmError::throwMe(CSSMERR_DL_RECORD_NOT_FOUND); + + const ReadSection &anOldDbRecord = aReUpdate ? *anIt->second : mTable->getRecordSection(aRecordNumber); + const RecordId aRecordId = MetaRecord::unpackRecordId(anOldDbRecord); + + // Did someone else delete the record we are trying to update. + if (aRecordId.mCreateVersion != inRecordId.mCreateVersion) + CssmError::throwMe(CSSMERR_DL_RECORD_NOT_FOUND); + +#if RECORDVERSIONCHECK + // Is the record we that our update is based on current? + if (aRecordId.mRecordVersion != inRecordId.mRecordVersion) + CssmError::throwMe(CSSMERR_DL_STALE_UNIQUE_RECORD); +#endif + + // Update the actual packed record. + auto_ptr aDbRecord(new WriteSection()); + getMetaRecord().updateRecord(anOldDbRecord, *aDbRecord, + CssmDbRecordAttributeData::overlay(inAttributes), inData, inModifyMode); + + + // Bump the RecordVersion of this record. + RecordId aNewRecordId(aRecordNumber, inRecordId.mCreateVersion, inRecordId.mRecordVersion + 1); + // Store the RecordVersion in the packed aDbRecord. + MetaRecord::packRecordId(aNewRecordId, *aDbRecord); + + if (!aReUpdate && !mDeletedSet.insert(aRecordNumber).second) + CssmError::throwMe(CSSMERR_DL_RECORD_NOT_FOUND); // Record was already in mDeletedSet + + // remove the original record from all the indexes + MutableIndexMap::iterator it; + for (it = mIndexMap.begin(); it != mIndexMap.end(); it++) + it->second->removeRecord(aRecordNumber); + + try + { + // Add the updated record to all the indexes; this will throw if the new record + // violates a unique index + for (it = mIndexMap.begin(); it != mIndexMap.end(); it++) + it->second->insertRecord(aRecordNumber, *(aDbRecord.get())); + + if (aReUpdate) + { + // Get rid of anOldDbRecord from the inserted map and replace it + // with aDbRecord. + delete anIt->second; + anIt->second = aDbRecord.get(); + } + else + { + // First time though so let's just put the new value in the map. + mInsertedMap.insert(InsertedMap::value_type(aRecordNumber, aDbRecord.get())); + } + aDbRecord.release(); + } + catch(...) + { + // We only remove aRecordNumber from mDeletedSet if we added it above. + if (!aReUpdate) + mDeletedSet.erase(aRecordNumber); + + // The 2 operations below are an attempt to preserve the indices when + // an insert fails. + + // Remove the updated record from all the indexes + MutableIndexMap::iterator it; + for (it = mIndexMap.begin(); it != mIndexMap.end(); it++) + it->second->removeRecord(aRecordNumber); + + // Add the original record back to all the indexes + for (it = mIndexMap.begin(); it != mIndexMap.end(); it++) + it->second->insertRecord(aRecordNumber, anOldDbRecord); + + throw; + } + + return aNewRecordId; +} + +const RecordId +ModifiedTable::getRecord(const RecordId &inRecordId, + CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR inoutAttributes, + CssmData *inoutData, + Allocator &inAllocator) const +{ + if (mIsModified) + { + uint32 aRecordNumber = inRecordId.mRecordNumber; + InsertedMap::const_iterator anIt = mInsertedMap.find(aRecordNumber); + if (anIt != mInsertedMap.end()) + { + // We found the record in mInsertedMap so we use the inserted + // record. + const ReadSection &aRecordSection = *(anIt->second); + const RecordId aRecordId = MetaRecord::unpackRecordId(aRecordSection); + + // Make sure the RecordNumber matches that in the RecordId we just retrived. + if (aRecordId.mRecordNumber != aRecordNumber) + CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT); + + if (aRecordId.mCreateVersion != inRecordId.mCreateVersion) + CssmError::throwMe(CSSMERR_DL_INVALID_RECORD_UID); + + // XXX Figure out which value to pass for inQueryFlags (5th) argument + getMetaRecord().unpackRecord(aRecordSection, inAllocator, + inoutAttributes, inoutData, 0); + + return aRecordId; + } + else if (mDeletedSet.find(aRecordNumber) != mDeletedSet.end()) + { + // If aRecordNumber was not in mInsertedMap but it was in + // mDeletedSet then it was deleted but not yet commited. + CssmError::throwMe(CSSMERR_DL_RECORD_NOT_FOUND); + } + } + + if (!mTable) + CssmError::throwMe(CSSMERR_DL_RECORD_NOT_FOUND); + + // Either this table wasn't modified yet or we didn't find aRecordNumber in + // mInsertedMap nor mDeletedSet so just ask mTable for it. + return mTable->getRecord(inRecordId, inoutAttributes, inoutData, + inAllocator); +} + +uint32 +ModifiedTable::nextRecordNumber() +{ + // If we still have unused free records in mTable get the next one. + if (mFreeListHead) + return mTable->popFreeList(mFreeListHead); + + // Bump up the mRecordNumberCount so we don't reuse the same one. + return mRecordNumberCount++; +} + +uint32 +ModifiedTable::recordNumberCount() const +{ + uint32 anOldMax = !mTable ? 0 : mTable->recordNumberCount() - 1; + uint32 anInsertedMax = mInsertedMap.empty() ? 0 : mInsertedMap.rbegin()->first; + + DeletedSet::reverse_iterator anIt = mDeletedSet.rbegin(); + DeletedSet::reverse_iterator anEnd = mDeletedSet.rend(); + for (; anIt != anEnd; anIt++) + { + if (*anIt != anOldMax || anOldMax <= anInsertedMax) + break; + anOldMax--; + } + + return max(anOldMax,anInsertedMax) + 1; +} + +const MetaRecord & +ModifiedTable::getMetaRecord() const +{ + return mNewMetaRecord ? *mNewMetaRecord : mTable->getMetaRecord(); +} + +// prepare to modify the table + +void +ModifiedTable::modifyTable() +{ + if (!mIsModified) { + createMutableIndexes(); + mIsModified = true; + } +} + +// create mutable indexes from the read-only indexes in the underlying table + +void +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)); + mIndexMap.insert(MutableIndexMap::value_type(it->first, mutableIndex.get())); + mutableIndex.release(); + } +} + +// find, and create if needed, an index with the given id + +DbMutableIndex & +ModifiedTable::findIndex(uint32 indexId, const MetaRecord &metaRecord, bool isUniqueIndex) +{ + MutableIndexMap::iterator it = mIndexMap.find(indexId); + + if (it == mIndexMap.end()) { + // create the new index + auto_ptr index(new DbMutableIndex(metaRecord, indexId, isUniqueIndex)); + it = mIndexMap.insert(MutableIndexMap::value_type(indexId, index.get())).first; + index.release(); + } + + return *it->second; +} + +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, 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); + + return offset; +} + +uint32 +ModifiedTable::writeTable(AtomicTempFile &inAtomicTempFile, uint32 inSectionOffset) +{ + if (mTable && !mIsModified) { + // the table has not been modified, so we can just dump the old table + // section into the new database + + const ReadSection &tableSection = mTable->getTableSection(); + uint32 tableSize = tableSection.at(Table::OffsetSize); + + inAtomicTempFile.write(AtomicFile::FromStart, inSectionOffset, + tableSection.range(Range(0, tableSize)), tableSize); + + return inSectionOffset + tableSize; + } + + // 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; + WriteSection aTableSection(Allocator::standard(), aRecordsOffset); + aTableSection.size(aRecordsOffset); + 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 + // to AtomicFile::write() + uint32 anOldRecordsCount = mTable->getRecordsCount(); + 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 aBlockSize = 0; // Size of block to read + for (uint32 aRecord = 0; aRecord < anOldRecordsCount; aRecord++) + { + ReadSection aRecordSection = MetaRecord::readSection(aRecordsSection, aReadOffset); + uint32 aRecordNumber = MetaRecord::unpackRecordNumber(aRecordSection); + uint32 aRecordSize = aRecordSection.size(); + aReadOffset += aRecordSize; + if (mDeletedSet.find(aRecordNumber) == mDeletedSet.end()) + { + // This record has not been deleted. Register the offset + // at which it will be in the new file in aTableSection. + aTableSection.put(Table::OffsetRecordNumbers + + AtomSize * aRecordNumber, + aWriteOffset); + aWriteOffset += aRecordSize; + aBlockSize += aRecordSize; + aRecordsCount++; + // XXX update all indexes being created. + } + else + { + // The current record has been deleted. Copy all records up + // to but not including the current one to the new file. + if (aBlockSize > 0) + { + inAtomicTempFile.write(AtomicFile::FromStart, anOffset, + aRecordsSection.range(Range(aBlockStart, + aBlockSize)), + aBlockSize); + anOffset += aBlockSize; + } + + // Set the start of the next block to the start of the next + // record, and the size of the block to 0. + aBlockStart = aReadOffset; + aBlockSize = 0; + } // if (mDeletedSet..) + } // for (aRecord...) + + // Copy all records that have not yet been copied to the new file. + if (aBlockSize > 0) + { + inAtomicTempFile.write(AtomicFile::FromStart, anOffset, + aRecordsSection.range(Range(aBlockStart, + aBlockSize)), + aBlockSize); + anOffset += aBlockSize; + } + } // if (mTable) + + // Now add all inserted records to the table. + InsertedMap::const_iterator anIt = mInsertedMap.begin(); + InsertedMap::const_iterator anEnd = mInsertedMap.end(); + // Iterate over all inserted objects. + for (; anIt != anEnd; anIt++) + { + // Write out each inserted/modified record + const WriteSection &aRecord = *anIt->second; + uint32 aRecordNumber = anIt->first; + // Put offset relative to start of this table in recordNumber array. + aTableSection.put(Table::OffsetRecordNumbers + AtomSize * aRecordNumber, + anOffset - inSectionOffset); + inAtomicTempFile.write(AtomicFile::FromStart, anOffset, + aRecord.address(), aRecord.size()); + anOffset += aRecord.size(); + aRecordsCount++; + // XXX update all indexes being created. + } + + // Reconstruct the freelist (this is O(N) where N is the number of recordNumbers) + // We could implement it faster by using the old freelist and skipping the records + // that have been inserted. However building the freelist for the newly used + // recordNumbers (not in mTable) would look like the code below anyway (starting + // from mTable->recordNumberCount()). + // The first part of this would be O(M Log(N)) (where M is the old number of + // free records, and N is the number of newly inserted records) + // The second part would be O(N) where N is the currently max RecordNumber + // in use - the old max RecordNumber in use. + uint32 aFreeListHead = 0; // Link to previous free record + for (uint32 aRecordNumber = 0; aRecordNumber < aRecordNumbersCount; aRecordNumber++) + { + // Make the freelist a list of all records with 0 offset (non existing). + if (!aTableSection.at(Table::OffsetRecordNumbers + AtomSize * aRecordNumber)) + { + aTableSection.put(Table::OffsetRecordNumbers + + AtomSize * aRecordNumber, + aFreeListHead); + // Make aFreeListHead point to the previous free recordNumber slot in the table. + aFreeListHead = (Table::OffsetRecordNumbers + AtomSize * aRecordNumber) | 1; + } + } + 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, + aTableSection.address() + indexOffset, anOffset - indexOffset); + } + + // Set the section size and recordCount. + aTableSection.put(Table::OffsetSize, anOffset); + aTableSection.put(Table::OffsetRecordsCount, aRecordsCount); + + // Write out aTableSection header. + inAtomicTempFile.write(AtomicFile::FromStart, inSectionOffset, + aTableSection.address(), aTableSection.size()); + + return anOffset + inSectionOffset; +} + + + +// +// Metadata +// + +// Attribute definitions + +static const CSSM_DB_ATTRIBUTE_INFO RelationID = +{ + CSSM_DB_ATTRIBUTE_NAME_AS_STRING, + {(char*) "RelationID"}, + CSSM_DB_ATTRIBUTE_FORMAT_UINT32 +}; +static const CSSM_DB_ATTRIBUTE_INFO RelationName = +{ + CSSM_DB_ATTRIBUTE_NAME_AS_STRING, + {(char*) "RelationName"}, + CSSM_DB_ATTRIBUTE_FORMAT_STRING +}; +static const CSSM_DB_ATTRIBUTE_INFO AttributeID = +{ + CSSM_DB_ATTRIBUTE_NAME_AS_STRING, + {(char*) "AttributeID"}, + CSSM_DB_ATTRIBUTE_FORMAT_UINT32 +}; +static const CSSM_DB_ATTRIBUTE_INFO AttributeNameFormat = +{ + CSSM_DB_ATTRIBUTE_NAME_AS_STRING, + {(char*) "AttributeNameFormat"}, + CSSM_DB_ATTRIBUTE_FORMAT_UINT32 +}; +static const CSSM_DB_ATTRIBUTE_INFO AttributeName = +{ + CSSM_DB_ATTRIBUTE_NAME_AS_STRING, + {(char*) "AttributeName"}, + CSSM_DB_ATTRIBUTE_FORMAT_STRING +}; +static const CSSM_DB_ATTRIBUTE_INFO AttributeNameID = +{ + CSSM_DB_ATTRIBUTE_NAME_AS_STRING, + {(char*) "AttributeNameID"}, + CSSM_DB_ATTRIBUTE_FORMAT_BLOB +}; +static const CSSM_DB_ATTRIBUTE_INFO AttributeFormat = +{ + CSSM_DB_ATTRIBUTE_NAME_AS_STRING, + {(char*) "AttributeFormat"}, + CSSM_DB_ATTRIBUTE_FORMAT_UINT32 +}; +static const CSSM_DB_ATTRIBUTE_INFO IndexID = +{ + CSSM_DB_ATTRIBUTE_NAME_AS_STRING, + {(char*) "IndexID"}, + CSSM_DB_ATTRIBUTE_FORMAT_UINT32 +}; +static const CSSM_DB_ATTRIBUTE_INFO IndexType = +{ + CSSM_DB_ATTRIBUTE_NAME_AS_STRING, + {(char*) "IndexType"}, + CSSM_DB_ATTRIBUTE_FORMAT_UINT32 +}; +static const CSSM_DB_ATTRIBUTE_INFO IndexedDataLocation = +{ + CSSM_DB_ATTRIBUTE_NAME_AS_STRING, + {(char*) "IndexedDataLocation"}, + CSSM_DB_ATTRIBUTE_FORMAT_UINT32 +}; +static const CSSM_DB_ATTRIBUTE_INFO ModuleID = +{ + CSSM_DB_ATTRIBUTE_NAME_AS_STRING, + {(char*) "ModuleID"}, + CSSM_DB_ATTRIBUTE_FORMAT_BLOB +}; +static const CSSM_DB_ATTRIBUTE_INFO AddinVersion = +{ + CSSM_DB_ATTRIBUTE_NAME_AS_STRING, + {(char*) "AddinVersion"}, + CSSM_DB_ATTRIBUTE_FORMAT_STRING +}; +static const CSSM_DB_ATTRIBUTE_INFO SSID = +{ + CSSM_DB_ATTRIBUTE_NAME_AS_STRING, + {(char*) "SSID"}, + CSSM_DB_ATTRIBUTE_FORMAT_UINT32 +}; +static const CSSM_DB_ATTRIBUTE_INFO SubserviceType = +{ + CSSM_DB_ATTRIBUTE_NAME_AS_STRING, + {(char*) "SubserviceType"}, + CSSM_DB_ATTRIBUTE_FORMAT_UINT32 +}; + +#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 + ATTRIBUTE(UINT32, RelationID), + ATTRIBUTE(STRING, RelationName) +}; + +static const CSSM_DB_ATTRIBUTE_INFO AttrSchemaAttributes[] = +{ + //RelationID, AttributeID, + //AttributeNameFormat, AttributeName, AttributeNameID, + //AttributeFormat + ATTRIBUTE(UINT32, RelationID), + ATTRIBUTE(UINT32, AttributeID), + ATTRIBUTE(UINT32, AttributeNameFormat), + ATTRIBUTE(STRING, AttributeName), + ATTRIBUTE(BLOB, AttributeNameID), + ATTRIBUTE(UINT32, AttributeFormat) +}; + +static const CSSM_DB_ATTRIBUTE_INFO AttrSchemaIndexes[] = +{ + ATTRIBUTE(UINT32, RelationID), + ATTRIBUTE(UINT32, IndexID), + ATTRIBUTE(UINT32, AttributeID), + ATTRIBUTE(UINT32, IndexType), + ATTRIBUTE(UINT32, IndexedDataLocation) + //RelationID, IndexID, AttributeID, + //IndexType, IndexedDataLocation +}; + +static const CSSM_DB_ATTRIBUTE_INFO AttrSchemaParsingModule[] = +{ + ATTRIBUTE(UINT32, RelationID), + ATTRIBUTE(UINT32, AttributeID), + ATTRIBUTE(BLOB, ModuleID), + ATTRIBUTE(STRING, AddinVersion), + ATTRIBUTE(UINT32, SSID), + ATTRIBUTE(UINT32, SubserviceType) + //RelationID, AttributeID, + //ModuleID, AddinVersion, SSID, SubserviceType +}; + +#undef ATTRIBUTE + +// +// DbVersion +// +DbVersion::DbVersion(const AppleDatabase &db, const RefPointer &inAtomicBufferedFile) : + mDatabase(reinterpret_cast(NULL), 0), + mDb(db), + mBufferedFile(inAtomicBufferedFile) +{ + off_t aLength = mBufferedFile->length(); + off_t bytesRead = 0; + const uint8 *ptr = mBufferedFile->read(0, aLength, bytesRead); + mBufferedFile->close(); + mDatabase = ReadSection(ptr, bytesRead); + open(); +} + +DbVersion::~DbVersion() +{ + try + { + for_each_map_delete(mTableMap.begin(), mTableMap.end()); + } + catch(...) {} +} + +void +DbVersion::open() +{ + try + { + // This is the oposite of DbModifier::commit() + mVersionId = mDatabase[mDatabase.size() - AtomSize]; + + const ReadSection aHeaderSection = mDatabase.subsection(HeaderOffset, + 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++) + { + uint32 aTableOffset = aSchemaSection.at(OffsetTables + AtomSize + * aTableNumber); + // XXX Set the size boundary on aTableSection. + const ReadSection aTableSection = + aSchemaSection.subsection(aTableOffset); + auto_ptr aTable(new Table(aTableSection)); + Table::Id aTableId = aTable->getMetaRecord().dataRecordType(); + mTableMap.insert(TableMap::value_type(aTableId, aTable.get())); + aTable.release(); + } + + // Fill in the schema for the meta tables. + + findTable(mDb.schemaRelations.DataRecordType).getMetaRecord(). + setRecordAttributeInfo(mDb.schemaRelations); + findTable(mDb.schemaIndexes.DataRecordType).getMetaRecord(). + setRecordAttributeInfo(mDb.schemaIndexes); + findTable(mDb.schemaParsingModule.DataRecordType).getMetaRecord(). + setRecordAttributeInfo(mDb.schemaParsingModule); + + // OK, we have created all the tables in the tableMap. Now + // lets read the schema and proccess it accordingly. + // Iterate over all schema records. + Table &aTable = findTable(mDb.schemaAttributes.DataRecordType); + aTable.getMetaRecord().setRecordAttributeInfo(mDb.schemaAttributes); + uint32 aRecordsCount = aTable.getRecordsCount(); + ReadSection aRecordsSection = aTable.getRecordsSection(); + uint32 aReadOffset = 0; + const MetaRecord &aMetaRecord = aTable.getMetaRecord(); + + CSSM_DB_ATTRIBUTE_DATA aRelationIDData = + { + RelationID, + 0, + NULL + }; + CSSM_DB_ATTRIBUTE_DATA aAttributeIDData = + { + AttributeID, + 0, + NULL + }; + CSSM_DB_ATTRIBUTE_DATA aAttributeNameFormatData = + { + AttributeNameFormat, + 0, + NULL + }; + CSSM_DB_ATTRIBUTE_DATA aAttributeNameData = + { + AttributeName, + 0, + NULL + }; + CSSM_DB_ATTRIBUTE_DATA aAttributeNameIDData = + { + AttributeNameID, + 0, + NULL + }; + CSSM_DB_ATTRIBUTE_DATA aAttributeFormatData = + { + AttributeFormat, + 0, + NULL + }; + CSSM_DB_ATTRIBUTE_DATA aRecordAttributes[] = + { + aRelationIDData, + aAttributeIDData, + aAttributeNameFormatData, + aAttributeNameData, + aAttributeNameIDData, + aAttributeFormatData + }; + CSSM_DB_RECORD_ATTRIBUTE_DATA aRecordAttributeData = + { + aMetaRecord.dataRecordType(), + 0, + sizeof(aRecordAttributes) / sizeof(CSSM_DB_ATTRIBUTE_DATA), + aRecordAttributes + }; + CssmDbRecordAttributeData &aRecordData = CssmDbRecordAttributeData::overlay(aRecordAttributeData); + + TrackingAllocator recordAllocator(Allocator::standard()); + for (uint32 aRecord = 0; aRecord != aRecordsCount; aRecord++) + { + ReadSection aRecordSection = MetaRecord::readSection(aRecordsSection, aReadOffset); + uint32 aRecordSize = aRecordSection.size(); + aReadOffset += aRecordSize; + aMetaRecord.unpackRecord(aRecordSection, recordAllocator, + &aRecordAttributeData, NULL, 0); + // Create the attribute coresponding to this entry + if (aRecordData[0].size() != 1 || aRecordData[0].format() != CSSM_DB_ATTRIBUTE_FORMAT_UINT32) + CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT); + uint32 aRelationId = aRecordData[0]; + + // 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_RELATIONID_MDS_START which is 0x40000000. + // Ref. Radar 2817921. + if (CSSM_DB_RECORDTYPE_SCHEMA_START <= aRelationId && aRelationId < CSSM_DB_RECORDTYPE_SCHEMA_END) + continue; + + // Get the MetaRecord corresponding to the specified RelationId + MetaRecord &aMetaRecord = findTable(aRelationId).getMetaRecord(); + + if (aRecordData[1].size() != 1 + || aRecordData[1].format() != CSSM_DB_ATTRIBUTE_FORMAT_UINT32 + || aRecordData[2].size() != 1 + || aRecordData[2].format() != CSSM_DB_ATTRIBUTE_FORMAT_UINT32 + || aRecordData[5].size() != 1 + || aRecordData[5].format() != CSSM_DB_ATTRIBUTE_FORMAT_UINT32) + CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT); + + uint32 anAttributeId = aRecordData[1]; + uint32 anAttributeNameFormat = aRecordData[2]; + uint32 anAttributeFormat = aRecordData[5]; + auto_ptr aName; + const CssmData *aNameID = NULL; + + if (aRecordData[3].size() == 1) + { + if (aRecordData[3].format() != CSSM_DB_ATTRIBUTE_FORMAT_STRING) + CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT); + + auto_ptr aName2(new string(static_cast(aRecordData[3]))); + aName = aName2; + } + + if (aRecordData[4].size() == 1) + { + if (aRecordData[4].format() != CSSM_DB_ATTRIBUTE_FORMAT_BLOB) + CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT); + + // @@@ Invoking conversion operator to CssmData & on aRecordData[4] + // And taking address of result. + aNameID = &static_cast(aRecordData[4]); + } + + // Make sure that the attribute specified by anAttributeNameFormat is present. + switch (anAttributeNameFormat) + { + case CSSM_DB_ATTRIBUTE_NAME_AS_STRING: + if (aRecordData[3].size() != 1) + CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT); + break; + case CSSM_DB_ATTRIBUTE_NAME_AS_OID: + if (aRecordData[4].size() != 1) + CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT); + break; + case CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER: + break; + default: + CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT); + } + + // Create the attribute + aMetaRecord.createAttribute(aName.get(), aNameID, anAttributeId, anAttributeFormat); + } + + // initialize the indexes associated with each table + { + TableMap::iterator it; + for (it = mTableMap.begin(); it != mTableMap.end(); it++) + it->second->readIndexSection(); + } + } + catch(...) + { + for_each_map_delete(mTableMap.begin(), mTableMap.end()); + mTableMap.clear(); + throw; + } +} + +const RecordId +DbVersion::getRecord(Table::Id inTableId, const RecordId &inRecordId, + CSSM_DB_RECORD_ATTRIBUTE_DATA *inoutAttributes, + CssmData *inoutData, + Allocator &inAllocator) const +{ + return findTable(inTableId).getRecord(inRecordId, inoutAttributes, + inoutData, inAllocator); +} + +Cursor * +DbVersion::createCursor(const CSSM_QUERY *inQuery) const +{ + // XXX We should add support for these special query types + // By Creating a Cursor that iterates over multiple tables + if (!inQuery || inQuery->RecordType == CSSM_DL_DB_RECORD_ANY + || inQuery->RecordType == CSSM_DL_DB_RECORD_ALL_KEYS) + { + return new MultiCursor(inQuery, *this); + } + + return findTable(inQuery->RecordType).createCursor(inQuery, *this); +} + +bool DbVersion::hasTable(Table::Id inTableId) const +{ + TableMap::const_iterator it = mTableMap.find(inTableId); + return it != mTableMap.end(); +} + +const Table & +DbVersion::findTable(Table::Id inTableId) const +{ + TableMap::const_iterator it = mTableMap.find(inTableId); + if (it == mTableMap.end()) + CssmError::throwMe(CSSMERR_DL_INVALID_RECORDTYPE); + return *it->second; +} + +Table & +DbVersion::findTable(Table::Id inTableId) +{ + TableMap::iterator it = mTableMap.find(inTableId); + if (it == mTableMap.end()) + CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT); + return *it->second; +} + +// +// Cursor implemetation +// +Cursor::Cursor() +{ +} + +Cursor::Cursor(const DbVersion &inDbVersion) : mDbVersion(&inDbVersion) +{ +} + +Cursor::~Cursor() +{ +} + +bool +Cursor::next(Table::Id &outTableId, + CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR outAttributes, + CssmData *outData, + Allocator &inAllocator, + RecordId &recordId) +{ + return false; +} + +// +// LinearCursor implemetation +// +LinearCursor::LinearCursor(const CSSM_QUERY *inQuery, const DbVersion &inDbVersion, + const Table &inTable) : + Cursor(inDbVersion), + mRecordsCount(inTable.getRecordsCount()), + mRecord(0), + mRecordsSection(inTable.getRecordsSection()), + mReadOffset(0), + mMetaRecord(inTable.getMetaRecord()) +{ + if (inQuery) + { + mConjunctive = inQuery->Conjunctive; + mQueryFlags = inQuery->QueryFlags; + // XXX Do something with inQuery->QueryLimits? + uint32 aPredicatesCount = inQuery->NumSelectionPredicates; + mPredicates.resize(aPredicatesCount); + try + { + for (uint32 anIndex = 0; anIndex < aPredicatesCount; anIndex++) + { + CSSM_SELECTION_PREDICATE &aPredicate = inQuery->SelectionPredicate[anIndex]; + mPredicates[anIndex] = new SelectionPredicate(mMetaRecord, aPredicate); + } + } + catch(...) + { + for_each_delete(mPredicates.begin(), mPredicates.end()); + throw; + } + } +} + +LinearCursor::~LinearCursor() +{ + for_each_delete(mPredicates.begin(), mPredicates.end()); +} + +bool +LinearCursor::next(Table::Id &outTableId, + CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR inoutAttributes, + CssmData *inoutData, Allocator &inAllocator, RecordId &recordId) +{ + while (mRecord++ < mRecordsCount) + { + ReadSection aRecordSection = MetaRecord::readSection(mRecordsSection, mReadOffset); + uint32 aRecordSize = aRecordSection.size(); + mReadOffset += aRecordSize; + + PredicateVector::const_iterator anIt = mPredicates.begin(); + PredicateVector::const_iterator anEnd = mPredicates.end(); + bool aMatch; + if (anIt == anEnd) + { + // If there are no predicates we have a match. + aMatch = true; + } + else if (mConjunctive == CSSM_DB_OR) + { + // If mConjunctive is OR, the first predicate that returns + // true indicates a match. Dropthough means no match + aMatch = false; + for (; anIt != anEnd; anIt++) + { + if ((*anIt)->evaluate(aRecordSection)) + { + aMatch = true; + break; + } + } + } + else if (mConjunctive == CSSM_DB_AND || mConjunctive == CSSM_DB_NONE) + { + // If mConjunctive is AND (or NONE), the first predicate that returns + // false indicates a mismatch. Dropthough means a match + aMatch = true; + for (; anIt != anEnd; anIt++) + { + if (!(*anIt)->evaluate(aRecordSection)) + { + aMatch = false; + break; + } + } + } + else + { + // XXX Should be CSSMERR_DL_INVALID_QUERY (or CSSMERR_DL_INVALID_CONJUNTIVE). + CssmError::throwMe(CSSMERR_DL_UNSUPPORTED_QUERY); + } + + if (aMatch) + { + // Get the actual record. + mMetaRecord.unpackRecord(aRecordSection, inAllocator, + inoutAttributes, inoutData, + mQueryFlags); + outTableId = mMetaRecord.dataRecordType(); + recordId = MetaRecord::unpackRecordId(aRecordSection); + return true; + } + } + + return false; +} + +// +// IndexCursor +// + +IndexCursor::IndexCursor(DbQueryKey *queryKey, const DbVersion &inDbVersion, + const Table &table, const DbConstIndex *index) : + Cursor(inDbVersion), mQueryKey(queryKey), mTable(table), mIndex(index) +{ + index->performQuery(*queryKey, mBegin, mEnd); +} + +IndexCursor::~IndexCursor() +{ + // the query key will be deleted automatically, since it's an auto_ptr +} + +bool +IndexCursor::next(Table::Id &outTableId, + CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR outAttributes, + CssmData *outData, + Allocator &inAllocator, RecordId &recordId) +{ + 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; +} + +// +// MultiCursor +// +MultiCursor::MultiCursor(const CSSM_QUERY *inQuery, const DbVersion &inDbVersion) : + Cursor(inDbVersion), mTableIterator(inDbVersion.begin()) +{ + if (inQuery) + mQuery.reset(new CssmAutoQuery(*inQuery)); + else + { + mQuery.reset(new CssmAutoQuery()); + mQuery->recordType(CSSM_DL_DB_RECORD_ANY); + } +} + +MultiCursor::~MultiCursor() +{ +} + +bool +MultiCursor::next(Table::Id &outTableId, + CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR inoutAttributes, + CssmData *inoutData, Allocator &inAllocator, RecordId &recordId) +{ + for (;;) + { + if (!mCursor.get()) + { + if (mTableIterator == mDbVersion->end()) + return false; + + const Table &aTable = *mTableIterator++; + if (!aTable.matchesTableId(mQuery->recordType())) + continue; + + mCursor.reset(aTable.createCursor(mQuery.get(), *mDbVersion)); + } + + if (mCursor->next(outTableId, inoutAttributes, inoutData, inAllocator, recordId)) + return true; + + mCursor.reset(NULL); + } +} + + +// +// DbModifier +// +DbModifier::DbModifier(AtomicFile &inAtomicFile, const AppleDatabase &db) : + Metadata(), + mDbVersion(), + mAtomicFile(inAtomicFile), + mDb(db) +{ +} + +DbModifier::~DbModifier() +{ + try + { + for_each_map_delete(mModifiedTableMap.begin(), mModifiedTableMap.end()); + // mAtomicTempFile will do automatic rollback on destruction. + } + catch(...) {} +} + +const RefPointer +DbModifier::getDbVersion(bool force) +{ + StLock _(mDbVersionLock); + + /* Initialize the shared memory file change mechanism */ + pthread_once(&gCommonInitMutex, initCommon); + + /* If we don't have a mDbVersion yet, or we are force to re-read the file + before a write transaction, or we have received any notifications after + the last time we read the file, or more than kForceReReadTime seconds + have passed since the last time we read the file, we open the file and + check if it has changed. */ + if (!mDbVersion || + force || + gSegment == NULL || + mNotifyCount != *gSegment || + CFAbsoluteTimeGetCurrent() > mDbLastRead + kForceReReadTime) + { + RefPointer atomicBufferedFile(mAtomicFile.read()); + off_t length = atomicBufferedFile->open(); + /* Record the number of notifications we've seen and when we last + opened the file. */ + if (gSegment != NULL) + { + mNotifyCount = *gSegment; + } + + mDbLastRead = CFAbsoluteTimeGetCurrent(); + + /* If we already have a mDbVersion, let's check if we can reuse it. */ + if (mDbVersion) + { + if (length < AtomSize) + CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT); + + off_t bytesRead = 0; + const uint8 *ptr = atomicBufferedFile->read(length - AtomSize, + AtomSize, bytesRead); + ReadSection aVersionSection(ptr, bytesRead); + uint32 aVersionId = aVersionSection[0]; + + /* If the version stamp hasn't changed the old mDbVersion is still + current. */ + if (aVersionId == mDbVersion->getVersionId()) + return mDbVersion; + } + + mDbVersion = new DbVersion(mDb, atomicBufferedFile); + } + + return mDbVersion; +} + +void +DbModifier::createDatabase(const CSSM_DBINFO &inDbInfo, + const CSSM_ACL_ENTRY_INPUT *inInitialAclEntry, + mode_t mode) +{ + // XXX This needs better locking. There is a possible race condition between + // two concurrent creators. Or a writer/creator or a close/create etc. + if (mAtomicTempFile || !mModifiedTableMap.empty()) + CssmError::throwMe(CSSMERR_DL_DATASTORE_ALREADY_EXISTS); + + mAtomicTempFile = mAtomicFile.create(mode); + // Set mVersionId to one since this is the first version of the database. + mVersionId = 1; + + // we need to create the meta tables first, because inserting tables + // (including the meta tables themselves) relies on them being there + createTable(new MetaRecord(mDb.schemaRelations)); + 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); + insertTableSchema(mDb.schemaIndexes); + insertTableSchema(mDb.schemaParsingModule); + + if (inInitialAclEntry != NULL) + { + //createACL(*inInitialAclEntry); + } + + if (inDbInfo.NumberOfRecordTypes == 0) + return; + if (inDbInfo.RecordAttributeNames == NULL) + CssmError::throwMe(CSSMERR_DL_INVALID_RECORDTYPE); + if (inDbInfo.RecordIndexes == NULL) + CssmError::throwMe(CSSMERR_DL_INVALID_RECORD_INDEX); + if (inDbInfo.DefaultParsingModules == NULL) + CssmError::throwMe(CSSMERR_DL_INVALID_PARSING_MODULE); + + for (uint32 anIndex = 0; anIndex < inDbInfo.NumberOfRecordTypes; anIndex++) + { + insertTable(CssmDbRecordAttributeInfo::overlay(inDbInfo.RecordAttributeNames[anIndex]), + &inDbInfo.RecordIndexes[anIndex], + &inDbInfo.DefaultParsingModules[anIndex]); + } +} + +void DbModifier::openDatabase() +{ + // No need to do anything on open if we are already writing the database. + if (!mAtomicTempFile) + getDbVersion(false); +} + +void DbModifier::closeDatabase() +{ + commit(); // XXX Requires write lock. + StLock _(mDbVersionLock); + mDbVersion = NULL; +} + +void DbModifier::deleteDatabase() +{ + bool isDirty = mAtomicTempFile; + rollback(); // XXX Requires write lock. + StLock _(mDbVersionLock); + + // Clean up mModifiedTableMap in case this object gets reused again for + // a new create. + for_each_map_delete(mModifiedTableMap.begin(), mModifiedTableMap.end()); + mModifiedTableMap.clear(); + + // If the database was dirty and we had no mDbVersion yet then rollback() + // would have deleted the db. + if (!isDirty || mDbVersion) + { + mDbVersion = NULL; + mAtomicFile.performDelete(); + } +} + +void +DbModifier::modifyDatabase() +{ + if (mAtomicTempFile) + return; + + try + { + mAtomicTempFile = mAtomicFile.write(); + // Now we are holding the write lock make sure we get the latest greatest version of the db. + // Also set mVersionId to one more that that of the old database. + mVersionId = getDbVersion(true)->getVersionId() + 1; + + // Never make a database with mVersionId 0 since it makes bad things happen to Jaguar and older systems + if (mVersionId == 0) + mVersionId = 1; + + // Remove all old modified tables + for_each_map_delete(mModifiedTableMap.begin(), mModifiedTableMap.end()); + mModifiedTableMap.clear(); + + // Setup the new tables + DbVersion::TableMap::const_iterator anIt = + mDbVersion->mTableMap.begin(); + DbVersion::TableMap::const_iterator anEnd = + mDbVersion->mTableMap.end(); + for (; anIt != anEnd; ++anIt) + { + auto_ptr aTable(new ModifiedTable(anIt->second)); + mModifiedTableMap.insert(ModifiedTableMap::value_type(anIt->first, + aTable.get())); + aTable.release(); + } + } + catch(...) + { + for_each_map_delete(mModifiedTableMap.begin(), mModifiedTableMap.end()); + mModifiedTableMap.clear(); + rollback(); + throw; + } +} + +void +DbModifier::deleteRecord(Table::Id inTableId, const RecordId &inRecordId) +{ + modifyDatabase(); + findTable(inTableId).deleteRecord(inRecordId); +} + +const RecordId +DbModifier::insertRecord(Table::Id inTableId, + const CSSM_DB_RECORD_ATTRIBUTE_DATA *inAttributes, + const CssmData *inData) +{ + modifyDatabase(); + return findTable(inTableId).insertRecord(mVersionId, inAttributes, inData); +} + +const RecordId +DbModifier::updateRecord(Table::Id inTableId, const RecordId &inRecordId, + const CSSM_DB_RECORD_ATTRIBUTE_DATA *inAttributes, + const CssmData *inData, + CSSM_DB_MODIFY_MODE inModifyMode) +{ + modifyDatabase(); + return findTable(inTableId).updateRecord(inRecordId, inAttributes, inData, inModifyMode); +} + +// Create a table associated with a given metarecord, and add the table +// to the database. + +ModifiedTable * +DbModifier::createTable(MetaRecord *inMetaRecord) +{ + auto_ptr aMetaRecord(inMetaRecord); + auto_ptr aModifiedTable(new ModifiedTable(inMetaRecord)); + // Now that aModifiedTable is fully constructed it owns inMetaRecord + aMetaRecord.release(); + + if (!mModifiedTableMap.insert + (ModifiedTableMap::value_type(inMetaRecord->dataRecordType(), + aModifiedTable.get())).second) + { + // XXX Should be CSSMERR_DL_DUPLICATE_RECORDTYPE. Since that + // doesn't exist we report that the metatable's unique index would + // no longer be valid + CssmError::throwMe(CSSMERR_DL_INVALID_UNIQUE_INDEX_DATA); + } + + return aModifiedTable.release(); +} + +void +DbModifier::deleteTable(Table::Id inTableId) +{ + modifyDatabase(); + // Can't delete schema tables. + if (CSSM_DB_RECORDTYPE_SCHEMA_START <= inTableId + && inTableId < CSSM_DB_RECORDTYPE_SCHEMA_END) + CssmError::throwMe(CSSMERR_DL_INVALID_RECORDTYPE); + + // Find the ModifiedTable and delete it + ModifiedTableMap::iterator it = mModifiedTableMap.find(inTableId); + if (it == mModifiedTableMap.end()) + CssmError::throwMe(CSSMERR_DL_INVALID_RECORDTYPE); + + delete it->second; + mModifiedTableMap.erase(it); +} + +uint32 +DbModifier::writeAuthSection(uint32 inSectionOffset) +{ + WriteSection anAuthSection; + + // XXX Put real data into the authsection. + uint32 anOffset = anAuthSection.put(0, 0); + anAuthSection.size(anOffset); + + mAtomicTempFile->write(AtomicFile::FromStart, inSectionOffset, + anAuthSection.address(), anAuthSection.size()); + return inSectionOffset + anOffset; +} + +uint32 +DbModifier::writeSchemaSection(uint32 inSectionOffset) +{ + uint32 aTableCount = mModifiedTableMap.size(); + WriteSection aTableSection(Allocator::standard(), + OffsetTables + AtomSize * aTableCount); + // Set aTableSection to the correct size. + aTableSection.size(OffsetTables + AtomSize * aTableCount); + aTableSection.put(OffsetTablesCount, aTableCount); + + uint32 anOffset = inSectionOffset + OffsetTables + AtomSize * aTableCount; + ModifiedTableMap::const_iterator anIt = mModifiedTableMap.begin(); + ModifiedTableMap::const_iterator anEnd = mModifiedTableMap.end(); + for (uint32 aTableNumber = 0; anIt != anEnd; anIt++, aTableNumber++) + { + // Put the offset to the current table relative to the start of + // this section into the tables array + aTableSection.put(OffsetTables + AtomSize * aTableNumber, + anOffset - inSectionOffset); + anOffset = anIt->second->writeTable(*mAtomicTempFile, anOffset); + } + + aTableSection.put(OffsetSchemaSize, anOffset - inSectionOffset); + mAtomicTempFile->write(AtomicFile::FromStart, inSectionOffset, + aTableSection.address(), aTableSection.size()); + + return anOffset; +} + +void +DbModifier::commit() +{ + if (!mAtomicTempFile) + return; + try + { + WriteSection aHeaderSection(Allocator::standard(), size_t(HeaderSize)); + // Set aHeaderSection to the correct size. + aHeaderSection.size(HeaderSize); + + // Start writing sections after the header + uint32 anOffset = HeaderOffset + HeaderSize; + + // Write auth section + aHeaderSection.put(OffsetAuthOffset, anOffset); + anOffset = writeAuthSection(anOffset); + // Write schema section + aHeaderSection.put(OffsetSchemaOffset, anOffset); + anOffset = writeSchemaSection(anOffset); + + // Write out the file header. + aHeaderSection.put(OffsetMagic, HeaderMagic); + aHeaderSection.put(OffsetVersion, HeaderVersion); + mAtomicTempFile->write(AtomicFile::FromStart, HeaderOffset, + aHeaderSection.address(), aHeaderSection.size()); + + // Write out the versionId. + WriteSection aVersionSection(Allocator::standard(), size_t(AtomSize)); + anOffset = aVersionSection.put(0, mVersionId); + aVersionSection.size(anOffset); + + mAtomicTempFile->write(AtomicFile::FromEnd, 0, + aVersionSection.address(), aVersionSection.size()); + + mAtomicTempFile->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 + *gSegment, and there is no value for which alternating + big and little endian increments will produce the original value. + */ + + OSAtomicIncrement32Barrier (gSegment); + } + } + catch(...) + { + rollback(); + throw; + } +} + +void +DbModifier::rollback() throw() +{ + // This will destroy the AtomicTempFile if we have one causing it to rollback. + mAtomicTempFile = NULL; +} + +const RecordId +DbModifier::getRecord(Table::Id inTableId, const RecordId &inRecordId, + CSSM_DB_RECORD_ATTRIBUTE_DATA *inoutAttributes, + CssmData *inoutData, Allocator &inAllocator) +{ + if (mAtomicTempFile) + { + // We are in the midst of changing the database. + return findTable(inTableId).getRecord(inRecordId, inoutAttributes, + inoutData, inAllocator); + } + else + { + return getDbVersion(false)->getRecord(inTableId, inRecordId, + inoutAttributes, inoutData, inAllocator); + } +} + +Cursor * +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. + if (mDbVersion) + return mDbVersion->createCursor(inQuery); + + // This is a newly created but never commited database. Return a + // Cursor that will not return any matches. + return new Cursor(); + } + + // Get the latest and greatest version of the db and create the cursor + // on that. + return getDbVersion(false)->createCursor(inQuery); +} + +// Insert schema records for a new table into the metatables of the database. This gets +// called while a database is being created. + +void +DbModifier::insertTableSchema(const CssmDbRecordAttributeInfo &inInfo, + const CSSM_DB_RECORD_INDEX_INFO *inIndexInfo /* = NULL */) +{ + ModifiedTable &aTable = findTable(inInfo.DataRecordType); + const MetaRecord &aMetaRecord = aTable.getMetaRecord(); + + CssmAutoDbRecordAttributeData aRecordBuilder(5); // Set capacity to 5 so we don't need to grow + + // Create the entry for the SchemaRelations table. + aRecordBuilder.add(RelationID, inInfo.recordType()); + aRecordBuilder.add(RelationName, mDb.recordName(inInfo.recordType())); + + // 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++) + { + // Create an entry for the SchemaAttributes table. + aRecordBuilder.clear(); + aRecordBuilder.add(RelationID, inInfo.recordType()); + 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: + aRecordBuilder.add(AttributeName, inInfo.at(anIndex).Label.AttributeName); + break; + case CSSM_DB_ATTRIBUTE_NAME_AS_OID: + aRecordBuilder.add(AttributeNameID, inInfo.at(anIndex).Label.AttributeOID); + break; + case CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER: + break; + default: + CssmError::throwMe(CSSMERR_DL_INVALID_FIELD_NAME); + } + + aRecordBuilder.add(AttributeID, attributeId); + aRecordBuilder.add(AttributeFormat, inInfo.at(anIndex).format()); + + // Insert the record into the SchemaAttributes ModifiedTable + anAttributeTable.insertRecord(mVersionId, &aRecordBuilder, NULL); + } + + 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); + aRecordBuilder.add(IndexID, indexId); + aRecordBuilder.add(AttributeID, attributeId); + aRecordBuilder.add(IndexType, thisIndex.IndexType); + aRecordBuilder.add(IndexedDataLocation, thisIndex.IndexedDataLocation); + + // 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); + } + } +} + +// Insert a new table. The attribute info is required; the index and parsing module +// descriptions are optional. This version gets called during the creation of a +// database. + +void +DbModifier::insertTable(const CssmDbRecordAttributeInfo &inInfo, + const CSSM_DB_RECORD_INDEX_INFO *inIndexInfo /* = NULL */, + const CSSM_DB_PARSING_MODULE_INFO *inParsingModule /* = NULL */) +{ + modifyDatabase(); + createTable(new MetaRecord(inInfo)); + insertTableSchema(inInfo, inIndexInfo); +} + +// Insert a new table. This is the version that gets called when a table is added +// after a database has been created. + +void +DbModifier::insertTable(Table::Id inTableId, const string &inTableName, + uint32 inNumberOfAttributes, + const CSSM_DB_SCHEMA_ATTRIBUTE_INFO *inAttributeInfo, + uint32 inNumberOfIndexes, + const CSSM_DB_SCHEMA_INDEX_INFO *inIndexInfo) +{ + modifyDatabase(); + ModifiedTable *aTable = createTable(new MetaRecord(inTableId, inNumberOfAttributes, inAttributeInfo)); + + CssmAutoDbRecordAttributeData aRecordBuilder(6); // Set capacity to 6 so we don't need to grow + + // Create the entry for the SchemaRelations table. + aRecordBuilder.add(RelationID, inTableId); + aRecordBuilder.add(RelationName, inTableName); + + // 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 < inNumberOfAttributes; anIndex++) + { + // Create an entry for the SchemaAttributes table. + aRecordBuilder.clear(); + aRecordBuilder.add(RelationID, inTableId); + // XXX What should this be? We set it to CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER for now + // since the AttributeID is always valid. + aRecordBuilder.add(AttributeNameFormat, uint32(CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER)); + aRecordBuilder.add(AttributeID, inAttributeInfo[anIndex].AttributeId); + if (inAttributeInfo[anIndex].AttributeName) + aRecordBuilder.add(AttributeName, inAttributeInfo[anIndex].AttributeName); + if (inAttributeInfo[anIndex].AttributeNameID.Length > 0) + aRecordBuilder.add(AttributeNameID, inAttributeInfo[anIndex].AttributeNameID); + aRecordBuilder.add(AttributeFormat, inAttributeInfo[anIndex].DataType); + + // Insert the record into the SchemaAttributes ModifiedTable + anAttributeTable.insertRecord(mVersionId, &aRecordBuilder, NULL); + } + + ModifiedTable &anIndexTable = findTable(mDb.schemaIndexes.DataRecordType); + for (uint32 anIndex = 0; anIndex < inNumberOfIndexes; anIndex++) + { + // Create an entry for the SchemaIndexes table. + aRecordBuilder.clear(); + aRecordBuilder.add(RelationID, inTableId); + aRecordBuilder.add(IndexID, inIndexInfo[anIndex].IndexId); + aRecordBuilder.add(AttributeID, inIndexInfo[anIndex].AttributeId); + aRecordBuilder.add(IndexType, inIndexInfo[anIndex].IndexType); + aRecordBuilder.add(IndexedDataLocation, inIndexInfo[anIndex].IndexedDataLocation); + + // 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); + index.appendAttribute(inIndexInfo[anIndex].AttributeId); + } +} + + + +bool DbModifier::hasTable(Table::Id inTableId) +{ + return getDbVersion(false)->hasTable(inTableId); +} + + + +ModifiedTable & +DbModifier::findTable(Table::Id inTableId) +{ + ModifiedTableMap::iterator it = mModifiedTableMap.find(inTableId); + if (it == mModifiedTableMap.end()) + CssmError::throwMe(CSSMERR_DL_INVALID_RECORDTYPE); + return *it->second; +} + + +// +// AppleDatabaseManager implementation +// + +AppleDatabaseManager::AppleDatabaseManager(const AppleDatabaseTableName *tableNames) + : DatabaseManager(), + 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 { + uint32 i; + for (i = 0; mTableNames[i].mTableName; i++) {} + if (i < AppleDatabaseTableName::kNumRequiredTableNames) + CssmError::throwMe(CSSMERR_DL_INTERNAL_ERROR); + } +} + +Database * +AppleDatabaseManager::make(const DbName &inDbName) +{ + return new AppleDatabase(inDbName, mTableNames); +} + + +// +// AppleDbContext implementation +// + +/* This is the version 0 CSSM_APPLEDL_OPEN_PARAMETERS struct used up to 10.2.x. */ +extern "C" { + +typedef struct cssm_appledl_open_parameters_v0 +{ + uint32 length; /* Should be sizeof(CSSM_APPLEDL_OPEN_PARAMETERS_V0). */ + uint32 version; /* Should be 0. */ + CSSM_BOOL autoCommit; +} CSSM_APPLEDL_OPEN_PARAMETERS_V0; + +}; + +AppleDbContext::AppleDbContext(Database &inDatabase, + DatabaseSession &inDatabaseSession, + CSSM_DB_ACCESS_TYPE inAccessRequest, + const AccessCredentials *inAccessCred, + const void *inOpenParameters) : + DbContext(inDatabase, inDatabaseSession, inAccessRequest, inAccessCred), + mAutoCommit(true), + mMode(0666) +{ + const CSSM_APPLEDL_OPEN_PARAMETERS *anOpenParameters = + reinterpret_cast(inOpenParameters); + + if (anOpenParameters) + { + switch (anOpenParameters->version) + { + case 1: + if (anOpenParameters->length < sizeof(CSSM_APPLEDL_OPEN_PARAMETERS)) + CssmError::throwMe(CSSMERR_APPLEDL_INVALID_OPEN_PARAMETERS); + + if (anOpenParameters->mask & kCSSM_APPLEDL_MASK_MODE) + mMode = anOpenParameters->mode; + /*DROPTHROUGH*/ + case 0: + if (anOpenParameters->length < sizeof(CSSM_APPLEDL_OPEN_PARAMETERS_V0)) + CssmError::throwMe(CSSMERR_APPLEDL_INVALID_OPEN_PARAMETERS); + + mAutoCommit = anOpenParameters->autoCommit == CSSM_FALSE ? false : true; + break; + + default: + CssmError::throwMe(CSSMERR_APPLEDL_INVALID_OPEN_PARAMETERS); + } + } +} + +AppleDbContext::~AppleDbContext() +{ +} + +// +// AppleDatabase implementation +// +AppleDatabase::AppleDatabase(const DbName &inDbName, const AppleDatabaseTableName *tableNames) : + Database(inDbName), + schemaRelations(tableNames[AppleDatabaseTableName::kSchemaInfo].mTableId, + sizeof(AttrSchemaRelations) / sizeof(CSSM_DB_ATTRIBUTE_INFO), + const_cast(AttrSchemaRelations)), + schemaAttributes(tableNames[AppleDatabaseTableName::kSchemaAttributes].mTableId, + sizeof(AttrSchemaAttributes) / sizeof(CSSM_DB_ATTRIBUTE_INFO), + const_cast(AttrSchemaAttributes)), + schemaIndexes(tableNames[AppleDatabaseTableName::kSchemaIndexes].mTableId, + sizeof(AttrSchemaIndexes) / sizeof(CSSM_DB_ATTRIBUTE_INFO), + const_cast(AttrSchemaIndexes)), + schemaParsingModule(tableNames[AppleDatabaseTableName::kSchemaParsingModule].mTableId, + sizeof(AttrSchemaParsingModule) / sizeof(CSSM_DB_ATTRIBUTE_INFO), + const_cast(AttrSchemaParsingModule)), + mAtomicFile(mDbName.dbName()), + mDbModifier(mAtomicFile, *this), + mTableNames(tableNames) +{ + /* temp check for X509Anchors access - this should removed before Leopard GM */ + if(!strcmp(inDbName.dbName(), "/System/Library/Keychains/X509Anchors")) { + Syslog::alert("Warning: accessing obsolete X509Anchors."); + } +} + +AppleDatabase::~AppleDatabase() +{ +} + +// Return the name of a record type. This uses a table that maps record types +// to record names. The table is provided when the database is created. + +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 ""; +} + +DbContext * +AppleDatabase::makeDbContext(DatabaseSession &inDatabaseSession, + CSSM_DB_ACCESS_TYPE inAccessRequest, + const AccessCredentials *inAccessCred, + const void *inOpenParameters) +{ + return new AppleDbContext(*this, inDatabaseSession, inAccessRequest, + inAccessCred, inOpenParameters); +} + +void +AppleDatabase::dbCreate(DbContext &inDbContext, const CSSM_DBINFO &inDBInfo, + const CSSM_ACL_ENTRY_INPUT *inInitialAclEntry) +{ + AppleDbContext &context = safer_cast(inDbContext); + try + { + StLock _(mWriteLock); + mDbModifier.createDatabase(inDBInfo, inInitialAclEntry, context.mode()); + } + catch(...) + { + mDbModifier.rollback(); + throw; + } + if (context.autoCommit()) + mDbModifier.commit(); +} + +void +AppleDatabase::dbOpen(DbContext &inDbContext) +{ + mDbModifier.openDatabase(); +} + +void +AppleDatabase::dbClose() +{ + StLock _(mWriteLock); + mDbModifier.closeDatabase(); +} + +void +AppleDatabase::dbDelete(DatabaseSession &inDatabaseSession, + const AccessCredentials *inAccessCred) +{ + StLock _(mWriteLock); + // XXX Check callers credentials. + mDbModifier.deleteDatabase(); +} + +void +AppleDatabase::createRelation(DbContext &inDbContext, + CSSM_DB_RECORDTYPE inRelationID, + const char *inRelationName, + uint32 inNumberOfAttributes, + const CSSM_DB_SCHEMA_ATTRIBUTE_INFO *inAttributeInfo, + uint32 inNumberOfIndexes, + const CSSM_DB_SCHEMA_INDEX_INFO &inIndexInfo) +{ + try + { + StLock _(mWriteLock); + // XXX Fix the refs here. + mDbModifier.insertTable(inRelationID, inRelationName, + inNumberOfAttributes, inAttributeInfo, + inNumberOfIndexes, &inIndexInfo); + } + catch(...) + { + if (safer_cast(inDbContext).autoCommit()) + mDbModifier.rollback(); + throw; + } + if (safer_cast(inDbContext).autoCommit()) + mDbModifier.commit(); +} + +void +AppleDatabase::destroyRelation(DbContext &inDbContext, + CSSM_DB_RECORDTYPE inRelationID) +{ + try + { + StLock _(mWriteLock); + mDbModifier.deleteTable(inRelationID); + } + catch(...) + { + if (safer_cast(inDbContext).autoCommit()) + mDbModifier.rollback(); + throw; + } + if (safer_cast(inDbContext).autoCommit()) + mDbModifier.commit(); +} + +void +AppleDatabase::authenticate(DbContext &inDbContext, + CSSM_DB_ACCESS_TYPE inAccessRequest, + const AccessCredentials &inAccessCred) +{ + CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); +} + +void +AppleDatabase::getDbAcl(DbContext &inDbContext, + const CSSM_STRING *inSelectionTag, + uint32 &outNumberOfAclInfos, + CSSM_ACL_ENTRY_INFO_PTR &outAclInfos) +{ + CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); +} + +void +AppleDatabase::changeDbAcl(DbContext &inDbContext, + const AccessCredentials &inAccessCred, + const CSSM_ACL_EDIT &inAclEdit) +{ + CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); +} + +void +AppleDatabase::getDbOwner(DbContext &inDbContext, + CSSM_ACL_OWNER_PROTOTYPE &outOwner) +{ + CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); +} + +void +AppleDatabase::changeDbOwner(DbContext &inDbContext, + const AccessCredentials &inAccessCred, + const CSSM_ACL_OWNER_PROTOTYPE &inNewOwner) +{ + CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); +} + +char * +AppleDatabase::getDbNameFromHandle(const DbContext &inDbContext) const +{ + CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); +} + +CSSM_DB_UNIQUE_RECORD_PTR +AppleDatabase::dataInsert(DbContext &inDbContext, + CSSM_DB_RECORDTYPE inRecordType, + const CSSM_DB_RECORD_ATTRIBUTE_DATA *inAttributes, + const CssmData *inData) +{ + CSSM_DB_UNIQUE_RECORD_PTR anUniqueRecordPtr = NULL; + try + { + StLock _(mWriteLock); + const RecordId aRecordId = + mDbModifier.insertRecord(inRecordType, inAttributes, inData); + + anUniqueRecordPtr = createUniqueRecord(inDbContext, inRecordType, + aRecordId); + if (safer_cast(inDbContext).autoCommit()) + mDbModifier.commit(); + } + catch(...) + { + if (anUniqueRecordPtr != NULL) + freeUniqueRecord(inDbContext, *anUniqueRecordPtr); + + if (safer_cast(inDbContext).autoCommit()) + mDbModifier.rollback(); + throw; + } + + return anUniqueRecordPtr; +} + +void +AppleDatabase::dataDelete(DbContext &inDbContext, + const CSSM_DB_UNIQUE_RECORD &inUniqueRecord) +{ + try + { + // syslog if it's the .Mac password + CSSM_DB_RECORD_ATTRIBUTE_DATA attrData; + // we have to do this in two phases -- the first to get the record type, and the second to actually read the attributes. Otherwise, we might get + // 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'; + attributes.Info.AttributeFormat = 0; + attributes.NumberOfValues = 1; + attributes.Value = NULL; + + attrData.NumberOfAttributes = 1; + 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)); + mDbModifier.deleteRecord(aTableId, aRecordId); + } + catch(...) + { + if (safer_cast(inDbContext).autoCommit()) + mDbModifier.rollback(); + throw; + } + + if (safer_cast(inDbContext).autoCommit()) + mDbModifier.commit(); +} + +void +AppleDatabase::dataModify(DbContext &inDbContext, + CSSM_DB_RECORDTYPE inRecordType, + CSSM_DB_UNIQUE_RECORD &inoutUniqueRecord, + const CSSM_DB_RECORD_ATTRIBUTE_DATA *inAttributesToBeModified, + const CssmData *inDataToBeModified, + CSSM_DB_MODIFY_MODE inModifyMode) +{ + try + { + StLock _(mWriteLock); + Table::Id aTableId; + const RecordId oldRecordId = parseUniqueRecord(inoutUniqueRecord, + aTableId); +#if 1 + if (inRecordType != aTableId) +#else + if (inRecordType != aTableId && + inRecordType != CSSM_DL_DB_RECORD_ANY && + !(inRecordType == CSSM_DL_DB_RECORD_ALL_KEYS && + (aTableId == CSSM_DL_DB_RECORD_PUBLIC_KEY || + aTableId == CSSM_DL_DB_RECORD_PRIVATE_KEY || + aTableId == CSSM_DL_DB_RECORD_SYMMETRIC_KEY))) +#endif + { + CssmError::throwMe(CSSMERR_DL_INVALID_RECORD_UID); + } + + const RecordId newRecordId = + mDbModifier.updateRecord(aTableId, + oldRecordId, + inAttributesToBeModified, + inDataToBeModified, + inModifyMode); + updateUniqueRecord(inDbContext, aTableId, newRecordId, + inoutUniqueRecord); + } + catch(...) + { + if (safer_cast(inDbContext).autoCommit()) + mDbModifier.rollback(); + throw; + } + + if (safer_cast(inDbContext).autoCommit()) + mDbModifier.commit(); +} + +CSSM_HANDLE +AppleDatabase::dataGetFirst(DbContext &inDbContext, + const CssmQuery *inQuery, + CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR inoutAttributes, + CssmData *inoutData, + CSSM_DB_UNIQUE_RECORD_PTR &outUniqueRecord) +{ + // XXX: register Cursor with DbContext and have DbContext call + // dataAbortQuery for all outstanding Query objects on close. + 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 + return CSSM_INVALID_HANDLE; + + outUniqueRecord = createUniqueRecord(inDbContext, aTableId, aRecordId); + return aCursor.release()->handle(); // We didn't throw so keep the Cursor around. +} + +bool +AppleDatabase::dataGetNext(DbContext &inDbContext, + CSSM_HANDLE inResultsHandle, + CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR inoutAttributes, + CssmData *inoutData, + CSSM_DB_UNIQUE_RECORD_PTR &outUniqueRecord) +{ + 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; + + outUniqueRecord = createUniqueRecord(inDbContext, aTableId, aRecordId); + + aCursor.release(); + return true; +} + +void +AppleDatabase::dataAbortQuery(DbContext &inDbContext, + CSSM_HANDLE inResultsHandle) +{ + delete &HandleObject::find(inResultsHandle, CSSMERR_DL_INVALID_RESULTS_HANDLE); +} + +void +AppleDatabase::dataGetFromUniqueRecordId(DbContext &inDbContext, + const CSSM_DB_UNIQUE_RECORD &inUniqueRecord, + CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR inoutAttributes, + CssmData *inoutData) +{ + Table::Id aTableId; + const RecordId aRecordId(parseUniqueRecord(inUniqueRecord, aTableId)); + // XXX Change CDSA spec to use new RecordId returned by this function + mDbModifier.getRecord(aTableId, aRecordId, inoutAttributes, inoutData, + inDbContext.mDatabaseSession); +} + +void +AppleDatabase::freeUniqueRecord(DbContext &inDbContext, + CSSM_DB_UNIQUE_RECORD &inUniqueRecord) +{ + if (inUniqueRecord.RecordIdentifier.Length != 0 + && inUniqueRecord.RecordIdentifier.Data != NULL) + { + inUniqueRecord.RecordIdentifier.Length = 0; + inDbContext.mDatabaseSession.free(inUniqueRecord.RecordIdentifier.Data); + } + inDbContext.mDatabaseSession.free(&inUniqueRecord); +} + +void +AppleDatabase::updateUniqueRecord(DbContext &inDbContext, + CSSM_DB_RECORDTYPE inTableId, + const RecordId &inRecordId, + CSSM_DB_UNIQUE_RECORD &inoutUniqueRecord) +{ + uint32 *aBuffer = reinterpret_cast(inoutUniqueRecord.RecordIdentifier.Data); + aBuffer[0] = inTableId; + aBuffer[1] = inRecordId.mRecordNumber; + aBuffer[2] = inRecordId.mCreateVersion; + aBuffer[3] = inRecordId.mRecordVersion; +} + +CSSM_DB_UNIQUE_RECORD_PTR +AppleDatabase::createUniqueRecord(DbContext &inDbContext, + CSSM_DB_RECORDTYPE inTableId, + const RecordId &inRecordId) +{ + CSSM_DB_UNIQUE_RECORD_PTR aUniqueRecord = + inDbContext.mDatabaseSession.alloc(); + memset(aUniqueRecord, 0, sizeof(*aUniqueRecord)); + aUniqueRecord->RecordIdentifier.Length = sizeof(uint32) * 4; + try + { + aUniqueRecord->RecordIdentifier.Data = + inDbContext.mDatabaseSession.alloc(sizeof(uint32) * 4); + updateUniqueRecord(inDbContext, inTableId, inRecordId, *aUniqueRecord); + } + catch(...) + { + inDbContext.mDatabaseSession.free(aUniqueRecord); + throw; + } + + return aUniqueRecord; +} + +const RecordId +AppleDatabase::parseUniqueRecord(const CSSM_DB_UNIQUE_RECORD &inUniqueRecord, + CSSM_DB_RECORDTYPE &outTableId) +{ + if (inUniqueRecord.RecordIdentifier.Length != sizeof(uint32) * 4) + CssmError::throwMe(CSSMERR_DL_INVALID_RECORD_UID); + + uint32 *aBuffer = reinterpret_cast(inUniqueRecord.RecordIdentifier.Data); + outTableId = aBuffer[0]; + return RecordId(aBuffer[1], aBuffer[2], aBuffer[3]); +} + +void +AppleDatabase::passThrough(DbContext &dbContext, + uint32 passThroughId, + const void *inputParams, + void **outputParams) +{ + switch (passThroughId) + { + case CSSM_APPLEFILEDL_TOGGLE_AUTOCOMMIT: + { + AppleDbContext &dbc = safer_cast(dbContext); + // Return the old state of the autoCommit flag if requested + if (outputParams) + *reinterpret_cast(outputParams) = dbc.autoCommit(); + dbc.autoCommit(inputParams ? CSSM_TRUE : CSSM_FALSE); + } + break; + + case CSSM_APPLEFILEDL_COMMIT: + mDbModifier.commit(); + break; + + case CSSM_APPLEFILEDL_ROLLBACK: + mDbModifier.rollback(); + break; + + 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) + { + returnValue = CSSM_TRUE; + } + else + { + returnValue = mDbModifier.hasTable(recordType); + } + + *(CSSM_BOOL*) outputParams = returnValue; + break; + } + + default: + CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); + break; + } +} diff --git a/libsecurity_filedb/lib/AppleDatabase.h b/libsecurity_filedb/lib/AppleDatabase.h new file mode 100644 index 00000000..738b9126 --- /dev/null +++ b/libsecurity_filedb/lib/AppleDatabase.h @@ -0,0 +1,666 @@ +/* + * Copyright (c) 2000-2001, 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. + */ + + +// +// AppleDatabase.h - Description t.b.d. +// +#ifndef _H_APPLEDATABASE +#define _H_APPLEDATABASE + +#include "MetaRecord.h" +#include "SelectionPredicate.h" +#include "DbIndex.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Security +{ + +// Abstract database Cursor class. +class Cursor; +class DbVersion; +class CssmAutoQuery; + +struct AppleDatabaseTableName +{ + uint32 mTableId; + const char *mTableName; + + // indices of meta-table entries in an array of table names + + enum { + kSchemaInfo = 0, + kSchemaAttributes, + kSchemaIndexes, + kSchemaParsingModule, + kNumRequiredTableNames + }; +}; + +// +// This is what the CDSA standard refers to as a Relation. We use +// the more conventional term Table. +// +class Table +{ + NOCOPY(Table) +public: + // Type used to refer to a table. + typedef CSSM_DB_RECORDTYPE Id; + + Table(const ReadSection &inTableSection); + ~Table(); + + // Return a newly created cursor satisfying inQuery on the receiving table + // The returned Cursor may or may not use indexes depending on their availability. + Cursor *createCursor(const CSSM_QUERY *inQuery, const DbVersion &inDbVersion) const; + + const ReadSection getRecordSection(uint32 inRecordNumber) const; + + const RecordId getRecord(const RecordId &inRecordId, + CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR inoutAttributes, + CssmData *inoutData, + Allocator &inAllocator) const; + + // Return the number of recordNumbers in use by this table including empty slots. + uint32 recordNumberCount() const { return mRecordNumbersCount; } + uint32 freeListHead() const { return mFreeListHead; } + + // Return the record number corresponding to aFreeListHead and update + // aFreeListHead to point to the next availble recordNumber slot. + uint32 popFreeList(uint32 &aFreeListHead) const; + + MetaRecord &getMetaRecord() { return mMetaRecord; } + const MetaRecord &getMetaRecord() const { return mMetaRecord; } + + uint32 getRecordsCount() const { return mRecordsCount; } + const ReadSection getRecordsSection() const; + + const ReadSection &getTableSection() const { return mTableSection; } + + bool matchesTableId(Id inTableId) const; + + void readIndexSection(); + + enum + { + OffsetSize = AtomSize * 0, + OffsetId = AtomSize * 1, + OffsetRecordsCount = AtomSize * 2, + OffsetRecords = AtomSize * 3, + OffsetIndexesOffset = AtomSize * 4, + OffsetFreeListHead = AtomSize * 5, + OffsetRecordNumbersCount = AtomSize * 6, + OffsetRecordNumbers = AtomSize * 7 + }; +protected: + friend class ModifiedTable; + + MetaRecord mMetaRecord; + const ReadSection mTableSection; + + uint32 mRecordsCount; + uint32 mFreeListHead; + // Number of record numbers (including freelist slots) in this table. + uint32 mRecordNumbersCount; + + // all the table's indexes, mapped by index id + typedef map ConstIndexMap; + ConstIndexMap mIndexMap; +}; + +class ModifiedTable +{ + NOCOPY(ModifiedTable) +public: + ModifiedTable(const Table *inTable); + ModifiedTable(MetaRecord *inMetaRecord); // Take over ownership of inMetaRecord + ~ModifiedTable(); + + // Mark the record with inRecordId as deleted. + void deleteRecord(const RecordId &inRecordId); + const RecordId insertRecord(uint32 inVersionId, + const CSSM_DB_RECORD_ATTRIBUTE_DATA *inAttributes, + const CssmData *inData); + const RecordId updateRecord(const RecordId &inRecordId, + const CSSM_DB_RECORD_ATTRIBUTE_DATA *inAttributes, + const CssmData *inData, + CSSM_DB_MODIFY_MODE inModifyMode); + const RecordId getRecord(const RecordId &inRecordId, + CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR inoutAttributes, + CssmData *inoutData, + Allocator &inAllocator) const; + + // Return the MetaRecord this table should use for writes. + const MetaRecord &getMetaRecord() const; + + // find, and create if needed, an index with the given id + DbMutableIndex &findIndex(uint32 indexId, const MetaRecord &metaRecord, bool isUniqueIndex); + + // Write this table to inOutputFile at inSectionOffset and return the new offset. + uint32 writeTable(AtomicTempFile &inAtomicTempFile, uint32 inSectionOffset); + +private: + // Return the next available record number for this table. + uint32 nextRecordNumber(); + + // Return the number of recordNumbers in use by this table including empty slots. + uint32 recordNumberCount() const; + + void modifyTable(); + void createMutableIndexes(); + uint32 writeIndexSection(WriteSection &tableSection, uint32 offset); + + // Optional, this is merly a reference, we do not own this object. + const Table *mTable; + + // Optional, New MetaRecord. This is only present if it is different from the + // MetaRecord of mTable or mTable is nil. + const MetaRecord *mNewMetaRecord; + + // Set of Records that have been deleted or modified. + typedef set DeletedSet; + DeletedSet mDeletedSet; + + // Set of Records that have been inserted or modified. + typedef map InsertedMap; + InsertedMap mInsertedMap; + + // Next lowest available RecordNumber + uint32 mRecordNumberCount; + // Head of the free list (if there is one) or 0 if either we have no + // mTable of the free list has been exhausted. + uint32 mFreeListHead; + + // has this table actually been modified? + bool mIsModified; + + typedef map MutableIndexMap; + MutableIndexMap mIndexMap; +}; + +// +// Read only snapshot of a database. +// +class Metadata +{ + NOCOPY(Metadata) +protected: + Metadata() {} + enum + { + HeaderOffset = 0, // Absolute offset of header. + OffsetMagic = AtomSize * 0, + OffsetVersion = AtomSize * 1, + OffsetAuthOffset = AtomSize * 2, + OffsetSchemaOffset = AtomSize * 3, + HeaderSize = AtomSize * 4, + + HeaderMagic = FOUR_CHAR_CODE('kych'), + HeaderVersion = 0x00010000 + }; + + enum + { + OffsetSchemaSize = AtomSize * 0, + OffsetTablesCount = AtomSize * 1, + OffsetTables = AtomSize * 2 + }; +}; + +// +// Read only representation of a database +// +class DbVersion : public Metadata, public RefCount +{ + NOCOPY(DbVersion) +public: + DbVersion(const class AppleDatabase &db, const RefPointer &inAtomicBufferedFile); + ~DbVersion(); + + uint32 getVersionId() const { return mVersionId; } + const RecordId getRecord(Table::Id inTableId, const RecordId &inRecordId, + CSSM_DB_RECORD_ATTRIBUTE_DATA *inoutAttributes, + CssmData *inoutData, Allocator &inAllocator) const; + Cursor *createCursor(const CSSM_QUERY *inQuery) const; +protected: + const Table &findTable(Table::Id inTableId) const; + Table &findTable(Table::Id inTableId); + +private: + void open(); // Part of constructor contract. + + ReadSection mDatabase; + uint32 mVersionId; + + friend class DbModifier; // XXX Fixme + typedef map TableMap; + TableMap mTableMap; + const class AppleDatabase &mDb; + RefPointer mBufferedFile; + +public: + typedef Table value_type; + typedef const Table &const_reference; + typedef const Table *const_pointer; + + // A const forward iterator. + class const_iterator + { + public: + const_iterator(const TableMap::const_iterator &it) : mIterator(it) {} + + // Use default copy consturctor and assignment operator. + //const_iterator(const const_iterator &it) : mIterator(it.mIterator) {} + //const_iterator &operator=(const const_iterator &it) { mIterator = it.mIterator; return *this; } + const_reference operator*() const { return *mIterator->second; } + const_iterator &operator++() { mIterator.operator++(); return *this; } + const_iterator operator++(int i) { return const_iterator(mIterator.operator++(i)); } + bool operator!=(const const_iterator &other) const { return mIterator != other.mIterator; } + bool operator==(const const_iterator &other) const { return mIterator == other.mIterator; } + + const_pointer operator->() const { return mIterator->second; } // Not really needed. + + private: + TableMap::const_iterator mIterator; + }; + + const_iterator begin() const { return const_iterator(mTableMap.begin()); } + const_iterator end() const { return const_iterator(mTableMap.end()); } + + bool hasTable(Table::Id inTableId) const; +}; + +// +// Cursor +// +class Cursor : public HandleObject +{ +public: + Cursor(); + Cursor(const DbVersion &inDbVersion); + virtual ~Cursor(); + virtual bool next(Table::Id &outTableId, + CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR outAttributes, + CssmData *outData, + Allocator &inAllocator, + RecordId &recordId); +protected: + const RefPointer mDbVersion; +}; + + +// +// LinearCursor +// +class LinearCursor : public Cursor +{ + NOCOPY(LinearCursor) +public: + LinearCursor(const CSSM_QUERY *inQuery, const DbVersion &inDbVersion, + const Table &inTable); + virtual ~LinearCursor(); + virtual bool next(Table::Id &outTableId, + CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR outAttributes, + CssmData *outData, + Allocator &inAllocator, + RecordId &recordId); + +private: + uint32 mRecordsCount; + uint32 mRecord; + const ReadSection mRecordsSection; + uint32 mReadOffset; + const MetaRecord &mMetaRecord; + + CSSM_DB_CONJUNCTIVE mConjunctive; + CSSM_QUERY_FLAGS mQueryFlags; // If CSSM_QUERY_RETURN_DATA is set return the raw key bits; + typedef vector PredicateVector; + + PredicateVector mPredicates; +}; + +// +// A cursor that uses an index. +// + +class IndexCursor : public Cursor +{ + NOCOPY(IndexCursor) +public: + IndexCursor(DbQueryKey *queryKey, const DbVersion &inDbVersion, + const Table &table, const DbConstIndex *index); + virtual ~IndexCursor(); + + virtual bool next(Table::Id &outTableId, + CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR outAttributes, + CssmData *outData, + Allocator &inAllocator, + RecordId &recordId); + +private: + auto_ptr mQueryKey; + const Table &mTable; + const DbConstIndex *mIndex; + + DbIndexIterator mBegin, mEnd; +}; + +// +// MultiCursor +// +class MultiCursor : public Cursor +{ + NOCOPY(MultiCursor) +public: + MultiCursor(const CSSM_QUERY *inQuery, const DbVersion &inDbVersion); + virtual ~MultiCursor(); + virtual bool next(Table::Id &outTableId, + CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR outAttributes, + CssmData *outData, + Allocator &inAllocator, + RecordId &recordId); +private: + auto_ptr mQuery; + + DbVersion::const_iterator mTableIterator; + auto_ptr mCursor; +}; + +// +// A DbModifier contains all pending changes to be made to a DB. +// It also contains a DbVersion representing the state of the Database before any such changes +// No read-style operations are supported by DbModifier. If a DbModifier exists for a +// particular Database and a client wishes to perform a query commit() must be called and +// the client should perform the new query on the current database version after the commit. +// Otherwise a client will not see changes made since the DbModifier was instanciated. +// +class DbModifier : public Metadata +{ + NOCOPY(DbModifier) +public: + DbModifier(AtomicFile &inAtomicFile, const class AppleDatabase &db); + ~DbModifier(); + + // Whole database affecting members. + void createDatabase(const CSSM_DBINFO &inDbInfo, + const CSSM_ACL_ENTRY_INPUT *inInitialAclEntry, + mode_t mode); + void openDatabase(); // This is optional right now. + void closeDatabase(); + void deleteDatabase(); + + void commit(); + void rollback() throw(); + + // Record changing members + void deleteRecord(Table::Id inTableId, const RecordId &inRecordId); + const RecordId insertRecord(Table::Id inTableId, + const CSSM_DB_RECORD_ATTRIBUTE_DATA *inAttributes, + const CssmData *inData); + const RecordId updateRecord(Table::Id inTableId, const RecordId &inRecordId, + const CSSM_DB_RECORD_ATTRIBUTE_DATA *inAttributes, + const CssmData *inData, + CSSM_DB_MODIFY_MODE inModifyMode); + + // Schema changing members + void insertTable(Table::Id inTableId, const string &inTableName, + uint32 inNumberOfAttributes, + const CSSM_DB_SCHEMA_ATTRIBUTE_INFO *inAttributeInfo, + uint32 inNumberOfIndexes, + const CSSM_DB_SCHEMA_INDEX_INFO *inIndexInfo); + void deleteTable(Table::Id inTableId); + + // Record reading members + const RecordId getRecord(Table::Id inTableId, const RecordId &inRecordId, + CSSM_DB_RECORD_ATTRIBUTE_DATA *inoutAttributes, + CssmData *inoutData, Allocator &inAllocator); + Cursor *createCursor(const CSSM_QUERY *inQuery); + + bool hasTable(Table::Id inTableid); + +protected: + void modifyDatabase(); + const RefPointer getDbVersion(bool force); + + ModifiedTable *createTable(MetaRecord *inMetaRecord); // Takes over ownership of inMetaRecord + + void insertTableSchema(const CssmDbRecordAttributeInfo &inInfo, + const CSSM_DB_RECORD_INDEX_INFO *inIndexInfo = NULL); + + void insertTable(const CssmDbRecordAttributeInfo &inInfo, + const CSSM_DB_RECORD_INDEX_INFO * inIndexInfo = NULL, + const CSSM_DB_PARSING_MODULE_INFO * inParsingModule = NULL); + + ModifiedTable &findTable(Table::Id inTableId); + + uint32 writeAuthSection(uint32 inSectionOffset); + uint32 writeSchemaSection(uint32 inSectionOffset); + +private: + + /* mDbVersion is the current DbVersion of this database before any changes + we are going to make. mNotifyCount holds the value of gNotifyCount at + the time mDbVersion was created. mDbLastRead is the time at which we + last checked if the file from which mDbVersion was read has changed. + mDbVersionLock protects the other 3 fields. */ + RefPointer mDbVersion; + int32_t mNotifyCount; + CFAbsoluteTime mDbLastRead; + Mutex mDbVersionLock; + + AtomicFile &mAtomicFile; + uint32 mVersionId; + RefPointer mAtomicTempFile; + + typedef map ModifiedTableMap; + ModifiedTableMap mModifiedTableMap; + + const class AppleDatabase &mDb; +}; + +// +// AppleDatabaseManager +// +class AppleDatabaseManager : public DatabaseManager +{ +public: + AppleDatabaseManager(const AppleDatabaseTableName *tableNames); + Database *make(const DbName &inDbName); + +protected: + const AppleDatabaseTableName *mTableNames; +}; + +// +// AppleDbContext +// +class AppleDbContext : public DbContext +{ +public: + AppleDbContext(Database &inDatabase, + DatabaseSession &inDatabaseSession, + CSSM_DB_ACCESS_TYPE inAccessRequest, + const AccessCredentials *inAccessCred, + const void *inOpenParameters); + virtual ~AppleDbContext(); + bool autoCommit() const { return mAutoCommit; } + void autoCommit(bool on) { mAutoCommit = on; } + mode_t mode() const { return mMode; } + +private: + bool mAutoCommit; + mode_t mMode; +}; + +// +// AppleDatabase +// +class AppleDatabase : public Database +{ +public: + AppleDatabase(const DbName &inDbName, const AppleDatabaseTableName *tableNames); + virtual ~AppleDatabase(); + + virtual void + dbCreate(DbContext &inDbContext, const CSSM_DBINFO &inDBInfo, + const CSSM_ACL_ENTRY_INPUT *inInitialAclEntry); + + virtual void + dbOpen(DbContext &inDbContext); + + virtual void + dbClose(); + + virtual void + dbDelete(DatabaseSession &inDatabaseSession, + const AccessCredentials *inAccessCred); + + virtual void + createRelation(DbContext &inDbContext, + CSSM_DB_RECORDTYPE inRelationID, + const char *inRelationName, + uint32 inNumberOfAttributes, + const CSSM_DB_SCHEMA_ATTRIBUTE_INFO *inAttributeInfo, + uint32 inNumberOfIndexes, + const CSSM_DB_SCHEMA_INDEX_INFO &inIndexInfo); + + virtual void + destroyRelation(DbContext &inDbContext, + CSSM_DB_RECORDTYPE inRelationID); + + virtual void + authenticate(DbContext &inDbContext, + CSSM_DB_ACCESS_TYPE inAccessRequest, + const AccessCredentials &inAccessCred); + + virtual void + getDbAcl(DbContext &inDbContext, + const CSSM_STRING *inSelectionTag, + uint32 &outNumberOfAclInfos, + CSSM_ACL_ENTRY_INFO_PTR &outAclInfos); + + virtual void + changeDbAcl(DbContext &inDbContext, + const AccessCredentials &inAccessCred, + const CSSM_ACL_EDIT &inAclEdit); + + virtual void + getDbOwner(DbContext &inDbContext, CSSM_ACL_OWNER_PROTOTYPE &outOwner); + + virtual void + changeDbOwner(DbContext &inDbContext, + const AccessCredentials &inAccessCred, + const CSSM_ACL_OWNER_PROTOTYPE &inNewOwner); + + virtual char * + getDbNameFromHandle(const DbContext &inDbContext) const; + + virtual CSSM_DB_UNIQUE_RECORD_PTR + dataInsert(DbContext &inDbContext, + CSSM_DB_RECORDTYPE RecordType, + const CSSM_DB_RECORD_ATTRIBUTE_DATA *inAttributes, + const CssmData *inData); + + virtual void + dataDelete(DbContext &inDbContext, + const CSSM_DB_UNIQUE_RECORD &inUniqueRecordIdentifier); + + virtual void + dataModify(DbContext &inDbContext, + CSSM_DB_RECORDTYPE inRecordType, + CSSM_DB_UNIQUE_RECORD &inoutUniqueRecordIdentifier, + const CSSM_DB_RECORD_ATTRIBUTE_DATA *inAttributesToBeModified, + const CssmData *inDataToBeModified, + CSSM_DB_MODIFY_MODE inModifyMode); + + virtual CSSM_HANDLE + dataGetFirst(DbContext &inDbContext, + const CssmQuery *inQuery, + CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR inoutAttributes, + CssmData *inoutData, + CSSM_DB_UNIQUE_RECORD_PTR &outUniqueRecord); + + virtual bool + dataGetNext(DbContext &inDbContext, + CSSM_HANDLE inResultsHandle, + CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR inoutAttributes, + CssmData *inoutData, + CSSM_DB_UNIQUE_RECORD_PTR &outUniqueRecord); + + virtual void + dataAbortQuery(DbContext &inDbContext, + CSSM_HANDLE inResultsHandle); + + virtual void + dataGetFromUniqueRecordId(DbContext &inDbContext, + const CSSM_DB_UNIQUE_RECORD &inUniqueRecord, + CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR inoutAttributes, + CssmData *inoutData); + + virtual void + freeUniqueRecord(DbContext &inDbContext, + CSSM_DB_UNIQUE_RECORD &inUniqueRecord); + + virtual void passThrough(DbContext &dbContext, + uint32 passThroughId, + const void *inputParams, + void **outputParams); + + // Subclasses must implement this method. + virtual DbContext *makeDbContext(DatabaseSession &inDatabaseSession, + CSSM_DB_ACCESS_TYPE inAccessRequest, + const AccessCredentials *inAccessCred, + const void *inOpenParameters); + + const CssmDbRecordAttributeInfo schemaRelations; + const CssmDbRecordAttributeInfo schemaAttributes; + const CssmDbRecordAttributeInfo schemaIndexes; + const CssmDbRecordAttributeInfo schemaParsingModule; + + const char *recordName(CSSM_DB_RECORDTYPE inRecordType) const; + +private: + static void + updateUniqueRecord(DbContext &inDbContext, + CSSM_DB_RECORDTYPE inTableId, + const RecordId &inRecordId, + CSSM_DB_UNIQUE_RECORD &inoutUniqueRecord); + + CSSM_DB_UNIQUE_RECORD_PTR + createUniqueRecord(DbContext &inDbContext, CSSM_DB_RECORDTYPE inTableId, + const RecordId &inRecordId); + const RecordId parseUniqueRecord(const CSSM_DB_UNIQUE_RECORD &inUniqueRecord, + CSSM_DB_RECORDTYPE &outTableId); + + Mutex mWriteLock; + AtomicFile mAtomicFile; + DbModifier mDbModifier; + const AppleDatabaseTableName *mTableNames; +}; + +} // end namespace Security + +#endif //_H_APPLEDATABASE diff --git a/libsecurity_filedb/lib/AtomicFile.cpp b/libsecurity_filedb/lib/AtomicFile.cpp new file mode 100644 index 00000000..1c37c4da --- /dev/null +++ b/libsecurity_filedb/lib/AtomicFile.cpp @@ -0,0 +1,1267 @@ +/* + * 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'). + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define kAtomicFileMaxBlockSize INT_MAX + + +// +// AtomicFile.cpp +// +AtomicFile::AtomicFile(const std::string &inPath) : + mPath(inPath) +{ + pathSplit(inPath, mDir, mFile); + + if (mDir.length() == 0) + { + const char* buffer = getwd(NULL); + mDir = buffer; + free((void*) buffer); + } + + mDir += '/'; + + // determine if the path is on a local or a networked volume + struct statfs info; + int result = statfs(mDir.c_str(), &info); + if (result == -1) // error on opening? + { + mIsLocalFileSystem = false; // revert to the old ways if we can't tell what kind of system we have + } + else + { + mIsLocalFileSystem = (info.f_flags & MNT_LOCAL) != 0; + if (mIsLocalFileSystem) + { + // compute the name of the lock file for this file + CC_SHA1_CTX ctx; + CC_SHA1_Init(&ctx); + CC_SHA1_Update(&ctx, (const void*) mFile.c_str(), mFile.length()); + u_int8_t digest[CC_SHA1_DIGEST_LENGTH]; + CC_SHA1_Final(digest, &ctx); + + u_int32_t hash = (digest[0] << 24) | (digest[1] << 16) | (digest[2] << 8) | digest[3]; + + char buffer[256]; + sprintf(buffer, "%08X", hash); + mLockFilePath = mDir + ".fl" + buffer; + } + } +} + +AtomicFile::~AtomicFile() +{ +} + +// Aquire the write lock and remove the file. +void +AtomicFile::performDelete() +{ + AtomicLockedFile lock(*this); + if (::unlink(mPath.c_str()) != 0) + { + int error = errno; + secdebug("atomicfile", "unlink %s: %s", mPath.c_str(), strerror(error)); + if (error == ENOENT) + CssmError::throwMe(CSSMERR_DL_DATASTORE_DOESNOT_EXIST); + else + UnixError::throwMe(error); + } + + // unlink our lock file + ::unlink(mLockFilePath.c_str()); +} + +// Aquire the write lock and rename the file (and bump the version and stuff). +void +AtomicFile::rename(const std::string &inNewPath) +{ + const char *path = mPath.c_str(); + const char *newPath = inNewPath.c_str(); + + // @@@ lock the destination file too. + AtomicLockedFile lock(*this); + if (::rename(path, newPath) != 0) + { + int error = errno; + secdebug("atomicfile", "rename(%s, %s): %s", path, newPath, strerror(error)); + UnixError::throwMe(error); + } +} + +// Lock the file for writing and return a newly created AtomicTempFile. +RefPointer +AtomicFile::create(mode_t mode) +{ + const char *path = mPath.c_str(); + + // First make sure the directory to this file exists and is writable + mkpath(mDir); + + RefPointer lock(new AtomicLockedFile(*this)); + int fileRef = ropen(path, O_WRONLY|O_CREAT|O_EXCL, mode); + if (fileRef == -1) + { + int error = errno; + secdebug("atomicfile", "open %s: %s", path, strerror(error)); + + // Do the obvious error code translations here. + // @@@ Consider moving these up a level. + if (error == EACCES) + CssmError::throwMe(CSSM_ERRCODE_OS_ACCESS_DENIED); + else if (error == EEXIST) + CssmError::throwMe(CSSMERR_DL_DATASTORE_ALREADY_EXISTS); + else + UnixError::throwMe(error); + } + rclose(fileRef); + + try + { + // Now that we have created the lock and the new db file create a tempfile + // object. + RefPointer temp(new AtomicTempFile(*this, lock, mode)); + secdebug("atomicfile", "%p created %s", this, path); + return temp; + } + catch (...) + { + // Creating the temp file failed so remove the db file we just created too. + if (::unlink(path) == -1) + { + secdebug("atomicfile", "unlink %s: %s", path, strerror(errno)); + } + throw; + } +} + +// Lock the database file for writing and return a newly created AtomicTempFile. +// If the parent directory allows the write we're going to allow this. Previous +// versions checked for writability of the db file and that caused problems when +// setuid programs had made entries. As long as the db (keychain) file is readable +// this function can make the newer keychain file with the correct owner just by virtue +// of the copy that takes place. + +RefPointer +AtomicFile::write() +{ + + RefPointer lock(new AtomicLockedFile(*this)); + return new AtomicTempFile(*this, lock); +} + +// Return a bufferedFile containing current version of the file for reading. +RefPointer +AtomicFile::read() +{ + return new AtomicBufferedFile(mPath, mIsLocalFileSystem); +} + +mode_t +AtomicFile::mode() const +{ + const char *path = mPath.c_str(); + struct stat st; + if (::stat(path, &st) == -1) + { + int error = errno; + secdebug("atomicfile", "stat %s: %s", path, strerror(error)); + UnixError::throwMe(error); + } + return st.st_mode; +} + +// Split full into a dir and file component. +void +AtomicFile::pathSplit(const std::string &inFull, std::string &outDir, std::string &outFile) +{ + std::string::size_type slash, len = inFull.size(); + slash = inFull.rfind('/'); + if (slash == std::string::npos) + { + outDir = ""; + outFile = inFull; + } + else if (slash + 1 == len) + { + outDir = inFull; + outFile = ""; + } + else + { + outDir = inFull.substr(0, slash + 1); + outFile = inFull.substr(slash + 1, len); + } +} + +static std::string RemoveDoubleSlashes(const std::string &path) +{ + std::string result; + unsigned i; + for (i = 0; i < path.length(); ++i) + { + result += path[i]; + if ((i < path.length() - 2) && path[i] == '/' && path[i + 1] == '/') + { + i += 1; // skip a second '/' + } + } + + return result; +} + + + +// +// Make sure the directory up to inDir exists inDir *must* end in a slash. +// +void +AtomicFile::mkpath(const std::string &inDir, mode_t mode) +{ + for (std::string::size_type pos = 0; (pos = inDir.find('/', pos + 1)) != std::string::npos;) + { + std::string path = inDir.substr(0, pos); + const char *cpath = path.c_str(); + struct stat sb; + if (::stat(cpath, &sb)) + { + // if we are creating a path in the user's home directory, override the user's mode + std::string homedir = getenv("HOME"); + + // canonicalize the path (remove double slashes) + string canonPath = RemoveDoubleSlashes(cpath); + + if (canonPath.find(homedir, 0) == 0) + { + mode = 0700; + } + + if (errno != ENOENT || ::mkdir(cpath, mode)) + UnixError::throwMe(errno); + } + else if (!S_ISDIR(sb.st_mode)) + CssmError::throwMe(CSSM_ERRCODE_OS_ACCESS_DENIED); // @@@ Should be is a directory + } +} + +int +AtomicFile::ropen(const char *const name, int flags, mode_t mode) +{ + bool isCreate = (flags & O_CREAT) != 0; + + /* + The purpose of checkForRead and checkForWrite is to mitigate + spamming of the log when a user has installed certain third + party software packages which create additional keychains. + Certain applications use a custom sandbox profile which do not + permit this and so the user gets a ton of spam in the log. + This turns into a serious performance problem. + + We handle this situation by checking two factors: + + 1: If the user is trying to create a file, we send the + request directly to open. This is the right thing + to do, as we don't want most applications creating + keychains unless they have been expressly authorized + to do so. + + The layers above this one only set O_CREAT when a file + doesn't exist, so the case where O_CREAT can be called + on an existing file is irrelevant. + + 2: If the user is trying to open the file for reading or + writing, we check with the sandbox mechanism to see if + the operation will be permitted (and tell it not to + log if it the operation will fail). + + If the operation is not permitted, we return -1 which + emulates the behavior of open. sandbox_check sets + errno properly, so the layers which call this function + will be able to act as though open had been called. + */ + + bool checkForRead = false; + bool checkForWrite = false; + + int fd, tries_left = 4 /* kNoResRetry */; + + if (!isCreate) + { + switch (flags & O_ACCMODE) + { + case O_RDONLY: + checkForRead = true; + break; + case O_WRONLY: + checkForWrite = true; + break; + case O_RDWR: + checkForRead = true; + checkForWrite = true; + break; + } + + if (checkForRead) + { + int result = sandbox_check(getpid(), "file-read-data", (sandbox_filter_type) (SANDBOX_FILTER_PATH | SANDBOX_CHECK_NO_REPORT), name); + if (result != 0) + { + return -1; + } + } + + if (checkForWrite) + { + int result = sandbox_check(getpid(), "file-write-data", (sandbox_filter_type) (SANDBOX_FILTER_PATH | SANDBOX_CHECK_NO_REPORT), name); + if (result != 0) + { + return -1; + } + } + } + + do + { + fd = ::open(name, flags, mode); + } while (fd < 0 && (errno == EINTR || (errno == ENFILE && --tries_left >= 0))); + + return fd; +} + +int +AtomicFile::rclose(int fd) +{ + int result; + do + { + result = ::close(fd); + } while(result && errno == EINTR); + + return result; +} + +// +// AtomicBufferedFile - This represents an instance of a file opened for reading. +// The file is read into memory and closed after this is done. +// The memory is released when this object is destroyed. +// +AtomicBufferedFile::AtomicBufferedFile(const std::string &inPath, bool isLocal) : + mPath(inPath), + mFileRef(-1), + mBuffer(NULL), + mLength(0), + mIsMapped(isLocal) +{ +} + +AtomicBufferedFile::~AtomicBufferedFile() +{ + if (mFileRef >= 0) + { + AtomicFile::rclose(mFileRef); + secdebug("atomicfile", "%p closed %s", this, mPath.c_str()); + } + + if (mBuffer) + { + secdebug("atomicfile", "%p free %s buffer %p", this, mPath.c_str(), mBuffer); + unloadBuffer(); + } +} + +// +// Open the file and return the length in bytes. +// +off_t +AtomicBufferedFile::open() +{ + const char *path = mPath.c_str(); + if (mFileRef >= 0) + { + secdebug("atomicfile", "open %s: already open, closing and reopening", path); + close(); + } + + mFileRef = AtomicFile::ropen(path, O_RDONLY, 0); + if (mFileRef == -1) + { + int error = errno; + secdebug("atomicfile", "open %s: %s", path, strerror(error)); + + // Do the obvious error code translations here. + // @@@ Consider moving these up a level. + if (error == ENOENT) + CssmError::throwMe(CSSMERR_DL_DATASTORE_DOESNOT_EXIST); + else if (error == EACCES) + CssmError::throwMe(CSSM_ERRCODE_OS_ACCESS_DENIED); + else + UnixError::throwMe(error); + } + + struct stat st; + int result = fstat(mFileRef, &st); + if (result == 0) + { + mLength = st.st_size; + } + else + { + int error = errno; + secdebug("atomicfile", "lseek(%s, END): %s", path, strerror(error)); + AtomicFile::rclose(mFileRef); + UnixError::throwMe(error); + } + + secdebug("atomicfile", "%p opened %s: %qd bytes", this, path, mLength); + + return mLength; +} + +// +// Unload the contents of the file. +// +void +AtomicBufferedFile::unloadBuffer() +{ + if (!mIsMapped) + { + delete [] mBuffer; + } + else + { + munmap(mBuffer, mLength); + } +} + +// +// Load the contents of the file into memory. +// If we are on a local file system, we mmap the file. Otherwise, we +// read it all into memory +void +AtomicBufferedFile::loadBuffer() +{ + if (!mIsMapped) + { + // make a buffer big enough to hold the entire file + mBuffer = new uint8[mLength]; + lseek(mFileRef, 0, SEEK_SET); + ssize_t pos = 0; + + ssize_t bytesToRead = mLength; + while (bytesToRead > 0) + { + ssize_t bytesRead = ::read(mFileRef, mBuffer + pos, bytesToRead); + if (bytesRead == -1) + { + if (errno != EINTR) + { + int error = errno; + secdebug("atomicfile", "lseek(%s, END): %s", mPath.c_str(), strerror(error)); + AtomicFile::rclose(mFileRef); + UnixError::throwMe(error); + } + } + else + { + bytesToRead -= bytesRead; + pos += bytesRead; + } + } + } + else + { + // mmap the buffer into place + mBuffer = (uint8*) mmap(NULL, mLength, PROT_READ, MAP_PRIVATE, mFileRef, 0); + if (mBuffer == (uint8*) -1) + { + int error = errno; + secdebug("atomicfile", "lseek(%s, END): %s", mPath.c_str(), strerror(error)); + AtomicFile::rclose(mFileRef); + UnixError::throwMe(error); + } + } +} + + + +// +// Read the file starting at inOffset for inLength bytes into the buffer and return +// a pointer to it. On return outLength contain the actual number of bytes read, it +// will only ever be less than inLength if EOF was reached, and it will never be more +// than inLength. +// +const uint8 * +AtomicBufferedFile::read(off_t inOffset, off_t inLength, off_t &outLength) +{ + if (mFileRef < 0) + { + secdebug("atomicfile", "read %s: file yet not opened, opening", mPath.c_str()); + open(); + } + + off_t bytesLeft = inLength; + if (mBuffer) + { + secdebug("atomicfile", "%p free %s buffer %p", this, mPath.c_str(), mBuffer); + unloadBuffer(); + } + + loadBuffer(); + + secdebug("atomicfile", "%p allocated %s buffer %p size %qd", this, mPath.c_str(), mBuffer, bytesLeft); + + ssize_t maxEnd = inOffset + inLength; + if (maxEnd > mLength) + { + maxEnd = mLength; + } + + outLength = maxEnd - inOffset; + + return mBuffer + inOffset; +} + +void +AtomicBufferedFile::close() +{ + if (mFileRef < 0) + { + secdebug("atomicfile", "close %s: already closed", mPath.c_str()); + } + else + { + int result = AtomicFile::rclose(mFileRef); + mFileRef = -1; + if (result == -1) + { + int error = errno; + secdebug("atomicfile", "close %s: %s", mPath.c_str(), strerror(errno)); + UnixError::throwMe(error); + } + + secdebug("atomicfile", "%p closed %s", this, mPath.c_str()); + } +} + + +// +// AtomicTempFile - A temporary file to write changes to. +// +AtomicTempFile::AtomicTempFile(AtomicFile &inFile, const RefPointer &inLockedFile, mode_t mode) : + mFile(inFile), + mLockedFile(inLockedFile), + mCreating(true) +{ + create(mode); +} + +AtomicTempFile::AtomicTempFile(AtomicFile &inFile, const RefPointer &inLockedFile) : + mFile(inFile), + mLockedFile(inLockedFile), + mCreating(false) +{ + create(mFile.mode()); +} + +AtomicTempFile::~AtomicTempFile() +{ + // rollback if we didn't commit yet. + if (mFileRef >= 0) + rollback(); +} + +// +// Open the file and return the length in bytes. +// +void +AtomicTempFile::create(mode_t mode) +{ + // we now generate our temporary file name through sandbox API's. + + // put the dir into a canonical form + string dir = mFile.dir(); + int i = dir.length() - 1; + + // walk backwards until we get to a non / character + while (i >= 0 && dir[i] == '/') + { + i -= 1; + } + + // point one beyond the string + i += 1; + + const char* temp = _amkrtemp((dir.substr(0, i) + "/" + mFile.file()).c_str()); + if (temp == NULL) + { + UnixError::throwMe(errno); + } + + mPath = temp; + free((void*) temp); + + const char *path = mPath.c_str(); + + mFileRef = AtomicFile::ropen(path, O_WRONLY|O_CREAT|O_TRUNC, mode); + if (mFileRef == -1) + { + int error = errno; + secdebug("atomicfile", "open %s: %s", path, strerror(error)); + + // Do the obvious error code translations here. + // @@@ Consider moving these up a level. + if (error == EACCES) + CssmError::throwMe(CSSM_ERRCODE_OS_ACCESS_DENIED); + else + UnixError::throwMe(error); + } + + // If we aren't creating the inital file, make sure we preserve + // the mode of the old file regardless of the current umask. + // If we are creating the inital file we respect the users + // current umask. + if (!mCreating) + { + if (::fchmod(mFileRef, mode)) + { + int error = errno; + secdebug("atomicfile", "fchmod %s: %s", path, strerror(error)); + UnixError::throwMe(error); + } + } + + secdebug("atomicfile", "%p created %s", this, path); +} + +void +AtomicTempFile::write(AtomicFile::OffsetType inOffsetType, off_t inOffset, const uint32 inData) +{ + uint32 aData = htonl(inData); + write(inOffsetType, inOffset, reinterpret_cast(&aData), sizeof(aData)); +} + +void +AtomicTempFile::write(AtomicFile::OffsetType inOffsetType, off_t inOffset, + const uint32 *inData, uint32 inCount) +{ +#ifdef HOST_LONG_IS_NETWORK_LONG + // Optimize this for the case where hl == nl + const uint32 *aBuffer = inData; +#else + auto_array aBuffer(inCount); + for (uint32 i = 0; i < inCount; i++) + aBuffer.get()[i] = htonl(inData[i]); +#endif + + write(inOffsetType, inOffset, reinterpret_cast(aBuffer.get()), + inCount * sizeof(*inData)); +} + +void +AtomicTempFile::write(AtomicFile::OffsetType inOffsetType, off_t inOffset, const uint8 *inData, size_t inLength) +{ + off_t pos; + if (inOffsetType == AtomicFile::FromEnd) + { + pos = ::lseek(mFileRef, 0, SEEK_END); + if (pos == -1) + { + int error = errno; + secdebug("atomicfile", "lseek(%s, %qd): %s", mPath.c_str(), inOffset, strerror(error)); + UnixError::throwMe(error); + } + } + else if (inOffsetType == AtomicFile::FromStart) + pos = inOffset; + else + CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR); + + off_t bytesLeft = inLength; + const uint8 *ptr = inData; + while (bytesLeft) + { + size_t toWrite = bytesLeft > kAtomicFileMaxBlockSize ? kAtomicFileMaxBlockSize : size_t(bytesLeft); + ssize_t bytesWritten = ::pwrite(mFileRef, ptr, toWrite, pos); + if (bytesWritten == -1) + { + int error = errno; + if (error == EINTR) + { + // We got interrupted by a signal, so try again. + secdebug("atomicfile", "write %s: interrupted, retrying", mPath.c_str()); + continue; + } + + secdebug("atomicfile", "write %s: %s", mPath.c_str(), strerror(error)); + UnixError::throwMe(error); + } + + // Write returning 0 is bad mmkay. + if (bytesWritten == 0) + { + secdebug("atomicfile", "write %s: 0 bytes written", mPath.c_str()); + CssmError::throwMe(CSSMERR_DL_INTERNAL_ERROR); + } + + secdebug("atomicfile", "%p wrote %s %ld bytes from %p", this, mPath.c_str(), bytesWritten, ptr); + + bytesLeft -= bytesWritten; + ptr += bytesWritten; + pos += bytesWritten; + } +} + +void +AtomicTempFile::fsync() +{ + if (mFileRef < 0) + { + secdebug("atomicfile", "fsync %s: already closed", mPath.c_str()); + } + else + { + int result; + do + { + result = ::fsync(mFileRef); + } while (result && errno == EINTR); + + if (result == -1) + { + int error = errno; + secdebug("atomicfile", "fsync %s: %s", mPath.c_str(), strerror(errno)); + UnixError::throwMe(error); + } + + secdebug("atomicfile", "%p fsynced %s", this, mPath.c_str()); + } +} + +void +AtomicTempFile::close() +{ + if (mFileRef < 0) + { + secdebug("atomicfile", "close %s: already closed", mPath.c_str()); + } + else + { + int result = AtomicFile::rclose(mFileRef); + mFileRef = -1; + if (result == -1) + { + int error = errno; + secdebug("atomicfile", "close %s: %s", mPath.c_str(), strerror(errno)); + UnixError::throwMe(error); + } + + secdebug("atomicfile", "%p closed %s", this, mPath.c_str()); + } +} + +// Commit the current create or write and close the write file. Note that a throw during the commit does an automatic rollback. +void +AtomicTempFile::commit() +{ + try + { + fsync(); + close(); + const char *oldPath = mPath.c_str(); + const char *newPath = mFile.path().c_str(); + + // + // Copy the security parameters of one file to another + // Adding this to guard against setuid utilities that are re-writing a user's keychain. We don't want to leave them root-owned. + // In order to not break backward compatability we'll make a best effort, but continue if these efforts fail. + // + // To clear something up - newPath is the name the keychain will become - which is the name of the file being replaced + // oldPath is the "temp filename". + + copyfile_state_t s; + s = copyfile_state_alloc(); + + if(copyfile(newPath, oldPath, s, COPYFILE_SECURITY | COPYFILE_NOFOLLOW) == -1) // Not fatal + secdebug("atomicfile", "copyfile (%s, %s): %s", oldPath, newPath, strerror(errno)); + + copyfile_state_free(s); + // END + + ::utimes(oldPath, NULL); + + if (::rename(oldPath, newPath) == -1) + { + int error = errno; + secdebug("atomicfile", "rename (%s, %s): %s", oldPath, newPath, strerror(errno)); + UnixError::throwMe(error); + } + + // Unlock the lockfile + mLockedFile = NULL; + + secdebug("atomicfile", "%p commited %s", this, oldPath); + } + catch (...) + { + rollback(); + throw; + } +} + +// Rollback the current create or write (happens automatically if commit() isn't called before the destructor is. +void +AtomicTempFile::rollback() throw() +{ + if (mFileRef >= 0) + { + AtomicFile::rclose(mFileRef); + mFileRef = -1; + } + + // @@@ Log errors if this fails. + const char *path = mPath.c_str(); + if (::unlink(path) == -1) + { + secdebug("atomicfile", "unlink %s: %s", path, strerror(errno)); + // rollback can't throw + } + + // @@@ Think about this. Depending on how we do locking we might not need this. + if (mCreating) + { + const char *path = mFile.path().c_str(); + if (::unlink(path) == -1) + { + secdebug("atomicfile", "unlink %s: %s", path, strerror(errno)); + // rollback can't throw + } + } +} + + +// +// An advisory write lock for inFile. +// +FileLocker::~FileLocker() +{ +} + + + +LocalFileLocker::LocalFileLocker(AtomicFile &inFile) : + mPath(inFile.lockFileName()) +{ +} + + +LocalFileLocker::~LocalFileLocker() +{ +} + + + +#ifndef NDEBUG +static double GetTime() +{ + struct timeval t; + gettimeofday(&t, NULL); + return ((double) t.tv_sec) + ((double) t.tv_usec) / 1000000.0; +} +#endif + + + +void +LocalFileLocker::lock(mode_t mode) +{ + struct stat st; + + do + { + // if the lock file doesn't exist, create it + mLockFile = open(mPath.c_str(), O_RDONLY | O_CREAT, mode); + + // if we can't open or create the file, something is wrong + if (mLockFile == -1) + { + UnixError::throwMe(errno); + } + + // try to get exclusive access to the file + IFDEBUG(double startTime = GetTime()); + int result = flock(mLockFile, LOCK_EX); + IFDEBUG(double endTime = GetTime()); + + IFDEBUG(secdebug("atomictime", "Waited %.4f milliseconds for file lock", (endTime - startTime) * 1000.0)); + + // errors at this point are bad + if (result == -1) + { + UnixError::throwMe(errno); + } + + // check and see if the file we have access to still exists. If not, another file shared our file lock + // due to a hash collision and has thrown our lock away -- that, or a user blew the lock file away himself. + + result = fstat(mLockFile, &st); + + // errors at this point are bad + if (result == -1) + { + UnixError::throwMe(errno); + } + + if (st.st_nlink == 0) // we've been unlinked! + { + close(mLockFile); + } + } while (st.st_nlink == 0); +} + + +void +LocalFileLocker::unlock() +{ + flock(mLockFile, LOCK_UN); + close(mLockFile); +} + + + +NetworkFileLocker::NetworkFileLocker(AtomicFile &inFile) : + mDir(inFile.dir()), + mPath(inFile.dir() + "lck~" + inFile.file()) +{ +} + +NetworkFileLocker::~NetworkFileLocker() +{ +} + +std::string +NetworkFileLocker::unique(mode_t mode) +{ + static const int randomPart = 16; + DevRandomGenerator randomGen; + std::string::size_type dirSize = mDir.size(); + std::string fullname(dirSize + randomPart + 2, '\0'); + fullname.replace(0, dirSize, mDir); + fullname[dirSize] = '~'; /* UNIQ_PREFIX */ + char buf[randomPart]; + struct stat filebuf; + int result, fd = -1; + + for (int retries = 0; retries < 10; ++retries) + { + /* Make a random filename. */ + randomGen.random(buf, randomPart); + for (int ix = 0; ix < randomPart; ++ix) + { + char ch = buf[ix] & 0x3f; + fullname[ix + dirSize + 1] = ch + + ( ch < 26 ? 'A' + : ch < 26 + 26 ? 'a' - 26 + : ch < 26 + 26 + 10 ? '0' - 26 - 26 + : ch == 26 + 26 + 10 ? '-' - 26 - 26 - 10 + : '_' - 26 - 26 - 11); + } + + result = lstat(fullname.c_str(), &filebuf); + if (result && errno == ENAMETOOLONG) + { + do + fullname.erase(fullname.end() - 1); + while((result = lstat(fullname.c_str(), &filebuf)) && errno == ENAMETOOLONG && fullname.size() > dirSize + 8); + } /* either it stopped being a problem or we ran out of filename */ + + if (result && errno == ENOENT) + { + fd = AtomicFile::ropen(fullname.c_str(), O_WRONLY|O_CREAT|O_EXCL, mode); + if (fd >= 0 || errno != EEXIST) + break; + } + } + + if (fd < 0) + { + int error = errno; + ::syslog(LOG_ERR, "Couldn't create temp file %s: %s", fullname.c_str(), strerror(error)); + secdebug("atomicfile", "Couldn't create temp file %s: %s", fullname.c_str(), strerror(error)); + UnixError::throwMe(error); + } + + /* @@@ Check for EINTR. */ + write(fd, "0", 1); /* pid 0, `works' across networks */ + + AtomicFile::rclose(fd); + + return fullname; +} + +/* Return 0 on success and 1 on failure if st is set to the result of stat(old) and -1 on failure if the stat(old) failed. */ +int +NetworkFileLocker::rlink(const char *const old, const char *const newn, struct stat &sto) +{ + int result = ::link(old,newn); + if (result) + { + int serrno = errno; + if (::lstat(old, &sto) == 0) + { + struct stat stn; + if (::lstat(newn, &stn) == 0 + && sto.st_dev == stn.st_dev + && sto.st_ino == stn.st_ino + && sto.st_uid == stn.st_uid + && sto.st_gid == stn.st_gid + && !S_ISLNK(sto.st_mode)) + { + /* Link failed but files are the same so the link really went ok. */ + return 0; + } + else + result = 1; + } + errno = serrno; /* Restore errno from link() */ + } + + return result; +} + +/* NFS-resistant rename() + * rename with fallback for systems that don't support it + * Note that this does not preserve the contents of the file. */ +int +NetworkFileLocker::myrename(const char *const old, const char *const newn) +{ + struct stat stbuf; + int fd = -1; + int ret; + + /* Try a real hardlink */ + ret = rlink(old, newn, stbuf); + if (ret > 0) + { + if (stbuf.st_nlink < 2 && (errno == EXDEV || errno == ENOTSUP)) + { + /* Hard link failed so just create a new file with O_EXCL instead. */ + fd = AtomicFile::ropen(newn, O_WRONLY|O_CREAT|O_EXCL, stbuf.st_mode); + if (fd >= 0) + ret = 0; + } + } + + /* We want the errno from the link or the ropen, not that of the unlink. */ + int serrno = errno; + + /* Unlink the temp file. */ + ::unlink(old); + if (fd > 0) + AtomicFile::rclose(fd); + + errno = serrno; + return ret; +} + +int +NetworkFileLocker::xcreat(const char *const name, mode_t mode, time_t &tim) +{ + std::string uniqueName = unique(mode); + const char *uniquePath = uniqueName.c_str(); + struct stat stbuf; /* return the filesystem time to the caller */ + stat(uniquePath, &stbuf); + tim = stbuf.st_mtime; + return myrename(uniquePath, name); +} + +void +NetworkFileLocker::lock(mode_t mode) +{ + const char *path = mPath.c_str(); + bool triedforce = false; + struct stat stbuf; + time_t t, locktimeout = 1024; /* DEFlocktimeout, 17 minutes. */ + bool doSyslog = false; + bool failed = false; + int retries = 0; + + while (!failed) + { + /* Don't syslog first time through. */ + if (doSyslog) + ::syslog(LOG_NOTICE, "Locking %s", path); + else + doSyslog = true; + + secdebug("atomicfile", "Locking %s", path); /* in order to cater for clock skew: get */ + if (!xcreat(path, mode, t)) /* time t from the filesystem */ + { + /* lock acquired, hurray! */ + break; + } + switch(errno) + { + case EEXIST: /* check if it's time for a lock override */ + if (!lstat(path, &stbuf) && stbuf.st_size <= 16 /* MAX_locksize */ && locktimeout + && !lstat(path, &stbuf) && locktimeout < t - stbuf.st_mtime) + /* stat() till unlink() should be atomic, but can't guarantee that. */ + { + if (triedforce) + { + /* Already tried, force lock override, not trying again */ + failed = true; + break; + } + else if (S_ISDIR(stbuf.st_mode) || ::unlink(path)) + { + triedforce=true; + ::syslog(LOG_ERR, "Forced unlock denied on %s", path); + secdebug("atomicfile", "Forced unlock denied on %s", path); + } + else + { + ::syslog(LOG_ERR, "Forcing lock on %s", path); + secdebug("atomicfile", "Forcing lock on %s", path); + sleep(16 /* DEFsuspend */); + break; + } + } + else + triedforce = false; /* legitimate iteration, clear flag */ + + /* Reset retry counter. */ + retries = 0; + usleep(250000); + break; + + case ENOSPC: /* no space left, treat it as a transient */ +#ifdef EDQUOT /* NFS failure */ + case EDQUOT: /* maybe it was a short term shortage? */ +#endif + case ENOENT: + case ENOTDIR: + case EIO: + /*case EACCES:*/ + if(++retries < (256 + 1)) /* nfsTRY number of times+1 to ignore spurious NFS errors */ + usleep(250000); + else + failed = true; + break; + +#ifdef ENAMETOOLONG + case ENAMETOOLONG: /* Filename is too long, shorten and retry */ + if (mPath.size() > mDir.size() + 8) + { + secdebug("atomicfile", "Truncating %s and retrying lock", path); + mPath.erase(mPath.end() - 1); + path = mPath.c_str(); + /* Reset retry counter. */ + retries = 0; + break; + } + /* DROPTHROUGH */ +#endif + default: + failed = true; + break; + } + } + + if (failed) + { + int error = errno; + ::syslog(LOG_ERR, "Lock failure on %s: %s", path, strerror(error)); + secdebug("atomicfile", "Lock failure on %s: %s", path, strerror(error)); + UnixError::throwMe(error); + } +} + +void +NetworkFileLocker::unlock() +{ + const char *path = mPath.c_str(); + if (::unlink(path) == -1) + { + secdebug("atomicfile", "unlink %s: %s", path, strerror(errno)); + // unlock can't throw + } +} + + + +AtomicLockedFile::AtomicLockedFile(AtomicFile &inFile) +{ + if (inFile.isOnLocalFileSystem()) + { + mFileLocker = new LocalFileLocker(inFile); + } + else + { + mFileLocker = new NetworkFileLocker(inFile); + } + + lock(); +} + + + +AtomicLockedFile::~AtomicLockedFile() +{ + unlock(); + delete mFileLocker; +} + + + +void +AtomicLockedFile::lock(mode_t mode) +{ + mFileLocker->lock(mode); +} + + + +void AtomicLockedFile::unlock() throw() +{ + mFileLocker->unlock(); +} + + + +#undef kAtomicFileMaxBlockSize diff --git a/libsecurity_filedb/lib/AtomicFile.h b/libsecurity_filedb/lib/AtomicFile.h new file mode 100644 index 00000000..96255055 --- /dev/null +++ b/libsecurity_filedb/lib/AtomicFile.h @@ -0,0 +1,257 @@ +/* + * Copyright (c) 2000-2001, 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. + */ + + +// +// AtomicFile.h - Description t.b.d. +// +#ifndef _SECURITY_ATOMICFILE_H_ +#define _SECURITY_ATOMICFILE_H_ 1 + +#include +#include +#include +#include + +namespace Security +{ + +class AtomicBufferedFile; +class AtomicLockedFile; +class AtomicTempFile; + +class AtomicFile +{ +public: + AtomicFile(const std::string &inPath); + ~AtomicFile(); + + // Aquire the write lock and remove the file. + void performDelete(); + + // Aquire the write lock and rename the file. + void rename(const std::string &inNewPath); + + // Lock the file for writing and return a newly created AtomicTempFile. + RefPointer create(mode_t mode); + + // Lock the file for writing and return a newly created AtomicTempFile. + RefPointer write(); + + // Return a bufferedFile containing current version of the file for reading. + RefPointer read(); + + string path() const { return mPath; } + string dir() const { return mDir; } + string file() const { return mFile; } + string lockFileName() { return mLockFilePath; } + + mode_t mode() const; + bool isOnLocalFileSystem() {return mIsLocalFileSystem;} + + enum OffsetType + { + FromStart, + FromEnd // only works with offset of 0 + }; + + static void pathSplit(const std::string &inFull, std::string &outDir, std::string &outFile); + static void mkpath(const std::string &inDir, mode_t mode = 0777); + static int ropen(const char *const name, int flags, mode_t mode); + static int rclose(int fd); + +private: + bool mIsLocalFileSystem; + string mPath; + string mDir; + string mFile; + string mLockFilePath; +}; + + +// +// AtomicBufferedFile - This represents an instance of a file opened for reading. +// The file is read into memory and closed after this is done. +// The memory is released when this object is destroyed. +// +class AtomicBufferedFile : public RefCount +{ +public: + AtomicBufferedFile(const std::string &inPath, bool isLocalFileSystem); + ~AtomicBufferedFile(); + + // Open the file and return it's size. + off_t open(); + + // Read inLength bytes starting at inOffset. + const uint8 *read(off_t inOffset, off_t inLength, off_t &outLength); + + // Return the current mode bits of the file + mode_t mode(); + + // Close the file (this doesn't release the buffer). + void close(); + + // Return the length of the file. + off_t length() const { return mLength; } + +private: + void loadBuffer(); + void unloadBuffer(); + +private: + // Complete path to the file + string mPath; + + // File descriptor to the file or -1 if it's not currently open. + int mFileRef; + + // This is where the data from the file is read in to. + uint8 *mBuffer; + + // Length of file in bytes. + off_t mLength; + + // Is on a local file system + bool mIsMapped; +}; + + +// +// AtomicTempFile - A temporary file to write changes to. +// +class AtomicTempFile : public RefCount +{ +public: + // Start a write for a new file. + AtomicTempFile(AtomicFile &inFile, const RefPointer &inLockedFile, mode_t mode); + + // Start a write of an existing file. + AtomicTempFile(AtomicFile &inFile, const RefPointer &inLockedFile); + + ~AtomicTempFile(); + + // Commit the current create or write and close the write file. + void commit(); + + void write(AtomicFile::OffsetType inOffsetType, off_t inOffset, const uint32 *inData, uint32 inCount); + void write(AtomicFile::OffsetType inOffsetType, off_t inOffset, const uint8 *inData, size_t inLength); + void write(AtomicFile::OffsetType inOffsetType, off_t inOffset, const uint32 inData); + +private: + // Called by both constructors. + void create(mode_t mode); + + // Fsync the file + void fsync(); + + // Close the file + void close(); + + // Rollback the current create or write (happens automatically if commit() isn't called before the destructor is). + void rollback() throw(); + +private: + // Our AtomicFile object. + AtomicFile &mFile; + + RefPointer mLockedFile; + + // Complete path to the file + string mPath; + + // File descriptor to the file or -1 if it's not currently open. + int mFileRef; + + // If this is true we unlink both mPath and mFile.path() when we rollback. + bool mCreating; +}; + + +class FileLocker +{ +public: + virtual ~FileLocker(); + + virtual void lock(mode_t mode) = 0; + virtual void unlock() = 0; +}; + + + +class LocalFileLocker : public FileLocker +{ +public: + LocalFileLocker(AtomicFile &inFile); + virtual ~LocalFileLocker(); + + virtual void lock(mode_t mode); + virtual void unlock(); + +private: + int mLockFile; + string mPath; +}; + + + +class NetworkFileLocker : public FileLocker +{ +public: + NetworkFileLocker(AtomicFile &inFile); + virtual ~NetworkFileLocker(); + + virtual void lock(mode_t mode); + virtual void unlock(); + +private: + std::string unique(mode_t mode); + int rlink(const char *const old, const char *const newn, struct stat &sto); + int myrename(const char *const old, const char *const newn); + int xcreat(const char *const name, mode_t mode, time_t &tim); + + // The directory in which we create the lock + string mDir; + + // Complete path to the file + string mPath; +}; + + + +// The current lock being held. +class AtomicLockedFile : public RefCount +{ +public: + // Create a write lock for inFile. + AtomicLockedFile(AtomicFile &inFile); + + ~AtomicLockedFile(); + +private: + void lock(mode_t mode = (S_IRUSR|S_IRGRP|S_IROTH) /* === 0444 */); + void unlock() throw(); + +private: + FileLocker* mFileLocker; +}; + + +} // end namespace Security + + +#endif // _SECURITY_ATOMICFILE_H_ diff --git a/libsecurity_filedb/lib/DbIndex.cpp b/libsecurity_filedb/lib/DbIndex.cpp new file mode 100644 index 00000000..f476af5e --- /dev/null +++ b/libsecurity_filedb/lib/DbIndex.cpp @@ -0,0 +1,476 @@ +/* + * 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. + */ + + +// +// DbIndex.cpp +// + +#include "DbIndex.h" +#include "AppleDatabase.h" +#include + +DbQueryKey::DbQueryKey(const DbConstIndex &index) +: mIndex(index), + mTableSection(index.table().getTableSection()) +{ +} + +// Perform a less-than comparison between two keys. An offset of +// kUseQueryKeyOffset means to use the key provided as part of the +// query; otherwise, the key comes from the database. + +const uint32 DbKeyComparator::kUseQueryKeyOffset; + +bool +DbKeyComparator::operator () (uint32 offset1, uint32 offset2) const +{ + ReadSection rs1, rs2; + const ReadSection *key1, *key2; + + // get the read sections to compare + + if (offset1 == kUseQueryKeyOffset) + key1 = &mKey.mKeyData; + else { + rs1 = mKey.mTableSection.subsection(offset1); + key1 = &rs1; + } + + if (offset2 == kUseQueryKeyOffset) + key2 = &mKey.mKeyData; + else { + rs2 = mKey.mTableSection.subsection(offset2); + key2 = &rs2; + } + + // compare the values of the attributes in the keys + + uint32 valueOffset1 = sizeof(uint32), valueOffset2 = sizeof(uint32); + + for (uint32 i = 0; i < mKey.mNumKeyValues; i++) { + const MetaAttribute &metaAttribute = *mKey.mIndex.mAttributes[i]; + auto_ptr value1(metaAttribute.createValue(*key1, valueOffset1)); + auto_ptr value2(metaAttribute.createValue(*key2, valueOffset2)); + + if (metaAttribute.evaluate(value1.get(), value2.get(), CSSM_DB_LESS_THAN)) + return true; + + else if (metaAttribute.evaluate(value2.get(), value1.get(), CSSM_DB_LESS_THAN)) + return false; + } + + // if we are here, the keys are equal + + return false; +} + +// Comparison used when inserting an item into an index, but otherwise +// similar to the version above. + +bool +DbIndexKey::operator < (const DbIndexKey &other) const +{ + // compare the values of the attributes in the keys + + uint32 numAttributes = mIndex.mAttributes.size(); + uint32 valueOffset1 = 0, valueOffset2 = 0; + + for (uint32 i = 0; i < numAttributes; i++) { + const MetaAttribute &metaAttribute = *mIndex.mAttributes[i]; + auto_ptr value1(metaAttribute.createValue(mKeySection.subsection(mKeyRange), + valueOffset1)); + auto_ptr value2(metaAttribute.createValue(other.mKeySection.subsection(other.mKeyRange), + valueOffset2)); + + if (metaAttribute.evaluate(value1.get(), value2.get(), CSSM_DB_LESS_THAN)) + return true; + + else if (metaAttribute.evaluate(value2.get(), value1.get(), CSSM_DB_LESS_THAN)) + return false; + } + + // if we are here, the keys are equal + + return false; +} + +DbIndex::DbIndex(const MetaRecord &metaRecord, uint32 indexId, bool isUniqueIndex) +: mMetaRecord(metaRecord), + mIndexId(indexId), + mIsUniqueIndex(isUniqueIndex) +{ +} + +// Append an attribute to the vector used to form index keys. + +void +DbIndex::appendAttribute(uint32 attributeId) +{ + CSSM_DB_ATTRIBUTE_INFO info; + info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER; + info.Label.AttributeID = attributeId; + + mAttributes.push_back(&(mMetaRecord.metaAttribute(info))); +} + +// Construct a new read-only index. + +DbConstIndex::DbConstIndex(const Table &table, uint32 indexId, bool isUniqueIndex) +: DbIndex(table.getMetaRecord(), indexId, isUniqueIndex), + mTable(table) +{ +} + +DbConstIndex::DbConstIndex(const Table &table, const ReadSection &indexSection) +: DbIndex(table.getMetaRecord(), indexSection.at(AtomSize), indexSection.at(2 * AtomSize)), + mTable(table) +{ + uint32 numAttributes = indexSection.at(3 * AtomSize); + + for (uint32 i = 0; i < numAttributes; i++) { + uint32 attributeId = indexSection.at((4 + i) * AtomSize); + appendAttribute(attributeId); + } + + uint32 offset = (4 + numAttributes) * AtomSize; + uint32 numRecords = indexSection.at(offset); + offset += AtomSize; + mKeyOffsetVector.overlay(numRecords, + reinterpret_cast(indexSection.range(Range(offset, numRecords * AtomSize)))); + + offset += numRecords * AtomSize; + mRecordNumberVector.overlay(numRecords, + reinterpret_cast(indexSection.range(Range(offset, numRecords * AtomSize)))); +} + +// Check to see if this index can be used to perform a given query, based on +// the attributes used in the query and their order. They must be a prefix +// of the index key attributes. If there is more than one attribute, all of the +// operators must be EQUAL and the conjunctive must be AND; this is needed to +// ensure that the results are a contiguous segment of the index. On success, +// the appropriate index key is generated from the query. + +bool +DbConstIndex::matchesQuery(const CSSM_QUERY &query, DbQueryKey *&queryKey) const +{ + uint32 numPredicates = query.NumSelectionPredicates; + + if (numPredicates == 0 || numPredicates > mAttributes.size()) + return false; + + // determine which index attributes are used in the query + + auto_array attributeUsed(mAttributes.size()); + for (uint32 i = 0; i < mAttributes.size(); attributeUsed[i++] = ~(uint32)0); + + for (uint32 i = 0, j; i < numPredicates; i++) { + const MetaAttribute &tableAttribute = + mMetaRecord.metaAttribute(query.SelectionPredicate[i].Attribute.Info); + + for (j = 0; j < mAttributes.size(); j++) { + if (tableAttribute.attributeId() == mAttributes[j]->attributeId()) { + if (attributeUsed[j] != ~(uint32)0) + // invalid query: attribute appears twice + CssmError::throwMe(CSSMERR_DL_INVALID_QUERY); + else { + // the jth index component is the ith predicate in the query + attributeUsed[j] = i; + break; + } + } + } + + if (j == mAttributes.size()) { + // the predicate attribute is not in the index, so return failure + return false; + } + } + + // check that the query predicates form a prefix of the index key, which means that + // the first N index components are the N query predicates in some order + + uint32 lastIndex; + for (lastIndex = mAttributes.size() - 1; (lastIndex >= 0) && (attributeUsed[lastIndex] == ~(uint32)0); + lastIndex--); + + if (lastIndex != numPredicates - 1) + return false; + + // if there is more than one predicate, the conjunctive must be AND and all the + // operators must be EQUAL for the compound index to be useful + + CSSM_DB_OPERATOR op; + + if (numPredicates > 1) { + if (query.Conjunctive != CSSM_DB_AND) + return false; + + for (uint32 i = 0; i < numPredicates; i++) + if (query.SelectionPredicate[i].DbOperator != CSSM_DB_EQUAL) + return false; + + op = CSSM_DB_EQUAL; + } + + // for a single predicate, check the operator + + else { + op = query.SelectionPredicate[0].DbOperator; + if (op != CSSM_DB_EQUAL && op != CSSM_DB_LESS_THAN && op != CSSM_DB_GREATER_THAN) + return false; + } + + // ok, after all that, we can use this index, so generate an object used as a key + // for this query on this index + + queryKey = new DbQueryKey(*this); + queryKey->mNumKeyValues = numPredicates; + queryKey->mOp = op; + + uint32 keyLength = sizeof(uint32); + for (uint32 i = 0; i < numPredicates; i++) + mAttributes[i]->packValue(queryKey->mKeyData, keyLength, + *(query.SelectionPredicate[attributeUsed[i]].Attribute.Value)); + queryKey->mKeyData.put(0, keyLength - sizeof(uint32)); + queryKey->mKeyData.size(keyLength); + + return true; +} + +// Perform a query on an index, returning the iterators that bound the +// returned results. + +void +DbConstIndex::performQuery(const DbQueryKey &queryKey, + DbIndexIterator &begin, DbIndexIterator &end) const +{ + DbKeyComparator cmp(queryKey); + + switch (queryKey.mOp) { + + case CSSM_DB_EQUAL: + { + pair result; + result = equal_range(mKeyOffsetVector.begin(), mKeyOffsetVector.end(), + DbKeyComparator::kUseQueryKeyOffset, cmp); + begin = result.first; + end = result.second; + } + break; + + case CSSM_DB_LESS_THAN: + begin = mKeyOffsetVector.begin(); + end = lower_bound(begin, mKeyOffsetVector.end(), + DbKeyComparator::kUseQueryKeyOffset, cmp); + break; + + case CSSM_DB_GREATER_THAN: + end = mKeyOffsetVector.end(); + begin = lower_bound(mKeyOffsetVector.begin(), end, + DbKeyComparator::kUseQueryKeyOffset, cmp); + break; + + default: + CssmError::throwMe(CSSMERR_DL_INTERNAL_ERROR); + break; + } +} + +// Given an iterator as returned by performQuery(), return the read section for the record. + +ReadSection +DbConstIndex::getRecordSection(DbIndexIterator iter) const +{ + uint32 recordNumber = mRecordNumberVector[iter - mKeyOffsetVector.begin()]; + return mTable.getRecordSection(recordNumber); +} + +// Construct a mutable index from a read-only index. + +DbMutableIndex::DbMutableIndex(const DbConstIndex &index) +: DbIndex(index), + mIndexDataSize(0) +{ + // go through the const index and copy all the entries into the + // mutable index + + const ReadSection &tableSection = index.mTable.getTableSection(); + + uint32 numRecords = index.mKeyOffsetVector.size(); + for (uint32 i = 0; i < numRecords; i++) { + uint32 recordNumber = index.mRecordNumberVector.at(i); + uint32 keyOffset = index.mKeyOffsetVector.at(i); + uint32 keySize = tableSection.at(keyOffset); + DbIndexKey key(tableSection, Range(keyOffset + AtomSize, keySize), *this); + mMap.insert(IndexMap::value_type(key, recordNumber)); + } +} + +DbMutableIndex::DbMutableIndex(const MetaRecord &metaRecord, uint32 indexId, bool isUniqueIndex) +: DbIndex(metaRecord, indexId, isUniqueIndex), + mIndexDataSize(0) +{ +} + +DbMutableIndex::~DbMutableIndex() +{ +} + +// Remove all entries for a record from an index. This is not an ideal implementation, +// since it walks the entire index. In a perfect world, we'd generate all the record's +// keys and lookup matching entries, deleting only those with the correct record number. +// But this is not a perfect world. + +void +DbMutableIndex::removeRecord(uint32 recordNumber) +{ + IndexMap::iterator it, temp; + for (it = mMap.begin(); it != mMap.end(); ) { + temp = it; it++; + if (temp->second == recordNumber) + mMap.erase(temp); + } +} + +// Insert a record into an index. + +void +DbMutableIndex::insertRecord(uint32 recordNumber, const ReadSection &packedRecord) +{ + // The common case is that each indexed attribute has a single value in + // the record; detect and handle this separately since we can avoid an + // expensive recursive technique. + + uint32 numAttributes = mAttributes.size(); + bool allSingleValued = true; + + for (uint32 i = 0; i < numAttributes; i++) { + uint32 numValues = mAttributes[i]->getNumberOfValues(packedRecord); + if (numValues == 0) { + // record does not have value required by index; for a unique index, + // this is an error, otherwise just don't index the record + if (mIsUniqueIndex) + CssmError::throwMe(CSSMERR_DL_MISSING_VALUE); + else + return; + } + else if (numValues > 1) { + allSingleValued = false; + break; + } + } + + if (allSingleValued) + insertRecordSingle(recordNumber, packedRecord); + + else { + // recursively build all appropriate index keys, and add them to the map + WriteSection keyData; + insertRecordMulti(recordNumber, packedRecord, 0, keyData, 0); + } +} + +void +DbMutableIndex::insertRecordSingle(uint32 recordNumber, const ReadSection &packedRecord) +{ + // append the key values to the index data + uint32 offset = mIndexDataSize; + for (uint32 i = 0; i < mAttributes.size(); i++) + mAttributes[i]->copyValueBytes(0, packedRecord, mIndexData, mIndexDataSize); + mIndexData.size(mIndexDataSize); + + // make an index key + DbIndexKey key(mIndexData, Range(offset, mIndexDataSize - offset), *this); + + // if this is a unique index, check for a record with the same key + if (mIsUniqueIndex && (mMap.find(key) != mMap.end())) + // the key already exists, which is an error + CssmError::throwMe(CSSMERR_DL_INVALID_UNIQUE_INDEX_DATA); + + // insert the item into the map + mMap.insert(IndexMap::value_type(key, recordNumber)); +} + +void +DbMutableIndex::insertRecordMulti(uint32 recordNumber, const ReadSection &packedRecord, + uint32 attributeIndex, WriteSection &keyData, uint32 keySize) +{ + const MetaAttribute &metaAttribute = *(mAttributes[attributeIndex]); + uint32 numValues = metaAttribute.getNumberOfValues(packedRecord); + + for (uint32 i = 0; i < numValues; i++) { + + uint32 newKeySize = keySize; + metaAttribute.copyValueBytes(i, packedRecord, keyData, newKeySize); + + if (attributeIndex + 1 == mAttributes.size()) { + uint32 offset = mIndexDataSize; + mIndexDataSize = mIndexData.put(mIndexDataSize, newKeySize, keyData.address()); + mIndexData.size(mIndexDataSize); + + DbIndexKey key(mIndexData, Range(offset, mIndexDataSize - offset), *this); + if (mIsUniqueIndex && (mMap.find(key) != mMap.end())) + CssmError::throwMe(CSSMERR_DL_INVALID_UNIQUE_INDEX_DATA); + + mMap.insert(IndexMap::value_type(key, recordNumber)); + } + else + // otherwise, recurse with the rest of the attributes + insertRecordMulti(recordNumber, packedRecord, attributeIndex + 1, keyData, newKeySize); + } +} + +uint32 +DbMutableIndex::writeIndex(WriteSection &ws, uint32 offset) +{ + IndexMap::iterator it; + + // reserve space for the index size + uint32 sizeOffset = offset; + offset += AtomSize; + + offset = ws.put(offset, mIndexId); + offset = ws.put(offset, mIsUniqueIndex ? 1 : 0); + + offset = ws.put(offset, mAttributes.size()); + for (uint32 i = 0; i < mAttributes.size(); i++) + offset = ws.put(offset, mAttributes[i]->attributeId()); + + offset = ws.put(offset, mMap.size()); + + // reserve space for the array of offsets to key data + uint32 keyPtrOffset = offset; + offset += AtomSize * mMap.size(); + + // write the array of record numbers + for (it = mMap.begin(); it != mMap.end(); it++) { + offset = ws.put(offset, it->second); + } + + // write the key data + for (it = mMap.begin(); it != mMap.end(); it++) { + keyPtrOffset = ws.put(keyPtrOffset, offset); + offset = ws.put(offset, it->first.keySize()); + offset = ws.put(offset, it->first.keySize(), it->first.keyData()); + } + + // write the index size + ws.put(sizeOffset, offset - sizeOffset); + + return offset; +} diff --git a/libsecurity_filedb/lib/DbIndex.h b/libsecurity_filedb/lib/DbIndex.h new file mode 100644 index 00000000..2e4b1c7b --- /dev/null +++ b/libsecurity_filedb/lib/DbIndex.h @@ -0,0 +1,198 @@ +/* + * 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. + */ + + +// +// DbIndex.h +// + +#ifndef _H_APPLEDL_DBINDEX +#define _H_APPLEDL_DBINDEX + +#include "MetaRecord.h" + +namespace Security +{ + +class Table; +class DbConstIndex; +class DbIndex; + +typedef constVector DbOffsetVector; + +typedef DbOffsetVector::const_iterator DbIndexIterator; + +// +// An object that represents a key being used as part of a query. +// + +class DbQueryKey +{ + friend class DbConstIndex; + friend class DbKeyComparator; + +public: + DbQueryKey(const DbConstIndex &index); + +private: + WriteSection mKeyData; + uint32 mNumKeyValues; + const DbConstIndex &mIndex; + const ReadSection &mTableSection; + CSSM_DB_OPERATOR mOp; +}; + +// +// An object which performs comparison between keys, either stored +// in a database or provided as part of a query. +// + +class DbKeyComparator +{ +public: + DbKeyComparator(const DbQueryKey &key) : mKey(key) {} + + bool operator () (uint32 keyOffset1, uint32 keyOffset2) const; + + // Pass this value as an argument to + // operator()(uint32,uint32) to compare against mKey. + static const uint32 kUseQueryKeyOffset = 0; + +private: + const DbQueryKey &mKey; +}; + +// +// A key as stored in an index. +// + +class DbIndexKey { +public: + DbIndexKey(const ReadSection &key, const Range &keyRange, const DbIndex &index) + : mKeySection(key), mKeyRange(keyRange), mIndex(index) {} + + bool operator < (const DbIndexKey &other) const; + + uint32 keySize() const { return mKeyRange.mSize; } + const uint8 *keyData() const { return mKeySection.range(mKeyRange); } + +private: + // the key data, expressed as a subsection of a read section + const ReadSection &mKeySection; + Range mKeyRange; + + // the index that knows how to interpret the key data + const DbIndex &mIndex; +}; + +// Base class containing stuff shared between const and mutable indexes. + +class DbIndex +{ + friend class DbIndexKey; + +public: + uint32 indexId() const { return mIndexId; } + + // append an attribute to the index key + void appendAttribute(uint32 attributeId); + +protected: + DbIndex(const MetaRecord &metaRecord, uint32 indexId, bool isUniqueIndex); + + // meta record for table associated with this index + const MetaRecord &mMetaRecord; + + // vector of indexed attributes + typedef vector AttributeVector; + AttributeVector mAttributes; + + uint32 mIndexId; + bool mIsUniqueIndex; +}; + +// Read-only index. + +class DbConstIndex : public DbIndex +{ + friend class DbMutableIndex; + friend class DbQueryKey; + friend class DbKeyComparator; + +public: + DbConstIndex(const Table &table, uint32 indexId, bool isUniqueIndex); + DbConstIndex(const Table &table, const ReadSection &indexSection); + + const Table &table() const { return mTable; } + + // check if this index can be used for a given query, and if so, generate + // the appropriate index key from the query + bool matchesQuery(const CSSM_QUERY &query, DbQueryKey *&queryKey) const; + + // perform a query on the index + void performQuery(const DbQueryKey &queryKey, + DbIndexIterator &begin, DbIndexIterator &end) const; + + // given an iterator as returned by performQuery(), return the read section for the record + ReadSection getRecordSection(DbIndexIterator iter) const; + +private: + // sorted vector of offsets to index key data + DbOffsetVector mKeyOffsetVector; + + // vector, in same order as key vector, of corresponding record numbers + DbOffsetVector mRecordNumberVector; + + const Table &mTable; +}; + +// A memory-resident index that can be modified, but not used for a query. + +class DbMutableIndex : public DbIndex +{ +public: + DbMutableIndex(const DbConstIndex &index); + DbMutableIndex(const MetaRecord &metaRecord, uint32 indexId, bool isUniqueIndex); + ~DbMutableIndex(); + + // insert a record into the index + void insertRecord(uint32 recordNumber, const ReadSection &packedRecord); + + // remove a record from the index + void removeRecord(uint32 recordNumber); + + // write the index + uint32 writeIndex(WriteSection &ws, uint32 offset); + +private: + // helper methods called by insertRecord() + void insertRecordSingle(uint32 recordOffset, const ReadSection &packedRecord); + void insertRecordMulti(uint32 recordOffset, const ReadSection &packedRecord, + uint32 attributeIndex, WriteSection &keyData, uint32 keySize); + + // a single write section which stores generated index key data + WriteSection mIndexData; + uint32 mIndexDataSize; + + // a map from index keys to record numbers + typedef multimap IndexMap; + IndexMap mMap; +}; + +} // end namespace Security + +#endif // _H_APPLEDL_DBINDEX diff --git a/libsecurity_filedb/lib/DbQuery.cpp b/libsecurity_filedb/lib/DbQuery.cpp new file mode 100644 index 00000000..f88d487b --- /dev/null +++ b/libsecurity_filedb/lib/DbQuery.cpp @@ -0,0 +1,30 @@ +/* + * 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. + */ + + +#ifdef __MWERKS__ +#define _CPP_DBQUERY +#endif +#include + +DbQuery::DbQuery () +{ +} + +DbQuery::~DbQuery () +{ +} diff --git a/libsecurity_filedb/lib/DbQuery.h b/libsecurity_filedb/lib/DbQuery.h new file mode 100644 index 00000000..1e48853c --- /dev/null +++ b/libsecurity_filedb/lib/DbQuery.h @@ -0,0 +1,45 @@ +/* + * 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 _DBQUERY_H_ +#define _DBQUERY_H_ 1 + +#include + +#ifdef _CPP_DBQUERY +# pragma export on +#endif + +namespace Security +{ + +class DbQuery: public HandleObject +{ + NOCOPY(DbQuery); +public: + DbQuery (); + virtual ~DbQuery (); +}; + +} // end namespace Security + +#ifdef _CPP_DBQUERY +# pragma export off +#endif + +#endif // _DBQUERY_H_ diff --git a/libsecurity_filedb/lib/DbValue.cpp b/libsecurity_filedb/lib/DbValue.cpp new file mode 100644 index 00000000..fba7fc0b --- /dev/null +++ b/libsecurity_filedb/lib/DbValue.cpp @@ -0,0 +1,555 @@ +/* + * 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. + */ + + +// +// DbValue.cpp +// + +#include "DbValue.h" +#include + +// +// DbValue +// + +DbValue::~DbValue() +{ +} + +// +// UInt32Value +// + +UInt32Value::UInt32Value(const ReadSection &rs, uint32 &offset) +: BasicValue(rs.at(offset)) +{ + offset += size(); +} + +UInt32Value::UInt32Value(const CSSM_DATA &data) +{ + switch (data.Length) + { + case 1: + mValue = *reinterpret_cast(data.Data); + break; + case 2: + mValue = *reinterpret_cast(data.Data); + break; + case 4: + mValue = *reinterpret_cast(data.Data); + break; + default: + CssmError::throwMe(CSSMERR_DL_INVALID_VALUE); + } +} + +UInt32Value::~UInt32Value() +{ +} + +void +UInt32Value::pack(WriteSection &ws, uint32 &offset) const +{ + offset = ws.put(offset, mValue); +} + +// +// SInt32Value +// + +SInt32Value::SInt32Value(const ReadSection &rs, uint32 &offset) +: BasicValue(static_cast(rs.at(offset))) +{ + offset += size(); +} + +SInt32Value::SInt32Value(const CSSM_DATA &data) +{ + switch (data.Length) + { + case 1: + mValue = *reinterpret_cast(data.Data); + break; + case 2: + mValue = *reinterpret_cast(data.Data); + break; + case 4: + mValue = *reinterpret_cast(data.Data); + break; + default: + CssmError::throwMe(CSSMERR_DL_INVALID_VALUE); + } +} + +SInt32Value::~SInt32Value() +{ +} + +void +SInt32Value::pack(WriteSection &ws, uint32 &offset) const +{ + offset = ws.put(offset, static_cast(mValue)); +} + +// +// DoubleValue +// + +DoubleValue::DoubleValue(const ReadSection &rs, uint32 &offset) +{ + Range r(offset, size()); + mValue = *reinterpret_cast(rs.range(r)); + offset += size(); +} + +DoubleValue::DoubleValue(const CSSM_DATA &data) +{ + switch (data.Length) + { + case 4: + mValue = *reinterpret_cast(data.Data); + break; + case 8: + mValue = *reinterpret_cast(data.Data); + break; + default: + CssmError::throwMe(CSSMERR_DL_INVALID_VALUE); + } +} + +DoubleValue::~DoubleValue() +{ +} + +void +DoubleValue::pack(WriteSection &ws, uint32 &offset) const +{ + offset = ws.put(offset, size(), bytes()); +} + +// +// BlobValue +// + +BlobValue::BlobValue(const ReadSection &rs, uint32 &offset) +{ + Length = rs.at(offset); + Data = const_cast(rs.range(Range(offset + AtomSize, Length))); + offset = ReadSection::align(offset + Length + AtomSize); +} + +BlobValue::BlobValue(const CSSM_DATA &data) +: CssmData(CssmData::overlay(data)) +{ +} + +BlobValue::~BlobValue() +{ +} + +void +BlobValue::pack(WriteSection &ws, uint32 &offset) const +{ + offset = ws.put(offset, Length); + offset = ws.put(offset, Length, Data); +} + +BlobValue::Comparator::~Comparator() +{ +} + +int +BlobValue::Comparator::operator () (const uint8 *ptr1, const uint8 *ptr2, uint32 length) +{ + return memcmp(ptr1, ptr2, length); +} + +bool +BlobValue::evaluate(const BlobValue &other, CSSM_DB_OPERATOR op) const +{ + return evaluate(*this, other, op, Comparator()); +} + +bool +BlobValue::evaluate(const CssmData &inData1, const CssmData &inData2, CSSM_DB_OPERATOR op, + Comparator compare) +{ + uint32 length1 = inData1.Length, length2 = inData2.Length; + const uint8 *data1 = inData1.Data; + const uint8 *data2 = inData2.Data; + + switch (op) { + + case CSSM_DB_CONTAINS_INITIAL_SUBSTRING: + if (length1 > length2) + return false; + length2 = length1; + goto DB_EQUAL; + + case CSSM_DB_CONTAINS_FINAL_SUBSTRING: + if (length1 > length2) + return false; + data2 += (length2 - length1); + length2 = length1; + // dropthrough... + + case CSSM_DB_EQUAL: + DB_EQUAL: + if (length1 != length2) + return false; + if (length1 == 0) + return true; + return compare(data1, data2, length1) == 0; + + case CSSM_DB_NOT_EQUAL: + if (length1 != length2) + return true; + if (length1 == 0) + return false; + return compare(data1, data2, length1) != 0; + + case CSSM_DB_LESS_THAN: + case CSSM_DB_GREATER_THAN: + { + uint32 length = min(length1, length2); + int result = (length == 0) ? 0 : compare(data1, data2, length); + + if (result < 0 || (result == 0 && length1 < length2)) + return op == CSSM_DB_LESS_THAN; + else if (result > 0 || (result == 0 && length1 > length2)) + return op == CSSM_DB_GREATER_THAN; + break; + } + + case CSSM_DB_CONTAINS: + if (length1 > length2) + return false; + if (length1 == 0) + return true; + // Both buffers are at least 1 byte long. + for (const uint8 *data = data2; data + length1 <= data2 + length2; data++) + if (compare(data1, data, length1) == 0) + return true; + break; + + default: + CssmError::throwMe(CSSMERR_DL_UNSUPPORTED_QUERY); + } + + return false; +} + +// +// TimeDateValue +// + +TimeDateValue::TimeDateValue(const ReadSection &rs, uint32 &offset) +{ + Length = kTimeDateSize; + Data = const_cast(rs.range(Range(offset, Length))); + offset = ReadSection::align(offset + Length); +} + +TimeDateValue::TimeDateValue(const CSSM_DATA &data) +: BlobValue(data) +{ + if (Length != kTimeDateSize || !isValidDate()) + CssmError::throwMe(CSSMERR_DL_INVALID_VALUE); +} + +TimeDateValue::~TimeDateValue() +{ +} + +void +TimeDateValue::pack(WriteSection &ws, uint32 &offset) const +{ + offset = ws.put(offset, Length, Data); +} + +bool +TimeDateValue::isValidDate() const +{ + if (Length != kTimeDateSize || Data[kTimeDateSize - 1] != 0 || + Data[kTimeDateSize - 2] != 'Z') + return false; + + for (uint32 i = 0; i < kTimeDateSize - 2; i++) + if (!isdigit(Data[i])) + return false; + + uint32 month = rangeValue(4, 2); + if (month < 1 || month > 12) + return false; + + uint32 day = rangeValue(6, 2); + if (day < 1 || day > 31) + return false; + + uint32 hour = rangeValue(8, 2); + if (hour < 0 || hour > 23) + return false; + + uint32 minute = rangeValue(10, 2); + if (minute < 0 || minute > 59) + return false; + + uint32 second = rangeValue(12, 2); + if (second < 0 || second > 59) + return false; + + return true; +} + +uint32 +TimeDateValue::rangeValue(uint32 start, uint32 length) const +{ + uint32 value = 0; + for (uint32 i = 0; i < length; i++) + value = value * 10 + Data[start + i] - '0'; + return value; +} + +// +// StringValue +// + +StringValue::StringValue(const ReadSection &rs, uint32 &offset) +: BlobValue(rs, offset) +{ +} + +StringValue::StringValue(const CSSM_DATA &data) +: BlobValue(data) +{ +} + +StringValue::~StringValue() +{ +} + +int +StringValue::Comparator::operator () (const uint8 *ptr1, const uint8 *ptr2, uint32 length) +{ + return strncmp(reinterpret_cast(ptr1), + reinterpret_cast(ptr2), length); +} + +bool +StringValue::evaluate(const StringValue &other, CSSM_DB_OPERATOR op) const +{ + return BlobValue::evaluate(*this, other, op, StringValue::Comparator()); +} + +// +// BigNumValue +// + +BigNumValue::BigNumValue(const ReadSection &rs, uint32 &offset) +: BlobValue(rs, offset) +{ +} + +BigNumValue::BigNumValue(const CSSM_DATA &data) +: BlobValue(data) +{ + // remove trailing zero bytes + while (Length > 1 && Data[Length - 1] == 0) + Length--; + + // if the number is zero (positive or negative), make the length zero + if (Length == 1 && (Data[0] & ~kSignBit) == 0) + Length = 0; +} + +BigNumValue::~BigNumValue() +{ +} + +// Walk the contents of two equal-sized bignums, moving backward +// from the high-order bytes, and return the comparison result +// ala memcmp. + +int +BigNumValue::compare(const uint8 *a, const uint8 *b, int length) +{ + for (int diff, i = length - 1; i >= 1; i--) + if ((diff = a[i] - b[i])) + return diff; + + // for the last (i.e. first) byte, mask out the sign bit + return (a[0] & ~kSignBit) - (b[0] & ~kSignBit); +} + +// Compare two bignums, assuming they are in canonical form (i.e., +// no bytes containing trailing zeros. + +bool +BigNumValue::evaluate(const BigNumValue &other, CSSM_DB_OPERATOR op) const +{ + uint32 length1 = Length, length2 = other.Length; + uint8 sign1 = length1 ? (Data[0] & kSignBit) : 0; + uint8 sign2 = length2 ? (other.Data[0] & kSignBit) : 0; + + switch (op) + { + case CSSM_DB_EQUAL: + case CSSM_DB_NOT_EQUAL: + return BlobValue::evaluate(other, op); + + case CSSM_DB_LESS_THAN: + if (sign1 ^ sign2) + // different signs: return true iff left value is the negative one + return sign1; + else if (length1 != length2) + // in canonical form, shorter numbers have smaller absolute value + return sign1 ? (length1 > length2) : (length1 < length2); + else { + // same length, same sign... + int c = compare(Data, other.Data, length1); + return sign1 ? (c > 0) : (c < 0); + } + break; + + case CSSM_DB_GREATER_THAN: + if (sign1 ^ sign2) + return sign2; + else if (length1 != length2) + return sign1 ? (length1 < length2) : (length1 > length2); + else { + int c = compare(Data, other.Data, length1); + return sign1 ? (c < 0) : (c > 0); + } + break; + + case CSSM_DB_CONTAINS: + case CSSM_DB_CONTAINS_INITIAL_SUBSTRING: + case CSSM_DB_CONTAINS_FINAL_SUBSTRING: + default: + CssmError::throwMe(CSSMERR_DL_UNSUPPORTED_QUERY); + } +} + +// +// MultiUInt32Value +// + +MultiUInt32Value::MultiUInt32Value(const ReadSection &rs, uint32 &offset) +{ + // this is relatively expensive, since it copies the data from the + // read section to get the endianness correct + + mNumValues = rs.at(offset); + mValues = new uint32[mNumValues]; + + for (uint32 i = 0; i < mNumValues; i++) + mValues[i] = rs.at(offset + (i + 1) * AtomSize); + + offset = ReadSection::align(offset + (mNumValues + 1) * AtomSize); + mOwnsValues = true; +} + +MultiUInt32Value::MultiUInt32Value(const CSSM_DATA &data) +{ + if (data.Length & (sizeof(uint32) - 1)) + CssmError::throwMe(CSSMERR_DL_INVALID_VALUE); + + mNumValues = data.Length / sizeof(uint32); + mValues = reinterpret_cast(data.Data); + mOwnsValues = false; +} + +MultiUInt32Value::~MultiUInt32Value() +{ + if (mOwnsValues) + delete [] mValues; +} + +void +MultiUInt32Value::pack(WriteSection &ws, uint32 &offset) const +{ + offset = ws.put(offset, mNumValues); + for (uint32 i = 0; i < mNumValues; i++) + offset = ws.put(offset, mValues[i]); +} + +static inline int +uint32cmp(const uint32 *a, const uint32 *b, uint32 length) +{ + return memcmp(a, b, length * sizeof(uint32)); +} + +bool +MultiUInt32Value::evaluate(const MultiUInt32Value &other, CSSM_DB_OPERATOR op) const +{ + uint32 length1 = mNumValues, length2 = other.mNumValues; + const uint32 *values1 = mValues; + const uint32 *values2 = other.mValues; + + switch (op) + { + case CSSM_DB_EQUAL: + if (length1 == length2) + return uint32cmp(values1, values2, length1) == 0; + break; + + case CSSM_DB_NOT_EQUAL: + if (length1 != length2 || uint32cmp(values1, values2, length1)) + return true; + break; + + case CSSM_DB_CONTAINS_INITIAL_SUBSTRING: + if (length1 <= length2) + return uint32cmp(values1, values2, length1) == 0; + break; + + case CSSM_DB_CONTAINS_FINAL_SUBSTRING: + if (length1 <= length2) + return uint32cmp(values1, values2 + (length2 - length1), length1) == 0; + break; + + case CSSM_DB_CONTAINS: + if (length1 <= length2) { + + if (length1 == 0) + return true; + + for (const uint32 *values = values2; values + length1 < values2 + length2; values++) + if (uint32cmp(values1, values, length1) == 0) + return true; + } + break; + + case CSSM_DB_LESS_THAN: + // this is not required by the spec, but is required to sort indexes over + // multi uint32 keys... + if (length1 < length2) + return true; + else if (length1 == length2) + return uint32cmp(values1, values2, length1) < 0; + break; + + default: + CssmError::throwMe(CSSMERR_DL_UNSUPPORTED_QUERY); + } + + return false; +} + + diff --git a/libsecurity_filedb/lib/DbValue.h b/libsecurity_filedb/lib/DbValue.h new file mode 100644 index 00000000..b4580d6c --- /dev/null +++ b/libsecurity_filedb/lib/DbValue.h @@ -0,0 +1,213 @@ +/* + * 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. + */ + + +// +// DbValue.h +// + +#ifndef _H_APPLEDL_DBVALUE +#define _H_APPLEDL_DBVALUE + +#include "ReadWriteSection.h" + +#include +#include +#include +#include +#include + +namespace Security +{ + +// +// DbValue -- A base class for all types of database values. +// +class DbValue +{ +public: + virtual ~DbValue(); +}; + +// A collection of subclasses of DbValue that work for simple +// data types, e.g. uint32, sint32, and double, that have +// the usual C comparison and sizeof operations. Defining this +// template saves typing below. + +template +class BasicValue : public DbValue +{ +public: + BasicValue() {} + BasicValue(T value) : mValue(value) {} + + bool evaluate(const BasicValue &other, CSSM_DB_OPERATOR op) const + { + switch (op) { + + case CSSM_DB_EQUAL: + return mValue == other.mValue; + + case CSSM_DB_NOT_EQUAL: + return mValue != other.mValue; + + case CSSM_DB_LESS_THAN: + return mValue < other.mValue; + + case CSSM_DB_GREATER_THAN: + return mValue > other.mValue; + + default: + CssmError::throwMe(CSSMERR_DL_UNSUPPORTED_QUERY); + return false; + } + } + + size_t size() const { return sizeof(T); } + size_t size(const ReadSection &rs, uint32 offset) const { return size(); } + const uint8 *bytes() const { return reinterpret_cast(&mValue); } + +protected: + T mValue; +}; + +// Actual useful subclasses of DbValue as instances of BasicValue. +// Note that all of these require a constructor of the form +// (const ReadSection &, uint32 &offset) that advances the offset +// to just after the value. + +class UInt32Value : public BasicValue +{ +public: + UInt32Value(const ReadSection &rs, uint32 &offset); + UInt32Value(const CSSM_DATA &data); + virtual ~UInt32Value(); + void pack(WriteSection &ws, uint32 &offset) const; +}; + +class SInt32Value : public BasicValue +{ +public: + SInt32Value(const ReadSection &rs, uint32 &offset); + SInt32Value(const CSSM_DATA &data); + virtual ~SInt32Value(); + void pack(WriteSection &ws, uint32 &offset) const; +}; + +class DoubleValue : public BasicValue +{ +public: + DoubleValue(const ReadSection &rs, uint32 &offset); + DoubleValue(const CSSM_DATA &data); + virtual ~DoubleValue(); + void pack(WriteSection &ws, uint32 &offset) const; +}; + +// Subclasses of Value for more complex types. + +class BlobValue : public DbValue, public CssmData +{ +public: + BlobValue() {} + BlobValue(const ReadSection &rs, uint32 &offset); + BlobValue(const CSSM_DATA &data); + virtual ~BlobValue(); + void pack(WriteSection &ws, uint32 &offset) const; + bool evaluate(const BlobValue &other, CSSM_DB_OPERATOR op) const; + + size_t size() const { return Length; } + const uint8 *bytes() const { return Data; } + +protected: + class Comparator { + public: + virtual ~Comparator(); + virtual int operator () (const uint8 *ptr1, const uint8 *ptr2, uint32 length); + }; + + static bool evaluate(const CssmData &data1, const CssmData &data2, CSSM_DB_OPERATOR op, + Comparator compare); +}; + +class TimeDateValue : public BlobValue +{ +public: + enum { kTimeDateSize = 16 }; + + TimeDateValue(const ReadSection &rs, uint32 &offset); + TimeDateValue(const CSSM_DATA &data); + virtual ~TimeDateValue(); + void pack(WriteSection &ws, uint32 &offset) const; + + bool isValidDate() const; + +private: + uint32 rangeValue(uint32 start, uint32 length) const; +}; + +class StringValue : public BlobValue +{ +public: + StringValue(const ReadSection &rs, uint32 &offset); + StringValue(const CSSM_DATA &data); + virtual ~StringValue(); + bool evaluate(const StringValue &other, CSSM_DB_OPERATOR op) const; + +private: + class Comparator : public BlobValue::Comparator { + public: + virtual int operator () (const uint8 *ptr1, const uint8 *ptr2, uint32 length); + }; + +}; + +class BigNumValue : public BlobValue +{ +public: + static const uint8 kSignBit = 0x80; + + BigNumValue(const ReadSection &rs, uint32 &offset); + BigNumValue(const CSSM_DATA &data); + virtual ~BigNumValue(); + bool evaluate(const BigNumValue &other, CSSM_DB_OPERATOR op) const; + +private: + static int compare(const uint8 *a, const uint8 *b, int length); +}; + +class MultiUInt32Value : public DbValue +{ +public: + MultiUInt32Value(const ReadSection &rs, uint32 &offset); + MultiUInt32Value(const CSSM_DATA &data); + virtual ~MultiUInt32Value(); + void pack(WriteSection &ws, uint32 &offset) const; + bool evaluate(const MultiUInt32Value &other, CSSM_DB_OPERATOR op) const; + + size_t size() const { return mNumValues * sizeof(uint32); } + const uint8 *bytes() const { return reinterpret_cast(mValues); } + +private: + uint32 mNumValues; + uint32 *mValues; + bool mOwnsValues; +}; + +} // end namespace Security + +#endif // _H_APPLEDL_DBVALUE + diff --git a/libsecurity_filedb/lib/MetaAttribute.cpp b/libsecurity_filedb/lib/MetaAttribute.cpp new file mode 100644 index 00000000..7d8c1ab4 --- /dev/null +++ b/libsecurity_filedb/lib/MetaAttribute.cpp @@ -0,0 +1,158 @@ +/* + * 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. + */ + + +// +// MetaAttribute.cpp +// + +#include "MetaAttribute.h" +#include "MetaRecord.h" + +MetaAttribute::~MetaAttribute() +{ +} + +// Construct an instance of an appropriate subclass of MetaAttribute +// based on the given format. + +MetaAttribute * +MetaAttribute::create(Format format, uint32 attributeIndex, + uint32 attributeId) +{ + switch (format) + { + case CSSM_DB_ATTRIBUTE_FORMAT_STRING: + return new TypedMetaAttribute(format, attributeIndex, attributeId); + + case CSSM_DB_ATTRIBUTE_FORMAT_SINT32: + return new TypedMetaAttribute(format, attributeIndex, attributeId); + + case CSSM_DB_ATTRIBUTE_FORMAT_UINT32: + return new TypedMetaAttribute(format, attributeIndex, attributeId); + + case CSSM_DB_ATTRIBUTE_FORMAT_BIG_NUM: + return new TypedMetaAttribute(format, attributeIndex, attributeId); + + case CSSM_DB_ATTRIBUTE_FORMAT_REAL: + return new TypedMetaAttribute(format, attributeIndex, attributeId); + + case CSSM_DB_ATTRIBUTE_FORMAT_TIME_DATE: + return new TypedMetaAttribute(format, attributeIndex, attributeId); + + case CSSM_DB_ATTRIBUTE_FORMAT_BLOB: + return new TypedMetaAttribute(format, attributeIndex, attributeId); + + case CSSM_DB_ATTRIBUTE_FORMAT_MULTI_UINT32: + return new TypedMetaAttribute(format, attributeIndex, attributeId); + + case CSSM_DB_ATTRIBUTE_FORMAT_COMPLEX: + default: + CssmError::throwMe(CSSMERR_DL_UNSUPPORTED_FIELD_FORMAT); + } +} + +void +MetaAttribute::packNumberOfValues(WriteSection &ws, uint32 numValues, uint32 &valueOffset) const +{ + uint32 offset = MetaRecord::OffsetAttributeOffsets + mAttributeIndex * AtomSize; + + if (numValues == 0) { + // a zero offset means the attribute has no values + ws.put(offset, 0); + } + else if (numValues == 1) { + // setting the low bit of the offset means that there is exactly one value + ws.put(offset, valueOffset | 1); + } + else { + // write the offset, then write the number of values at that position + ws.put(offset, valueOffset); + valueOffset = ws.put(valueOffset, numValues); + } +} + +void +MetaAttribute::unpackNumberOfValues(const ReadSection &rs, uint32 &numValues, + uint32 &valueOffset) const +{ + uint32 offset = MetaRecord::OffsetAttributeOffsets + mAttributeIndex * AtomSize; + valueOffset = rs[offset]; + + if (valueOffset == 0) + // a zero offset means no values + numValues = 0; + else if (valueOffset & 1) { + // setting the LSB means exactly one value + valueOffset ^= 1; + numValues = 1; + } + else { + // otherwise, the number of values is at the offset, and the values follow + numValues = rs[valueOffset]; + valueOffset += AtomSize; + } +} + +void +MetaAttribute::packAttribute(WriteSection &ws, uint32 &valueOffset, uint32 numValues, + const CSSM_DATA *values) const +{ + packNumberOfValues(ws, numValues, valueOffset); + for (uint32 i = 0; i < numValues; i++) + packValue(ws, valueOffset, values[i]); +} + +void +MetaAttribute::unpackAttribute(const ReadSection &rs, Allocator &allocator, + uint32 &numValues, CSSM_DATA *&values) const +{ + uint32 valueOffset; + unpackNumberOfValues(rs, numValues, valueOffset); + + // Rough check for number of values; will be more like 10 or 20 + if (numValues > 1024) + CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT); + + values = reinterpret_cast(allocator.malloc(numValues * sizeof(CSSM_DATA))); + + for (uint32 i = 0; i < numValues; i++) + unpackValue(rs, valueOffset, values[i], allocator); +} + +uint32 +MetaAttribute::getNumberOfValues(const ReadSection &rs) const +{ + uint32 numValues, valueOffset; + unpackNumberOfValues(rs, numValues, valueOffset); + return numValues; +} + +void +MetaAttribute::copyValueBytes(uint32 valueIndex, const ReadSection &rs, WriteSection &ws, + uint32 &writeOffset) const +{ + uint32 numValues, valueOffset; + unpackNumberOfValues(rs, numValues, valueOffset); + + // skip bytes before the desired value + for (uint32 i = 0; i < valueIndex; i++) + skipValue(rs, valueOffset); + + // copy the value bytes into the write section + copyValue(rs, valueOffset, ws, writeOffset); +} diff --git a/libsecurity_filedb/lib/MetaAttribute.h b/libsecurity_filedb/lib/MetaAttribute.h new file mode 100644 index 00000000..2e61d2ed --- /dev/null +++ b/libsecurity_filedb/lib/MetaAttribute.h @@ -0,0 +1,162 @@ +/* + * 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. + */ + + +// +// MetaAttribute.h +// + +#ifndef _H_APPLEDL_METAATTRIBUTE +#define _H_APPLEDL_METAATTRIBUTE + +#include "DbValue.h" +#include + +namespace Security +{ + +// A base class for all meta attributes. + +class MetaAttribute +{ +public: + typedef CSSM_DB_ATTRIBUTE_FORMAT Format; + + virtual ~MetaAttribute(); + + // construct an appropriate subclass of MetaAttribute + static MetaAttribute *create(Format format, uint32 attributeIndex, + uint32 attributeId); + + Format attributeFormat() const { return mFormat; } + uint32 attributeIndex() const { return mAttributeIndex; } + uint32 attributeId() const { return mAttributeId; } + + void packAttribute(WriteSection &ws, uint32 &valueOffset, + uint32 numValues, const CSSM_DATA *values) const; + void unpackAttribute(const ReadSection &rs, Allocator &allocator, + uint32 &numValues, CSSM_DATA *&values) const; + + uint32 getNumberOfValues(const ReadSection &rs) const; + void copyValueBytes(uint32 valueIndex, const ReadSection &rs, WriteSection &ws, + uint32 &writeOffset) const; + + // interface required of all subclasses, implemented with templates below + virtual DbValue *createValue(const CSSM_DATA &data) const = 0; + virtual DbValue *createValue(const ReadSection &rs, uint32 &offset) const = 0; + virtual void packValue(WriteSection &ws, uint32 &offset, const CSSM_DATA &data) const = 0; + virtual void unpackValue(const ReadSection &rs, uint32 &offset, CSSM_DATA &data, + Allocator &allocator) const = 0; + virtual void skipValue(const ReadSection &rs, uint32 &offset) const = 0; + virtual void copyValue(const ReadSection &rs, uint32 &readOffset, WriteSection &ws, + uint32 &writeOffset) const = 0; + virtual bool evaluate(const DbValue *value, const ReadSection &rs, CSSM_DB_OPERATOR op) const = 0; + virtual bool evaluate(const DbValue *value1, const DbValue *value2, CSSM_DB_OPERATOR op) const = 0; + virtual uint32 parse(const CssmData &inData, CSSM_DATA_PTR &outValues) const = 0; + +protected: + MetaAttribute(Format format, uint32 attributeIndex, uint32 attributeId) + : mFormat(format), mAttributeIndex(attributeIndex), mAttributeId(attributeId) {} + + void packNumberOfValues(WriteSection &ws, uint32 numValues, uint32 &valueOffset) const; + void unpackNumberOfValues(const ReadSection &rs, uint32 &numValues, uint32 &valueOffset) const; + + Format mFormat; + uint32 mAttributeIndex; + uint32 mAttributeId; +}; + +// Template used to describe particular subclasses of MetaAttribute + +template +class TypedMetaAttribute : public MetaAttribute +{ +public: + TypedMetaAttribute(Format format, uint32 attributeIndex, uint32 attributeId) + : MetaAttribute(format, attributeIndex, attributeId) {} + + DbValue *createValue(const CSSM_DATA &data) const + { + return new T(data); + } + + DbValue *createValue(const ReadSection &rs, uint32 &offset) const + { + return new T(rs, offset); + } + + void packValue(WriteSection &ws, uint32 &offset, const CSSM_DATA &data) const + { + T value(data); + value.pack(ws, offset); + } + + void unpackValue(const ReadSection &rs, uint32 &offset, CSSM_DATA &data, Allocator &allocator) const + { + T value(rs, offset); + data.Length = value.size(); + + if (data.Length != 0) + { + data.Data = reinterpret_cast(allocator.malloc(data.Length)); + memcpy(data.Data, value.bytes(), data.Length); + } + else + { + data.Data = NULL; + } + } + + void skipValue(const ReadSection &rs, uint32 &offset) const + { + T value(rs, offset); + } + + void copyValue(const ReadSection &rs, uint32 &readOffset, WriteSection &ws, uint32 &writeOffset) const + { + T value(rs, readOffset); + value.pack(ws, writeOffset); + } + + bool evaluate(const DbValue *value, const ReadSection &rs, CSSM_DB_OPERATOR op) const + { + uint32 offset, numValues; + unpackNumberOfValues(rs, numValues, offset); + + /* If any of the values for this attribute match we have a + match. This is the same behaviour that indexes have. */ + for (uint32 ix = 0; ix < numValues; ++ix) + if (dynamic_cast(value)->evaluate(T(rs, offset), op)) + return true; + + return false; + } + + bool evaluate(const DbValue *value1, const DbValue *value2, CSSM_DB_OPERATOR op) const + { + return (dynamic_cast(value1))->evaluate(*dynamic_cast(value2), op); + } + + uint32 parse(const CssmData &inData, CSSM_DATA_PTR &outValues) const + { + return 0; + } +}; + +} // end namespace Security + +#endif // _H_APPLEDL_METAATTRIBUTE diff --git a/libsecurity_filedb/lib/MetaRecord.cpp b/libsecurity_filedb/lib/MetaRecord.cpp new file mode 100644 index 00000000..d5ee1be4 --- /dev/null +++ b/libsecurity_filedb/lib/MetaRecord.cpp @@ -0,0 +1,580 @@ +/* + * 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. + */ + + +// +// MetaRecord.cpp +// + +#include "MetaRecord.h" +#include +#include + + +MetaRecord::MetaRecord(CSSM_DB_RECORDTYPE inRecordType) : + mRecordType(inRecordType) +{ +} + +MetaRecord::MetaRecord(const CSSM_DB_RECORD_ATTRIBUTE_INFO &inInfo) +: mRecordType(inInfo.DataRecordType) +{ + try + { + setRecordAttributeInfo(inInfo); + } + catch (...) + { + for_each_delete(mAttributeVector.begin(), mAttributeVector.end()); + } +} + +MetaRecord::MetaRecord(CSSM_DB_RECORDTYPE inRelationID, + uint32 inNumberOfAttributes, + const CSSM_DB_SCHEMA_ATTRIBUTE_INFO *inAttributeInfo) : + mRecordType(inRelationID) +{ + try { + for (uint32 anIndex = 0; anIndex < inNumberOfAttributes; anIndex++) + { + string aName; + if (inAttributeInfo[anIndex].AttributeName) + aName = string(inAttributeInfo[anIndex].AttributeName); + + const CssmData *aNameID = NULL; + if (inAttributeInfo[anIndex].AttributeNameID.Length > 0) + aNameID = &CssmData::overlay(inAttributeInfo[anIndex].AttributeNameID); + + uint32 aNumber = inAttributeInfo[anIndex].AttributeId; + createAttribute( + inAttributeInfo[anIndex].AttributeName ? &aName : NULL, + aNameID, aNumber, + inAttributeInfo[anIndex].DataType); + } + } + catch (...) + { + for_each_delete(mAttributeVector.begin(), mAttributeVector.end()); + } +} + +MetaRecord::~MetaRecord() +{ + // for_each_delete(mAttributeVector.begin(), mAttributeVector.end()); + AttributeVector::iterator it = mAttributeVector.begin(); + while (it != mAttributeVector.end()) + { + MetaAttribute* mat = *it++; + if (mat != NULL) + { + delete mat; + } + } +} + +void +MetaRecord::setRecordAttributeInfo(const CSSM_DB_RECORD_ATTRIBUTE_INFO &inInfo) +{ + for (uint32 anIndex = 0; anIndex < inInfo.NumberOfAttributes; anIndex++) + { + switch (inInfo.AttributeInfo[anIndex].AttributeNameFormat) + { + case CSSM_DB_ATTRIBUTE_NAME_AS_STRING: + { + string aName(inInfo.AttributeInfo[anIndex].Label.AttributeName); + createAttribute(&aName, nil, anIndex, + inInfo.AttributeInfo[anIndex].AttributeFormat); + break; + } + case CSSM_DB_ATTRIBUTE_NAME_AS_OID: + { + const CssmData &aNameID = CssmOid::overlay(inInfo.AttributeInfo[anIndex].Label.AttributeOID); + createAttribute(nil, &aNameID, anIndex, + inInfo.AttributeInfo[anIndex].AttributeFormat); + break; + } + case CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER: + { + uint32 aNumber = inInfo.AttributeInfo[anIndex].Label.AttributeID; + createAttribute(nil, nil, aNumber, + inInfo.AttributeInfo[anIndex].AttributeFormat); + break; + } + default: + CssmError::throwMe(CSSMERR_DL_INVALID_FIELD_NAME); + break; + } + } +} + +void +MetaRecord::createAttribute(const string *inAttributeName, + const CssmOid *inAttributeOID, + uint32 inAttributeID, + CSSM_DB_ATTRIBUTE_FORMAT inAttributeFormat) +{ + // Index of new element is current size of vector + uint32 anAttributeIndex = mAttributeVector.size(); + bool aInsertedAttributeName = false; + bool aInsertedAttributeOID = false; + bool aInsertedAttributeID = false; + + if (inAttributeName) + { + if (!mNameStringMap.insert(NameStringMap::value_type(*inAttributeName, anAttributeIndex)).second) + CssmError::throwMe(CSSMERR_DL_FIELD_SPECIFIED_MULTIPLE); + aInsertedAttributeName = true; + } + try + { + if (inAttributeOID) + { + if (!mNameOIDMap.insert(NameOIDMap::value_type(*inAttributeOID, anAttributeIndex)).second) + CssmError::throwMe(CSSMERR_DL_FIELD_SPECIFIED_MULTIPLE); + aInsertedAttributeOID = true; + } + + if (!mNameIntMap.insert(NameIntMap::value_type(inAttributeID, anAttributeIndex)).second) + CssmError::throwMe(CSSMERR_DL_FIELD_SPECIFIED_MULTIPLE); + aInsertedAttributeID = true; + + // Note: this no longer throws INVALID_FIELD_NAME since the attribute will always have + // an attribute ID by which it is known + + mAttributeVector.push_back(MetaAttribute::create(inAttributeFormat, + anAttributeIndex, inAttributeID)); + } + catch(...) + { + if (aInsertedAttributeName) + mNameStringMap.erase(*inAttributeName); + if (aInsertedAttributeOID) + mNameOIDMap.erase(*inAttributeOID); + if (inAttributeID) + mNameIntMap.erase(inAttributeID); + + throw; + } +} + + +// Create a packed record from the given inputs. +void +MetaRecord::packRecord(WriteSection &inWriteSection, + const CSSM_DB_RECORD_ATTRIBUTE_DATA *inAttributes, + const CssmData *inData) const +{ + uint32 aDataSize; + if (inData) + aDataSize = inData->Length; + else + aDataSize = 0; + + inWriteSection.put(OffsetDataSize, aDataSize); + uint32 anOffset = OffsetAttributeOffsets + AtomSize * mAttributeVector.size(); + if (aDataSize) + anOffset = inWriteSection.put(anOffset, aDataSize, inData->Data); + + vector aNumValues(mAttributeVector.size(), ~(uint32)0); + vector aValues(mAttributeVector.size()); + uint32 anIndex; + + if (inAttributes == NULL) + inWriteSection.put(OffsetSemanticInformation, 0); + else + { + inWriteSection.put(OffsetSemanticInformation, inAttributes->SemanticInformation); + + // Put the supplied attribute values into the list of attributes + // and values. + anIndex = inAttributes->NumberOfAttributes; + // Make sure that AttributeData is a valid array. + if (anIndex > 0) + Required(inAttributes->AttributeData); + + while (anIndex-- > 0) + { + CSSM_DB_ATTRIBUTE_DATA &anAttribute = inAttributes->AttributeData[anIndex]; + uint32 anAttributeIndex = attributeIndex(anAttribute.Info); + // Make sure that the caller specified the attribute values in the correct format. + if (anAttribute.Info.AttributeFormat != mAttributeVector[anAttributeIndex]->attributeFormat()) + CssmError::throwMe(CSSMERR_DL_INCOMPATIBLE_FIELD_FORMAT); + + // If this attribute was specified before, throw. + if (aNumValues[anAttributeIndex] != ~(uint32)0) + CssmError::throwMe(CSSMERR_DL_FIELD_SPECIFIED_MULTIPLE); + + aNumValues[anAttributeIndex] = anAttribute.NumberOfValues; + aValues[anAttributeIndex] = anAttribute.Value; + } + } + + for (anIndex = 0; anIndex < mAttributeVector.size(); ++anIndex) + { + const MetaAttribute &aMetaAttribute = *mAttributeVector[anIndex]; + uint32 aNumberOfValues = aNumValues[anIndex]; + // Now call the parsingmodule for each attribute that + // wasn't explicitly specified and that has a parsingmodule. + if (aNumberOfValues == ~(uint32)0) + aNumberOfValues = aDataSize == 0 ? 0 : aMetaAttribute.parse(*inData, aValues[anIndex]); + + // XXX When do we throw CSSMERR_DL_MISSING_VALUE? Maybe if an + // attribute is part of a unique index. + + // Now we have a valuelist for this attribute. Let's encode it. + aMetaAttribute.packAttribute(inWriteSection, anOffset, aNumberOfValues, aValues[anIndex]); + } + + inWriteSection.put(OffsetRecordSize, anOffset); + inWriteSection.size(anOffset); +} + +inline void +MetaRecord::unpackAttribute(const ReadSection &inReadSection, + Allocator &inAllocator, + CSSM_DB_ATTRIBUTE_DATA &inoutAttribute) const +{ + const MetaAttribute &aMetaAttribute = metaAttribute(inoutAttribute.Info); + // XXX: See ISSUES on whether AttributeFormat should be an outputvalue or not. + inoutAttribute.Info.AttributeFormat = aMetaAttribute.attributeFormat(); + aMetaAttribute.unpackAttribute(inReadSection, inAllocator, + inoutAttribute.NumberOfValues, + inoutAttribute.Value); +} + +void +MetaRecord::unpackRecord(const ReadSection &inReadSection, + Allocator &inAllocator, + CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR inoutAttributes, + CssmData *inoutData, + CSSM_QUERY_FLAGS inQueryFlags) const +{ + // XXX Use POD wrapper for inoutAttributes here. + TrackingAllocator anAllocator(inAllocator); + + try + { + if (inoutData) + { + // XXX Treat KEY records specially. + + // If inQueryFlags & CSSM_QUERY_RETURN_DATA is true return the raw + // key bits in the CSSM_KEY structure + Range aDataRange = dataRange(inReadSection); + inoutData->Length = aDataRange.mSize; + inoutData->Data = inReadSection.allocCopyRange(aDataRange, anAllocator); + } + + if (inoutAttributes) + { + inoutAttributes->DataRecordType = dataRecordType(); + inoutAttributes->SemanticInformation = semanticInformation(inReadSection); + uint32 anIndex = inoutAttributes->NumberOfAttributes; + + // Make sure that AttributeData is a valid array. + if (anIndex > 0 && inoutAttributes->AttributeData == NULL) + CssmError::throwMe(CSSM_ERRCODE_INVALID_POINTER); + + while (anIndex-- > 0) + { + unpackAttribute(inReadSection, anAllocator, + inoutAttributes->AttributeData[anIndex]); + } + } + } + catch (CssmError e) + { + if (e.osStatus() != CSSMERR_DL_DATABASE_CORRUPT) + { + // clear all pointers so that nothing dangles back to the user + if (inoutData) + { + inoutData->Data = NULL; + } + + if (inoutAttributes) + { + unsigned i; + for (i = 0; i < inoutAttributes->NumberOfAttributes; ++i) + { + CSSM_DB_ATTRIBUTE_DATA& data = inoutAttributes->AttributeData[i]; + + unsigned j; + for (j = 0; j < data.NumberOfValues; ++j) + { + data.Value[j].Data = NULL; + } + + data.Value = NULL; + + if (data.Info.AttributeNameFormat == CSSM_DB_ATTRIBUTE_NAME_AS_STRING) + { + data.Info.Label.AttributeName = NULL; + } + } + } + } + + throw; + } + catch (...) + { + // clear all pointers so that nothing dangles back to the user + if (inoutData) + { + inoutData->Data = NULL; + } + + if (inoutAttributes) + { + unsigned i; + for (i = 0; i < inoutAttributes->NumberOfAttributes; ++i) + { + CSSM_DB_ATTRIBUTE_DATA& data = inoutAttributes->AttributeData[i]; + + unsigned j; + for (j = 0; j < data.NumberOfValues; ++j) + { + data.Value[j].Data = NULL; + } + + data.Value = NULL; + + if (data.Info.AttributeNameFormat == CSSM_DB_ATTRIBUTE_NAME_AS_STRING) + { + data.Info.Label.AttributeName = NULL; + } + } + } + + throw; + } + + + // Don't free anything the trackingAllocator allocated when it is destructed. + anAllocator.commit(); +} + +// Return the index (0 though NumAttributes - 1) of the attribute +// represented by inAttributeInfo + +#ifndef NDEBUG +#define LOG_NAME_AS_STRING_FAIL +#endif +uint32 +MetaRecord::attributeIndex(const CSSM_DB_ATTRIBUTE_INFO &inAttributeInfo) const +{ + uint32 anIndex; + switch (inAttributeInfo.AttributeNameFormat) + { + case CSSM_DB_ATTRIBUTE_NAME_AS_STRING: + { + string aName(inAttributeInfo.Label.AttributeName); + assert(aName.size() < 500); // MDS leak debug + NameStringMap::const_iterator it = mNameStringMap.find(aName); + if (it == mNameStringMap.end()) { + #ifdef LOG_NAME_AS_STRING_FAIL + printf("NAME_AS_STRING failure; attrName %s\n", + inAttributeInfo.Label.AttributeName); + for(it = mNameStringMap.begin(); + it != mNameStringMap.end(); + it++) { + printf("name %s val %d\n", it->first.c_str(), it->second); + } + #endif + CssmError::throwMe(CSSMERR_DL_INVALID_FIELD_NAME); + } + anIndex = it->second; + break; + } + case CSSM_DB_ATTRIBUTE_NAME_AS_OID: + { + const CssmOid &aName = CssmOid::overlay(inAttributeInfo.Label.AttributeOID); + NameOIDMap::const_iterator it = mNameOIDMap.find(aName); + if (it == mNameOIDMap.end()) + CssmError::throwMe(CSSMERR_DL_INVALID_FIELD_NAME); + anIndex = it->second; + break; + } + case CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER: + { + uint32 aName = inAttributeInfo.Label.AttributeID; + NameIntMap::const_iterator it = mNameIntMap.find(aName); + if (it == mNameIntMap.end()) + CssmError::throwMe(CSSMERR_DL_INVALID_FIELD_NAME); + anIndex = it->second; + break; + } + default: + CssmError::throwMe(CSSMERR_DL_INVALID_FIELD_NAME); + break; + } + + return anIndex; +} + +const MetaAttribute & +MetaRecord::metaAttribute(const CSSM_DB_ATTRIBUTE_INFO &inAttributeInfo) const +{ + return *mAttributeVector[attributeIndex(inAttributeInfo)]; +} + +// Create a packed record from the given inputs and the old packed record inReadSection. +void +MetaRecord::updateRecord(const ReadSection &inReadSection, + WriteSection &inWriteSection, + const CssmDbRecordAttributeData *inAttributes, + const CssmData *inData, + CSSM_DB_MODIFY_MODE inModifyMode) const +{ + TrackingAllocator anAllocator(Allocator::standard()); + + // modify the opaque data associated with the record + + uint32 aDataSize; + const uint8 *aDataData = NULL; + + if (inData) + { + // prepare to write new data + aDataSize = inData->Length; + aDataData = inData->Data; + } + else + { + // prepare to copy old data + Range aDataRange = dataRange(inReadSection); + aDataSize = aDataRange.mSize; + if (aDataSize) + aDataData = inReadSection.range(aDataRange); + } + + // compute the data offset; this will keep a running total of the record size + uint32 anOffset = OffsetAttributeOffsets + AtomSize * mAttributeVector.size(); + + // write the appropriate data to the new record + inWriteSection.put(OffsetDataSize, aDataSize); + if (aDataSize) + anOffset = inWriteSection.put(anOffset, aDataSize, aDataData); + + // unpack the old attributes since some of them may need to be preserved + + auto_array attributeData(mAttributeVector.size()); + + for (uint32 anAttributeIndex = mAttributeVector.size(); anAttributeIndex-- > 0; ) + { + // unpack the old attribute data for this attribute index + const MetaAttribute &attribute = *mAttributeVector[anAttributeIndex]; + attribute.unpackAttribute(inReadSection, anAllocator, + attributeData[anAttributeIndex].NumberOfValues, + attributeData[anAttributeIndex].Value); + } + + // retrieve the currrent semantic information + + uint32 oldSemanticInformation = semanticInformation(inReadSection); + + // process each input attribute as necessary, based on the modification mode + + if (inAttributes == NULL) + { + // make sure the modification mode is NONE, otherwise it's an + // error accordining to the spec + if (inModifyMode != CSSM_DB_MODIFY_ATTRIBUTE_NONE) + CssmError::throwMe(CSSMERR_DL_INVALID_MODIFY_MODE); + } + + else { + + // modify the semantic information + + uint32 inSemanticInformation = inAttributes ? inAttributes->SemanticInformation : 0; + + if (inModifyMode == CSSM_DB_MODIFY_ATTRIBUTE_ADD) + oldSemanticInformation |= inSemanticInformation; + + else if (inModifyMode == CSSM_DB_MODIFY_ATTRIBUTE_DELETE) + oldSemanticInformation &= ~inSemanticInformation; + + else if (inModifyMode == CSSM_DB_MODIFY_ATTRIBUTE_REPLACE) + oldSemanticInformation = inSemanticInformation; + + uint32 anIndex = inAttributes->NumberOfAttributes; + if (anIndex > 0) + Required(inAttributes->AttributeData); + + // modify the attributes + + while (anIndex-- > 0) { + + const CssmDbAttributeData &anAttribute = inAttributes->at(anIndex); + uint32 anAttributeIndex = attributeIndex(anAttribute.info()); + if (anAttribute.format() != mAttributeVector[anAttributeIndex]->attributeFormat()) + CssmError::throwMe(CSSMERR_DL_INCOMPATIBLE_FIELD_FORMAT); + + CssmDbAttributeData &oldAttribute = attributeData[anAttributeIndex]; + + // if the modify mode is ADD, merge new values with pre-existing values + + if (inModifyMode == CSSM_DB_MODIFY_ATTRIBUTE_ADD) + oldAttribute.add(anAttribute, anAllocator); + + // if the modify mode is DELETE, remove the indicated values, or remove + // all values if none are specified + + else if (inModifyMode == CSSM_DB_MODIFY_ATTRIBUTE_DELETE) + { + if (anAttribute.size() == 0) + oldAttribute.deleteValues(anAllocator); + else + oldAttribute.deleteValues(anAttribute, anAllocator); + } + + // if the modify mode is REPLACE, then replace the specified values, or + // delete all values if no values are specified + + else if (inModifyMode == CSSM_DB_MODIFY_ATTRIBUTE_REPLACE) + { + oldAttribute.deleteValues(anAllocator); + if (anAttribute.size() > 0) + oldAttribute.add(anAttribute, anAllocator); + else + // The spec says "all values are deleted or the the value is replaced + // with the default" but doesn't say which. We could call the parsing + // module for the attribute here...if they were implemented! But instead + // we choose "all values are deleted" and leave it at that. + ; + } + } + } + + // write the resulting attributes into the new record + + inWriteSection.put(OffsetSemanticInformation, oldSemanticInformation); + + for (uint32 anIndex = 0; anIndex < mAttributeVector.size(); ++anIndex) + { + const MetaAttribute &metaAttribute = *mAttributeVector[anIndex]; + metaAttribute.packAttribute(inWriteSection, anOffset, + attributeData[anIndex].NumberOfValues, + attributeData[anIndex].Value); + } + + inWriteSection.put(OffsetRecordSize, anOffset); + inWriteSection.size(anOffset); +} + diff --git a/libsecurity_filedb/lib/MetaRecord.h b/libsecurity_filedb/lib/MetaRecord.h new file mode 100644 index 00000000..610ccb06 --- /dev/null +++ b/libsecurity_filedb/lib/MetaRecord.h @@ -0,0 +1,176 @@ +/* + * 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. + */ + + +// +// MetaRecord.h +// + +#ifndef _H_APPLEDL_METARECORD +#define _H_APPLEDL_METARECORD + +#include "MetaAttribute.h" + +namespace Security +{ + +// +// Part of the Unique record identifier needed to identify the actual record. +// +class RecordId +{ +public: + RecordId() : mRecordNumber(~(uint32)0), mCreateVersion(~(uint32)0), mRecordVersion(~(uint32)0) {} + RecordId(uint32 inRecordNumber, uint32 inCreateVersion, uint32 inRecordVersion = 0) + : mRecordNumber(inRecordNumber), + mCreateVersion(inCreateVersion), + mRecordVersion(inRecordVersion) {} + bool operator <(const RecordId &inRecordId) const + { + return (mRecordNumber < inRecordId.mRecordNumber + || (mRecordNumber == inRecordId.mRecordNumber + && (mCreateVersion < inRecordId.mCreateVersion + || (mCreateVersion == inRecordId.mCreateVersion + && mRecordVersion < inRecordId.mRecordVersion)))); + } + uint32 mRecordNumber; + uint32 mCreateVersion; + uint32 mRecordVersion; +}; + +// +// Meta (or Schema) representation of an a Record. Used for packing and unpacking objects. +// + +class MetaRecord +{ + NOCOPY(MetaRecord) + +public: + MetaRecord(CSSM_DB_RECORDTYPE inRecordType); + MetaRecord(const CSSM_DB_RECORD_ATTRIBUTE_INFO &inInfo); + MetaRecord(CSSM_DB_RECORDTYPE inRelationID, + uint32 inNumberOfAttributes, + const CSSM_DB_SCHEMA_ATTRIBUTE_INFO *inAttributeInfo); + ~MetaRecord(); + + void setRecordAttributeInfo(const CSSM_DB_RECORD_ATTRIBUTE_INFO &inInfo); + + void createAttribute(const string *inAttributeName, + const CssmOid *inAttributeOID, + uint32 inAttributeID, + CSSM_DB_ATTRIBUTE_FORMAT inAttributeFormat); + + // Create a packed record from the given inputs. + void packRecord(WriteSection &inWriteSection, + const CSSM_DB_RECORD_ATTRIBUTE_DATA *inAttributes, + const CssmData *inData) const; + + // Unpack a record from the given inputs and return the RecordId of the record. + void unpackRecord(const ReadSection &inReadSection, + Allocator &inAllocator, + CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR inoutAttributes, + CssmData *inoutData, + CSSM_QUERY_FLAGS inQueryFlags) const; + + const MetaAttribute &metaAttribute(const CSSM_DB_ATTRIBUTE_INFO &inAttributeInfo) const; + + void updateRecord(const ReadSection &inReadSection, + WriteSection &inWriteSection, + const CssmDbRecordAttributeData *inAttributes, + const CssmData *inData, + CSSM_DB_MODIFY_MODE inModifyMode) const; + + CSSM_DB_RECORDTYPE dataRecordType() const { return mRecordType; } + + Range dataRange(const ReadSection &inReadSection) const + { + return Range(OffsetAttributeOffsets + mAttributeVector.size() * AtomSize, + inReadSection[OffsetDataSize]); + } + + // Currently this is not a real attribute. We should probably fix this. + uint32 semanticInformation(const ReadSection &inReadSection) const + { + return inReadSection[OffsetSemanticInformation]; + } + + // Return the ReadSection for record at offset + static const ReadSection readSection(const ReadSection &inTableSection, uint32 inOffset) + { + return inTableSection.subsection(inOffset, + inTableSection[inOffset + OffsetRecordSize]); + } + + // Set the RecordId of the record in inWriteSection + static void packRecordId(const RecordId &inRecordId, + WriteSection &inWriteSection) + { + inWriteSection.put(OffsetRecordNumber, inRecordId.mRecordNumber); + inWriteSection.put(OffsetCreateVersion, inRecordId.mCreateVersion); + inWriteSection.put(OffsetRecordVersion, inRecordId.mRecordVersion); + } + + // Return the RecordId for the record inRecordSection + static const uint32 unpackRecordNumber(const ReadSection &inRecordSection) + { + return inRecordSection[OffsetRecordNumber]; + } + + // Return the RecordId for the record inRecordSection + static const RecordId unpackRecordId(const ReadSection &inRecordSection) + { + return RecordId(inRecordSection[OffsetRecordNumber], + inRecordSection[OffsetCreateVersion], + inRecordSection[OffsetRecordVersion]); + } + +private: + // Return the index (0 though NumAttributes - 1) of the attribute + // represented by inAttributeInfo + uint32 attributeIndex(const CSSM_DB_ATTRIBUTE_INFO &inAttributeInfo) const; + + void unpackAttribute(const ReadSection &inReadSection, Allocator &inAllocator, + CSSM_DB_ATTRIBUTE_DATA &inoutAttribute) const; + + friend class MetaAttribute; + enum + { + OffsetRecordSize = AtomSize * 0, + OffsetRecordNumber = AtomSize * 1, + OffsetCreateVersion = AtomSize * 2, + OffsetRecordVersion = AtomSize * 3, + OffsetDataSize = AtomSize * 4, + OffsetSemanticInformation = AtomSize * 5, + OffsetAttributeOffsets = AtomSize * 6 + }; + + CSSM_DB_RECORDTYPE mRecordType; + typedef std::map NameStringMap; + typedef std::map, uint32> NameOIDMap; + typedef std::map NameIntMap; + typedef std::vector AttributeVector; + NameStringMap mNameStringMap; + NameOIDMap mNameOIDMap; + NameIntMap mNameIntMap; + AttributeVector mAttributeVector; +}; + +} // end namespace Security + +#endif // _H_APPLEDL_METARECORD + diff --git a/libsecurity_filedb/lib/OverUnderflowCheck.h b/libsecurity_filedb/lib/OverUnderflowCheck.h new file mode 100644 index 00000000..7224ac77 --- /dev/null +++ b/libsecurity_filedb/lib/OverUnderflowCheck.h @@ -0,0 +1,85 @@ +#ifndef __OVERUNDERFLOWCHECK__ +#define __OVERUNDERFLOWCHECK__ + +inline uint32 CheckUInt32Add(uint32 a, uint32 b) +{ + uint32 c = a + b; + if (c < a) + { + CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT); + } + + return c; +} + + + +inline uint32 CheckUInt32Subtract(uint32 a, uint32 b) +{ + if (a < b) + { + CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT); + } + + return a - b; +} + + + +inline uint32 CheckUInt32Multiply(uint32 a, uint32 b) +{ + uint32 c = a * b; + uint64 cc = ((uint64) a) * ((uint64) b); + if (c != cc) + { + CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT); + } + + return c; +} + + + +inline uint64 Check64BitAdd(uint64 a, uint64 b) +{ + uint64 c = a + b; + if (c < a) + { + CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT); + } + + return c; +} + + + +inline uint64 Check64BitSubtract(uint64 a, uint64 b) +{ + if (a < b) + { + CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT); + } + + return a - b; +} + + + +inline uint64 Check64BitMultiply(uint64 a, uint64 b) +{ + if (a != 0) + { + uint64 max = (uint64) -1; + uint64 limit = max / a; + if (b > limit) + { + CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT); + } + } + + return a * b; +} + + + +#endif diff --git a/libsecurity_filedb/lib/ReadWriteSection.cpp b/libsecurity_filedb/lib/ReadWriteSection.cpp new file mode 100644 index 00000000..be2a5e75 --- /dev/null +++ b/libsecurity_filedb/lib/ReadWriteSection.cpp @@ -0,0 +1,53 @@ +#include "ReadWriteSection.h" + +uint32 WriteSection::put(uint32 inOffset, uint32 inValue) +{ + uint32 aLength = CheckUInt32Add(inOffset, sizeof(inValue)); + if (aLength > mCapacity) + grow(aLength); + + if (mAddress == NULL) + CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT); + + *reinterpret_cast(mAddress + inOffset) = htonl(inValue); + return aLength; +} + + + +uint32 WriteSection::put(uint32 inOffset, uint32 inLength, const uint8 *inData) +{ + // if we are being asked to put 0 bytes, just return + if (inLength == 0 || inData == NULL) + { + return inOffset; + } + + uint32 aLength = CheckUInt32Add(inOffset, inLength); + + // Round up to nearest multiple of 4 bytes, to pad with zeros + uint32 aNewOffset = align(aLength); + if (aNewOffset > mCapacity) + grow(aNewOffset); + + if (mAddress == NULL) + CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT); + + memcpy(mAddress + inOffset, inData, inLength); + + for (uint32 anOffset = aLength; anOffset < aNewOffset; anOffset++) + mAddress[anOffset] = 0; + + return aNewOffset; +} + + + +void WriteSection::grow(size_t inNewCapacity) +{ + size_t n = CheckUInt32Multiply(mCapacity, 2); + size_t aNewCapacity = max(n, inNewCapacity); + mAddress = reinterpret_cast(mAllocator.realloc(mAddress, aNewCapacity)); + memset(mAddress + mCapacity, 0, aNewCapacity - mCapacity); + mCapacity = aNewCapacity; +} diff --git a/libsecurity_filedb/lib/ReadWriteSection.h b/libsecurity_filedb/lib/ReadWriteSection.h new file mode 100644 index 00000000..10f971fa --- /dev/null +++ b/libsecurity_filedb/lib/ReadWriteSection.h @@ -0,0 +1,209 @@ +/* + * 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. + */ + + +// +// ReadWriteSection.h +// + +#ifndef _H_APPLEDL_READWRITESECTION +#define _H_APPLEDL_READWRITESECTION + +#include +#include +#include +#include +#include +#include "OverUnderflowCheck.h" + +namespace Security +{ + +// +// Atom -- An Atom is a 32-bit unsigned integer value that is always internally +// represented using network byte order. +// +typedef Endian Atom; + +enum { + AtomSize = sizeof(uint32) // XXX Why not just use sizeof(Atom)? +}; + +// +// Class representing a range (or subrange of a buffer). +// +class Range +{ +public: + Range(uint32 inOffset, uint32 inSize) : mOffset(inOffset), mSize(inSize) {} + uint32 mOffset; + uint32 mSize; +}; + +// +// Class representing a packed record. All the accessors on this class are const since the +// underlying data is read-only +// +// XXX Should be replaced by Atom::Vector +class ReadSection +{ +protected: + ReadSection(uint8 *inAddress, size_t inLength) : mAddress(inAddress), mLength(inLength) + { + if (mAddress == NULL) + CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT); + } +public: + ReadSection() : mAddress(NULL), mLength(0) {} + ReadSection(const uint8 *inAddress, size_t inLength) : + mAddress(const_cast(inAddress)), mLength(inLength) {} + + uint32 size() const { return mLength; } + + uint32 at(uint32 inOffset) const + { + if (inOffset > mLength) + { + CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT); + } + + return ntohl(*reinterpret_cast(mAddress + inOffset)); + } + + uint32 operator[](uint32 inOffset) const + { + return at(inOffset); + } + + // Return a subsection from inOffset to end of section. + ReadSection subsection(uint32 inOffset) const + { + if (inOffset > mLength) + CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT); + return ReadSection(mAddress + inOffset, mLength - inOffset); + } + + // Return a subsection from inOffset of inLength bytes. + ReadSection subsection(uint32 inOffset, uint32 inLength) const + { + if (CheckUInt32Add(inOffset, inLength) > mLength) + CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT); + return ReadSection(mAddress + inOffset, inLength); + } + + ReadSection subsection(const Range &inRange) const + { + return subsection(inRange.mOffset, inRange.mSize); + } + + const uint8 *range(const Range &inRange) const + { + if (CheckUInt32Add(inRange.mOffset, inRange.mSize) > mLength) + CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT); + return mAddress + inRange.mOffset; + } + + uint8 *allocCopyRange(const Range &inRange, Allocator &inAllocator) const + { + uint8 *aData; + if (inRange.mSize == 0) + aData = NULL; + else + { + if (CheckUInt32Add(inRange.mOffset, inRange.mSize) > mLength) + CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT); + + aData = reinterpret_cast(inAllocator.malloc(inRange.mSize)); + memcpy(aData, mAddress + inRange.mOffset, inRange.mSize); + } + + return aData; + } + + static uint32 align(uint32 offset) { return (CheckUInt32Subtract(CheckUInt32Add(offset, AtomSize), 1)) & ~(AtomSize - 1); } + +protected: + uint8 *mAddress; + size_t mLength; +}; + +// +// Class representing a packed record (or buffer) used for writing. +// +class WriteSection : public ReadSection +{ +public: + static const size_t DefaultCapacity = 64; + + WriteSection(Allocator &inAllocator, size_t inCapacity) : + ReadSection(reinterpret_cast(inAllocator.malloc(inCapacity)), 0), + mAllocator(inAllocator), + mCapacity(inCapacity) + { + if (mCapacity > 0) + memset(mAddress, 0, mCapacity); + } + + WriteSection(Allocator &inAllocator = Allocator::standard()) : + ReadSection(reinterpret_cast(inAllocator.malloc(DefaultCapacity)), 0), + mAllocator(inAllocator), + mCapacity(DefaultCapacity) + { + } + + WriteSection(const WriteSection &ws, int length) : + ReadSection(reinterpret_cast(ws.mAllocator.malloc(length)), length), + mAllocator(ws.mAllocator), + mCapacity(length) + { + memcpy(mAddress, ws.mAddress, length); + } + + ~WriteSection() { mAllocator.free(mAddress); } + +private: + void grow(size_t inNewCapacity); + +public: +#if BUG_GCC + uint32 size() const { return ReadSection::size(); } +#else + // XXX This should work but egcs-2.95.2 doesn't like it. + using ReadSection::size; +#endif + + void size(uint32 inLength) { mLength = inLength; } + uint32 put(uint32 inOffset, uint32 inValue); + uint32 put(uint32 inOffset, uint32 inLength, const uint8 *inData); + + const uint8 *address() const { return mAddress; } + uint8 *release() + { + uint8 *anAddress = mAddress; + mAddress = NULL; + mCapacity = 0; + return anAddress; + } + +private: + Allocator &mAllocator; + size_t mCapacity; +}; + +} // end namespace Security + +#endif // _H_APPLEDL_READWRITESECTION diff --git a/libsecurity_filedb/lib/SelectionPredicate.cpp b/libsecurity_filedb/lib/SelectionPredicate.cpp new file mode 100644 index 00000000..85426ac2 --- /dev/null +++ b/libsecurity_filedb/lib/SelectionPredicate.cpp @@ -0,0 +1,51 @@ +/* + * 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. + */ + + +// +// SelectionPredicate.cpp +// + +#include "SelectionPredicate.h" + +SelectionPredicate::SelectionPredicate(const MetaRecord &inMetaRecord, + const CSSM_SELECTION_PREDICATE &inPredicate) +: mMetaAttribute(inMetaRecord.metaAttribute(inPredicate.Attribute.Info)), + mDbOperator(inPredicate.DbOperator) +{ + // Make sure that the caller specified the attribute values in the correct format. + if (inPredicate.Attribute.Info.AttributeFormat != mMetaAttribute.attributeFormat()) + CssmError::throwMe(CSSMERR_DL_INCOMPATIBLE_FIELD_FORMAT); + + // XXX See ISSUES + if (inPredicate.Attribute.NumberOfValues != 1) + CssmError::throwMe(CSSMERR_DL_UNSUPPORTED_QUERY); + + mData = inPredicate.Attribute.Value[0]; + mValue = mMetaAttribute.createValue(mData); +} + +SelectionPredicate::~SelectionPredicate() +{ + delete mValue; +} + +bool +SelectionPredicate::evaluate(const ReadSection &rs) const +{ + return mMetaAttribute.evaluate(mValue, rs, mDbOperator); +} diff --git a/libsecurity_filedb/lib/SelectionPredicate.h b/libsecurity_filedb/lib/SelectionPredicate.h new file mode 100644 index 00000000..d5b93c5d --- /dev/null +++ b/libsecurity_filedb/lib/SelectionPredicate.h @@ -0,0 +1,52 @@ +/* + * 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. + */ + + +// +// SelectionPredicate.h +// + +#ifndef _H_APPLEDL_SELECTIONPREDICATE +#define _H_APPLEDL_SELECTIONPREDICATE + +#include "MetaRecord.h" +#include + +namespace Security +{ + +class SelectionPredicate +{ + NOCOPY(SelectionPredicate) + +public: + SelectionPredicate(const MetaRecord &inMetaRecord, + const CSSM_SELECTION_PREDICATE &inPredicate); + ~SelectionPredicate(); + + bool evaluate(const ReadSection &inReadSection) const; + +private: + const MetaAttribute &mMetaAttribute; + CSSM_DB_OPERATOR mDbOperator; + CssmDataContainer mData; + DbValue *mValue; +}; + +} // end namespace Security + +#endif // _H_APPLEDL_SELECTIONPREDICATE diff --git a/libsecurity_filedb/libsecurity_filedb.xcodeproj/project.pbxproj b/libsecurity_filedb/libsecurity_filedb.xcodeproj/project.pbxproj new file mode 100644 index 00000000..2937d1ec --- /dev/null +++ b/libsecurity_filedb/libsecurity_filedb.xcodeproj/project.pbxproj @@ -0,0 +1,285 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + AAEA4A440E9163290043771D /* ReadWriteSection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AAEA4A430E9163290043771D /* ReadWriteSection.cpp */; }; + C28A1D08052E14480094CEF0 /* AppleDatabase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C28A1CED052E14480094CEF0 /* AppleDatabase.cpp */; }; + C28A1D0A052E14480094CEF0 /* AtomicFile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C28A1CEF052E14480094CEF0 /* AtomicFile.cpp */; }; + C28A1D14052E14480094CEF0 /* DbIndex.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C28A1CF9052E14480094CEF0 /* DbIndex.cpp */; }; + C28A1D18052E14480094CEF0 /* DbQuery.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C28A1CFD052E14480094CEF0 /* DbQuery.cpp */; }; + C28A1D1A052E14480094CEF0 /* DbValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C28A1CFF052E14480094CEF0 /* DbValue.cpp */; }; + C28A1D1C052E14480094CEF0 /* MetaAttribute.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C28A1D01052E14480094CEF0 /* MetaAttribute.cpp */; }; + C28A1D1E052E14480094CEF0 /* MetaRecord.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C28A1D03052E14480094CEF0 /* MetaRecord.cpp */; }; + C28A1D21052E14480094CEF0 /* SelectionPredicate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C28A1D06052E14480094CEF0 /* SelectionPredicate.cpp */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 182BB219146F0538000BF1F3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 182BB214146F0538000BF1F3 /* libsecurity_cdsa_plugin.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 4CA1FEBE052A3C8100F22E42; + remoteInfo = libsecurity_cdsa_plugin; + }; + 182BB33C146F1057000BF1F3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 182BB214146F0538000BF1F3 /* libsecurity_cdsa_plugin.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = C2C38A530535EDE600D7421F; + remoteInfo = generate; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 182BB206146F043D000BF1F3 /* base.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = base.xcconfig; sourceTree = ""; }; + 182BB207146F043D000BF1F3 /* debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = debug.xcconfig; sourceTree = ""; }; + 182BB208146F043D000BF1F3 /* lib.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = lib.xcconfig; sourceTree = ""; }; + 182BB209146F043D000BF1F3 /* release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = release.xcconfig; sourceTree = ""; }; + 182BB214146F0538000BF1F3 /* libsecurity_cdsa_plugin.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libsecurity_cdsa_plugin.xcodeproj; path = ../libsecurity_cdsa_plugin/libsecurity_cdsa_plugin.xcodeproj; sourceTree = ""; }; + 4CA1FEBE052A3C8100F22E42 /* libsecurity_filedb.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libsecurity_filedb.a; sourceTree = BUILT_PRODUCTS_DIR; }; + AA827A5B0C62AD0300D7A310 /* OverUnderflowCheck.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OverUnderflowCheck.h; sourceTree = ""; }; + AAEA4A430E9163290043771D /* ReadWriteSection.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ReadWriteSection.cpp; sourceTree = ""; }; + C28A1CED052E14480094CEF0 /* AppleDatabase.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = AppleDatabase.cpp; sourceTree = ""; }; + C28A1CEE052E14480094CEF0 /* AppleDatabase.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = AppleDatabase.h; sourceTree = ""; }; + C28A1CEF052E14480094CEF0 /* AtomicFile.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = AtomicFile.cpp; sourceTree = ""; }; + C28A1CF0052E14480094CEF0 /* AtomicFile.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = AtomicFile.h; sourceTree = ""; }; + C28A1CF9052E14480094CEF0 /* DbIndex.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = DbIndex.cpp; sourceTree = ""; }; + C28A1CFA052E14480094CEF0 /* DbIndex.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DbIndex.h; sourceTree = ""; }; + C28A1CFD052E14480094CEF0 /* DbQuery.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = DbQuery.cpp; sourceTree = ""; }; + C28A1CFE052E14480094CEF0 /* DbQuery.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DbQuery.h; sourceTree = ""; }; + C28A1CFF052E14480094CEF0 /* DbValue.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = DbValue.cpp; sourceTree = ""; }; + C28A1D00052E14480094CEF0 /* DbValue.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DbValue.h; sourceTree = ""; }; + C28A1D01052E14480094CEF0 /* MetaAttribute.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = MetaAttribute.cpp; sourceTree = ""; }; + C28A1D02052E14480094CEF0 /* MetaAttribute.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = MetaAttribute.h; sourceTree = ""; }; + C28A1D03052E14480094CEF0 /* MetaRecord.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = MetaRecord.cpp; sourceTree = ""; }; + C28A1D04052E14480094CEF0 /* MetaRecord.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = MetaRecord.h; sourceTree = ""; }; + C28A1D05052E14480094CEF0 /* ReadWriteSection.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ReadWriteSection.h; sourceTree = ""; }; + C28A1D06052E14480094CEF0 /* SelectionPredicate.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SelectionPredicate.cpp; sourceTree = ""; }; + C28A1D07052E14480094CEF0 /* SelectionPredicate.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SelectionPredicate.h; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 4CA1FEBB052A3C8100F22E42 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 182BB205146F043D000BF1F3 /* config */ = { + isa = PBXGroup; + children = ( + 182BB206146F043D000BF1F3 /* base.xcconfig */, + 182BB207146F043D000BF1F3 /* debug.xcconfig */, + 182BB208146F043D000BF1F3 /* lib.xcconfig */, + 182BB209146F043D000BF1F3 /* release.xcconfig */, + ); + name = config; + path = ../config; + sourceTree = ""; + }; + 182BB215146F0538000BF1F3 /* Products */ = { + isa = PBXGroup; + children = ( + 182BB21A146F0538000BF1F3 /* libsecurity_cdsa_plugin.a */, + ); + name = Products; + sourceTree = ""; + }; + 4CA1FEA7052A3C3800F22E42 = { + isa = PBXGroup; + children = ( + 182BB214146F0538000BF1F3 /* libsecurity_cdsa_plugin.xcodeproj */, + C28A1CEC052E14480094CEF0 /* lib */, + 182BB205146F043D000BF1F3 /* config */, + 4CA1FEBF052A3C8100F22E42 /* Products */, + ); + sourceTree = ""; + }; + 4CA1FEBF052A3C8100F22E42 /* Products */ = { + isa = PBXGroup; + children = ( + 4CA1FEBE052A3C8100F22E42 /* libsecurity_filedb.a */, + ); + name = Products; + sourceTree = ""; + }; + C28A1CEC052E14480094CEF0 /* lib */ = { + isa = PBXGroup; + children = ( + AA827A5B0C62AD0300D7A310 /* OverUnderflowCheck.h */, + C28A1CED052E14480094CEF0 /* AppleDatabase.cpp */, + C28A1CEE052E14480094CEF0 /* AppleDatabase.h */, + C28A1CEF052E14480094CEF0 /* AtomicFile.cpp */, + C28A1CF0052E14480094CEF0 /* AtomicFile.h */, + C28A1CF9052E14480094CEF0 /* DbIndex.cpp */, + C28A1CFA052E14480094CEF0 /* DbIndex.h */, + C28A1CFD052E14480094CEF0 /* DbQuery.cpp */, + C28A1CFE052E14480094CEF0 /* DbQuery.h */, + C28A1CFF052E14480094CEF0 /* DbValue.cpp */, + C28A1D00052E14480094CEF0 /* DbValue.h */, + C28A1D01052E14480094CEF0 /* MetaAttribute.cpp */, + C28A1D02052E14480094CEF0 /* MetaAttribute.h */, + C28A1D03052E14480094CEF0 /* MetaRecord.cpp */, + C28A1D04052E14480094CEF0 /* MetaRecord.h */, + C28A1D05052E14480094CEF0 /* ReadWriteSection.h */, + C28A1D06052E14480094CEF0 /* SelectionPredicate.cpp */, + C28A1D07052E14480094CEF0 /* SelectionPredicate.h */, + AAEA4A430E9163290043771D /* ReadWriteSection.cpp */, + ); + path = lib; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 4CA1FEBD052A3C8100F22E42 /* libsecurity_filedb */ = { + isa = PBXNativeTarget; + buildConfigurationList = C27AD35C0987FCDE001272E0 /* Build configuration list for PBXNativeTarget "libsecurity_filedb" */; + buildPhases = ( + 4CA1FEBA052A3C8100F22E42 /* Sources */, + 4CA1FEBB052A3C8100F22E42 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + 182BB33D146F1057000BF1F3 /* PBXTargetDependency */, + ); + name = libsecurity_filedb; + productName = libsecurity_filedb; + productReference = 4CA1FEBE052A3C8100F22E42 /* libsecurity_filedb.a */; + productType = "com.apple.product-type.library.static"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 4CA1FEAB052A3C3800F22E42 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0420; + }; + buildConfigurationList = C27AD3600987FCDE001272E0 /* Build configuration list for PBXProject "libsecurity_filedb" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 1; + knownRegions = ( + English, + Japanese, + French, + German, + ); + mainGroup = 4CA1FEA7052A3C3800F22E42; + productRefGroup = 4CA1FEBF052A3C8100F22E42 /* Products */; + projectDirPath = ""; + projectReferences = ( + { + ProductGroup = 182BB215146F0538000BF1F3 /* Products */; + ProjectRef = 182BB214146F0538000BF1F3 /* libsecurity_cdsa_plugin.xcodeproj */; + }, + ); + projectRoot = ""; + targets = ( + 4CA1FEBD052A3C8100F22E42 /* libsecurity_filedb */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXReferenceProxy section */ + 182BB21A146F0538000BF1F3 /* libsecurity_cdsa_plugin.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libsecurity_cdsa_plugin.a; + remoteRef = 182BB219146F0538000BF1F3 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; +/* End PBXReferenceProxy section */ + +/* Begin PBXSourcesBuildPhase section */ + 4CA1FEBA052A3C8100F22E42 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + C28A1D08052E14480094CEF0 /* AppleDatabase.cpp in Sources */, + C28A1D0A052E14480094CEF0 /* AtomicFile.cpp in Sources */, + C28A1D14052E14480094CEF0 /* DbIndex.cpp in Sources */, + C28A1D18052E14480094CEF0 /* DbQuery.cpp in Sources */, + C28A1D1A052E14480094CEF0 /* DbValue.cpp in Sources */, + C28A1D1C052E14480094CEF0 /* MetaAttribute.cpp in Sources */, + C28A1D1E052E14480094CEF0 /* MetaRecord.cpp in Sources */, + C28A1D21052E14480094CEF0 /* SelectionPredicate.cpp in Sources */, + AAEA4A440E9163290043771D /* ReadWriteSection.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 182BB33D146F1057000BF1F3 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = generate; + targetProxy = 182BB33C146F1057000BF1F3 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + C27AD35D0987FCDE001272E0 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 182BB207146F043D000BF1F3 /* debug.xcconfig */; + buildSettings = { + }; + name = Debug; + }; + C27AD35F0987FCDE001272E0 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 182BB209146F043D000BF1F3 /* release.xcconfig */; + buildSettings = { + }; + name = Release; + }; + C27AD3610987FCDE001272E0 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 182BB208146F043D000BF1F3 /* lib.xcconfig */; + buildSettings = { + }; + name = Debug; + }; + C27AD3630987FCDE001272E0 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 182BB208146F043D000BF1F3 /* lib.xcconfig */; + buildSettings = { + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + C27AD35C0987FCDE001272E0 /* Build configuration list for PBXNativeTarget "libsecurity_filedb" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C27AD35D0987FCDE001272E0 /* Debug */, + C27AD35F0987FCDE001272E0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C27AD3600987FCDE001272E0 /* Build configuration list for PBXProject "libsecurity_filedb" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C27AD3610987FCDE001272E0 /* Debug */, + C27AD3630987FCDE001272E0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 4CA1FEAB052A3C3800F22E42 /* Project object */; +} diff --git a/libsecurity_keychain/APPLE_LICENSE b/libsecurity_keychain/APPLE_LICENSE new file mode 100644 index 00000000..71fe6fd7 --- /dev/null +++ b/libsecurity_keychain/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/libsecurity_keychain/Info-security_keychain.plist b/libsecurity_keychain/Info-security_keychain.plist new file mode 100644 index 00000000..0c67376e --- /dev/null +++ b/libsecurity_keychain/Info-security_keychain.plist @@ -0,0 +1,5 @@ + + + + + diff --git a/libsecurity_keychain/lib/ACL.cpp b/libsecurity_keychain/lib/ACL.cpp new file mode 100644 index 00000000..a3bb5de2 --- /dev/null +++ b/libsecurity_keychain/lib/ACL.cpp @@ -0,0 +1,434 @@ +/* + * 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@ + */ + +// +// ACL.cpp +// +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +using namespace KeychainCore; +using namespace DataWalkers; + + +// +// The default form of a prompt selector +// +const CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR ACL::defaultSelector = { + CSSM_ACL_KEYCHAIN_PROMPT_CURRENT_VERSION, 0 +}; + + +// +// ACL static constants +// +const CSSM_ACL_HANDLE ACL::ownerHandle; + + +// +// Create an ACL object from the result of a CSSM ACL query +// +ACL::ACL(Access &acc, const AclEntryInfo &info, Allocator &alloc) + : allocator(alloc), access(acc), mState(unchanged), mSubjectForm(NULL), mMutex(Mutex::recursive) +{ + // parse the subject + parse(info.proto().subject()); + + // fill in AclEntryInfo layer information + const AclEntryPrototype &proto = info.proto(); + mAuthorizations = proto.authorization(); + mDelegate = proto.delegate(); + mEntryTag = proto.s_tag(); + + // take CSSM entry handle from info layer + mCssmHandle = info.handle(); +} + +ACL::ACL(Access &acc, const AclOwnerPrototype &owner, Allocator &alloc) + : allocator(alloc), access(acc), mState(unchanged), mSubjectForm(NULL), mMutex(Mutex::recursive) +{ + // parse subject + parse(owner.subject()); + + // for an owner "entry", the next-layer information is fixed (and fake) + mAuthorizations.insert(CSSM_ACL_AUTHORIZATION_CHANGE_ACL); + mDelegate = owner.delegate(); + mEntryTag[0] = '\0'; + + // use fixed (fake) entry handle + mCssmHandle = ownerHandle; +} + + +// +// Create a new ACL that authorizes anyone to do anything. +// This constructor produces a "pure" ANY ACL, without descriptor or selector. +// To generate a "standard" form of ANY, use the appListForm constructor below, +// then change its form to allowAnyForm. +// +ACL::ACL(Access &acc, Allocator &alloc) + : allocator(alloc), access(acc), mSubjectForm(NULL), mMutex(Mutex::recursive) +{ + mState = inserted; // new + mForm = allowAllForm; // everybody + mAuthorizations.insert(CSSM_ACL_AUTHORIZATION_ANY); // anything + mDelegate = false; + + //mPromptDescription stays empty + mPromptSelector = defaultSelector; + + // randomize the CSSM handle + UniformRandomBlobs().random(mCssmHandle); +} + + +// +// Create a new ACL in standard form. +// As created, it authorizes all activities. +// +ACL::ACL(Access &acc, string description, const CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR &promptSelector, + Allocator &alloc) + : allocator(alloc), access(acc), mSubjectForm(NULL), mMutex(Mutex::recursive) +{ + mState = inserted; // new + mForm = appListForm; + mAuthorizations.insert(CSSM_ACL_AUTHORIZATION_ANY); // anything + mDelegate = false; + + mPromptDescription = description; + mPromptSelector = promptSelector; + + // randomize the CSSM handle + UniformRandomBlobs().random(mCssmHandle); +} + + +// +// Destroy an ACL +// +ACL::~ACL() +{ + // release subject form (if any) + chunkFree(mSubjectForm, allocator); +} + + +// +// Does this ACL authorize a particular right? +// +bool ACL::authorizes(AclAuthorization right) +{ + StLock_(mMutex); + return mAuthorizations.find(right) != mAuthorizations.end() + || mAuthorizations.find(CSSM_ACL_AUTHORIZATION_ANY) != mAuthorizations.end() + || mAuthorizations.empty(); +} + + +// +// Add an application to the trusted-app list of this ACL. +// Will fail unless this is a standard "simple" form ACL. +// +void ACL::addApplication(TrustedApplication *app) +{ + StLock_(mMutex); + switch (mForm) { + case appListForm: // simple... + mAppList.push_back(app); + modify(); + break; + case allowAllForm: // hmm... + if (!mPromptDescription.empty()) { + // verbose "any" form (has description, "any" override) + mAppList.push_back(app); + modify(); + break; + } + // pure "any" form without description. Cannot convert to appListForm + default: + MacOSError::throwMe(errSecACLNotSimple); + } +} + + +// +// Mark an ACL as modified. +// +void ACL::modify() +{ + StLock_(mMutex); + if (mState == unchanged) { + secdebug("SecAccess", "ACL %p marked modified", this); + mState = modified; + } +} + + +// +// Mark an ACL as "removed" +// Removed ACLs have no valid contents (they are invalid on their face). +// When "updated" to the originating item, they will cause the corresponding +// ACL entry to be deleted. Otherwise, they are irrelevant. +// Note: Removing an ACL does not actually remove it from its Access's map. +// +void ACL::remove() +{ + StLock_(mMutex); + mAppList.clear(); + mForm = invalidForm; + mState = deleted; +} + + +// +// Produce CSSM-layer form (ACL prototype) copies of our content. +// Note that the result is chunk-allocated, and becomes owned by the caller. +// +void ACL::copyAclEntry(AclEntryPrototype &proto, Allocator &alloc) +{ + StLock_(mMutex); + proto.clearPod(); // preset + + // carefully copy the subject + makeSubject(); + assert(mSubjectForm); + proto = AclEntryPrototype(*mSubjectForm, mDelegate); // shares subject + ChunkCopyWalker w(alloc); + walk(w, proto.subject()); // copy subject in-place + + // the rest of a prototype + proto.tag(mEntryTag); + AuthorizationGroup tags(mAuthorizations, allocator); + proto.authorization() = tags; +} + +void ACL::copyAclOwner(AclOwnerPrototype &proto, Allocator &alloc) +{ + StLock_(mMutex); + proto.clearPod(); + + makeSubject(); + assert(mSubjectForm); + proto = AclOwnerPrototype(*mSubjectForm, mDelegate); // shares subject + ChunkCopyWalker w(alloc); + walk(w, proto.subject()); // copy subject in-place +} + + +// +// (Re)place this ACL's setting into the AclBearer specified. +// If update, assume this is an update operation and the ACL was +// originally derived from this object; specifically, assume the +// CSSM handle is valid. If not update, assume this is a different +// object that has no related ACL entry (yet). +// +void ACL::setAccess(AclBearer &target, bool update, + const AccessCredentials *cred) +{ + StLock_(mMutex); + // determine what action we need to perform + State action = state(); + if (!update) + action = (action == deleted) ? unchanged : inserted; + + // the owner acl (pseudo) "entry" is a special case + if (isOwner()) { + switch (action) { + case unchanged: + secdebug("SecAccess", "ACL %p owner unchanged", this); + return; + case inserted: // means modify the initial owner + case modified: + { + secdebug("SecAccess", "ACL %p owner modified", this); + makeSubject(); + assert(mSubjectForm); + AclOwnerPrototype proto(*mSubjectForm, mDelegate); + target.changeOwner(proto, cred); + return; + } + default: + assert(false); + return; + } + } + + // simple cases + switch (action) { + case unchanged: // ignore + secdebug("SecAccess", "ACL %p handle 0x%lx unchanged", this, entryHandle()); + return; + case deleted: // delete + secdebug("SecAccess", "ACL %p handle 0x%lx deleted", this, entryHandle()); + target.deleteAcl(entryHandle(), cred); + return; + default: + break; + } + + // build the byzantine data structures that CSSM loves so much + makeSubject(); + assert(mSubjectForm); + AclEntryPrototype proto(*mSubjectForm, mDelegate); + proto.tag(mEntryTag); + AutoAuthorizationGroup tags(mAuthorizations, allocator); + proto.authorization() = tags; + AclEntryInput input(proto); + switch (action) { + case inserted: // insert + secdebug("SecAccess", "ACL %p inserted", this); + target.addAcl(input, cred); + break; + case modified: // update + secdebug("SecAccess", "ACL %p handle 0x%lx modified", this, entryHandle()); + target.changeAcl(entryHandle(), input, cred); + break; + default: + assert(false); + } +} + + +// +// Parse an AclEntryPrototype (presumably from a CSSM "Get" ACL operation +// into internal form. +// +void ACL::parse(const TypedList &subject) +{ + StLock_(mMutex); + try { + switch (subject.type()) { + case CSSM_ACL_SUBJECT_TYPE_ANY: + // subsume an "any" as a standard form + mForm = allowAllForm; + return; + case CSSM_ACL_SUBJECT_TYPE_KEYCHAIN_PROMPT: + // pure keychain prompt - interpret as applist form with no apps + parsePrompt(subject); + mForm = appListForm; + return; + case CSSM_ACL_SUBJECT_TYPE_THRESHOLD: + { + // app-list format: THRESHOLD(1, n): sign(1), ..., sign(n), PROMPT + if (subject[1] != 1) + throw ParseError(); + uint32 count = subject[2]; + + // parse final (PROMPT) element + TypedList &end = subject[count + 2]; // last choice + if (end.type() != CSSM_ACL_SUBJECT_TYPE_KEYCHAIN_PROMPT) + throw ParseError(); // not PROMPT at end + parsePrompt(end); + + // check for leading ANY + TypedList &first = subject[3]; + if (first.type() == CSSM_ACL_SUBJECT_TYPE_ANY) { + mForm = allowAllForm; + return; + } + + // parse other (code signing) elements + for (uint32 n = 0; n < count - 1; n++) + mAppList.push_back(new TrustedApplication(TypedList(subject[n + 3].list()))); + } + mForm = appListForm; + return; + default: + mForm = customForm; + mSubjectForm = chunkCopy(&subject); + return; + } + } catch (const ParseError &) { + secdebug("SecAccess", "acl compile failed; marking custom"); + mForm = customForm; + mSubjectForm = chunkCopy(&subject); + mAppList.clear(); + } +} + +void ACL::parsePrompt(const TypedList &subject) +{ + StLock_(mMutex); + assert(subject.length() == 3); + mPromptSelector = + *subject[1].data().interpretedAs(CSSM_ERRCODE_INVALID_ACL_SUBJECT_VALUE); + mPromptDescription = subject[2].toString(); +} + + +// +// Take this ACL and produce its meaning as a CSSM ACL subject in mSubjectForm +// +void ACL::makeSubject() +{ + StLock_(mMutex); + switch (form()) { + case allowAllForm: + chunkFree(mSubjectForm, allocator); // release previous + if (mPromptDescription.empty()) { + // no description -> pure ANY + mSubjectForm = new(allocator) TypedList(allocator, CSSM_ACL_SUBJECT_TYPE_ANY); + } else { + // have description -> threshold(1 of 2) of { ANY, PROMPT } + mSubjectForm = new(allocator) TypedList(allocator, CSSM_ACL_SUBJECT_TYPE_THRESHOLD, + new(allocator) ListElement(1), + new(allocator) ListElement(2)); + *mSubjectForm += new(allocator) ListElement(TypedList(allocator, CSSM_ACL_SUBJECT_TYPE_ANY)); + TypedList prompt(allocator, CSSM_ACL_SUBJECT_TYPE_KEYCHAIN_PROMPT, + new(allocator) ListElement(allocator, CssmData::wrap(mPromptSelector)), + new(allocator) ListElement(allocator, mPromptDescription)); + *mSubjectForm += new(allocator) ListElement(prompt); + } + return; + case appListForm: { + // threshold(1 of n+1) of { app1, ..., appn, PROMPT } + chunkFree(mSubjectForm, allocator); // release previous + uint32 appCount = mAppList.size(); + mSubjectForm = new(allocator) TypedList(allocator, CSSM_ACL_SUBJECT_TYPE_THRESHOLD, + new(allocator) ListElement(1), + new(allocator) ListElement(appCount + 1)); + for (uint32 n = 0; n < appCount; n++) + *mSubjectForm += + new(allocator) ListElement(mAppList[n]->makeSubject(allocator)); + TypedList prompt(allocator, CSSM_ACL_SUBJECT_TYPE_KEYCHAIN_PROMPT, + new(allocator) ListElement(allocator, CssmData::wrap(mPromptSelector)), + new(allocator) ListElement(allocator, mPromptDescription)); + *mSubjectForm += new(allocator) ListElement(prompt); + } + return; + case customForm: + assert(mSubjectForm); // already set; keep it + return; + default: + assert(false); // unexpected + } +} diff --git a/libsecurity_keychain/lib/ACL.h b/libsecurity_keychain/lib/ACL.h new file mode 100644 index 00000000..93850df6 --- /dev/null +++ b/libsecurity_keychain/lib/ACL.h @@ -0,0 +1,157 @@ +/* + * 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@ + */ + +// +// ACL.h - ACL control wrappers +// +#ifndef _SECURITY_ACL_H_ +#define _SECURITY_ACL_H_ + +#include +#include +#include +#include +#include +#include "SecCFTypes.h" + +#include + +namespace Security { +namespace KeychainCore { + +using CssmClient::AclBearer; + +class Access; +class TrustedApplication; + + +// +// An ACL Entry for an Access object +// +class ACL : public SecCFObject { + NOCOPY(ACL) +public: + SECCFFUNCTIONS(ACL, SecACLRef, errSecInvalidItemRef, gTypes().ACL) + + // create from CSSM layer ACL entry + ACL(Access &acc, const AclEntryInfo &info, + Allocator &alloc = Allocator::standard()); + // create from CSSM layer owner prototype + ACL(Access &acc, const AclOwnerPrototype &owner, + Allocator &alloc = Allocator::standard()); + // create an "any" ACL + ACL(Access &acc, Allocator &alloc = Allocator::standard()); + // create from "standard form" arguments (with empty application list) + ACL(Access &acc, string description, const CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR &promptSelector, + Allocator &alloc = Allocator::standard()); + virtual ~ACL(); + + Allocator &allocator; + + enum State { + unchanged, // unchanged from source + inserted, // new + modified, // was changed (replace) + deleted // was deleted (now invalid) + }; + State state() const { return mState; } + + enum Form { + invalidForm, // invalid + customForm, // not a recognized format (but valid) + allowAllForm, // indiscriminate + appListForm // list of apps + prompt confirm + }; + Form form() const { return mForm; } + void form(Form f) { mForm = f; } + + Access &access; // we belong to this Access + +public: + AclAuthorizationSet &authorizations() { return mAuthorizations; } + bool authorizes(AclAuthorization right); + void setAuthorization(CSSM_ACL_AUTHORIZATION_TAG auth) + { mAuthorizations.clear(); mAuthorizations.insert(auth); } + + typedef vector< SecPointer > ApplicationList; + ApplicationList &applications() + { assert(form() == appListForm); return mAppList; } + void addApplication(TrustedApplication *app); + + CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR &promptSelector() { return mPromptSelector; } + string &promptDescription() { return mPromptDescription; } + + CSSM_ACL_HANDLE entryHandle() const { return mCssmHandle; } + + static const CSSM_ACL_HANDLE ownerHandle = 0xff0e2743; // pseudo-handle for owner ACL + bool isOwner() const { return mCssmHandle == ownerHandle; } + void makeOwner() { mCssmHandle = ownerHandle; } + + void modify(); // mark modified (update on commit) + void remove(); // mark removed (delete on commit) + + // produce chunk copies of CSSM forms; caller takes ownership + void copyAclEntry(AclEntryPrototype &proto, Allocator &alloc = Allocator::standard()); + void copyAclOwner(AclOwnerPrototype &proto, Allocator &alloc = Allocator::standard()); + +public: + void setAccess(AclBearer &target, bool update = false, + const AccessCredentials *cred = NULL); + +public: + struct ParseError { }; + +public: + static const CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR defaultSelector; + +private: + void parse(const TypedList &subject); + void parsePrompt(const TypedList &subject); + void makeSubject(); + void clearSubjects(Form newForm); + +private: + State mState; // change state + Form mForm; // format type + + // AclEntryPrototype fields (minus subject, which is virtually constructed) + CSSM_ACL_HANDLE mCssmHandle; // CSSM entry handle (for updates) + string mEntryTag; // CSSM entry tag (64 bytes or so, they say) + bool mDelegate; // CSSM delegate flag + AclAuthorizationSet mAuthorizations; // rights for this ACL entry + + // composite AclEntryPrototype (constructed when needed) + TypedList *mSubjectForm; + + // following values valid only if form() == appListForm + ApplicationList mAppList; // list of trusted applications + CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR mPromptSelector; // selector field of PROMPT subject + string mPromptDescription; // description field of PROMPT subject + Mutex mMutex; +}; + + +} // end namespace KeychainCore +} // end namespace Security + +#endif // !_SECURITY_ACL_H_ diff --git a/libsecurity_keychain/lib/Access.cpp b/libsecurity_keychain/lib/Access.cpp new file mode 100644 index 00000000..a4cb3672 --- /dev/null +++ b/libsecurity_keychain/lib/Access.cpp @@ -0,0 +1,380 @@ +/* + * 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@ + */ + +// +// Access.cpp +// +#include +#include +#include "SecBridge.h" +#include +#include +#include +#include + +using namespace KeychainCore; +using namespace CssmClient; + + +// +// Access static constants +// +const CSSM_ACL_HANDLE Access::ownerHandle; + + +// +// Create a completely open Access (anyone can do anything) +// Note that this means anyone can *change* the ACL at will, too. +// These ACL entries contain no descriptor names. +// +Access::Access() : mMutex(Mutex::recursive) +{ + SecPointer owner = new ACL(*this); + owner->setAuthorization(CSSM_ACL_AUTHORIZATION_CHANGE_ACL); + addOwner(owner); + + SecPointer any = new ACL(*this); + add(any); +} + + +// +// Create a default Access object. +// This construct an Access with "default form", whatever that happens to be +// in this release. +// +Access::Access(const string &descriptor, const ACL::ApplicationList &trusted) : mMutex(Mutex::recursive) +{ + makeStandard(descriptor, trusted); +} + +Access::Access(const string &descriptor) : mMutex(Mutex::recursive) +{ + ACL::ApplicationList trusted; + trusted.push_back(new TrustedApplication); + makeStandard(descriptor, trusted); +} + +Access::Access(const string &descriptor, const ACL::ApplicationList &trusted, + const AclAuthorizationSet &limitedRights, const AclAuthorizationSet &freeRights) : mMutex(Mutex::recursive) +{ + makeStandard(descriptor, trusted, limitedRights, freeRights); +} + +void Access::makeStandard(const string &descriptor, const ACL::ApplicationList &trusted, + const AclAuthorizationSet &limitedRights, const AclAuthorizationSet &freeRights) +{ + StLock_(mMutex); + + // owner "entry" + SecPointer owner = new ACL(*this, descriptor, ACL::defaultSelector); + owner->setAuthorization(CSSM_ACL_AUTHORIZATION_CHANGE_ACL); + addOwner(owner); + + // unlimited entry + SecPointer unlimited = new ACL(*this, descriptor, ACL::defaultSelector); + if (freeRights.empty()) { + unlimited->authorizations().clear(); + unlimited->authorizations().insert(CSSM_ACL_AUTHORIZATION_ENCRYPT); + } else + unlimited->authorizations() = freeRights; + unlimited->form(ACL::allowAllForm); + add(unlimited); + + // limited entry + SecPointer limited = new ACL(*this, descriptor, ACL::defaultSelector); + if (limitedRights.empty()) { + limited->authorizations().clear(); + limited->authorizations().insert(CSSM_ACL_AUTHORIZATION_DECRYPT); + limited->authorizations().insert(CSSM_ACL_AUTHORIZATION_SIGN); + limited->authorizations().insert(CSSM_ACL_AUTHORIZATION_MAC); + limited->authorizations().insert(CSSM_ACL_AUTHORIZATION_DERIVE); + limited->authorizations().insert(CSSM_ACL_AUTHORIZATION_EXPORT_CLEAR); + limited->authorizations().insert(CSSM_ACL_AUTHORIZATION_EXPORT_WRAPPED); + } else + limited->authorizations() = limitedRights; + limited->applications() = trusted; + add(limited); +} + + +// +// Create an Access object whose initial value is taken +// from a CSSM ACL bearing object. +// +Access::Access(AclBearer &source) : mMutex(Mutex::recursive) +{ + // retrieve and set + AutoAclOwnerPrototype owner; + source.getOwner(owner); + AutoAclEntryInfoList acls; + source.getAcl(acls); + compile(*owner, acls.count(), acls.entries()); +} + + +// +// Create an Access object from CSSM-layer access controls +// +Access::Access(const CSSM_ACL_OWNER_PROTOTYPE &owner, + uint32 aclCount, const CSSM_ACL_ENTRY_INFO *acls) : mMutex(Mutex::recursive) +{ + compile(owner, aclCount, acls); +} + + +Access::~Access() +{ +} + + +// Convert a SecPointer to a SecACLRef. +static SecACLRef +convert(const SecPointer &acl) +{ + return *acl; +} + +// +// Return all ACL components in a newly-made CFArray. +// +CFArrayRef Access::copySecACLs() const +{ + return makeCFArray(convert, mAcls); +} + +CFArrayRef Access::copySecACLs(CSSM_ACL_AUTHORIZATION_TAG action) const +{ + list choices; + for (Map::const_iterator it = mAcls.begin(); it != mAcls.end(); it++) + if (it->second->authorizes(action)) + choices.push_back(it->second); + return choices.empty() ? NULL : makeCFArray(convert, choices); +} + + +// +// Enter the complete access configuration into a AclBearer. +// If update, skip any part marked unchanged. (If not update, skip +// any part marked deleted.) +// +void Access::setAccess(AclBearer &target, bool update /* = false */) +{ + StLock_(mMutex); + AclFactory factory; + editAccess(target, update, factory.promptCred()); +} + +void Access::setAccess(AclBearer &target, Maker &maker) +{ + StLock_(mMutex); + if (maker.makerType() == Maker::kStandardMakerType) + { + // remove initial-setup ACL + target.deleteAcl(Maker::creationEntryTag, maker.cred()); + + // insert our own ACL entries + editAccess(target, false, maker.cred()); + } +} + +void Access::editAccess(AclBearer &target, bool update, const AccessCredentials *cred) +{ + StLock_(mMutex); + assert(mAcls[ownerHandle]); // have owner + + // apply all non-owner ACLs first + for (Map::iterator it = mAcls.begin(); it != mAcls.end(); it++) + if (!it->second->isOwner()) + it->second->setAccess(target, update, cred); + + // finally, apply owner + mAcls[ownerHandle]->setAccess(target, update, cred); +} + + +// +// A convenience function to add one application to a standard ("simple") form +// ACL entry. This will only work if +// -- there is exactly one ACL entry authorizing the right +// -- that entry is in simple form +// +void Access::addApplicationToRight(AclAuthorization right, TrustedApplication *app) +{ + StLock_(mMutex); + vector acls; + findAclsForRight(right, acls); + if (acls.size() != 1) + MacOSError::throwMe(errSecACLNotSimple); // let's not guess here... + (*acls.begin())->addApplication(app); +} + + +// +// Yield new (copied) CSSM level owner and acls values, presumably +// for use at CSSM layer operations. +// Caller is responsible for releasing the beasties when done. +// +void Access::copyOwnerAndAcl(CSSM_ACL_OWNER_PROTOTYPE * &ownerResult, + uint32 &aclCount, CSSM_ACL_ENTRY_INFO * &aclsResult) +{ + StLock_(mMutex); + Allocator& alloc = Allocator::standard(); + int count = mAcls.size() - 1; // one will be owner, others are acls + AclOwnerPrototype owner; + CssmAutoPtr acls = new(alloc) AclEntryInfo[count]; + AclEntryInfo *aclp = acls; // -> next unfilled acl element + for (Map::const_iterator it = mAcls.begin(); it != mAcls.end(); it++) { + SecPointer acl = it->second; + if (acl->isOwner()) { + acl->copyAclOwner(owner, alloc); + } else { + aclp->handle() = acl->entryHandle(); + acl->copyAclEntry(*aclp, alloc); + ++aclp; + } + } + assert((aclp - acls) == count); // all ACL elements filled + + // commit output + ownerResult = new(alloc) AclOwnerPrototype(owner); + aclCount = count; + aclsResult = acls.release(); +} + + +// +// Retrieve the description from a randomly chosen ACL within this Access. +// In the conventional case where all ACLs have the same descriptor, this +// is deterministic. But you have been warned. +// +string Access::promptDescription() const +{ + for (Map::const_iterator it = mAcls.begin(); it != mAcls.end(); it++) { + ACL *acl = it->second; + switch (acl->form()) { + case ACL::allowAllForm: + case ACL::appListForm: + { + string descr = acl->promptDescription(); + if (!descr.empty()) + return descr; + } + default: + break; + } + } + // couldn't find suitable ACL (no description anywhere) + CssmError::throwMe(errSecACLNotSimple); +} + + +// +// Add a new ACL to the resident set. The ACL must have been +// newly made for this Access. +// +void Access::add(ACL *newAcl) +{ + StLock_(mMutex); + if (&newAcl->access != this) + MacOSError::throwMe(paramErr); + assert(!mAcls[newAcl->entryHandle()]); + mAcls[newAcl->entryHandle()] = newAcl; +} + + +// +// Add the owner ACL to the resident set. The ACL must have been +// newly made for this Access. +// Since an Access must have exactly one owner ACL, this call +// should only be made (exactly once) for a newly created Access. +// +void Access::addOwner(ACL *newAcl) +{ + StLock_(mMutex); + newAcl->makeOwner(); + assert(mAcls.find(ownerHandle) == mAcls.end()); // no owner yet + add(newAcl); +} + + +// +// Compile a set of ACL entries and owner into internal form. +// +void Access::compile(const CSSM_ACL_OWNER_PROTOTYPE &owner, + uint32 aclCount, const CSSM_ACL_ENTRY_INFO *acls) +{ + StLock_(mMutex); + // add owner acl + mAcls[ownerHandle] = new ACL(*this, AclOwnerPrototype::overlay(owner)); + + // add acl entries + const AclEntryInfo *acl = AclEntryInfo::overlay(acls); + for (uint32 n = 0; n < aclCount; n++) { + secdebug("SecAccess", "%p compiling entry %ld", this, acl[n].handle()); + mAcls[acl[n].handle()] = new ACL(*this, acl[n]); + } + secdebug("SecAccess", "%p %ld entries compiled", this, mAcls.size()); +} + + +// +// Creation helper objects +// +const char Access::Maker::creationEntryTag[] = "___setup___"; + +Access::Maker::Maker(Allocator &alloc, MakerType makerType) + : allocator(alloc), mKey(alloc), mCreds(allocator), mMakerType(makerType) +{ + if (makerType == kStandardMakerType) + { + // generate random key + mKey.malloc(keySize); + UniformRandomBlobs().random(mKey.get()); + + // create entry info for resource creation + mInput = AclEntryPrototype(TypedList(allocator, CSSM_ACL_SUBJECT_TYPE_PASSWORD, + new(allocator) ListElement(mKey.get()))); + mInput.proto().tag(creationEntryTag); + + // create credential sample for access + mCreds += TypedList(allocator, CSSM_SAMPLE_TYPE_PASSWORD, new(allocator) ListElement(mKey.get())); + } + else + { + // just make it an CSSM_ACL_SUBJECT_TYPE_ANY list + mInput = AclEntryPrototype(TypedList(allocator, CSSM_ACL_SUBJECT_TYPE_ANY)); + } +} + +void Access::Maker::initialOwner(ResourceControlContext &ctx, const AccessCredentials *creds) +{ + //@@@ make up ctx.entry-info + ctx.input() = mInput; + ctx.credentials(creds); +} + +const AccessCredentials *Access::Maker::cred() +{ + return &mCreds; +} diff --git a/libsecurity_keychain/lib/Access.h b/libsecurity_keychain/lib/Access.h new file mode 100644 index 00000000..1d57909a --- /dev/null +++ b/libsecurity_keychain/lib/Access.h @@ -0,0 +1,139 @@ +/* + * 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@ + */ + +// +// Access.h - Access control wrappers +// +#ifndef _SECURITY_ACCESS_H_ +#define _SECURITY_ACCESS_H_ + +#include +#include +#include +#include +#include +#include +#include + +namespace Security { +namespace KeychainCore { + +using CssmClient::AclBearer; + + +class Access : public SecCFObject { + NOCOPY(Access) +public: + SECCFFUNCTIONS(Access, SecAccessRef, errSecInvalidItemRef, gTypes().Access) + + class Maker { + NOCOPY(Maker) + static const size_t keySize = 16; // number of (random) bytes + friend class Access; + public: + enum MakerType {kStandardMakerType, kAnyMakerType}; + + Maker(Allocator &alloc = Allocator::standard(), MakerType makerType = kStandardMakerType); + + void initialOwner(ResourceControlContext &ctx, const AccessCredentials *creds = NULL); + const AccessCredentials *cred(); + + TrackingAllocator allocator; + + static const char creationEntryTag[]; + + MakerType makerType() {return mMakerType;} + + private: + CssmAutoData mKey; + AclEntryInput mInput; + AutoCredentials mCreds; + MakerType mMakerType; + }; + +public: + // make default forms + Access(const string &description); + Access(const string &description, const ACL::ApplicationList &trusted); + Access(const string &description, const ACL::ApplicationList &trusted, + const AclAuthorizationSet &limitedRights, const AclAuthorizationSet &freeRights); + + // make a completely open Access (anyone can do anything) + Access(); + + // retrieve from an existing AclBearer + Access(AclBearer &source); + + // make from CSSM layer information (presumably retrieved by caller) + Access(const CSSM_ACL_OWNER_PROTOTYPE &owner, + uint32 aclCount, const CSSM_ACL_ENTRY_INFO *acls); + virtual ~Access(); + +public: + CFArrayRef copySecACLs() const; + CFArrayRef copySecACLs(CSSM_ACL_AUTHORIZATION_TAG action) const; + + void add(ACL *newAcl); + void addOwner(ACL *newOwnerAcl); + + void setAccess(AclBearer &target, bool update = false); + void setAccess(AclBearer &target, Maker &maker); + + template + void findAclsForRight(AclAuthorization right, Container &cont) + { + cont.clear(); + for (Map::const_iterator it = mAcls.begin(); it != mAcls.end(); it++) + if (it->second->authorizes(right)) + cont.push_back(it->second); + } + + std::string promptDescription() const; // from any one of the ACLs contained + + void addApplicationToRight(AclAuthorization right, TrustedApplication *app); + + void copyOwnerAndAcl(CSSM_ACL_OWNER_PROTOTYPE * &owner, + uint32 &aclCount, CSSM_ACL_ENTRY_INFO * &acls); + +protected: + void makeStandard(const string &description, const ACL::ApplicationList &trusted, + const AclAuthorizationSet &limitedRights = AclAuthorizationSet(), + const AclAuthorizationSet &freeRights = AclAuthorizationSet()); + void compile(const CSSM_ACL_OWNER_PROTOTYPE &owner, + uint32 aclCount, const CSSM_ACL_ENTRY_INFO *acls); + + void editAccess(AclBearer &target, bool update, const AccessCredentials *cred); + +private: + static const CSSM_ACL_HANDLE ownerHandle = ACL::ownerHandle; + typedef map > Map; + + Map mAcls; // set of ACL entries + Mutex mMutex; +}; + + +} // end namespace KeychainCore +} // end namespace Security + +#endif // !_SECURITY_ACCESS_H_ diff --git a/libsecurity_keychain/lib/CCallbackMgr.cp b/libsecurity_keychain/lib/CCallbackMgr.cp new file mode 100644 index 00000000..07a49e6a --- /dev/null +++ b/libsecurity_keychain/lib/CCallbackMgr.cp @@ -0,0 +1,240 @@ +/* + * 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@ + */ + + +/* + File: CCallbackMgr.cp + + Contains: Code that communicates with processes that install a callback + with the Keychain Manager to receive keychain events. + +*/ + +#include "CCallbackMgr.h" + +#include +#include + +#include +#include "Globals.h" +#include +#include +#include +#include + +using namespace KeychainCore; +using namespace CssmClient; +using namespace SecurityServer; + +#pragma mark ÑÑÑÑ CallbackInfo ÑÑÑÑ + +CallbackInfo::CallbackInfo() : mCallback(NULL),mEventMask(0),mContext(NULL) +{ +} + +CallbackInfo::CallbackInfo(SecKeychainCallback inCallbackFunction, + SecKeychainEventMask inEventMask, void *inContext) + : mCallback(inCallbackFunction), mEventMask(inEventMask), mContext(inContext) +{ +} + +CallbackInfo::~CallbackInfo() +{ +} + +bool CallbackInfo::operator==(const CallbackInfo& other) const +{ + return mCallback==other.mCallback; +} + +bool CallbackInfo::operator!=(const CallbackInfo& other) const +{ + return !(*this==other); +} + + +#pragma mark ÑÑÑÑ CCallbackMgr ÑÑÑÑ + + +class CallbackMaker +{ +protected: + RefPointer mCallbackManager; + +public: + CallbackMaker(); + CCallbackMgr& instance() {return *mCallbackManager;} +}; + + +CallbackMaker::CallbackMaker() +{ + CCallbackMgr* manager = new CCallbackMgr(); + mCallbackManager = manager; +} + + + +ModuleNexus gCallbackMaker; + +CCallbackMgr::CCallbackMgr() : EventListener (kNotificationDomainDatabase, kNotificationAllEvents) +{ + EventListener::FinishedInitialization(this); +} + +CCallbackMgr::~CCallbackMgr() +{ +} + +CCallbackMgr& CCallbackMgr::Instance() +{ + return gCallbackMaker().instance(); +} + +void CCallbackMgr::AddCallback( SecKeychainCallback inCallbackFunction, + SecKeychainEventMask inEventMask, + void* inContext) + +{ + CallbackInfo info( inCallbackFunction, inEventMask, inContext ); + CallbackInfo existingInfo; + + + CallbackInfoListIterator ix = find( CCallbackMgr::Instance().mEventCallbacks.begin(), + CCallbackMgr::Instance().mEventCallbacks.end(), info ); + + // make sure it is not already there + if ( ix!=CCallbackMgr::Instance().mEventCallbacks.end() ) + { + // It's already there. This could mean that the old process died unexpectedly, + // so we need to validate the process ID of the existing callback. + // On Mac OS X this list is per process so this is always a duplicate + MacOSError::throwMe(errSecDuplicateCallback); + } + + CCallbackMgr::Instance().mEventCallbacks.push_back(info); +} + + +class Predicate +{ + SecKeychainCallback mCallbackFunction; +public: + Predicate(SecKeychainCallback inCallbackFunction) : mCallbackFunction(inCallbackFunction) {} + bool operator()(const CallbackInfo &cbInfo) { return cbInfo.mCallback == mCallbackFunction; } +}; + +void CCallbackMgr::RemoveCallback(SecKeychainCallback inCallbackFunction) +{ + size_t oldSize = CCallbackMgr::Instance().mEventCallbacks.size(); + Predicate predicate(inCallbackFunction); + CCallbackMgr::Instance().mEventCallbacks.remove_if(predicate); + + if (oldSize == CCallbackMgr::Instance().mEventCallbacks.size()) + MacOSError::throwMe(errSecInvalidCallback); +} + +void CCallbackMgr::AlertClients(const list &eventCallbacks, + SecKeychainEvent inEvent, + pid_t inPid, + const Keychain &inKeychain, + const Item &inItem) +{ + secdebug("kcnotify", "dispatch event %ld pid %d keychain %p item %p", + inEvent, inPid, &inKeychain, !!inItem ? &*inItem : NULL); + + // Iterate through callbacks, looking for those registered for inEvent + const SecKeychainEventMask theMask = 1U << inEvent; + + for (ConstCallbackInfoListIterator ix = eventCallbacks.begin(); ix != eventCallbacks.end(); ++ix) + { + if (!(ix->mEventMask & theMask)) + continue; + + SecKeychainCallbackInfo cbInfo; + cbInfo.version = 0; // @@@ kKeychainAPIVersion; + cbInfo.item = inItem ? inItem->handle() : 0; + cbInfo.keychain = inKeychain ? inKeychain->handle() : 0; + cbInfo.pid = inPid; + + ix->mCallback(inEvent, &cbInfo, ix->mContext); + if (cbInfo.item) CFRelease(cbInfo.item); + if (cbInfo.keychain) CFRelease(cbInfo.keychain); + } +} + + + +void CCallbackMgr::consume (SecurityServer::NotificationDomain domain, SecurityServer::NotificationEvent whichEvent, const CssmData &data) +{ + NameValueDictionary dictionary (data); + + // Decode from userInfo the event type, 'keychain' CFDict, and 'item' CFDict + SecKeychainEvent thisEvent = whichEvent; + + pid_t thisPid; + const NameValuePair* pidRef = dictionary.FindByName(PID_KEY); + if (pidRef == 0) + { + thisPid = 0; + } + else + { + thisPid = n2h(*reinterpret_cast(pidRef->Value().data ())); + } + + Keychain thisKeychain; + Item thisItem; + list eventCallbacks; + { + // Lock the global API lock before doing stuff with StorageManager. + // make sure we have a database identifier + if (dictionary.FindByName (SSUID_KEY) != 0) + { + StLock_(*globals().storageManager.getStorageManagerMutex()); + DLDbIdentifier dbid = NameValueDictionary::MakeDLDbIdentifierFromNameValueDictionary(dictionary); + thisKeychain = globals().storageManager.keychain(dbid); + } + + const NameValuePair* item = dictionary.FindByName(ITEM_KEY); + + if (item && thisKeychain) + { + PrimaryKey pk(item->Value()); + thisItem = thisKeychain->item(pk); + } + + // Deal with events that we care about ourselves first. + if (thisEvent == kSecDeleteEvent && thisKeychain.get() && thisItem.get()) + thisKeychain->didDeleteItem(thisItem.get()); + else if (thisEvent == kSecKeychainListChangedEvent) + globals().storageManager.forceUserSearchListReread(); + + eventCallbacks = CCallbackMgr::Instance().mEventCallbacks; + // We can safely release the global API lock now since thisKeychain and thisItem + // are CFRetained and will be until they go out of scope. + } + + // Notify our process of this event. + CCallbackMgr::AlertClients(eventCallbacks, thisEvent, thisPid, thisKeychain, thisItem); +} diff --git a/libsecurity_keychain/lib/CCallbackMgr.h b/libsecurity_keychain/lib/CCallbackMgr.h new file mode 100644 index 00000000..5098a7e1 --- /dev/null +++ b/libsecurity_keychain/lib/CCallbackMgr.h @@ -0,0 +1,102 @@ +/* + * Copyright (c) 1998-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@ + */ + + +/* + * CCallbackMgr.h -- Code that communicates with processes that install a callback + * with the Keychain Manager to receive keychain events. + */ +#ifndef _SECURITY_CCALLBACKMGR_H_ +#define _SECURITY_CCALLBACKMGR_H_ + +#include +#include +#include +#include +#include +#include +#include "KCEventNotifier.h" + +namespace Security +{ + +namespace KeychainCore +{ + +class CallbackInfo; +class CCallbackMgr; + +class CallbackInfo +{ +public: + ~CallbackInfo(); + CallbackInfo(); + CallbackInfo(SecKeychainCallback inCallbackFunction,SecKeychainEventMask inEventMask,void *inContext); + + bool operator ==(const CallbackInfo& other) const; + bool operator !=(const CallbackInfo& other) const; + + SecKeychainCallback mCallback; + SecKeychainEventMask mEventMask; + void *mContext; +}; + +// typedefs +typedef CallbackInfo *CallbackInfoPtr; +typedef CallbackInfo const *ConstCallbackInfoPtr; + +typedef list::iterator CallbackInfoListIterator; +typedef list::const_iterator ConstCallbackInfoListIterator; + + +class CCallbackMgr : public SecurityServer::EventListener +{ +public: + CCallbackMgr(); + ~CCallbackMgr(); + + static CCallbackMgr& Instance(); + + static void AddCallback( SecKeychainCallback inCallbackFunction, SecKeychainEventMask inEventMask, void* inContext); + + static void RemoveCallback( SecKeychainCallback inCallbackFunction ); + //static void RemoveCallbackUPP(KCCallbackUPP inCallbackFunction); + static bool HasCallbacks() + { return CCallbackMgr::Instance().mEventCallbacks.size() > 0; }; + +private: + + void consume (SecurityServer::NotificationDomain domain, SecurityServer::NotificationEvent whichEvent, + const CssmData &data); + + static void AlertClients(const list &eventCallbacks, SecKeychainEvent inEvent, pid_t inPid, + const Keychain& inKeychain, const Item &inItem); + + list mEventCallbacks; +}; + +} // end namespace KeychainCore + +} // end namespace Security + +#endif // !_SECURITY_CCALLBACKMGR_H_ diff --git a/libsecurity_keychain/lib/Certificate.cpp b/libsecurity_keychain/lib/Certificate.cpp new file mode 100644 index 00000000..e44308d2 --- /dev/null +++ b/libsecurity_keychain/lib/Certificate.cpp @@ -0,0 +1,1262 @@ +/* + * Copyright (c) 2002-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@ + */ + +// +// Certificate.cpp +// +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//#include "CLFieldsCommon.h" + + +using namespace KeychainCore; + +CL +Certificate::clForType(CSSM_CERT_TYPE type) +{ + return CL(gGuidAppleX509CL); +} + +Certificate::Certificate(const CSSM_DATA &data, CSSM_CERT_TYPE type, CSSM_CERT_ENCODING encoding) : + ItemImpl(CSSM_DL_DB_RECORD_X509_CERTIFICATE, reinterpret_cast(NULL), UInt32(data.Length), reinterpret_cast(data.Data)), + mHaveTypeAndEncoding(true), + mPopulated(false), + mType(type), + mEncoding(encoding), + mCL(clForType(type)), + mCertHandle(0), + mV1SubjectPublicKeyCStructValue(NULL), + mV1SubjectNameCStructValue(NULL), + mV1IssuerNameCStructValue(NULL) +{ + if (data.Length == 0 || data.Data == NULL) + MacOSError::throwMe(paramErr); +} + +// db item constructor +Certificate::Certificate(const Keychain &keychain, const PrimaryKey &primaryKey, const CssmClient::DbUniqueRecord &uniqueId) : + ItemImpl(keychain, primaryKey, uniqueId), + mHaveTypeAndEncoding(false), + mPopulated(false), + mCL(NULL), + mCertHandle(0), + mV1SubjectPublicKeyCStructValue(NULL), + mV1SubjectNameCStructValue(NULL), + mV1IssuerNameCStructValue(NULL) +{ +} + + + +Certificate* Certificate::make(const Keychain &keychain, const PrimaryKey &primaryKey, const CssmClient::DbUniqueRecord &uniqueId) +{ + Certificate* c = new Certificate(keychain, primaryKey, uniqueId); + keychain->addItem(primaryKey, c); + return c; +} + + + +Certificate* Certificate::make(const Keychain &keychain, const PrimaryKey &primaryKey) +{ + Certificate* c = new Certificate(keychain, primaryKey); + keychain->addItem(primaryKey, c); + return c; +} + + + + +// PrimaryKey item constructor +Certificate::Certificate(const Keychain &keychain, const PrimaryKey &primaryKey) : + ItemImpl(keychain, primaryKey), + mHaveTypeAndEncoding(false), + mPopulated(false), + mCL(NULL), + mCertHandle(0), + mV1SubjectPublicKeyCStructValue(NULL), + mV1SubjectNameCStructValue(NULL), + mV1IssuerNameCStructValue(NULL) +{ + // @@@ In this case we don't know the type... +} + +Certificate::Certificate(Certificate &certificate) : + ItemImpl(certificate), + mHaveTypeAndEncoding(certificate.mHaveTypeAndEncoding), + mPopulated(false /* certificate.mPopulated */), + mType(certificate.mType), + mEncoding(certificate.mEncoding), + mCL(certificate.mCL), + mCertHandle(0), + mV1SubjectPublicKeyCStructValue(NULL), + mV1SubjectNameCStructValue(NULL), + mV1IssuerNameCStructValue(NULL) +{ +} + +Certificate::~Certificate() throw() +{ + if (mV1SubjectPublicKeyCStructValue) + releaseFieldValue(CSSMOID_X509V1SubjectPublicKeyCStruct, mV1SubjectPublicKeyCStructValue); + + if (mCertHandle && mCL) + CSSM_CL_CertAbortCache(mCL->handle(), mCertHandle); + + if (mV1SubjectNameCStructValue) + releaseFieldValue(CSSMOID_X509V1SubjectNameCStruct, mV1SubjectNameCStructValue); + + if (mV1IssuerNameCStructValue) + releaseFieldValue(CSSMOID_X509V1IssuerNameCStruct, mV1IssuerNameCStructValue); +} + +CSSM_HANDLE +Certificate::certHandle() +{ + StLock_(mMutex); + const CSSM_DATA *cert = &data(); + if (!mCertHandle) + { + if (CSSM_RETURN retval = CSSM_CL_CertCache(clHandle(), cert, &mCertHandle)) + CssmError::throwMe(retval); + } + + return mCertHandle; +} + +/* Return a zero terminated list of CSSM_DATA_PTR's with the values of the field specified by field. Caller must call releaseFieldValues to free the storage allocated by this call. */ +CSSM_DATA_PTR * +Certificate::copyFieldValues(const CSSM_OID &field) +{ + StLock_(mMutex); + CSSM_CL_HANDLE clh = clHandle(); + CSSM_DATA_PTR fieldValue, *fieldValues; + CSSM_HANDLE resultsHandle = 0; + uint32 numberOfFields = 0; + CSSM_RETURN result; + + result = CSSM_CL_CertGetFirstCachedFieldValue(clh, certHandle(), &field, &resultsHandle, &numberOfFields, &fieldValue); + if (result) + { + if (result == CSSMERR_CL_NO_FIELD_VALUES) + return NULL; + + CssmError::throwMe(result); + } + + fieldValues = new CSSM_DATA_PTR[numberOfFields + 1]; + fieldValues[0] = fieldValue; + fieldValues[numberOfFields] = NULL; + + for (uint32 value = 1; value < numberOfFields; ++value) + { + CSSM_RETURN cresult = CSSM_CL_CertGetNextCachedFieldValue(clh, resultsHandle, &fieldValues[value]); + if (cresult) + { + fieldValues[value] = NULL; + result = cresult; + break; // No point in continuing really. + } + } + + CSSM_CL_CertAbortQuery(clh, resultsHandle); + + if (result) + { + releaseFieldValues(field, fieldValues); + CssmError::throwMe(result); + } + + return fieldValues; +} + +void +Certificate::releaseFieldValues(const CSSM_OID &field, CSSM_DATA_PTR *fieldValues) +{ + StLock_(mMutex); + if (fieldValues) + { + CSSM_CL_HANDLE clh = clHandle(); + + for (int ix = 0; fieldValues[ix]; ++ix) + CSSM_CL_FreeFieldValue(clh, &field, fieldValues[ix]); + + delete[] fieldValues; + } +} + +void +Certificate::addParsedAttribute(const CSSM_DB_ATTRIBUTE_INFO &info, const CSSM_OID &field) +{ + StLock_(mMutex); + CSSM_DATA_PTR *fieldValues = copyFieldValues(field); + if (fieldValues) + { + CssmDbAttributeData &anAttr = mDbAttributes->add(info); + for (int ix = 0; fieldValues[ix]; ++ix) + anAttr.add(*fieldValues[ix], *mDbAttributes); + + releaseFieldValues(field, fieldValues); + } +} + +void +Certificate::addSubjectKeyIdentifier() +{ + StLock_(mMutex); + const CSSM_DB_ATTRIBUTE_INFO &info = Schema::attributeInfo(kSecSubjectKeyIdentifierItemAttr); + const CSSM_OID &field = CSSMOID_SubjectKeyIdentifier; + + CSSM_DATA_PTR *fieldValues = copyFieldValues(field); + if (fieldValues) + { + CssmDbAttributeData &anAttr = mDbAttributes->add(info); + for (int ix = 0; fieldValues[ix]; ++ix) + { + const CSSM_X509_EXTENSION *extension = reinterpret_cast(fieldValues[ix]->Data); + if (extension == NULL || fieldValues[ix]->Length != sizeof(CSSM_X509_EXTENSION)) + { + assert(extension != NULL && fieldValues[ix]->Length == sizeof(CSSM_X509_EXTENSION)); + continue; + } + const CE_SubjectKeyID *skid = reinterpret_cast(extension->value.parsedValue); + if (skid == NULL) + { + assert(skid != NULL); + continue; + } + anAttr.add(*skid, *mDbAttributes); + } + + releaseFieldValues(field, fieldValues); + } +} + +/* Return a CSSM_DATA_PTR with the value of the first field specified by field. Caller must call releaseFieldValue to free the storage allocated by this call. */ +CSSM_DATA_PTR +Certificate::copyFirstFieldValue(const CSSM_OID &field) +{ + StLock_(mMutex); + CSSM_CL_HANDLE clh = clHandle(); + CSSM_DATA_PTR fieldValue; + CSSM_HANDLE resultsHandle = 0; + uint32 numberOfFields = 0; + CSSM_RETURN result; + + result = CSSM_CL_CertGetFirstCachedFieldValue(clh, certHandle(), &field, &resultsHandle, &numberOfFields, &fieldValue); + if (result) + { + if (result == CSSMERR_CL_NO_FIELD_VALUES) + return NULL; + + CssmError::throwMe(result); + } + + result = CSSM_CL_CertAbortQuery(clh, resultsHandle); + + if (result) + { + releaseFieldValue(field, fieldValue); + CssmError::throwMe(result); + } + + return fieldValue; +} + +void +Certificate::releaseFieldValue(const CSSM_OID &field, CSSM_DATA_PTR fieldValue) +{ + StLock_(mMutex); + if (fieldValue) + { + CSSM_CL_HANDLE clh = clHandle(); + CSSM_CL_FreeFieldValue(clh, &field, fieldValue); + } +} + + + +/* + This method computes the keyIdentifier for the public key in the cert as + described below: + + The keyIdentifier is composed of the 160-bit SHA-1 hash of the + value of the BIT STRING subjectPublicKey (excluding the tag, + length, and number of unused bits). +*/ +const CssmData & +Certificate::publicKeyHash() +{ + StLock_(mMutex); + if (mPublicKeyHash.Length) + return mPublicKeyHash; + + CSSM_DATA_PTR keyPtr = copyFirstFieldValue(CSSMOID_CSSMKeyStruct); + if (keyPtr && keyPtr->Data) + { + CssmClient::CSP csp(gGuidAppleCSP); + CssmClient::PassThrough passThrough(csp); + CSSM_KEY *key = reinterpret_cast(keyPtr->Data); + void *outData; + CssmData *cssmData; + + /* Given a CSSM_KEY_PTR in any format, obtain the SHA-1 hash of the + * associated key blob. + * Key is specified in CSSM_CSP_CreatePassThroughContext. + * Hash is allocated by the CSP, in the App's memory, and returned + * in *outData. */ + passThrough.key(key); + passThrough(CSSM_APPLECSP_KEYDIGEST, NULL, &outData); + cssmData = reinterpret_cast(outData); + + assert(cssmData->Length <= sizeof(mPublicKeyHashBytes)); + mPublicKeyHash.Data = mPublicKeyHashBytes; + mPublicKeyHash.Length = cssmData->Length; + memcpy(mPublicKeyHash.Data, cssmData->Data, cssmData->Length); + csp.allocator().free(cssmData->Data); + csp.allocator().free(cssmData); + } + + releaseFieldValue(CSSMOID_CSSMKeyStruct, keyPtr); + + return mPublicKeyHash; +} + +const CssmData & +Certificate::subjectKeyIdentifier() +{ + StLock_(mMutex); + if (mSubjectKeyID.Length) + return mSubjectKeyID; + + CSSM_DATA_PTR fieldValue = copyFirstFieldValue(CSSMOID_SubjectKeyIdentifier); + if (fieldValue && fieldValue->Data && fieldValue->Length == sizeof(CSSM_X509_EXTENSION)) + { + const CSSM_X509_EXTENSION *extension = reinterpret_cast(fieldValue->Data); + const CE_SubjectKeyID *skid = reinterpret_cast(extension->value.parsedValue); // CSSM_DATA + + if (skid->Length <= sizeof(mSubjectKeyIDBytes)) + { + mSubjectKeyID.Data = mSubjectKeyIDBytes; + mSubjectKeyID.Length = skid->Length; + memcpy(mSubjectKeyID.Data, skid->Data, skid->Length); + } + else + mSubjectKeyID.Length = 0; + } + + releaseFieldValue(CSSMOID_SubjectKeyIdentifier, fieldValue); + + return mSubjectKeyID; +} + + +/* + * Given an CSSM_X509_NAME, Find the first name/value pair with + * a printable value which matches the specified OID (e.g., CSSMOID_CommonName). + * Returns the CFString-style encoding associated with name component's BER tag. + * Returns NULL if none found. + */ +static const CSSM_DATA * +findPrintableField( + const CSSM_X509_NAME &x509Name, + const CSSM_OID *tvpType, // NULL means "any printable field" + CFStringBuiltInEncodings *encoding) // RETURNED +{ + for(uint32 rdnDex=0; rdnDexnumberOfPairs; tvpDex++) { + const CSSM_X509_TYPE_VALUE_PAIR *tvpPtr = + &rdnPtr->AttributeTypeAndValue[tvpDex]; + + /* type/value pair: match caller's specified type? */ + if(tvpType != NULL && tvpType->Data != NULL) { + if(tvpPtr->type.Length != tvpType->Length) { + continue; + } + if(memcmp(tvpPtr->type.Data, tvpType->Data, tvpType->Length)) { + /* If we don't have a match but the requested OID is CSSMOID_UserID, + * look for a matching X.500 UserID OID: (0.9.2342.19200300.100.1.1) */ + const char cssm_userid_oid[] = { 0x09,0x49,0x86,0x49,0x1f,0x12,0x8c,0xe4,0x81,0x81 }; + const char x500_userid_oid[] = { 0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x01 }; + if(!(tvpType->Length == sizeof(cssm_userid_oid) && + !memcmp(tvpPtr->type.Data, x500_userid_oid, sizeof(x500_userid_oid)) && + !memcmp(tvpType->Data, cssm_userid_oid, sizeof(cssm_userid_oid)))) { + continue; + } + } + } + + /* printable? */ + switch(tvpPtr->valueType) { + case BER_TAG_PRINTABLE_STRING: + case BER_TAG_IA5_STRING: + *encoding = kCFStringEncodingASCII; + return &tvpPtr->value; + case BER_TAG_PKIX_UTF8_STRING: + case BER_TAG_GENERAL_STRING: + case BER_TAG_PKIX_UNIVERSAL_STRING: + *encoding = kCFStringEncodingUTF8; + return &tvpPtr->value; + case BER_TAG_T61_STRING: + case BER_TAG_VIDEOTEX_STRING: + case BER_TAG_ISO646_STRING: + *encoding = kCFStringEncodingISOLatin1; + return &tvpPtr->value; + case BER_TAG_PKIX_BMP_STRING: + *encoding = kCFStringEncodingUnicode; + return &tvpPtr->value; + default: + /* not printable */ + break; + } + } /* for each pair */ + } /* for each RDN */ + + /* no printable component of specified type found */ + return NULL; +} + +/* + * Infer printable label for a given CSSM_X509_NAME. Returns NULL + * if no appropriate printable name found. Returns the CFString-style + * encoding associated with name component's BER tag. Also optionally + * returns Description component and its encoding if present and the + * returned name component was from CommonName. + */ +static const CSSM_DATA *inferLabelFromX509Name( + const CSSM_X509_NAME *x509Name, + CFStringBuiltInEncodings *encoding, // RETURNED + const CSSM_DATA **description, // optionally RETURNED + CFStringBuiltInEncodings *descrEncoding) // RETURNED if description != NULL +{ + const CSSM_DATA *printValue; + /* + * Search order (take the first one found with a printable + * value): + * -- common name + * -- Orgnaizational Unit + * -- Organization + * -- field of any kind + */ + printValue = findPrintableField(*x509Name, &CSSMOID_CommonName, encoding); + if(printValue != NULL) { + if(description != NULL) { + *description = findPrintableField(*x509Name, &CSSMOID_Description, descrEncoding); + } + return printValue; + } + printValue = findPrintableField(*x509Name, &CSSMOID_OrganizationalUnitName, encoding); + if(printValue != NULL) { + return printValue; + } + printValue = findPrintableField(*x509Name, &CSSMOID_OrganizationName, encoding); + if(printValue != NULL) { + return printValue; + } + /* take anything */ + return findPrintableField(*x509Name, NULL, encoding); +} + +/* + * 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) +{ + /* callees of this routine don't care about the encoding */ + CFStringBuiltInEncodings encoding = kCFStringEncodingASCII; + return inferLabelFromX509Name(x509Name, &encoding, NULL, &encoding); +} + + +void +Certificate::inferLabel(bool addLabel, CFStringRef *rtnString) +{ + StLock_(mMutex); + // Set PrintName and optionally the Alias attribute for this certificate, based on the + // X509 SubjectAltName and SubjectName. + const CSSM_DATA *printName = NULL; + const CSSM_DATA *description = NULL; + std::vector emailAddresses; + CSSM_DATA puntData; + CssmAutoData printPlusDescr(Allocator::standard()); + CssmData printPlusDescData; + CFStringBuiltInEncodings printEncoding = kCFStringEncodingUTF8; + CFStringBuiltInEncodings descrEncoding = kCFStringEncodingUTF8; + + // Find the SubjectAltName fields, if any, and extract all the GNT_RFC822Name entries from all of them + const CSSM_OID &sanOid = CSSMOID_SubjectAltName; + CSSM_DATA_PTR *sanValues = copyFieldValues(sanOid); + const CSSM_OID &snOid = CSSMOID_X509V1SubjectNameCStruct; + CSSM_DATA_PTR snValue = copyFirstFieldValue(snOid); + + getEmailAddresses(sanValues, snValue, emailAddresses); + + if (snValue && snValue->Data) + { + const CSSM_X509_NAME &x509Name = *(const CSSM_X509_NAME *)snValue->Data; + printName = inferLabelFromX509Name(&x509Name, &printEncoding, + &description, &descrEncoding); + if (printName) + { + /* Don't ever use "Thawte Freemail Member" as the label for a cert. Instead force + a fall back on the email address. */ + const char tfm[] = "Thawte Freemail Member"; + if ( (printName->Length == sizeof(tfm) - 1) && + !memcmp(printName->Data, tfm, sizeof(tfm) - 1)) { + printName = NULL; + } + } + } + + /* Do a check to see if a '\0' was at the end of printName and strip it. */ + CssmData cleanedUpPrintName; + if((printName != NULL) && + (printName->Length != 0) && + (printEncoding != kCFStringEncodingISOLatin1) && + (printEncoding != kCFStringEncodingUnicode) && + (printName->Data[printName->Length - 1] == '\0')) { + cleanedUpPrintName.Data = printName->Data; + cleanedUpPrintName.Length = printName->Length - 1; + printName = &cleanedUpPrintName; + } + + if((printName != NULL) && (description != NULL) && (description->Length != 0)) + { + /* + * Munge Print Name (which in this case is the CommonName) and Description + * together with the Description in parentheses. We convert from whatever + * format Print Name and Description are in to UTF8 here. + */ + CFRef combo(CFStringCreateMutable(NULL, 0)); + CFRef cfPrint(CFStringCreateWithBytes(NULL, printName->Data, + (CFIndex)printName->Length, printEncoding, true)); + CssmData cleanedUpDescr(description->Data, description->Length); + if ((cleanedUpDescr.Data[cleanedUpDescr.Length - 1] == '\0') && + (descrEncoding != kCFStringEncodingISOLatin1) && + (descrEncoding != kCFStringEncodingUnicode)) { + cleanedUpDescr.Length--; + } + CFRef cfDesc(CFStringCreateWithBytes(NULL, cleanedUpDescr.Data, + (CFIndex)cleanedUpDescr.Length, descrEncoding, true)); + CFStringAppend(combo, cfPrint); + CFStringAppendCString(combo, " (", kCFStringEncodingASCII); + CFStringAppend(combo, cfDesc); + CFStringAppendCString(combo, ")", kCFStringEncodingASCII); + CFRef comboData(CFStringCreateExternalRepresentation(NULL, combo, + kCFStringEncodingUTF8, 0)); + printPlusDescr.copy(CFDataGetBytePtr(comboData), CFDataGetLength(comboData)); + printPlusDescData = printPlusDescr; + printName = &printPlusDescData; + printEncoding = kCFStringEncodingUTF8; + } + + if (printName == NULL) + { + /* If the we couldn't find a label use the emailAddress instead. */ + if (!emailAddresses.empty()) + printName = &emailAddresses[0]; + else + { + /* punt! */ + puntData.Data = (uint8 *)"X509 Certificate"; + puntData.Length = 16; + printName = &puntData; + } + printEncoding = kCFStringEncodingUTF8; + } + + /* If we couldn't find an email address just use the printName which might be the url or something else useful. */ + if (emailAddresses.empty()) + emailAddresses.push_back(CssmData::overlay(*printName)); + + /* What do we do with the inferred label - return it or add it mDbAttributes? */ + if (addLabel) + { + mDbAttributes->add(Schema::kX509CertificatePrintName, *printName); + CssmDbAttributeData &attrData = mDbAttributes->add(Schema::kX509CertificateAlias); + + /* Add the email addresses to attrData and normalize them. */ + uint32 ix = 0; + for (std::vector::const_iterator it = emailAddresses.begin(); it != emailAddresses.end(); ++it, ++ix) + { + /* Add the email address using the allocator from mDbAttributes. */ + attrData.add(*it, *mDbAttributes); + /* Normalize the emailAddresses in place since attrData already copied it. */ + normalizeEmailAddress(attrData.Value[ix]); + } + } + + if (rtnString) + { + CFStringBuiltInEncodings testEncoding = printEncoding; + if(testEncoding == kCFStringEncodingISOLatin1) { + // try UTF-8 first + testEncoding = kCFStringEncodingUTF8; + } + *rtnString = CFStringCreateWithBytes(NULL, printName->Data, + (CFIndex)printName->Length, testEncoding, true); + if(*rtnString == NULL && printEncoding == kCFStringEncodingISOLatin1) { + // string cannot be represented in UTF-8, fall back to ISO Latin 1 + *rtnString = CFStringCreateWithBytes(NULL, printName->Data, + (CFIndex)printName->Length, printEncoding, true); + } + } + + // Clean up + if (snValue) + releaseFieldValue(snOid, snValue); + if (sanValues) + releaseFieldValues(sanOid, sanValues); +} + +void +Certificate::populateAttributes() +{ + StLock_(mMutex); + if (mPopulated) + return; + + addParsedAttribute(Schema::attributeInfo(kSecSubjectItemAttr), CSSMOID_X509V1SubjectName); + addParsedAttribute(Schema::attributeInfo(kSecIssuerItemAttr), CSSMOID_X509V1IssuerName); + addParsedAttribute(Schema::attributeInfo(kSecSerialNumberItemAttr), CSSMOID_X509V1SerialNumber); + + addSubjectKeyIdentifier(); + + if(!mHaveTypeAndEncoding) + MacOSError::throwMe(errSecDataNotAvailable); // @@@ Or some other error. + + // Adjust mType based on the actual version of the cert. + CSSM_DATA_PTR versionPtr = copyFirstFieldValue(CSSMOID_X509V1Version); + if (versionPtr && versionPtr->Data && versionPtr->Length == sizeof(uint32)) + { + mType = CSSM_CERT_X_509v1 + (*reinterpret_cast(versionPtr->Data)); + } + else + mType = CSSM_CERT_X_509v1; + + releaseFieldValue(CSSMOID_X509V1Version, versionPtr); + + mDbAttributes->add(Schema::attributeInfo(kSecCertTypeItemAttr), mType); + mDbAttributes->add(Schema::attributeInfo(kSecCertEncodingItemAttr), mEncoding); + mDbAttributes->add(Schema::attributeInfo(kSecPublicKeyHashItemAttr), publicKeyHash()); + inferLabel(true); + + mPopulated = true; +} + +const CssmData & +Certificate::data() +{ + StLock_(mMutex); + CssmDataContainer *data = mData.get(); + if (!data && mKeychain) + { + // Make sure mUniqueId is set. + dbUniqueRecord(); + CssmDataContainer _data; + mData = NULL; + /* new data allocated by CSPDL, implicitly freed by CssmDataContainer */ + mUniqueId->get(NULL, &_data); + /* this saves a copy to be freed at destruction and to be passed to caller */ + setData(_data.length(), _data.data()); + return *mData.get(); + } + + // If the data hasn't been set we can't return it. + if (!data) + MacOSError::throwMe(errSecDataNotAvailable); + + return *data; +} + +CSSM_CERT_TYPE +Certificate::type() +{ + StLock_(mMutex); + if (!mHaveTypeAndEncoding) + { + SecKeychainAttribute attr; + attr.tag = kSecCertTypeItemAttr; + attr.data = &mType; + attr.length = sizeof(mType); + getAttribute(attr, NULL); + } + + return mType; +} + +CSSM_CERT_ENCODING +Certificate::encoding() +{ + StLock_(mMutex); + if (!mHaveTypeAndEncoding) + { + SecKeychainAttribute attr; + attr.tag = kSecCertEncodingItemAttr; + attr.data = &mEncoding; + attr.length = sizeof(mEncoding); + getAttribute(attr, NULL); + } + + return mEncoding; +} + +const CSSM_X509_ALGORITHM_IDENTIFIER_PTR +Certificate::algorithmID() +{ + StLock_(mMutex); + if (!mV1SubjectPublicKeyCStructValue) + mV1SubjectPublicKeyCStructValue = copyFirstFieldValue(CSSMOID_X509V1SubjectPublicKeyCStruct); + + CSSM_X509_SUBJECT_PUBLIC_KEY_INFO *info = (CSSM_X509_SUBJECT_PUBLIC_KEY_INFO *)mV1SubjectPublicKeyCStructValue->Data; + CSSM_X509_ALGORITHM_IDENTIFIER *algid = &info->algorithm; + return algid; +} + +CFStringRef +Certificate::commonName() +{ + StLock_(mMutex); + return distinguishedName(&CSSMOID_X509V1SubjectNameCStruct, &CSSMOID_CommonName); +} + +CFStringRef +Certificate::distinguishedName(const CSSM_OID *sourceOid, const CSSM_OID *componentOid) +{ + StLock_(mMutex); + CFStringRef rtnString = NULL; + CSSM_DATA_PTR fieldValue = copyFirstFieldValue(*sourceOid); + CSSM_X509_NAME_PTR x509Name = (CSSM_X509_NAME_PTR)fieldValue->Data; + const CSSM_DATA *printValue = NULL; + CFStringBuiltInEncodings encoding; + + if (fieldValue && fieldValue->Data) + printValue = findPrintableField(*x509Name, componentOid, &encoding); + + if (printValue) + rtnString = CFStringCreateWithBytes(NULL, printValue->Data, + CFIndex(printValue->Length), encoding, true); + + releaseFieldValue(*sourceOid, fieldValue); + + return rtnString; +} + + +/* + * Return a CFString containing the first email addresses for this certificate, based on the + * X509 SubjectAltName and SubjectName. + */ +CFStringRef +Certificate::copyFirstEmailAddress() +{ + StLock_(mMutex); + CFStringRef rtnString; + + const CSSM_OID &sanOid = CSSMOID_SubjectAltName; + CSSM_DATA_PTR *sanValues = copyFieldValues(sanOid); + const CSSM_OID &snOid = CSSMOID_X509V1SubjectNameCStruct; + CSSM_DATA_PTR snValue = copyFirstFieldValue(snOid); + std::vector emailAddresses; + + getEmailAddresses(sanValues, snValue, emailAddresses); + if (emailAddresses.empty()) + rtnString = NULL; + else + { + /* Encoding is kCFStringEncodingUTF8 since the string is either + PRINTABLE_STRING, IA5_STRING, T61_STRING or PKIX_UTF8_STRING. */ + rtnString = CFStringCreateWithBytes(NULL, emailAddresses[0].Data, + (CFIndex)emailAddresses[0].Length, kCFStringEncodingUTF8, true); + } + + // Clean up + if (snValue) + releaseFieldValue(snOid, snValue); + if (sanValues) + releaseFieldValues(sanOid, sanValues); + + return rtnString; +} + +/* + * Return a CFArray containing the email addresses for this certificate, based on the + * X509 SubjectAltName and SubjectName. + */ +CFArrayRef +Certificate::copyEmailAddresses() +{ + StLock_(mMutex); + CFMutableArrayRef array = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); + std::vector emailAddresses; + + // Find the SubjectAltName fields, if any, and extract all the GNT_RFC822Name entries from all of them + const CSSM_OID &sanOid = CSSMOID_SubjectAltName; + CSSM_DATA_PTR *sanValues = copyFieldValues(sanOid); + + const CSSM_OID &snOid = CSSMOID_X509V1SubjectNameCStruct; + CSSM_DATA_PTR snValue = copyFirstFieldValue(snOid); + + getEmailAddresses(sanValues, snValue, emailAddresses); + + for (std::vector::const_iterator it = emailAddresses.begin(); it != emailAddresses.end(); ++it) + { + /* Encoding is kCFStringEncodingUTF8 since the string is either + PRINTABLE_STRING, IA5_STRING, T61_STRING or PKIX_UTF8_STRING. */ + CFStringRef string = CFStringCreateWithBytes(NULL, it->Data, static_cast(it->Length), kCFStringEncodingUTF8, true); + CFArrayAppendValue(array, string); + CFRelease(string); + } + + // Clean up + if (snValue) + releaseFieldValue(snOid, snValue); + if (sanValues) + releaseFieldValues(sanOid, sanValues); + + return array; +} + +const CSSM_X509_NAME_PTR +Certificate::subjectName() +{ + StLock_(mMutex); + if (!mV1SubjectNameCStructValue) + if ((mV1SubjectNameCStructValue = copyFirstFieldValue(CSSMOID_X509V1SubjectNameCStruct)) == NULL) + return NULL; + + return (const CSSM_X509_NAME_PTR)mV1SubjectNameCStructValue->Data; +} + +const CSSM_X509_NAME_PTR +Certificate::issuerName() +{ + StLock_(mMutex); + if (!mV1IssuerNameCStructValue) + if ((mV1IssuerNameCStructValue = copyFirstFieldValue(CSSMOID_X509V1IssuerNameCStruct)) == NULL) + return NULL; + + return (const CSSM_X509_NAME_PTR)mV1IssuerNameCStructValue->Data; +} + +CSSM_CL_HANDLE +Certificate::clHandle() +{ + StLock_(mMutex); + if (!mCL) + mCL = clForType(type()); + + return mCL->handle(); +} + +bool +Certificate::operator < (Certificate &other) +{ + // Certificates in different keychains are considered equal if data is equal + // Note that the Identity '<' operator relies on this assumption. + return data() < other.data(); +} + +bool +Certificate::operator == (Certificate &other) +{ + // Certificates in different keychains are considered equal if data is equal + // Note that the Identity '==' operator relies on this assumption. + return data() == other.data(); +} + +bool +Certificate::equal(SecCFObject &other) +{ + return (*this) == (Certificate &)other; +} + +void +Certificate::update() +{ + ItemImpl::update(); +} + +Item +Certificate::copyTo(const Keychain &keychain, Access *newAccess) +{ + StLock_(mMutex); + /* Certs can't have access controls. */ + if (newAccess) + MacOSError::throwMe(errSecNoAccessForItem); + + Item item(new Certificate(data(), type(), encoding())); + keychain->add(item); + return item; +} + +void +Certificate::didModify() +{ +} + +PrimaryKey +Certificate::add(Keychain &keychain) +{ + StLock_(mMutex); + // If we already have a Keychain we can't be added. + if (mKeychain) + MacOSError::throwMe(errSecDuplicateItem); + + populateAttributes(); + + CSSM_DB_RECORDTYPE recordType = mDbAttributes->recordType(); + + Db db(keychain->database()); + // add the item to the (regular) db + try + { + mUniqueId = db->insert(recordType, mDbAttributes.get(), mData.get()); + } + catch (const CssmError &e) + { + if (e.osStatus() != CSSMERR_DL_INVALID_RECORDTYPE) + throw; + + // Create the cert relation and try again. + db->createRelation(CSSM_DL_DB_RECORD_X509_CERTIFICATE, + "CSSM_DL_DB_RECORD_X509_CERTIFICATE", + Schema::X509CertificateSchemaAttributeCount, + Schema::X509CertificateSchemaAttributeList, + Schema::X509CertificateSchemaIndexCount, + Schema::X509CertificateSchemaIndexList); + keychain->keychainSchema()->didCreateRelation( + CSSM_DL_DB_RECORD_X509_CERTIFICATE, + "CSSM_DL_DB_RECORD_X509_CERTIFICATE", + Schema::X509CertificateSchemaAttributeCount, + Schema::X509CertificateSchemaAttributeList, + Schema::X509CertificateSchemaIndexCount, + Schema::X509CertificateSchemaIndexList); + + mUniqueId = db->insert(recordType, mDbAttributes.get(), mData.get()); + } + + mPrimaryKey = keychain->makePrimaryKey(recordType, mUniqueId); + mKeychain = keychain; + + return mPrimaryKey; +} + +SecPointer +Certificate::publicKey() +{ + StLock_(mMutex); + SecPointer keyItem; + // Return a CSSM_DATA_PTR with the value of the first field specified by field. + // Caller must call releaseFieldValue to free the storage allocated by this call. + // call OSStatus SecKeyGetCSSMKey(SecKeyRef key, const CSSM_KEY **cssmKey); to retrieve + + CSSM_DATA_PTR keyPtr = copyFirstFieldValue(CSSMOID_CSSMKeyStruct); + if (keyPtr && keyPtr->Data) + { + CssmClient::CSP csp(gGuidAppleCSP); + CssmKey *cssmKey = reinterpret_cast(keyPtr->Data); + CssmClient::Key key(csp, *cssmKey); + keyItem = new KeyItem(key); + // Clear out KeyData since KeyItem() takes over ownership of the key, and we don't want it getting released. + cssmKey->KeyData.Data = NULL; + cssmKey->KeyData.Length = 0; + } + + releaseFieldValue(CSSMOID_CSSMKeyStruct, keyPtr); + + return keyItem; +} + +// This function "borrowed" from the X509 CL, which is (currently) linked into +// the Security.framework as a built-in plugin. +extern "C" bool getField_normRDN_NSS ( + const CSSM_DATA &derName, + uint32 &numFields, // RETURNED (if successful, 0 or 1) + CssmOwnedData &fieldValue); // RETURNED + +KCCursor +Certificate::cursorForIssuerAndSN(const StorageManager::KeychainList &keychains, const CssmData &issuer, const CssmData &serialNumber) +{ + CssmAutoData fieldValue(Allocator::standard(Allocator::normal)); + uint32 numFields; + + // We need to decode issuer, normalize it, then re-encode it + if (!getField_normRDN_NSS(issuer, numFields, fieldValue)) + MacOSError::throwMe(errSecDataNotAvailable); + + // Code basically copied from SecKeychainSearchCreateFromAttributes and SecKeychainSearchCopyNext: + KCCursor cursor(keychains, kSecCertificateItemClass, NULL); + cursor->conjunctive(CSSM_DB_AND); + cursor->add(CSSM_DB_EQUAL, Schema::kX509CertificateIssuer, fieldValue.get()); + cursor->add(CSSM_DB_EQUAL, Schema::kX509CertificateSerialNumber, serialNumber); + + return cursor; +} + +KCCursor +Certificate::cursorForIssuerAndSN_CF(const StorageManager::KeychainList &keychains, CFDataRef issuer, CFDataRef serialNumber) +{ + // This assumes a normalized issuer + CSSM_DATA issuerCSSM, serialNumberCSSM; + + issuerCSSM.Length = CFDataGetLength(issuer); + issuerCSSM.Data = const_cast(CFDataGetBytePtr(issuer)); + + serialNumberCSSM.Length = CFDataGetLength(serialNumber); + serialNumberCSSM.Data = const_cast(CFDataGetBytePtr(serialNumber)); + + // Code basically copied from SecKeychainSearchCreateFromAttributes and SecKeychainSearchCopyNext: + KCCursor cursor(keychains, kSecCertificateItemClass, NULL); + cursor->conjunctive(CSSM_DB_AND); + cursor->add(CSSM_DB_EQUAL, Schema::kX509CertificateIssuer, issuerCSSM); + cursor->add(CSSM_DB_EQUAL, Schema::kX509CertificateSerialNumber, serialNumberCSSM); + + return cursor; +} + +KCCursor +Certificate::cursorForSubjectKeyID(const StorageManager::KeychainList &keychains, const CssmData &subjectKeyID) +{ + KCCursor cursor(keychains, kSecCertificateItemClass, NULL); + cursor->conjunctive(CSSM_DB_AND); + cursor->add(CSSM_DB_EQUAL, Schema::kX509CertificateSubjectKeyIdentifier, subjectKeyID); + + return cursor; +} + +KCCursor +Certificate::cursorForEmail(const StorageManager::KeychainList &keychains, const char *emailAddress) +{ + KCCursor cursor(keychains, kSecCertificateItemClass, NULL); + if (emailAddress) + { + cursor->conjunctive(CSSM_DB_AND); + CssmSelectionPredicate &pred = cursor->add(CSSM_DB_EQUAL, Schema::kX509CertificateAlias, emailAddress); + /* Normalize the emailAddresses in place since cursor already copied it. */ + normalizeEmailAddress(pred.Attribute.Value[0]); + } + + return cursor; +} + +SecPointer +Certificate::findInKeychain(const StorageManager::KeychainList &keychains) +{ + StLock_(mMutex); + const CSSM_OID &issuerOid = CSSMOID_X509V1IssuerName; + CSSM_DATA_PTR issuerPtr = copyFirstFieldValue(issuerOid); + CssmData issuer(issuerPtr->Data, issuerPtr->Length); + + const CSSM_OID &serialOid = CSSMOID_X509V1SerialNumber; + CSSM_DATA_PTR serialPtr = copyFirstFieldValue(serialOid); + CssmData serial(serialPtr->Data, serialPtr->Length); + + SecPointer foundCert = NULL; + try { + foundCert = findByIssuerAndSN(keychains, issuer, serial); + } catch (...) { + foundCert = NULL; + } + + releaseFieldValue(issuerOid, issuerPtr); + releaseFieldValue(serialOid, serialPtr); + + return foundCert; +} + +SecPointer +Certificate::findByIssuerAndSN(const StorageManager::KeychainList &keychains, const CssmData &issuer, const CssmData &serialNumber) +{ + Item item; + if (!cursorForIssuerAndSN(keychains, issuer, serialNumber)->next(item)) + CssmError::throwMe(errSecItemNotFound); + + return static_cast(&*item); +} + +SecPointer +Certificate::findBySubjectKeyID(const StorageManager::KeychainList &keychains, const CssmData &subjectKeyID) +{ + Item item; + if (!cursorForSubjectKeyID(keychains, subjectKeyID)->next(item)) + CssmError::throwMe(errSecItemNotFound); + + return static_cast(&*item); +} + +SecPointer +Certificate::findByEmail(const StorageManager::KeychainList &keychains, const char *emailAddress) +{ + Item item; + if (!cursorForEmail(keychains, emailAddress)->next(item)) + CssmError::throwMe(errSecItemNotFound); + + return static_cast(&*item); +} + +/* Normalize emailAddresses in place. */ +void +Certificate::normalizeEmailAddress(CSSM_DATA &emailAddress) +{ + /* Do a check to see if a '\0' was at the end of emailAddress and strip it. */ + if (emailAddress.Length && emailAddress.Data[emailAddress.Length - 1] == '\0') + emailAddress.Length--; + bool foundAt = false; + for (uint32 ix = 0; ix < emailAddress.Length; ++ix) + { + uint8 ch = emailAddress.Data[ix]; + if (foundAt) + { + if ('A' <= ch && ch <= 'Z') + emailAddress.Data[ix] = ch + 'a' - 'A'; + } + else if (ch == '@') + foundAt = true; + } +} + +void +Certificate::getEmailAddresses(CSSM_DATA_PTR *sanValues, CSSM_DATA_PTR snValue, std::vector &emailAddresses) +{ + // Get the email addresses for this certificate, based on the + // X509 SubjectAltName and SubjectName. + + // Find the SubjectAltName fields, if any, and extract all the GNT_RFC822Name entries from all of them + if (sanValues) + { + for (CSSM_DATA_PTR *sanIx = sanValues; *sanIx; ++sanIx) + { + CSSM_DATA_PTR sanValue = *sanIx; + if (sanValue && sanValue->Data) + { + CSSM_X509_EXTENSION *cssmExt = (CSSM_X509_EXTENSION *)sanValue->Data; + CE_GeneralNames *parsedValue = (CE_GeneralNames *)cssmExt->value.parsedValue; + + /* Grab all the values that are of type GNT_RFC822Name. */ + for (uint32 i = 0; i < parsedValue->numNames; ++i) + { + if (parsedValue->generalName[i].nameType == GNT_RFC822Name) + { + if (parsedValue->generalName[i].berEncoded) // can't handle this + continue; + + emailAddresses.push_back(CssmData::overlay(parsedValue->generalName[i].name)); + } + } + } + } + } + + if (emailAddresses.empty() && snValue && snValue->Data) + { + const CSSM_X509_NAME &x509Name = *(const CSSM_X509_NAME *)snValue->Data; + for (uint32 rdnDex = 0; rdnDex < x509Name.numberOfRDNs; rdnDex++) + { + const CSSM_X509_RDN *rdnPtr = + &x509Name.RelativeDistinguishedName[rdnDex]; + for (uint32 tvpDex = 0; tvpDex < rdnPtr->numberOfPairs; tvpDex++) + { + const CSSM_X509_TYPE_VALUE_PAIR *tvpPtr = + &rdnPtr->AttributeTypeAndValue[tvpDex]; + + /* type/value pair: match caller's specified type? */ + if (((tvpPtr->type.Length != CSSMOID_EmailAddress.Length) || + memcmp(tvpPtr->type.Data, CSSMOID_EmailAddress.Data, CSSMOID_EmailAddress.Length))) { + continue; + } + + /* printable? */ + switch (tvpPtr->valueType) + { + case BER_TAG_PRINTABLE_STRING: + case BER_TAG_IA5_STRING: + case BER_TAG_T61_STRING: + case BER_TAG_PKIX_UTF8_STRING: + /* success */ + emailAddresses.push_back(CssmData::overlay(tvpPtr->value)); + break; + default: + break; + } + } /* for each pair */ + } /* for each RDN */ + } +} + +void Certificate::willRead() +{ + populateAttributes(); +} + +Boolean Certificate::isSelfSigned() +{ + StLock_(mMutex); + CSSM_DATA_PTR issuer = NULL; + CSSM_DATA_PTR subject = NULL; + OSStatus ortn = noErr; + Boolean brtn = false; + + issuer = copyFirstFieldValue(CSSMOID_X509V1IssuerNameStd); + subject = copyFirstFieldValue(CSSMOID_X509V1SubjectNameStd); + if((issuer == NULL) || (subject == NULL)) { + ortn = paramErr; + } + else if((issuer->Length == subject->Length) && + !memcmp(issuer->Data, subject->Data, issuer->Length)) { + brtn = true; + } + if(brtn) { + /* names match: verify signature */ + CSSM_RETURN crtn; + CSSM_DATA certData = data(); + crtn = CSSM_CL_CertVerify(clHandle(), 0, + &certData, &certData, NULL, 0); + if(crtn) { + brtn = false; + } + } + if(issuer) { + releaseFieldValue(CSSMOID_X509V1IssuerNameStd, issuer); + } + if(subject) { + releaseFieldValue(CSSMOID_X509V1SubjectNameStd, subject); + } + if(ortn) { + MacOSError::throwMe(ortn); + } + return brtn; +} diff --git a/libsecurity_keychain/lib/Certificate.h b/libsecurity_keychain/lib/Certificate.h new file mode 100644 index 00000000..320dc7f4 --- /dev/null +++ b/libsecurity_keychain/lib/Certificate.h @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2002-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@ + */ + +// +// Certificate.h - Certificate objects +// +#ifndef _SECURITY_CERTIFICATE_H_ +#define _SECURITY_CERTIFICATE_H_ + +#include + +#include +// @@@ This should not be here. +#include +#include + +namespace Security +{ + +namespace KeychainCore +{ + +class KeyItem; + +class Certificate : public ItemImpl +{ + NOCOPY(Certificate) +public: + SECCFFUNCTIONS(Certificate, SecCertificateRef, errSecInvalidItemRef, gTypes().Certificate) + + static CL clForType(CSSM_CERT_TYPE type); + + // new item constructor + Certificate(const CSSM_DATA &data, CSSM_CERT_TYPE type, CSSM_CERT_ENCODING encoding); + +private: + // db item constructor + Certificate(const Keychain &keychain, const PrimaryKey &primaryKey, const CssmClient::DbUniqueRecord &uniqueId); + + // PrimaryKey item constructor + Certificate(const Keychain &keychain, const PrimaryKey &primaryKey); + +public: + static Certificate* make(const Keychain &keychain, const PrimaryKey &primaryKey, const CssmClient::DbUniqueRecord &uniqueId); + static Certificate* make(const Keychain &keychain, const PrimaryKey &primaryKey); + + Certificate(Certificate &certificate); + virtual ~Certificate() throw(); + + virtual void update(); + virtual Item copyTo(const Keychain &keychain, Access *newAccess = NULL); + virtual void didModify(); // Forget any attributes and data we just wrote to the db + + const CssmData &data(); + CSSM_CERT_TYPE type(); + CSSM_CERT_ENCODING encoding(); + CFStringRef commonName(); + CFStringRef distinguishedName(const CSSM_OID *sourceOid, const CSSM_OID *componentOid); + CFStringRef copyFirstEmailAddress(); + CFArrayRef copyEmailAddresses(); + const CSSM_X509_NAME_PTR subjectName(); + const CSSM_X509_NAME_PTR issuerName(); + const CSSM_X509_ALGORITHM_IDENTIFIER_PTR algorithmID(); + CSSM_CL_HANDLE clHandle(); + void inferLabel(bool addLabel, CFStringRef *rtnString = NULL); + SecPointer publicKey(); + const CssmData &publicKeyHash(); + const CssmData &subjectKeyIdentifier(); + + static KCCursor cursorForIssuerAndSN(const StorageManager::KeychainList &keychains, const CssmData &issuer, const CssmData &serialNumber); + static KCCursor cursorForSubjectKeyID(const StorageManager::KeychainList &keychains, const CssmData &subjectKeyID); + static KCCursor cursorForEmail(const StorageManager::KeychainList &keychains, const char *emailAddress); + static KCCursor cursorForIssuerAndSN_CF(const StorageManager::KeychainList &keychains, CFDataRef issuer, CFDataRef serialNumber); + + SecPointer findInKeychain(const StorageManager::KeychainList &keychains); + static SecPointer findByIssuerAndSN(const StorageManager::KeychainList &keychains, const CssmData &issuer, const CssmData &serialNumber); + static SecPointer findBySubjectKeyID(const StorageManager::KeychainList &keychains, const CssmData &subjectKeyID); + static SecPointer findByEmail(const StorageManager::KeychainList &keychains, const char *emailAddress); + + static void normalizeEmailAddress(CSSM_DATA &emailAddress); + static void getEmailAddresses(CSSM_DATA_PTR *sanValues, CSSM_DATA_PTR snValue, std::vector &emailAddresses); + + bool operator < (Certificate &other); + bool operator == (Certificate &other); + + bool equal(SecCFObject &other); + +public: + CSSM_DATA_PTR copyFirstFieldValue(const CSSM_OID &field); + void releaseFieldValue(const CSSM_OID &field, CSSM_DATA_PTR fieldValue); + + CSSM_DATA_PTR *copyFieldValues(const CSSM_OID &field); + void releaseFieldValues(const CSSM_OID &field, CSSM_DATA_PTR *fieldValues); + Boolean isSelfSigned(); + +protected: + virtual void willRead(); + virtual PrimaryKey add(Keychain &keychain); + CSSM_HANDLE certHandle(); + + void addParsedAttribute(const CSSM_DB_ATTRIBUTE_INFO &info, const CSSM_OID &field); + + void addSubjectKeyIdentifier(); + void populateAttributes(); + +private: + bool mHaveTypeAndEncoding; + bool mPopulated; + CSSM_CERT_TYPE mType; + CSSM_CERT_ENCODING mEncoding; + CssmClient::CL mCL; + CSSM_HANDLE mCertHandle; + CssmData mPublicKeyHash; + uint8 mPublicKeyHashBytes[20]; + CssmData mSubjectKeyID; + uint8 mSubjectKeyIDBytes[20]; + CSSM_DATA_PTR mV1SubjectPublicKeyCStructValue; // Hack to prevent algorithmID() from leaking. + CSSM_DATA_PTR mV1SubjectNameCStructValue; + CSSM_DATA_PTR mV1IssuerNameCStructValue; +}; + +} // end namespace KeychainCore + +} // end namespace Security + +#endif // !_SECURITY_CERTIFICATE_H_ diff --git a/libsecurity_keychain/lib/CertificateRequest.cpp b/libsecurity_keychain/lib/CertificateRequest.cpp new file mode 100644 index 00000000..6bd86579 --- /dev/null +++ b/libsecurity_keychain/lib/CertificateRequest.cpp @@ -0,0 +1,857 @@ +/* + * 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@ + */ + +// +// CertificateRequest.cpp +// +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* one top-level prefs file for all of .mac cert requests */ +#define DOT_MAC_REQ_PREFS "com.apple.security.certreq" + +/* + * Within that dictionary is a set of per-policy dictionaries; the key in the + * top-level prefs for these dictionaries is the raw policy OID data encoded + * as an ASCII string. + * + * Within one per-policy dictionary exists a number of per-user dictionaries, + * with the username key as a string. Note that this user name, the one passed to the + * .mac server, does NOT have to have any relation to the current Unix user name; one + * Unix user can have multiple .mac accounts. + * + * + * Within the per-policy, per user dictionary are these two values, both stored + * as raw data (CFData) blobs. + */ +#define DOT_MAC_REF_ID_KEY "refId" +#define DOT_MAC_CERT_KEY "certificate" + +/* Domain for .mac cert requests */ +#define DOT_MAC_DOMAIN_KEY "domain" +#define DOT_MAC_DOMAIN "mac.com" + +/* Hosts for .mac cert requests */ +#define DOT_MAC_MGMT_HOST "certmgmt" +#define DOT_MAC_INFO_HOST "certinfo" + +/* + * Compare two CSSM_DATAs (or two CSSM_OIDs), return true if identical. + */ +bool nssCompareCssmData( + 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; + } +} + +/* any nonzero value means true */ +static bool attrBoolValue( + const SecCertificateRequestAttribute *attr) +{ + if((attr->value.Data != NULL) && + (attr->value.Length != 0) && + (attr->value.Data[0] != 0)) { + return true; + } + else { + return false; + } +} + +static void tokenizeName( + const CSSM_DATA *inName, /* required */ + CSSM_DATA *outName, /* required */ + CSSM_DATA *outDomain) /* optional */ +{ + if (!inName || !outName) return; + CSSM_SIZE idx = 0; + CSSM_SIZE stopIdx = inName->Length; + uint8 *p = inName->Data; + *outName = *inName; + if (outDomain) { + outDomain->Length = idx; + outDomain->Data = p; + } + if (!p) return; + while (idx < stopIdx) { + if (*p++ == '@') { + outName->Length = idx; + if (outDomain) { + outDomain->Length = inName->Length - (idx + 1); + outDomain->Data = p; + } + break; + } + idx++; + } +} + +using namespace KeychainCore; + +CertificateRequest::CertificateRequest(const CSSM_OID &policy, + CSSM_CERT_TYPE certificateType, + CSSM_TP_AUTHORITY_REQUEST_TYPE requestType, + SecKeyRef privateKeyItemRef, + SecKeyRef publicKeyItemRef, + const SecCertificateRequestAttributeList *attributeList, + bool isNew /* = true */) + : mAlloc(Allocator::standard()), + mTP(gGuidAppleDotMacTP), + mCL(gGuidAppleX509CL), + mPolicy(mAlloc, policy.Data, policy.Length), + mCertType(certificateType), + mReqType(requestType), + mPrivKey(NULL), + mPubKey(NULL), + mEstTime(0), + mRefId(mAlloc), + mCertState(isNew ? CRS_New : CRS_Reconstructed), + mCertData(mAlloc), + mUserName(mAlloc), + mPassword(mAlloc), + mHostName(mAlloc), + mDomain(mAlloc), + mDoRenew(false), + mIsAsync(false), + mMutex(Mutex::recursive) +{ + StLock_(mMutex); + certReqDbg("CertificateRequest construct"); + + /* Validate policy OID. */ + if(!(nssCompareCssmData(&CSSMOID_DOTMAC_CERT_REQ_IDENTITY, &policy) || + nssCompareCssmData(&CSSMOID_DOTMAC_CERT_REQ_EMAIL_SIGN, &policy) || + nssCompareCssmData(&CSSMOID_DOTMAC_CERT_REQ_EMAIL_ENCRYPT, &policy) || + nssCompareCssmData(&CSSMOID_DOTMAC_CERT_REQ_SHARED_SERVICES, &policy))) { + certReqDbg("CertificateRequest(): unknown policy oid"); + MacOSError::throwMe(paramErr); + } + if(privateKeyItemRef) { + mPrivKey = privateKeyItemRef; + CFRetain(mPrivKey); + } + if(publicKeyItemRef) { + mPubKey = publicKeyItemRef; + CFRetain(mPubKey); + } + + /* parse attr array */ + if(attributeList == NULL) { + return; + } + + bool doPendingRequest = false; + for(unsigned dex=0; dexcount; dex++) { + const SecCertificateRequestAttribute *attr = &attributeList->attr[dex]; + + if((attr->oid.Data == NULL) || (attr->value.Data == NULL)) { + MacOSError::throwMe(paramErr); + } + if(nssCompareCssmData(&CSSMOID_DOTMAC_CERT_REQ_VALUE_USERNAME, &attr->oid)) { + CSSM_DATA userName = { 0, NULL }; + CSSM_DATA domainName = { 0, NULL }; + tokenizeName(&attr->value, &userName, &domainName); + if (!domainName.Length || !domainName.Data) { + domainName.Length = strlen(DOT_MAC_DOMAIN); + domainName.Data = (uint8*) DOT_MAC_DOMAIN; + } + mUserName.copy(userName); + mDomain.copy(domainName); + } + else if(nssCompareCssmData(&CSSMOID_DOTMAC_CERT_REQ_VALUE_PASSWORD, &attr->oid)) { + mPassword.copy(attr->value); + } + else if(nssCompareCssmData(&CSSMOID_DOTMAC_CERT_REQ_VALUE_HOSTNAME, &attr->oid)) { + mHostName.copy(attr->value); + } + else if(nssCompareCssmData(&CSSMOID_DOTMAC_CERT_REQ_VALUE_RENEW, &attr->oid)) { + /* + * any nonzero value means true + * FIXME: this is deprecated, Treadstone doesn't allow this. Reject this + * request? Ignore? + */ + mDoRenew = attrBoolValue(attr); + } + else if(nssCompareCssmData(&CSSMOID_DOTMAC_CERT_REQ_VALUE_ASYNC, &attr->oid)) { + /* any nonzero value means true */ + mIsAsync = attrBoolValue(attr); + } + else if(nssCompareCssmData(&CSSMOID_DOTMAC_CERT_REQ_VALUE_IS_PENDING, &attr->oid)) { + /* any nonzero value means true */ + doPendingRequest = attrBoolValue(attr); + } + + else { + certReqDbg("CertificateRequest(): unknown name/value oid"); + MacOSError::throwMe(paramErr); + } + } + if(mCertState == CRS_Reconstructed) { + /* see if we have a refId or maybe even a cert in prefs */ + retrieveResults(); + if(mCertData.data() != NULL) { + mCertState = CRS_HaveCert; + } + else if(mRefId.data() != NULL) { + mCertState = CRS_HaveRefId; + } + else if(doPendingRequest) { + /* ask the server if there's a request pending */ + postPendingRequest(); + /* NOT REACHED - that always throws */ + } + else { + certReqDbg("CertificateRequest(): nothing in prefs"); + /* Nothing found in prefs; nothing to go by */ + MacOSError::throwMe(errSecItemNotFound); + } + } +} + +CertificateRequest::~CertificateRequest() throw() +{ + StLock_(mMutex); + certReqDbg("CertificateRequest destruct"); + + if(mPrivKey) { + CFRelease(mPrivKey); + } + if(mPubKey) { + CFRelease(mPubKey); + } +} + +#pragma mark ----- cert request submit ----- + +void CertificateRequest::submit( + sint32 *estimatedTime) +{ + StLock_(mMutex); + CSSM_DATA &policy = mPolicy.get(); + if(nssCompareCssmData(&CSSMOID_DOTMAC_CERT_REQ_IDENTITY, &policy) || + nssCompareCssmData(&CSSMOID_DOTMAC_CERT_REQ_EMAIL_SIGN, &policy) || + nssCompareCssmData(&CSSMOID_DOTMAC_CERT_REQ_EMAIL_ENCRYPT, &policy) || + nssCompareCssmData(&CSSMOID_DOTMAC_CERT_REQ_SHARED_SERVICES, &policy)) { + return submitDotMac(estimatedTime); + } + else { + /* shouldn't be here, we already validated policy in constructor */ + assert(0); + certReqDbg("CertificateRequest::submit(): bad policy"); + MacOSError::throwMe(paramErr); + } +} + +void CertificateRequest::submitDotMac( + sint32 *estimatedTime) +{ + StLock_(mMutex); + 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; + CSSM_TP_CALLERAUTH_CONTEXT callerAuth; + CSSM_FIELD policyField; + CSSM_DATA refId = {0, NULL}; + const CSSM_KEY *privKey; + const CSSM_KEY *pubKey; + OSStatus ortn; + + if(mCertState != CRS_New) { + certReqDbg("CertificateRequest: can only submit a new request"); + MacOSError::throwMe(paramErr); + } + if((mUserName.data() == NULL) || (mPassword.data() == NULL)) { + certReqDbg("CertificateRequest: user name and password required"); + MacOSError::throwMe(paramErr); + } + + /* get keys and CSP handle in CSSM terms */ + if((mPrivKey == NULL) || (mPubKey == NULL)) { + certReqDbg("CertificateRequest: pub and priv keys required"); + MacOSError::throwMe(paramErr); + } + ortn = SecKeyGetCSSMKey(mPrivKey, &privKey); + if(ortn) { + MacOSError::throwMe(ortn); + } + ortn = SecKeyGetCSSMKey(mPubKey, &pubKey); + if(ortn) { + MacOSError::throwMe(ortn); + } + ortn = SecKeyGetCSPHandle(mPrivKey, &cspHand); + if(ortn) { + MacOSError::throwMe(ortn); + } + + /* + * CSSM_X509_TYPE_VALUE_PAIR_PTR - one pair for now. + * Caller passes in user name like "johnsmith"; in the CSR, + * we write "johnsmith@mac.com". + */ + tvp.type = CSSMOID_CommonName; + tvp.valueType = BER_TAG_PKIX_UTF8_STRING; + CssmAutoData fullUserName(mAlloc); + unsigned nameLen = mUserName.length(); + unsigned domainLen = mDomain.length(); + fullUserName.malloc(nameLen + 1 + domainLen); + tvp.value = fullUserName.get(); + memmove(tvp.value.Data, mUserName.data(), nameLen); + memmove(tvp.value.Data + nameLen, "@", 1); + memmove(tvp.value.Data + nameLen + 1, mDomain.data(), domainLen); + + /* Fill in the CSSM_APPLE_DOTMAC_TP_CERT_REQUEST */ + memset(&certReq, 0, sizeof(certReq)); + certReq.version = CSSM_DOT_MAC_TP_REQ_VERSION; + certReq.cspHand = cspHand; + certReq.clHand = mCL->handle(); + certReq.numTypeValuePairs = 1; + certReq.typeValuePairs = &tvp; + certReq.publicKey = const_cast(pubKey); + certReq.privateKey = const_cast(privKey); + certReq.userName = mUserName.get(); + certReq.password = mPassword.get(); + if(mDoRenew) { + certReq.flags |= CSSM_DOTMAC_TP_SIGN_RENEW; + } + /* we don't deal with CSR here, input or output */ + + /* now the rest of the args for CSSM_TP_SubmitCredRequest() */ + reqSet.Requests = &certReq; + reqSet.NumberOfRequests = 1; + policyField.FieldOid = mPolicy; + policyField.FieldValue.Data = NULL; + policyField.FieldValue.Length = 0; + memset(&callerAuth, 0, sizeof(callerAuth)); + callerAuth.Policy.NumberOfPolicyIds = 1; + callerAuth.Policy.PolicyIds = &policyField; + ortn = SecKeyGetCredentials(mPrivKey, + CSSM_ACL_AUTHORIZATION_SIGN, + kSecCredentialTypeDefault, + const_cast(&callerAuth.CallerCredentials)); + if(ortn) { + certReqDbg("CertificateRequest: SecKeyGetCredentials error"); + MacOSError::throwMe(ortn); + } + + CssmAutoData hostName(mAlloc); + tpAuthority.AuthorityCert = NULL; + tpAuthority.AuthorityLocation = &tpNetAddrs; + tpNetAddrs.AddressType = CSSM_ADDR_NAME; + if(mHostName.data() != NULL) { + tpNetAddrs.Address = mHostName.get(); + } else { + unsigned hostLen = strlen(DOT_MAC_MGMT_HOST); + hostName.malloc(hostLen + 1 + domainLen); + tpNetAddrs.Address = hostName.get(); + memmove(tpNetAddrs.Address.Data, DOT_MAC_MGMT_HOST, hostLen); + memmove(tpNetAddrs.Address.Data + hostLen, ".", 1); + memmove(tpNetAddrs.Address.Data + hostLen + 1, mDomain.data(), domainLen); + } + tpAuthPtr = &tpAuthority; + + /* go */ + crtn = CSSM_TP_SubmitCredRequest(mTP->handle(), + tpAuthPtr, + CSSM_TP_AUTHORITY_REQUEST_CERTISSUE, + &reqSet, + &callerAuth, + &mEstTime, + &refId); // CSSM_DATA_PTR ReferenceIdentifier + + /* handle return, store results */ + switch(crtn) { + case CSSM_OK: + /* refID is a cert, we have to store it in prefs for later retrieval. */ + certReqDbg("submitDotMac: full success, storing cert"); + if(!mIsAsync) { + /* store in prefs if not running in async mode */ + ortn = storeResults(NULL, &refId); + if(ortn) { + crtn = ortn; + } + } + /* but keep a local copy too */ + mCertData.copy(refId); + mCertState = CRS_HaveCert; + if(estimatedTime) { + /* it's ready right now */ + *estimatedTime = 0; + } + break; + + case CSSMERR_APPLE_DOTMAC_REQ_QUEUED: + /* refID is the blob we use in CSSM_TP_RetrieveCredResult() */ + certReqDbg("submitDotMac: queued, storing refId"); + mRefId.copy(refId); + /* return success - this crtn is not visible at API */ + crtn = CSSM_OK; + if(!mIsAsync) { + /* store in prefs if not running in async mode */ + ortn = storeResults(&refId, NULL); + if(ortn) { + crtn = ortn; + } + } + mCertState = CRS_HaveRefId; + if(estimatedTime) { + *estimatedTime = mEstTime; + } + break; + + case CSSMERR_APPLE_DOTMAC_REQ_REDIRECT: + /* refID is a URL, caller obtains via getReturnData() */ + certReqDbg("submitDotMac: redirect"); + mRefId.copy(refId); + mCertState = CRS_HaveOtherData; + break; + + default: + /* all others are fatal errors, thrown below */ + break; + } + if(refId.Data) { + /* mallocd on our behalf by TP */ + free(refId.Data); + } + if(crtn) { + CssmError::throwMe(crtn); + } +} + +#pragma mark ----- cert request get result ----- + +void CertificateRequest::getResult( + sint32 *estimatedTime, // optional + CssmData &certData) +{ + StLock_(mMutex); + CSSM_DATA &policy = mPolicy.get(); + if(nssCompareCssmData(&CSSMOID_DOTMAC_CERT_REQ_IDENTITY, &policy) || + nssCompareCssmData(&CSSMOID_DOTMAC_CERT_REQ_EMAIL_SIGN, &policy) || + nssCompareCssmData(&CSSMOID_DOTMAC_CERT_REQ_EMAIL_ENCRYPT, &policy) || + nssCompareCssmData(&CSSMOID_DOTMAC_CERT_REQ_SHARED_SERVICES, &policy)) { + return getResultDotMac(estimatedTime, certData); + } + else { + /* shouldn't be here, we already validated policy in constructor */ + assert(0); + certReqDbg("CertificateRequest::getResult(): bad policy"); + MacOSError::throwMe(paramErr); + } +} + +void CertificateRequest::getResultDotMac( + sint32 *estimatedTime, // optional + CssmData &certData) +{ + StLock_(mMutex); + switch(mCertState) { + case CRS_HaveCert: + /* trivial case, we already have what caller is looking for */ + certReqDbg("getResultDotMac: have the cert right now"); + assert(mCertData.data() != NULL); + certData = mCertData.get(); + if(estimatedTime) { + *estimatedTime = 0; + } + break; + case CRS_HaveRefId: + { + /* ping the server */ + certReqDbg("getResultDotMac: CRS_HaveRefId; polling server"); + assert(mRefId.data() != NULL); + CSSM_BOOL ConfirmationRequired; + CSSM_TP_RESULT_SET_PTR resultSet = NULL; + CSSM_RETURN crtn; + + crtn = CSSM_TP_RetrieveCredResult(mTP->handle(), + &mRefId.get(), + NULL, // CallerAuthCredentials + &mEstTime, + &ConfirmationRequired, + &resultSet); + switch(crtn) { + case CSSM_OK: + break; + case CSSMERR_TP_CERT_NOT_VALID_YET: + /* + * By convention, this means "not ready yet". + * The dot mac server does not have a way of telling us the + * estimated time on a straight lookup like this (we only get + * an estimated completion time on the initial request), so we + * fake it. + */ + certReqDbg("getResultDotMac: polled server, not ready yet"); + if(estimatedTime) { + *estimatedTime = (mEstTime) ? mEstTime : 1; + } + MacOSError::throwMe(CSSMERR_APPLE_DOTMAC_REQ_IS_PENDING); + default: + certReqDbg("CSSM_TP_RetrieveCredResult error"); + CssmError::throwMe(crtn); + } + if(resultSet == NULL) { + certReqDbg("***CSSM_TP_RetrieveCredResult OK, but no result set"); + MacOSError::throwMe(internalComponentErr); + } + if(resultSet->NumberOfResults != 1) { + certReqDbg("***CSSM_TP_RetrieveCredResult OK, NumberOfResults (%lu)", + (unsigned long)resultSet->NumberOfResults); + MacOSError::throwMe(internalComponentErr); + } + if(resultSet->Results == NULL) { + certReqDbg("***CSSM_TP_RetrieveCredResult OK, but empty result set"); + MacOSError::throwMe(internalComponentErr); + } + certReqDbg("getResultDotMac: polled server, SUCCESS"); + CSSM_DATA_PTR result = (CSSM_DATA_PTR)resultSet->Results; + if(result->Data == NULL) { + certReqDbg("***CSSM_TP_RetrieveCredResult OK, but empty result"); + MacOSError::throwMe(internalComponentErr); + } + mCertData.copy(*result); + certData = mCertData.get(); + mCertState = CRS_HaveCert; + if(estimatedTime) { + *estimatedTime = 0; + } + + /* + * Free the stuff allocated on our behalf by TP. + * FIXME - are we sure CssmClient is using alloc, free, etc.? + */ + free(result->Data); + free(result); + free(resultSet); + break; + } + default: + /* what do we do with this? */ + certReqDbg("CertificateRequest::getResultDotMac(): bad state"); + MacOSError::throwMe(internalComponentErr); + } + + /* + * One more thing: once we pass a cert back to caller, we erase + * the record of this transaction from prefs. + */ + assert(mCertData.data() != NULL); + assert(mCertData.data() == certData.Data); + removeResults(); +} + +/* + * Obtain policy/error specific return data blob. We own the data, it's + * not copied. + */ +void CertificateRequest::getReturnData( + CssmData &rtnData) +{ + StLock_(mMutex); + rtnData = mRefId.get(); +} + +#pragma mark ----- preferences support ----- + +/* Current user as CFString, for use as key in per-policy dictionary */ +CFStringRef CertificateRequest::createUserKey() +{ + StLock_(mMutex); + return CFStringCreateWithBytes(NULL, (UInt8 *)mUserName.data(), mUserName.length(), + kCFStringEncodingUTF8, false); +} + +#define MAX_OID_LEN 2048 // way big... */ + +/* current policy as CFString, for use as key in prefs dictionary */ +CFStringRef CertificateRequest::createPolicyKey() +{ + StLock_(mMutex); + char oidstr[MAX_OID_LEN]; + unsigned char *inp = (unsigned char *)mPolicy.data(); + char *outp = oidstr; + unsigned len = mPolicy.length(); + for(unsigned dex=0; dex_(mMutex); + assert(mPolicy.data() != NULL); + assert(mUserName.data() != NULL); + assert(mDomain.data() != NULL); + + bool deleteEntry = ((refId == NULL) && (certData == NULL)); + + /* get a mutable copy of the existing prefs, or a fresh empty one */ + MutableDictionary *prefsDict = MutableDictionary::CreateMutableDictionary(DOT_MAC_REQ_PREFS, Dictionary::US_User); + if (prefsDict == NULL) + { + prefsDict = new MutableDictionary(); + } + + /* get a mutable copy of the dictionary for this policy, or a fresh empty one */ + CFStringRef policyKey = createPolicyKey(); + MutableDictionary *policyDict = prefsDict->copyMutableDictValue(policyKey); + + CFStringRef userKey = createUserKey(); + if(deleteEntry) { + /* remove user dictionary from this policy dictionary */ + policyDict->removeValue(userKey); + } + else { + /* get a mutable copy of the dictionary for this user, or a fresh empty one */ + MutableDictionary *userDict = policyDict->copyMutableDictValue(userKey); + + CFStringRef domainKey = CFStringCreateWithBytes(NULL, (UInt8 *)mDomain.data(), mDomain.length(), kCFStringEncodingUTF8, false); + userDict->setValue(CFSTR(DOT_MAC_DOMAIN_KEY), domainKey); + CFRelease(domainKey); + + /* write refId and/or cert --> user dictionary */ + if(refId) { + userDict->setDataValue(CFSTR(DOT_MAC_REF_ID_KEY), refId->Data, refId->Length); + } + if(certData) { + userDict->setDataValue(CFSTR(DOT_MAC_CERT_KEY), certData->Data, certData->Length); + } + + /* new user dictionary --> policy dictionary */ + policyDict->setValue(userKey, userDict->dict()); + delete userDict; + } + CFRelease(userKey); + + /* new policy dictionary to prefs dictionary, or nuke it */ + if(policyDict->count() == 0) { + prefsDict->removeValue(policyKey); + } + else { + prefsDict->setValue(policyKey, policyDict->dict()); + } + CFRelease(policyKey); + delete policyDict; + + /* prefs --> disk */ + OSStatus ortn = noErr; + if(!prefsDict->writePlistToPrefs(DOT_MAC_REQ_PREFS, Dictionary::US_User)) { + certReqDbg("storeResults: error writing prefs to disk"); + ortn = ioErr; + } + delete prefsDict; + return ortn; +} + +/* + * Attempt to fetch mCertData or mRefId from preferences. + */ +void CertificateRequest::retrieveResults() +{ + StLock_(mMutex); + assert(mPolicy.data() != NULL); + assert(mUserName.data() != NULL); + + /* get the .mac cert prefs as a dictionary */ + Dictionary *pd = Dictionary::CreateDictionary(DOT_MAC_REQ_PREFS, Dictionary::US_User); + if (pd == NULL) + { + certReqDbg("retrieveResults: no prefs found"); + return; + } + + auto_ptr prefsDict(pd); + + /* get dictionary for current policy */ + CFStringRef policyKey = createPolicyKey(); + Dictionary *policyDict = prefsDict->copyDictValue(policyKey); + CFRelease(policyKey); + if(policyDict != NULL) { + /* dictionary for user */ + CFStringRef userKey = createUserKey(); + Dictionary *userDict = policyDict->copyDictValue(userKey); + if(userDict != NULL) { + /* is there a cert in there? */ + CFDataRef val = userDict->getDataValue(CFSTR(DOT_MAC_CERT_KEY)); + if(val) { + mCertData.copy(CFDataGetBytePtr(val), CFDataGetLength(val)); + } + + /* how about refId? */ + val = userDict->getDataValue(CFSTR(DOT_MAC_REF_ID_KEY)); + if(val) { + mRefId.copy(CFDataGetBytePtr(val), CFDataGetLength(val)); + } + delete userDict; + } + CFRelease(userKey); + delete policyDict; + } +} + +/* + * Remove all trace of current policy/user. Called when we successfully transferred + * the cert back to caller. + */ +void CertificateRequest::removeResults() +{ + StLock_(mMutex); + assert(mPolicy.data() != NULL); + assert(mUserName.data() != NULL); + storeResults(NULL, NULL); +} + +/* + * Have the TP ping the server to see of there's a request pending for the current + * user. Always throws: either + * CSSMERR_APPLE_DOTMAC_REQ_IS_PENDING -- request pending + * CSSMERR_APPLE_DOTMAC_NO_REQ_PENDING -- no request pending + * paramErr -- no user, no password + * other gross errors, e.g. ioErr for server connection failure + * + * The distinguishing features about this TP request are: + * + * policy OID = CSSMOID_DOTMAC_CERT_REQ_{IDENTITY,EMAIL_SIGN,EMAIL_ENCRYPT,SHARED_SERVICES} + * CSSM_TP_AUTHORITY_REQUEST_TYPE = CSSM_TP_AUTHORITY_REQUEST_CERTLOOKUP + * CSSM_APPLE_DOTMAC_TP_CERT_REQUEST.flags = CSSM_DOTMAC_TP_IS_REQ_PENDING + * must have userName and password + * hostname optional as usual + */ +void CertificateRequest::postPendingRequest() +{ + StLock_(mMutex); + 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_TP_CALLERAUTH_CONTEXT callerAuth; + CSSM_FIELD policyField; + CSSM_DATA refId = {0, NULL}; + + assert(mCertState == CRS_Reconstructed); + if((mUserName.data() == NULL) || (mPassword.data() == NULL)) { + certReqDbg("postPendingRequest: user name and password required"); + MacOSError::throwMe(paramErr); + } + + /* Fill in the CSSM_APPLE_DOTMAC_TP_CERT_REQUEST */ + memset(&certReq, 0, sizeof(certReq)); + certReq.version = CSSM_DOT_MAC_TP_REQ_VERSION; + certReq.userName = mUserName.get(); + certReq.password = mPassword.get(); + certReq.flags = CSSM_DOTMAC_TP_IS_REQ_PENDING; + + /* now the rest of the args for CSSM_TP_SubmitCredRequest() */ + reqSet.Requests = &certReq; + reqSet.NumberOfRequests = 1; + /* + * This OID actually doesn't matter - right? This RPC doesn't know about + * which request we seek... + */ + policyField.FieldOid = mPolicy; + policyField.FieldValue.Data = NULL; + policyField.FieldValue.Length = 0; + memset(&callerAuth, 0, sizeof(callerAuth)); + callerAuth.Policy.NumberOfPolicyIds = 1; + callerAuth.Policy.PolicyIds = &policyField; + /* no other creds here */ + + if(mHostName.data() != NULL) { + tpAuthority.AuthorityCert = NULL; + tpAuthority.AuthorityLocation = &tpNetAddrs; + tpNetAddrs.AddressType = CSSM_ADDR_NAME; + tpNetAddrs.Address = mHostName.get(); + tpAuthPtr = &tpAuthority; + } + + /* go */ + crtn = CSSM_TP_SubmitCredRequest(mTP->handle(), + tpAuthPtr, + CSSM_TP_AUTHORITY_REQUEST_CERTLOOKUP, + &reqSet, + &callerAuth, + &mEstTime, + &refId); // CSSM_DATA_PTR ReferenceIdentifier + + if(refId.Data) { + /* shouldn't be any but just in case.... */ + free(refId.Data); + } + switch(crtn) { + case CSSMERR_APPLE_DOTMAC_REQ_IS_PENDING: + certReqDbg("postPendingRequest: REQ_IS_PENDING"); + break; + case CSSMERR_APPLE_DOTMAC_NO_REQ_PENDING: + certReqDbg("postPendingRequest: NO_REQ_PENDING"); + break; + case CSSM_OK: + /* should never happen */ + certReqDbg("postPendingRequest: unexpected success!"); + crtn = internalComponentErr; + break; + default: + certReqDbg("postPendingRequest: unexpected rtn %lu", (unsigned long)crtn); + break; + } + CssmError::throwMe(crtn); +} + diff --git a/libsecurity_keychain/lib/CertificateRequest.h b/libsecurity_keychain/lib/CertificateRequest.h new file mode 100644 index 00000000..9f45b6dd --- /dev/null +++ b/libsecurity_keychain/lib/CertificateRequest.h @@ -0,0 +1,154 @@ +/* + * 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@ + */ + +// +// CertificateRequest.h +// +#ifndef _SECURITY_CERTIFICATEREQUEST_H_ +#define _SECURITY_CERTIFICATEREQUEST_H_ + +#include +#include +#include "SecCFTypes.h" +#include +#include +#include +#include +#include +#include + +#define certReqDbg(args...) secdebug("certReq", ## args) + +namespace Security +{ + +namespace KeychainCore +{ + +class CertificateRequest : public SecCFObject +{ + NOCOPY(CertificateRequest) +public: + SECCFFUNCTIONS(CertificateRequest, SecCertificateRequestRef, errSecInvalidItemRef, gTypes().CertificateRequest) + + CertificateRequest(const CSSM_OID &policy, + CSSM_CERT_TYPE certificateType, + CSSM_TP_AUTHORITY_REQUEST_TYPE requestType, + SecKeyRef privateKeyItemRef, // optional + SecKeyRef publicKeyItemRef, // optional + const SecCertificateRequestAttributeList *attributeList, + /* + * true when called from SecCertificateRequestCreate, cooking up a new + * request from scratch + * false when called from SecCertificateFindRequest, recomnstructing + * a request in progress + */ + bool isNew = true); + + virtual ~CertificateRequest() throw(); + + void submit( + sint32 *estimatedTime); + void getResult( + sint32 *estimatedTime, // optional + CssmData &certData); + + /* + * Obtain policy/error specific return data blob. We own the data, it's + * not copied. + */ + void getReturnData( + CssmData &rtnData); + + CSSM_CERT_TYPE certType() { return mCertType; } + CSSM_TP_AUTHORITY_REQUEST_TYPE reqType() { return mReqType; } + +private: + void submitDotMac( + sint32 *estimatedTime); + void getResultDotMac( + sint32 *estimatedTime, // optional + CssmData &certData); + void postPendingRequest(); + + /* preferences support */ + CFStringRef createUserKey(); + CFStringRef createPolicyKey(); + CFDictionaryRef getPolicyDictionary( + CFDictionaryRef prefsDict); + CFDictionaryRef getUserDictionary( + CFDictionaryRef policyDict); + + /* + * Preferences storage and retrieval. + * Both assume valid mPolicy and mUserName. storeResults stores the + * specified data; retrieveResults retrieves whatever is found in the + * prefs dictionary and restores to mRefId or mCert as appropriate. + */ + OSStatus storeResults( + const CSSM_DATA *refId, // optional, for queued requests + const CSSM_DATA *certDat); // optional, for immediate completion + void retrieveResults(); + void removeResults(); + + typedef enum { + CRS_New = 0, // created via SecCertificateRequestCreate + CRS_Reconstructed, // created via SecCertificateFindRequest + CRS_HaveCert, // completed request one way or another, have a good cert + CRS_HaveRefId, // submitted request, have RefId for later retrieval + CRS_HaveOtherData // submitted request, have other data in mRefId + } CertReqState; + + Allocator &mAlloc; + CssmClient::TP mTP; + CssmClient::CL mCL; + CssmAutoData mPolicy; /* i.e., "CssmAutoOid" */ + CSSM_CERT_TYPE mCertType; + CSSM_TP_AUTHORITY_REQUEST_TYPE mReqType; + SecKeyRef mPrivKey; + SecKeyRef mPubKey; + sint32 mEstTime; + CssmAutoData mRefId; /* returned from SubmitCredRequest() */ + CertReqState mCertState; + CssmAutoData mCertData; + + /* + * The incoming SecCertificateRequestAttributeList oid/value pairs + * map to these: + */ + CssmAutoData mUserName; + CssmAutoData mPassword; /* optional (lookup doesn't use it) */ + CssmAutoData mHostName; /* optional */ + CssmAutoData mDomain; /* optional */ + bool mDoRenew; + bool mIsAsync; /* true means no persistent state + * stored in user prefs; default + * is false */ + Mutex mMutex; +}; + +} // end namespace KeychainCore + +} // end namespace Security + +#endif // !_SECURITY_CERTIFICATEREQUEST_H_ diff --git a/libsecurity_keychain/lib/CertificateValues.cpp b/libsecurity_keychain/lib/CertificateValues.cpp new file mode 100644 index 00000000..b3aa9045 --- /dev/null +++ b/libsecurity_keychain/lib/CertificateValues.cpp @@ -0,0 +1,562 @@ +/* + * 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@ + */ + +// +// CertificateValues.cpp +// +#include +#include +#include +#include +#include +#include +#include "SecCertificateOIDs.h" +#include "CertificateValues.h" +#include "SecCertificateP.h" +#include "SecCertificatePrivP.h" +#include +#include "SecCertificateP.h" + +extern "C" void appendProperty(CFMutableArrayRef properties, CFStringRef propertyType, CFStringRef label, CFTypeRef value); + +extern CFStringRef kSecPropertyKeyType; +extern CFStringRef kSecPropertyKeyLabel; +extern CFStringRef kSecPropertyKeyLocalizedLabel; +extern CFStringRef kSecPropertyKeyValue; + +extern CFStringRef kSecPropertyTypeData; +extern CFStringRef kSecPropertyTypeString; +extern CFStringRef kSecPropertyTypeURL; +extern CFStringRef kSecPropertyTypeDate; + +CFStringRef kSecPropertyTypeArray = CFSTR("array"); +CFStringRef kSecPropertyTypeNumber = CFSTR("number"); + + +#pragma mark ---------- CertificateValues Implementation ---------- + +using namespace KeychainCore; + +void addFieldValues(const void *key, const void *value, void *context); +void addPropertyToFieldValues(const void *value, void *context); +void filterFieldValues(const void *key, const void *value, void *context); +void validateKeys(const void *value, void *context); + +CFDictionaryRef CertificateValues::mOIDRemap = NULL; + +typedef struct FieldValueFilterContext +{ + CFMutableDictionaryRef filteredValues; + CFArrayRef filterKeys; +} FieldValueFilterContext; + +CertificateValues::CertificateValues(SecCertificateRef certificateRef) : mCertificateRef(certificateRef), + mCertificateData(NULL) +{ + if (mCertificateRef) + CFRetain(mCertificateRef); +} + +CertificateValues::~CertificateValues() throw() +{ + if (mCertificateData) + CFRelease(mCertificateData); + if (mCertificateRef) + CFRelease(mCertificateRef); +} + +CFDictionaryRef CertificateValues::copyFieldValues(CFArrayRef keys, CFErrorRef *error) +{ + if (keys) + { + if (CFGetTypeID(keys)!=CFArrayGetTypeID()) + return NULL; + CFRange range = CFRangeMake(0, CFArrayGetCount((CFArrayRef)keys)); + bool failed = false; + CFArrayApplyFunction(keys, range, validateKeys, &failed); + if (failed) + return NULL; + } + + if (mCertificateData) + { + CFRelease(mCertificateData); + mCertificateData = NULL; + } + if (!mCertificateData) + { + mCertificateData = SecCertificateCopyData(mCertificateRef); // OK to call, no big lock + if (!mCertificateData) + { + if (error) { + *error = CFErrorCreate(NULL, kCFErrorDomainOSStatus, errSecInvalidCertificateRef, NULL); + } + return NULL; + } + } + + SecCertificateRefP certificateP = SecCertificateCreateWithDataP(kCFAllocatorDefault, mCertificateData); + if (!certificateP) + { + if (error) + *error = CFErrorCreate(NULL, kCFErrorDomainOSStatus, errSecInvalidCertificateGroup, NULL); + return NULL; + } + + CFMutableDictionaryRef fieldValues=CFDictionaryCreateMutable(kCFAllocatorDefault, 0, + &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + + // Return an array of CFStringRefs representing the common names in the certificates subject if any + CFArrayRef commonNames=SecCertificateCopyCommonNames(certificateP); + if (commonNames) + { + CFMutableArrayRef additionalValues = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); + appendProperty(additionalValues, kSecPropertyTypeArray, CFSTR("CN"), commonNames); + CFDictionaryAddValue(fieldValues, kSecOIDCommonName, (CFTypeRef)CFArrayGetValueAtIndex(additionalValues, 0)); + CFRelease(commonNames); + CFRelease(additionalValues); + } + + // These can exist in the subject alt name or in the subject + CFArrayRef dnsNames=SecCertificateCopyDNSNames(certificateP); + if (dnsNames) + { + CFMutableArrayRef additionalValues = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); + appendProperty(additionalValues, kSecPropertyTypeArray, CFSTR("DNS"), dnsNames); + CFDictionaryAddValue(fieldValues, CFSTR("DNSNAMES"), (CFTypeRef)CFArrayGetValueAtIndex(additionalValues, 0)); + CFRelease(dnsNames); + CFRelease(additionalValues); + } + + CFArrayRef ipAddresses=SecCertificateCopyIPAddresses(certificateP); + if (ipAddresses) + { + CFMutableArrayRef additionalValues = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); + appendProperty(additionalValues, kSecPropertyTypeArray, CFSTR("IP"), dnsNames); + CFDictionaryAddValue(fieldValues, CFSTR("IPADDRESSES"), (CFTypeRef)CFArrayGetValueAtIndex(additionalValues, 0)); + CFRelease(ipAddresses); + CFRelease(additionalValues); + } + + // These can exist in the subject alt name or in the subject + CFArrayRef emailAddrs=SecCertificateCopyRFC822Names(certificateP); + if (emailAddrs) + { + CFMutableArrayRef additionalValues = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); + appendProperty(additionalValues, kSecPropertyTypeArray, CFSTR("DNS"), dnsNames); + CFDictionaryAddValue(fieldValues, kSecOIDEmailAddress, (CFTypeRef)CFArrayGetValueAtIndex(additionalValues, 0)); + CFRelease(emailAddrs); + CFRelease(additionalValues); + } + + CFAbsoluteTime notBefore = SecCertificateNotValidBefore(certificateP); + CFNumberRef notBeforeRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, ¬Before); + if (notBeforeRef) + { + CFMutableArrayRef additionalValues = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); + appendProperty(additionalValues, kSecPropertyTypeNumber, CFSTR("Not Valid Before"), notBeforeRef); + CFDictionaryAddValue(fieldValues, kSecOIDX509V1ValidityNotBefore, (CFTypeRef)CFArrayGetValueAtIndex(additionalValues, 0)); + CFRelease(notBeforeRef); + CFRelease(additionalValues); + } + + CFAbsoluteTime notAfter = SecCertificateNotValidAfter(certificateP); + CFNumberRef notAfterRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, ¬After); + if (notAfterRef) + { + CFMutableArrayRef additionalValues = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); + appendProperty(additionalValues, kSecPropertyTypeNumber, CFSTR("Not Valid After"), notAfterRef); + CFDictionaryAddValue(fieldValues, kSecOIDX509V1ValidityNotAfter, (CFTypeRef)CFArrayGetValueAtIndex(additionalValues, 0)); + CFRelease(notAfterRef); + CFRelease(additionalValues); + } + + SecKeyUsage keyUsage=SecCertificateGetKeyUsage(certificateP); + CFNumberRef ku = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &keyUsage); + if (ku) + { + CFMutableArrayRef additionalValues = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); + appendProperty(additionalValues, kSecPropertyTypeNumber, CFSTR("Key Usage"), ku); + CFDictionaryAddValue(fieldValues, kSecOIDKeyUsage, (CFTypeRef)CFArrayGetValueAtIndex(additionalValues, 0)); + CFRelease(ku); + CFRelease(additionalValues); + } + + CFArrayRef ekus = SecCertificateCopyExtendedKeyUsage(certificateP); + if (ekus) + { + CFMutableArrayRef additionalValues = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); + appendProperty(additionalValues, kSecPropertyTypeArray, CFSTR("Extended Key Usage"), ekus); + CFDictionaryAddValue(fieldValues, kSecOIDExtendedKeyUsage, (CFTypeRef)CFArrayGetValueAtIndex(additionalValues, 0)); + CFRelease(ekus); + CFRelease(additionalValues); + } + + // Add all values from properties dictionary + CFArrayRef properties = SecCertificateCopyProperties(certificateP); + if (properties) + { + CFRange range = CFRangeMake(0, CFArrayGetCount((CFArrayRef)properties)); + CFArrayApplyFunction(properties, range, addPropertyToFieldValues, fieldValues); + // CFDictionaryApplyFunction(properties, addFieldValues, fieldValues); + CFRelease(properties); + } + + CFAbsoluteTime verifyTime = CFAbsoluteTimeGetCurrent(); + CFMutableArrayRef summaryProperties = + SecCertificateCopySummaryProperties(certificateP, verifyTime); + if (summaryProperties) + { + CFRange range = CFRangeMake(0, CFArrayGetCount((CFArrayRef)summaryProperties)); + CFArrayApplyFunction(summaryProperties, range, addPropertyToFieldValues, fieldValues); +// CFDictionaryApplyFunction(summaryProperties, addFieldValues, fieldValues); +// CFDictionaryAddValue(fieldValues, CFSTR("summaryProperties"), summaryProperties); + CFRelease(summaryProperties); + } + + if (certificateP) + CFRelease(certificateP); + + if (keys==NULL) + return (CFDictionaryRef)fieldValues; + + // Otherwise, we need to filter + CFMutableDictionaryRef filteredFieldValues=CFDictionaryCreateMutable(kCFAllocatorDefault, 0, + &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + + FieldValueFilterContext fvcontext; + fvcontext.filteredValues = filteredFieldValues; + fvcontext.filterKeys = keys; + + CFDictionaryApplyFunction(fieldValues, filterFieldValues, &fvcontext); + + CFRelease(fieldValues); + return (CFDictionaryRef)filteredFieldValues; +} + +void validateKeys(const void *value, void *context) +{ + if (value == NULL || (CFGetTypeID(value)!=CFStringGetTypeID())) + if (context) + *(bool *)context = true; +} + +void filterFieldValues(const void *key, const void *value, void *context) +{ + // each element of keys is a CFStringRef with an OID, e.g. + // CFTypeRef kSecOIDTitle = CFSTR("2.5.4.12"); + + CFTypeRef fieldKey = (CFTypeRef)key; + if (fieldKey == NULL || (CFGetTypeID(fieldKey)!=CFStringGetTypeID()) || context==NULL) + return; + + FieldValueFilterContext *fvcontext = (FieldValueFilterContext *)context; + + CFRange range = CFRangeMake(0, CFArrayGetCount(fvcontext->filterKeys)); + CFIndex idx = CFArrayGetFirstIndexOfValue(fvcontext->filterKeys, range, fieldKey); + if (idx != kCFNotFound) + CFDictionaryAddValue(fvcontext->filteredValues, fieldKey, value); +} + +void addFieldValues(const void *key, const void *value, void *context) +{ + CFMutableDictionaryRef fieldValues = (CFMutableDictionaryRef)context; + CFDictionaryAddValue(fieldValues, key, value); +} + +void addPropertyToFieldValues(const void *value, void *context) +{ + CFMutableDictionaryRef fieldValues = (CFMutableDictionaryRef)context; + if (CFGetTypeID(value)==CFDictionaryGetTypeID()) + { + CFStringRef label = (CFStringRef)CFDictionaryGetValue((CFDictionaryRef)value, kSecPropertyKeyLabel); +#if 0 + CFStringRef typeD = (CFStringRef)CFDictionaryGetValue((CFDictionaryRef)value, kSecPropertyKeyType); + CFTypeRef valueD = (CFStringRef)CFDictionaryGetValue((CFDictionaryRef)value, kSecPropertyKeyValue); +#endif + CFStringRef key = CertificateValues::remapLabelToKey(label); + if (key) + CFDictionaryAddValue(fieldValues, key, value); + } +} + +CFStringRef CertificateValues::remapLabelToKey(CFStringRef label) +{ + if (!label) + return NULL; + + if (!mOIDRemap) + { + CFTypeRef keys[] = + { + CFSTR("Subject Name"), + CFSTR("Normalized Subject Name"), + CFSTR("Issuer Name"), + CFSTR("Normalized Subject Name"), + CFSTR("Version"), + CFSTR("Serial Number"), + CFSTR("Signature Algorithm"), + CFSTR("Subject Unique ID"), + CFSTR("Issuer Unique ID"), + CFSTR("Public Key Algorithm"), + CFSTR("Public Key Data"), + CFSTR("Signature"), + CFSTR("Not Valid Before"), + CFSTR("Not Valid After"), + CFSTR("Expires") + }; + + CFTypeRef values[] = + { + kSecOIDX509V1SubjectName, + kSecOIDX509V1SubjectNameStd, + kSecOIDX509V1IssuerName, + kSecOIDX509V1IssuerNameStd, + kSecOIDX509V1Version, + kSecOIDX509V1SerialNumber, + kSecOIDX509V1SignatureAlgorithm, // or CSSMOID_X509V1SignatureAlgorithmTBS? + kSecOIDX509V1CertificateSubjectUniqueId, + kSecOIDX509V1CertificateIssuerUniqueId, + kSecOIDX509V1SubjectPublicKeyAlgorithm, + kSecOIDX509V1SubjectPublicKey, + kSecOIDX509V1Signature, + kSecOIDX509V1ValidityNotBefore, + kSecOIDX509V1ValidityNotAfter, + kSecOIDInvalidityDate + }; + + mOIDRemap = CFDictionaryCreate(NULL, keys, values, + (sizeof(keys) / sizeof(*keys)), &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + } + + CFTypeRef result = (CFTypeRef)CFDictionaryGetValue(mOIDRemap, label); + + return result?(CFStringRef)result:label; +} + +CFDataRef CertificateValues::copySerialNumber(CFErrorRef *error) +{ + CFDataRef result = NULL; + SecCertificateRefP certificateP = getSecCertificateRefP(error); + + if (certificateP) + { + result = SecCertificateCopySerialNumberP(certificateP); + CFRelease(certificateP); + } + return result; +} + +CFDataRef CertificateValues::getNormalizedIssuerContent(CFErrorRef *error) +{ + // We wrap with SecDERItemCopySequence, since SecItemCopyMatching expects it + CFDataRef result = NULL; + SecCertificateRefP certificateP = getSecCertificateRefP(error); + if (certificateP) + { + result = SecCertificateGetNormalizedIssuer(certificateP); + CFRelease(certificateP); + } + return result; +} + +CFDataRef CertificateValues::getNormalizedSubjectContent(CFErrorRef *error) +{ + // We wrap with SecDERItemCopySequence, since SecItemCopyMatching expects it + CFDataRef result = NULL; + SecCertificateRefP certificateP = getSecCertificateRefP(error); + if (certificateP) + { + result = SecCertificateGetNormalizedSubject(certificateP); + CFRelease(certificateP); + } + return result; +} + +bool CertificateValues::SecCertificateIsValidX(CFAbsoluteTime verifyTime, CFErrorRef *error) +{ + // We wrap with SecDERItemCopySequence, since SecItemCopyMatching expects it + bool result = NULL; + SecCertificateRefP certificateP = getSecCertificateRefP(error); + if (certificateP) + { + result = SecCertificateIsValid(certificateP, verifyTime); + CFRelease(certificateP); + } + return result; +} + +SecCertificateRefP CertificateValues::getSecCertificateRefP(CFErrorRef *error) +{ + // SecCertificateCopyData returns an object created with CFDataCreate, so we + // own it and must release it + + if (mCertificateData) + { + CFRelease(mCertificateData); + mCertificateData = NULL; + } + + mCertificateData = SecCertificateCopyData(mCertificateRef); // OK to call, no big lock + if (!mCertificateData && error) + { + *error = CFErrorCreate(NULL, kCFErrorDomainOSStatus, errSecInvalidCertificateRef, NULL); + return NULL; + } + + SecCertificateRefP certificateP = SecCertificateCreateWithDataP(kCFAllocatorDefault, mCertificateData); + if (!certificateP && error) + { + *error = CFErrorCreate(NULL, kCFErrorDomainOSStatus, errSecInvalidCertificateGroup, NULL); + return NULL; + } + + return certificateP; +} + +#pragma mark ---------- OID Constants ---------- + +CFTypeRef kSecOIDADC_CERT_POLICY = CFSTR("1.2.840.113635.100.5.3"); +CFTypeRef kSecOIDAPPLE_CERT_POLICY = CFSTR("1.2.840.113635.100.5.1"); +CFTypeRef kSecOIDAPPLE_EKU_CODE_SIGNING = CFSTR("1.2.840.113635.100.4.1"); +CFTypeRef kSecOIDAPPLE_EKU_CODE_SIGNING_DEV = CFSTR("1.2.840.113635.100.4.1.1"); +CFTypeRef kSecOIDAPPLE_EKU_ICHAT_ENCRYPTION = CFSTR("1.2.840.113635.100.4.3"); +CFTypeRef kSecOIDAPPLE_EKU_ICHAT_SIGNING = CFSTR("1.2.840.113635.100.4.2"); +CFTypeRef kSecOIDAPPLE_EKU_RESOURCE_SIGNING = CFSTR("1.2.840.113635.100.4.1.4"); +CFTypeRef kSecOIDAPPLE_EKU_SYSTEM_IDENTITY = CFSTR("1.2.840.113635.100.4.4"); +CFTypeRef kSecOIDAPPLE_EXTENSION = CFSTR("1.2.840.113635.100.6"); +CFTypeRef kSecOIDAPPLE_EXTENSION_ADC_APPLE_SIGNING = CFSTR("1.2.840.113635.100.6.1.2.0.0"); +CFTypeRef kSecOIDAPPLE_EXTENSION_ADC_DEV_SIGNING = CFSTR("1.2.840.113635.100.6.1.2.0"); +CFTypeRef kSecOIDAPPLE_EXTENSION_APPLE_SIGNING = CFSTR("1.2.840.113635.100.6.1.1"); +CFTypeRef kSecOIDAPPLE_EXTENSION_CODE_SIGNING = CFSTR("1.2.840.113635.100.6.1"); +CFTypeRef kSecOIDAPPLE_EXTENSION_INTERMEDIATE_MARKER = CFSTR("1.2.840.113635.100.6.2"); +CFTypeRef kSecOIDAPPLE_EXTENSION_WWDR_INTERMEDIATE = CFSTR("1.2.840.113635.100.6.2.1"); +CFTypeRef kSecOIDAPPLE_EXTENSION_ITMS_INTERMEDIATE = CFSTR("1.2.840.113635.100.6.2.2"); +CFTypeRef kSecOIDAPPLE_EXTENSION_AAI_INTERMEDIATE = CFSTR("1.2.840.113635.100.6.2.3"); +CFTypeRef kSecOIDAPPLE_EXTENSION_APPLEID_INTERMEDIATE = CFSTR("1.2.840.113635.100.6.2.7"); +CFTypeRef kSecOIDAuthorityInfoAccess = CFSTR("1.3.6.1.5.5.7.1.1"); +CFTypeRef kSecOIDAuthorityKeyIdentifier = CFSTR("2.5.29.35"); +CFTypeRef kSecOIDBasicConstraints = CFSTR("2.5.29.19"); +CFTypeRef kSecOIDBiometricInfo = CFSTR("1.3.6.1.5.5.7.1.2"); +CFTypeRef kSecOIDCSSMKeyStruct = CFSTR("2.16.840.1.113741.2.1.1.1.20"); +CFTypeRef kSecOIDCertIssuer = CFSTR("2.5.29.29"); +CFTypeRef kSecOIDCertificatePolicies = CFSTR("2.5.29.32"); +CFTypeRef kSecOIDClientAuth = CFSTR("1.3.6.1.5.5.7.3.2"); +CFTypeRef kSecOIDCollectiveStateProvinceName = CFSTR("2.5.4.8.1"); +CFTypeRef kSecOIDCollectiveStreetAddress = CFSTR("2.5.4.9.1"); +CFTypeRef kSecOIDCommonName = CFSTR("2.5.4.3"); +CFTypeRef kSecOIDCountryName = CFSTR("2.5.4.6"); +CFTypeRef kSecOIDCrlDistributionPoints = CFSTR("2.5.29.31"); +CFTypeRef kSecOIDCrlNumber = CFSTR("2.5.29.20"); +CFTypeRef kSecOIDCrlReason = CFSTR("2.5.29.21"); +CFTypeRef kSecOIDDOTMAC_CERT_EMAIL_ENCRYPT = CFSTR("1.2.840.113635.100.3.2.3"); +CFTypeRef kSecOIDDOTMAC_CERT_EMAIL_SIGN = CFSTR("1.2.840.113635.100.3.2.2"); +CFTypeRef kSecOIDDOTMAC_CERT_EXTENSION = CFSTR("1.2.840.113635.100.3.2"); +CFTypeRef kSecOIDDOTMAC_CERT_IDENTITY = CFSTR("1.2.840.113635.100.3.2.1"); +CFTypeRef kSecOIDDOTMAC_CERT_POLICY = CFSTR("1.2.840.113635.100.5.2"); +CFTypeRef kSecOIDDeltaCrlIndicator = CFSTR("2.5.29.27"); +CFTypeRef kSecOIDDescription = CFSTR("2.5.4.13"); +CFTypeRef kSecOIDEKU_IPSec = CFSTR("1.3.6.1.5.5.8.2.2"); +CFTypeRef kSecOIDEmailAddress = CFSTR("1.2.840.113549.1.9.1"); +CFTypeRef kSecOIDEmailProtection = CFSTR("1.3.6.1.5.5.7.3.4"); +CFTypeRef kSecOIDExtendedKeyUsage = CFSTR("2.5.29.37"); +CFTypeRef kSecOIDExtendedKeyUsageAny = CFSTR("2.5.29.37.0"); +CFTypeRef kSecOIDExtendedUseCodeSigning = CFSTR("1.3.6.1.5.5.7.3.3"); +CFTypeRef kSecOIDGivenName = CFSTR("2.5.4.42"); +CFTypeRef kSecOIDHoldInstructionCode = CFSTR("2.5.29.23"); +CFTypeRef kSecOIDInvalidityDate = CFSTR("2.5.29.24"); +CFTypeRef kSecOIDIssuerAltName = CFSTR("2.5.29.18"); +CFTypeRef kSecOIDIssuingDistributionPoint = CFSTR("2.5.29.28"); +CFTypeRef kSecOIDIssuingDistributionPoints = CFSTR("2.5.29.28"); +CFTypeRef kSecOIDKERBv5_PKINIT_KP_CLIENT_AUTH = CFSTR("1.3.6.1.5.2.3.4"); +CFTypeRef kSecOIDKERBv5_PKINIT_KP_KDC = CFSTR("1.3.6.1.5.2.3.5"); +CFTypeRef kSecOIDKeyUsage = CFSTR("2.5.29.15"); +CFTypeRef kSecOIDLocalityName = CFSTR("2.5.4.7"); +CFTypeRef kSecOIDMS_NTPrincipalName = CFSTR("1.3.6.1.4.1.311.20.2.3"); +CFTypeRef kSecOIDMicrosoftSGC = CFSTR("1.3.6.1.4.1.311.10.3.3"); +CFTypeRef kSecOIDNameConstraints = CFSTR("2.5.29.30"); +CFTypeRef kSecOIDNetscapeCertSequence = CFSTR("2.16.840.1.113730.2.5"); +CFTypeRef kSecOIDNetscapeCertType = CFSTR("2.16.840.1.113730.1.1"); +CFTypeRef kSecOIDNetscapeSGC = CFSTR("2.16.840.1.113730.4.1"); +CFTypeRef kSecOIDOCSPSigning = CFSTR("1.3.6.1.5.5.7.3.9"); +CFTypeRef kSecOIDOrganizationName = CFSTR("2.5.4.10"); +CFTypeRef kSecOIDOrganizationalUnitName = CFSTR("2.5.4.11"); +CFTypeRef kSecOIDPolicyConstraints = CFSTR("2.5.29.36"); +CFTypeRef kSecOIDPolicyMappings = CFSTR("2.5.29.33"); +CFTypeRef kSecOIDPrivateKeyUsagePeriod = CFSTR("2.5.29.16"); +CFTypeRef kSecOIDQC_Statements = CFSTR("1.3.6.1.5.5.7.1.3"); +CFTypeRef kSecOIDSerialNumber = CFSTR("2.5.4.5"); +CFTypeRef kSecOIDServerAuth = CFSTR("1.3.6.1.5.5.7.3.1"); +CFTypeRef kSecOIDStateProvinceName = CFSTR("2.5.4.8"); +CFTypeRef kSecOIDStreetAddress = CFSTR("2.5.4.9"); +CFTypeRef kSecOIDSubjectAltName = CFSTR("2.5.29.17"); +CFTypeRef kSecOIDSubjectDirectoryAttributes = CFSTR("2.5.29.9"); +CFTypeRef kSecOIDSubjectEmailAddress = CFSTR("2.16.840.1.113741.2.1.1.1.50.3"); +CFTypeRef kSecOIDSubjectInfoAccess = CFSTR("1.3.6.1.5.5.7.1.11"); +CFTypeRef kSecOIDSubjectKeyIdentifier = CFSTR("2.5.29.14"); +CFTypeRef kSecOIDSubjectPicture = CFSTR("2.16.840.1.113741.2.1.1.1.50.2"); +CFTypeRef kSecOIDSubjectSignatureBitmap = CFSTR("2.16.840.1.113741.2.1.1.1.50.1"); +CFTypeRef kSecOIDSurname = CFSTR("2.5.4.4"); +CFTypeRef kSecOIDTimeStamping = CFSTR("1.3.6.1.5.5.7.3.8"); +CFTypeRef kSecOIDTitle = CFSTR("2.5.4.12"); +CFTypeRef kSecOIDUseExemptions = CFSTR("2.16.840.1.113741.2.1.1.1.50.4"); +CFTypeRef kSecOIDX509V1CertificateIssuerUniqueId = CFSTR("2.16.840.1.113741.2.1.1.1.11"); +CFTypeRef kSecOIDX509V1CertificateSubjectUniqueId = CFSTR("2.16.840.1.113741.2.1.1.1.12"); +CFTypeRef kSecOIDX509V1IssuerName = CFSTR("2.16.840.1.113741.2.1.1.1.5"); +CFTypeRef kSecOIDX509V1IssuerNameCStruct = CFSTR("2.16.840.1.113741.2.1.1.1.5.1"); +CFTypeRef kSecOIDX509V1IssuerNameLDAP = CFSTR("2.16.840.1.113741.2.1.1.1.5.2"); +CFTypeRef kSecOIDX509V1IssuerNameStd = CFSTR("2.16.840.1.113741.2.1.1.1.23"); +CFTypeRef kSecOIDX509V1SerialNumber = CFSTR("2.16.840.1.113741.2.1.1.1.3"); +CFTypeRef kSecOIDX509V1Signature = CFSTR("2.16.840.1.113741.2.1.3.2.2"); +CFTypeRef kSecOIDX509V1SignatureAlgorithm = CFSTR("2.16.840.1.113741.2.1.3.2.1"); +CFTypeRef kSecOIDX509V1SignatureAlgorithmParameters = CFSTR("2.16.840.1.113741.2.1.3.2.3"); +CFTypeRef kSecOIDX509V1SignatureAlgorithmTBS = CFSTR("2.16.840.1.113741.2.1.3.2.10"); +CFTypeRef kSecOIDX509V1SignatureCStruct = CFSTR("2.16.840.1.113741.2.1.3.2.0.1"); +CFTypeRef kSecOIDX509V1SignatureStruct = CFSTR("2.16.840.1.113741.2.1.3.2.0"); +CFTypeRef kSecOIDX509V1SubjectName = CFSTR("2.16.840.1.113741.2.1.1.1.8"); +CFTypeRef kSecOIDX509V1SubjectNameCStruct = CFSTR("2.16.840.1.113741.2.1.1.1.8.1"); +CFTypeRef kSecOIDX509V1SubjectNameLDAP = CFSTR("2.16.840.1.113741.2.1.1.1.8.2"); +CFTypeRef kSecOIDX509V1SubjectNameStd = CFSTR("2.16.840.1.113741.2.1.1.1.22"); +CFTypeRef kSecOIDX509V1SubjectPublicKey = CFSTR("2.16.840.1.113741.2.1.1.1.10"); +CFTypeRef kSecOIDX509V1SubjectPublicKeyAlgorithm = CFSTR("2.16.840.1.113741.2.1.1.1.9"); +CFTypeRef kSecOIDX509V1SubjectPublicKeyAlgorithmParameters = CFSTR("2.16.840.1.113741.2.1.1.1.18"); +CFTypeRef kSecOIDX509V1SubjectPublicKeyCStruct = CFSTR("2.16.840.1.113741.2.1.1.1.20.1"); +CFTypeRef kSecOIDX509V1ValidityNotAfter = CFSTR("2.16.840.1.113741.2.1.1.1.7"); +CFTypeRef kSecOIDX509V1ValidityNotBefore = CFSTR("2.16.840.1.113741.2.1.1.1.6"); +CFTypeRef kSecOIDX509V1Version = CFSTR("2.16.840.1.113741.2.1.1.1.2"); +CFTypeRef kSecOIDX509V3Certificate = CFSTR("2.16.840.1.113741.2.1.1.1.1"); +CFTypeRef kSecOIDX509V3CertificateCStruct = CFSTR("2.16.840.1.113741.2.1.1.1.1.1"); +CFTypeRef kSecOIDX509V3CertificateExtensionCStruct = CFSTR("2.16.840.1.113741.2.1.1.1.13.1"); +CFTypeRef kSecOIDX509V3CertificateExtensionCritical = CFSTR("2.16.840.1.113741.2.1.1.1.16"); +CFTypeRef kSecOIDX509V3CertificateExtensionId = CFSTR("2.16.840.1.113741.2.1.1.1.15"); +CFTypeRef kSecOIDX509V3CertificateExtensionStruct = CFSTR("2.16.840.1.113741.2.1.1.1.13"); +CFTypeRef kSecOIDX509V3CertificateExtensionType = CFSTR("2.16.840.1.113741.2.1.1.1.19"); +CFTypeRef kSecOIDX509V3CertificateExtensionValue = CFSTR("2.16.840.1.113741.2.1.1.1.17"); +CFTypeRef kSecOIDX509V3CertificateExtensionsCStruct = CFSTR("2.16.840.1.113741.2.1.1.1.21.1"); +CFTypeRef kSecOIDX509V3CertificateExtensionsStruct = CFSTR("2.16.840.1.113741.2.1.1.1.21"); +CFTypeRef kSecOIDX509V3CertificateNumberOfExtensions = CFSTR("2.16.840.1.113741.2.1.1.1.14"); +CFTypeRef kSecOIDX509V3SignedCertificate = CFSTR("2.16.840.1.113741.2.1.1.1.0"); +CFTypeRef kSecOIDX509V3SignedCertificateCStruct = CFSTR("2.16.840.1.113741.2.1.1.1.0.1"); +CFTypeRef kSecOIDSRVName = CFSTR("1.3.6.1.5.5.7.8.7"); + diff --git a/libsecurity_keychain/lib/CertificateValues.h b/libsecurity_keychain/lib/CertificateValues.h new file mode 100644 index 00000000..3a10cea3 --- /dev/null +++ b/libsecurity_keychain/lib/CertificateValues.h @@ -0,0 +1,70 @@ +/* + * 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@ + */ + +// +// CertificateValues.h - Objects in a Certificate +// +#ifndef _SECURITY_CERTIFICATEVALUES_H_ +#define _SECURITY_CERTIFICATEVALUES_H_ + +#include +#include "SecBaseP.h" +//#include + +namespace Security +{ + +namespace KeychainCore +{ + +class CertificateValues// : public SecCFObject +{ + NOCOPY(CertificateValues) + +public: + + CertificateValues(SecCertificateRef certificateRef); + virtual ~CertificateValues() throw(); + + static CFStringRef remapLabelToKey(CFStringRef label); + CFDictionaryRef copyFieldValues(CFArrayRef keys, CFErrorRef *error); + CFDataRef copySerialNumber(CFErrorRef *error); + CFDataRef getNormalizedIssuerContent(CFErrorRef *error); + CFDataRef getNormalizedSubjectContent(CFErrorRef *error); + bool SecCertificateIsValidX(CFAbsoluteTime verifyTime, CFErrorRef *error); + +private: + + SecCertificateRefP getSecCertificateRefP(CFErrorRef *error); + + SecCertificateRef mCertificateRef; + CFDataRef mCertificateData; + static CFDictionaryRef mOIDRemap; +}; + + +} // end namespace KeychainCore + +} // end namespace Security + +#endif // !_SECURITY_CERTIFICATEVALUES_H_ diff --git a/libsecurity_keychain/lib/DLDBListCFPref.cpp b/libsecurity_keychain/lib/DLDBListCFPref.cpp new file mode 100644 index 00000000..ee11d931 --- /dev/null +++ b/libsecurity_keychain/lib/DLDBListCFPref.cpp @@ -0,0 +1,1068 @@ +/* + * 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@ + */ + + +/* + DLDBListCFPref.cpp +*/ + +#include "DLDBListCFPref.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +dispatch_once_t AppSandboxChecked; +xpc_object_t KeychainHomeFromXPC; + +using namespace CssmClient; + +static const double kDLDbListCFPrefRevertInterval = 30.0; + +// normal debug calls, which get stubbed out for deployment builds + +#define kKeyGUID CFSTR("GUID") +#define kKeySubserviceId CFSTR("SubserviceId") +#define kKeySubserviceType CFSTR("SubserviceType") +#define kKeyDbName CFSTR("DbName") +#define kKeyDbLocation CFSTR("DbLocation") +#define kKeyActive CFSTR("Active") +#define kKeyMajorVersion CFSTR("MajorVersion") +#define kKeyMinorVersion CFSTR("MinorVersion") +#define kDefaultDLDbListKey CFSTR("DLDBSearchList") +#define kDefaultKeychainKey CFSTR("DefaultKeychain") +#define kLoginKeychainKey CFSTR("LoginKeychain") +#define kUserDefaultPath "~/Library/Preferences/com.apple.security.plist" +#define kSystemDefaultPath "/Library/Preferences/com.apple.security.plist" +#define kCommonDefaultPath "/Library/Preferences/com.apple.security-common.plist" +#define kLoginKeychainPathPrefix "~/Library/Keychains/" +#define kUserLoginKeychainPath "~/Library/Keychains/login.keychain" +#define kSystemLoginKeychainPath "/Library/Keychains/System.keychain" + + +// A utility class for managing password database lookups + +const time_t kPasswordCacheExpire = 30; // number of seconds cached password db info is valid + +PasswordDBLookup::PasswordDBLookup () : mValid (false), mCurrent (0), mTime (0) +{ +} + +void PasswordDBLookup::lookupInfoOnUID (uid_t uid) +{ + time_t currentTime = time (NULL); + + if (!mValid || uid != mCurrent || currentTime - mTime >= kPasswordCacheExpire) + { + struct passwd* pw = getpwuid(uid); + if (pw == NULL) + { + UnixError::throwMe (EPERM); + } + + mDirectory = pw->pw_dir; + mName = pw->pw_name; + mValid = true; + mCurrent = uid; + mTime = currentTime; + + secdebug("secpref", "uid=%d caching home=%s", uid, pw->pw_dir); + + endpwent(); + } +} + +PasswordDBLookup *DLDbListCFPref::mPdbLookup = NULL; + +//------------------------------------------------------------------------------------- +// +// Lists of DL/DBs, with CFPreferences backing store +// +//------------------------------------------------------------------------------------- + +DLDbListCFPref::DLDbListCFPref(SecPreferencesDomain domain) : mDomain(domain), mPropertyList(NULL), mChanged(false), + mSearchListSet(false), mDefaultDLDbIdentifierSet(false), mLoginDLDbIdentifierSet(false) +{ + secdebug("secpref", "New DLDbListCFPref %p for domain %d", this, domain); + loadPropertyList(true); +} + +void DLDbListCFPref::set(SecPreferencesDomain domain) +{ + save(); + + mDomain = domain; + + secdebug("secpref", "DLDbListCFPref %p domain set to %d", this, domain); + + if (loadPropertyList(true)) + resetCachedValues(); +} + +DLDbListCFPref::~DLDbListCFPref() +{ + save(); + + if (mPropertyList) + CFRelease(mPropertyList); +} + +void +DLDbListCFPref::forceUserSearchListReread() +{ + // set mPrefsTimeStamp so that it will "expire" the next time loadPropertyList is called + mPrefsTimeStamp = CFAbsoluteTimeGetCurrent() - kDLDbListCFPrefRevertInterval; +} + +bool +DLDbListCFPref::loadPropertyList(bool force) +{ + string prefsPath; + + switch (mDomain) + { + case kSecPreferencesDomainUser: + prefsPath = ExpandTildesInPath(kUserDefaultPath); + break; + case kSecPreferencesDomainSystem: + prefsPath = kSystemDefaultPath; + break; + case kSecPreferencesDomainCommon: + prefsPath = kCommonDefaultPath; + break; + default: + MacOSError::throwMe(errSecInvalidPrefsDomain); + } + + secdebug("secpref", "force=%s prefsPath=%s", force ? "true" : "false", + prefsPath.c_str()); + + CFAbsoluteTime now = CFAbsoluteTimeGetCurrent(); + + // If for some reason the prefs file path has changed, blow away the old plist and force an update + if (mPrefsPath != prefsPath) + { + mPrefsPath = prefsPath; + if (mPropertyList) + { + CFRelease(mPropertyList); + mPropertyList = NULL; + } + + mPrefsTimeStamp = now; + } + else if (!force) + { + if (now - mPrefsTimeStamp < kDLDbListCFPrefRevertInterval) + return false; + + mPrefsTimeStamp = now; + } + + struct stat st; + if (stat(mPrefsPath.c_str(), &st)) + { + if (errno == ENOENT) + { + if (mPropertyList) + { + if (CFDictionaryGetCount(mPropertyList) == 0) + return false; + CFRelease(mPropertyList); + } + + mPropertyList = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + return true; + } + } + else + { + if (mPropertyList) + { + if (mTimespec.tv_sec == st.st_mtimespec.tv_sec + && mTimespec.tv_nsec == st.st_mtimespec.tv_nsec) + return false; + } + + mTimespec = st.st_mtimespec; + } + + CFMutableDictionaryRef thePropertyList = NULL; + CFMutableDataRef xmlData = NULL; + CFStringRef errorString = NULL; + int fd = -1; + + do + { + fd = open(mPrefsPath.c_str(), O_RDONLY, 0); + if (fd < 0) + break; + + off_t theSize = lseek(fd, 0, SEEK_END); + if (theSize <= 0) + break; + + if (lseek(fd, 0, SEEK_SET)) + break; + + xmlData = CFDataCreateMutable(NULL, CFIndex(theSize)); + if (!xmlData) + break; + CFDataSetLength(xmlData, CFIndex(theSize)); + void *buffer = reinterpret_cast(CFDataGetMutableBytePtr(xmlData)); + if (!buffer) + break; + ssize_t bytesRead = read(fd, buffer, theSize); + if (bytesRead != theSize) + break; + + thePropertyList = CFMutableDictionaryRef(CFPropertyListCreateFromXMLData(NULL, xmlData, kCFPropertyListMutableContainers, &errorString)); + if (!thePropertyList) + break; + + if (CFGetTypeID(thePropertyList) != CFDictionaryGetTypeID()) + { + CFRelease(thePropertyList); + thePropertyList = NULL; + break; + } + } while (0); + + if (fd >= 0) + close(fd); + if (xmlData) + CFRelease(xmlData); + if (errorString) + CFRelease(errorString); + + if (!thePropertyList) + { + thePropertyList = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + } + + if (mPropertyList) + { + if (CFEqual(mPropertyList, thePropertyList)) + { + // The new property list is the same as the old one, so nothing has changed. + CFRelease(thePropertyList); + return false; + } + CFRelease(mPropertyList); + } + + mPropertyList = thePropertyList; + return true; +} + +void +DLDbListCFPref::writePropertyList() +{ + if (!mPropertyList || CFDictionaryGetCount(mPropertyList) == 0) + { + // There is nothing in the mPropertyList dictionary, + // so we don't need a prefs file. + unlink(mPrefsPath.c_str()); + } + else + { + if(testAndFixPropertyList()) + return; + + CFDataRef xmlData = CFPropertyListCreateXMLData(NULL, mPropertyList); + if (!xmlData) + return; // Bad out of memory or something evil happened let's act like CF and do nothing. + + // The prefs file should at least be made readable by user/group/other and writable by the owner. + // Change from euid to ruid if needed for the duration of the new prefs file creat. + + mode_t mode = 0666; + changeIdentity(UNPRIV); + int fd = open(mPrefsPath.c_str(), O_WRONLY|O_CREAT|O_TRUNC, mode); + changeIdentity(PRIV); + if (fd >= 0) + { + const void *buffer = CFDataGetBytePtr(xmlData); + size_t toWrite = CFDataGetLength(xmlData); + /* ssize_t bytesWritten = */ write(fd, buffer, toWrite); + // Emulate CFPreferences by not checking for any errors. + + fsync(fd); + struct stat st; + if (!fstat(fd, &st)) + mTimespec = st.st_mtimespec; + + close(fd); + } + + CFRelease(xmlData); + } + + mPrefsTimeStamp = CFAbsoluteTimeGetCurrent(); +} + +// This function can clean up some problems caused by setuid clients. We've had instances where the +// Keychain search list has become owned by root, but is still able to be re-written by the user because +// of the permissions on the directory above. We'll take advantage of that fact to recreate the file with +// the correct ownership by copying it. + +int +DLDbListCFPref::testAndFixPropertyList() +{ + char *prefsPath = (char *)mPrefsPath.c_str(); + + int fd1, fd2, retval; + struct stat stbuf; + + if((fd1 = open(prefsPath, O_RDONLY)) < 0) { + if (errno == ENOENT) return 0; // Doesn't exist - the default case + else return -1; + } + + if((retval = fstat(fd1, &stbuf)) == -1) return -1; + + if(stbuf.st_uid != getuid()) { + char tempfile[MAXPATHLEN+1]; + + snprintf(tempfile, MAXPATHLEN, "%s.XXXXX", prefsPath); + mktemp(tempfile); + changeIdentity(UNPRIV); + if((fd2 = open(tempfile, O_RDWR | O_CREAT | O_EXCL, 0666)) < 0) { + retval = -1; + } else { + copyfile_state_t s = copyfile_state_alloc(); + retval = fcopyfile(fd1, fd2, s, COPYFILE_DATA); + copyfile_state_free(s); + if(!retval) retval = ::unlink(prefsPath); + if(!retval) retval = ::rename(tempfile, prefsPath); + } + changeIdentity(PRIV); + close(fd2); + } + close(fd1); + return retval; +} + +// Encapsulated process uid/gid change routine. +void +DLDbListCFPref::changeIdentity(ID_Direction toPriv) +{ + if(toPriv == UNPRIV) { + savedEUID = geteuid(); + savedEGID = getegid(); + if(savedEGID != getgid()) setegid(getgid()); + if(savedEUID != getuid()) seteuid(getuid()); + } else { + if(savedEUID != getuid()) seteuid(savedEUID); + if(savedEGID != getgid()) setegid(savedEGID); + } +} + +void +DLDbListCFPref::resetCachedValues() +{ + // Unset the login and default Keychain. + mLoginDLDbIdentifier = mDefaultDLDbIdentifier = DLDbIdentifier(); + + // Clear the searchList. + mSearchList.clear(); + + changed(false); + + // Note that none of our cached values are valid + mSearchListSet = mDefaultDLDbIdentifierSet = mLoginDLDbIdentifierSet = false; + + mPrefsTimeStamp = CFAbsoluteTimeGetCurrent(); +} + +void DLDbListCFPref::save() +{ + if (!hasChanged()) + return; + + // Resync from disc to make sure we don't clobber anyone elses changes. + // @@@ This is probably already done by the next layer up so we don't + // really need to do it here again. + loadPropertyList(true); + + // Do the searchList first since it might end up invoking defaultDLDbIdentifier() which can set + // mLoginDLDbIdentifierSet and mDefaultDLDbIdentifierSet to true. + if (mSearchListSet) + { + // Make a temporary CFArray with the contents of the vector + if (mSearchList.size() == 1 && mSearchList[0] == defaultDLDbIdentifier() && mSearchList[0] == LoginDLDbIdentifier()) + { + // The only element in the search list is the default keychain, which is a + // post Jaguar style login keychain, so omit the entry from the prefs file. + CFDictionaryRemoveValue(mPropertyList, kDefaultDLDbListKey); + } + else + { + CFMutableArrayRef searchArray = CFArrayCreateMutable(kCFAllocatorDefault, mSearchList.size(), &kCFTypeArrayCallBacks); + for (DLDbList::const_iterator ix=mSearchList.begin();ix!=mSearchList.end();ix++) + { + CFDictionaryRef aDict = dlDbIdentifierToCFDictionaryRef(*ix); + CFArrayAppendValue(searchArray, aDict); + CFRelease(aDict); + } + + CFDictionarySetValue(mPropertyList, kDefaultDLDbListKey, searchArray); + CFRelease(searchArray); + } + } + + if (mLoginDLDbIdentifierSet) + { + // Make a temporary CFArray with the login keychain + CFArrayRef loginArray = NULL; + if (!mLoginDLDbIdentifier) + { + loginArray = CFArrayCreate(kCFAllocatorDefault, NULL, 0, &kCFTypeArrayCallBacks); + } + else if (!(mLoginDLDbIdentifier == LoginDLDbIdentifier())) + { + CFDictionaryRef aDict = dlDbIdentifierToCFDictionaryRef(mLoginDLDbIdentifier); + const void *value = reinterpret_cast(aDict); + loginArray = CFArrayCreate(kCFAllocatorDefault, &value, 1, &kCFTypeArrayCallBacks); + CFRelease(aDict); + } + + if (loginArray) + { + CFDictionarySetValue(mPropertyList, kLoginKeychainKey, loginArray); + CFRelease(loginArray); + } + else + CFDictionaryRemoveValue(mPropertyList, kLoginKeychainKey); + } + + if (mDefaultDLDbIdentifierSet) + { + // Make a temporary CFArray with the default keychain + CFArrayRef defaultArray = NULL; + if (!mDefaultDLDbIdentifier) + { + defaultArray = CFArrayCreate(kCFAllocatorDefault, NULL, 0, &kCFTypeArrayCallBacks); + } + else if (!(mDefaultDLDbIdentifier == LoginDLDbIdentifier())) + { + CFDictionaryRef aDict = dlDbIdentifierToCFDictionaryRef(mDefaultDLDbIdentifier); + const void *value = reinterpret_cast(aDict); + defaultArray = CFArrayCreate(kCFAllocatorDefault, &value, 1, &kCFTypeArrayCallBacks); + CFRelease(aDict); + } + + if (defaultArray) + { + CFDictionarySetValue(mPropertyList, kDefaultKeychainKey, defaultArray); + CFRelease(defaultArray); + } + else + CFDictionaryRemoveValue(mPropertyList, kDefaultKeychainKey); + } + + writePropertyList(); + changed(false); +} + + +//---------------------------------------------------------------------- +// Conversions +//---------------------------------------------------------------------- + +DLDbIdentifier DLDbListCFPref::LoginDLDbIdentifier() +{ + CSSM_VERSION theVersion={}; + CssmSubserviceUid ssuid(gGuidAppleCSPDL,&theVersion,0,CSSM_SERVICE_DL|CSSM_SERVICE_CSP); + CssmNetAddress *dbLocation=NULL; + + switch (mDomain) { + case kSecPreferencesDomainUser: + return DLDbIdentifier(ssuid, ExpandTildesInPath(kUserLoginKeychainPath).c_str(), dbLocation); + default: + assert(false); + case kSecPreferencesDomainSystem: + case kSecPreferencesDomainCommon: + return DLDbIdentifier(ssuid, kSystemLoginKeychainPath, dbLocation); + } +} + +DLDbIdentifier DLDbListCFPref::JaguarLoginDLDbIdentifier() +{ + CSSM_VERSION theVersion={}; + CssmSubserviceUid ssuid(gGuidAppleCSPDL,&theVersion,0,CSSM_SERVICE_DL|CSSM_SERVICE_CSP); + CssmNetAddress *dbLocation=NULL; + + switch (mDomain) { + case kSecPreferencesDomainUser: + { + string basepath = ExpandTildesInPath(kLoginKeychainPathPrefix) + getPwInfo(kUsername); + return DLDbIdentifier(ssuid,basepath.c_str(),dbLocation); + } + case kSecPreferencesDomainSystem: + case kSecPreferencesDomainCommon: + return DLDbIdentifier(ssuid, kSystemLoginKeychainPath, dbLocation); + default: + assert(false); + return DLDbIdentifier(); + } +} + +DLDbIdentifier DLDbListCFPref::makeDLDbIdentifier (const CSSM_GUID &guid, const CSSM_VERSION &version, + uint32 subserviceId, CSSM_SERVICE_TYPE subserviceType, + const char* dbName, CSSM_NET_ADDRESS *dbLocation) +{ + CssmSubserviceUid ssuid (guid, &version, subserviceId, subserviceType); + return DLDbIdentifier (ssuid, ExpandTildesInPath (dbName).c_str (), dbLocation); +} + +DLDbIdentifier DLDbListCFPref::cfDictionaryRefToDLDbIdentifier(CFDictionaryRef theDict) +{ + // We must get individual values from the dictionary and store in basic types + if (CFGetTypeID(theDict) != CFDictionaryGetTypeID()) + throw std::logic_error("wrong type in property list"); + + // GUID + CCFValue vGuid(::CFDictionaryGetValue(theDict,kKeyGUID)); + string guidStr=vGuid; + const Guid guid(guidStr.c_str()); + + //CSSM_VERSION + CSSM_VERSION theVersion={0,}; + CCFValue vMajor(::CFDictionaryGetValue(theDict,kKeyMajorVersion)); + theVersion.Major = vMajor; + CCFValue vMinor(::CFDictionaryGetValue(theDict,kKeyMinorVersion)); + theVersion.Minor = vMinor; + + //subserviceId + CCFValue vSsid(::CFDictionaryGetValue(theDict,kKeySubserviceId)); + uint32 subserviceId=sint32(vSsid); + + //CSSM_SERVICE_TYPE + CSSM_SERVICE_TYPE subserviceType=CSSM_SERVICE_DL; + CCFValue vSsType(::CFDictionaryGetValue(theDict,kKeySubserviceType)); + subserviceType=vSsType; + + // Get DbName from dictionary + CCFValue vDbName(::CFDictionaryGetValue(theDict,kKeyDbName)); + string dbName=vDbName; + + // jch Get DbLocation from dictionary + CssmNetAddress *dbLocation=NULL; + + return makeDLDbIdentifier (guid, theVersion, subserviceId, subserviceType, dbName.c_str (), dbLocation); +} + +void DLDbListCFPref::clearPWInfo () +{ + if (mPdbLookup != NULL) + { + delete mPdbLookup; + mPdbLookup = NULL; + } +} + +string DLDbListCFPref::getPwInfo(PwInfoType type) +{ + const char *value; + switch (type) + { + case kHomeDir: + if (KeychainHomeFromXPC) { + value = xpc_string_get_string_ptr(KeychainHomeFromXPC); + } else { + value = getenv("HOME"); + } + if (value) + return value; + break; + case kUsername: + value = getenv("USER"); + if (value) + return value; + break; + } + + // Get our effective uid + uid_t uid = geteuid(); + // If we are setuid root use the real uid instead + if (!uid) uid = getuid(); + + // get the password entries + if (mPdbLookup == NULL) + { + mPdbLookup = new PasswordDBLookup (); + } + + mPdbLookup->lookupInfoOnUID (uid); + + string result; + switch (type) + { + case kHomeDir: + result = mPdbLookup->getDirectory (); + break; + case kUsername: + result = mPdbLookup->getName (); + break; + } + + return result; +} + +static void check_app_sandbox() +{ + if (!_xpc_runtime_is_app_sandboxed()) { + // We are not in a sandbox, no work to do here + return; + } + + extern xpc_object_t xpc_create_with_format(const char * format, ...); + xpc_connection_t con = xpc_connection_create("com.apple.security.XPCKeychainSandboxCheck", NULL); + xpc_connection_set_event_handler(con, ^(xpc_object_t event) { + xpc_type_t xtype = xpc_get_type(event); + if (XPC_TYPE_ERROR == xtype) { + syslog(LOG_ERR, "Keychain sandbox connection error: %s\n", xpc_dictionary_get_string(event, XPC_ERROR_KEY_DESCRIPTION)); + } else { + syslog(LOG_ERR, "Keychain sandbox unexpected connection event %p\n", event); + } + }); + xpc_connection_resume(con); + + xpc_object_t message = xpc_create_with_format("{op: GrantKeychainPaths}"); + xpc_object_t reply = xpc_connection_send_message_with_reply_sync(con, message); + xpc_type_t xtype = xpc_get_type(reply); + if (XPC_TYPE_DICTIONARY == xtype) { +#if 0 + // This is useful for debugging. + char *debug = xpc_copy_description(reply); + syslog(LOG_ERR, "DEBUG (KCsandbox) %s\n", debug); + free(debug); +#endif + + xpc_object_t extensions_array = xpc_dictionary_get_value(reply, "extensions"); + xpc_array_apply(extensions_array, ^(size_t index, xpc_object_t extension) { + char pbuf[MAXPATHLEN]; + char *path = pbuf; + int status = sandbox_consume_fs_extension(xpc_string_get_string_ptr(extension), &path); + if (status) { + syslog(LOG_ERR, "Keychain sandbox consume extension error: s=%d p=%s %m\n", status, path); + } + return (bool)true; + }); + + KeychainHomeFromXPC = xpc_dictionary_get_value(reply, "keychain-home"); + xpc_retain(KeychainHomeFromXPC); + xpc_release(con); + } else if (XPC_TYPE_ERROR == xtype) { + syslog(LOG_ERR, "Keychain sandbox message error: %s\n", xpc_dictionary_get_string(reply, XPC_ERROR_KEY_DESCRIPTION)); + } else { + syslog(LOG_ERR, "Keychain sandbox unexpected message reply type %p\n", xtype); + } + xpc_release(message); + xpc_release(reply); +} + + + +string DLDbListCFPref::ExpandTildesInPath(const string &inPath) +{ + dispatch_once(&AppSandboxChecked, ^{ + check_app_sandbox(); + }); + + if ((short)inPath.find("~/",0,2) == 0) + return getPwInfo(kHomeDir) + inPath.substr(1); + else + return inPath; +} + +string DLDbListCFPref::StripPathStuff(const string &inPath) +{ + if (inPath.find("/private/var/automount/Network/",0,31) == 0) + return inPath.substr(22); + if (inPath.find("/private/automount/Servers/",0,27) == 0) + return "/Network" + inPath.substr(18); + if (inPath.find("/automount/Servers/",0,19) == 0) + return "/Network" + inPath.substr(10); + if (inPath.find("/private/automount/Network/",0,27) == 0) + return inPath.substr(18); + if (inPath.find("/automount/Network/",0,19) == 0) + return inPath.substr(10); + if (inPath.find("/private/Network/",0,17) == 0) + return inPath.substr(8); + return inPath; +} + +string DLDbListCFPref::AbbreviatedPath(const string &inPath) +{ + string path = StripPathStuff(inPath); + string home = StripPathStuff(getPwInfo(kHomeDir) + "/"); + size_t homeLen = home.length(); + + if (homeLen > 1 && path.find(home.c_str(), 0, homeLen) == 0) + return "~" + path.substr(homeLen - 1); + else + return path; +} + +CFDictionaryRef DLDbListCFPref::dlDbIdentifierToCFDictionaryRef(const DLDbIdentifier& dldbIdentifier) +{ + CFRef aDict(CFDictionaryCreateMutable(kCFAllocatorDefault,0, + &kCFTypeDictionaryKeyCallBacks,&kCFTypeDictionaryValueCallBacks)); + if (!aDict) + throw ::std::bad_alloc(); + + // Put SUBSERVICE_UID in dictionary + char buffer[Guid::stringRepLength+1]; + const CssmSubserviceUid& ssuid=dldbIdentifier.ssuid(); + const Guid &theGuid = Guid::overlay(ssuid.Guid); + CFRef stringGuid(::CFStringCreateWithCString(kCFAllocatorDefault, + theGuid.toString(buffer),kCFStringEncodingMacRoman)); + if (stringGuid) + ::CFDictionarySetValue(aDict,kKeyGUID,stringGuid); + + if (ssuid.SubserviceId!=0) + { + CFRef subserviceId(::CFNumberCreate(kCFAllocatorDefault,kCFNumberSInt32Type,&ssuid.SubserviceId)); + if (subserviceId) + ::CFDictionarySetValue(aDict,kKeySubserviceId,subserviceId); + } + if (ssuid.SubserviceType!=0) + { + CFRef subserviceType(CFNumberCreate(kCFAllocatorDefault,kCFNumberSInt32Type,&ssuid.SubserviceType)); + if (subserviceType) + ::CFDictionarySetValue(aDict,kKeySubserviceType,subserviceType); + } + if (ssuid.Version.Major!=0 && ssuid.Version.Minor!=0) + { + CFRef majorVersion(::CFNumberCreate(kCFAllocatorDefault,kCFNumberSInt32Type,&ssuid.Version.Major)); + if (majorVersion) + ::CFDictionarySetValue(aDict,kKeyMajorVersion,majorVersion); + CFRef minorVersion(::CFNumberCreate(kCFAllocatorDefault,kCFNumberSInt32Type,&ssuid.Version.Minor)); + if (minorVersion) + ::CFDictionarySetValue(aDict,kKeyMinorVersion,minorVersion); + } + + // Put DbName in dictionary + const char *dbName=dldbIdentifier.dbName(); + if (dbName) + { + CFRef theDbName(::CFStringCreateWithCString(kCFAllocatorDefault,AbbreviatedPath(dbName).c_str(),kCFStringEncodingUTF8)); + ::CFDictionarySetValue(aDict,kKeyDbName,theDbName); + } + // Put DbLocation in dictionary + const CSSM_NET_ADDRESS *dbLocation=dldbIdentifier.dbLocation(); + if (dbLocation!=NULL && dbLocation->AddressType!=CSSM_ADDR_NONE) + { + CFRef theData(::CFDataCreate(kCFAllocatorDefault,dbLocation->Address.Data,dbLocation->Address.Length)); + if (theData) + ::CFDictionarySetValue(aDict,kKeyDbLocation,theData); + } + + ::CFRetain(aDict); + return aDict; +} + +bool DLDbListCFPref::revert(bool force) +{ + // If the prefs have not been refreshed in the last kDLDbListCFPrefRevertInterval + // seconds or we are asked to force a reload, then reload. + if (!loadPropertyList(force)) + return false; + + resetCachedValues(); + return true; +} + +void +DLDbListCFPref::add(const DLDbIdentifier &dldbIdentifier) +{ + // convert the location specified in dldbIdentifier to a standard form + // make a canonical form of the database name + std::string canon = ExpandTildesInPath(AbbreviatedPath(dldbIdentifier.dbName()).c_str()); + + DLDbIdentifier localIdentifier (dldbIdentifier.ssuid(), canon.c_str(), dldbIdentifier.dbLocation ()); + + if (member(localIdentifier)) + return; + + mSearchList.push_back(localIdentifier); + changed(true); +} + +void +DLDbListCFPref::remove(const DLDbIdentifier &dldbIdentifier) +{ + // Make sure mSearchList is set + searchList(); + for (vector::iterator ix = mSearchList.begin(); ix != mSearchList.end(); ++ix) + { + if (*ix==dldbIdentifier) // found in list + { + mSearchList.erase(ix); + changed(true); + break; + } + } +} + +void +DLDbListCFPref::rename(const DLDbIdentifier &oldId, const DLDbIdentifier &newId) +{ + // Make sure mSearchList is set + searchList(); + for (vector::iterator ix = mSearchList.begin(); + ix != mSearchList.end(); ++ix) + { + if (*ix==oldId) + { + // replace oldId with newId + *ix = newId; + changed(true); + } + else if (*ix==newId) + { + // remove newId except where we just inserted it + mSearchList.erase(ix); + changed(true); + } + } +} + +bool +DLDbListCFPref::member(const DLDbIdentifier &dldbIdentifier) +{ + for (vector::const_iterator ix = searchList().begin(); ix != mSearchList.end(); ++ix) + { + if (ix->mImpl == NULL) + { + continue; + } + + // compare the dldbIdentifiers based on the full, real path to the keychain + if (ix->ssuid() == dldbIdentifier.ssuid()) + { + char localPath[PATH_MAX], + inPath[PATH_MAX]; + + // try to resolve these down to a canonical form + const char* localPathPtr = cached_realpath(ix->dbName(), localPath); + const char* inPathPtr = cached_realpath(dldbIdentifier.dbName(), inPath); + + // if either of the paths didn't resolve for some reason, use the originals + if (localPathPtr == NULL) + { + localPathPtr = ix->dbName(); + } + + if (inPathPtr == NULL) + { + inPathPtr = dldbIdentifier.dbName(); + } + + if (strcmp(localPathPtr, inPathPtr) == 0) + { + return true; + } + } + } + + return false; +} + +const vector & +DLDbListCFPref::searchList() +{ + if (!mSearchListSet) + { + CFArrayRef searchList = reinterpret_cast(CFDictionaryGetValue(mPropertyList, kDefaultDLDbListKey)); + if (searchList && CFGetTypeID(searchList) != CFArrayGetTypeID()) + searchList = NULL; + + if (searchList) + { + CFIndex top = CFArrayGetCount(searchList); + // Each entry is a CFDictionary; peel it off & add it to the array + for (CFIndex idx = 0; idx < top; ++idx) + { + CFDictionaryRef theDict = reinterpret_cast(CFArrayGetValueAtIndex(searchList, idx)); + try + { + mSearchList.push_back(cfDictionaryRefToDLDbIdentifier(theDict)); + } + catch (...) + { + // Drop stuff that doesn't parse on the floor. + } + } + + // If there were entries specified, but they were invalid revert to using the + // default keychain in the searchlist. + if (top > 0 && mSearchList.size() == 0) + searchList = NULL; + } + + // The default when no search list is specified is to only search the + // default keychain. + if (!searchList && static_cast(defaultDLDbIdentifier())) + mSearchList.push_back(mDefaultDLDbIdentifier); + + mSearchListSet = true; + } + + return mSearchList; +} + +void +DLDbListCFPref::searchList(const vector &searchList) +{ + vector newList(searchList); + mSearchList.swap(newList); + mSearchListSet = true; + changed(true); +} + +void +DLDbListCFPref::defaultDLDbIdentifier(const DLDbIdentifier &dlDbIdentifier) +{ + if (!(defaultDLDbIdentifier() == dlDbIdentifier)) + { + mDefaultDLDbIdentifier = dlDbIdentifier; + changed(true); + } +} + +const DLDbIdentifier & +DLDbListCFPref::defaultDLDbIdentifier() +{ + + if (!mDefaultDLDbIdentifierSet) + { + CFArrayRef defaultArray = reinterpret_cast(CFDictionaryGetValue(mPropertyList, kDefaultKeychainKey)); + if (defaultArray && CFGetTypeID(defaultArray) != CFArrayGetTypeID()) + defaultArray = NULL; + + if (defaultArray && CFArrayGetCount(defaultArray) > 0) + { + CFDictionaryRef defaultDict = reinterpret_cast(CFArrayGetValueAtIndex(defaultArray, 0)); + try + { + secdebug("secpref", "getting default DLDbIdentifier from defaultDict"); + mDefaultDLDbIdentifier = cfDictionaryRefToDLDbIdentifier(defaultDict); + secdebug("secpref", "now we think the default keychain is %s", (mDefaultDLDbIdentifier) ? mDefaultDLDbIdentifier.dbName() : ""); + } + catch (...) + { + // If defaultArray doesn't parse fall back on the default way of getting the default keychain + defaultArray = NULL; + } + } + + if (!defaultArray) + { + + // If the Panther style login keychain actually exists we use that otherwise no + // default is set. + mDefaultDLDbIdentifier = loginDLDbIdentifier(); + secdebug("secpref", "now we think the default keychain is: %s", (mDefaultDLDbIdentifier) ? mDefaultDLDbIdentifier.dbName() : + "Name doesn't exist"); + + + //"Name doesn't exist"); + + struct stat st; + int st_result = stat(mDefaultDLDbIdentifier.dbName(), &st); + + + if (st_result) + { + secdebug("secpref", "stat(%s) -> %d", mDefaultDLDbIdentifier.dbName(), st_result); + mDefaultDLDbIdentifier = DLDbIdentifier(); // initialize a NULL keychain + secdebug("secpref", "after DLDbIdentifier(), we think the default keychain is %s", static_cast(mDefaultDLDbIdentifier) ? mDefaultDLDbIdentifier.dbName() : ""); + } + } + + mDefaultDLDbIdentifierSet = true; + } + + + return mDefaultDLDbIdentifier; +} + +void +DLDbListCFPref::loginDLDbIdentifier(const DLDbIdentifier &dlDbIdentifier) +{ + if (!(loginDLDbIdentifier() == dlDbIdentifier)) + { + mLoginDLDbIdentifier = dlDbIdentifier; + changed(true); + } +} + +const DLDbIdentifier & +DLDbListCFPref::loginDLDbIdentifier() +{ + if (!mLoginDLDbIdentifierSet) + { + CFArrayRef loginArray = reinterpret_cast(CFDictionaryGetValue(mPropertyList, kLoginKeychainKey)); + if (loginArray && CFGetTypeID(loginArray) != CFArrayGetTypeID()) + loginArray = NULL; + + if (loginArray && CFArrayGetCount(loginArray) > 0) + { + CFDictionaryRef loginDict = reinterpret_cast(CFArrayGetValueAtIndex(loginArray, 0)); + try + { + secdebug("secpref", "Getting login DLDbIdentifier from loginDict"); + mLoginDLDbIdentifier = cfDictionaryRefToDLDbIdentifier(loginDict); + secdebug("secpref", "we think the login keychain is %s", static_cast(mLoginDLDbIdentifier) ? mLoginDLDbIdentifier.dbName() : ""); + } + catch (...) + { + // If loginArray doesn't parse fall back on the default way of getting the login keychain. + loginArray = NULL; + } + } + + if (!loginArray) + { + mLoginDLDbIdentifier = LoginDLDbIdentifier(); + secdebug("secpref", "after LoginDLDbIdentifier(), we think the login keychain is %s", static_cast(mLoginDLDbIdentifier) ? mLoginDLDbIdentifier.dbName() : ""); + } + + mLoginDLDbIdentifierSet = true; + } + + return mLoginDLDbIdentifier; +} diff --git a/libsecurity_keychain/lib/DLDBListCFPref.h b/libsecurity_keychain/lib/DLDBListCFPref.h new file mode 100644 index 00000000..c7eddc7b --- /dev/null +++ b/libsecurity_keychain/lib/DLDBListCFPref.h @@ -0,0 +1,222 @@ +/* + * 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@ + */ + + +/* + * DLDBListCFPref.h + */ +#ifndef _SECURITY_DLDBLISTCFPREF_H_ +#define _SECURITY_DLDBLISTCFPREF_H_ + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Security +{ + +class PasswordDBLookup +{ +protected: + string mDirectory; + string mName; + bool mValid; + uid_t mCurrent; + time_t mTime; + +public: + PasswordDBLookup (); + + void lookupInfoOnUID (uid_t uid); + const string& getDirectory () {return mDirectory;} + const string& getName () {return mName;} +}; + +class DLDbListCFPref +{ +public: + DLDbListCFPref(SecPreferencesDomain domain = kSecPreferencesDomainUser); + ~DLDbListCFPref(); + + void set(SecPreferencesDomain domain); + + void save(); + vector& list() { return mSearchList; } + + static DLDbIdentifier makeDLDbIdentifier (const CSSM_GUID &guid, const CSSM_VERSION &version, + uint32 subserviceId, CSSM_SERVICE_TYPE subserviceType, + const char* dbName, CSSM_NET_ADDRESS *dbLocation); + + static DLDbIdentifier cfDictionaryRefToDLDbIdentifier(CFDictionaryRef theDict); + static CFDictionaryRef dlDbIdentifierToCFDictionaryRef(const DLDbIdentifier& dldbIdentifier); + bool revert(bool force); + + void add(const DLDbIdentifier &); + void remove(const DLDbIdentifier &); + void rename(const DLDbIdentifier &oldId, const DLDbIdentifier &newId); + bool member(const DLDbIdentifier &); + const vector &searchList(); + void searchList(const vector &); + void defaultDLDbIdentifier(const DLDbIdentifier &); + const DLDbIdentifier &defaultDLDbIdentifier(); + void loginDLDbIdentifier(const DLDbIdentifier &); + const DLDbIdentifier &loginDLDbIdentifier(); + void forceUserSearchListReread (); + + DLDbIdentifier LoginDLDbIdentifier(); + DLDbIdentifier JaguarLoginDLDbIdentifier(); + + static string ExpandTildesInPath(const string &inPath); + static string StripPathStuff(const string &inPath); + static string AbbreviatedPath(const string &inPath); + +protected: + SecPreferencesDomain mDomain; + bool hasChanged() const { return mChanged; } + void changed(bool hasChanged) { mChanged = hasChanged; } + + enum PwInfoType + { + kHomeDir, + kUsername + }; + + static PasswordDBLookup *mPdbLookup; + static string getPwInfo(PwInfoType type); + static void clearPWInfo (); + + void resetCachedValues(); + bool loadPropertyList(bool force); + void writePropertyList(); + int testAndFixPropertyList(); + + enum ID_Direction + { + UNPRIV, + PRIV + }; + uid_t savedEUID; + gid_t savedEGID; + + void changeIdentity(ID_Direction); + + +private: + CFAbsoluteTime mPrefsTimeStamp; + struct timespec mTimespec; + CFMutableDictionaryRef mPropertyList; + + string mPrefsPath, mHomeDir, mUserName; + vector mSearchList; + DLDbIdentifier mDefaultDLDbIdentifier; + DLDbIdentifier mLoginDLDbIdentifier; + bool mChanged, mSearchListSet, mDefaultDLDbIdentifierSet, mLoginDLDbIdentifierSet; +}; + +class CCFValue +{ +public: + template + T cfref() const { return reinterpret_cast(CFTypeRef(mRef)); } + + CCFValue() {} + CCFValue(CFTypeRef ref) : mRef(ref) {} + CCFValue &operator =(CFTypeRef ref) { mRef = ref; return *this; } + + CCFValue &operator = (bool value) + { + mRef = value?kCFBooleanTrue:kCFBooleanFalse; + return *this; + } + +/* + CCFValue &operator = (const string &value) { string(value); return *this; } + + void string(const string &value, CFStringEncoding encoding=kCFStringEncodingMacRoman) + { + mRef = CFStringCreate(); +CFStringRef CFStringCreateWithBytes(CFAllocatorRef alloc, const UInt8 *bytes, CFIndex numBytes, CFStringEncoding encoding, Boolean isExternalRepresentation); + if (!mRef) throw std::bad_alloc; + CFRelease(mRef); + } +*/ + + bool hasValue() const { return mRef; } + + operator bool() const + { + if (!mRef) return false; + if (::CFGetTypeID(mRef) != ::CFBooleanGetTypeID()) + throw std::logic_error("wrong type in property list"); + + return ::CFBooleanGetValue(cfref()); + } + + operator sint32() const + { + if (!mRef) return 0; + if (::CFGetTypeID(mRef) != ::CFNumberGetTypeID()) + throw std::logic_error("wrong type in property list"); + + sint32 val; + ::CFNumberGetValue(cfref(),kCFNumberSInt32Type,&val); + return val; + } + + operator uint32() const { return uint32(sint32(*this)); } + + operator const string() const { return getString(); } + + const string getString(CFStringEncoding encoding=kCFStringEncodingUTF8) const + { + if (!mRef) + throw std::logic_error("missing string in property list"); + if (::CFGetTypeID(mRef) != ::CFStringGetTypeID()) + throw std::logic_error("wrong type in property list"); + + const char *tmpStr=::CFStringGetCStringPtr(cfref(),encoding); + if (tmpStr == NULL) + { + CFIndex maxLen = CFStringGetMaximumSizeForEncoding(CFStringGetLength(cfref()), encoding); + auto_array buffer(maxLen + 1); + + if (!::CFStringGetCString(cfref(),buffer.get(),maxLen + 1,encoding)) + throw std::logic_error("could not convert string from property list"); + + tmpStr=buffer.get(); + return string(tmpStr?tmpStr:""); + } + return string(tmpStr?tmpStr:""); + } +private: + CFCopyRefmRef; +}; + +} // end namespace Security + +#endif /* !_SECURITY_DLDBLISTCFPREF_H_ */ diff --git a/libsecurity_keychain/lib/DynamicDLDBList.cpp b/libsecurity_keychain/lib/DynamicDLDBList.cpp new file mode 100644 index 00000000..5c6eb510 --- /dev/null +++ b/libsecurity_keychain/lib/DynamicDLDBList.cpp @@ -0,0 +1,235 @@ +/* + * 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@ + */ + + +/* + DynamicDLDBList.cpp +*/ + +#include "DynamicDLDBList.h" + +#include "Globals.h" + +#include +#include // For Required() +#include +#include +#include "KCEventNotifier.h" + +using namespace KeychainCore; + +// +// DynamicDLDBList +// +DynamicDLDBList::DynamicDLDBList() + : mMutex(Mutex::recursive), mSearchListSet(false) +{ +} + +DynamicDLDBList::~DynamicDLDBList() +{ +} + +CSSM_RETURN +DynamicDLDBList::appNotifyCallback(const CSSM_GUID *guid, void *context, + uint32 subserviceId, CSSM_SERVICE_TYPE subserviceType, CSSM_MODULE_EVENT eventType) +{ + CSSM_RETURN status = 0; + try + { + reinterpret_cast(context)->callback(Guid::required(guid), + subserviceId, subserviceType, eventType); + } + catch (const CommonError &error) + { + status = error.osStatus(); + } + catch (...) + { + } + + return status; +} + +/* Assume mLock is locked already. Add all databases for this module. */ +bool +DynamicDLDBList::_add(const Guid &guid, uint32 subserviceID, CSSM_SERVICE_TYPE subserviceType) +{ + return _add(dlDbIdentifier(guid, subserviceID, subserviceType)); +} + +/* Assume mLock is locked already. Add a single database to the searchlist. */ +bool +DynamicDLDBList::_add(const DLDbIdentifier &dlDbIdentifier) +{ + StLock_(mMutex); + + if (find(mSearchList.begin(), mSearchList.end(), dlDbIdentifier) == mSearchList.end()) + { + mSearchList.push_back(dlDbIdentifier); + return true; + } + + return false; +} + +/* Assume mLock is locked already. Remove all databases for this module. */ +bool +DynamicDLDBList::_remove(const Guid &guid, uint32 subserviceID, CSSM_SERVICE_TYPE subserviceType) +{ + return _remove(dlDbIdentifier(guid, subserviceID, subserviceType)); +} + +/* Assume mLock is locked already. Remove a single database from the + searchlist. */ +bool +DynamicDLDBList::_remove(const DLDbIdentifier &dlDbIdentifier) +{ + StLock_(mMutex); + + // search for subserviceUid but ignore the dbName, which is dynamic + for (SearchList::iterator it = mSearchList.begin(); it != mSearchList.end(); it++) + if (it->ssuid() == dlDbIdentifier.ssuid()) + { + mSearchList.erase(it); + + // Remove from the storageManager cache if it was there. + globals().storageManager.didRemoveKeychain(dlDbIdentifier); + return true; + } + // not found + return false; +} + +bool +DynamicDLDBList::_load() +{ + StLock_(mMutex); + + bool list_changed = false; + MDSClient::Directory &mds = MDSClient::mds(); + MDSClient::Table common(mds); + MDSClient::Table dl(mds); + MDSClient::Table csp(mds); + + for (MDSClient::Table::iterator commonIt = + common.find(MDSClient::Attribute("DynamicFlag") != false); + commonIt != common.end(); ++commonIt) + { + CSSM_SERVICE_MASK serviceMask = (*commonIt)->serviceMask(); + if (serviceMask & CSSM_SERVICE_DL) + { + string moduleID = (*commonIt)->moduleID(); + secdebug("dynamic", "Loading dynamic %sDL module: %s", + (serviceMask & CSSM_SERVICE_CSP) ? "CSP/" : "", moduleID.c_str()); + + /* Register module for callbacks and load it. */ + Guid moduleGuid(moduleID); + CssmClient::Module module(moduleGuid); + module->appNotifyCallback(appNotifyCallback, this); + module->load(); + mModules.push_back(module); + + /* Now that we have registered for notifications, Find all already + registered dl subsevices for this module. */ + for (MDSClient::Table::iterator dlIt = + dl.find(MDSClient::Attribute("ModuleID") == moduleID); + dlIt!= dl.end(); ++dlIt) + { + uint32 subserviceID = (*dlIt)->subserviceID(); + bool hasCSP = csp.find(MDSClient::Attribute("ModuleID") == moduleID + && MDSClient::Attribute("SSID") == subserviceID) != csp.end(); + + secdebug("dynamic", "Adding databases from %sDL SSID %lu module: %s", + hasCSP ? "CSP/" : "", (unsigned long)subserviceID, moduleID.c_str()); + list_changed |= _add(moduleGuid, subserviceID, + hasCSP ? CSSM_SERVICE_CSP | CSSM_SERVICE_DL : CSSM_SERVICE_DL); + } + } + } + + return list_changed; +} + +const vector & +DynamicDLDBList::searchList() +{ + StLock_(mMutex); + if (!mSearchListSet) + { + // Load all dynamic DL's so we start receiving notifications. + _load(); + + mSearchListSet = true; + } + + return mSearchList; +} + +void +DynamicDLDBList::callback(const Guid &guid, uint32 subserviceID, + CSSM_SERVICE_TYPE subserviceType, CSSM_MODULE_EVENT eventType) +{ + secdebug("event", "Received callback from guid: %s ssid: %lu type: %lu event: %lu", + guid.toString().c_str(), (unsigned long)subserviceID, (unsigned long)subserviceType, (unsigned long)eventType); + + StLock_(mMutex); + + bool list_changed = false; + + if (subserviceType & CSSM_SERVICE_DL) + { + if (eventType == CSSM_NOTIFY_INSERT) + { + /* A DL or CSP/DL was inserted. */ + secdebug("dynamic", "%sDL module: %s SSID: %lu inserted", + (subserviceType & CSSM_SERVICE_CSP) ? "CSP/" : "", guid.toString().c_str(), (unsigned long)subserviceID); + list_changed = _add(guid, subserviceID, subserviceType); + } + else if (eventType == CSSM_NOTIFY_REMOVE) + { + /* A DL or CSP/DL was removed. */ + secdebug("dynamic", "%sDL module: %s SSID: %lu removed", + (subserviceType & CSSM_SERVICE_CSP) ? "CSP/" : "", guid.toString().c_str(), (unsigned long)subserviceID); + list_changed = _remove(guid, subserviceID, subserviceType); + } + } + + if (list_changed) + { + // Make sure we are not holding mLock nor the StorageManager mLock when we post these events. + // @@@ Rather than posting we should simulate a receive since each client will receive this + // cssm level notification. + KCEventNotifier::PostKeychainEvent(kSecKeychainListChangedEvent); + } +} + +DLDbIdentifier DynamicDLDBList::dlDbIdentifier(const Guid &guid, + uint32 subserviceID, CSSM_SERVICE_TYPE subserviceType) +{ + CSSM_VERSION theVersion={}; + CssmSubserviceUid ssuid(guid, &theVersion, subserviceID, subserviceType); + CssmNetAddress *dbLocation=NULL; + + return DLDbIdentifier(ssuid, NULL, dbLocation); +} diff --git a/libsecurity_keychain/lib/DynamicDLDBList.h b/libsecurity_keychain/lib/DynamicDLDBList.h new file mode 100644 index 00000000..12c75be3 --- /dev/null +++ b/libsecurity_keychain/lib/DynamicDLDBList.h @@ -0,0 +1,74 @@ +/* + * 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@ + */ + + +/* + * DynamicDLDBList.h + */ +#ifndef _SECURITY_DYNAMICDLDBLIST_H_ +#define _SECURITY_DYNAMICDLDBLIST_H_ + +#include +#include + +namespace Security +{ + +namespace KeychainCore +{ + +class DynamicDLDBList +{ +public: + DynamicDLDBList(); + ~DynamicDLDBList(); + + const vector &searchList(); + +protected: + Mutex mMutex; + bool _add(const Guid &guid, uint32 subserviceID, CSSM_SERVICE_TYPE subserviceType); + bool _add(const DLDbIdentifier &); + bool _remove(const Guid &guid, uint32 subserviceID, CSSM_SERVICE_TYPE subserviceType); + bool _remove(const DLDbIdentifier &); + bool _load(); + DLDbIdentifier dlDbIdentifier(const Guid &guid, uint32 subserviceID, + CSSM_SERVICE_TYPE subserviceType); + void callback(const Guid &guid, uint32 subserviceID, + CSSM_SERVICE_TYPE subserviceType, CSSM_MODULE_EVENT eventType); + +private: + static CSSM_RETURN appNotifyCallback(const CSSM_GUID *guid, void *context, + uint32 subserviceId, CSSM_SERVICE_TYPE subserviceType, CSSM_MODULE_EVENT eventType); + + vector mModules; + typedef vector SearchList; + SearchList mSearchList; + bool mSearchListSet; +}; + +} // end namespace KeychainCore + +} // end namespace Security + +#endif /* !_SECURITY_DYNAMICDLDBLIST_H_ */ diff --git a/libsecurity_keychain/lib/ExtendedAttribute.cpp b/libsecurity_keychain/lib/ExtendedAttribute.cpp new file mode 100644 index 00000000..a667eb91 --- /dev/null +++ b/libsecurity_keychain/lib/ExtendedAttribute.cpp @@ -0,0 +1,193 @@ +/* + * 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@ + */ + +/* + * ExtendedAttribute.cpp - Extended Keychain Item Attribute class. + * + * Created 9/6/06 by dmitch. + */ + +#include "ExtendedAttribute.h" +#include "SecKeychainItemExtendedAttributes.h" +#include "SecKeychainItemPriv.h" +#include "cssmdatetime.h" +#include + +using namespace KeychainCore; + +/* + * Construct new ExtendedAttr from API. + */ +ExtendedAttribute::ExtendedAttribute( + CSSM_DB_RECORDTYPE recordType, + const CssmData &itemID, + const CssmData attrName, + const CssmData attrValue) : + ItemImpl(CSSM_DL_DB_RECORD_EXTENDED_ATTRIBUTE, + reinterpret_cast(NULL), + 0, NULL), + mRecordType(recordType), + mItemID(Allocator::standard(), itemID.Data, itemID.Length), + mAttrName(Allocator::standard(), attrName.Data, attrName.Length), + mAttrValue(Allocator::standard(), attrValue.Data, attrValue.Length) +{ + setupAttrs(); +} + +// db item contstructor +ExtendedAttribute::ExtendedAttribute( + const Keychain &keychain, + const PrimaryKey &primaryKey, + const CssmClient::DbUniqueRecord &uniqueId) : + ItemImpl(keychain, primaryKey, uniqueId), + mRecordType(0), + mItemID(Allocator::standard()), + mAttrName(Allocator::standard()), + mAttrValue(Allocator::standard()) +{ + +} + +// PrimaryKey item contstructor +ExtendedAttribute::ExtendedAttribute( + const Keychain &keychain, + const PrimaryKey &primaryKey) : + ItemImpl(keychain, primaryKey), + mRecordType(0), + mItemID(Allocator::standard()), + mAttrName(Allocator::standard()), + mAttrValue(Allocator::standard()) +{ + +} + +ExtendedAttribute* ExtendedAttribute::make(const Keychain &keychain, const PrimaryKey &primaryKey, const CssmClient::DbUniqueRecord &uniqueId) +{ + ExtendedAttribute* ea = new ExtendedAttribute(keychain, primaryKey, uniqueId); + keychain->addItem(primaryKey, ea); + return ea; +} + + + +ExtendedAttribute* ExtendedAttribute::make(const Keychain &keychain, const PrimaryKey &primaryKey) +{ + ExtendedAttribute* ea = new ExtendedAttribute(keychain, primaryKey); + keychain->addItem(primaryKey, ea); + return ea; +} + + + +// copy - required due to Item's weird constructor/vendor +ExtendedAttribute::ExtendedAttribute( + ExtendedAttribute &extendedAttr) : + ItemImpl(extendedAttr), + mRecordType(extendedAttr.mRecordType), + mItemID(Allocator::standard()), + mAttrName(Allocator::standard()), + mAttrValue(Allocator::standard()) +{ + // CssmData cd = extendedAttr.mItemID; + mItemID.copy(extendedAttr.mItemID); + // cd = extendedAttr.mAttrName; + mAttrName.copy(extendedAttr.mAttrName); + // cd = extendedAttr.mAttrValue; + mAttrValue.copy(extendedAttr.mAttrValue); + setupAttrs(); +} + +ExtendedAttribute::~ExtendedAttribute() throw() +{ + +} + +PrimaryKey +ExtendedAttribute::add(Keychain &keychain) +{ + StLock_(mMutex); + // If we already have a Keychain we can't be added. + if (mKeychain) + MacOSError::throwMe(errSecDuplicateItem); + + SInt64 date; + CSSMDateTimeUtils::GetCurrentMacLongDateTime(date); + CssmDbAttributeInfo attrInfo(kSecModDateItemAttr, CSSM_DB_ATTRIBUTE_FORMAT_TIME_DATE); + setAttribute(attrInfo, date); + + Db db(keychain->database()); + // add the item to the (regular) db + try + { + mUniqueId = db->insert(CSSM_DL_DB_RECORD_EXTENDED_ATTRIBUTE, mDbAttributes.get(), mData.get()); + } + catch (const CssmError &e) + { + if (e.osStatus() != CSSMERR_DL_INVALID_RECORDTYPE) + throw; + + /* + * First exposure of this keychain to the extended attribute record type. + * Create the relation and try again. + */ + db->createRelation(CSSM_DL_DB_RECORD_EXTENDED_ATTRIBUTE, + "CSSM_DL_DB_RECORD_EXTENDED_ATTRIBUTE", + Schema::ExtendedAttributeSchemaAttributeCount, + Schema::ExtendedAttributeSchemaAttributeList, + Schema::ExtendedAttributeSchemaIndexCount, + Schema::ExtendedAttributeSchemaIndexList); + keychain->keychainSchema()->didCreateRelation( + CSSM_DL_DB_RECORD_EXTENDED_ATTRIBUTE, + "CSSM_DL_DB_RECORD_EXTENDED_ATTRIBUTE", + Schema::ExtendedAttributeSchemaAttributeCount, + Schema::ExtendedAttributeSchemaAttributeList, + Schema::ExtendedAttributeSchemaIndexCount, + Schema::ExtendedAttributeSchemaIndexList); + + mUniqueId = db->insert(CSSM_DL_DB_RECORD_EXTENDED_ATTRIBUTE, mDbAttributes.get(), mData.get()); + } + + mPrimaryKey = keychain->makePrimaryKey(CSSM_DL_DB_RECORD_EXTENDED_ATTRIBUTE, mUniqueId); + mKeychain = keychain; + + return mPrimaryKey; +} + +/* set up DB attrs based on member vars */ +void ExtendedAttribute::setupAttrs() +{ + StLock_(mMutex); + CssmDbAttributeInfo attrInfo1(kExtendedAttrRecordTypeAttr, CSSM_DB_ATTRIBUTE_FORMAT_UINT32); + setAttribute(attrInfo1, (uint32)mRecordType); + CssmData cd = mItemID; + CssmDbAttributeInfo attrInfo2(kExtendedAttrItemIDAttr, CSSM_DB_ATTRIBUTE_FORMAT_BLOB); + setAttribute(attrInfo2, cd); + cd = mAttrName; + CssmDbAttributeInfo attrInfo3(kExtendedAttrAttributeNameAttr, CSSM_DB_ATTRIBUTE_FORMAT_BLOB); + setAttribute(attrInfo3, cd); + cd = mAttrValue; + CssmDbAttributeInfo attrInfo4(kExtendedAttrAttributeValueAttr, CSSM_DB_ATTRIBUTE_FORMAT_BLOB); + setAttribute(attrInfo4, cd); +} + + diff --git a/libsecurity_keychain/lib/ExtendedAttribute.h b/libsecurity_keychain/lib/ExtendedAttribute.h new file mode 100644 index 00000000..d98626d4 --- /dev/null +++ b/libsecurity_keychain/lib/ExtendedAttribute.h @@ -0,0 +1,91 @@ +/* + * 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@ + */ + +/* + * ExtendedAttribute.h - Extended Keychain Item Attribute class. + * + * Created 9/6/06 by dmitch. + */ + +#ifndef _SECURITY_EXTENDED_ATTRIBUTE_H_ +#define _SECURITY_EXTENDED_ATTRIBUTE_H_ + +#include +#include + +/* this is not public */ +typedef struct OpaqueSecExtendedAttributeRef *SecKeychainItemExtendedAttributeRef; + +namespace Security +{ + +namespace KeychainCore +{ + +class ExtendedAttribute : public ItemImpl +{ + NOCOPY(ExtendedAttribute) +public: + SECCFFUNCTIONS(ExtendedAttribute, SecKeychainItemExtendedAttributeRef, + errSecInvalidItemRef, gTypes().ExtendedAttribute) + + /* construct new ExtendedAttr from API */ + ExtendedAttribute(CSSM_DB_RECORDTYPE recordType, + const CssmData &itemID, + const CssmData attrName, + const CssmData attrValue); + +private: + // db item contstructor + ExtendedAttribute(const Keychain &keychain, + const PrimaryKey &primaryKey, + const CssmClient::DbUniqueRecord &uniqueId); + + // PrimaryKey item contstructor + ExtendedAttribute(const Keychain &keychain, const PrimaryKey &primaryKey); + +public: + static ExtendedAttribute* make(const Keychain &keychain, const PrimaryKey &primaryKey, const CssmClient::DbUniqueRecord &uniqueId); + static ExtendedAttribute* make(const Keychain &keychain, const PrimaryKey &primaryKey); + + ExtendedAttribute(ExtendedAttribute &extendedAttribute); + + virtual ~ExtendedAttribute() throw(); + + virtual PrimaryKey add(Keychain &keychain); + bool operator == (const ExtendedAttribute &other) const; +private: + /* set up DB attrs based on member vars */ + void setupAttrs(); + + CSSM_DB_RECORDTYPE mRecordType; + CssmAutoData mItemID; + CssmAutoData mAttrName; + CssmAutoData mAttrValue; +}; + +} // end namespace KeychainCore + +} // end namespace Security + +#endif /* _SECURITY_EXTENDED_ATTRIBUTES_H_ */ diff --git a/libsecurity_keychain/lib/Globals.cpp b/libsecurity_keychain/lib/Globals.cpp new file mode 100644 index 00000000..f1763961 --- /dev/null +++ b/libsecurity_keychain/lib/Globals.cpp @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2000-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@ + * + * Globals.cpp -- Private "globals" and interfaces for KeychainCore + */ + +#include "Globals.h" +#include "KCExceptions.h" + + +namespace Security { +namespace KeychainCore { + +using namespace CssmClient; + +ModuleNexus globals; +bool gServerMode; + +#pragma mark ÑÑÑÑ Constructor/Destructor ÑÑÑÑ + +Globals::Globals() : +mUI(true) +{ +} + +const AccessCredentials * Globals::keychainCredentials() +{ + return (mUI ? mACLFactory.unlockCred() : mACLFactory.cancelCred()); +} + +const AccessCredentials * Globals::smartcardCredentials() +{ + return (mUI ? mACLFactory.promptedPINCred() : mACLFactory.cancelCred()); +} + +const AccessCredentials * Globals::itemCredentials() +{ + return (mUI ? mACLFactory.promptCred() : mACLFactory.nullCred()); +} + +const AccessCredentials * Globals::smartcardItemCredentials() +{ + return (mUI ? mACLFactory.promptedPINItemCred() : mACLFactory.cancelCred()); +} + +} // namespace KeychainCore +} // namespace Security diff --git a/libsecurity_keychain/lib/Globals.h b/libsecurity_keychain/lib/Globals.h new file mode 100644 index 00000000..7e5f01f8 --- /dev/null +++ b/libsecurity_keychain/lib/Globals.h @@ -0,0 +1,73 @@ +/* + * 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@ + */ + +// +// DefaultKeychain.h - Private "globals" and interfaces for KeychainCore +// +#ifndef _SECURITY_GLOBALS_H_ +#define _SECURITY_GLOBALS_H_ + +#ifdef check +#undef check +#endif +#include +#include + + +namespace Security +{ + +namespace KeychainCore +{ + +class Globals +{ +public: + Globals(); + + const AccessCredentials *keychainCredentials(); + const AccessCredentials *smartcardCredentials(); + const AccessCredentials *itemCredentials(); + const AccessCredentials *smartcardItemCredentials(); + + void setUserInteractionAllowed(bool bUI) { mUI=bUI; } + bool getUserInteractionAllowed() const { return mUI; } + + // Public globals + StorageManager storageManager; + +private: + + // Other "globals" + bool mUI; + CssmClient::AclFactory mACLFactory; +}; + +extern ModuleNexus globals; +extern bool gServerMode; + +} // end namespace KeychainCore + +} // end namespace Security + +#endif // !_SECURITY_GLOBALS_H_ diff --git a/libsecurity_keychain/lib/Identity.cpp b/libsecurity_keychain/lib/Identity.cpp new file mode 100644 index 00000000..52c72ac2 --- /dev/null +++ b/libsecurity_keychain/lib/Identity.cpp @@ -0,0 +1,93 @@ +/* + * 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@ + */ + +// +// Identity.cpp - Working with Identities +// +#include + +#include +#include + +using namespace KeychainCore; + +Identity::Identity(const SecPointer &privateKey, + const SecPointer &certificate) : + mPrivateKey(privateKey), + mCertificate(certificate) +{ +} + +Identity::Identity(const StorageManager::KeychainList &keychains, const SecPointer &certificate) : + mCertificate(certificate) +{ + // Find a key whose label matches the publicKeyHash of the public key in the certificate. + KCCursor keyCursor(keychains, CSSM_DL_DB_RECORD_PRIVATE_KEY, NULL); + keyCursor->add(CSSM_DB_EQUAL, KeySchema::Label, certificate->publicKeyHash()); + + Item key; + if (!keyCursor->next(key)) + MacOSError::throwMe(errSecItemNotFound); + + SecPointer keyItem(static_cast(&*key)); + mPrivateKey = keyItem; +} + +Identity::~Identity() throw() +{ +} + +SecPointer +Identity::privateKey() const +{ + return mPrivateKey; +} + +SecPointer +Identity::certificate() const +{ + return mCertificate; +} + +bool +Identity::operator < (const Identity &other) const +{ + // Certificates in different keychains are considered equal if data is equal + return (mCertificate < other.mCertificate); +} + +bool +Identity::operator == (const Identity &other) const +{ + // Certificates in different keychains are considered equal if data is equal; + // however, if their keys are in different keychains, the identities should + // not be considered equal (according to mb) + return (mCertificate == other.mCertificate && mPrivateKey == other.mPrivateKey); +} + +bool +Identity::equal(SecCFObject &other) +{ + return (*this) == (const Identity &)other; +} + diff --git a/libsecurity_keychain/lib/Identity.h b/libsecurity_keychain/lib/Identity.h new file mode 100644 index 00000000..b39a3c26 --- /dev/null +++ b/libsecurity_keychain/lib/Identity.h @@ -0,0 +1,67 @@ +/* + * 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@ + */ + +// +// Identity.h - Working with Identities +// +#ifndef _SECURITY_IDENTITY_H_ +#define _SECURITY_IDENTITY_H_ + +#include +#include + +namespace Security +{ + +namespace KeychainCore +{ + +class Identity : public SecCFObject +{ + NOCOPY(Identity) +public: + SECCFFUNCTIONS(Identity, SecIdentityRef, errSecInvalidItemRef, gTypes().Identity) + + Identity(const SecPointer &privateKey, + const SecPointer &certificate); + Identity(const StorageManager::KeychainList &keychains, const SecPointer &certificate); + virtual ~Identity() throw(); + + SecPointer privateKey() const; + SecPointer certificate() const; + + bool operator < (const Identity &other) const; + bool operator == (const Identity &other) const; + + bool equal(SecCFObject &other); + +private: + SecPointer mPrivateKey; + SecPointer mCertificate; +}; + +} // end namespace KeychainCore + +} // end namespace Security + +#endif // !_SECURITY_IDENTITY_H_ diff --git a/libsecurity_keychain/lib/IdentityCursor.cpp b/libsecurity_keychain/lib/IdentityCursor.cpp new file mode 100644 index 00000000..764dce18 --- /dev/null +++ b/libsecurity_keychain/lib/IdentityCursor.cpp @@ -0,0 +1,351 @@ +/* + * Copyright (c) 2002-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@ + * + * IdentityCursor.cpp -- Working with IdentityCursor + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace KeychainCore; + +IdentityCursorPolicyAndID::IdentityCursorPolicyAndID(const StorageManager::KeychainList &searchList, CSSM_KEYUSE keyUsage, CFStringRef idString, SecPolicyRef policy, bool returnOnlyValidIdentities) : + IdentityCursor(searchList, keyUsage), + mPolicy(policy), + mIDString(idString), + mReturnOnlyValidIdentities(returnOnlyValidIdentities), + mPreferredIdentityChecked(false), + mPreferredIdentity(nil) +{ + if (mPolicy) + CFRetain(mPolicy); + + if (mIDString) + CFRetain(mIDString); +} + +IdentityCursorPolicyAndID::~IdentityCursorPolicyAndID() throw() +{ + if (mPolicy) + CFRelease(mPolicy); + + if (mIDString) + CFRelease(mIDString); +} + +void +IdentityCursorPolicyAndID::findPreferredIdentity() +{ + char idUTF8[MAXPATHLEN]; + if (!mIDString || !CFStringGetCString(mIDString, idUTF8, sizeof(idUTF8)-1, kCFStringEncodingUTF8)) + idUTF8[0] = (char)'\0'; + uint32_t iprfValue = 'iprf'; // value is specified in host byte order, since kSecTypeItemAttr has type uint32 in the db schema + SecKeychainAttribute sAttrs[] = { + { kSecTypeItemAttr, sizeof(uint32_t), &iprfValue }, + { kSecServiceItemAttr, strlen(idUTF8), (char *)idUTF8 } + }; + SecKeychainAttributeList sAttrList = { sizeof(sAttrs) / sizeof(sAttrs[0]), sAttrs }; + +// StorageManager::KeychainList keychains; +// globals().storageManager.optionalSearchList((CFTypeRef)nil, keychains); + + Item item; + KCCursor cursor(mSearchList /*keychains*/, kSecGenericPasswordItemClass, &sAttrList); + if (!cursor->next(item)) + return; + + // get persistent certificate reference + SecKeychainAttribute itemAttrs[] = { { kSecGenericItemAttr, 0, NULL } }; + SecKeychainAttributeList itemAttrList = { sizeof(itemAttrs) / sizeof(itemAttrs[0]), itemAttrs }; + item->getContent(NULL, &itemAttrList, NULL, NULL); + + // find certificate, given persistent reference data + CFDataRef pItemRef = CFDataCreateWithBytesNoCopy(NULL, (const UInt8 *)itemAttrs[0].data, itemAttrs[0].length, kCFAllocatorNull); + SecKeychainItemRef certItemRef = nil; + OSStatus status = SecKeychainItemCopyFromPersistentReference(pItemRef, &certItemRef); + if (pItemRef) + CFRelease(pItemRef); + item->freeContent(&itemAttrList, NULL); + if (status || !certItemRef) + return; + + // create identity reference, given certificate + Item certItem = ItemImpl::required(SecKeychainItemRef(certItemRef)); + SecPointer certificate(static_cast(certItem.get())); + SecPointer identity(new Identity(mSearchList /*keychains*/, certificate)); + + mPreferredIdentity = identity; + + if (certItemRef) + CFRelease(certItemRef); +} + +bool +IdentityCursorPolicyAndID::next(SecPointer &identity) +{ + SecPointer currIdentity; + Boolean identityOK = true; + + if (!mPreferredIdentityChecked) + { + try + { + findPreferredIdentity(); + } + catch(...) {} + mPreferredIdentityChecked = true; + if (mPreferredIdentity) + { + identity = mPreferredIdentity; + return true; + } + } + + for (;;) + { + bool result = IdentityCursor::next(currIdentity); // base class finds the next identity by keyUsage + if ( result ) + { + if (mPreferredIdentity && (currIdentity == mPreferredIdentity)) + { + identityOK = false; // we already returned this one, move on to the next + continue; + } + + // If there was no policy specified, we're done. + if ( !mPolicy ) + { + identityOK = true; // return this identity + break; + } + + // To reduce the number of (potentially expensive) trust evaluations performed, we need + // to do some pre-processing to filter out certs that don't match the search criteria. + // Rather than try to duplicate the TP's policy logic here, we'll just call the TP with + // a single-element certificate array, no anchors, and no keychains to search. + + SecPointer certificate = currIdentity->certificate(); + CFRef certRef(certificate->handle()); + CFRef anchorsArray(CFArrayCreateMutable(NULL, 1, NULL)); + CFRef certArray(CFArrayCreateMutable(NULL, 1, NULL)); + if ( !certArray || !anchorsArray ) + { + identityOK = false; // skip this and move on to the next one + continue; + } + CFArrayAppendValue(certArray, certRef); + + SecPointer trustLite = new Trust(certArray, mPolicy); + StorageManager::KeychainList emptyList; + // Set the anchors and keychain search list to be empty + trustLite->anchors(anchorsArray); + trustLite->searchLibs(emptyList); + trustLite->evaluate(); + SecTrustResultType trustResult = trustLite->result(); + + if (trustResult == kSecTrustResultRecoverableTrustFailure || + trustResult == kSecTrustResultFatalTrustFailure) + { + CFArrayRef certChain = NULL; + CSSM_TP_APPLE_EVIDENCE_INFO *statusChain = NULL, *evInfo = NULL; + trustLite->buildEvidence(certChain, TPEvidenceInfo::overlayVar(statusChain)); + if (statusChain) + evInfo = &statusChain[0]; + if (!evInfo || evInfo->NumStatusCodes > 0) // per-cert codes means we can't use this cert for this policy + trustResult = kSecTrustResultInvalid; // handled below + if (certChain) + CFRelease(certChain); + } + if (trustResult == kSecTrustResultInvalid) + { + identityOK = false; // move on to the next one + continue; + } + + // If trust evaluation isn't requested, we're done. + if ( !mReturnOnlyValidIdentities ) + { + identityOK = true; // return this identity + break; + } + + // Perform a full trust evaluation on the certificate with the specified policy. + SecPointer trust = new Trust(certArray, mPolicy); + trust->evaluate(); + trustResult = trust->result(); + + if (trustResult == kSecTrustResultInvalid || + trustResult == kSecTrustResultRecoverableTrustFailure || + trustResult == kSecTrustResultFatalTrustFailure) + { + identityOK = false; // move on to the next one + continue; + } + + identityOK = true; // this one was OK; return it. + break; + } + else + { + identityOK = false; // no more left. + break; + } + } // for(;;) + + if ( identityOK ) + { + identity = currIdentity; // caller will release the identity + return true; + } + else + { + return false; + } +} + + +IdentityCursor::IdentityCursor(const StorageManager::KeychainList &searchList, CSSM_KEYUSE keyUsage) : + mSearchList(searchList), + mKeyCursor(mSearchList, CSSM_DL_DB_RECORD_PRIVATE_KEY, NULL), + mMutex(Mutex::recursive) +{ + StLock_(mMutex); + + // If keyUsage is CSSM_KEYUSE_ANY then we need a key that can do everything + if (keyUsage & CSSM_KEYUSE_ANY) + keyUsage = CSSM_KEYUSE_ENCRYPT | CSSM_KEYUSE_DECRYPT + | CSSM_KEYUSE_DERIVE | CSSM_KEYUSE_SIGN + | CSSM_KEYUSE_VERIFY | CSSM_KEYUSE_SIGN_RECOVER + | CSSM_KEYUSE_VERIFY_RECOVER | CSSM_KEYUSE_WRAP + | CSSM_KEYUSE_UNWRAP; + + if (keyUsage & CSSM_KEYUSE_ENCRYPT) + mKeyCursor->add(CSSM_DB_EQUAL, KeySchema::Encrypt, true); + if (keyUsage & CSSM_KEYUSE_DECRYPT) + mKeyCursor->add(CSSM_DB_EQUAL, KeySchema::Decrypt, true); + if (keyUsage & CSSM_KEYUSE_DERIVE) + mKeyCursor->add(CSSM_DB_EQUAL, KeySchema::Derive, true); + if (keyUsage & CSSM_KEYUSE_SIGN) + mKeyCursor->add(CSSM_DB_EQUAL, KeySchema::Sign, true); + if (keyUsage & CSSM_KEYUSE_VERIFY) + mKeyCursor->add(CSSM_DB_EQUAL, KeySchema::Verify, true); + if (keyUsage & CSSM_KEYUSE_SIGN_RECOVER) + mKeyCursor->add(CSSM_DB_EQUAL, KeySchema::SignRecover, true); + if (keyUsage & CSSM_KEYUSE_VERIFY_RECOVER) + mKeyCursor->add(CSSM_DB_EQUAL, KeySchema::VerifyRecover, true); + if (keyUsage & CSSM_KEYUSE_WRAP) + mKeyCursor->add(CSSM_DB_EQUAL, KeySchema::Wrap, true); + if (keyUsage & CSSM_KEYUSE_UNWRAP) + mKeyCursor->add(CSSM_DB_EQUAL, KeySchema::Unwrap, true); +} + +IdentityCursor::~IdentityCursor() throw() +{ +} + +CFDataRef +IdentityCursor::pubKeyHashForSystemIdentity(CFStringRef domain) +{ + StLock_(mMutex); + + CFDataRef entryValue = nil; + auto_ptr identDict; + Dictionary* d = Dictionary::CreateDictionary("com.apple.security.systemidentities", Dictionary::US_System); + if (d) + { + identDict.reset(d); + entryValue = identDict->getDataValue(domain); + if (entryValue == nil) { + /* try for default entry if we're not already looking for default */ + if(!CFEqual(domain, kSecIdentityDomainDefault)) { + entryValue = identDict->getDataValue(kSecIdentityDomainDefault); + } + } + } + + if (entryValue) { + CFRetain(entryValue); + } + return entryValue; +} + +bool +IdentityCursor::next(SecPointer &identity) +{ + StLock_(mMutex); + + for (;;) + { + if (!mCertificateCursor) + { + Item key; + if (!mKeyCursor->next(key)) + return false; + + mCurrentKey = static_cast(key.get()); + + CssmClient::DbUniqueRecord uniqueId = mCurrentKey->dbUniqueRecord(); + CssmClient::DbAttributes dbAttributes(uniqueId->database(), 1); + dbAttributes.add(KeySchema::Label); + uniqueId->get(&dbAttributes, NULL); + const CssmData &keyHash = dbAttributes[0]; + + mCertificateCursor = KCCursor(mSearchList, CSSM_DL_DB_RECORD_X509_CERTIFICATE, NULL); + mCertificateCursor->add(CSSM_DB_EQUAL, Schema::kX509CertificatePublicKeyHash, keyHash); + + // if we have entries for the system identities, exclude their public key hashes in the search + CFDataRef systemDefaultCertPubKeyHash = pubKeyHashForSystemIdentity(kSecIdentityDomainDefault); + if (systemDefaultCertPubKeyHash) { + CssmData pkHash((void *)CFDataGetBytePtr(systemDefaultCertPubKeyHash), CFDataGetLength(systemDefaultCertPubKeyHash)); + mCertificateCursor->add(CSSM_DB_NOT_EQUAL, Schema::kX509CertificatePublicKeyHash, pkHash); + CFRelease(systemDefaultCertPubKeyHash); + } + CFDataRef kerbKDCCertPubKeyHash = pubKeyHashForSystemIdentity(kSecIdentityDomainKerberosKDC); + if (kerbKDCCertPubKeyHash) { + CssmData pkHash((void *)CFDataGetBytePtr(kerbKDCCertPubKeyHash), CFDataGetLength(kerbKDCCertPubKeyHash)); + mCertificateCursor->add(CSSM_DB_NOT_EQUAL, Schema::kX509CertificatePublicKeyHash, pkHash); + CFRelease(kerbKDCCertPubKeyHash); + } + } + + Item cert; + if (mCertificateCursor->next(cert)) + { + SecPointer certificate(static_cast(cert.get())); + identity = new Identity(mCurrentKey, certificate); + return true; + } + else + mCertificateCursor = KCCursor(); + } +} diff --git a/libsecurity_keychain/lib/IdentityCursor.h b/libsecurity_keychain/lib/IdentityCursor.h new file mode 100644 index 00000000..b9a8de09 --- /dev/null +++ b/libsecurity_keychain/lib/IdentityCursor.h @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2002-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@ + */ + +// +// IdentityCursor.h - Working with IdentityCursors +// +#ifndef _SECURITY_IDENTITYCURSOR_H_ +#define _SECURITY_IDENTITYCURSOR_H_ + +#include +#include +#include +#include +#include +#include + +namespace Security +{ + +namespace KeychainCore +{ + +class Identity; +class KeyItem; + +class IdentityCursor : public SecCFObject +{ + NOCOPY(IdentityCursor) +public: + SECCFFUNCTIONS(IdentityCursor, SecIdentitySearchRef, errSecInvalidSearchRef, gTypes().IdentityCursor) + + IdentityCursor(const StorageManager::KeychainList &searchList, CSSM_KEYUSE keyUsage); + virtual ~IdentityCursor() throw(); + virtual bool next(SecPointer &identity); + + CFDataRef pubKeyHashForSystemIdentity(CFStringRef domain); + +protected: + StorageManager::KeychainList mSearchList; + +private: + KCCursor mKeyCursor; + KCCursor mCertificateCursor; + SecPointer mCurrentKey; + Mutex mMutex; +}; + +class IdentityCursorPolicyAndID : public IdentityCursor +{ +public: + IdentityCursorPolicyAndID(const StorageManager::KeychainList &searchList, CSSM_KEYUSE keyUsage, CFStringRef idString, SecPolicyRef policy, bool returnOnlyValidIdentities); + virtual ~IdentityCursorPolicyAndID() throw(); + virtual bool next(SecPointer &identity); + virtual void findPreferredIdentity(); + +private: + SecPolicyRef mPolicy; + CFStringRef mIDString; + bool mReturnOnlyValidIdentities; + bool mPreferredIdentityChecked; + SecPointer mPreferredIdentity; +}; + + +} // end namespace KeychainCore + +} // end namespace Security + +#endif // !_SECURITY_IDENTITYCURSOR_H_ diff --git a/libsecurity_keychain/lib/Item.cpp b/libsecurity_keychain/lib/Item.cpp new file mode 100644 index 00000000..032dea03 --- /dev/null +++ b/libsecurity_keychain/lib/Item.cpp @@ -0,0 +1,1397 @@ +/* + * 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@ + */ + + +// +// Item.cpp +// + +#include "Item.h" + +#include "Certificate.h" +#include "KeyItem.h" +#include "ExtendedAttribute.h" + +#include "Globals.h" +#include +#include "KCEventNotifier.h" +#include "cssmdatetime.h" +#include +#include +#include +#include +#include + +#define SENDACCESSNOTIFICATIONS 1 + +//%%% schema indexes should be defined in Schema.h +#define APPLEDB_CSSM_PRINTNAME_ATTRIBUTE 1 /* schema index for label attribute of keys or certificates */ +#define APPLEDB_GENERIC_PRINTNAME_ATTRIBUTE 7 /* schema index for label attribute of password items */ +#define IS_PASSWORD_ITEM_CLASS(X) ( (X) == kSecInternetPasswordItemClass || \ + (X) == kSecGenericPasswordItemClass || \ + (X) == kSecAppleSharePasswordItemClass ) ? 1 : 0 + +using namespace KeychainCore; +using namespace CSSMDateTimeUtils; + +// +// ItemImpl +// + +// NewItemImpl constructor +ItemImpl::ItemImpl(SecItemClass itemClass, OSType itemCreator, UInt32 length, const void* data, bool dontDoAttributes) + : mDbAttributes(new DbAttributes()), + mKeychain(NULL), + mDoNotEncrypt(false), + mInCache(false), + mMutex(Mutex::recursive) +{ + if (length && data) + mData = new CssmDataContainer(data, length); + + mDbAttributes->recordType(Schema::recordTypeFor(itemClass)); + + if (itemCreator) + mDbAttributes->add(Schema::attributeInfo(kSecCreatorItemAttr), itemCreator); +} + +ItemImpl::ItemImpl(SecItemClass itemClass, SecKeychainAttributeList *attrList, UInt32 length, const void* data) + : mDbAttributes(new DbAttributes()), + mKeychain(NULL), + mDoNotEncrypt(false), + mInCache(false), + mMutex(Mutex::recursive) +{ + if (length && data) + mData = new CssmDataContainer(data, length); + + + mDbAttributes->recordType(Schema::recordTypeFor(itemClass)); + + if(attrList) + { + for(UInt32 i=0; i < attrList->count; i++) + { + mDbAttributes->add(Schema::attributeInfo(attrList->attr[i].tag), CssmData(attrList->attr[i].data, attrList->attr[i].length)); + } + } +} + +// DbItemImpl constructor +ItemImpl::ItemImpl(const Keychain &keychain, const PrimaryKey &primaryKey, const DbUniqueRecord &uniqueId) + : mUniqueId(uniqueId), mKeychain(keychain), mPrimaryKey(primaryKey), + mDoNotEncrypt(false), mInCache(false), + mMutex(Mutex::recursive) +{ +} + +// PrimaryKey ItemImpl constructor +ItemImpl::ItemImpl(const Keychain &keychain, const PrimaryKey &primaryKey) + : mKeychain(keychain), mPrimaryKey(primaryKey), mDoNotEncrypt(false), + mInCache(false), + mMutex(Mutex::recursive) +{ +} + +ItemImpl* ItemImpl::make(const Keychain &keychain, const PrimaryKey &primaryKey, const CssmClient::DbUniqueRecord &uniqueId) +{ + ItemImpl* ii = new ItemImpl(keychain, primaryKey, uniqueId); + keychain->addItem(primaryKey, ii); + return ii; +} + + + +ItemImpl* ItemImpl::make(const Keychain &keychain, const PrimaryKey &primaryKey) +{ + ItemImpl* ii = new ItemImpl(keychain, primaryKey); + keychain->addItem(primaryKey, ii); + return ii; +} + + + +// Constructor used when copying an item to a keychain. + +ItemImpl::ItemImpl(ItemImpl &item) : + mData(item.modifiedData() ? NULL : new CssmDataContainer()), + mDbAttributes(new DbAttributes()), + mKeychain(NULL), + mDoNotEncrypt(false), + mInCache(false), + mMutex(Mutex::recursive) +{ + mDbAttributes->recordType(item.recordType()); + CSSM_DB_RECORD_ATTRIBUTE_INFO *schemaAttributes = NULL; + + if (item.mKeychain) { + // get the entire source item from its keychain. This requires figuring + // out the schema for the item based on its record type. + + for (uint32 i = 0; i < Schema::DBInfo.NumberOfRecordTypes; i++) + if (item.recordType() == Schema::DBInfo.RecordAttributeNames[i].DataRecordType) { + schemaAttributes = &Schema::DBInfo.RecordAttributeNames[i]; + break; + } + + if (schemaAttributes == NULL) + // the source item is invalid + MacOSError::throwMe(errSecInvalidItemRef); + + for (uint32 i = 0; i < schemaAttributes->NumberOfAttributes; i++) + mDbAttributes->add(schemaAttributes->AttributeInfo[i]); + + item.getContent(mDbAttributes.get(), mData.get()); + } + + // @@@ We don't deal with modified attributes. + + if (item.modifiedData()) + // the copied data comes from the source item + mData = new CssmDataContainer(item.modifiedData()->Data, + item.modifiedData()->Length); +} + +ItemImpl::~ItemImpl() +{ +} + + + +Mutex* +ItemImpl::getMutexForObject() +{ + if (mKeychain.get()) + { + return mKeychain->getKeychainMutex(); + } + + return NULL; +} + + + +void +ItemImpl::aboutToDestruct() +{ + if (mKeychain && *mPrimaryKey) + { + mKeychain->removeItem(mPrimaryKey, this); + } +} + + + +void +ItemImpl::didModify() +{ + StLock_(mMutex); + mData = NULL; + mDbAttributes.reset(NULL); +} + +const CSSM_DATA & +ItemImpl::defaultAttributeValue(const CSSM_DB_ATTRIBUTE_INFO &info) +{ + static const uint32 zeroInt = 0; + static const double zeroDouble = 0.0; + static const char timeBytes[] = "20010101000000Z"; + + static const CSSM_DATA defaultFourBytes = { 4, (uint8 *) &zeroInt }; + static const CSSM_DATA defaultEightBytes = { 8, (uint8 *) &zeroDouble }; + static const CSSM_DATA defaultTime = { 16, (uint8 *) timeBytes }; + static const CSSM_DATA defaultZeroBytes = { 0, NULL }; + + switch (info.AttributeFormat) + { + case CSSM_DB_ATTRIBUTE_FORMAT_SINT32: + case CSSM_DB_ATTRIBUTE_FORMAT_UINT32: + return defaultFourBytes; + + case CSSM_DB_ATTRIBUTE_FORMAT_REAL: + return defaultEightBytes; + + case CSSM_DB_ATTRIBUTE_FORMAT_TIME_DATE: + return defaultTime; + + default: + return defaultZeroBytes; + } +} + + + +PrimaryKey ItemImpl::addWithCopyInfo (Keychain &keychain, bool isCopy) +{ + StLock_(mMutex); + // If we already have a Keychain we can't be added. + if (mKeychain) + MacOSError::throwMe(errSecDuplicateItem); + + // If we don't have any attributes we can't be added. + // (this might occur if attempting to add the item twice, since our attributes + // and data are set to NULL at the end of this function.) + if (!mDbAttributes.get()) + MacOSError::throwMe(errSecDuplicateItem); + + CSSM_DB_RECORDTYPE recordType = mDbAttributes->recordType(); + + // update the creation and update dates on the new item + if (!isCopy) + { + KeychainSchema schema = keychain->keychainSchema(); + SInt64 date; + GetCurrentMacLongDateTime(date); + if (schema->hasAttribute(recordType, kSecCreationDateItemAttr)) + { + setAttribute(schema->attributeInfoFor(recordType, kSecCreationDateItemAttr), date); + } + + if (schema->hasAttribute(recordType, kSecModDateItemAttr)) + { + setAttribute(schema->attributeInfoFor(recordType, kSecModDateItemAttr), date); + } + } + + // If the label (PrintName) attribute isn't specified, set a default label. + if (!mDoNotEncrypt && !mDbAttributes->find(Schema::attributeInfo(kSecLabelItemAttr))) + { + // if doNotEncrypt was set all of the attributes are wrapped in the data blob. Don't calculate here. + CssmDbAttributeData *label = NULL; + switch (recordType) + { + case CSSM_DL_DB_RECORD_GENERIC_PASSWORD: + label = mDbAttributes->find(Schema::attributeInfo(kSecServiceItemAttr)); + break; + + case CSSM_DL_DB_RECORD_APPLESHARE_PASSWORD: + case CSSM_DL_DB_RECORD_INTERNET_PASSWORD: + label = mDbAttributes->find(Schema::attributeInfo(kSecServerItemAttr)); + // if AppleShare server name wasn't specified, try the server address + if (!label) label = mDbAttributes->find(Schema::attributeInfo(kSecAddressItemAttr)); + break; + + default: + break; + } + // if all else fails, use the account name. + if (!label) + label = mDbAttributes->find(Schema::attributeInfo(kSecAccountItemAttr)); + + if (label && label->size()) + setAttribute (Schema::attributeInfo(kSecLabelItemAttr), label->at(0)); + } + + // get the attributes that are part of the primary key + const CssmAutoDbRecordAttributeInfo &primaryKeyInfos = + keychain->primaryKeyInfosFor(recordType); + + // make sure each primary key element has a value in the item, otherwise + // the database will complain. we make a set of the provided attribute infos + // to avoid O(N^2) behavior. + + DbAttributes *attributes = mDbAttributes.get(); + typedef set InfoSet; + InfoSet infoSet; + + if (!mDoNotEncrypt) + { + // make a set of all the attributes in the key + for (uint32 i = 0; i < attributes->size(); i++) + infoSet.insert(attributes->at(i).Info); + + for (uint32 i = 0; i < primaryKeyInfos.size(); i++) { // check to make sure all required attributes are in the key + InfoSet::const_iterator it = infoSet.find(primaryKeyInfos.at(i)); + + if (it == infoSet.end()) { // not in the key? add the default + // we need to add a default value to the item attributes + attributes->add(primaryKeyInfos.at(i), defaultAttributeValue(primaryKeyInfos.at(i))); + } + } + } + + Db db(keychain->database()); + if (mDoNotEncrypt) + { + mUniqueId = db->insertWithoutEncryption (recordType, NULL, mData.get()); + } + else if (useSecureStorage(db)) + { + // Add the item to the secure storage db + SSDbImpl* impl = dynamic_cast(&(*db)); + if (impl == NULL) + { + CssmError::throwMe(CSSMERR_CSSM_INVALID_POINTER); + } + + SSDb ssDb(impl); + + TrackingAllocator allocator(Allocator::standard()); + + // hhs replaced with the new aclFactory class + AclFactory aclFactory; + const AccessCredentials *nullCred = aclFactory.nullCred(); + + SecPointer access = mAccess; + if (!access) { + // create default access controls for the new item + CssmDbAttributeData *data = mDbAttributes->find(Schema::attributeInfo(kSecLabelItemAttr)); + string printName = data ? CssmData::overlay(data->Value[0]).toString() : "keychain item"; + access = new Access(printName); + + // special case for "iTools" password - allow anyone to decrypt the item + if (recordType == CSSM_DL_DB_RECORD_GENERIC_PASSWORD) + { + CssmDbAttributeData *data = mDbAttributes->find(Schema::attributeInfo(kSecServiceItemAttr)); + if (data && data->Value[0].Length == 6 && !memcmp("iTools", data->Value[0].Data, 6)) + { + typedef vector > AclSet; + AclSet acls; + access->findAclsForRight(CSSM_ACL_AUTHORIZATION_DECRYPT, acls); + for (AclSet::const_iterator it = acls.begin(); it != acls.end(); it++) + (*it)->form(ACL::allowAllForm); + } + } + } + + // Get the handle of the DL underlying this CSPDL. + CSSM_DL_DB_HANDLE dldbh; + db->passThrough(CSSM_APPLECSPDL_DB_GET_HANDLE, NULL, + reinterpret_cast(&dldbh)); + + // Turn off autocommit on the underlying DL and remember the old state. + CSSM_BOOL autoCommit = CSSM_TRUE; + ObjectImpl::check(CSSM_DL_PassThrough(dldbh, + CSSM_APPLEFILEDL_TOGGLE_AUTOCOMMIT, + 0, reinterpret_cast(&autoCommit))); + + try + { + // Create a new SSGroup with temporary access controls + Access::Maker maker; + ResourceControlContext prototype; + maker.initialOwner(prototype, nullCred); + SSGroup ssGroup(ssDb, &prototype); + + try + { + // Insert the record using the newly created group. + mUniqueId = ssDb->insert(recordType, mDbAttributes.get(), + mData.get(), ssGroup, maker.cred()); + } + catch(...) + { + ssGroup->deleteKey(nullCred); + throw; + } + + // now finalize the access controls on the group + access->setAccess(*ssGroup, maker); + mAccess = NULL; // use them and lose them + if (autoCommit) + { + // autoCommit was on so commit now that we are done and turn + // it back on. + ObjectImpl::check(CSSM_DL_PassThrough(dldbh, + CSSM_APPLEFILEDL_COMMIT, NULL, NULL)); + CSSM_DL_PassThrough(dldbh, CSSM_APPLEFILEDL_TOGGLE_AUTOCOMMIT, + reinterpret_cast(autoCommit), NULL); + } + } + catch (...) + { + if (autoCommit) + { + // autoCommit was off so rollback since we failed and turn + // autoCommit back on. + CSSM_DL_PassThrough(dldbh, CSSM_APPLEFILEDL_ROLLBACK, NULL, NULL); + CSSM_DL_PassThrough(dldbh, CSSM_APPLEFILEDL_TOGGLE_AUTOCOMMIT, + reinterpret_cast(autoCommit), NULL); + } + throw; + } + } + else + { + // add the item to the (regular) db + mUniqueId = db->insert(recordType, mDbAttributes.get(), mData.get()); + } + + mPrimaryKey = keychain->makePrimaryKey(recordType, mUniqueId); + mKeychain = keychain; + + // Forget our data and attributes. + mData = NULL; + mDbAttributes.reset(NULL); + + return mPrimaryKey; +} + + + +PrimaryKey +ItemImpl::add (Keychain &keychain) +{ + return addWithCopyInfo (keychain, false); +} + + + +Item +ItemImpl::copyTo(const Keychain &keychain, Access *newAccess) +{ + StLock_(mMutex); + Item item(*this); + if (newAccess) + item->setAccess(newAccess); + else + { + /* Attempt to copy the access from the current item to the newly created one. */ + SSGroup myGroup = group(); + if (myGroup) + { + SecPointer access = new Access(*myGroup); + item->setAccess(access); + } + } + + keychain->addCopy(item); + return item; +} + +void +ItemImpl::update() +{ + StLock_(mMutex); + if (!mKeychain) + MacOSError::throwMe(errSecNoSuchKeychain); + + // Don't update if nothing changed. + if (!isModified()) + return; + + CSSM_DB_RECORDTYPE aRecordType = recordType(); + KeychainSchema schema = mKeychain->keychainSchema(); + + // Update the modification date on the item if there is a mod date attribute. + if (schema->hasAttribute(aRecordType, kSecModDateItemAttr)) + { + SInt64 date; + GetCurrentMacLongDateTime(date); + setAttribute(schema->attributeInfoFor(aRecordType, kSecModDateItemAttr), date); + } + + // Make sure that we have mUniqueId + dbUniqueRecord(); + Db db(mUniqueId->database()); + if (mDoNotEncrypt) + { + CSSM_DB_RECORD_ATTRIBUTE_DATA attrData; + memset (&attrData, 0, sizeof (attrData)); + attrData.DataRecordType = aRecordType; + + mUniqueId->modifyWithoutEncryption(aRecordType, + &attrData, + mData.get(), + CSSM_DB_MODIFY_ATTRIBUTE_REPLACE); + } + else if (useSecureStorage(db)) + { + // Add the item to the secure storage db + SSDbUniqueRecordImpl * impl = dynamic_cast(&(*mUniqueId)); + if (impl == NULL) + { + CssmError::throwMe(CSSMERR_CSSM_INVALID_POINTER); + } + + SSDbUniqueRecord ssUniqueId(impl); + + // @@@ Share this instance + const AccessCredentials *autoPrompt = globals().itemCredentials(); + + + // Only call this is user interaction is enabled. + ssUniqueId->modify(aRecordType, + mDbAttributes.get(), + mData.get(), + CSSM_DB_MODIFY_ATTRIBUTE_REPLACE, + autoPrompt); + } + else + { + mUniqueId->modify(aRecordType, + mDbAttributes.get(), + mData.get(), + CSSM_DB_MODIFY_ATTRIBUTE_REPLACE); + } + + if (!mDoNotEncrypt) + { + PrimaryKey oldPK = mPrimaryKey; + mPrimaryKey = mKeychain->makePrimaryKey(aRecordType, mUniqueId); + + // Forget our data and attributes. + mData = NULL; + mDbAttributes.reset(NULL); + + // Let the Keychain update what it needs to. + mKeychain->didUpdate(this, oldPK, mPrimaryKey); + } +} + +void +ItemImpl::getClass(SecKeychainAttribute &attr, UInt32 *actualLength) +{ + StLock_(mMutex); + if (actualLength) + *actualLength = sizeof(SecItemClass); + + if (attr.length < sizeof(SecItemClass)) + MacOSError::throwMe(errSecBufferTooSmall); + + SecItemClass aClass = Schema::itemClassFor(recordType()); + memcpy(attr.data, &aClass, sizeof(SecItemClass)); +} + +void +ItemImpl::setAttribute(SecKeychainAttribute& attr) +{ + StLock_(mMutex); + setAttribute(Schema::attributeInfo(attr.tag), CssmData(attr.data, attr.length)); +} + +CSSM_DB_RECORDTYPE +ItemImpl::recordType() +{ + StLock_(mMutex); + if (mDbAttributes.get()) + return mDbAttributes->recordType(); + + return mPrimaryKey->recordType(); +} + +const DbAttributes * +ItemImpl::modifiedAttributes() +{ + StLock_(mMutex); + return mDbAttributes.get(); +} + +const CssmData * +ItemImpl::modifiedData() +{ + StLock_(mMutex); + return mData.get(); +} + +void +ItemImpl::setData(UInt32 length,const void *data) +{ + StLock_(mMutex); + mData = new CssmDataContainer(data, length); +} + +void +ItemImpl::setAccess(Access *newAccess) +{ + StLock_(mMutex); + mAccess = newAccess; +} + +CssmClient::DbUniqueRecord +ItemImpl::dbUniqueRecord() +{ + StLock_(mMutex); + if (!isPersistent()) // is there no database attached? + { + MacOSError::throwMe(errSecNotAvailable); + } + + if (!mUniqueId) + { + DbCursor cursor(mPrimaryKey->createCursor(mKeychain)); + if (!cursor->next(NULL, NULL, mUniqueId)) + MacOSError::throwMe(errSecInvalidItemRef); + } + + return mUniqueId; +} + +PrimaryKey +ItemImpl::primaryKey() +{ + return mPrimaryKey; +} + +bool +ItemImpl::isPersistent() +{ + return mKeychain; +} + +bool +ItemImpl::isModified() +{ + StLock_(mMutex); + return mData.get() || mDbAttributes.get(); +} + +Keychain +ItemImpl::keychain() +{ + return mKeychain; +} + +bool +ItemImpl::operator < (const ItemImpl &other) +{ + if (mData && *mData) + { + // Pointer compare + return this < &other; + } + + return mPrimaryKey < other.mPrimaryKey; +} + +void +ItemImpl::setAttribute(const CssmDbAttributeInfo &info, const CssmPolyData &data) +{ + StLock_(mMutex); + if (!mDbAttributes.get()) + { + mDbAttributes.reset(new DbAttributes()); + mDbAttributes->recordType(mPrimaryKey->recordType()); + } + + uint32 length = data.Length; + const void *buf = reinterpret_cast(data.Data); + uint8 timeString[16]; + + // XXX This code is duplicated in KCCursorImpl::KCCursorImpl() + // Convert a 4 or 8 byte TIME_DATE to a CSSM_DB_ATTRIBUTE_FORMAT_TIME_DATE + // style attribute value. + if (info.format() == CSSM_DB_ATTRIBUTE_FORMAT_TIME_DATE) + { + if (length == sizeof(UInt32)) + { + MacSecondsToTimeString(*reinterpret_cast(buf), 16, &timeString); + buf = &timeString; + length = 16; + } + else if (length == sizeof(SInt64)) + { + MacLongDateTimeToTimeString(*reinterpret_cast(buf), 16, &timeString); + buf = &timeString; + length = 16; + } + } + + mDbAttributes->add(info, CssmData(const_cast(buf), length)); +} + +void +ItemImpl::modifyContent(const SecKeychainAttributeList *attrList, UInt32 dataLength, const void *inData) +{ + StLock_(mMutex); + if (!mDbAttributes.get()) + { + mDbAttributes.reset(new DbAttributes()); + mDbAttributes->recordType(mPrimaryKey->recordType()); + } + + if(attrList) // optional + { + for(UInt32 ix=0; ix < attrList->count; ix++) + { + SecKeychainAttrType attrTag = attrList->attr[ix].tag; + + if (attrTag == APPLEDB_CSSM_PRINTNAME_ATTRIBUTE) + { + // must remap a caller-supplied kSecKeyPrintName attribute tag for key items, since it isn't in the schema + // (note that this will ultimately match kGenericPrintName in Schema.cpp) + attrTag = kSecLabelItemAttr; + } + + mDbAttributes->add(Schema::attributeInfo(attrTag), CssmData(attrList->attr[ix].data, attrList->attr[ix].length)); + } + } + + if(inData) + { + mData = new CssmDataContainer(inData, dataLength); + } + + update(); +} + +void +ItemImpl::getContent(SecItemClass *itemClass, SecKeychainAttributeList *attrList, UInt32 *length, void **outData) +{ + StLock_(mMutex); + // If the data hasn't been set we can't return it. + if (!mKeychain && outData) + { + CssmData *data = mData.get(); + if (!data) + MacOSError::throwMe(errSecDataNotAvailable); + } + // TODO: need to check and make sure attrs are valid and handle error condition + + + if (itemClass) + *itemClass = Schema::itemClassFor(recordType()); + + bool getDataFromDatabase = mKeychain && mPrimaryKey; + if (getDataFromDatabase) // are we attached to a database? + { + dbUniqueRecord(); + + // get the number of attributes requested by the caller + UInt32 attrCount = attrList ? attrList->count : 0; + + // make a DBAttributes structure and populate it + DbAttributes dbAttributes(mUniqueId->database(), attrCount); + for (UInt32 ix = 0; ix < attrCount; ++ix) + { + dbAttributes.add(Schema::attributeInfo(attrList->attr[ix].tag)); + } + + // request the data from the database (since we are a reference "item" and the data is really stored there) + CssmDataContainer itemData; + getContent(&dbAttributes, outData ? &itemData : NULL); + + // retrieve the data from result + for (UInt32 ix = 0; ix < attrCount; ++ix) + { + if (dbAttributes.at(ix).NumberOfValues > 0) + { + attrList->attr[ix].data = dbAttributes.at(ix).Value[0].Data; + attrList->attr[ix].length = dbAttributes.at(ix).Value[0].Length; + + // We don't want the data released, it is up the client + dbAttributes.at(ix).Value[0].Data = NULL; + dbAttributes.at(ix).Value[0].Length = 0; + } + else + { + attrList->attr[ix].data = NULL; + attrList->attr[ix].length = 0; + } + } + + // clean up + if (outData) + { + *outData=itemData.data(); + itemData.Data = NULL; + + if (length) + *length=itemData.length(); + itemData.Length = 0; + } + } + else + { + getLocalContent(attrList, length, outData); + } + + // Inform anyone interested that we are doing this +#if SENDACCESSNOTIFICATIONS + if (outData) + { + secdebug("kcnotify", "ItemImpl::getContent(%p, %p, %p, %p) retrieved content", + itemClass, attrList, length, outData); + + KCEventNotifier::PostKeychainEvent(kSecDataAccessEvent, mKeychain, this); + } +#endif +} + +void +ItemImpl::freeContent(SecKeychainAttributeList *attrList, void *data) +{ + Allocator &allocator = Allocator::standard(); // @@@ This might not match the one used originally + if (data) + allocator.free(data); + + UInt32 attrCount = attrList ? attrList->count : 0; + for (UInt32 ix = 0; ix < attrCount; ++ix) + { + allocator.free(attrList->attr[ix].data); + attrList->attr[ix].data = NULL; + } +} + +void +ItemImpl::modifyAttributesAndData(const SecKeychainAttributeList *attrList, UInt32 dataLength, const void *inData) +{ + StLock_(mMutex); + if (!mKeychain) + MacOSError::throwMe(errSecNoSuchKeychain); + + if (!mDoNotEncrypt) + { + if (!mDbAttributes.get()) + { + mDbAttributes.reset(new DbAttributes()); + mDbAttributes->recordType(mPrimaryKey->recordType()); + } + + CSSM_DB_RECORDTYPE recordType = mDbAttributes->recordType(); + UInt32 attrCount = attrList ? attrList->count : 0; + for (UInt32 ix = 0; ix < attrCount; ix++) + { + SecKeychainAttrType attrTag = attrList->attr[ix].tag; + + if (attrTag == kSecLabelItemAttr) + { + // must remap a caller-supplied label attribute tag for password items, since it isn't in the schema + // (note that this will ultimately match kGenericPrintName in Schema.cpp) + if (IS_PASSWORD_ITEM_CLASS( Schema::itemClassFor(recordType) )) + attrTag = APPLEDB_GENERIC_PRINTNAME_ATTRIBUTE; + } + + CssmDbAttributeInfo info=mKeychain->attributeInfoFor(recordType, attrTag); + + if (attrList->attr[ix].length || info.AttributeFormat==CSSM_DB_ATTRIBUTE_FORMAT_STRING || info.AttributeFormat==CSSM_DB_ATTRIBUTE_FORMAT_BLOB + || info.AttributeFormat==CSSM_DB_ATTRIBUTE_FORMAT_STRING || info.AttributeFormat==CSSM_DB_ATTRIBUTE_FORMAT_BIG_NUM + || info.AttributeFormat==CSSM_DB_ATTRIBUTE_FORMAT_MULTI_UINT32) + mDbAttributes->add(info, CssmData(attrList->attr[ix].data, attrList->attr[ix].length)); + else + mDbAttributes->add(info); + } + } + + if(inData) + { + mData = new CssmDataContainer(inData, dataLength); + } + + update(); +} + +void +ItemImpl::getAttributesAndData(SecKeychainAttributeInfo *info, SecItemClass *itemClass, + SecKeychainAttributeList **attrList, UInt32 *length, void **outData) +{ + StLock_(mMutex); + // If the data hasn't been set we can't return it. + if (!mKeychain && outData) + { + CssmData *data = mData.get(); + if (!data) + MacOSError::throwMe(errSecDataNotAvailable); + } + // TODO: need to check and make sure attrs are valid and handle error condition + + SecItemClass myItemClass = Schema::itemClassFor(recordType()); + if (itemClass) + *itemClass = myItemClass; + + // @@@ This call won't work for floating items (like certificates). + dbUniqueRecord(); + + UInt32 attrCount = info ? info->count : 0; + DbAttributes dbAttributes(mUniqueId->database(), attrCount); + for (UInt32 ix = 0; ix < attrCount; ix++) + { + CssmDbAttributeData &record = dbAttributes.add(); + record.Info.AttributeNameFormat=CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER; + record.Info.Label.AttributeID=info->tag[ix]; + + if (record.Info.Label.AttributeID == kSecLabelItemAttr) + { + // must remap a caller-supplied label attribute tag for password items, since it isn't in the schema + if (IS_PASSWORD_ITEM_CLASS( myItemClass )) + record.Info.Label.AttributeID = APPLEDB_GENERIC_PRINTNAME_ATTRIBUTE; + } + } + + CssmDataContainer itemData; + getContent(&dbAttributes, outData ? &itemData : NULL); + + if (info && attrList) + { + SecKeychainAttributeList *theList=reinterpret_cast(malloc(sizeof(SecKeychainAttributeList))); + SecKeychainAttribute *attr=reinterpret_cast(malloc(sizeof(SecKeychainAttribute)*attrCount)); + theList->count=attrCount; + theList->attr=attr; + + for (UInt32 ix = 0; ix < attrCount; ++ix) + { + attr[ix].tag=info->tag[ix]; + + if (dbAttributes.at(ix).NumberOfValues > 0) + { + attr[ix].data = dbAttributes.at(ix).Value[0].Data; + attr[ix].length = dbAttributes.at(ix).Value[0].Length; + + // We don't want the data released, it is up the client + dbAttributes.at(ix).Value[0].Data = NULL; + dbAttributes.at(ix).Value[0].Length = 0; + } + else + { + attr[ix].data = NULL; + attr[ix].length = 0; + } + } + *attrList=theList; + } + + if (outData) + { + *outData=itemData.data(); + itemData.Data=NULL; + + if (length) *length=itemData.length(); + itemData.Length=0; + +#if SENDACCESSNOTIFICATIONS + secdebug("kcnotify", "ItemImpl::getAttributesAndData(%p, %p, %p, %p, %p) retrieved data", + info, itemClass, attrList, length, outData); + + KCEventNotifier::PostKeychainEvent(kSecDataAccessEvent, mKeychain, this); +#endif + } + +} + +void +ItemImpl::freeAttributesAndData(SecKeychainAttributeList *attrList, void *data) +{ + Allocator &allocator = Allocator::standard(); // @@@ This might not match the one used originally + + if (data) + allocator.free(data); + + if (attrList) + { + for (UInt32 ix = 0; ix < attrList->count; ++ix) + { + allocator.free(attrList->attr[ix].data); + } + free(attrList->attr); + free(attrList); + } +} + +void +ItemImpl::getAttribute(SecKeychainAttribute& attr, UInt32 *actualLength) +{ + StLock_(mMutex); + if (attr.tag == kSecClassItemAttr) + return getClass(attr, actualLength); + + if (mDbAttributes.get()) + { + CssmDbAttributeData *data = mDbAttributes->find(Schema::attributeInfo(attr.tag)); + if (data) + { + getAttributeFrom(data, attr, actualLength); + return; + } + } + + if (!mKeychain) + MacOSError::throwMe(errSecNoSuchAttr); + + dbUniqueRecord(); + DbAttributes dbAttributes(mUniqueId->database(), 1); + dbAttributes.add(Schema::attributeInfo(attr.tag)); + mUniqueId->get(&dbAttributes, NULL); + getAttributeFrom(&dbAttributes.at(0), attr, actualLength); +} + +void +ItemImpl::getAttributeFrom(CssmDbAttributeData *data, SecKeychainAttribute &attr, UInt32 *actualLength) +{ + StLock_(mMutex); + static const uint32 zero = 0; + uint32 length; + const void *buf = NULL; + + // Temporary storage for buf. + sint64 macLDT; + uint32 macSeconds; + sint16 svalue16; + uint16 uvalue16; + sint8 svalue8; + uint8 uvalue8; + + if (!data) + length = 0; + else if (data->size() < 1) // Attribute has no values. + { + if (data->format() == CSSM_DB_ATTRIBUTE_FORMAT_SINT32 + || data->format() == CSSM_DB_ATTRIBUTE_FORMAT_UINT32) + { + length = sizeof(zero); + buf = &zero; + } + else if (CSSM_DB_ATTRIBUTE_FORMAT_TIME_DATE) + length = 0; // Should we throw here? + else // All other formats + length = 0; + } + else // Get the first value + { + length = data->Value[0].Length; + buf = data->Value[0].Data; + + if (data->format() == CSSM_DB_ATTRIBUTE_FORMAT_SINT32) + { + if (attr.length == sizeof(sint8)) + { + length = attr.length; + svalue8 = sint8(*reinterpret_cast(buf)); + buf = &svalue8; + } + else if (attr.length == sizeof(sint16)) + { + length = attr.length; + svalue16 = sint16(*reinterpret_cast(buf)); + buf = &svalue16; + } + } + else if (data->format() == CSSM_DB_ATTRIBUTE_FORMAT_UINT32) + { + if (attr.length == sizeof(uint8)) + { + length = attr.length; + uvalue8 = uint8(*reinterpret_cast(buf)); + buf = &uvalue8; + } + else if (attr.length == sizeof(uint16)) + { + length = attr.length; + uvalue16 = uint16(*reinterpret_cast(buf)); + buf = &uvalue16; + } + } + else if (data->format() == CSSM_DB_ATTRIBUTE_FORMAT_TIME_DATE) + { + if (attr.length == sizeof(uint32)) + { + TimeStringToMacSeconds(data->Value[0], macSeconds); + buf = &macSeconds; + length = attr.length; + } + else if (attr.length == sizeof(sint64)) + { + TimeStringToMacLongDateTime(data->Value[0], macLDT); + buf = &macLDT; + length = attr.length; + } + } + } + + if (actualLength) + *actualLength = length; + + if (length) + { + if (attr.length < length) + MacOSError::throwMe(errSecBufferTooSmall); + + memcpy(attr.data, buf, length); + } +} + +void +ItemImpl::getData(CssmDataContainer& outData) +{ + StLock_(mMutex); + if (!mKeychain) + { + CssmData *data = mData.get(); + // If the data hasn't been set we can't return it. + if (!data) + MacOSError::throwMe(errSecDataNotAvailable); + + outData = *data; + return; + } + + getContent(NULL, &outData); + +#if SENDACCESSNOTIFICATIONS + secdebug("kcnotify", "ItemImpl::getData retrieved data"); + + //%%% be done elsewhere, but here is good for now + KCEventNotifier::PostKeychainEvent(kSecDataAccessEvent, mKeychain, this); +#endif +} + +SSGroup +ItemImpl::group() +{ + StLock_(mMutex); + SSGroup group; + if (!!mUniqueId) + { + Db db(mKeychain->database()); + if (useSecureStorage(db)) + { + group = safer_cast(*mUniqueId).group(); + } + } + + return group; +} + +void ItemImpl::getLocalContent(SecKeychainAttributeList *attributeList, UInt32 *outLength, void **outData) +{ + StLock_(mMutex); + willRead(); + Allocator &allocator = Allocator::standard(); // @@@ This might not match the one used originally + if (outData) + { + CssmData *data = mData.get(); + if (!data) + MacOSError::throwMe(errSecDataNotAvailable); + + // Copy the data out of our internal cached copy. + uint32 length = data->Length; + *outData = allocator.malloc(length); + memcpy(*outData, data->Data, length); + if (outLength) + *outLength = length; + } + + if (attributeList) + { + if (!mDbAttributes.get()) + MacOSError::throwMe(errSecDataNotAvailable); + + // Pull attributes out of a "floating" item, i.e. one that isn't attached to a database + for (UInt32 ix = 0; ix < attributeList->count; ++ix) + { + SecKeychainAttribute &attribute = attributeList->attr[ix]; + CssmDbAttributeData *data = mDbAttributes->find(Schema::attributeInfo(attribute.tag)); + if (data && data->NumberOfValues > 0) + { + // Copy the data out of our internal cached copy. + uint32 length = data->Value[0].Length; + attribute.data = allocator.malloc(length); + memcpy(attribute.data, data->Value[0].Data, length); + attribute.length = length; + } + else + { + attribute.length = 0; + attribute.data = NULL; + } + } + } +} + +void +ItemImpl::getContent(DbAttributes *dbAttributes, CssmDataContainer *itemData) +{ + StLock_(mMutex); + // Make sure mUniqueId is set. + dbUniqueRecord(); + if (itemData) + { + Db db(mUniqueId->database()); + if (mDoNotEncrypt) + { + mUniqueId->getWithoutEncryption (dbAttributes, itemData); + return; + } + if (useSecureStorage(db)) + { + SSDbUniqueRecordImpl* impl = dynamic_cast(&(*mUniqueId)); + if (impl == NULL) + { + CssmError::throwMe(CSSMERR_CSSM_INVALID_POINTER); + } + + SSDbUniqueRecord ssUniqueId(impl); + const AccessCredentials *autoPrompt = globals().itemCredentials(); + ssUniqueId->get(dbAttributes, itemData, autoPrompt); + return; + } + } + + mUniqueId->get(dbAttributes, itemData); +} + +bool +ItemImpl::useSecureStorage(const Db &db) +{ + StLock_(mMutex); + switch (recordType()) + { + case CSSM_DL_DB_RECORD_GENERIC_PASSWORD: + case CSSM_DL_DB_RECORD_INTERNET_PASSWORD: + case CSSM_DL_DB_RECORD_APPLESHARE_PASSWORD: + if (db->dl()->subserviceMask() & CSSM_SERVICE_CSP) + return true; + break; + default: + break; + } + return false; +} + +void ItemImpl::willRead() +{ +} + + +void ItemImpl::copyPersistentReference(CFDataRef &outDataRef) +{ + StLock_(mMutex); + // item must be in a keychain and have a primary key to be persistent + if (!mKeychain || !mPrimaryKey) { + MacOSError::throwMe(errSecItemNotFound); + } + DLDbIdentifier dlDbIdentifier = mKeychain->dlDbIdentifier(); + DLDbIdentifier newDlDbIdentifier(dlDbIdentifier.ssuid(), + DLDbListCFPref::AbbreviatedPath(mKeychain->name()).c_str(), + dlDbIdentifier.dbLocation()); + NameValueDictionary dict; + NameValueDictionary::MakeNameValueDictionaryFromDLDbIdentifier(newDlDbIdentifier, dict); + + CssmData* pKey = mPrimaryKey; + dict.Insert (new NameValuePair(ITEM_KEY, *pKey)); + + // flatten the NameValueDictionary + CssmData dictData; + dict.Export(dictData); + outDataRef = ::CFDataCreate(kCFAllocatorDefault, dictData.Data, dictData.Length); + free (dictData.Data); +} + +void ItemImpl::copyRecordIdentifier(CSSM_DATA &data) +{ + StLock_(mMutex); + CssmClient::DbUniqueRecord uniqueRecord = dbUniqueRecord (); + uniqueRecord->getRecordIdentifier(data); +} + +/* + * Obtain blob used to bind a keychain item to an Extended Attribute record. + * We just use the PrimaryKey blob as the default. Note that for standard Items, + * this can cause the loss of extended attribute bindings if a Primary Key + * attribute changes. + */ +const CssmData &ItemImpl::itemID() +{ + StLock_(mMutex); + if(mPrimaryKey->length() == 0) { + /* not in a keychain; we don't have a primary key */ + MacOSError::throwMe(errSecNoSuchAttr); + } + return *mPrimaryKey; +} + + +void ItemImpl::postItemEvent(SecKeychainEvent theEvent) +{ + mKeychain->postEvent(theEvent, this); +} + + + +// +// Item -- This class is here to magically create the right subclass of ItemImpl +// when constructing new items. +// +Item::Item() +{ +} + +Item::Item(ItemImpl *impl) : SecPointer(impl) +{ +} + +Item::Item(SecItemClass itemClass, OSType itemCreator, UInt32 length, const void* data, bool inhibitCheck) +{ + if (!inhibitCheck) + { + if (itemClass == CSSM_DL_DB_RECORD_X509_CERTIFICATE + || itemClass == CSSM_DL_DB_RECORD_PUBLIC_KEY + || itemClass == CSSM_DL_DB_RECORD_PRIVATE_KEY + || itemClass == CSSM_DL_DB_RECORD_SYMMETRIC_KEY) + MacOSError::throwMe(errSecNoSuchClass); /* @@@ errSecInvalidClass */ + } + + *this = new ItemImpl(itemClass, itemCreator, length, data, inhibitCheck); +} + +Item::Item(SecItemClass itemClass, SecKeychainAttributeList *attrList, UInt32 length, const void* data) +{ + *this = new ItemImpl(itemClass, attrList, length, data); +} + +Item::Item(const Keychain &keychain, const PrimaryKey &primaryKey, const CssmClient::DbUniqueRecord &uniqueId) + : SecPointer( + primaryKey->recordType() == CSSM_DL_DB_RECORD_X509_CERTIFICATE + ? Certificate::make(keychain, primaryKey, uniqueId) + : (primaryKey->recordType() == CSSM_DL_DB_RECORD_PUBLIC_KEY + || primaryKey->recordType() == CSSM_DL_DB_RECORD_PRIVATE_KEY + || primaryKey->recordType() == CSSM_DL_DB_RECORD_SYMMETRIC_KEY) + ? KeyItem::make(keychain, primaryKey, uniqueId) + : primaryKey->recordType() == CSSM_DL_DB_RECORD_EXTENDED_ATTRIBUTE + ? ExtendedAttribute::make(keychain, primaryKey, uniqueId) + : ItemImpl::make(keychain, primaryKey, uniqueId)) +{ +} + +Item::Item(const Keychain &keychain, const PrimaryKey &primaryKey) + : SecPointer( + primaryKey->recordType() == CSSM_DL_DB_RECORD_X509_CERTIFICATE + ? Certificate::make(keychain, primaryKey) + : (primaryKey->recordType() == CSSM_DL_DB_RECORD_PUBLIC_KEY + || primaryKey->recordType() == CSSM_DL_DB_RECORD_PRIVATE_KEY + || primaryKey->recordType() == CSSM_DL_DB_RECORD_SYMMETRIC_KEY) + ? KeyItem::make(keychain, primaryKey) + : primaryKey->recordType() == CSSM_DL_DB_RECORD_EXTENDED_ATTRIBUTE + ? ExtendedAttribute::make(keychain, primaryKey) + : ItemImpl::make(keychain, primaryKey)) +{ +} + +Item::Item(ItemImpl &item) + : SecPointer( + item.recordType() == CSSM_DL_DB_RECORD_X509_CERTIFICATE + ? new Certificate(safer_cast(item)) + : (item.recordType() == CSSM_DL_DB_RECORD_PUBLIC_KEY + || item.recordType() == CSSM_DL_DB_RECORD_PRIVATE_KEY + || item.recordType() == CSSM_DL_DB_RECORD_SYMMETRIC_KEY) + ? new KeyItem(safer_cast(item)) + : item.recordType() == CSSM_DL_DB_RECORD_EXTENDED_ATTRIBUTE + ? new ExtendedAttribute(safer_cast(item)) + : new ItemImpl(item)) +{ +} + +CFIndex GetItemRetainCount(Item& item) +{ + return CFGetRetainCount(item->handle(false)); +} + diff --git a/libsecurity_keychain/lib/Item.h b/libsecurity_keychain/lib/Item.h new file mode 100644 index 00000000..33927360 --- /dev/null +++ b/libsecurity_keychain/lib/Item.h @@ -0,0 +1,195 @@ +/* + * 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@ + */ + + +// +// Item.h +// +#ifndef _SECURITY_ITEM_H_ +#define _SECURITY_ITEM_H_ + +#include +#include +#include +#include + +namespace Security +{ + +using namespace CssmClient; + +namespace KeychainCore +{ +class Keychain; + +class ItemImpl : public SecCFObject +{ +public: + SECCFFUNCTIONS(ItemImpl, SecKeychainItemRef, errSecInvalidItemRef, gTypes().ItemImpl) + + friend class Item; + friend class KeychainImpl; +protected: + + // new item constructors + ItemImpl(SecItemClass itemClass, OSType itemCreator, UInt32 length, const void* data, bool inhibitCheck = false); + + ItemImpl(SecItemClass itemClass, SecKeychainAttributeList *attrList, UInt32 length, const void* data); + + // db item contstructor + ItemImpl(const Keychain &keychain, const PrimaryKey &primaryKey, const CssmClient::DbUniqueRecord &uniqueId); + + // PrimaryKey item contstructor + ItemImpl(const Keychain &keychain, const PrimaryKey &primaryKey); + +public: + + static ItemImpl* make(const Keychain &keychain, const PrimaryKey &primaryKey, const CssmClient::DbUniqueRecord &uniqueId); + static ItemImpl* make(const Keychain &keychain, const PrimaryKey &primaryKey); + + ItemImpl(ItemImpl &item); + + // Return true if we got the attribute, false if we only got the actualLength. + void getAttributeFrom(CssmDbAttributeData *data, SecKeychainAttribute &attr, UInt32 *actualLength); + void getClass(SecKeychainAttribute &attr, UInt32 *actualLength); + + PrimaryKey addWithCopyInfo(Keychain &keychain, bool isCopy); + Mutex* getMutexForObject(); + +protected: + // Methods called by KeychainImpl; + + // Add the receiver to keychain + virtual PrimaryKey add(Keychain &keychain); + + // Get the default value for an attribute + static const CSSM_DATA &defaultAttributeValue(const CSSM_DB_ATTRIBUTE_INFO &info); + +public: + virtual ~ItemImpl(); + bool isPersistent(); + bool isModified(); + + virtual void update(); + + void aboutToDestruct(); + + // put a copy of the item into a given keychain + virtual Item copyTo(const Keychain &keychain, Access *newAccess = NULL); + + CSSM_DB_RECORDTYPE recordType(); + + // Used for writing the record to the database. + CssmClient::DbUniqueRecord dbUniqueRecord(); + const CssmClient::DbAttributes *modifiedAttributes(); + const CssmData *modifiedData(); + virtual void didModify(); // Forget any attributes and data we just wrote to the db + + Keychain keychain(); + PrimaryKey primaryKey(); + bool operator < (const ItemImpl &other); + + void getAttribute(SecKeychainAttribute& attr, UInt32 *actualLength); + void getData(CssmDataContainer& outData); + + void modifyContent(const SecKeychainAttributeList *attrList, UInt32 dataLength, const void *inData); + void getContent(SecItemClass *itemClass, SecKeychainAttributeList *attrList, UInt32 *length, void **outData); + static void freeContent(SecKeychainAttributeList *attrList, void *data); + static void freeAttributesAndData(SecKeychainAttributeList *attrList, void *data); + + void getAttributesAndData(SecKeychainAttributeInfo *info, SecItemClass *itemClass, + SecKeychainAttributeList **attrList, UInt32 *length, void **outData); + void modifyAttributesAndData(const SecKeychainAttributeList *attrList, UInt32 dataLength, const void *inData); + + void setAttribute(SecKeychainAttribute& attr); + void setAttribute(const CssmDbAttributeInfo &info, const CssmPolyData &data); + void setData(UInt32 length,const void *data); + void setAccess(Access *newAccess); + void copyRecordIdentifier(CSSM_DATA &data); + SSGroup group(); + + void getContent(DbAttributes *dbAttributes, CssmDataContainer *itemData); + void getLocalContent(SecKeychainAttributeList *attributeList, UInt32 *outLength, void **outData); + + bool useSecureStorage(const CssmClient::Db &db); + virtual void willRead(); + + // create a persistent reference to this item + void copyPersistentReference(CFDataRef &outDataRef); + + // for keychain syncing + void doNotEncrypt () {mDoNotEncrypt = true;} + + // for posting events on this item + void postItemEvent (SecKeychainEvent theEvent); + + // Only call these functions while holding globals().apiLock. + bool inCache() const throw() { return mInCache; } + void inCache(bool inCache) throw() { mInCache = inCache; } + + /* For binding to extended attributes. */ + virtual const CssmData &itemID(); + +protected: + // new item members + RefPointer mData; + auto_ptr mDbAttributes; + SecPointer mAccess; + + // db item members + CssmClient::DbUniqueRecord mUniqueId; + Keychain mKeychain; + PrimaryKey mPrimaryKey; + +private: + // keychain syncing flags + bool mDoNotEncrypt; + + // mInCache is protected by globals().apiLock + // True iff we are in the cache of items in mKeychain + bool mInCache; + +protected: + Mutex mMutex; +}; + + +class Item : public SecPointer +{ +public: + Item(); + Item(ItemImpl *impl); + Item(SecItemClass itemClass, OSType itemCreator, UInt32 length, const void* data, bool inhibitCheck); + Item(SecItemClass itemClass, SecKeychainAttributeList *attrList, UInt32 length, const void* data); + Item(const Keychain &keychain, const PrimaryKey &primaryKey, const CssmClient::DbUniqueRecord &uniqueId); + Item(const Keychain &keychain, const PrimaryKey &primaryKey); + Item(ItemImpl &item); +}; + +CFIndex GetItemRetainCount(Item& item); + +} // end namespace KeychainCore + +} // end namespace Security + +#endif // !_SECURITY_ITEM_H_ diff --git a/libsecurity_keychain/lib/KCCursor.cpp b/libsecurity_keychain/lib/KCCursor.cpp new file mode 100644 index 00000000..0464edfd --- /dev/null +++ b/libsecurity_keychain/lib/KCCursor.cpp @@ -0,0 +1,300 @@ +/* + * 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@ + */ + + +// +// KCCursor.cpp +// + +#include "KCCursor.h" + +#include "Item.h" +#include +#include +#include "cssmdatetime.h" +#include "Globals.h" +#include "StorageManager.h" +#include +#include + +using namespace KeychainCore; +using namespace CssmClient; +using namespace CSSMDateTimeUtils; + +using namespace KeySchema; + +// define a table of our attributes for easy lookup +static const CSSM_DB_ATTRIBUTE_INFO* gKeyAttributeLookupTable[] = +{ + &KeyClass, &PrintName, &Alias, &Permanent, &Private, &Modifiable, &Label, &ApplicationTag, &KeyCreator, + &KeyType, &KeySizeInBits, &EffectiveKeySize, &StartDate, &EndDate, &Sensitive, &AlwaysSensitive, &Extractable, + &NeverExtractable, &Encrypt, &Decrypt, &Derive, &Sign, &Verify, &SignRecover, &VerifyRecover, &Wrap, &Unwrap +}; + +// +// KCCursorImpl +// +KCCursorImpl::KCCursorImpl(const StorageManager::KeychainList &searchList, SecItemClass itemClass, const SecKeychainAttributeList *attrList, CSSM_DB_CONJUNCTIVE dbConjunctive, CSSM_DB_OPERATOR dbOperator) : + mSearchList(searchList), + mCurrent(mSearchList.begin()), + mAllFailed(true), + mMutex(Mutex::recursive) +{ + recordType(Schema::recordTypeFor(itemClass)); + + if (!attrList) // No additional selectionPredicates: we are done + return; + + conjunctive(dbConjunctive); + const SecKeychainAttribute *end=&attrList->attr[attrList->count]; + // Add all the attrs in attrs list to the cursor. + for (const SecKeychainAttribute *attr=attrList->attr; attr != end; ++attr) + { + const CSSM_DB_ATTRIBUTE_INFO *temp; + + if (attr->tag <' ') // ok, is this a key schema? Handle differently, just because we can... + { + temp = gKeyAttributeLookupTable[attr->tag]; + } + else + { + temp = &Schema::attributeInfo(attr->tag); + } + const CssmDbAttributeInfo &info = *temp; + void *buf = attr->data; + UInt32 length = attr->length; + uint8 timeString[16]; + + // XXX This code is duplicated in NewItemImpl::setAttribute() + // Convert a 4 or 8 byte TIME_DATE to a CSSM_DB_ATTRIBUTE_FORMAT_TIME_DATE + // style attribute value. + if (info.format() == CSSM_DB_ATTRIBUTE_FORMAT_TIME_DATE) + { + if (length == sizeof(UInt32)) + { + MacSecondsToTimeString(*reinterpret_cast(buf), + 16, &timeString); + buf = &timeString; + length = 16; + } + else if (length == sizeof(SInt64)) + { + MacLongDateTimeToTimeString(*reinterpret_cast(buf), + 16, &timeString); + buf = &timeString; + length = 16; + } + } + add(dbOperator ,info, CssmData(buf,length)); + } +} + +KCCursorImpl::KCCursorImpl(const StorageManager::KeychainList &searchList, const SecKeychainAttributeList *attrList) : + mSearchList(searchList), + mCurrent(mSearchList.begin()), + mAllFailed(true), + mMutex(Mutex::recursive) +{ + if (!attrList) // No additional selectionPredicates: we are done + return; + + conjunctive(CSSM_DB_AND); + bool foundClassAttribute=false; + const SecKeychainAttribute *end=&attrList->attr[attrList->count]; + // Add all the attrs in attrs list to the cursor. + for (const SecKeychainAttribute *attr=attrList->attr; attr != end; ++attr) + { + if (attr->tag!=kSecClassItemAttr) // a regular attribute + { + const CssmDbAttributeInfo &info = Schema::attributeInfo(attr->tag); + void *buf = attr->data; + UInt32 length = attr->length; + uint8 timeString[16]; + + // XXX This code is duplicated in NewItemImpl::setAttribute() + // Convert a 4 or 8 byte TIME_DATE to a CSSM_DB_ATTRIBUTE_FORMAT_TIME_DATE + // style attribute value. + if (info.format() == CSSM_DB_ATTRIBUTE_FORMAT_TIME_DATE) + { + if (length == sizeof(UInt32)) + { + MacSecondsToTimeString(*reinterpret_cast(buf), + 16, &timeString); + buf = &timeString; + length = 16; + } + else if (length == sizeof(SInt64)) + { + MacLongDateTimeToTimeString(*reinterpret_cast(buf), + 16, &timeString); + buf = &timeString; + length = 16; + } + } + add(CSSM_DB_EQUAL,info, CssmData(buf,length)); + + continue; + } + + // the class attribute + if (foundClassAttribute || attr->length != sizeof(SecItemClass)) + MacOSError::throwMe(paramErr); // We have 2 different 'clas' attributes + + recordType(Schema::recordTypeFor(*reinterpret_cast(attr->data))); + foundClassAttribute=true; + } +} + +KCCursorImpl::~KCCursorImpl() throw() +{ +} + +static ModuleNexus gActivationMutex; + +bool +KCCursorImpl::next(Item &item) +{ + StLock_(mMutex); + DbAttributes dbAttributes; + DbUniqueRecord uniqueId; + OSStatus status = 0; + + for (;;) + { + while (!mDbCursor) + { + if (mCurrent == mSearchList.end()) + { + // If we got always failed when calling mDbCursor->next return the error from + // the last call to mDbCursor->next now + if (mAllFailed && status) + CssmError::throwMe(status); + + // No more keychains to search so we are done. + return false; + } + + try + { + /* WARNING: THIS SECTION IS CRITICAL. + If multiple threads are attempting to activate + the same database at the same time, the global + system database queue will reflect the most recent + activation rather than the activation which was + created by this thread. + + We could protect the database structures, but that's not the + right answer because it's perfectly legal to have + more than one context. That would basically just + make a big lock around CDSA, which is a performance + nightmare. Instead, we protect the PROCESS under + which databases are activated. + */ + + StLock _(gActivationMutex()); // force serialization of cursor creation + (*mCurrent)->database()->activate(); + mDbCursor = DbCursor((*mCurrent)->database(), *this); + } + catch(const CommonError &err) + { + ++mCurrent; + } + } + + bool gotRecord; + try + { + // Clear out existing attributes first! + // (the previous iteration may have left attributes from a different schema) + dbAttributes.clear(); + + gotRecord = mDbCursor->next(&dbAttributes, NULL, uniqueId); + mAllFailed = false; + } + catch(const CommonError &err) + { + // Catch the last error we get and move on to the next keychain + // This error will be returned when we reach the end of our keychain list + // iff all calls to KCCursorImpl::next failed + status = err.osStatus(); + gotRecord = false; + dbAttributes.invalidate(); + } + catch(...) + { + // Catch all other errors + status = errSecItemNotFound; + gotRecord = false; + } + + // If we did not get a record from the current keychain or the current + // keychain did not exist skip to the next keychain in the list. + if (!gotRecord) + { + ++mCurrent; + mDbCursor = DbCursor(); + continue; + } + + // If doing a search for all records, skip the db blob added by the CSPDL + if (dbAttributes.recordType() == CSSM_DL_DB_RECORD_METADATA && + mDbCursor->recordType() == CSSM_DL_DB_RECORD_ANY) + continue; + + // Filter out group keys at this layer + if (dbAttributes.recordType() == CSSM_DL_DB_RECORD_SYMMETRIC_KEY) + { + bool groupKey = false; + try + { + // fetch the key label attribute, if it exists + dbAttributes.add(KeySchema::Label); + Db db((*mCurrent)->database()); + CSSM_RETURN getattr_result = CSSM_DL_DataGetFromUniqueRecordId(db->handle(), uniqueId, &dbAttributes, NULL); + if (getattr_result == CSSM_OK) + { + CssmDbAttributeData *label = dbAttributes.find(KeySchema::Label); + CssmData attrData; + if (label) + attrData = *label; + if (attrData.length() > 4 && !memcmp(attrData.data(), "ssgp", 4)) + groupKey = true; + } + else + { + dbAttributes.invalidate(); + } + } + catch (...) {} + + if (groupKey) + continue; + } + + break; + } + + // Go though Keychain since item might already exist. + item = (*mCurrent)->item(dbAttributes.recordType(), uniqueId); + return true; +} diff --git a/libsecurity_keychain/lib/KCCursor.h b/libsecurity_keychain/lib/KCCursor.h new file mode 100644 index 00000000..a25e225c --- /dev/null +++ b/libsecurity_keychain/lib/KCCursor.h @@ -0,0 +1,85 @@ +/* + * 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@ + */ + +// +// KCCursor.h +// +#ifndef _SECURITY_KCCURSOR_H_ +#define _SECURITY_KCCURSOR_H_ + +#include + +namespace Security +{ + +namespace KeychainCore +{ + +class KCCursorImpl : public SecCFObject, public CssmAutoQuery +{ + NOCOPY(KCCursorImpl) +public: + SECCFFUNCTIONS(KCCursorImpl, SecKeychainSearchRef, errSecInvalidSearchRef, gTypes().KCCursorImpl) + + friend class KCCursor; +protected: + KCCursorImpl(const StorageManager::KeychainList &searchList, SecItemClass itemClass, const SecKeychainAttributeList *attrList, CSSM_DB_CONJUNCTIVE dbConjunctive, CSSM_DB_OPERATOR dbOperator); + KCCursorImpl(const StorageManager::KeychainList &searchList, const SecKeychainAttributeList *attrList); + +public: + virtual ~KCCursorImpl() throw(); + bool next(Item &item); + +private: + StorageManager::KeychainList mSearchList; + StorageManager::KeychainList::iterator mCurrent; + CssmClient::DbCursor mDbCursor; + bool mAllFailed; + +protected: + Mutex mMutex; +}; + + +class KCCursor : public SecPointer +{ +public: + KCCursor() {} + + KCCursor(KCCursorImpl *impl) : SecPointer(impl) {} + + KCCursor(const StorageManager::KeychainList &searchList, const SecKeychainAttributeList *attrList) + : SecPointer(new KCCursorImpl(searchList, attrList)) {} + + KCCursor(const StorageManager::KeychainList &searchList, SecItemClass itemClass, const SecKeychainAttributeList *attrList, CSSM_DB_CONJUNCTIVE dbConjunctive=CSSM_DB_AND, CSSM_DB_OPERATOR dbOperator=CSSM_DB_EQUAL) + : SecPointer(new KCCursorImpl(searchList, itemClass, attrList, dbConjunctive, dbOperator)) {} + + typedef KCCursorImpl Impl; +}; + + +} // end namespace KeychainCore + +} // end namespace Security + +#endif // !_SECURITY_KCCURSOR_H_ diff --git a/libsecurity_keychain/lib/KCEventNotifier.cpp b/libsecurity_keychain/lib/KCEventNotifier.cpp new file mode 100644 index 00000000..f33a0a56 --- /dev/null +++ b/libsecurity_keychain/lib/KCEventNotifier.cpp @@ -0,0 +1,79 @@ +/* + * 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@ + * + * KCEventNotifier.cpp -- OS X CF Notifier for Keychain Events + */ + +#include +#include "KCEventNotifier.h" +#include "KCExceptions.h" +#include "Keychains.h" + +using namespace KeychainCore; + +void KCEventNotifier::PostKeychainEvent(SecKeychainEvent whichEvent, const Keychain &keychain, const Item &kcItem) +{ + DLDbIdentifier dlDbIdentifier; + PrimaryKey primaryKey; + + if (keychain) + dlDbIdentifier = keychain->dlDbIdentifier(); + + if (kcItem) + primaryKey = kcItem->primaryKey(); + + PostKeychainEvent(whichEvent, dlDbIdentifier, primaryKey); +} + + +void KCEventNotifier::PostKeychainEvent(SecKeychainEvent whichEvent, + const DLDbIdentifier &dlDbIdentifier, + const PrimaryKey &primaryKey) +{ + NameValueDictionary nvd; + + Endian thePid = getpid(); + nvd.Insert (new NameValuePair (PID_KEY, CssmData (reinterpret_cast(&thePid), sizeof (pid_t)))); + + if (dlDbIdentifier) + { + NameValueDictionary::MakeNameValueDictionaryFromDLDbIdentifier (dlDbIdentifier, nvd); + } + + CssmData* pKey = primaryKey; + + if (primaryKey) + { + nvd.Insert (new NameValuePair (ITEM_KEY, *pKey)); + } + + // flatten the dictionary + CssmData data; + nvd.Export (data); + + SecurityServer::ClientSession cs (Allocator::standard(), Allocator::standard()); + cs.postNotification (SecurityServer::kNotificationDomainDatabase, whichEvent, data); + + secdebug("kcnotify", "KCEventNotifier::PostKeychainEvent posted event %u", (unsigned int) whichEvent); + + free (data.data ()); +} diff --git a/libsecurity_keychain/lib/KCEventNotifier.h b/libsecurity_keychain/lib/KCEventNotifier.h new file mode 100644 index 00000000..23b7ee86 --- /dev/null +++ b/libsecurity_keychain/lib/KCEventNotifier.h @@ -0,0 +1,60 @@ +/* + * 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@ + */ + + +/* + * KCEventNotifier.h -- OS X CF Notifier for Keychain Events + */ +#ifndef _SECURITY_KCEVENTNOTIFIER_H_ +#define _SECURITY_KCEVENTNOTIFIER_H_ + +#include +#include +#include +#include +#include + +namespace Security +{ + +namespace KeychainCore +{ + +class Keychain; + +class KCEventNotifier +{ +public: + static void PostKeychainEvent(SecKeychainEvent kcEvent, + const Keychain& keychain, + const Item &item = Item()); + static void PostKeychainEvent(SecKeychainEvent kcEvent, + const DLDbIdentifier &dlDbIdentifier = DLDbIdentifier(), + const PrimaryKey &primaryKey = PrimaryKey()); +}; + +} // end namespace KeychainCore + +} // end namespace Security + +#endif /* _SECURITY_KCEVENTNOTIFIER_H_ */ diff --git a/libsecurity_keychain/lib/KCExceptions.h b/libsecurity_keychain/lib/KCExceptions.h new file mode 100644 index 00000000..3c62f782 --- /dev/null +++ b/libsecurity_keychain/lib/KCExceptions.h @@ -0,0 +1,97 @@ +/* + * 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@ + */ + + +/* + * KCExceptions.h + */ +#ifndef _SECURITY_KCEXCEPTIONS_H_ +#define _SECURITY_KCEXCEPTIONS_H_ + +#include +#include + +#ifdef lock +#undef lock +#endif +//#include + +#ifdef check +#undef check +#endif + +namespace Security +{ + +namespace KeychainCore +{ + +// +// Helpers for memory pointer validation +// + +/* remove RequiredParam when cdsa does namespaces +template +inline T &Required(T *ptr,OSStatus err = paramErr) +{ + return Required(ptr,err); +} +*/ + +template +inline void KCThrowIfMemFail_(const T *ptr) +{ + if (ptr==NULL) + MacOSError::throwMe(memFullErr); +} + +inline void KCThrowIf_(OSStatus theErr) +{ + // will also work for OSErr + if (theErr!=noErr) + MacOSError::throwMe(theErr); +} + +inline void KCThrowIf_(bool test,OSStatus theErr) +{ + // will also work for OSErr + if (test) + MacOSError::throwMe(theErr); +} + +inline void KCThrowParamErrIf_(bool test) +{ + if (test) + MacOSError::throwMe(paramErr); +} + +inline void KCUnimplemented_() +{ + MacOSError::throwMe(unimpErr); +} + +} // end namespace KeychainCore + +} // end namespace Security + +#endif /* !_SECURITY_KCEXCEPTIONS_H_ */ diff --git a/libsecurity_keychain/lib/KCUtilities.cpp b/libsecurity_keychain/lib/KCUtilities.cpp new file mode 100644 index 00000000..d90869b1 --- /dev/null +++ b/libsecurity_keychain/lib/KCUtilities.cpp @@ -0,0 +1,30 @@ +/* + * 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@ + */ + + +#include + +namespace Security +{ + +} // end namespace Security diff --git a/libsecurity_keychain/lib/KCUtilities.h b/libsecurity_keychain/lib/KCUtilities.h new file mode 100644 index 00000000..76583502 --- /dev/null +++ b/libsecurity_keychain/lib/KCUtilities.h @@ -0,0 +1,46 @@ +/* + * 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@ + */ + +#ifndef _SECURITY_KCUTILITIES_H_ +#define _SECURITY_KCUTILITIES_H_ + +#include +#include + +namespace Security +{ + +// +// Helpers for memory pointer validation +// +template +inline T &RequiredParam(T *ptr,OSStatus err = paramErr) +{ + if (ptr == NULL) + MacOSError::throwMe(err); + return *ptr; +} + +} // end namespace Security + +#endif // !_SECURITY_KCUTILITIES_H_ diff --git a/libsecurity_keychain/lib/KeyItem.cpp b/libsecurity_keychain/lib/KeyItem.cpp new file mode 100644 index 00000000..46be6bae --- /dev/null +++ b/libsecurity_keychain/lib/KeyItem.cpp @@ -0,0 +1,1350 @@ +/* + * 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@ + */ + +// +// KeyItem.cpp +// +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "KCEventNotifier.h" + +// @@@ This needs to be shared. +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); + +using namespace KeychainCore; +using namespace CssmClient; + +KeyItem::KeyItem(const Keychain &keychain, const PrimaryKey &primaryKey, const CssmClient::DbUniqueRecord &uniqueId) : + ItemImpl(keychain, primaryKey, uniqueId), + mKey(), + algid(NULL), + mPubKeyHash(Allocator::standard()) +{ +} + +KeyItem::KeyItem(const Keychain &keychain, const PrimaryKey &primaryKey) : + ItemImpl(keychain, primaryKey), + mKey(), + algid(NULL), + mPubKeyHash(Allocator::standard()) +{ +} + +KeyItem* KeyItem::make(const Keychain &keychain, const PrimaryKey &primaryKey, const CssmClient::DbUniqueRecord &uniqueId) +{ + KeyItem* k = new KeyItem(keychain, primaryKey, uniqueId); + keychain->addItem(primaryKey, k); + return k; +} + + + +KeyItem* KeyItem::make(const Keychain &keychain, const PrimaryKey &primaryKey) +{ + KeyItem* k = new KeyItem(keychain, primaryKey); + keychain->addItem(primaryKey, k); + return k; +} + + + +KeyItem::KeyItem(KeyItem &keyItem) : + ItemImpl(keyItem), + mKey(), + algid(NULL), + mPubKeyHash(Allocator::standard()) +{ + // @@@ this doesn't work for keys that are not in a keychain. +} + +KeyItem::KeyItem(const CssmClient::Key &key) : + ItemImpl(key->keyClass() + CSSM_DL_DB_RECORD_PUBLIC_KEY, (OSType)0, (UInt32)0, (const void*)NULL), + mKey(key), + algid(NULL), + mPubKeyHash(Allocator::standard()) +{ + if (key->keyClass() > CSSM_KEYCLASS_SESSION_KEY) + MacOSError::throwMe(paramErr); +} + +KeyItem::~KeyItem() throw() +{ +} + +void +KeyItem::update() +{ + ItemImpl::update(); +} + +Item +KeyItem::copyTo(const Keychain &keychain, Access *newAccess) +{ + if (!(keychain->database()->dl()->subserviceMask() & CSSM_SERVICE_CSP)) + MacOSError::throwMe(errSecInvalidKeychain); + + /* Get the destination keychain's db. */ + SSDbImpl* dbImpl = dynamic_cast(&(*keychain->database())); + if (dbImpl == NULL) + { + CssmError::throwMe(CSSMERR_CSSM_INVALID_POINTER); + } + + SSDb ssDb(dbImpl); + + /* Make sure mKey is valid. */ + key(); + + // Generate a random label to use initially + CssmClient::CSP appleCsp(gGuidAppleCSP); + CssmClient::Random random(appleCsp, CSSM_ALGID_APPLE_YARROW); + uint8 labelBytes[20]; + CssmData label(labelBytes, sizeof(labelBytes)); + random.generate(label, label.Length); + + /* Set up the ACL for the new key. */ + SecPointer access; + if (newAccess) + access = newAccess; + else + access = new Access(*mKey); + + /* Generate a random 3DES wrapping Key. */ + CssmClient::GenerateKey genKey(csp(), CSSM_ALGID_3DES_3KEY, 192); + CssmClient::Key wrappingKey(genKey(KeySpec(CSSM_KEYUSE_WRAP | CSSM_KEYUSE_UNWRAP, + CSSM_KEYATTR_EXTRACTABLE /* | CSSM_KEYATTR_RETURN_DATA */))); + + /* make a random IV */ + uint8 ivBytes[8]; + CssmData iv(ivBytes, sizeof(ivBytes)); + random.generate(iv, iv.length()); + + /* Extract the key by wrapping it with the wrapping key. */ + CssmClient::WrapKey wrap(csp(), CSSM_ALGID_3DES_3KEY_EDE); + wrap.key(wrappingKey); + wrap.cred(getCredentials(CSSM_ACL_AUTHORIZATION_EXPORT_WRAPPED, kSecCredentialTypeDefault)); + wrap.mode(CSSM_ALGMODE_ECBPad); + wrap.padding(CSSM_PADDING_PKCS7); + wrap.initVector(iv); + CssmClient::Key wrappedKey(wrap(mKey)); + + /* Unwrap the new key into the new Keychain. */ + CssmClient::UnwrapKey unwrap(keychain->csp(), CSSM_ALGID_3DES_3KEY_EDE); + unwrap.key(wrappingKey); + unwrap.mode(CSSM_ALGMODE_ECBPad); + unwrap.padding(CSSM_PADDING_PKCS7); + unwrap.initVector(iv); + + /* Setup the dldbHandle in the context. */ + unwrap.add(CSSM_ATTRIBUTE_DL_DB_HANDLE, ssDb->handle()); + + /* Set up an initial aclEntry so we can change it after the unwrap. */ + Access::Maker maker(Allocator::standard(), Access::Maker::kAnyMakerType); + ResourceControlContext rcc; + maker.initialOwner(rcc, NULL); + unwrap.owner(rcc.input()); + + /* Unwrap the key. */ + uint32 usage = mKey->usage(); + /* Work around csp brokeness where it sets all usage bits in the Keyheader when CSSM_KEYUSE_ANY is set. */ + if (usage & CSSM_KEYUSE_ANY) + usage = CSSM_KEYUSE_ANY; + + CssmClient::Key unwrappedKey(unwrap(wrappedKey, KeySpec(usage, + (mKey->attributes() | CSSM_KEYATTR_PERMANENT) & ~(CSSM_KEYATTR_ALWAYS_SENSITIVE | CSSM_KEYATTR_NEVER_EXTRACTABLE), + label))); + + /* Look up unwrapped key in the DLDB. */ + DbUniqueRecord uniqueId; + SSDbCursor dbCursor(ssDb, 1); + dbCursor->recordType(recordType()); + dbCursor->add(CSSM_DB_EQUAL, kInfoKeyLabel, label); + CssmClient::Key copiedKey; + if (!dbCursor->nextKey(NULL, copiedKey, uniqueId)) + MacOSError::throwMe(errSecItemNotFound); + + /* Copy the Label, PrintName and ApplicationTag attributes from the old key to the new one. */ + dbUniqueRecord(); + DbAttributes oldDbAttributes(mUniqueId->database(), 3); + oldDbAttributes.add(kInfoKeyLabel); + oldDbAttributes.add(kInfoKeyPrintName); + oldDbAttributes.add(kInfoKeyApplicationTag); + mUniqueId->get(&oldDbAttributes, NULL); + try + { + uniqueId->modify(recordType(), &oldDbAttributes, NULL, CSSM_DB_MODIFY_ATTRIBUTE_REPLACE); + } + catch (CssmError e) + { + // clean up after trying to insert a duplicate key + uniqueId->deleteRecord (); + throw; + } + + /* Set the acl and owner on the unwrapped key. */ + access->setAccess(*unwrappedKey, maker); + + /* Return a keychain item which represents the new key. */ + Item item(keychain->item(recordType(), uniqueId)); + + KCEventNotifier::PostKeychainEvent(kSecAddEvent, keychain, item); + + return item; +} + +Item +KeyItem::importTo(const Keychain &keychain, Access *newAccess, SecKeychainAttributeList *attrList) +{ + if (!(keychain->database()->dl()->subserviceMask() & CSSM_SERVICE_CSP)) + MacOSError::throwMe(errSecInvalidKeychain); + + /* Get the destination keychain's db. */ + SSDbImpl* dbImpl = dynamic_cast(&(*keychain->database())); + if (dbImpl == NULL) + CssmError::throwMe(CSSMERR_CSSM_INVALID_POINTER); + + SSDb ssDb(dbImpl); + + /* Make sure mKey is valid. */ + /* We can't call key() here, since we won't have a unique record id yet */ + if (!mKey) + CssmError::throwMe(CSSMERR_CSSM_INVALID_POINTER); + + // Generate a random label to use initially + CssmClient::CSP appleCsp(gGuidAppleCSP); + CssmClient::Random random(appleCsp, CSSM_ALGID_APPLE_YARROW); + uint8 labelBytes[20]; + CssmData label(labelBytes, sizeof(labelBytes)); + random.generate(label, label.Length); + + /* Set up the ACL for the new key. */ + SecPointer access; + if (newAccess) + access = newAccess; + else + access = new Access(*mKey); + + /* Generate a random 3DES wrapping Key. */ + CssmClient::GenerateKey genKey(csp(), CSSM_ALGID_3DES_3KEY, 192); + CssmClient::Key wrappingKey(genKey(KeySpec(CSSM_KEYUSE_WRAP | CSSM_KEYUSE_UNWRAP, + CSSM_KEYATTR_EXTRACTABLE /* | CSSM_KEYATTR_RETURN_DATA */))); + + /* make a random IV */ + uint8 ivBytes[8]; + CssmData iv(ivBytes, sizeof(ivBytes)); + random.generate(iv, iv.length()); + + /* Extract the key by wrapping it with the wrapping key. */ + CssmClient::WrapKey wrap(csp(), CSSM_ALGID_3DES_3KEY_EDE); + wrap.key(wrappingKey); + wrap.cred(getCredentials(CSSM_ACL_AUTHORIZATION_EXPORT_WRAPPED, kSecCredentialTypeDefault)); + wrap.mode(CSSM_ALGMODE_ECBPad); + wrap.padding(CSSM_PADDING_PKCS7); + wrap.initVector(iv); + CssmClient::Key wrappedKey(wrap(mKey)); + + /* Unwrap the new key into the new Keychain. */ + CssmClient::UnwrapKey unwrap(keychain->csp(), CSSM_ALGID_3DES_3KEY_EDE); + unwrap.key(wrappingKey); + unwrap.mode(CSSM_ALGMODE_ECBPad); + unwrap.padding(CSSM_PADDING_PKCS7); + unwrap.initVector(iv); + + /* Setup the dldbHandle in the context. */ + unwrap.add(CSSM_ATTRIBUTE_DL_DB_HANDLE, ssDb->handle()); + + /* Set up an initial aclEntry so we can change it after the unwrap. */ + Access::Maker maker(Allocator::standard(), Access::Maker::kAnyMakerType); + ResourceControlContext rcc; + maker.initialOwner(rcc, NULL); + unwrap.owner(rcc.input()); + + /* Unwrap the key. */ + uint32 usage = mKey->usage(); + /* Work around csp brokeness where it sets all usage bits in the Keyheader when CSSM_KEYUSE_ANY is set. */ + if (usage & CSSM_KEYUSE_ANY) + usage = CSSM_KEYUSE_ANY; + + CssmClient::Key unwrappedKey(unwrap(wrappedKey, KeySpec(usage, + (mKey->attributes() | CSSM_KEYATTR_PERMANENT) & ~(CSSM_KEYATTR_ALWAYS_SENSITIVE | CSSM_KEYATTR_NEVER_EXTRACTABLE), + label))); + + /* Look up unwrapped key in the DLDB. */ + DbUniqueRecord uniqueId; + SSDbCursor dbCursor(ssDb, 1); + dbCursor->recordType(recordType()); + dbCursor->add(CSSM_DB_EQUAL, kInfoKeyLabel, label); + CssmClient::Key copiedKey; + if (!dbCursor->nextKey(NULL, copiedKey, uniqueId)) + MacOSError::throwMe(errSecItemNotFound); + + // Set the initial label, application label, and application tag (if provided) + if (attrList) { + DbAttributes newDbAttributes; + SSDbCursor otherDbCursor(ssDb, 1); + otherDbCursor->recordType(recordType()); + bool checkForDuplicates = false; + + for (UInt32 index=0; index < attrList->count; index++) { + SecKeychainAttribute attr = attrList->attr[index]; + CssmData attrData(attr.data, attr.length); + if (attr.tag == kSecKeyPrintName) { + newDbAttributes.add(kInfoKeyPrintName, attrData); + } + if (attr.tag == kSecKeyLabel) { + newDbAttributes.add(kInfoKeyLabel, attrData); + otherDbCursor->add(CSSM_DB_EQUAL, kInfoKeyLabel, attrData); + checkForDuplicates = true; + } + if (attr.tag == kSecKeyApplicationTag) { + newDbAttributes.add(kInfoKeyApplicationTag, attrData); + otherDbCursor->add(CSSM_DB_EQUAL, kInfoKeyApplicationTag, attrData); + checkForDuplicates = true; + } + } + + DbAttributes otherDbAttributes; + DbUniqueRecord otherUniqueId; + CssmClient::Key otherKey; + try + { + if (checkForDuplicates && otherDbCursor->nextKey(&otherDbAttributes, otherKey, otherUniqueId)) + MacOSError::throwMe(errSecDuplicateItem); + + uniqueId->modify(recordType(), &newDbAttributes, NULL, CSSM_DB_MODIFY_ATTRIBUTE_REPLACE); + } + catch (CssmError e) + { + // clean up after trying to insert a duplicate key + uniqueId->deleteRecord (); + throw; + } + } + + /* Set the acl and owner on the unwrapped key. */ + access->setAccess(*unwrappedKey, maker); + + /* Return a keychain item which represents the new key. */ + Item item(keychain->item(recordType(), uniqueId)); + + KCEventNotifier::PostKeychainEvent(kSecAddEvent, keychain, item); + + return item; +} + +void +KeyItem::didModify() +{ +} + +PrimaryKey +KeyItem::add(Keychain &keychain) +{ + MacOSError::throwMe(unimpErr); +} + +CssmClient::SSDbUniqueRecord +KeyItem::ssDbUniqueRecord() +{ + DbUniqueRecordImpl *impl = &*dbUniqueRecord(); + Security::CssmClient::SSDbUniqueRecordImpl *simpl = dynamic_cast(impl); + if (simpl == NULL) + { + CssmError::throwMe(CSSMERR_CSSM_INVALID_POINTER); + } + + return CssmClient::SSDbUniqueRecord(simpl); +} + +CssmClient::Key & +KeyItem::key() +{ + if (!mKey) + { + CssmClient::SSDbUniqueRecord uniqueId(ssDbUniqueRecord()); + CssmDataContainer dataBlob(uniqueId->allocator()); + uniqueId->get(NULL, &dataBlob); + mKey = CssmClient::Key(uniqueId->database()->csp(), *reinterpret_cast(dataBlob.Data)); + } + + return mKey; +} + +CssmClient::CSP +KeyItem::csp() +{ + return key()->csp(); +} + + +const CSSM_X509_ALGORITHM_IDENTIFIER& +KeyItem::algorithmIdentifier() +{ +#if 0 + CssmKey *mKey; + CSSM_KEY_TYPE algorithm + CSSM_KEY_PTR cssmKey = (CSSM_KEY_PTR)thisData->Data; +cssmKey->KeyHeader + static void printKeyHeader( + const CSSM_KEYHEADER &hdr) +{ + printf(" Algorithm : "); + switch(hdr.AlgorithmId) { +CSSM_X509_ALGORITHM_IDENTIFIER algID; + +CSSM_OID *CL_algToOid( + CSSM_ALGORITHMS algId) +typedef struct cssm_x509_algorithm_identifier { + CSSM_OID algorithm; + CSSM_DATA parameters; +} CSSM_X509_ALGORITHM_IDENTIFIER, *CSSM_X509_ALGORITHM_IDENTIFIER_PTR; +#endif + + abort(); +} + +/* + * itemID, used to locate Extended Attributes, is the public key hash for keys. + */ +const CssmData &KeyItem::itemID() +{ + if(mPubKeyHash.length() == 0) { + /* + * Fetch the attribute from disk. + */ + UInt32 tag = kSecKeyLabel; + UInt32 format = 0; + SecKeychainAttributeInfo attrInfo = {1, &tag, &format}; + SecKeychainAttributeList *attrList = NULL; + getAttributesAndData(&attrInfo, NULL, &attrList, NULL, NULL); + if((attrList == NULL) || (attrList->count != 1)) { + MacOSError::throwMe(errSecNoSuchAttr); + } + mPubKeyHash.copy(attrList->attr->data, attrList->attr->length); + freeAttributesAndData(attrList, NULL); + } + return mPubKeyHash; +} + + +unsigned int +KeyItem::strengthInBits(const CSSM_X509_ALGORITHM_IDENTIFIER *algid) +{ + // @@@ Make a context with key based on algid and use that to get the effective keysize and not just the logical one. + CSSM_KEY_SIZE keySize = {}; + CSSM_RETURN rv = CSSM_QueryKeySizeInBits (csp()->handle(), + CSSM_INVALID_HANDLE, + key(), + &keySize); + if (rv) + return 0; + + return keySize.LogicalKeySizeInBits; +} + +const AccessCredentials * +KeyItem::getCredentials( + CSSM_ACL_AUTHORIZATION_TAG operation, + SecCredentialType credentialType) +{ + // @@@ Fix this to actually examine the ACL for this key and consider operation and do the right thing. + //AutoAclEntryInfoList aclInfos; + //key()->getAcl(aclInfos); + + bool smartcard = keychain() != NULL ? (keychain()->database()->dl()->guid() == gGuidAppleSdCSPDL) : false; + + AclFactory factory; + switch (credentialType) + { + case kSecCredentialTypeDefault: + return smartcard?globals().smartcardItemCredentials():globals().itemCredentials(); + case kSecCredentialTypeWithUI: + return smartcard?globals().smartcardItemCredentials():factory.promptCred(); + case kSecCredentialTypeNoUI: + return factory.nullCred(); + default: + MacOSError::throwMe(paramErr); + } +} + +bool +KeyItem::operator == (KeyItem &other) +{ + if (mKey && *mKey) + { + // Pointer compare + return this == &other; + } + + // If keychains are different, then keys are different + Keychain otherKeychain = other.keychain(); + return (mKeychain && otherKeychain && (*mKeychain == *otherKeychain)); +} + +void +KeyItem::createPair( + Keychain keychain, + CSSM_ALGORITHMS algorithm, + uint32 keySizeInBits, + CSSM_CC_HANDLE contextHandle, + CSSM_KEYUSE publicKeyUsage, + uint32 publicKeyAttr, + CSSM_KEYUSE privateKeyUsage, + uint32 privateKeyAttr, + SecPointer initialAccess, + SecPointer &outPublicKey, + SecPointer &outPrivateKey) +{ + bool freeKeys = false; + bool deleteContext = false; + + if (!(keychain->database()->dl()->subserviceMask() & CSSM_SERVICE_CSP)) + MacOSError::throwMe(errSecInvalidKeychain); + + SSDbImpl* impl = dynamic_cast(&(*keychain->database())); + if (impl == NULL) + { + CssmError::throwMe(CSSMERR_CSSM_INVALID_POINTER); + } + + SSDb ssDb(impl); + CssmClient::CSP csp(keychain->csp()); + CssmClient::CSP appleCsp(gGuidAppleCSP); + + // Generate a random label to use initially + CssmClient::Random random(appleCsp, CSSM_ALGID_APPLE_YARROW); + uint8 labelBytes[20]; + CssmData label(labelBytes, sizeof(labelBytes)); + random.generate(label, label.Length); + + // Create a Access::Maker for the initial owner of the private key. + ResourceControlContext rcc; + memset(&rcc, 0, sizeof(rcc)); + Access::Maker maker; + // @@@ Potentially provide a credential argument which allows us to generate keys in the csp. Currently the CSP let's anyone do this, but we might restrict this in the future, f.e. a smartcard could require out of band pin entry before a key can be generated. + maker.initialOwner(rcc); + // Create the cred we need to manipulate the keys until we actually set a new access control for them. + const AccessCredentials *cred = maker.cred(); + + CSSM_KEY publicCssmKey, privateCssmKey; + memset(&publicCssmKey, 0, sizeof(publicCssmKey)); + memset(&privateCssmKey, 0, sizeof(privateCssmKey)); + + CSSM_CC_HANDLE ccHandle = 0; + + Item publicKeyItem, privateKeyItem; + try + { + CSSM_RETURN status; + if (contextHandle) + ccHandle = contextHandle; + else + { + status = CSSM_CSP_CreateKeyGenContext(csp->handle(), algorithm, keySizeInBits, NULL, NULL, NULL, NULL, NULL, &ccHandle); + if (status) + CssmError::throwMe(status); + deleteContext = true; + } + + CSSM_DL_DB_HANDLE dldbHandle = ssDb->handle(); + CSSM_DL_DB_HANDLE_PTR dldbHandlePtr = &dldbHandle; + CSSM_CONTEXT_ATTRIBUTE contextAttributes = { CSSM_ATTRIBUTE_DL_DB_HANDLE, sizeof(dldbHandle), { (char *)dldbHandlePtr } }; + status = CSSM_UpdateContextAttributes(ccHandle, 1, &contextAttributes); + if (status) + CssmError::throwMe(status); + + // Generate the keypair + status = CSSM_GenerateKeyPair(ccHandle, publicKeyUsage, publicKeyAttr, &label, &publicCssmKey, privateKeyUsage, privateKeyAttr, &label, &rcc, &privateCssmKey); + if (status) + CssmError::throwMe(status); + freeKeys = true; + + // Find the keys we just generated in the DL to get SecKeyRef's to them + // so we can change the label to be the hash of the public key, and + // fix up other attributes. + + // Look up public key in the DLDB. + DbAttributes pubDbAttributes; + DbUniqueRecord pubUniqueId; + SSDbCursor dbPubCursor(ssDb, 1); + dbPubCursor->recordType(CSSM_DL_DB_RECORD_PUBLIC_KEY); + dbPubCursor->add(CSSM_DB_EQUAL, kInfoKeyLabel, label); + CssmClient::Key publicKey; + if (!dbPubCursor->nextKey(&pubDbAttributes, publicKey, pubUniqueId)) + MacOSError::throwMe(errSecItemNotFound); + + // Look up private key in the DLDB. + DbAttributes privDbAttributes; + DbUniqueRecord privUniqueId; + SSDbCursor dbPrivCursor(ssDb, 1); + dbPrivCursor->recordType(CSSM_DL_DB_RECORD_PRIVATE_KEY); + dbPrivCursor->add(CSSM_DB_EQUAL, kInfoKeyLabel, label); + CssmClient::Key privateKey; + if (!dbPrivCursor->nextKey(&privDbAttributes, privateKey, privUniqueId)) + MacOSError::throwMe(errSecItemNotFound); + + // Convert reference public key to a raw key so we can use it + // in the appleCsp. + CssmClient::WrapKey wrap(csp, CSSM_ALGID_NONE); + wrap.cred(cred); + CssmClient::Key rawPubKey = wrap(publicKey); + + // Calculate the hash of the public key using the appleCSP. + CssmClient::PassThrough passThrough(appleCsp); + void *outData; + CssmData *cssmData; + + /* Given a CSSM_KEY_PTR in any format, obtain the SHA-1 hash of the + * associated key blob. + * Key is specified in CSSM_CSP_CreatePassThroughContext. + * Hash is allocated bythe CSP, in the App's memory, and returned + * in *outData. */ + passThrough.key(rawPubKey); + passThrough(CSSM_APPLECSP_KEYDIGEST, NULL, &outData); + cssmData = reinterpret_cast(outData); + CssmData &pubKeyHash = *cssmData; + + auto_ptrprivDescription; + auto_ptrpubDescription; + try { + privDescription.reset(new string(initialAccess->promptDescription())); + pubDescription.reset(new string(initialAccess->promptDescription())); + } + catch(...) { + /* this path taken if no promptDescription available, e.g., for complex ACLs */ + privDescription.reset(new string("Private key")); + pubDescription.reset(new string("Public key")); + } + + // Set the label of the public key to the public key hash. + // Set the PrintName of the public key to the description in the acl. + pubDbAttributes.add(kInfoKeyLabel, pubKeyHash); + pubDbAttributes.add(kInfoKeyPrintName, *pubDescription); + pubUniqueId->modify(CSSM_DL_DB_RECORD_PUBLIC_KEY, &pubDbAttributes, NULL, CSSM_DB_MODIFY_ATTRIBUTE_REPLACE); + + // Set the label of the private key to the public key hash. + // Set the PrintName of the private key to the description in the acl. + privDbAttributes.add(kInfoKeyLabel, pubKeyHash); + privDbAttributes.add(kInfoKeyPrintName, *privDescription); + privUniqueId->modify(CSSM_DL_DB_RECORD_PRIVATE_KEY, &privDbAttributes, NULL, CSSM_DB_MODIFY_ATTRIBUTE_REPLACE); + + // @@@ Not exception safe! + csp.allocator().free(cssmData->Data); + csp.allocator().free(cssmData); + + // Finally fix the acl and owner of the private key to the specified access control settings. + initialAccess->setAccess(*privateKey, maker); + + if(publicKeyAttr & CSSM_KEYATTR_PUBLIC_KEY_ENCRYPT) { + /* + * Make the public key acl completely open. + * If the key was not encrypted, it already has a wide-open + * ACL (though that is a feature of securityd; it's not + * CDSA-specified behavior). + */ + SecPointer pubKeyAccess(new Access()); + pubKeyAccess->setAccess(*publicKey, maker); + } + + // Create keychain items which will represent the keys. + publicKeyItem = keychain->item(CSSM_DL_DB_RECORD_PUBLIC_KEY, pubUniqueId); + privateKeyItem = keychain->item(CSSM_DL_DB_RECORD_PRIVATE_KEY, privUniqueId); + + KeyItem* impl = dynamic_cast(&(*publicKeyItem)); + if (impl == NULL) + { + CssmError::throwMe(CSSMERR_CSSM_INVALID_POINTER); + } + + outPublicKey = impl; + + impl = dynamic_cast(&(*privateKeyItem)); + if (impl == NULL) + { + CssmError::throwMe(CSSMERR_CSSM_INVALID_POINTER); + } + + outPrivateKey = impl; + } + catch (...) + { + if (freeKeys) + { + // Delete the keys if something goes wrong so we don't end up with inaccessible keys in the database. + CSSM_FreeKey(csp->handle(), cred, &publicCssmKey, TRUE); + CSSM_FreeKey(csp->handle(), cred, &privateCssmKey, TRUE); + } + + if (deleteContext) + CSSM_DeleteContext(ccHandle); + + throw; + } + + if (freeKeys) + { + CSSM_FreeKey(csp->handle(), NULL, &publicCssmKey, FALSE); + CSSM_FreeKey(csp->handle(), NULL, &privateCssmKey, FALSE); + } + + if (deleteContext) + CSSM_DeleteContext(ccHandle); + + if (keychain && publicKeyItem && privateKeyItem) + { + keychain->postEvent(kSecAddEvent, publicKeyItem); + keychain->postEvent(kSecAddEvent, privateKeyItem); + } +} + +void +KeyItem::importPair( + Keychain keychain, + const CSSM_KEY &publicWrappedKey, + const CSSM_KEY &privateWrappedKey, + SecPointer initialAccess, + SecPointer &outPublicKey, + SecPointer &outPrivateKey) +{ + bool freePublicKey = false; + bool freePrivateKey = false; + bool deleteContext = false; + + if (!(keychain->database()->dl()->subserviceMask() & CSSM_SERVICE_CSP)) + MacOSError::throwMe(errSecInvalidKeychain); + + SSDbImpl* impl = dynamic_cast(&(*keychain->database())); + if (impl == NULL) + { + CssmError::throwMe(CSSMERR_CSSM_INVALID_POINTER); + } + + SSDb ssDb(impl); + CssmClient::CSP csp(keychain->csp()); + CssmClient::CSP appleCsp(gGuidAppleCSP); + + // Create a Access::Maker for the initial owner of the private key. + ResourceControlContext rcc; + memset(&rcc, 0, sizeof(rcc)); + Access::Maker maker(Allocator::standard(), Access::Maker::kAnyMakerType); + // @@@ Potentially provide a credential argument which allows us to unwrap keys in the csp. + // Currently the CSP lets anyone do this, but we might restrict this in the future, e.g. + // a smartcard could require out of band pin entry before a key can be generated. + maker.initialOwner(rcc); + // Create the cred we need to manipulate the keys until we actually set a new access control for them. + const AccessCredentials *cred = maker.cred(); + + CSSM_KEY publicCssmKey, privateCssmKey; + memset(&publicCssmKey, 0, sizeof(publicCssmKey)); + memset(&privateCssmKey, 0, sizeof(privateCssmKey)); + + CSSM_CC_HANDLE ccHandle = 0; + + Item publicKeyItem, privateKeyItem; + try + { + CSSM_RETURN status; + + // Calculate the hash of the public key using the appleCSP. + CssmClient::PassThrough passThrough(appleCsp); + void *outData; + CssmData *cssmData; + + /* Given a CSSM_KEY_PTR in any format, obtain the SHA-1 hash of the + * associated key blob. + * Key is specified in CSSM_CSP_CreatePassThroughContext. + * Hash is allocated bythe CSP, in the App's memory, and returned + * in *outData. */ + passThrough.key(&publicWrappedKey); + passThrough(CSSM_APPLECSP_KEYDIGEST, NULL, &outData); + cssmData = reinterpret_cast(outData); + CssmData &pubKeyHash = *cssmData; + + status = CSSM_CSP_CreateSymmetricContext(csp->handle(), publicWrappedKey.KeyHeader.WrapAlgorithmId, CSSM_ALGMODE_NONE, NULL, NULL, NULL, CSSM_PADDING_NONE, NULL, &ccHandle); + if (status) + CssmError::throwMe(status); + deleteContext = true; + + CSSM_DL_DB_HANDLE dldbHandle = ssDb->handle(); + CSSM_DL_DB_HANDLE_PTR dldbHandlePtr = &dldbHandle; + CSSM_CONTEXT_ATTRIBUTE contextAttributes = { CSSM_ATTRIBUTE_DL_DB_HANDLE, sizeof(dldbHandle), { (char *)dldbHandlePtr } }; + status = CSSM_UpdateContextAttributes(ccHandle, 1, &contextAttributes); + if (status) + CssmError::throwMe(status); + + // Unwrap the the keys + CSSM_DATA descriptiveData = {0, NULL}; + + status = CSSM_UnwrapKey( + ccHandle, + NULL, + &publicWrappedKey, + publicWrappedKey.KeyHeader.KeyUsage, + publicWrappedKey.KeyHeader.KeyAttr | CSSM_KEYATTR_PERMANENT, + &pubKeyHash, + &rcc, + &publicCssmKey, + &descriptiveData); + + if (status) + CssmError::throwMe(status); + freePublicKey = true; + + if (descriptiveData.Data != NULL) + free (descriptiveData.Data); + + status = CSSM_UnwrapKey( + ccHandle, + NULL, + &privateWrappedKey, + privateWrappedKey.KeyHeader.KeyUsage, + privateWrappedKey.KeyHeader.KeyAttr | CSSM_KEYATTR_PERMANENT, + &pubKeyHash, + &rcc, + &privateCssmKey, + &descriptiveData); + + if (status) + CssmError::throwMe(status); + + if (descriptiveData.Data != NULL) + free (descriptiveData.Data); + + freePrivateKey = true; + + // Find the keys we just generated in the DL to get SecKeyRefs to them + // so we can change the label to be the hash of the public key, and + // fix up other attributes. + + // Look up public key in the DLDB. + DbAttributes pubDbAttributes; + DbUniqueRecord pubUniqueId; + SSDbCursor dbPubCursor(ssDb, 1); + dbPubCursor->recordType(CSSM_DL_DB_RECORD_PUBLIC_KEY); + dbPubCursor->add(CSSM_DB_EQUAL, kInfoKeyLabel, pubKeyHash); + CssmClient::Key publicKey; + if (!dbPubCursor->nextKey(&pubDbAttributes, publicKey, pubUniqueId)) + MacOSError::throwMe(errSecItemNotFound); + + // Look up private key in the DLDB. + DbAttributes privDbAttributes; + DbUniqueRecord privUniqueId; + SSDbCursor dbPrivCursor(ssDb, 1); + dbPrivCursor->recordType(CSSM_DL_DB_RECORD_PRIVATE_KEY); + dbPrivCursor->add(CSSM_DB_EQUAL, kInfoKeyLabel, pubKeyHash); + CssmClient::Key privateKey; + if (!dbPrivCursor->nextKey(&privDbAttributes, privateKey, privUniqueId)) + MacOSError::throwMe(errSecItemNotFound); + + // @@@ Not exception safe! + csp.allocator().free(cssmData->Data); + csp.allocator().free(cssmData); + + auto_ptrprivDescription; + auto_ptrpubDescription; + try { + privDescription.reset(new string(initialAccess->promptDescription())); + pubDescription.reset(new string(initialAccess->promptDescription())); + } + catch(...) { + /* this path taken if no promptDescription available, e.g., for complex ACLs */ + privDescription.reset(new string("Private key")); + pubDescription.reset(new string("Public key")); + } + + // Set the label of the public key to the public key hash. + // Set the PrintName of the public key to the description in the acl. + pubDbAttributes.add(kInfoKeyPrintName, *pubDescription); + pubUniqueId->modify(CSSM_DL_DB_RECORD_PUBLIC_KEY, &pubDbAttributes, NULL, CSSM_DB_MODIFY_ATTRIBUTE_REPLACE); + + // Set the label of the private key to the public key hash. + // Set the PrintName of the private key to the description in the acl. + privDbAttributes.add(kInfoKeyPrintName, *privDescription); + privUniqueId->modify(CSSM_DL_DB_RECORD_PRIVATE_KEY, &privDbAttributes, NULL, CSSM_DB_MODIFY_ATTRIBUTE_REPLACE); + + // Finally fix the acl and owner of the private key to the specified access control settings. + initialAccess->setAccess(*privateKey, maker); + + // Make the public key acl completely open + SecPointer pubKeyAccess(new Access()); + pubKeyAccess->setAccess(*publicKey, maker); + + // Create keychain items which will represent the keys. + publicKeyItem = keychain->item(CSSM_DL_DB_RECORD_PUBLIC_KEY, pubUniqueId); + privateKeyItem = keychain->item(CSSM_DL_DB_RECORD_PRIVATE_KEY, privUniqueId); + + KeyItem* impl = dynamic_cast(&(*publicKeyItem)); + if (impl == NULL) + { + CssmError::throwMe(CSSMERR_CSSM_INVALID_POINTER); + } + + outPublicKey = impl; + + impl = dynamic_cast(&(*privateKeyItem)); + if (impl == NULL) + { + CssmError::throwMe(CSSMERR_CSSM_INVALID_POINTER); + } + outPrivateKey = impl; + } + catch (...) + { + if (freePublicKey) + CSSM_FreeKey(csp->handle(), cred, &publicCssmKey, TRUE); + if (freePrivateKey) + CSSM_FreeKey(csp->handle(), cred, &privateCssmKey, TRUE); + + if (deleteContext) + CSSM_DeleteContext(ccHandle); + + throw; + } + + if (freePublicKey) + CSSM_FreeKey(csp->handle(), cred, &publicCssmKey, FALSE); + if (freePrivateKey) + CSSM_FreeKey(csp->handle(), cred, &privateCssmKey, FALSE); + + if (deleteContext) + CSSM_DeleteContext(ccHandle); + + if (keychain && publicKeyItem && privateKeyItem) + { + KCEventNotifier::PostKeychainEvent(kSecAddEvent, keychain, publicKeyItem); + KCEventNotifier::PostKeychainEvent(kSecAddEvent, keychain, privateKeyItem); + } +} + +SecPointer +KeyItem::generateWithAttributes(const SecKeychainAttributeList *attrList, + Keychain keychain, + CSSM_ALGORITHMS algorithm, + uint32 keySizeInBits, + CSSM_CC_HANDLE contextHandle, + CSSM_KEYUSE keyUsage, + uint32 keyAttr, + SecPointer initialAccess) +{ + CssmClient::CSP appleCsp(gGuidAppleCSP); + CssmClient::CSP csp(NULL); + SSDb ssDb(NULL); + uint8 labelBytes[20]; + CssmData label(labelBytes, sizeof(labelBytes)); + bool freeKey = false; + bool deleteContext = false; + const CSSM_DATA *plabel = NULL; + + if (keychain) + { + if (!(keychain->database()->dl()->subserviceMask() & CSSM_SERVICE_CSP)) + MacOSError::throwMe(errSecInvalidKeychain); + + SSDbImpl* impl = dynamic_cast(&(*keychain->database())); + if (impl == NULL) + { + CssmError::throwMe(CSSMERR_CSSM_INVALID_POINTER); + } + + ssDb = SSDb(impl); + csp = keychain->csp(); + + // Generate a random label to use initially + CssmClient::Random random(appleCsp, CSSM_ALGID_APPLE_YARROW); + random.generate(label, label.Length); + plabel = &label; + } + else + { + // Not a persistent key so create it in the regular csp + csp = appleCsp; + } + + // Create a Access::Maker for the initial owner of the private key. + ResourceControlContext *prcc = NULL, rcc; + const AccessCredentials *cred = NULL; + Access::Maker maker; + if (keychain && initialAccess) + { + memset(&rcc, 0, sizeof(rcc)); + // @@@ Potentially provide a credential argument which allows us to generate keys in the csp. + // Currently the CSP lets anyone do this, but we might restrict this in the future, e.g. a smartcard + // could require out-of-band pin entry before a key can be generated. + maker.initialOwner(rcc); + // Create the cred we need to manipulate the keys until we actually set a new access control for them. + cred = maker.cred(); + prcc = &rcc; + } + + CSSM_KEY cssmKey; + + CSSM_CC_HANDLE ccHandle = 0; + + Item keyItem; + try + { + CSSM_RETURN status; + if (contextHandle) + ccHandle = contextHandle; + else + { + status = CSSM_CSP_CreateKeyGenContext(csp->handle(), algorithm, keySizeInBits, NULL, NULL, NULL, NULL, NULL, &ccHandle); + if (status) + CssmError::throwMe(status); + deleteContext = true; + } + + if (ssDb) + { + CSSM_DL_DB_HANDLE dldbHandle = ssDb->handle(); + CSSM_DL_DB_HANDLE_PTR dldbHandlePtr = &dldbHandle; + CSSM_CONTEXT_ATTRIBUTE contextAttributes = { CSSM_ATTRIBUTE_DL_DB_HANDLE, sizeof(dldbHandle), { (char *)dldbHandlePtr } }; + status = CSSM_UpdateContextAttributes(ccHandle, 1, &contextAttributes); + if (status) + CssmError::throwMe(status); + + keyAttr |= CSSM_KEYATTR_PERMANENT; + } + + // Generate the key + status = CSSM_GenerateKey(ccHandle, keyUsage, keyAttr, plabel, prcc, &cssmKey); + if (status) + CssmError::throwMe(status); + + if (ssDb) + { + freeKey = true; + // Find the key we just generated in the DL and get a SecKeyRef + // so we can specify the label attribute(s) and initial ACL. + + // Look up key in the DLDB. + DbAttributes dbAttributes; + DbUniqueRecord uniqueId; + SSDbCursor dbCursor(ssDb, 1); + dbCursor->recordType(CSSM_DL_DB_RECORD_SYMMETRIC_KEY); + dbCursor->add(CSSM_DB_EQUAL, kInfoKeyLabel, label); + CssmClient::Key key; + if (!dbCursor->nextKey(&dbAttributes, key, uniqueId)) + MacOSError::throwMe(errSecItemNotFound); + + // Set the initial label, application label, and application tag (if provided) + if (attrList) { + DbAttributes newDbAttributes; + SSDbCursor otherDbCursor(ssDb, 1); + otherDbCursor->recordType(CSSM_DL_DB_RECORD_SYMMETRIC_KEY); + bool checkForDuplicates = false; + + for (UInt32 index=0; index < attrList->count; index++) { + SecKeychainAttribute attr = attrList->attr[index]; + CssmData attrData(attr.data, attr.length); + if (attr.tag == kSecKeyPrintName) { + newDbAttributes.add(kInfoKeyPrintName, attrData); + } + if (attr.tag == kSecKeyLabel) { + newDbAttributes.add(kInfoKeyLabel, attrData); + otherDbCursor->add(CSSM_DB_EQUAL, kInfoKeyLabel, attrData); + checkForDuplicates = true; + } + if (attr.tag == kSecKeyApplicationTag) { + newDbAttributes.add(kInfoKeyApplicationTag, attrData); + otherDbCursor->add(CSSM_DB_EQUAL, kInfoKeyApplicationTag, attrData); + checkForDuplicates = true; + } + } + + DbAttributes otherDbAttributes; + DbUniqueRecord otherUniqueId; + CssmClient::Key otherKey; + if (checkForDuplicates && otherDbCursor->nextKey(&otherDbAttributes, otherKey, otherUniqueId)) + MacOSError::throwMe(errSecDuplicateItem); + + uniqueId->modify(CSSM_DL_DB_RECORD_SYMMETRIC_KEY, &newDbAttributes, NULL, CSSM_DB_MODIFY_ATTRIBUTE_REPLACE); + } + + // Finally, fix the acl and owner of the key to the specified access control settings. + if (initialAccess) + initialAccess->setAccess(*key, maker); + + // Create keychain item which will represent the key. + keyItem = keychain->item(CSSM_DL_DB_RECORD_SYMMETRIC_KEY, uniqueId); + } + else + { + CssmClient::Key tempKey(csp, cssmKey); + keyItem = new KeyItem(tempKey); + } + } + catch (...) + { + if (freeKey) + { + // Delete the key if something goes wrong so we don't end up with inaccessible keys in the database. + CSSM_FreeKey(csp->handle(), cred, &cssmKey, TRUE); + } + + if (deleteContext) + CSSM_DeleteContext(ccHandle); + + throw; + } + + if (freeKey) + { + CSSM_FreeKey(csp->handle(), NULL, &cssmKey, FALSE); + } + + if (deleteContext) + CSSM_DeleteContext(ccHandle); + + if (keychain && keyItem) + keychain->postEvent(kSecAddEvent, keyItem); + + KeyItem* item = dynamic_cast(&*keyItem); + if (item == NULL) + { + CssmError::throwMe(CSSMERR_CSSM_INVALID_POINTER); + } + + return item; +} + +SecPointer +KeyItem::generate(Keychain keychain, + CSSM_ALGORITHMS algorithm, + uint32 keySizeInBits, + CSSM_CC_HANDLE contextHandle, + CSSM_KEYUSE keyUsage, + uint32 keyAttr, + SecPointer initialAccess) +{ + return KeyItem::generateWithAttributes(NULL, keychain, + algorithm, keySizeInBits, contextHandle, + keyUsage, keyAttr, initialAccess); +} + + +void KeyItem::RawSign(SecPadding padding, CSSM_DATA dataToSign, const AccessCredentials *credentials, CSSM_DATA& signature) +{ + CSSM_ALGORITHMS baseAlg = key()->header().algorithm(); + if (baseAlg != CSSM_ALGID_RSA) + { + MacOSError::throwMe(paramErr); + } + + CSSM_ALGORITHMS paddingAlg = CSSM_PADDING_PKCS1; + + switch (padding) + { + case kSecPaddingPKCS1: + { + paddingAlg = CSSM_PADDING_PKCS1; + break; + } + + case kSecPaddingPKCS1MD2: + { + baseAlg = CSSM_ALGID_MD2WithRSA; + break; + } + + case kSecPaddingPKCS1MD5: + { + baseAlg = CSSM_ALGID_MD5WithRSA; + break; + } + + case kSecPaddingPKCS1SHA1: + { + baseAlg = CSSM_ALGID_SHA1WithRSA; + break; + } + + default: + { + paddingAlg = CSSM_PADDING_NONE; + break; + } + } + + Sign signContext(csp(), baseAlg); + signContext.key(key()); + signContext.set(CSSM_ATTRIBUTE_PADDING, paddingAlg); + signContext.cred(credentials); + + CssmData data(dataToSign.Data, dataToSign.Length); + signContext.sign(data); + + CssmData sig(signature.Data, signature.Length); + signContext(sig); // yes, this is an accessor. Believe it, or not. + signature.Length = sig.length(); +} + + + +void KeyItem::RawVerify(SecPadding padding, CSSM_DATA dataToVerify, const AccessCredentials *credentials, CSSM_DATA sig) +{ + CSSM_ALGORITHMS baseAlg = key()->header().algorithm(); + if (baseAlg != CSSM_ALGID_RSA) + { + MacOSError::throwMe(paramErr); + } + + CSSM_ALGORITHMS paddingAlg = CSSM_PADDING_PKCS1; + + switch (padding) + { + case kSecPaddingPKCS1: + { + paddingAlg = CSSM_PADDING_PKCS1; + break; + } + + case kSecPaddingPKCS1MD2: + { + baseAlg = CSSM_ALGID_MD2WithRSA; + break; + } + + case kSecPaddingPKCS1MD5: + { + baseAlg = CSSM_ALGID_MD5WithRSA; + break; + } + + case kSecPaddingPKCS1SHA1: + { + baseAlg = CSSM_ALGID_SHA1WithRSA; + break; + } + + default: + { + paddingAlg = CSSM_PADDING_NONE; + break; + } + } + + Verify verifyContext(csp(), baseAlg); + verifyContext.key(key()); + verifyContext.set(CSSM_ATTRIBUTE_PADDING, paddingAlg); + verifyContext.cred(credentials); + + CssmData data(dataToVerify.Data, dataToVerify.Length); + CssmData signature(sig.Data, sig.Length); + verifyContext.verify(data, signature); +} + + + +void KeyItem::Encrypt(SecPadding padding, CSSM_DATA dataToEncrypt, const AccessCredentials *credentials, CSSM_DATA& encryptedData) +{ + CSSM_ALGORITHMS baseAlg = key()->header().algorithm(); + if (baseAlg != CSSM_ALGID_RSA) + { + MacOSError::throwMe(paramErr); + } + + CSSM_ALGORITHMS paddingAlg = CSSM_PADDING_PKCS1; + + switch (padding) + { + case kSecPaddingPKCS1: + { + paddingAlg = CSSM_PADDING_PKCS1; + break; + } + + default: + { + paddingAlg = CSSM_PADDING_NONE; + break; + } + } + + CssmClient::Encrypt encryptContext(csp(), baseAlg); + encryptContext.key(key()); + encryptContext.padding(paddingAlg); + encryptContext.cred(credentials); + + CssmData inData(dataToEncrypt.Data, dataToEncrypt.Length); + CssmData outData(encryptedData.Data, encryptedData.Length); + CssmData remData((void*) NULL, 0); + + encryptedData.Length = encryptContext.encrypt(inData, outData, remData); +} + + + +void KeyItem::Decrypt(SecPadding padding, CSSM_DATA dataToDecrypt, const AccessCredentials *credentials, CSSM_DATA& decryptedData) +{ + CSSM_ALGORITHMS baseAlg = key()->header().algorithm(); + if (baseAlg != CSSM_ALGID_RSA) + { + MacOSError::throwMe(paramErr); + } + + CSSM_ALGORITHMS paddingAlg = CSSM_PADDING_PKCS1; + + switch (padding) + { + case kSecPaddingPKCS1: + { + paddingAlg = CSSM_PADDING_PKCS1; + break; + } + + + default: + { + paddingAlg = CSSM_PADDING_NONE; + break; + } + } + + CssmClient::Decrypt decryptContext(csp(), baseAlg); + decryptContext.key(key()); + decryptContext.padding(paddingAlg); + decryptContext.cred(credentials); + + CssmData inData(dataToDecrypt.Data, dataToDecrypt.Length); + CssmData outData(decryptedData.Data, decryptedData.Length); + CssmData remData((void*) NULL, 0); + decryptedData.Length = decryptContext.decrypt(inData, outData, remData); + if (remData.Data != NULL) + { + free(remData.Data); + } +} + diff --git a/libsecurity_keychain/lib/KeyItem.h b/libsecurity_keychain/lib/KeyItem.h new file mode 100644 index 00000000..8e5e0521 --- /dev/null +++ b/libsecurity_keychain/lib/KeyItem.h @@ -0,0 +1,139 @@ +/* + * 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@ + */ + +// +// KeyItem.h +// +#ifndef _SECURITY_KEYITEM_H_ +#define _SECURITY_KEYITEM_H_ + +#include +#include + +namespace Security +{ + +namespace KeychainCore +{ + +class KeyItem : public ItemImpl +{ + NOCOPY(KeyItem) +public: + SECCFFUNCTIONS(KeyItem, SecKeyRef, errSecInvalidItemRef, gTypes().KeyItem) + + // db item constructor +private: + KeyItem(const Keychain &keychain, const PrimaryKey &primaryKey, const CssmClient::DbUniqueRecord &uniqueId); + + // PrimaryKey item constructor + KeyItem(const Keychain &keychain, const PrimaryKey &primaryKey); + +public: + static KeyItem* make(const Keychain &keychain, const PrimaryKey &primaryKey, const CssmClient::DbUniqueRecord &uniqueId); + static KeyItem* make(const Keychain &keychain, const PrimaryKey &primaryKey); + + KeyItem(KeyItem &keyItem); + + KeyItem(const CssmClient::Key &key); + + virtual ~KeyItem() throw(); + + virtual void update(); + virtual Item copyTo(const Keychain &keychain, Access *newAccess = NULL); + virtual Item importTo(const Keychain &keychain, Access *newAccess = NULL, SecKeychainAttributeList *attrList = NULL); + virtual void didModify(); + + CssmClient::SSDbUniqueRecord ssDbUniqueRecord(); + CssmClient::Key &key(); + CssmClient::CSP csp(); + + const CSSM_X509_ALGORITHM_IDENTIFIER& algorithmIdentifier(); + unsigned int strengthInBits(const CSSM_X509_ALGORITHM_IDENTIFIER *algid); + + const AccessCredentials *getCredentials( + CSSM_ACL_AUTHORIZATION_TAG operation, + SecCredentialType credentialType); + + bool operator == (KeyItem &other); + + static void createPair( + Keychain keychain, + CSSM_ALGORITHMS algorithm, + uint32 keySizeInBits, + CSSM_CC_HANDLE contextHandle, + CSSM_KEYUSE publicKeyUsage, + uint32 publicKeyAttr, + CSSM_KEYUSE privateKeyUsage, + uint32 privateKeyAttr, + SecPointer initialAccess, + SecPointer &outPublicKey, + SecPointer &outPrivateKey); + + static void importPair( + Keychain keychain, + const CSSM_KEY &publicCssmKey, + const CSSM_KEY &privateCssmKey, + SecPointer initialAccess, + SecPointer &outPublicKey, + SecPointer &outPrivateKey); + + static SecPointer generate( + Keychain keychain, + CSSM_ALGORITHMS algorithm, + uint32 keySizeInBits, + CSSM_CC_HANDLE contextHandle, + CSSM_KEYUSE keyUsage, + uint32 keyAttr, + SecPointer initialAccess); + + static SecPointer generateWithAttributes( + const SecKeychainAttributeList *attrList, + Keychain keychain, + CSSM_ALGORITHMS algorithm, + uint32 keySizeInBits, + CSSM_CC_HANDLE contextHandle, + CSSM_KEYUSE keyUsage, + uint32 keyAttr, + SecPointer initialAccess); + + virtual const CssmData &itemID(); + + void RawSign(SecPadding padding, CSSM_DATA dataToSign, const AccessCredentials *credentials, CSSM_DATA& signedData); + void RawVerify(SecPadding padding, CSSM_DATA dataToVerify, const AccessCredentials *credentials, CSSM_DATA signature); + void Encrypt(SecPadding padding, CSSM_DATA dataToEncrypt, const AccessCredentials *credentials, CSSM_DATA& encryptedData); + void Decrypt(SecPadding padding, CSSM_DATA dataToEncrypt, const AccessCredentials *credentials, CSSM_DATA& encryptedData); + +protected: + virtual PrimaryKey add(Keychain &keychain); +private: + CssmClient::Key mKey; + const CSSM_X509_ALGORITHM_IDENTIFIER *algid; + CssmAutoData mPubKeyHash; +}; + +} // end namespace KeychainCore + +} // end namespace Security + +#endif // !_SECURITY_KEYITEM_H_ diff --git a/libsecurity_keychain/lib/Keychains.cpp b/libsecurity_keychain/lib/Keychains.cpp new file mode 100644 index 00000000..d6fa704b --- /dev/null +++ b/libsecurity_keychain/lib/Keychains.cpp @@ -0,0 +1,1372 @@ +/* + * 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@ + */ + + +// +// Keychains.cpp +// + +#include "KCEventNotifier.h" +#include "Keychains.h" + +#include "Item.h" +#include "KCCursor.h" +#include "Globals.h" +#include +#include +#include +#include +#include +#include +#include + +#include "SecKeychainPriv.h" + +#include +#include +#include "DLDbListCFPref.h" +#include +#include +#include +#include +#include +#include +#include +#include + +static dispatch_once_t SecKeychainSystemKeychainChecked; + +OSStatus SecKeychainSystemKeychainCheckWouldDeadlock() +{ + dispatch_once(&SecKeychainSystemKeychainChecked, ^{}); + return noErr; +} + +using namespace KeychainCore; +using namespace CssmClient; + + +typedef struct EventItem +{ + SecKeychainEvent kcEvent; + Item item; +} EventItem; + +typedef std::list EventBufferSuper; +class EventBuffer : public EventBufferSuper +{ +public: + EventBuffer () {} + virtual ~EventBuffer (); +}; + + +EventBuffer::~EventBuffer () +{ +} + + + +// +// KeychainSchemaImpl +// +KeychainSchemaImpl::KeychainSchemaImpl(const Db &db) : mMutex(Mutex::recursive) +{ + DbCursor relations(db); + relations->recordType(CSSM_DL_DB_SCHEMA_INFO); + DbAttributes relationRecord(db, 1); + relationRecord.add(Schema::RelationID); + DbUniqueRecord outerUniqueId(db); + + while (relations->next(&relationRecord, NULL, outerUniqueId)) + { + DbUniqueRecord uniqueId(db); + + uint32 relationID = relationRecord.at(0); + if (CSSM_DB_RECORDTYPE_SCHEMA_START <= relationID + && relationID < CSSM_DB_RECORDTYPE_SCHEMA_END) + continue; + + // 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, Schema::RelationID, relationID); + + // Set up a record for retriving the SCHEMA_ATTRIBUTES + DbAttributes attributeRecord(db, 2); + attributeRecord.add(Schema::AttributeFormat); + attributeRecord.add(Schema::AttributeID); + + RelationInfoMap &rim = mDatabaseInfoMap[relationID]; + while (attributes->next(&attributeRecord, NULL, uniqueId)) + rim[attributeRecord.at(1)] = attributeRecord.at(0); + + // Create a cursor on the CSSM_DL_DB_SCHEMA_INDEXES table for records + // with RelationID == relationID + DbCursor indexes(db); + indexes->recordType(CSSM_DL_DB_SCHEMA_INDEXES); + indexes->conjunctive(CSSM_DB_AND); + indexes->add(CSSM_DB_EQUAL, Schema::RelationID, relationID); + indexes->add(CSSM_DB_EQUAL, Schema::IndexType, + uint32(CSSM_DB_INDEX_UNIQUE)); + + // Set up a record for retriving the SCHEMA_INDEXES + DbAttributes indexRecord(db, 1); + indexRecord.add(Schema::AttributeID); + + CssmAutoDbRecordAttributeInfo &infos = + *new CssmAutoDbRecordAttributeInfo(); + mPrimaryKeyInfoMap. + insert(PrimaryKeyInfoMap::value_type(relationID, &infos)); + infos.DataRecordType = relationID; + while (indexes->next(&indexRecord, NULL, uniqueId)) + { + CssmDbAttributeInfo &info = infos.add(); + info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER; + info.Label.AttributeID = indexRecord.at(0); + // @@@ Might insert bogus value if DB is corrupt + info.AttributeFormat = rim[info.Label.AttributeID]; + } + } +} + +KeychainSchemaImpl::~KeychainSchemaImpl() +{ + try + { + for_each_map_delete(mPrimaryKeyInfoMap.begin(), mPrimaryKeyInfoMap.end()); + } + catch(...) + { + } +} + +const KeychainSchemaImpl::RelationInfoMap & +KeychainSchemaImpl::relationInfoMapFor(CSSM_DB_RECORDTYPE recordType) const +{ + DatabaseInfoMap::const_iterator dit = mDatabaseInfoMap.find(recordType); + if (dit == mDatabaseInfoMap.end()) + MacOSError::throwMe(errSecNoSuchClass); + return dit->second; +} + +bool KeychainSchemaImpl::hasRecordType (CSSM_DB_RECORDTYPE recordType) const +{ + DatabaseInfoMap::const_iterator it = mDatabaseInfoMap.find(recordType); + return it != mDatabaseInfoMap.end(); +} + +bool +KeychainSchemaImpl::hasAttribute(CSSM_DB_RECORDTYPE recordType, uint32 attributeId) const +{ + try + { + const RelationInfoMap &rmap = relationInfoMapFor(recordType); + RelationInfoMap::const_iterator rit = rmap.find(attributeId); + return rit != rmap.end(); + } + catch (MacOSError result) + { + if (result.osStatus () == errSecNoSuchClass) + { + return false; + } + else + { + throw; + } + } +} + +CSSM_DB_ATTRIBUTE_FORMAT +KeychainSchemaImpl::attributeFormatFor(CSSM_DB_RECORDTYPE recordType, uint32 attributeId) const +{ + const RelationInfoMap &rmap = relationInfoMapFor(recordType); + RelationInfoMap::const_iterator rit = rmap.find(attributeId); + if (rit == rmap.end()) + MacOSError::throwMe(errSecNoSuchAttr); + + return rit->second; +} + +CssmDbAttributeInfo +KeychainSchemaImpl::attributeInfoFor(CSSM_DB_RECORDTYPE recordType, uint32 attributeId) const +{ + CSSM_DB_ATTRIBUTE_INFO info; + info.AttributeFormat = attributeFormatFor(recordType, attributeId); + info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER; + info.Label.AttributeID = attributeId; + + return info; +} + +void +KeychainSchemaImpl::getAttributeInfoForRecordType(CSSM_DB_RECORDTYPE recordType, SecKeychainAttributeInfo **Info) const +{ + const RelationInfoMap &rmap = relationInfoMapFor(recordType); + + SecKeychainAttributeInfo *theList=reinterpret_cast(malloc(sizeof(SecKeychainAttributeInfo))); + + UInt32 capacity=rmap.size(); + UInt32 *tagBuf=reinterpret_cast(malloc(capacity*sizeof(UInt32))); + UInt32 *formatBuf=reinterpret_cast(malloc(capacity*sizeof(UInt32))); + UInt32 i=0; + + + for (RelationInfoMap::const_iterator rit = rmap.begin(); rit != rmap.end(); ++rit) + { + if (i>=capacity) + { + capacity *= 2; + if (capacity <= i) capacity = i + 1; + tagBuf=reinterpret_cast(realloc(tagBuf, (capacity*sizeof(UInt32)))); + formatBuf=reinterpret_cast(realloc(tagBuf, (capacity*sizeof(UInt32)))); + } + tagBuf[i]=rit->first; + formatBuf[i++]=rit->second; + } + + theList->count=i; + theList->tag=tagBuf; + theList->format=formatBuf; + *Info=theList; +} + + +const CssmAutoDbRecordAttributeInfo & +KeychainSchemaImpl::primaryKeyInfosFor(CSSM_DB_RECORDTYPE recordType) const +{ + PrimaryKeyInfoMap::const_iterator it; + it = mPrimaryKeyInfoMap.find(recordType); + + if (it == mPrimaryKeyInfoMap.end()) + MacOSError::throwMe(errSecNoSuchClass); // @@@ Not really but whatever. + + return *it->second; +} + +bool +KeychainSchemaImpl::operator <(const KeychainSchemaImpl &other) const +{ + return mDatabaseInfoMap < other.mDatabaseInfoMap; +} + +bool +KeychainSchemaImpl::operator ==(const KeychainSchemaImpl &other) const +{ + return mDatabaseInfoMap == other.mDatabaseInfoMap; +} + +void +KeychainSchemaImpl::didCreateRelation(CSSM_DB_RECORDTYPE relationID, + const char *inRelationName, + uint32 inNumberOfAttributes, + const CSSM_DB_SCHEMA_ATTRIBUTE_INFO *pAttributeInfo, + uint32 inNumberOfIndexes, + const CSSM_DB_SCHEMA_INDEX_INFO *pIndexInfo) +{ + StLock_(mMutex); + + if (CSSM_DB_RECORDTYPE_SCHEMA_START <= relationID + && relationID < CSSM_DB_RECORDTYPE_SCHEMA_END) + return; + + RelationInfoMap &rim = mDatabaseInfoMap[relationID]; + for (uint32 ix = 0; ix < inNumberOfAttributes; ++ix) + rim[pAttributeInfo[ix].AttributeId] = pAttributeInfo[ix].DataType; + + CssmAutoDbRecordAttributeInfo &infos = + *new CssmAutoDbRecordAttributeInfo(); + mPrimaryKeyInfoMap. + insert(PrimaryKeyInfoMap::value_type(relationID, &infos)); + infos.DataRecordType = relationID; + for (uint32 ix = 0; ix < inNumberOfIndexes; ++ix) + if (pIndexInfo[ix].IndexType == CSSM_DB_INDEX_UNIQUE) + { + CssmDbAttributeInfo &info = infos.add(); + info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER; + info.Label.AttributeID = pIndexInfo[ix].AttributeId; + info.AttributeFormat = rim[info.Label.AttributeID]; + } +} + + +struct Event +{ + SecKeychainEvent eventCode; + PrimaryKey primaryKey; +}; +typedef std::list EventList; + +#define SYSTEM_KEYCHAIN_CHECK_UNIX_BASE_NAME "/var/run/systemkeychaincheck" +#define SYSTEM_KEYCHAIN_CHECK_UNIX_DOMAIN_SOCKET_NAME (SYSTEM_KEYCHAIN_CHECK_UNIX_BASE_NAME ".socket") +#define SYSTEM_KEYCHAIN_CHECK_COMPLETE_FILE_NAME (SYSTEM_KEYCHAIN_CHECK_UNIX_BASE_NAME ".done") + +static void check_system_keychain() +{ + // sadly we can't use XPC here, XPC_DOMAIN_TYPE_SYSTEM doesn't exist yet. Also xpc-helper uses the + // keychain API (I assume for checking codesign things). So we use Unix Domain Sockets. + + // NOTE: if we hit a system error we attempt to log it, and then just don't check the system keychain. + // In theory a system might be able to recover from this state if we let it try to muddle along, and + // past behaviour didn't even try this hard to do the keychain check. In particular we could be in a + // sandbox'ed process. So we just do our best and let another process try again. + + struct stat keycheck_file_info; + if (stat(SYSTEM_KEYCHAIN_CHECK_COMPLETE_FILE_NAME, &keycheck_file_info) < 0) { + int server_fd = socket(PF_UNIX, SOCK_STREAM, 0); + if (server_fd < 0) { + syslog(LOG_ERR, "Can't get socket (%m) system keychain may be unchecked"); + return; + } + + struct sockaddr_un keychain_check_server_address; + keychain_check_server_address.sun_family = AF_UNIX; + if (strlcpy(keychain_check_server_address.sun_path, SYSTEM_KEYCHAIN_CHECK_UNIX_DOMAIN_SOCKET_NAME, sizeof(keychain_check_server_address.sun_path)) > sizeof(keychain_check_server_address.sun_path)) { + // It would be nice if we could compile time assert this + syslog(LOG_ERR, "Socket path too long, max length %d, your length %d", sizeof(keychain_check_server_address.sun_path), strlen(SYSTEM_KEYCHAIN_CHECK_UNIX_DOMAIN_SOCKET_NAME)); + close(server_fd); + return; + } + keychain_check_server_address.sun_len = SUN_LEN(&keychain_check_server_address); + + int rc = connect(server_fd, (struct sockaddr *)&keychain_check_server_address, keychain_check_server_address.sun_len); + if (rc < 0) { + syslog(LOG_ERR, "Can not connect to %s: %m", SYSTEM_KEYCHAIN_CHECK_UNIX_DOMAIN_SOCKET_NAME); + close(server_fd); + return; + } + + // this read lets us block until the EOF comes, we don't ever get a byte (and if we do, we don't care about it) + char byte; + ssize_t read_size = read(server_fd, &byte, 1); + if (read_size < 0) { + syslog(LOG_ERR, "Error reading from system keychain checker: %m"); + } + + close(server_fd); + return; + } +} + +// +// KeychainImpl +// +KeychainImpl::KeychainImpl(const Db &db) + : mInCache(false), mDb(db), mCustomUnlockCreds (this), mIsInBatchMode (false), mMutex(Mutex::recursive) +{ + dispatch_once(&SecKeychainSystemKeychainChecked, ^{ + check_system_keychain(); + }); + mDb->defaultCredentials(this); // install activation hook + mEventBuffer = new EventBuffer; +} + +KeychainImpl::~KeychainImpl() +{ + try + { + // Remove ourselves from the cache if we are in it. + // fprintf(stderr, "Removing %p from storage manager cache.\n", handle(false)); + globals().storageManager.removeKeychain(dlDbIdentifier(), this); + delete mEventBuffer; + } + catch(...) + { + } +} + +Mutex* +KeychainImpl::getMutexForObject() +{ + return globals().storageManager.getStorageManagerMutex(); +} + +Mutex* +KeychainImpl::getKeychainMutex() +{ + return &mMutex; +} + +void KeychainImpl::aboutToDestruct() +{ + // remove me from the global cache, we are done + // fprintf(stderr, "Destructing keychain object\n"); + DLDbIdentifier identifier = dlDbIdentifier(); + globals().storageManager.removeKeychain(identifier, this); +} + +bool +KeychainImpl::operator ==(const KeychainImpl &keychain) const +{ + return dlDbIdentifier() == keychain.dlDbIdentifier(); +} + +KCCursor +KeychainImpl::createCursor(SecItemClass itemClass, const SecKeychainAttributeList *attrList) +{ + StLock_(mMutex); + + StorageManager::KeychainList keychains; + keychains.push_back(Keychain(this)); + return KCCursor(keychains, itemClass, attrList); +} + +KCCursor +KeychainImpl::createCursor(const SecKeychainAttributeList *attrList) +{ + StLock_(mMutex); + + StorageManager::KeychainList keychains; + keychains.push_back(Keychain(this)); + return KCCursor(keychains, attrList); +} + +void +KeychainImpl::create(UInt32 passwordLength, const void *inPassword) +{ + StLock_(mMutex); + + if (!inPassword) + { + create(); + return; + } + + Allocator &alloc = Allocator::standard(); + + // @@@ Share this instance + + const CssmData password(const_cast(inPassword), passwordLength); + AclFactory::PasswordChangeCredentials pCreds (password, alloc); + AclFactory::AnyResourceContext rcc(pCreds); + create(&rcc); +} + +void KeychainImpl::create(ConstStringPtr inPassword) +{ + StLock_(mMutex); + + if ( inPassword ) + create(static_cast(inPassword[0]), &inPassword[1]); + else + create(); +} + +void +KeychainImpl::create() +{ + StLock_(mMutex); + + AclFactory aclFactory; + AclFactory::AnyResourceContext rcc(aclFactory.unlockCred()); + create(&rcc); +} + +void KeychainImpl::createWithBlob(CssmData &blob) +{ + StLock_(mMutex); + + mDb->dbInfo(&Schema::DBInfo); + AclFactory aclFactory; + AclFactory::AnyResourceContext rcc(aclFactory.unlockCred()); + mDb->resourceControlContext (&rcc); + try + { + mDb->createWithBlob(blob); + } + catch (...) + { + mDb->resourceControlContext(NULL); + mDb->dbInfo(NULL); + throw; + } + mDb->resourceControlContext(NULL); + mDb->dbInfo(NULL); // Clear the schema (to not break an open call later) + globals().storageManager.created(Keychain(this)); + + KCEventNotifier::PostKeychainEvent (kSecKeychainListChangedEvent, this, NULL); +} + +void +KeychainImpl::create(const ResourceControlContext *rcc) +{ + StLock_(mMutex); + + mDb->dbInfo(&Schema::DBInfo); // Set the schema (to force a create) + mDb->resourceControlContext(rcc); + try + { + mDb->create(); + } + catch (...) + { + mDb->resourceControlContext(NULL); + mDb->dbInfo(NULL); // Clear the schema (to not break an open call later) + throw; + } + mDb->resourceControlContext(NULL); + mDb->dbInfo(NULL); // Clear the schema (to not break an open call later) + globals().storageManager.created(Keychain(this)); +} + +void +KeychainImpl::open() +{ + StLock_(mMutex); + + mDb->open(); +} + +void +KeychainImpl::lock() +{ + StLock_(mMutex); + + mDb->lock(); +} + +void +KeychainImpl::unlock() +{ + StLock_(mMutex); + + mDb->unlock(); +} + +void +KeychainImpl::unlock(const CssmData &password) +{ + StLock_(mMutex); + + mDb->unlock(password); +} + +void +KeychainImpl::unlock(ConstStringPtr password) +{ + StLock_(mMutex); + + if (password) + { + const CssmData data(const_cast(&password[1]), password[0]); + unlock(data); + } + else + unlock(); +} + +void +KeychainImpl::getSettings(uint32 &outIdleTimeOut, bool &outLockOnSleep) +{ + StLock_(mMutex); + + mDb->getSettings(outIdleTimeOut, outLockOnSleep); +} + +void KeychainImpl::markBlobForDotMacSyncUpdate(CssmData& data) +{ + // find the plist for dot mac + CFArrayRef dictionaries = (CFArrayRef) CFPreferencesCopyValue(CFSTR("KeychainSyncList"), + CFSTR("com.apple.keychainsync"), + kCFPreferencesCurrentUser, + kCFPreferencesAnyHost); + + if (dictionaries == NULL) // no such preference? The user doesn't .Mac + { + return; + } + + CFStringRef currentPath = CFStringCreateWithCString(NULL, name(), kCFStringEncodingUTF8); + + // in each dictionary look for the path to the current keychain + CFIndex i; + CFIndex count = CFArrayGetCount(dictionaries); + + // make a mutable copy of the array + CFMutableArrayRef mutableDictionaries = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); + for (i = 0; i < count; ++i) + { + CFMutableDictionaryRef d = (CFMutableDictionaryRef) CFDictionaryCreateMutableCopy(NULL, 0, (CFDictionaryRef) CFArrayGetValueAtIndex(dictionaries, i)); + CFArrayAppendValue(mutableDictionaries, d); + CFRelease(d); + } + + // clean up what we don't need anymore + CFRelease(dictionaries); + + bool somethingChanged = false; + + for (i = 0; i < count; ++i) + { + CFMutableDictionaryRef d = (CFMutableDictionaryRef) CFArrayGetValueAtIndex(mutableDictionaries, i); + + // get the path and expand any tildes + CFStringRef path = (CFStringRef) CFDictionaryGetValue(d, CFSTR("DbName")); + CFIndex length = CFStringGetMaximumSizeForEncoding(CFStringGetLength(path), kCFStringEncodingUTF8); + char buffer[length + 1]; // adjust for NULL termination + CFStringGetCString(path, buffer, sizeof(buffer), kCFStringEncodingUTF8); + string fullPath = buffer; + fullPath = DLDbListCFPref::ExpandTildesInPath(fullPath); + path = CFStringCreateWithCString(NULL, fullPath.c_str(), kCFStringEncodingUTF8); + + if (CFStringCompare(path, currentPath, 0) == kCFCompareEqualTo) + { + // if the value already exists, don't worry about it + CFDataRef oldBlob = (CFDataRef) CFDictionaryGetValue(d, CFSTR("DbOldBlob")); + if (oldBlob == NULL) + { + // CFify the blob + CFDataRef theBlob = (CFDataRef) CFDataCreate(NULL, (uint8*) data.data(), data.length()); + CFDictionaryAddValue(d, CFSTR("DbOldBlob"), theBlob); + CFRelease(theBlob); + + CFPreferencesSetValue(CFSTR("KeychainSyncList"), + mutableDictionaries, + CFSTR("com.apple.keychainsync"), + kCFPreferencesCurrentUser, + kCFPreferencesAnyHost); + somethingChanged = true; + } + } + } + + CFRelease(currentPath); + + CFRelease(mutableDictionaries); + + if (somethingChanged) + { + CFPreferencesSynchronize(CFSTR("com.apple.keychainsync"), kCFPreferencesCurrentUser, kCFPreferencesAnyHost); + } +} + + + +void +KeychainImpl::setSettings(uint32 inIdleTimeOut, bool inLockOnSleep) +{ + StLock_(mMutex); + + // The .Mac syncing code only makes sense for the AppleFile CSP/DL, + // but other DLs such as the OCSP and LDAP DLs do not expose a way to + // change settings or the password. To make a minimal change that only affects + // the smartcard case, we only look for that CSP/DL + + bool isSmartcard = (mDb->dl()->guid() == gGuidAppleSdCSPDL); + + // get the old keychain blob so that we can tell .Mac to resync it + CssmAutoData oldBlob(mDb ->allocator()); + if (!isSmartcard) + mDb->copyBlob(oldBlob.get()); + + mDb->setSettings(inIdleTimeOut, inLockOnSleep); + + // if we got here, nothing threw underneath. Send the results off to .Mac heaven + if (!isSmartcard) + markBlobForDotMacSyncUpdate(oldBlob.get()); +} + +void +KeychainImpl::changePassphrase(UInt32 oldPasswordLength, const void *oldPassword, + UInt32 newPasswordLength, const void *newPassword) +{ + StLock_(mMutex); + + bool isSmartcard = (mDb->dl()->guid() == gGuidAppleSdCSPDL); + + TrackingAllocator allocator(Allocator::standard()); + AutoCredentials cred = AutoCredentials(allocator); + if (oldPassword) + { + const CssmData &oldPass = *new(allocator) CssmData(const_cast(oldPassword), oldPasswordLength); + TypedList &oldList = *new(allocator) TypedList(allocator, CSSM_SAMPLE_TYPE_KEYCHAIN_LOCK); + oldList.append(new(allocator) ListElement(CSSM_SAMPLE_TYPE_PASSWORD)); + oldList.append(new(allocator) ListElement(oldPass)); + cred += oldList; + } + + if (newPassword) + { + const CssmData &newPass = *new(allocator) CssmData(const_cast(newPassword), newPasswordLength); + TypedList &newList = *new(allocator) TypedList(allocator, CSSM_SAMPLE_TYPE_KEYCHAIN_CHANGE_LOCK); + newList.append(new(allocator) ListElement(CSSM_SAMPLE_TYPE_PASSWORD)); + newList.append(new(allocator) ListElement(newPass)); + cred += newList; + } + + // get the old keychain blob so that we can tell .Mac to resync it + CssmAutoData oldBlob(mDb->allocator()); + if (!isSmartcard) + mDb->copyBlob(oldBlob.get()); + + mDb->changePassphrase(&cred); + + // if we got here, nothing threw underneath. Send the results off to .Mac heaven + if (!isSmartcard) + markBlobForDotMacSyncUpdate(oldBlob.get()); +} + +void +KeychainImpl::changePassphrase(ConstStringPtr oldPassword, ConstStringPtr newPassword) +{ + StLock_(mMutex); + + const void *oldPtr, *newPtr; + UInt32 oldLen, newLen; + if (oldPassword) + { + oldLen = oldPassword[0]; + oldPtr = oldPassword + 1; + } + else + { + oldLen = 0; + oldPtr = NULL; + } + + if (newPassword) + { + newLen = newPassword[0]; + newPtr = newPassword + 1; + } + else + { + newLen = 0; + newPtr = NULL; + } + + changePassphrase(oldLen, oldPtr, newLen, newPtr); +} + +void +KeychainImpl::authenticate(const CSSM_ACCESS_CREDENTIALS *cred) +{ + StLock_(mMutex); + + if (!exists()) + MacOSError::throwMe(errSecNoSuchKeychain); + + MacOSError::throwMe(unimpErr); +} + +UInt32 +KeychainImpl::status() const +{ + // @@@ We should figure out the read/write status though a DL passthrough + // or some other way. Also should locked be unlocked read only or just + // read-only? + return (mDb->isLocked() ? 0 : kSecUnlockStateStatus | kSecWritePermStatus) + | kSecReadPermStatus; +} + +bool +KeychainImpl::exists() +{ + StLock_(mMutex); + + bool exists = true; + try + { + open(); + // Ok to leave the mDb open since it will get closed when it goes away. + } + catch (const CssmError &e) + { + if (e.osStatus() != CSSMERR_DL_DATASTORE_DOESNOT_EXIST) + throw; + exists = false; + } + + return exists; +} + +bool +KeychainImpl::isActive() const +{ + return mDb->isActive(); +} + +void KeychainImpl::completeAdd(Item &inItem, PrimaryKey &primaryKey) +{ + + + // The inItem shouldn't be in the cache yet + assert(!inItem->inCache()); + + // Insert inItem into mDbItemMap with key primaryKey. p.second will be + // true if it got inserted. If not p.second will be false and p.first + // will point to the current entry with key primaryKey. + pair p = + mDbItemMap.insert(DbItemMap::value_type(primaryKey, inItem.get())); + if (!p.second) + { + // There was already an ItemImpl * in mDbItemMap with key + // primaryKey. Get a ref to the pointer to it so we can assign a + // new value to it below. + ItemImpl *oldItem = p.first->second; + + // @@@ If this happens we are breaking our API contract of + // uniquifying items. We really need to insert the item into the + // map before we start the add. And have the item be in an + // "is being added" state. + assert(oldItem->inCache()); + secdebug("keychain", "add of new item %p somehow replaced %p", + inItem.get(), oldItem); + oldItem->inCache(false); + oldItem = inItem.get(); + } + + inItem->inCache(true); +} + +void +KeychainImpl::addCopy(Item &inItem) +{ + Keychain keychain(this); + PrimaryKey primaryKey = inItem->addWithCopyInfo(keychain, true); + completeAdd(inItem, primaryKey); + postEvent(kSecAddEvent, inItem); +} + +void +KeychainImpl::add(Item &inItem) +{ + Keychain keychain(this); + PrimaryKey primaryKey = inItem->add(keychain); + completeAdd(inItem, primaryKey); + postEvent(kSecAddEvent, inItem); +} + +void +KeychainImpl::didUpdate(const Item &inItem, PrimaryKey &oldPK, + PrimaryKey &newPK) +{ + // If the primary key hasn't changed we don't need to update mDbItemMap. + if (oldPK != newPK) + { + // If inItem isn't in the cache we don't need to update mDbItemMap. + assert(inItem->inCache()); + if (inItem->inCache()) + { + // First remove the entry for inItem in mDbItemMap with key oldPK. + DbItemMap::iterator it = mDbItemMap.find(oldPK); + if (it != mDbItemMap.end() && (ItemImpl*) it->second == inItem.get()) + mDbItemMap.erase(it); + + // Insert inItem into mDbItemMap with key newPK. p.second will be + // true if it got inserted. If not p.second will be false and + // p.first will point to the current entry with key newPK. + pair p = + mDbItemMap.insert(DbItemMap::value_type(newPK, inItem.get())); + if (!p.second) + { + // There was already an ItemImpl * in mDbItemMap with key + // primaryKey. Get a ref to the pointer to it so we can assign + // a new value to it below. + ItemImpl *oldItem = p.first->second; + + // @@@ If this happens we are breaking our API contract of + // uniquifying items. We really need to insert the item into + // the map with the new primary key before we start the update. + // And have the item be in an "is being updated" state. + assert(oldItem->inCache()); + secdebug("keychain", "update of item %p somehow replaced %p", + inItem.get(), oldItem); + oldItem->inCache(false); + oldItem = inItem.get(); + } + } + } + + postEvent(kSecUpdateEvent, inItem); +} + +void +KeychainImpl::deleteItem(Item &inoutItem) +{ + { + // We don't need to hold the DO mutex through event posting, and, in fact, doing so causes deadlock. + // Hold it only as long as needed, instead. + + + // item must be persistent + if (!inoutItem->isPersistent()) + MacOSError::throwMe(errSecInvalidItemRef); + + DbUniqueRecord uniqueId = inoutItem->dbUniqueRecord(); + PrimaryKey primaryKey = inoutItem->primaryKey(); + uniqueId->deleteRecord(); + + // Don't remove the item from the mDbItemMap here since this would cause + // us to report a new item to our caller when we receive the + // kSecDeleteEvent notification. + // It will be removed before we post the notification, because + // CCallbackMgr will call didDeleteItem() + + // Post the notification for the item deletion with + // the primaryKey obtained when the item still existed + } + + postEvent(kSecDeleteEvent, inoutItem); +} + + +CssmClient::CSP +KeychainImpl::csp() +{ + StLock_(mMutex); + + if (!mDb->dl()->subserviceMask() & CSSM_SERVICE_CSP) + MacOSError::throwMe(errSecInvalidKeychain); + + // Try to cast first to a CSPDL to handle case where we don't have an SSDb + try + { + CssmClient::CSPDL cspdl(dynamic_cast(&*mDb->dl())); + return CSP(cspdl); + } + catch (...) + { + SSDbImpl* impl = dynamic_cast(&(*mDb)); + if (impl == NULL) + { + CssmError::throwMe(CSSMERR_CSSM_INVALID_POINTER); + } + + SSDb ssDb(impl); + return ssDb->csp(); + } +} + +PrimaryKey +KeychainImpl::makePrimaryKey(CSSM_DB_RECORDTYPE recordType, DbUniqueRecord &uniqueId) +{ + StLock_(mMutex); + + DbAttributes primaryKeyAttrs(uniqueId->database()); + primaryKeyAttrs.recordType(recordType); + gatherPrimaryKeyAttributes(primaryKeyAttrs); + uniqueId->get(&primaryKeyAttrs, NULL); + return PrimaryKey(primaryKeyAttrs); +} + +const CssmAutoDbRecordAttributeInfo & +KeychainImpl::primaryKeyInfosFor(CSSM_DB_RECORDTYPE recordType) +{ + StLock_(mMutex); + + try + { + return keychainSchema()->primaryKeyInfosFor(recordType); + } + catch (const CommonError &error) + { + switch (error.osStatus()) + { + case errSecNoSuchClass: + case CSSMERR_DL_INVALID_RECORDTYPE: + resetSchema(); + return keychainSchema()->primaryKeyInfosFor(recordType); + default: + throw; + } + } +} + +void KeychainImpl::gatherPrimaryKeyAttributes(DbAttributes& primaryKeyAttrs) +{ + StLock_(mMutex); + + const CssmAutoDbRecordAttributeInfo &infos = + primaryKeyInfosFor(primaryKeyAttrs.recordType()); + + // @@@ fix this to not copy info. + for (uint32 i = 0; i < infos.size(); i++) + primaryKeyAttrs.add(infos.at(i)); +} + +ItemImpl * +KeychainImpl::_lookupItem(const PrimaryKey &primaryKey) +{ + DbItemMap::iterator it = mDbItemMap.find(primaryKey); + if (it != mDbItemMap.end()) + { + if (it->second == NULL) + { + // we've been weak released... + mDbItemMap.erase(it); + } + else + { + return it->second; + } + } + + return NULL; +} + +Item +KeychainImpl::item(const PrimaryKey &primaryKey) +{ + StLock_(mMutex); + + // Lookup the item in the map while holding the apiLock. + ItemImpl *itemImpl = _lookupItem(primaryKey); + if (itemImpl) + return Item(itemImpl); + + try + { + // We didn't find it so create a new item with just a keychain and + // a primary key. However since we aren't holding + // globals().apiLock anymore some other thread might have beaten + // us to creating this item and adding it to the cache. If that + // happens we retry the lookup. + return Item(this, primaryKey); + } + catch (const MacOSError &e) + { + // If the item creation failed because some other thread already + // inserted this item into the cache we retry the lookup. + if (e.osStatus() == errSecDuplicateItem) + { + // Lookup the item in the map while holding the apiLock. + ItemImpl *itemImpl = _lookupItem(primaryKey); + if (itemImpl) + return Item(itemImpl); + } + throw; + } +} + + +Item +KeychainImpl::item(CSSM_DB_RECORDTYPE recordType, DbUniqueRecord &uniqueId) +{ + StLock_(mMutex); + + PrimaryKey primaryKey = makePrimaryKey(recordType, uniqueId); + { + // Lookup the item in the map while holding the apiLock. + ItemImpl *itemImpl = _lookupItem(primaryKey); + + if (itemImpl) + { + return Item(itemImpl); + } + } + + try + { + // We didn't find it so create a new item with a keychain, a primary key + // and a DbUniqueRecord. However since we aren't holding + // globals().apiLock anymore some other thread might have beaten + // us to creating this item and adding it to the cache. If that + // happens we retry the lookup. + return Item(this, primaryKey, uniqueId); + } + catch (const MacOSError &e) + { + // If the item creation failed because some other thread already + // inserted this item into the cache we retry the lookup. + if (e.osStatus() == errSecDuplicateItem) + { + // Lookup the item in the map while holding the apiLock. + ItemImpl *itemImpl = _lookupItem(primaryKey); + if (itemImpl) + return Item(itemImpl); + } + throw; + } +} + +KeychainSchema +KeychainImpl::keychainSchema() +{ + StLock_(mMutex); + if (!mKeychainSchema) + mKeychainSchema = KeychainSchema(mDb); + + return mKeychainSchema; +} + +void KeychainImpl::resetSchema() +{ + mKeychainSchema = NULL; // re-fetch it from db next time +} + + +// Called from DbItemImpl's constructor (so it is only partially constructed), +// add it to the map. +void +KeychainImpl::addItem(const PrimaryKey &primaryKey, ItemImpl *dbItemImpl) +{ + StLock_(mMutex); + + // The dbItemImpl shouldn't be in the cache yet + assert(!dbItemImpl->inCache()); + + // Insert dbItemImpl into mDbItemMap with key primaryKey. p.second will + // be true if it got inserted. If not p.second will be false and p.first + // will point to the current entry with key primaryKey. + pair p = + mDbItemMap.insert(DbItemMap::value_type(primaryKey, dbItemImpl)); + + if (!p.second) + { + // There was already an ItemImpl * in mDbItemMap with key primaryKey. + // There is a race condition here when being called in multiple threads + // We might have added an item using add and received a notification at + // the same time. + MacOSError::throwMe(errSecDuplicateItem); + } + + dbItemImpl->inCache(true); +} + +void +KeychainImpl::didDeleteItem(ItemImpl *inItemImpl) +{ + StLock_(mMutex); + + // Called by CCallbackMgr + secdebug("kcnotify", "%p notified that item %p was deleted", this, inItemImpl); + removeItem(inItemImpl->primaryKey(), inItemImpl); +} + +void +KeychainImpl::removeItem(const PrimaryKey &primaryKey, ItemImpl *inItemImpl) +{ + StLock_(mMutex); + + // If inItemImpl isn't in the cache to begin with we are done. + if (!inItemImpl->inCache()) + return; + + DbItemMap::iterator it = mDbItemMap.find(primaryKey); + if (it != mDbItemMap.end() && (ItemImpl*) it->second == inItemImpl) + mDbItemMap.erase(it); + + inItemImpl->inCache(false); +} + +void +KeychainImpl::getAttributeInfoForItemID(CSSM_DB_RECORDTYPE itemID, + SecKeychainAttributeInfo **Info) +{ + StLock_(mMutex); + + try + { + keychainSchema()->getAttributeInfoForRecordType(itemID, Info); + } + catch (const CommonError &error) + { + switch (error.osStatus()) + { + case errSecNoSuchClass: + case CSSMERR_DL_INVALID_RECORDTYPE: + resetSchema(); + keychainSchema()->getAttributeInfoForRecordType(itemID, Info); + default: + throw; + } + } +} + +void +KeychainImpl::freeAttributeInfo(SecKeychainAttributeInfo *Info) +{ + free(Info->tag); + free(Info->format); + free(Info); +} + +CssmDbAttributeInfo +KeychainImpl::attributeInfoFor(CSSM_DB_RECORDTYPE recordType, UInt32 tag) +{ + StLock_(mMutex); + + try + { + return keychainSchema()->attributeInfoFor(recordType, tag); + } + catch (const CommonError &error) + { + switch (error.osStatus()) + { + case errSecNoSuchClass: + case CSSMERR_DL_INVALID_RECORDTYPE: + resetSchema(); + return keychainSchema()->attributeInfoFor(recordType, tag); + default: + throw; + } + } +} + +void +KeychainImpl::recode(const CssmData &data, const CssmData &extraData) +{ + StLock_(mMutex); + + mDb->recode(data, extraData); +} + +void +KeychainImpl::copyBlob(CssmData &data) +{ + StLock_(mMutex); + + mDb->copyBlob(data); +} + +void +KeychainImpl::setBatchMode(Boolean mode, Boolean rollback) +{ + StLock_(mMutex); + + mDb->setBatchMode(mode, rollback); + mIsInBatchMode = mode; + if (!mode) + { + if (!rollback) // was batch mode being turned off without an abort? + { + // dump the buffer + EventBuffer::iterator it = mEventBuffer->begin(); + while (it != mEventBuffer->end()) + { + PrimaryKey primaryKey; + if (it->item) + { + primaryKey = it->item->primaryKey(); + } + + KCEventNotifier::PostKeychainEvent(it->kcEvent, mDb->dlDbIdentifier(), primaryKey); + + ++it; + } + + } + + // notify that a keychain has changed in too many ways to count + KCEventNotifier::PostKeychainEvent(kSecKeychainLeftBatchModeEvent); + mEventBuffer->clear(); + } + else + { + KCEventNotifier::PostKeychainEvent(kSecKeychainEnteredBatchModeEvent); + } +} + +void +KeychainImpl::postEvent(SecKeychainEvent kcEvent, ItemImpl* item) +{ + PrimaryKey primaryKey; + + { + StLock_(mMutex); + + if (item != NULL) + { + primaryKey = item->primaryKey(); + } + } + + if (!mIsInBatchMode) + { + KCEventNotifier::PostKeychainEvent(kcEvent, mDb->dlDbIdentifier(), primaryKey); + } + else + { + StLock_(mMutex); + + EventItem it; + it.kcEvent = kcEvent; + if (item != NULL) + { + it.item = item; + } + + mEventBuffer->push_back (it); + } +} + +Keychain::Keychain() +{ + dispatch_once(&SecKeychainSystemKeychainChecked, ^{ + check_system_keychain(); + }); +} + +Keychain +Keychain::optional(SecKeychainRef handle) +{ + if (handle) + return KeychainImpl::required(handle); + else + return globals().storageManager.defaultKeychain(); +} + + +CFIndex GetKeychainRetainCount(Keychain& kc) +{ + CFTypeRef ref = kc->handle(false); + return CFGetRetainCount(ref); +} + + +// +// Create default credentials for this keychain. +// This is triggered upon default open (i.e. a Db::activate() with no set credentials). +// +// This function embodies the "default credentials" logic for Keychain-layer databases. +// +const AccessCredentials * +KeychainImpl::makeCredentials() +{ + return defaultCredentials(); +} + + +const AccessCredentials * +KeychainImpl::defaultCredentials() +{ + StLock_(mMutex); + + // Use custom unlock credentials for file keychains which have a referral + // record and the standard credentials for all others. + + if (mDb->dl()->guid() == gGuidAppleCSPDL && mCustomUnlockCreds(mDb)) + return &mCustomUnlockCreds; + else + if (mDb->dl()->guid() == gGuidAppleSdCSPDL) + return globals().smartcardCredentials(); + else + return globals().keychainCredentials(); +} + + + diff --git a/libsecurity_keychain/lib/Keychains.h b/libsecurity_keychain/lib/Keychains.h new file mode 100644 index 00000000..f2ebaa54 --- /dev/null +++ b/libsecurity_keychain/lib/Keychains.h @@ -0,0 +1,263 @@ +/* + * 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@ + */ + +// +// Keychains.h - The Keychain class +// +#ifndef _SECURITY_KEYCHAINS_H_ +#define _SECURITY_KEYCHAINS_H_ + +#include +#include +#include +#include +#include +#include +#include +#include "SecCFTypes.h" +#include "defaultcreds.h" + +class EventBuffer; + +namespace Security +{ + +namespace KeychainCore +{ + +class KCCursor; +class Item; +class PrimaryKey; +class StorageManager; + +class KeychainSchemaImpl : public RefCount +{ + NOCOPY(KeychainSchemaImpl) +public: + friend class KeychainSchema; +protected: + KeychainSchemaImpl(const CssmClient::Db &db); +public: + virtual ~KeychainSchemaImpl(); + + CSSM_DB_ATTRIBUTE_FORMAT attributeFormatFor(CSSM_DB_RECORDTYPE recordType, uint32 attributeId) const; + const CssmAutoDbRecordAttributeInfo &primaryKeyInfosFor(CSSM_DB_RECORDTYPE recordType) const; + + bool operator <(const KeychainSchemaImpl &other) const; + bool operator ==(const KeychainSchemaImpl &other) const; + + void getAttributeInfoForRecordType(CSSM_DB_RECORDTYPE recordType, SecKeychainAttributeInfo **Info) const; + CssmDbAttributeInfo attributeInfoFor(CSSM_DB_RECORDTYPE recordType, uint32 attributeId) const; + bool hasAttribute(CSSM_DB_RECORDTYPE recordType, uint32 attributeId) const; + bool hasRecordType(CSSM_DB_RECORDTYPE recordType) const; + + void didCreateRelation(CSSM_DB_RECORDTYPE inRelationID, + const char *inRelationName, + uint32 inNumberOfAttributes, + const CSSM_DB_SCHEMA_ATTRIBUTE_INFO *pAttributeInfo, + uint32 inNumberOfIndexes, + const CSSM_DB_SCHEMA_INDEX_INFO *pIndexInfo); + +private: + typedef map PrimaryKeyInfoMap; + PrimaryKeyInfoMap mPrimaryKeyInfoMap; + + typedef map RelationInfoMap; + typedef map DatabaseInfoMap; + DatabaseInfoMap mDatabaseInfoMap; + Mutex mMutex; + +private: + const RelationInfoMap &relationInfoMapFor(CSSM_DB_RECORDTYPE recordType) const; +}; + + +class KeychainSchema : public RefPointer +{ +public: + KeychainSchema() {} + KeychainSchema(KeychainSchemaImpl *impl) : RefPointer(impl) {} + KeychainSchema(const CssmClient::Db &db) : RefPointer(new KeychainSchemaImpl(db)) {} + + bool operator <(const KeychainSchema &other) const + { return ptr && other.ptr ? *ptr < *other.ptr : ptr < other.ptr; } + bool operator ==(const KeychainSchema &other) const + { return ptr && other.ptr ? *ptr == *other.ptr : ptr == other.ptr; } + +private: + typedef KeychainSchemaImpl Impl; +}; + + +class ItemImpl; + +class KeychainImpl : public SecCFObject, private CssmClient::Db::DefaultCredentialsMaker +{ + NOCOPY(KeychainImpl) +public: + SECCFFUNCTIONS(KeychainImpl, SecKeychainRef, errSecInvalidKeychain, gTypes().KeychainImpl) + + friend class Keychain; + friend class ItemImpl; +protected: + KeychainImpl(const CssmClient::Db &db); + +protected: + // Methods called by ItemImpl; + void didUpdate(const Item &inItem, PrimaryKey &oldPK, + PrimaryKey &newPK); + void completeAdd(Item &item, PrimaryKey &key); + + void markBlobForDotMacSyncUpdate(CssmData &data); + +public: + virtual ~KeychainImpl(); + + Mutex* getKeychainMutex(); + Mutex* getMutexForObject(); + void aboutToDestruct(); + + bool operator ==(const KeychainImpl &) const; + + // Item calls + void add(Item &item); + void addCopy(Item &item); + void deleteItem(Item &item); // item must be persistant. + + // Keychain calls + void create(UInt32 passwordLength, const void *inPassword); + void createWithBlob(CssmData &blob); + void create(ConstStringPtr inPassword); + void create(); + void create(const ResourceControlContext *rcc); + void open(); + + // Locking and unlocking a keychain. + void lock(); + void unlock(); + void unlock(const CssmData &password); + void unlock(ConstStringPtr password); // @@@ This has a length limit, we should remove it. + + void getSettings(uint32 &outIdleTimeOut, bool &outLockOnSleep); + void setSettings(uint32 inIdleTimeOut, bool inLockOnSleep); + + // Passing in NULL for either oldPassword or newPassword will cause them to be prompted for. + // To specify a zero length password in either case the oldPasswordLength or newPasswordLength + // value must be 0 and the oldPassword or newPassword must not be NULL. + void changePassphrase(UInt32 oldPasswordLength, const void *oldPassword, + UInt32 newPasswordLength, const void *newPassword); + void changePassphrase(ConstStringPtr oldPassword, ConstStringPtr newPassword); + + void authenticate(const CSSM_ACCESS_CREDENTIALS *cred); // Does not do an unlock. + + const char *name() const { return mDb->name(); } + UInt32 status() const; + bool exists(); + bool isActive() const; + + KCCursor createCursor(const SecKeychainAttributeList *attrList); + KCCursor createCursor(SecItemClass itemClass, const SecKeychainAttributeList *attrList); + CssmClient::Db database() { return mDb; } + DLDbIdentifier dlDbIdentifier() const { return mDb->dlDbIdentifier(); } + + CssmClient::CSP csp(); + + PrimaryKey makePrimaryKey(CSSM_DB_RECORDTYPE recordType, CssmClient::DbUniqueRecord &uniqueId); + void gatherPrimaryKeyAttributes(CssmClient::DbAttributes& primaryKeyAttrs); + + const CssmAutoDbRecordAttributeInfo &primaryKeyInfosFor(CSSM_DB_RECORDTYPE recordType); + + Item item(const PrimaryKey& primaryKey); + Item item(CSSM_DB_RECORDTYPE recordType, CssmClient::DbUniqueRecord &uniqueId); + + CssmDbAttributeInfo attributeInfoFor(CSSM_DB_RECORDTYPE recordType, UInt32 tag); + void getAttributeInfoForItemID(CSSM_DB_RECORDTYPE itemID, SecKeychainAttributeInfo **Info); + static void freeAttributeInfo(SecKeychainAttributeInfo *Info); + KeychainSchema keychainSchema(); + void resetSchema(); + void didDeleteItem(ItemImpl *inItemImpl); + + void recode(const CssmData &data, const CssmData &extraData); + void copyBlob(CssmData &dbBlob); + + void setBatchMode(Boolean mode, Boolean rollBack); + + // yield default open() credentials for this keychain (as of now) + const AccessCredentials *defaultCredentials(); + + // Only call these functions while holding globals().apiLock. + bool inCache() const throw() { return mInCache; } + void inCache(bool inCache) throw() { mInCache = inCache; } + + void postEvent(SecKeychainEvent kcEvent, ItemImpl* item); + + void addItem(const PrimaryKey &primaryKey, ItemImpl *dbItemImpl); + +private: + void removeItem(const PrimaryKey &primaryKey, ItemImpl *inItemImpl); + ItemImpl *_lookupItem(const PrimaryKey &primaryKey); + + const AccessCredentials *makeCredentials(); + + typedef map DbItemMap; + // Weak reference map of all items we know about that have a primaryKey + DbItemMap mDbItemMap; + // True iff we are in the cache of keychains in StorageManager + bool mInCache; + + CssmClient::Db mDb; + + KeychainSchema mKeychainSchema; + + // Data for auto-unlock credentials + DefaultCredentials mCustomUnlockCreds; + bool mIsInBatchMode; + EventBuffer *mEventBuffer; + Mutex mMutex; +}; + + +CFIndex GetKeychainRetainCount(Keychain& kc); + +class Keychain : public SecPointer +{ +public: + Keychain(); + Keychain(KeychainImpl *impl) : SecPointer(impl) {} + + static Keychain optional(SecKeychainRef handle); + +private: + friend class StorageManager; + Keychain(const CssmClient::Db &db) + : SecPointer(new KeychainImpl(db)) {} + + typedef KeychainImpl Impl; +}; + + +} // end namespace KeychainCore + +} // end namespace Security + +#endif // !_SECURITY_KEYCHAINS_H_ diff --git a/libsecurity_keychain/lib/MacOSErrorStrings.h b/libsecurity_keychain/lib/MacOSErrorStrings.h new file mode 100644 index 00000000..fc9cc2b7 --- /dev/null +++ b/libsecurity_keychain/lib/MacOSErrorStrings.h @@ -0,0 +1,61 @@ +/* + * 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@ + */ + +/* + 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. +*/ + +/* Definitions for miscellaneous OS errors that can be returned (with appropriate error strings) */ +enum +{ + errSecMisc_nsvErr = -35, /* The disk couldn't be found. It may have been ejected. */ + errSecMisc_bdNamErr = -37, /* Tried to open a file whose name contains an illegal character. */ + errSecMisc_fnfErr = -43, /* The file could not be found. */ + errSecMisc_wPrErr = -44, /* The disk is write-protected. */ + errSecMisc_fLckdErr = -45, /* The file is locked. */ + errSecMisc_vLckdErr = -46, /* The volume is locked. */ + errSecMisc_fBsyErr = -47, /* The file is busy. It may be in use by another application. */ + errSecMisc_dupFNErr = -48, /* A file with the same name already exists. */ + errSecMisc_opWrErr = -49, /* The file is already open with write permission. */ + errSecMisc_volOffLinErr = -53, /* The volume is no longer available. It may have been ejected. */ + errSecMisc_permErr = -54, /* The file could not be opened. It may be in use by another application. */ + errSecMisc_extFSErr = -58, /* This volume does not appear to be compatible. */ + errSecMisc_wrPermErr = -61, /* Could not write to the file. It may have been opened with insufficient access privileges. */ + errSecMisc_offLinErr = -65, /* The storage device is no longer available. It may have been ejected. */ + errSecMisc_memFullErr = -108, + errSecMisc_dirNFErr = -120, /* The directory could not be found. */ + errSecMisc_volGoneErr = -124, /* The server volume is no longer available. It may have been disconnected. */ + errSecMisc_userCanceledErr = -128, /* The operation was cancelled by the user. */ + errSecMisc_resNotFound = -192, /* A required resource could not be found. */ + errSecMisc_resFNotFound = -193, /* A required resource is missing or damaged. */ + errSecMisc_icNoURLErr = -673, /* The specified location (URL) is an unknown type, or does not contain enough information. */ + errSecMisc_icConfigNotFoundErr = -674, /* A helper application to open the specified URL could not be found. */ + errSecMisc_cantGetFlavorErr = -1854, /* The location (URL) of this item is missing or improperly formatted. */ + errSecMisc_afpAccessDenied = -5000, /* Access to this item was denied. */ + errSecMisc_afpUserNotAuth = -5023, /* Authentication failed. The password for this server may have changed since the item was added to the keychain. */ + errSecMisc_afpPwdPolicyErr = -5046 /* This AppleShare IP server is configured to not allow users to save passwords for automatic login. Contact the server administrator for more information. */ +}; + diff --git a/libsecurity_keychain/lib/Password.cpp b/libsecurity_keychain/lib/Password.cpp new file mode 100644 index 00000000..327e7e67 --- /dev/null +++ b/libsecurity_keychain/lib/Password.cpp @@ -0,0 +1,147 @@ +/* + * 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@ + */ + +// +// Password.cpp +// +#include "Password.h" +#include +#include "SecBridge.h" + +#include "KCCursor.h" + +using namespace KeychainCore; +using namespace CssmClient; + +PasswordImpl::PasswordImpl(SecItemClass itemClass, SecKeychainAttributeList *searchAttrList, SecKeychainAttributeList *itemAttrList) : + mItem(itemClass, itemAttrList, 0, NULL), mUseKeychain(false), mFoundInKeychain(false), mRememberInKeychain(false), mMutex(Mutex::recursive) +{ + if (searchAttrList && itemAttrList) + { + mUseKeychain = true; + mKeychain = Keychain::optional(NULL); + mRememberInKeychain = true; + + // initialize mFoundInKeychain to true if mItem is found + + StorageManager::KeychainList keychains; + globals().storageManager.optionalSearchList(NULL, keychains); + KCCursor cursor(keychains, itemClass, searchAttrList); + + if (cursor->next(mItem)) + mFoundInKeychain = true; + } +} + +PasswordImpl::PasswordImpl(PasswordImpl& existing) +{ + mKeychain = existing.mKeychain; + mItem = existing.mItem; + mUseKeychain = existing.mUseKeychain; + mFoundInKeychain = existing.mFoundInKeychain; + mRememberInKeychain = existing.mRememberInKeychain; +} + + + +PasswordImpl::~PasswordImpl() throw() +{ +} + +void +PasswordImpl::setAccess(Access *access) +{ + // changing an existing ACL is more work than this SPI wants to do + if (!mFoundInKeychain) + mItem->setAccess(access); +} + +void +PasswordImpl::setData(UInt32 length, const void *data) +{ + assert(mUseKeychain); + + // do different things based on mFoundInKeychain? + mItem->setData(length,data); +} + +bool +PasswordImpl::getData(UInt32 *length, const void **data) +{ + if (mItem->isPersistent()) + { + // try to retrieve it + CssmDataContainer outData; + try + { + mItem->getData(outData); + if (length && data) + { + *length=outData.length(); + outData.Length=0; + *data=outData.data(); + outData.Data=NULL; + } + return true; + } + catch (...) + { + // cancel unlock: CSP_USER_CANCELED + // deny rogue app CSP_OPERATION_AUTH_DENIED + return false; + } + } + else + return false; +} + +void +PasswordImpl::save() +{ + assert(mUseKeychain); + + if (mFoundInKeychain) + { + mItem->update(); + } + else + { + mKeychain->add(mItem); + + // reinitialize mItem now it's on mKeychain + mFoundInKeychain = true; // should be set by member that resets mItem + } +} + +Password::Password(SecItemClass itemClass, SecKeychainAttributeList *searchAttrList, SecKeychainAttributeList *itemAttrList) : + SecPointer(new PasswordImpl(itemClass, searchAttrList, itemAttrList)) +{ +} + +Password::Password(PasswordImpl *impl) : SecPointer(impl) +{ +} + +Password::Password(PasswordImpl &impl) : SecPointer(new PasswordImpl(impl)) +{ +} diff --git a/libsecurity_keychain/lib/Password.h b/libsecurity_keychain/lib/Password.h new file mode 100644 index 00000000..90e2e33e --- /dev/null +++ b/libsecurity_keychain/lib/Password.h @@ -0,0 +1,81 @@ +/* + * 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@ + */ + +// +// Password.h - Password acquiring wrapper +// +#ifndef _SECURITY_PASSWORD_H_ +#define _SECURITY_PASSWORD_H_ + +#include +// included by item #include +#include + + +namespace Security { +namespace KeychainCore { + +class PasswordImpl : public SecCFObject { +public: + SECCFFUNCTIONS(PasswordImpl, SecPasswordRef, errSecInvalidPasswordRef, gTypes().PasswordImpl) + +public: + // make default forms + PasswordImpl(SecItemClass itemClass, SecKeychainAttributeList *searchAttrList, SecKeychainAttributeList *itemAttrList); + PasswordImpl(PasswordImpl& existing); + + virtual ~PasswordImpl() throw(); + + bool getData(UInt32 *length, const void **data); + void setData(UInt32 length,const void *data); + void save(); + bool useKeychain() const { return mUseKeychain; } + bool rememberInKeychain() const { return mRememberInKeychain; } + void setRememberInKeychain(bool remember) { mRememberInKeychain = remember; } + void setAccess(Access *access); + +private: + // keychain item cached? + Keychain mKeychain; + Item mItem; + bool mUseKeychain; + bool mFoundInKeychain; + bool mRememberInKeychain; + Mutex mMutex; +}; + +class Password : public SecPointer +{ +public: + Password(SecItemClass itemClass, SecKeychainAttributeList *searchAttrList, SecKeychainAttributeList *itemAttrList); + Password(PasswordImpl *impl); + Password(PasswordImpl &impl); +}; + + + + +} // end namespace KeychainCore +} // end namespace Security + +#endif // !_SECURITY_PASSWORD_H_ diff --git a/libsecurity_keychain/lib/Policies.cpp b/libsecurity_keychain/lib/Policies.cpp new file mode 100644 index 00000000..2957cac9 --- /dev/null +++ b/libsecurity_keychain/lib/Policies.cpp @@ -0,0 +1,313 @@ +/* + * 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@ + */ + +// +// Policy.cpp - Working with Policies +// +#include +#include +#include +#include + +/* Oids longer than this are considered invalid. */ +#define MAX_OID_SIZE 32 + +//%%FIXME: need to use a common copy of this utility function +CFStringRef SecDERItemCopyOIDDecimalRepresentation(uint8 *oid, size_t oidLen) +{ + if (oidLen == 0) + return CFSTR(""); + + if (oidLen > MAX_OID_SIZE) + return CFSTR("Oid too long"); + + CFMutableStringRef result = CFStringCreateMutable(kCFAllocatorDefault, 0); + + // The first two levels are encoded into one byte, since the root level + // has only 3 nodes (40*x + y). However if x = joint-iso-itu-t(2) then + // y may be > 39, so we have to add special-case handling for this. + uint32_t x = oid[0] / 40; + uint32_t y = oid[0] % 40; + if (x > 2) + { + // Handle special case for large y if x = 2 + y += (x - 2) * 40; + x = 2; + } + CFStringAppendFormat(result, NULL, CFSTR("%u.%u"), x, y); + + uint32_t value = 0; + for (x = 1; x < oidLen; ++x) + { + value = (value << 7) | (oid[x] & 0x7F); + /* @@@ value may not span more than 4 bytes. */ + /* A max number of 20 values is allowed. */ + if (!(oid[x] & 0x80)) + { + CFStringAppendFormat(result, NULL, CFSTR(".%lu"), value); + value = 0; + } + } + return result; +} + + +using namespace KeychainCore; + +Policy::Policy(TP supportingTp, const CssmOid &policyOid) + : mTp(supportingTp), + mOid(Allocator::standard(), policyOid), + mValue(Allocator::standard()), + mAuxValue(Allocator::standard()) +{ + // value is as yet unimplemented + secdebug("policy", "Policy() this %p", this); +} + +Policy::~Policy() throw() +{ + secdebug("policy", "~Policy() this %p", this); +} + +void Policy::setValue(const CssmData &value) +{ + StLock_(mMutex); + mValue = value; + mAuxValue.reset(); + + // Certain policy values may contain an embedded pointer. Ask me how I feel about that. + if (mOid == CSSMOID_APPLE_TP_SSL || + mOid == CSSMOID_APPLE_TP_EAP || + mOid == CSSMOID_APPLE_TP_IP_SEC || + mOid == CSSMOID_APPLE_TP_APPLEID_SHARING) + { + CSSM_APPLE_TP_SSL_OPTIONS *opts = (CSSM_APPLE_TP_SSL_OPTIONS *)value.data(); + if (opts->Version == CSSM_APPLE_TP_SSL_OPTS_VERSION) + { + if (opts->ServerNameLen > 0) + { + // Copy auxiliary data, then update the embedded pointer to reference our copy + mAuxValue.copy(const_cast(opts->ServerName), opts->ServerNameLen); + mValue.get().interpretedAs()->ServerName = + reinterpret_cast(mAuxValue.data()); + } + else + { + // Clear the embedded pointer! + mValue.get().interpretedAs()->ServerName = + reinterpret_cast(NULL); + } + } + } + else if (mOid == CSSMOID_APPLE_TP_SMIME || + mOid == CSSMOID_APPLE_TP_ICHAT) + { + CSSM_APPLE_TP_SMIME_OPTIONS *opts = (CSSM_APPLE_TP_SMIME_OPTIONS *)value.data(); + if (opts->Version == CSSM_APPLE_TP_SMIME_OPTS_VERSION) + { + if (opts->SenderEmailLen > 0) + { + // Copy auxiliary data, then update the embedded pointer to reference our copy + mAuxValue.copy(const_cast(opts->SenderEmail), opts->SenderEmailLen); + mValue.get().interpretedAs()->SenderEmail = + reinterpret_cast(mAuxValue.data()); + } + else + { + // Clear the embedded pointer! + mValue.get().interpretedAs()->SenderEmail = + reinterpret_cast(NULL); + } + } + } +} + +void Policy::setProperties(CFDictionaryRef properties) +{ + // Set the policy value based on the provided dictionary keys. + if (mOid == CSSMOID_APPLE_TP_SSL || + mOid == CSSMOID_APPLE_TP_EAP || + mOid == CSSMOID_APPLE_TP_IP_SEC || + mOid == CSSMOID_APPLE_TP_APPLEID_SHARING) + { + CSSM_APPLE_TP_SSL_OPTIONS options = { CSSM_APPLE_TP_SSL_OPTS_VERSION, 0, NULL, 0 }; + char *buf = NULL; + CFStringRef nameStr = NULL; + if (CFDictionaryGetValueIfPresent(properties, (const void *)kSecPolicyName, (const void **)&nameStr)) { + buf = (char *)malloc(MAXPATHLEN); + if (buf) { + if (CFStringGetCString(nameStr, buf, MAXPATHLEN, kCFStringEncodingUTF8)) { + options.ServerName = buf; + options.ServerNameLen = strlen(buf)+1; // include terminating null + } + } + } + CFBooleanRef clientRef = NULL; + if (CFDictionaryGetValueIfPresent(properties, (const void *)kSecPolicyClient, (const void **)&clientRef) + && CFBooleanGetValue(clientRef) == true) + options.Flags |= CSSM_APPLE_TP_SSL_CLIENT; + + const CssmData value((uint8*)&options, sizeof(options)); + this->setValue(value); + + if (buf) free(buf); + } + else if (mOid == CSSMOID_APPLE_TP_SMIME || + mOid == CSSMOID_APPLE_TP_ICHAT) + { + CSSM_APPLE_TP_SMIME_OPTIONS options = { CSSM_APPLE_TP_SMIME_OPTS_VERSION, 0, 0, NULL }; + char *buf = NULL; + CFStringRef nameStr = NULL; + if (CFDictionaryGetValueIfPresent(properties, (const void *)kSecPolicyName, (const void **)&nameStr)) { + buf = (char *)malloc(MAXPATHLEN); + if (buf) { + if (CFStringGetCString(nameStr, buf, MAXPATHLEN, kCFStringEncodingUTF8)) { + options.SenderEmail = buf; + options.SenderEmailLen = strlen(buf)+1; // include terminating null + } + } + } + CFBooleanRef kuRef = NULL; + if (CFDictionaryGetValueIfPresent(properties, (const void *)kSecPolicyKU_DigitalSignature, (const void **)&kuRef) + && CFBooleanGetValue(kuRef) == true) + options.IntendedUsage |= CE_KU_DigitalSignature; + if (CFDictionaryGetValueIfPresent(properties, (const void *)kSecPolicyKU_NonRepudiation, (const void **)&kuRef) + && CFBooleanGetValue(kuRef) == true) + options.IntendedUsage |= CE_KU_NonRepudiation; + if (CFDictionaryGetValueIfPresent(properties, (const void *)kSecPolicyKU_KeyEncipherment, (const void **)&kuRef) + && CFBooleanGetValue(kuRef) == true) + options.IntendedUsage |= CE_KU_KeyEncipherment; + if (CFDictionaryGetValueIfPresent(properties, (const void *)kSecPolicyKU_DataEncipherment, (const void **)&kuRef) + && CFBooleanGetValue(kuRef) == true) + options.IntendedUsage |= CE_KU_DataEncipherment; + if (CFDictionaryGetValueIfPresent(properties, (const void *)kSecPolicyKU_KeyAgreement, (const void **)&kuRef) + && CFBooleanGetValue(kuRef) == true) + options.IntendedUsage |= CE_KU_KeyAgreement; + if (CFDictionaryGetValueIfPresent(properties, (const void *)kSecPolicyKU_KeyCertSign, (const void **)&kuRef) + && CFBooleanGetValue(kuRef) == true) + options.IntendedUsage |= CE_KU_KeyCertSign; + if (CFDictionaryGetValueIfPresent(properties, (const void *)kSecPolicyKU_CRLSign, (const void **)&kuRef) + && CFBooleanGetValue(kuRef) == true) + options.IntendedUsage |= CE_KU_CRLSign; + if (CFDictionaryGetValueIfPresent(properties, (const void *)kSecPolicyKU_EncipherOnly, (const void **)&kuRef) + && CFBooleanGetValue(kuRef) == true) + options.IntendedUsage |= CE_KU_EncipherOnly; + if (CFDictionaryGetValueIfPresent(properties, (const void *)kSecPolicyKU_DecipherOnly, (const void **)&kuRef) + && CFBooleanGetValue(kuRef) == true) + options.IntendedUsage |= CE_KU_DecipherOnly; + + const CssmData value((uint8*)&options, sizeof(options)); + this->setValue(value); + + if (buf) free(buf); + } + +} + +CFDictionaryRef Policy::properties() +{ + // Builds and returns a dictionary which the caller must release. + CSSM_DATA value = this->value(); + CFMutableDictionaryRef properties = CFDictionaryCreateMutable(NULL, 0, + &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + if (!properties) return NULL; + + // kSecPolicyOid + CFStringRef oidStr = SecDERItemCopyOIDDecimalRepresentation((uint8*)mOid.data(), mOid.length()); + if (oidStr) { + CFDictionarySetValue(properties, (const void *)kSecPolicyOid, (const void *)oidStr); + CFRelease(oidStr); + } + + // kSecPolicyName + if (mAuxValue) { + CFStringRef nameStr = CFStringCreateWithBytes(NULL, + (const UInt8 *)reinterpret_cast(mAuxValue.data()), + (CFIndex)mAuxValue.length(), kCFStringEncodingUTF8, false); + if (nameStr) { + CFDictionarySetValue(properties, (const void *)kSecPolicyName, (const void *)nameStr); + CFRelease(nameStr); + } + } + + // kSecPolicyClient + if (mValue) { + if (mOid == CSSMOID_APPLE_TP_SSL || + mOid == CSSMOID_APPLE_TP_EAP || + mOid == CSSMOID_APPLE_TP_IP_SEC || + mOid == CSSMOID_APPLE_TP_APPLEID_SHARING) + { + CSSM_APPLE_TP_SSL_OPTIONS *opts = (CSSM_APPLE_TP_SSL_OPTIONS *)mValue.data(); + if (opts->Flags & CSSM_APPLE_TP_SSL_CLIENT) { + CFDictionarySetValue(properties, (const void *)kSecPolicyClient, (const void *)kCFBooleanTrue); + } + } + } + + // key usage flags (currently only for S/MIME and iChat policies) + if (mValue) { + if (mOid == CSSMOID_APPLE_TP_SMIME || + mOid == CSSMOID_APPLE_TP_ICHAT) + { + CSSM_APPLE_TP_SMIME_OPTIONS *opts = (CSSM_APPLE_TP_SMIME_OPTIONS *)mValue.data(); + CE_KeyUsage usage = opts->IntendedUsage; + if (usage & CE_KU_DigitalSignature) + CFDictionarySetValue(properties, (const void *)kSecPolicyKU_DigitalSignature, (const void *)kCFBooleanTrue); + if (usage & CE_KU_NonRepudiation) + CFDictionarySetValue(properties, (const void *)kSecPolicyKU_NonRepudiation, (const void *)kCFBooleanTrue); + if (usage & CE_KU_KeyEncipherment) + CFDictionarySetValue(properties, (const void *)kSecPolicyKU_KeyEncipherment, (const void *)kCFBooleanTrue); + if (usage & CE_KU_DataEncipherment) + CFDictionarySetValue(properties, (const void *)kSecPolicyKU_DataEncipherment, (const void *)kCFBooleanTrue); + if (usage & CE_KU_KeyAgreement) + CFDictionarySetValue(properties, (const void *)kSecPolicyKU_KeyAgreement, (const void *)kCFBooleanTrue); + if (usage & CE_KU_KeyCertSign) + CFDictionarySetValue(properties, (const void *)kSecPolicyKU_KeyCertSign, (const void *)kCFBooleanTrue); + if (usage & CE_KU_CRLSign) + CFDictionarySetValue(properties, (const void *)kSecPolicyKU_CRLSign, (const void *)kCFBooleanTrue); + if (usage & CE_KU_EncipherOnly) + CFDictionarySetValue(properties, (const void *)kSecPolicyKU_EncipherOnly, (const void *)kCFBooleanTrue); + if (usage & CE_KU_DecipherOnly) + CFDictionarySetValue(properties, (const void *)kSecPolicyKU_DecipherOnly, (const void *)kCFBooleanTrue); + } + } + return properties; +} + + +bool Policy::operator < (const Policy& other) const +{ + //@@@ inefficient + return oid() < other.oid() || + oid() == other.oid() && value() < other.value(); +} + +bool Policy::operator == (const Policy& other) const +{ + return oid() == other.oid() && value() == other.value(); +} + +bool Policy::equal(SecCFObject &other) +{ + return (*this) == (const Policy &)other; +} diff --git a/libsecurity_keychain/lib/Policies.h b/libsecurity_keychain/lib/Policies.h new file mode 100644 index 00000000..8dfc4ed2 --- /dev/null +++ b/libsecurity_keychain/lib/Policies.h @@ -0,0 +1,87 @@ +/* + * 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@ + */ + + +// +// Policies.h +// +#ifndef _SECURITY_POLICY_H_ +#define _SECURITY_POLICY_H_ + +#include +#include +#include +#include +#include "SecCFTypes.h" + +namespace Security +{ + +namespace KeychainCore +{ + +using namespace CssmClient; + +// +// A Policy[Impl] represents a particular +// CSSM "policy" managed by a particular TP. +// +class Policy : public SecCFObject +{ + NOCOPY(Policy) +public: + SECCFFUNCTIONS(Policy, SecPolicyRef, errSecInvalidItemRef, gTypes().Policy) + + Policy(TP supportingTp, const CssmOid &policyOid); + +public: + virtual ~Policy() throw(); + + TP &tp() { return mTp; } + const TP &tp() const { return mTp; } + const CssmOid &oid() const { return mOid; } + const CssmData &value() const { return mValue; } + CssmOwnedData &value() { return mValue; } + + void setValue(const CssmData &value); + void setProperties(CFDictionaryRef properties); + CFDictionaryRef properties(); + + bool operator < (const Policy& other) const; + bool operator == (const Policy& other) const; + + bool equal(SecCFObject &other); + +private: + TP mTp; // TP module for this Policy + CssmAutoData mOid; // OID for this policy + CssmAutoData mValue; // value for this policy + CssmAutoData mAuxValue; // variable-length value data for this policy + Mutex mMutex; +}; + +} // end namespace KeychainCore + +} // end namespace Security + +#endif // !_SECURITY_POLICY_H_ diff --git a/libsecurity_keychain/lib/PolicyCursor.cpp b/libsecurity_keychain/lib/PolicyCursor.cpp new file mode 100644 index 00000000..522530fa --- /dev/null +++ b/libsecurity_keychain/lib/PolicyCursor.cpp @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2002-2004,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@ + */ + +// +// PolicyCursor.cpp +// +#include +#include +#include +#include + +using namespace KeychainCore; +using namespace CssmClient; + + +// +// This preliminary implementation bypasses MDS and uses +// a fixed set of policies known to exist in the one known TP. +// +struct TheOneTP : public TP { + TheOneTP() : TP(gGuidAppleX509TP) { } +}; + +static ModuleNexus theOneTP; +static const CssmOid *theOidList[] = { + static_cast(&CSSMOID_APPLE_ISIGN), + static_cast(&CSSMOID_APPLE_X509_BASIC), + static_cast(&CSSMOID_APPLE_TP_SSL), + static_cast(&CSSMOID_APPLE_TP_SMIME), + static_cast(&CSSMOID_APPLE_TP_EAP), + static_cast(&CSSMOID_APPLE_TP_SW_UPDATE_SIGNING), + static_cast(&CSSMOID_APPLE_TP_IP_SEC), + static_cast(&CSSMOID_APPLE_TP_ICHAT), + static_cast(&CSSMOID_APPLE_TP_RESOURCE_SIGN), + static_cast(&CSSMOID_APPLE_TP_PKINIT_CLIENT), + static_cast(&CSSMOID_APPLE_TP_PKINIT_SERVER), + static_cast(&CSSMOID_APPLE_TP_CODE_SIGNING), + static_cast(&CSSMOID_APPLE_TP_PACKAGE_SIGNING), + static_cast(&CSSMOID_APPLE_TP_REVOCATION_CRL), + static_cast(&CSSMOID_APPLE_TP_REVOCATION_OCSP), + static_cast(&CSSMOID_APPLE_TP_MACAPPSTORE_RECEIPT), + static_cast(&CSSMOID_APPLE_TP_APPLEID_SHARING), + static_cast(&CSSMOID_APPLE_TP_TIMESTAMPING), + NULL // sentinel +}; + + +// +// Canonical Construction +// +PolicyCursor::PolicyCursor(const CSSM_OID* oid, const CSSM_DATA* value) + : mOid(Allocator::standard()), mOidGiven(false), mMutex(Mutex::recursive) +{ + if (oid) { + mOid = CssmOid::required(oid); + mOidGiven = true; + } + mSearchPos = 0; +} + + +// +// Destroy +// +PolicyCursor::~PolicyCursor() throw() +{ +} + + +// +// Crank the iterator +// +bool PolicyCursor::next(SecPointer &policy) +{ + StLock_(mMutex); + + while (theOidList[mSearchPos]) { + if (mOidGiven && mOid != *theOidList[mSearchPos]) { + mSearchPos++; + continue; // no oid match + } + // ignoring mValue - not used by current TP + policy = new Policy(theOneTP(), *theOidList[mSearchPos]); + mSearchPos++; // advance cursor + return true; // return next match + } + return false; // end of table, no more matches +} diff --git a/libsecurity_keychain/lib/PolicyCursor.h b/libsecurity_keychain/lib/PolicyCursor.h new file mode 100644 index 00000000..10a9c847 --- /dev/null +++ b/libsecurity_keychain/lib/PolicyCursor.h @@ -0,0 +1,90 @@ +/* + * 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@ + */ + +// +// PolicyCursor.h +// +#ifndef _SECURITY_POLICYCURSOR_H_ +#define _SECURITY_POLICYCURSOR_H_ + +#include +#include +#include +#include +#include +#include "SecCFTypes.h" + +namespace Security +{ + +namespace KeychainCore +{ + +class Policy; + +class PolicyCursor : public SecCFObject +{ + NOCOPY(PolicyCursor) +public: + SECCFFUNCTIONS(PolicyCursor, SecPolicySearchRef, errSecInvalidSearchRef, gTypes().PolicyCursor) + + PolicyCursor(const CSSM_OID* oid, const CSSM_DATA* value); + virtual ~PolicyCursor() throw(); + bool next(SecPointer &policy); + +private: + //CFArrayRef mKeychainSearchList; + //SecKeyUsage mKeyUsage; + //SecPolicyRef mPolicy; + CssmAutoData mOid; + bool mOidGiven; + // value ignored (for now?) + +#if 1 // quick version -- using built-in policy list + + int mSearchPos; // next untried table entry + +#else // MDS version -- later + bool mFirstLookup; + + // + // Initialization + // + MDS_HANDLE mMdsHand; + CSSM_DB_HANDLE mDbHand; + // + // Used for searching (lookups) + // + MDS_DB_HANDLE mObjDlDb; + MDS_DB_HANDLE mCdsaDlDb; + MDS_FUNCS* mMdsFuncs; +#endif + + Mutex mMutex; +}; + +} // end namespace KeychainCore + +} // end namespace Security + +#endif // !_SECURITY_POLICYCURSOR_H_ diff --git a/libsecurity_keychain/lib/PrimaryKey.cpp b/libsecurity_keychain/lib/PrimaryKey.cpp new file mode 100644 index 00000000..92390f13 --- /dev/null +++ b/libsecurity_keychain/lib/PrimaryKey.cpp @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2000-2001,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@ + */ + + +// +// PrimaryKey.cpp +// + +#include "PrimaryKey.h" + +using namespace KeychainCore; +using namespace CssmClient; + + +PrimaryKeyImpl::PrimaryKeyImpl(const CSSM_DATA &data) +: CssmDataContainer(data.Data, data.Length), mMutex(Mutex::recursive) +{ + +//@@@ do bounds checking here, throw if invalid + +} + +PrimaryKeyImpl::PrimaryKeyImpl(const DbAttributes &primaryKeyAttrs) : mMutex(Mutex::recursive) +{ + Length = sizeof(uint32); + for (uint32 ix = 0; ix < primaryKeyAttrs.size(); ++ix) + { + if (primaryKeyAttrs.at(ix).size() == 0) + MacOSError::throwMe(errSecInvalidKeychain); + + Length += sizeof(uint32) + primaryKeyAttrs.at(ix).Value[0].Length; + } + + // Careful with exceptions + Data = mAllocator.alloc(Length); + uint8 *p = Data; + + putUInt32(p, primaryKeyAttrs.recordType()); + for (uint32 ix = 0; ix < primaryKeyAttrs.size(); ++ix) + { + uint32 len = primaryKeyAttrs.at(ix).Value[0].Length; + putUInt32(p, len); + memcpy(p, primaryKeyAttrs.at(ix).Value[0].Data, len); + p += len; + } +} + +CssmClient::DbCursor +PrimaryKeyImpl::createCursor(const Keychain &keychain) +{ + StLock_(mMutex); + DbCursor cursor(keychain->database()); + + // @@@ Set up cursor to find item with this. + uint8 *p = Data; + uint32 left = Length; + if (left < sizeof(*p)) + MacOSError::throwMe(errSecNoSuchAttr); // XXX Not really but whatever. + + CSSM_DB_RECORDTYPE rt = getUInt32(p, left); + const CssmAutoDbRecordAttributeInfo &infos = keychain->primaryKeyInfosFor(rt); + + cursor->recordType(rt); + cursor->conjunctive(CSSM_DB_AND); + for (uint32 ix = 0; ix < infos.size(); ++ix) + { + uint32 len = getUInt32(p, left); + + if (left < len) + MacOSError::throwMe(errSecNoSuchAttr); // XXX Not really but whatever. + + CssmData value(p, len); + left -= len; + p += len; + + cursor->add(CSSM_DB_EQUAL, infos.at(ix), value); + } + + return cursor; +} + + +void +PrimaryKeyImpl::putUInt32(uint8 *&p, uint32 value) +{ + *p++ = (value >> 24); + *p++ = (value >> 16) & 0xff; + *p++ = (value >> 8) & 0xff; + *p++ = value & 0xff; +} + +uint32 +PrimaryKeyImpl::getUInt32(uint8 *&p, uint32 &left) const +{ + if (left < sizeof(uint32)) + MacOSError::throwMe(errSecNoSuchAttr); // XXX Not really but whatever. + + + // @@@ Assumes data written in big endian. + uint32 value = (p[0] << 24) + (p[1] << 16) + (p[2] << 8) + p[3]; + p += sizeof(uint32); + left -= sizeof(uint32); + return value; +} + + + +CSSM_DB_RECORDTYPE +PrimaryKeyImpl::recordType() const +{ + uint8 *data = Data; + uint32 length = Length; + return getUInt32(data, length); +} diff --git a/libsecurity_keychain/lib/PrimaryKey.h b/libsecurity_keychain/lib/PrimaryKey.h new file mode 100644 index 00000000..cde32749 --- /dev/null +++ b/libsecurity_keychain/lib/PrimaryKey.h @@ -0,0 +1,75 @@ +/* + * 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@ + */ + + +// +// PrimaryKey.h +// +#ifndef _SECURITY_PRIMARYKEY_H_ +#define _SECURITY_PRIMARYKEY_H_ + +#include +#include + +namespace Security +{ + +namespace KeychainCore +{ + +class PrimaryKeyImpl : public CssmDataContainer +{ +public: + PrimaryKeyImpl(const CSSM_DATA &data); + PrimaryKeyImpl(const CssmClient::DbAttributes &primaryKeyAttrs); + ~PrimaryKeyImpl() {} + + void putUInt32(uint8 *&p, uint32 value); + uint32 getUInt32(uint8 *&p, uint32 &left) const; + + CssmClient::DbCursor createCursor(const Keychain &keychain); + + CSSM_DB_RECORDTYPE recordType() const; +private: + +protected: + Mutex mMutex; +}; + + +class PrimaryKey : public RefPointer +{ +public: + PrimaryKey() {} + PrimaryKey(PrimaryKeyImpl *impl) : RefPointer(impl) {} + PrimaryKey(const CSSM_DATA &data) + : RefPointer(new PrimaryKeyImpl(data)) {} + PrimaryKey(const CssmClient::DbAttributes &primaryKeyAttrs) + : RefPointer(new PrimaryKeyImpl(primaryKeyAttrs)) {} +}; + +} // end namespace KeychainCore + +} // end namespace Security + +#endif // !_SECURITY_PRIMARYKEY_H_ diff --git a/libsecurity_keychain/lib/SecACL.cpp b/libsecurity_keychain/lib/SecACL.cpp new file mode 100644 index 00000000..3aeeb27d --- /dev/null +++ b/libsecurity_keychain/lib/SecACL.cpp @@ -0,0 +1,294 @@ +/* + * 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@ + */ + +#include +#include +#include +#include + +#include "SecBridge.h" + +// Forward reference +/*! + @function GetACLAuthorizationTagFromString + @abstract Get the CSSM ACL item from the CFString + @param aclStr The String name of the ACL + @result The CSSM ACL value +*/ +sint32 GetACLAuthorizationTagFromString(CFStringRef aclStr); + +CFStringRef GetAuthStringFromACLAuthorizationTag(sint32 tag); + +// +// Local functions +// +static void setApplications(ACL *acl, CFArrayRef applicationList); + +CFTypeID +SecACLGetTypeID(void) +{ + BEGIN_SECAPI + + return gTypes().ACL.typeID; + + END_SECAPI1(_kCFRuntimeNotATypeID) +} + + +/*! + */ +OSStatus SecACLCreateFromSimpleContents(SecAccessRef accessRef, + CFArrayRef applicationList, + CFStringRef description, const CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR *promptSelector, + SecACLRef *newAcl) +{ + BEGIN_SECAPI + SecPointer access = Access::required(accessRef); + SecPointer acl = new ACL(*access, cfString(description), *promptSelector); + if (applicationList) { + // application-list + prompt + acl->form(ACL::appListForm); + setApplications(acl, applicationList); + } else { + // allow-any + acl->form(ACL::allowAllForm); + } + access->add(acl.get()); + Required(newAcl) = acl->handle(); + END_SECAPI +} + +OSStatus SecACLCreateWithSimpleContents(SecAccessRef access, + CFArrayRef applicationList, + CFStringRef description, + SecKeychainPromptSelector promptSelector, + SecACLRef *newAcl) +{ + CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR cdsaPromptSelector; + cdsaPromptSelector.version = CSSM_ACL_KEYCHAIN_PROMPT_CURRENT_VERSION; + cdsaPromptSelector.flags = promptSelector; + return SecACLCreateFromSimpleContents(access, applicationList, description, &cdsaPromptSelector, newAcl); +} + + +/*! + */ +OSStatus SecACLRemove(SecACLRef aclRef) +{ + BEGIN_SECAPI + ACL::required(aclRef)->remove(); + END_SECAPI +} + + +static SecTrustedApplicationRef +convert(const SecPointer &trustedApplication) +{ + return *trustedApplication; +} + +/*! + */ +OSStatus SecACLCopySimpleContents(SecACLRef aclRef, + CFArrayRef *applicationList, + CFStringRef *promptDescription, CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR *promptSelector) +{ + BEGIN_SECAPI + SecPointer acl = ACL::required(aclRef); + switch (acl->form()) { + case ACL::allowAllForm: + Required(applicationList) = NULL; + Required(promptDescription) = + acl->promptDescription().empty() ? NULL + : makeCFString(acl->promptDescription()); + Required(promptSelector) = acl->promptSelector(); + break; + case ACL::appListForm: + Required(applicationList) = + makeCFArray(convert, acl->applications()); + Required(promptDescription) = makeCFString(acl->promptDescription()); + Required(promptSelector) = acl->promptSelector(); + break; + default: + return errSecACLNotSimple; // custom or unknown + } + END_SECAPI +} + +OSStatus SecACLCopyContents(SecACLRef acl, + CFArrayRef *applicationList, + CFStringRef *description, + SecKeychainPromptSelector *promptSelector) +{ + CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR cdsaPromptSelector; + memset(&cdsaPromptSelector, 0, sizeof(cdsaPromptSelector)); + OSStatus err = noErr; + + err = SecACLCopySimpleContents(acl, applicationList, description, &cdsaPromptSelector); + *promptSelector = cdsaPromptSelector.flags; + return err; +} + +OSStatus SecACLSetSimpleContents(SecACLRef aclRef, + CFArrayRef applicationList, + CFStringRef description, const CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR *promptSelector) +{ + BEGIN_SECAPI + SecPointer acl = ACL::required(aclRef); + acl->promptDescription() = description ? cfString(description) : ""; + acl->promptSelector() = promptSelector ? *promptSelector : ACL::defaultSelector; + if (applicationList) { + // application-list + prompt + acl->form(ACL::appListForm); + setApplications(acl, applicationList); + } else { + // allow-any + acl->form(ACL::allowAllForm); + } + acl->modify(); + END_SECAPI +} + +OSStatus SecACLSetContents(SecACLRef acl, + CFArrayRef applicationList, + CFStringRef description, + SecKeychainPromptSelector promptSelector) +{ + CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR cdsaPromptSelector; + cdsaPromptSelector.version = CSSM_ACL_PROCESS_SELECTOR_CURRENT_VERSION; + cdsaPromptSelector.flags = promptSelector; + return SecACLSetSimpleContents(acl, applicationList, description, &cdsaPromptSelector); +} + +// +// Stuff a CFArray-of-SecTrustedApplications into an ACL object +// +static void setApplications(ACL *acl, CFArrayRef applicationList) +{ + ACL::ApplicationList &appList = acl->applications(); + appList.clear(); + //@@@ should really use STL iterator overlay on CFArray. By hand... + CFIndex count = CFArrayGetCount(applicationList); + for (CFIndex n = 0; n < count; n++) + appList.push_back(TrustedApplication::required( + SecTrustedApplicationRef(CFArrayGetValueAtIndex(applicationList, n)))); +} + + +// +// Set and get the authorization tags of an ACL entry +// +OSStatus SecACLGetAuthorizations(SecACLRef acl, + CSSM_ACL_AUTHORIZATION_TAG *tags, uint32 *tagCount) +{ + BEGIN_SECAPI + AclAuthorizationSet auths = ACL::required(acl)->authorizations(); + if (Required(tagCount) < auths.size()) { // overflow + *tagCount = auths.size(); // report size required + CssmError::throwMe(paramErr); + } + *tagCount = auths.size(); + copy(auths.begin(), auths.end(), tags); + END_SECAPI +} + +CFArrayRef SecACLCopyAuthorizations(SecACLRef acl) +{ + CFArrayRef result = NULL; + if (NULL == acl) + { + return result; + } + + AclAuthorizationSet auths = ACL::required(acl)->authorizations(); + uint32 numAuths = auths.size(); + + CSSM_ACL_AUTHORIZATION_TAG* tags = new CSSM_ACL_AUTHORIZATION_TAG[numAuths]; + int i; + for (i = 0; i < numAuths; ++i) + { + tags[i] = NULL; + } + + OSStatus err = SecACLGetAuthorizations(acl, tags, &numAuths); + if (noErr != err) + { + + return result; + } + + CFTypeRef* strings = new CFTypeRef[numAuths]; + for (i = 0; i < numAuths; ++i) + { + strings[i] = NULL; + } + + for (size_t iCnt = 0; iCnt < numAuths; iCnt++) + { + strings[iCnt] = (CFTypeRef)GetAuthStringFromACLAuthorizationTag(tags[iCnt]); + } + + result = CFArrayCreate(kCFAllocatorDefault, (const void **)strings, numAuths, NULL); + + delete[] strings; + delete[] tags; + + return result; + +} + +OSStatus SecACLSetAuthorizations(SecACLRef aclRef, + CSSM_ACL_AUTHORIZATION_TAG *tags, uint32 tagCount) +{ + BEGIN_SECAPI + SecPointer acl = ACL::required(aclRef); + if (acl->isOwner()) // can't change rights of the owner ACL + MacOSError::throwMe(errSecInvalidOwnerEdit); + AclAuthorizationSet &auths = acl->authorizations(); + auths.clear(); + copy(tags, tags + tagCount, insert_iterator(auths, auths.begin())); + acl->modify(); + END_SECAPI +} + +OSStatus SecACLUpdateAuthorizations(SecACLRef acl, CFArrayRef authorizations) +{ + if (NULL == acl || NULL == authorizations) + { + return paramErr; + } + uint32 tagCount = CFArrayGetCount(authorizations); + + size_t tagSize = (tagCount * sizeof(CSSM_ACL_AUTHORIZATION_TAG)); + + CSSM_ACL_AUTHORIZATION_TAG* tags = (CSSM_ACL_AUTHORIZATION_TAG*)malloc(tagSize); + memset(tags, 0, tagSize); + for (uint32 iCnt = 0; iCnt < tagCount; iCnt++) + { + tags[iCnt] = GetACLAuthorizationTagFromString((CFStringRef)CFArrayGetValueAtIndex(authorizations, iCnt)); + } + + OSStatus result = SecACLSetAuthorizations(acl, tags, tagCount); + free(tags); + return result; +} diff --git a/libsecurity_keychain/lib/SecACL.h b/libsecurity_keychain/lib/SecACL.h new file mode 100644 index 00000000..6138adde --- /dev/null +++ b/libsecurity_keychain/lib/SecACL.h @@ -0,0 +1,220 @@ +/* + * 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 SecACL + The functions provided in SecACL are for managing entries in the access control list. + */ + +#ifndef _SECURITY_SECACL_H_ +#define _SECURITY_SECACL_H_ + +#include +#include +#include +#include +#include + + +#if defined(__cplusplus) +extern "C" { +#endif + + typedef uint16 SecKeychainPromptSelector; + enum + { + kSecKeychainPromptRequirePassphase = 0x0001, /* require re-entering of passphrase */ + /* the following bits are ignored by 10.4 and earlier */ + kSecKeychainPromptUnsigned = 0x0010, /* prompt for unsigned clients */ + kSecKeychainPromptUnsignedAct = 0x0020, /* UNSIGNED bit overrides system default */ + kSecKeychainPromptInvalid = 0x0040, /* prompt for invalid signed clients */ + kSecKeychainPromptInvalidAct = 0x0080, + }; + + + /*! + @function SecACLGetTypeID + @abstract Returns the type identifier of SecACL instances. + @result The CFTypeID of SecACL instances. + */ + CFTypeID SecACLGetTypeID(void) + __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_NA); + + /*! + @function SecACLCreateFromSimpleContents + @abstract Creates a new access control list entry from the application list, description, and prompt selector provided and adds it to an item's access. + @param access An access reference. + @param applicationList An array of SecTrustedApplication instances that will be allowed access without prompting. + @param description The human readable name that will be used to refer to this item when the user is prompted. + @param promptSelector A pointer to a CSSM prompt selector. + @param newAcl A pointer to an access control list entry. On return, this points to the reference of the new access control list entry. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion This function is deprecated in 10.7 and later; + use SecACLCreateWithSimpleContents instead. + */ + OSStatus SecACLCreateFromSimpleContents(SecAccessRef access, + CFArrayRef applicationList, + CFStringRef description, const CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR *promptSelector, + SecACLRef *newAcl) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + + /*! + @function SecACLCreateWithSimpleContents + @abstract Creates a new access control list entry from the application list, description, and prompt selector provided and adds it to an item's access. + @param access An access reference. + @param applicationList An array of SecTrustedApplication instances that will be allowed access without prompting. + @param description The human readable name that will be used to refer to this item when the user is prompted. + @param promptSelector A SecKeychainPromptSelector selector. + @param newAcl A pointer to an access control list entry. On return, this points to the reference of the new access control list entry. + @result A result code. See "Security Error Codes" (SecBase.h). + */ + OSStatus SecACLCreateWithSimpleContents(SecAccessRef access, + CFArrayRef applicationList, + CFStringRef description, + SecKeychainPromptSelector promptSelector, + SecACLRef *newAcl) + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); + + /*! + @function SecACLRemove + @abstract Removes the access control list entry specified. + @param aclRef The reference to the access control list entry to remove. + @result A result code. See "Security Error Codes" (SecBase.h). + */ + OSStatus SecACLRemove(SecACLRef aclRef) + __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_NA); + + /*! + @function SecACLCopySimpleContents + @abstract Returns the application list, description, and CSSM prompt selector for a given access control list entry. + @param acl An access control list entry reference. + @param applicationList On return, An array of SecTrustedApplication instances that will be allowed access without prompting, for the given access control list entry. The caller needs to call CFRelease on this array when it's no longer needed. + @param description On return, the human readable name that will be used to refer to this item when the user is prompted, for the given access control list entry. The caller needs to call CFRelease on this string when it's no longer needed. + @param promptSelector A pointer to a CSSM prompt selector. On return, this points to the CSSM prompt selector for the given access control list entry. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion This function is deprecated in 10.7 and later; + use SecACLCopyContents instead. + */ + OSStatus SecACLCopySimpleContents(SecACLRef acl, + CFArrayRef *applicationList, + CFStringRef *description, CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR *promptSelector) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + + /*! + @function SecACLCopyContents + @abstract Returns the application list, description, and prompt selector for a given access control list entry. + @param acl An access control list entry reference. + @param applicationList On return, An array of SecTrustedApplication instances that will be allowed access without prompting, for the given access control list entry. The caller needs to call CFRelease on this array when it's no longer needed. + @param description On return, the human readable name that will be used to refer to this item when the user is prompted, for the given access control list entry. The caller needs to call CFRelease on this string when it's no longer needed. + @param promptSelector A pointer to a SecKeychainPromptSelector. On return, this points to the SecKeychainPromptSelector for the given access control list entry. + @result A result code. See "Security Error Codes" (SecBase.h). + */ + OSStatus SecACLCopyContents(SecACLRef acl, + CFArrayRef *applicationList, + CFStringRef *description, + SecKeychainPromptSelector *promptSelector) + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); + /*! + @function SecACLSetSimpleContents + @abstract Sets the application list, description, and CSSM prompt selector for a given access control list entry. + @param acl A reference to the access control list entry to edit. + @param applicationList An application list reference. + @param description The human readable name that will be used to refer to this item when the user is prompted. + @param promptSelector A pointer to a CSSM prompt selector. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion This function is deprecated in 10.7 and later; + use SecACLSetContents instead. + */ + OSStatus SecACLSetSimpleContents(SecACLRef acl, + CFArrayRef applicationList, + CFStringRef description, const CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR *promptSelector) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + + /*! + @function SecACLSetContents + @abstract Sets the application list, description, and prompt selector for a given access control list entry. + @param acl A reference to the access control list entry to edit. + @param applicationList An application list reference. + @param description The human readable name that will be used to refer to this item when the user is prompted. + @param promptSelector A SecKeychainPromptSelector selector. + @result A result code. See "Security Error Codes" (SecBase.h). + */ + OSStatus SecACLSetContents(SecACLRef acl, + CFArrayRef applicationList, + CFStringRef description, + SecKeychainPromptSelector promptSelector) + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); + + /*! + @function SecACLGetAuthorizations + @abstract Retrieve the CSSM authorization tags of a given access control list entry. + @param acl An access control list entry reference. + @param tags On return, this points to the first item in an array of CSSM authorization tags. + @param tagCount On return, this points to the number of tags in the CSSM authorization tag array. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion This function is deprecated in 10.7 and later; + use SecACLCopyAuthorizations instead. + */ + OSStatus SecACLGetAuthorizations(SecACLRef acl, + CSSM_ACL_AUTHORIZATION_TAG *tags, uint32 *tagCount) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + + /*! + @function SecACLCopyAuthorizations + @abstract Retrieve the authorization tags of a given access control list entry. + @param acl An access control list entry reference. + @result On return, a CFArrayRef of the authorizations for this ACL. + */ + CFArrayRef SecACLCopyAuthorizations(SecACLRef acl) + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); + + /*! + @function SecACLSetAuthorizations + @abstract Sets the CSSM authorization tags of a given access control list entry. + @param acl An access control list entry reference. + @param tags A pointer to the first item in an array of CSSM authorization tags. + @param tagCount The number of tags in the CSSM authorization tag array. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion This function is deprecated in 10.7 and later; + use SecACLUpdateAuthorizations instead. + */ + OSStatus SecACLSetAuthorizations(SecACLRef acl, + CSSM_ACL_AUTHORIZATION_TAG *tags, uint32 tagCount) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + + + /*! + @function SecACLUpdateAuthorizations + @abstract Sets the authorization tags of a given access control list entry. + @param acl An access control list entry reference. + @param authorizations A pointer to an array of authorization tags. + @result A result code. See "Security Error Codes" (SecBase.h). + */ + OSStatus SecACLUpdateAuthorizations(SecACLRef acl, CFArrayRef authorizations) + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); + +#if defined(__cplusplus) +} +#endif + +#endif /* !_SECURITY_SECACL_H_ */ diff --git a/libsecurity_keychain/lib/SecAccess.cpp b/libsecurity_keychain/lib/SecAccess.cpp new file mode 100644 index 00000000..ada2817b --- /dev/null +++ b/libsecurity_keychain/lib/SecAccess.cpp @@ -0,0 +1,673 @@ +/* + * 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@ + */ + +#include +#include +#include +#include "SecBridge.h" +#include + +/* No restrictions. Permission to perform all operations on + the resource or available to an ACL owner. */ + + +CFTypeRef kSecACLAuthorizationAny = (CFTypeRef)(CFSTR("ACLAuthorizationAny")); + +CFTypeRef kSecACLAuthorizationLogin = (CFTypeRef)(CFSTR("ACLAuthorizationLogin")); +CFTypeRef kSecACLAuthorizationGenKey = (CFTypeRef)(CFSTR("ACLAuthorizationGenKey")); +CFTypeRef kSecACLAuthorizationDelete = (CFTypeRef)(CFSTR("ACLAuthorizationDelete")); +CFTypeRef kSecACLAuthorizationExportWrapped = (CFTypeRef)(CFSTR("ACLAuthorizationExportWrapped")); +CFTypeRef kSecACLAuthorizationExportClear = (CFTypeRef)(CFSTR("ACLAuthorizationExportClear")); +CFTypeRef kSecACLAuthorizationImportWrapped = (CFTypeRef)(CFSTR("ACLAuthorizationImportWrapped")); +CFTypeRef kSecACLAuthorizationImportClear = (CFTypeRef)(CFSTR("ACLAuthorizationImportClear")); +CFTypeRef kSecACLAuthorizationSign = (CFTypeRef)(CFSTR("ACLAuthorizationSign")); +CFTypeRef kSecACLAuthorizationEncrypt = (CFTypeRef)(CFSTR("ACLAuthorizationEncrypt")); +CFTypeRef kSecACLAuthorizationDecrypt = (CFTypeRef)(CFSTR("ACLAuthorizationDecrypt")); +CFTypeRef kSecACLAuthorizationMAC = (CFTypeRef)(CFSTR("ACLAuthorizationMAC")); +CFTypeRef kSecACLAuthorizationDerive = (CFTypeRef)(CFSTR("ACLAuthorizationDerive")); + +/* Defined authorization tag values for Keychain */ + + + +CFTypeRef kSecACLAuthorizationKeychainCreate = (CFTypeRef)(CFSTR("ACLAuthorizationKeychainCreate")); +CFTypeRef kSecACLAuthorizationKeychainDelete = (CFTypeRef)(CFSTR("ACLAuthorizationKeychainDelete")); +CFTypeRef kSecACLAuthorizationKeychainItemRead = (CFTypeRef)(CFSTR("ACLAuthorizationKeychainItemRead")); +CFTypeRef kSecACLAuthorizationKeychainItemInsert = (CFTypeRef)(CFSTR("ACLAuthorizationKeychainItemInsert")); +CFTypeRef kSecACLAuthorizationKeychainItemModify = (CFTypeRef)(CFSTR("ACLAuthorizationKeychainItemModify")); +CFTypeRef kSecACLAuthorizationKeychainItemDelete = (CFTypeRef)(CFSTR("ACLAuthorizationKeychainItemDelete")); + +CFTypeRef kSecACLAuthorizationChangeACL = (CFTypeRef)(CFSTR("ACLAuthorizationChangeACL")); +CFTypeRef kSecACLAuthorizationChangeOwner = (CFTypeRef)(CFSTR("ACLAuthorizationChangeOwner")); + + +static CFArrayRef copyTrustedAppListFromBundle(CFStringRef bundlePath, CFStringRef trustedAppListFileName); + +static CFStringRef gKeys[] = +{ + (CFStringRef)kSecACLAuthorizationAny, + (CFStringRef)kSecACLAuthorizationLogin, + (CFStringRef)kSecACLAuthorizationGenKey, + (CFStringRef)kSecACLAuthorizationDelete, + (CFStringRef)kSecACLAuthorizationExportWrapped, + (CFStringRef)kSecACLAuthorizationExportClear, + (CFStringRef)kSecACLAuthorizationImportWrapped, + (CFStringRef)kSecACLAuthorizationImportClear, + (CFStringRef)kSecACLAuthorizationSign, + (CFStringRef)kSecACLAuthorizationEncrypt, + (CFStringRef)kSecACLAuthorizationDecrypt, + (CFStringRef)kSecACLAuthorizationMAC, + (CFStringRef)kSecACLAuthorizationDerive, + + /* Defined authorization tag values for Keychain */ + (CFStringRef)kSecACLAuthorizationKeychainCreate, + (CFStringRef)kSecACLAuthorizationKeychainDelete, + (CFStringRef)kSecACLAuthorizationKeychainItemRead, + (CFStringRef)kSecACLAuthorizationKeychainItemInsert, + (CFStringRef)kSecACLAuthorizationKeychainItemModify, + (CFStringRef)kSecACLAuthorizationKeychainItemDelete, + + (CFStringRef)kSecACLAuthorizationChangeACL, + (CFStringRef)kSecACLAuthorizationChangeOwner + +}; + +static sint32 gValues[] = +{ + CSSM_ACL_AUTHORIZATION_ANY, + CSSM_ACL_AUTHORIZATION_LOGIN, + CSSM_ACL_AUTHORIZATION_GENKEY, + CSSM_ACL_AUTHORIZATION_DELETE, + CSSM_ACL_AUTHORIZATION_EXPORT_WRAPPED, + CSSM_ACL_AUTHORIZATION_EXPORT_CLEAR, + CSSM_ACL_AUTHORIZATION_IMPORT_WRAPPED, + CSSM_ACL_AUTHORIZATION_IMPORT_CLEAR, + CSSM_ACL_AUTHORIZATION_SIGN, + CSSM_ACL_AUTHORIZATION_ENCRYPT, + CSSM_ACL_AUTHORIZATION_DECRYPT, + CSSM_ACL_AUTHORIZATION_MAC, + CSSM_ACL_AUTHORIZATION_DERIVE, + CSSM_ACL_AUTHORIZATION_DBS_CREATE, + CSSM_ACL_AUTHORIZATION_DBS_DELETE, + CSSM_ACL_AUTHORIZATION_DB_READ, + CSSM_ACL_AUTHORIZATION_DB_INSERT, + CSSM_ACL_AUTHORIZATION_DB_MODIFY, + CSSM_ACL_AUTHORIZATION_DB_DELETE, + CSSM_ACL_AUTHORIZATION_CHANGE_ACL, + CSSM_ACL_AUTHORIZATION_CHANGE_OWNER +}; + +CFDictionaryRef CreateStringToNumDictionary() +{ + int numItems = (sizeof(gValues) / sizeof(sint32)); + CFMutableDictionaryRef tempDict = CFDictionaryCreateMutable(kCFAllocatorDefault, numItems, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + + for (int iCnt = 0; iCnt < numItems; iCnt++) + { + sint32 aNumber = gValues[iCnt]; + CFNumberRef aNum = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &aNumber); + + CFStringRef aString = gKeys[iCnt]; + CFDictionaryAddValue(tempDict, aString, aNum); + CFRelease(aNum); + } + + CFDictionaryRef result = CFDictionaryCreateCopy(kCFAllocatorDefault, tempDict); + CFRelease(tempDict); + return result; + +} + +CFDictionaryRef CreateNumToStringDictionary() +{ + int numItems = (sizeof(gValues) / sizeof(sint32)); + + CFMutableDictionaryRef tempDict = CFDictionaryCreateMutable(kCFAllocatorDefault, numItems, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + + for (int iCnt = 0; iCnt < numItems; iCnt++) + { + sint32 aNumber = gValues[iCnt]; + CFNumberRef aNum = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &aNumber); + + CFStringRef aString = gKeys[iCnt]; + CFDictionaryAddValue(tempDict, aNum, aString); + CFRelease(aNum); + + } + + CFDictionaryRef result = CFDictionaryCreateCopy(kCFAllocatorDefault, tempDict); + CFRelease(tempDict); + return result; +} + + + +sint32 GetACLAuthorizationTagFromString(CFStringRef aclStr) +{ + if (NULL == aclStr) + { +#ifndef NDEBUG + CFShow(CFSTR("GetACLAuthorizationTagFromString aclStr is NULL")); +#endif + return 0; + } + + static CFDictionaryRef gACLMapping = NULL; + + if (NULL == gACLMapping) + { + gACLMapping = CreateStringToNumDictionary(); + } + + sint32 result = 0; + CFNumberRef valueResult = (CFNumberRef)CFDictionaryGetValue(gACLMapping, aclStr); + if (NULL != valueResult) + { + if (!CFNumberGetValue(valueResult, kCFNumberSInt32Type, &result)) + { + return 0; + } + + } + else + { + return 0; + } + + return result; + +} + +CFStringRef GetAuthStringFromACLAuthorizationTag(sint32 tag) +{ + static CFDictionaryRef gTagMapping = NULL; + CFNumberRef aNum = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &tag); + + if (NULL == gTagMapping) + { + gTagMapping = CreateNumToStringDictionary(); + } + + CFStringRef result = (CFStringRef)kSecACLAuthorizationAny; + + if (NULL != gTagMapping && CFDictionaryContainsKey(gTagMapping, aNum)) + { + result = (CFStringRef)CFDictionaryGetValue(gTagMapping, aNum); + } + return result; +} + +// +// CF boilerplate +// +CFTypeID SecAccessGetTypeID(void) +{ + BEGIN_SECAPI + return gTypes().Access.typeID; + END_SECAPI1(_kCFRuntimeNotATypeID) +} + + +// +// API bridge calls +// +/*! + * Create a new SecAccessRef that is set to the default configuration + * of a (newly created) security object. + */ +OSStatus SecAccessCreate(CFStringRef descriptor, CFArrayRef trustedList, SecAccessRef *accessRef) +{ + BEGIN_SECAPI + Required(descriptor); + SecPointer access; + if (trustedList) { + CFIndex length = CFArrayGetCount(trustedList); + ACL::ApplicationList trusted; + for (CFIndex n = 0; n < length; n++) + trusted.push_back(TrustedApplication::required( + SecTrustedApplicationRef(CFArrayGetValueAtIndex(trustedList, n)))); + access = new Access(cfString(descriptor), trusted); + } else { + access = new Access(cfString(descriptor)); + } + Required(accessRef) = access->handle(); + END_SECAPI +} + + +/*! + */ +OSStatus SecAccessCreateFromOwnerAndACL(const CSSM_ACL_OWNER_PROTOTYPE *owner, + uint32 aclCount, const CSSM_ACL_ENTRY_INFO *acls, + SecAccessRef *accessRef) +{ + BEGIN_SECAPI + Required(accessRef); // preflight + SecPointer access = new Access(Required(owner), aclCount, &Required(acls)); + *accessRef = access->handle(); + END_SECAPI +} + +SecAccessRef SecAccessCreateWithOwnerAndACL(uid_t userId, gid_t groupId, SecAccessOwnerType ownerType, CFArrayRef acls, CFErrorRef *error) +{ + SecAccessRef result = NULL; + + CSSM_ACL_PROCESS_SUBJECT_SELECTOR selector = + { + CSSM_ACL_PROCESS_SELECTOR_CURRENT_VERSION, // selector version + ownerType, + userId, + groupId + }; + + CSSM_LIST_ELEMENT subject2 = { NULL, 0 }; + subject2.Element.Word.Data = (UInt8 *)&selector; + subject2.Element.Word.Length = sizeof(selector); + CSSM_LIST_ELEMENT subject1 = + { + &subject2, CSSM_ACL_SUBJECT_TYPE_PROCESS, CSSM_LIST_ELEMENT_WORDID + }; + + CFIndex numAcls = 0; + + if (NULL != acls) + { + numAcls = CFArrayGetCount(acls); + } + +#ifndef NDEBUG + CFStringRef debugStr = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, + CFSTR("SecAccessCreateWithOwnerAndACL: processing %d acls"), numAcls); + CFShow(debugStr); + CFRelease(debugStr); +#endif + + CSSM_ACL_AUTHORIZATION_TAG rights[numAcls]; + memset(rights, 0, sizeof(rights)); + + for (CFIndex iCnt = 0; iCnt < numAcls; iCnt++) + { + CFStringRef aclStr = (CFStringRef)CFArrayGetValueAtIndex(acls, iCnt); + +#ifndef NDEBUG + debugStr = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, + CFSTR("SecAccessCreateWithOwnerAndACL: acls[%d] = %@"), iCnt, aclStr); + + CFShow(debugStr); + CFRelease(debugStr); +#endif + + CSSM_ACL_AUTHORIZATION_TAG aTag = GetACLAuthorizationTagFromString(aclStr); + +#ifndef NDEBUG + debugStr = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, + CFSTR("SecAccessCreateWithOwnerAndACL: rights[%d] = %d"), iCnt, aTag); + + CFShow(debugStr); + CFRelease(debugStr); +#endif + + rights[iCnt] = aTag; + } + + + for (CFIndex iCnt = 0; iCnt < numAcls; iCnt++) + { +#ifndef NDEBUG + debugStr = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, + CFSTR("SecAccessCreateWithOwnerAndACL: rights[%d] = %d"), iCnt, rights[iCnt]); + + CFShow(debugStr); + CFRelease(debugStr); +#endif + + + } + + CSSM_ACL_OWNER_PROTOTYPE owner = + { + // TypedSubject + { CSSM_LIST_TYPE_UNKNOWN, &subject1, &subject2 }, + // Delegate + false + }; + + + // ACL entries (any number, just one here) + CSSM_ACL_ENTRY_INFO acl_rights[] = + { + { + // prototype + { + // TypedSubject + { CSSM_LIST_TYPE_UNKNOWN, &subject1, &subject2 }, + false, // Delegate + // rights for this entry + { sizeof(rights) / sizeof(rights[0]), rights }, + // rest is defaulted + } + } + }; + + OSStatus err = SecAccessCreateFromOwnerAndACL(&owner, + sizeof(acl_rights) / sizeof(acl_rights[0]), acl_rights, &result); + + if (noErr != err) + { + result = NULL; + if (NULL != error) + { + *error = CFErrorCreate(kCFAllocatorDefault, CFSTR("FIX ME"), err, NULL); + } + } + return result; +} + + +/*! + */ +OSStatus SecAccessGetOwnerAndACL(SecAccessRef accessRef, + CSSM_ACL_OWNER_PROTOTYPE_PTR *owner, + uint32 *aclCount, CSSM_ACL_ENTRY_INFO_PTR *acls) +{ + BEGIN_SECAPI + Access::required(accessRef)->copyOwnerAndAcl( + Required(owner), Required(aclCount), Required(acls)); + END_SECAPI +} + +OSStatus SecAccessCopyOwnerAndACL(SecAccessRef accessRef, uid_t* userId, gid_t* groupId, SecAccessOwnerType* ownerType, CFArrayRef* aclList) +{ + CSSM_ACL_OWNER_PROTOTYPE_PTR owner = NULL; + CSSM_ACL_ENTRY_INFO_PTR acls = NULL; + uint32 aclCount = 0; + OSStatus result = SecAccessGetOwnerAndACL(accessRef, &owner, &aclCount, &acls); + if (noErr != result ) + { + return result; + } + + if (NULL != owner) + { + CSSM_LIST_ELEMENT_PTR listHead = owner->TypedSubject.Head; + if (listHead != NULL && listHead->ElementType == CSSM_LIST_ELEMENT_WORDID) + { + CSSM_LIST_ELEMENT_PTR nextElement = listHead->NextElement; + if (listHead->WordID == CSSM_ACL_SUBJECT_TYPE_PROCESS && listHead->ElementType == CSSM_LIST_ELEMENT_WORDID) + { + // nextElement contains the required data + CSSM_ACL_PROCESS_SUBJECT_SELECTOR* selectorPtr = (CSSM_ACL_PROCESS_SUBJECT_SELECTOR*)nextElement->Element.Word.Data; + if (NULL != selectorPtr) + { + if (NULL != userId) + { + *userId = (uid_t)selectorPtr->uid; + } + + if (NULL != groupId) + { + *groupId = (gid_t)selectorPtr->gid; + } + + if (NULL != ownerType) + { + *ownerType = (SecAccessOwnerType)selectorPtr->mask; + } + } + } + + } + + } + + if (NULL != aclList) + { +#ifndef NDEBUG + CFShow(CFSTR("SecAccessCopyOwnerAndACL: processing the ACL list")); +#endif + + CFMutableArrayRef stringArray = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); + CSSM_ACL_OWNER_PROTOTYPE_PTR protoPtr = NULL; + uint32 numAcls = 0L; + CSSM_ACL_ENTRY_INFO_PTR aclEntry = NULL; + + result = SecAccessGetOwnerAndACL(accessRef, &protoPtr, &numAcls, &aclEntry); + if (noErr == result) + { +#ifndef NDEBUG + CFStringRef tempStr = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("SecAccessCopyOwnerAndACL: numAcls = %d"), numAcls); + CFShow(tempStr); + CFRelease(tempStr); +#endif + + for (uint32 iCnt = 0; iCnt < numAcls; iCnt++) + { + CSSM_ACL_ENTRY_PROTOTYPE prototype = aclEntry[iCnt].EntryPublicInfo; + CSSM_AUTHORIZATIONGROUP authGroup = prototype.Authorization; + int numAuthTags = (int)authGroup.NumberOfAuthTags; + + for (int jCnt = 0; jCnt < numAuthTags; jCnt++) + { + + sint32 aTag = authGroup.AuthTags[jCnt]; + CFStringRef aString = GetAuthStringFromACLAuthorizationTag(aTag); + + CFArrayAppendValue(stringArray, aString); + } + } + } + + if (NULL != stringArray) + { + if (0 < CFArrayGetCount(stringArray)) + { + *aclList = CFArrayCreateCopy(kCFAllocatorDefault, stringArray); + } + CFRelease(stringArray); + } + } + + return result; +} + +/*! + */ +OSStatus SecAccessCopyACLList(SecAccessRef accessRef, + CFArrayRef *aclList) +{ + BEGIN_SECAPI + Required(aclList) = Access::required(accessRef)->copySecACLs(); + END_SECAPI +} + + +/*! + */ +OSStatus SecAccessCopySelectedACLList(SecAccessRef accessRef, + CSSM_ACL_AUTHORIZATION_TAG action, + CFArrayRef *aclList) +{ + BEGIN_SECAPI + Required(aclList) = Access::required(accessRef)->copySecACLs(action); + END_SECAPI +} + +CFArrayRef SecAccessCopyMatchingACLList(SecAccessRef accessRef, CFTypeRef authorizationTag) +{ + CFArrayRef result = NULL; + CSSM_ACL_AUTHORIZATION_TAG tag = GetACLAuthorizationTagFromString((CFStringRef)authorizationTag); + OSStatus err = SecAccessCopySelectedACLList(accessRef, tag, &result); + if (noErr != err) + { + result = NULL; + } + return result; +} + +CFArrayRef copyTrustedAppListFromBundle(CFStringRef bundlePath, CFStringRef trustedAppListFileName) +{ + CFStringRef errorString = nil; + CFURLRef bundleURL,trustedAppsURL = NULL; + CFBundleRef secBundle = NULL; + CFPropertyListRef trustedAppsPlist = NULL; + CFDataRef xmlDataRef = NULL; + SInt32 errorCode; + CFArrayRef trustedAppList = NULL; + CFMutableStringRef trustedAppListFileNameWithoutExtension = NULL; + + // Make a CFURLRef from the CFString representation of the bundleÕs path. + bundleURL = CFURLCreateWithFileSystemPath( + kCFAllocatorDefault,bundlePath,kCFURLPOSIXPathStyle,true); + + CFRange wholeStrRange; + + if (!bundleURL) + goto xit; + + // Make a bundle instance using the URLRef. + secBundle = CFBundleCreate(kCFAllocatorDefault,bundleURL); + if (!secBundle) + goto xit; + + trustedAppListFileNameWithoutExtension = + CFStringCreateMutableCopy(NULL,CFStringGetLength(trustedAppListFileName),trustedAppListFileName); + wholeStrRange = CFStringFind(trustedAppListFileName,CFSTR(".plist"),0); + + CFStringDelete(trustedAppListFileNameWithoutExtension,wholeStrRange); + + // Look for a resource in the bundle by name and type + trustedAppsURL = CFBundleCopyResourceURL(secBundle,trustedAppListFileNameWithoutExtension,CFSTR("plist"),NULL); + if (!trustedAppsURL) + goto xit; + + if ( trustedAppListFileNameWithoutExtension ) + CFRelease(trustedAppListFileNameWithoutExtension); + + if (!CFURLCreateDataAndPropertiesFromResource(kCFAllocatorDefault,trustedAppsURL,&xmlDataRef,NULL,NULL,&errorCode)) + goto xit; + + trustedAppsPlist = CFPropertyListCreateFromXMLData(kCFAllocatorDefault,xmlDataRef,kCFPropertyListImmutable,&errorString); + trustedAppList = (CFArrayRef)trustedAppsPlist; + +xit: + if (bundleURL) + CFRelease(bundleURL); + if (secBundle) + CFRelease(secBundle); + if (trustedAppsURL) + CFRelease(trustedAppsURL); + if (xmlDataRef) + CFRelease(xmlDataRef); + if (errorString) + CFRelease(errorString); + + return trustedAppList; +} + +OSStatus SecAccessCreateWithTrustedApplications(CFStringRef trustedApplicationsPListPath, CFStringRef accessLabel, Boolean allowAny, SecAccessRef* returnedAccess) +{ + OSStatus err = noErr; + SecAccessRef accessToReturn=nil; + CFMutableArrayRef 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=NULL, someOther=NULL; + CFArrayRef trustedAppListFromBundle=NULL; + + trustedApplications=CFArrayCreateMutable(kCFAllocatorDefault,0,&kCFTypeArrayCallBacks); + err = SecTrustedApplicationCreateFromPath(NULL, &myself); + if (!err) + CFArrayAppendValue(trustedApplications,myself); + + CFURLRef url = CFURLCreateWithFileSystemPath(NULL, trustedApplicationsPListPath, kCFURLPOSIXPathStyle, 0); + CFStringRef leafStr = NULL; + leafStr = CFURLCopyLastPathComponent(url); + + CFURLRef bndlPathURL = NULL; + bndlPathURL = CFURLCreateCopyDeletingLastPathComponent(NULL, url); + CFStringRef bndlPath = NULL; + bndlPath = CFURLCopyFileSystemPath(bndlPathURL, kCFURLPOSIXPathStyle); + trustedAppListFromBundle=copyTrustedAppListFromBundle(bndlPath, leafStr); + if ( leafStr ) + CFRelease(leafStr); + if ( bndlPath ) + CFRelease(bndlPath); + if ( url ) + CFRelease(url); + if ( bndlPathURL ) + CFRelease(bndlPathURL); + if (trustedAppListFromBundle) + { + int ix,top; + char buffer[MAXPATHLEN]; + top = CFArrayGetCount(trustedAppListFromBundle); + for (ix=0;ix +#include +#include +#include +#include +#include + + +#if defined(__cplusplus) +extern "C" { +#endif + + + +typedef UInt32 SecAccessOwnerType; +enum +{ + kSecUseOnlyUID = 1, + kSecUseOnlyGID = 2, + kSecHonorRoot = 0x100, + kSecMatchBits = (kSecUseOnlyUID | kSecUseOnlyGID) +}; + +/* No restrictions. Permission to perform all operations on + the resource or available to an ACL owner. */ +extern CFTypeRef kSecACLAuthorizationAny + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); + +extern CFTypeRef kSecACLAuthorizationLogin + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecACLAuthorizationGenKey + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecACLAuthorizationDelete + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecACLAuthorizationExportWrapped + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecACLAuthorizationExportClear + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecACLAuthorizationImportWrapped + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecACLAuthorizationImportClear + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecACLAuthorizationSign + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecACLAuthorizationEncrypt + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecACLAuthorizationDecrypt + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecACLAuthorizationMAC + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecACLAuthorizationDerive + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); + +/* Defined authorization tag values for Keychain */ +extern CFTypeRef kSecACLAuthorizationKeychainCreate + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecACLAuthorizationKeychainDelete + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecACLAuthorizationKeychainItemRead + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecACLAuthorizationKeychainItemInsert + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecACLAuthorizationKeychainItemModify + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecACLAuthorizationKeychainItemDelete + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); + +extern CFTypeRef kSecACLAuthorizationChangeACL + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecACLAuthorizationChangeOwner + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); + + +/*! + @function SecAccessGetTypeID + @abstract Returns the type identifier of SecAccess instances. + @result The CFTypeID of SecAccess instances. +*/ +CFTypeID SecAccessGetTypeID(void); + +/*! + @function SecAccessCreate + @abstract Creates a new SecAccessRef that is set to the currently designated system default + configuration of a (newly created) security object. Note that the precise nature of + this default may change between releases. + @param descriptor The name of the item as it should appear in security dialogs + @param trustedlist A CFArray of TrustedApplicationRefs, specifying which applications + should be allowed to access an item without triggering confirmation dialogs. + If NULL, defaults to (just) the application creating the item. To set no applications, + pass a CFArray with no elements. + @param accessRef On return, a pointer to the new access reference. + @result A result code. See "Security Error Codes" (SecBase.h). +*/ +OSStatus SecAccessCreate(CFStringRef descriptor, CFArrayRef trustedlist, SecAccessRef *accessRef); + +/*! + @function SecAccessCreateFromOwnerAndACL + @abstract Creates a new SecAccessRef using the owner and access control list you provide. + @param owner A pointer to a CSSM access control list owner. + @param aclCount An unsigned 32-bit integer representing the number of items in the access control list. + @param acls A pointer to the access control list. + @param On return, a pointer to the new access reference. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion For 10.7 and later please use the SecAccessCreateWithOwnerAndACL API +*/ +OSStatus SecAccessCreateFromOwnerAndACL(const CSSM_ACL_OWNER_PROTOTYPE *owner, uint32 aclCount, const CSSM_ACL_ENTRY_INFO *acls, SecAccessRef *accessRef) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/*! + @function SecAccessCreateWithOwnerAndACL + @abstract Creates a new SecAccessRef using either for a user or a group with a list of ACLs + @param userId An user id that specifies the user to associate with this SecAccessRef. + @param groupId A group id that specifies the group to associate with this SecAccessRef. + @param ownerType Specifies the how the ownership of the new SecAccessRef is defined. + @param acls A CFArrayRef of the ACLs to associate with this SecAccessRef + @param error Optionally a pointer to a CFErrorRef to return any errors with may have occured + @result A pointer to the new access reference. +*/ +SecAccessRef SecAccessCreateWithOwnerAndACL(uid_t userId, gid_t groupId, SecAccessOwnerType ownerType, CFArrayRef acls, CFErrorRef *error) + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); + +/*! + @function SecAccessGetOwnerAndACL + @abstract Retrieves the owner and the access control list of a given access. + @param accessRef A reference to the access from which to retrieve the information. + @param owner On return, a pointer to the access control list owner. + @param aclCount On return, a pointer to an unsigned 32-bit integer representing the number of items in the access control list. + @param acls On return, a pointer to the access control list. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion For 10.7 and later please use the SecAccessCopyOwnerAndACL API + */ +OSStatus SecAccessGetOwnerAndACL(SecAccessRef accessRef, CSSM_ACL_OWNER_PROTOTYPE_PTR *owner, uint32 *aclCount, CSSM_ACL_ENTRY_INFO_PTR *acls) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/*! + @function SecAccessCopyOwnerAndACL + @abstract Retrieves the owner and the access control list of a given access. + @param accessRef A reference to the access from which to retrieve the information. + @param userId On return, the user id of the owner + @param groupId On return, the group id of the owner + @param ownerType On return, the type of owner for this AccessRef + @param aclCount On return, a Boolean that if true specifies that the ownerId is a uid_t else it is a gid_t. + @param aclList On return, a pointer to a new created CFArray of SecACL instances. The caller is responsible for calling CFRelease on this array. + @result A result code. See "Security Error Codes" (SecBase.h). + */ +OSStatus SecAccessCopyOwnerAndACL(SecAccessRef accessRef, uid_t* userId, gid_t* groupId, SecAccessOwnerType* ownerType, CFArrayRef* aclList) + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); + +/*! + @function SecAccessCopyACLList + @abstract Copies all the access control lists of a given access. + @param accessRef A reference to the access from which to retrieve the information. + @param aclList On return, a pointer to a new created CFArray of SecACL instances. The caller is responsible for calling CFRelease on this array. + @result A result code. See "Security Error Codes" (SecBase.h). +*/ +OSStatus SecAccessCopyACLList(SecAccessRef accessRef, CFArrayRef *aclList); + +/*! + @function SecAccessCopySelectedACLList + @abstract Copies selected access control lists from a given access. + @param accessRef A reference to the access from which to retrieve the information. + @param action An authorization tag specifying what action with which to select the action control lists. + @param aclList On return, a pointer to the selected access control lists. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion For 10.7 and later please use the SecAccessCopyMatchingACLList API +*/ +OSStatus SecAccessCopySelectedACLList(SecAccessRef accessRef, CSSM_ACL_AUTHORIZATION_TAG action, CFArrayRef *aclList) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + + +/*! + @function SecAccessCopyMatchingACLList + @abstract Copies selected access control lists from a given access. + @param accessRef A reference to the access from which to retrieve the information. + @param authorizationTag An authorization tag specifying what action with which to select the action control lists. + @result A pointer to the selected access control lists. +*/ +CFArrayRef SecAccessCopyMatchingACLList(SecAccessRef accessRef, CFTypeRef authorizationTag) + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); + +#if defined(__cplusplus) +} +#endif + +#endif /* !_SECURITY_SECACCESS_H_ */ diff --git a/libsecurity_keychain/lib/SecAccessPriv.h b/libsecurity_keychain/lib/SecAccessPriv.h new file mode 100644 index 00000000..e96eaefc --- /dev/null +++ b/libsecurity_keychain/lib/SecAccessPriv.h @@ -0,0 +1,76 @@ +/* + * 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 SecAccessPriv + SecAccessPriv implements a way to set and manipulate access control rules and + restrictions on SecKeychainItems. The functions here are private. +*/ + +#ifndef _SECURITY_SECACCESS_PRIV_H_ +#define _SECURITY_SECACCESS_PRIV_H_ + +#include +#include +#include + + +#if defined(__cplusplus) +extern "C" { +#endif + +/*! + @function SecKeychainAddIToolsPassword + @abstract Creates a new iTools password using the access control list from iToolsTrustedApps.plist. + @param keychain A reference to the keychain to which to add the password. Pass NULL to add the password to the default keychain. + @param accountNameLength The length of the buffer pointed to by accountName. + @param accountName A pointer to a string containing the account name associated with this password. + @param passwordLength The length of the buffer pointed to by passwordData. + @param passwordData A pointer to a buffer containing the password data to be stored in the keychain. + @param itemRef On return, a reference to the new keychain item. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion The SecKeychainAddIToolsPassword function adds a new iTools password to the specified keychain with an ACL composed of a list of trusted applications. A required parameter to identify the password is the accountName, which is an application-defined string. The servicename will always be "iTools". SecKeychainAddIToolsPassword optionally returns a reference to the newly added item. +*/ + +OSStatus SecKeychainAddIToolsPassword(SecKeychainRef keychain, UInt32 accountNameLength, const char *accountName, + UInt32 passwordLength, const void *passwordData, SecKeychainItemRef *itemRef); + +/*! + @function SecAccessCreateWithTrustedApplications + @abstract Creates a SecAccess object with the specified trusted applications. + @param trustedApplicationsPListPath A full path to the .plist file that contains the trusted applications. The extension must end in ".plist". + @param accessLabel The access label for the new SecAccessRef. + @param allowAny Flag that determines allow access to any application. + @param returnedAccess On return, a new SecAccessRef. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion The SecAccessCreateWithPList creates a SecAccess with the provided list of trusted applications. +*/ + +OSStatus SecAccessCreateWithTrustedApplications(CFStringRef trustedApplicationsPListPath, CFStringRef accessLabel, Boolean allowAny, SecAccessRef* returnedAccess); + + +#if defined(__cplusplus) +} +#endif + +#endif /* !_SECURITY_SECACCESS_PRIV_H_ */ diff --git a/libsecurity_keychain/lib/SecAsn1TypesP.h b/libsecurity_keychain/lib/SecAsn1TypesP.h new file mode 100644 index 00000000..2a027acb --- /dev/null +++ b/libsecurity_keychain/lib/SecAsn1TypesP.h @@ -0,0 +1,241 @@ +/* + * 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. + */ + +/* + * Types for encoding/decoding of ASN.1 using BER/DER (Basic/Distinguished + * Encoding Rules). + */ + +#ifndef _SEC_ASN1_TYPES_H_ +#define _SEC_ASN1_TYPES_H_ + +#include /* Boolean */ +#include +#include + +#include +#if 1 /* TARGET_OS_EMBEDDED */ +/* @@@ We need something that tells us which platform we are building + for that let's us distinguish if we are doing an emulator build. */ + +typedef struct { + size_t Length; + uint8_t *Data; +} SecAsn1Item, SecAsn1Oid; + +typedef struct { + SecAsn1Oid algorithm; + SecAsn1Item parameters; +} SecAsn1AlgId; + +typedef struct { + SecAsn1AlgId algorithm; + SecAsn1Item subjectPublicKey; +} SecAsn1PubKeyInfo; + +#else +#include +#include + +typedef CSSM_DATA SecAsn1Item; +typedef CSSM_OID SecAsn1Oid; +typedef CSSM_X509_ALGORITHM_IDENTIFIER SecAsn1AlgId; +typedef CSSM_X509_SUBJECT_PUBLIC_KEY_INFO SecAsn1PubKeyInfo; + +#endif + +/* + * An array of these structures defines a BER/DER encoding for an object. + * + * The array usually starts with a dummy entry whose kind is SEC_ASN1_SEQUENCE; + * such an array is terminated with an entry where kind == 0. (An array + * which consists of a single component does not require a second dummy + * entry -- the array is only searched as long as previous component(s) + * instruct it.) + */ +typedef struct SecAsn1Template_struct { + /* + * Kind of item being decoded/encoded, including tags and modifiers. + */ + uint32_t kind; + + /* + * This value is the offset from the base of the structure (i.e., the + * (void *) passed as 'src' to SecAsn1EncodeItem, or the 'dst' argument + * passed to SecAsn1CoderRef()) to the field that holds the value being + * decoded/encoded. + */ + uint32_t offset; + + /* + * When kind suggests it (e.g., SEC_ASN1_POINTER, SEC_ASN1_GROUP, + * SEC_ASN1_INLINE, or a component that is *not* a SEC_ASN1_UNIVERSAL), + * this points to a sub-template for nested encoding/decoding. + * OR, iff SEC_ASN1_DYNAMIC is set, then this is a pointer to a pointer + * to a function which will return the appropriate template when called + * at runtime. NOTE! that explicit level of indirection, which is + * necessary because ANSI does not allow you to store a function + * pointer directly as a "void *" so we must store it separately and + * dereference it to get at the function pointer itself. + */ + const void *sub; + + /* + * In the first element of a template array, the value is the size + * of the structure to allocate when this template is being referenced + * by another template via SEC_ASN1_POINTER or SEC_ASN1_GROUP. + * In all other cases, the value is ignored. + */ + uint32_t size; +} SecAsn1Template; + + +/* + * BER/DER values for ASN.1 identifier octets. + */ +#define SEC_ASN1_TAG_MASK 0xff + +/* + * BER/DER universal type tag numbers. + */ +#define SEC_ASN1_TAGNUM_MASK 0x1f +#define SEC_ASN1_BOOLEAN 0x01 +#define SEC_ASN1_INTEGER 0x02 +#define SEC_ASN1_BIT_STRING 0x03 +#define SEC_ASN1_OCTET_STRING 0x04 +#define SEC_ASN1_NULL 0x05 +#define SEC_ASN1_OBJECT_ID 0x06 +#define SEC_ASN1_OBJECT_DESCRIPTOR 0x07 +/* External type and instance-of type 0x08 */ +#define SEC_ASN1_REAL 0x09 +#define SEC_ASN1_ENUMERATED 0x0a +#define SEC_ASN1_EMBEDDED_PDV 0x0b +#define SEC_ASN1_UTF8_STRING 0x0c +/* not used 0x0d */ +/* not used 0x0e */ +/* not used 0x0f */ +#define SEC_ASN1_SEQUENCE 0x10 +#define SEC_ASN1_SET 0x11 +#define SEC_ASN1_NUMERIC_STRING 0x12 +#define SEC_ASN1_PRINTABLE_STRING 0x13 +#define SEC_ASN1_T61_STRING 0x14 +#define SEC_ASN1_VIDEOTEX_STRING 0x15 +#define SEC_ASN1_IA5_STRING 0x16 +#define SEC_ASN1_UTC_TIME 0x17 +#define SEC_ASN1_GENERALIZED_TIME 0x18 +#define SEC_ASN1_GRAPHIC_STRING 0x19 +#define SEC_ASN1_VISIBLE_STRING 0x1a +#define SEC_ASN1_GENERAL_STRING 0x1b +#define SEC_ASN1_UNIVERSAL_STRING 0x1c +/* not used 0x1d */ +#define SEC_ASN1_BMP_STRING 0x1e +#define SEC_ASN1_HIGH_TAG_NUMBER 0x1f +#define SEC_ASN1_TELETEX_STRING SEC_ASN1_T61_STRING + +/* + * Modifiers to type tags. These are also specified by a/the + * standard, and must not be changed. + */ +#define SEC_ASN1_METHOD_MASK 0x20 +#define SEC_ASN1_PRIMITIVE 0x00 +#define SEC_ASN1_CONSTRUCTED 0x20 + +#define SEC_ASN1_CLASS_MASK 0xc0 +#define SEC_ASN1_UNIVERSAL 0x00 +#define SEC_ASN1_APPLICATION 0x40 +#define SEC_ASN1_CONTEXT_SPECIFIC 0x80 +#define SEC_ASN1_PRIVATE 0xc0 + +/* + * Our additions, used for templates. + * These are not defined by any standard; the values are used internally only. + * Just be careful to keep them out of the low 8 bits. + */ +#define SEC_ASN1_OPTIONAL 0x00100 +#define SEC_ASN1_EXPLICIT 0x00200 +#define SEC_ASN1_ANY 0x00400 +#define SEC_ASN1_INLINE 0x00800 +#define SEC_ASN1_POINTER 0x01000 +#define SEC_ASN1_GROUP 0x02000 /* with SET or SEQUENCE means + * SET OF or SEQUENCE OF */ +#define SEC_ASN1_DYNAMIC 0x04000 /* subtemplate is found by calling + * a function at runtime */ +#define SEC_ASN1_SKIP 0x08000 /* skip a field; only for decoding */ +#define SEC_ASN1_INNER 0x10000 /* with ANY means capture the + * contents only (not the id, len, + * or eoc); only for decoding */ +#define SEC_ASN1_SAVE 0x20000 /* stash away the encoded bytes first; + * only for decoding */ +#define SEC_ASN1_SKIP_REST 0x80000 /* skip all following fields; + * only for decoding */ +#define SEC_ASN1_CHOICE 0x100000 /* pick one from a template */ + +/* + * Indicate that a type SEC_ASN1_INTEGER is actually signed. + * The default is unsigned, which causes a leading zero to be + * encoded if the MS bit of the source data is 1. + */ +#define SEC_ASN1_SIGNED_INT 0X800000 + +/* Shorthand/Aliases */ +#define SEC_ASN1_SEQUENCE_OF (SEC_ASN1_GROUP | SEC_ASN1_SEQUENCE) +#define SEC_ASN1_SET_OF (SEC_ASN1_GROUP | SEC_ASN1_SET) +#define SEC_ASN1_ANY_CONTENTS (SEC_ASN1_ANY | SEC_ASN1_INNER) + +/* + * Function used for SEC_ASN1_DYNAMIC. + * "arg" is a pointer to the top-level structure being encoded or + * decoded. + * + * "enc" when true, means that we are encoding (false means decoding) + * + * "buf" For decode only; points to the start of the decoded data for + * the current template. Callee can use the tag at this location + * to infer the returned template. Not used on encode. + * + * "Dest" points to the template-specific item being decoded to + * or encoded from. (This is as opposed to arg, which + * points to the start of the struct associated with the + * current array of templates). + */ + +typedef const SecAsn1Template * SecAsn1TemplateChooser( + void *arg, + Boolean enc, + const char *buf, + void *dest); + +typedef SecAsn1TemplateChooser * SecAsn1TemplateChooserPtr; + + +#endif /* _SEC_ASN1_TYPES_H_ */ diff --git a/libsecurity_keychain/lib/SecBase.cpp b/libsecurity_keychain/lib/SecBase.cpp new file mode 100644 index 00000000..299de837 --- /dev/null +++ b/libsecurity_keychain/lib/SecBase.cpp @@ -0,0 +1,1119 @@ +/* + * 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@ + */ + +#include +#include +#include +#include "SecBridge.h" + +static CFStringRef copyErrorMessageFromBundle(OSStatus status,CFStringRef tableName); + +// caller MUST release the string, since it is gotten with "CFCopyLocalizedStringFromTableInBundle" +// intended use of reserved param is to pass in CFStringRef with name of the Table for lookup +// Will look by default in "SecErrorMessages.strings" in the resources of Security.framework. + + +CFStringRef +SecCopyErrorMessageString(OSStatus status, void *reserved) +{ + try + { + CFStringRef result = copyErrorMessageFromBundle(status,CFSTR("SecErrorMessages")); + if (result == NULL) + result = copyErrorMessageFromBundle(status,CFSTR("SecDebugErrorMessages")); + + if (result == NULL) + { + if (status >= errSecErrnoBase && status <= errSecErrnoLimit) + { + result = CFStringCreateWithFormat (NULL, NULL, CFSTR("UNIX[%s]"), strerror(status-errSecErrnoBase)); + } + else + { + // no error message found, so format a faked-up error message from the status + result = CFStringCreateWithFormat(NULL, NULL, CFSTR("OSStatus %d"), status); + } + } + + return result; + } + catch (...) + { + return NULL; + } +} + + +void +cssmPerror(const char *how, CSSM_RETURN error) +{ + try + { + const char* errMsg = cssmErrorString(error); + fprintf(stderr, "%s: %s\n", how ? how : "error", errMsg); + } + catch (...) + { + fprintf(stderr, "failed to print error: %lu\n", (unsigned long)error); + } +} + + +const char * +cssmErrorString(CSSM_RETURN error) +{ + static ThreadNexus lastError; + + try { + string err; + + if (error >= errSecErrnoBase && error <= errSecErrnoLimit) + { + err = string ("UNIX[") + strerror(error - errSecErrnoBase) + "]"; + } + else + { + CFStringRef result = copyErrorMessageFromBundle(error,CFSTR("SecErrorMessages")); + if (result == NULL) + result = copyErrorMessageFromBundle(error,CFSTR("SecDebugErrorMessages")); + err = cfString(result, true); + } + + if (err.empty()) + { + char buf[200]; + snprintf(buf, sizeof(buf), "unknown error %ld=%lx", (long) error, (long) error); + err = buf; + } + + lastError() = err; + return lastError().c_str(); + } + catch (...) + { + char buf[256]; + snprintf (buf, sizeof (buf), "unknown error %ld=%lx", (long) error, (long) error); + lastError() = buf; + return lastError().c_str(); + } +} + + +static ModuleNexus gBundleLock; + +CFStringRef +copyErrorMessageFromBundle(OSStatus status,CFStringRef tableName) +{ + StLock _lock(gBundleLock()); + + CFStringRef errorString = nil; + CFStringRef keyString = nil; + CFBundleRef secBundle = NULL; + + // Make a bundle instance using the URLRef. + secBundle = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.security")); + if (!secBundle) + goto xit; + + // Convert status to Int32 string representation, e.g. "-25924" + keyString = CFStringCreateWithFormat (kCFAllocatorDefault,NULL,CFSTR("%d"),status); + if (!keyString) + goto xit; + + errorString = CFCopyLocalizedStringFromTableInBundle(keyString,tableName,secBundle,NULL); + if (CFStringCompare(errorString, keyString, 0)==kCFCompareEqualTo) // no real error message + { + if (errorString) + CFRelease(errorString); + errorString = nil; + } +xit: + if (keyString) + CFRelease(keyString); + + return errorString; +} + +/* Convert a possible CSSM type osStatus error to a more Keychain friendly OSStatus. */ +OSStatus SecKeychainErrFromOSStatus(OSStatus osStatus) +{ + if (CSSM_ERR_IS_CONVERTIBLE(osStatus)) + { + switch (CSSM_ERRCODE(osStatus)) + { + // CONVERTIBLE ERROR CODES. + case CSSM_ERRCODE_SERVICE_NOT_AVAILABLE: + return errSecNotAvailable; + case CSSM_ERRCODE_USER_CANCELED: + return userCanceledErr; + case CSSM_ERRCODE_OPERATION_AUTH_DENIED: + return errSecAuthFailed; + case CSSM_ERRCODE_NO_USER_INTERACTION: + return errSecInteractionNotAllowed; + case CSSM_ERRCODE_IN_DARK_WAKE: + return errSecInDarkWake; + case CSSM_ERRCODE_OS_ACCESS_DENIED: + return wrPermErr; + case CSSM_ERRCODE_INSUFFICIENT_CLIENT_IDENTIFICATION: + return errSecInsufficientClientID; + case CSSM_ERRCODE_DEVICE_RESET: + return errSecDeviceReset; + case CSSM_ERRCODE_DEVICE_FAILED: + return errSecDeviceFailed; + case CSSM_ERRCODE_INTERNAL_ERROR: + return errSecInternalError; + case CSSM_ERRCODE_MEMORY_ERROR: + return errSecMemoryError; + case CSSM_ERRCODE_MDS_ERROR: + return errSecMDSError; + case CSSM_ERRCODE_INVALID_POINTER: + case CSSM_ERRCODE_INVALID_INPUT_POINTER: + case CSSM_ERRCODE_INVALID_OUTPUT_POINTER: + case CSSM_ERRCODE_INVALID_CERTGROUP_POINTER: + case CSSM_ERRCODE_INVALID_CERT_POINTER: + case CSSM_ERRCODE_INVALID_CRL_POINTER: + case CSSM_ERRCODE_INVALID_FIELD_POINTER: + case CSSM_ERRCODE_INVALID_DB_LIST_POINTER: + return errSecInvalidPointer; + case CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED: + return errSecUnimplemented; + case CSSM_ERRCODE_SELF_CHECK_FAILED: + case CSSMERR_CL_SELF_CHECK_FAILED: + case CSSMERR_DL_SELF_CHECK_FAILED: + return errSecSelfCheckFailed; + case CSSM_ERRCODE_FUNCTION_FAILED: + return errSecFunctionFailed; + case CSSM_ERRCODE_MODULE_MANIFEST_VERIFY_FAILED: + return errSecModuleManifestVerifyFailed; + case CSSM_ERRCODE_INVALID_GUID: + return errSecInvalidGUID; + case CSSM_ERRCODE_OBJECT_USE_AUTH_DENIED: + case CSSM_ERRCODE_OBJECT_MANIP_AUTH_DENIED: + return errAuthorizationDenied; + case CSSM_ERRCODE_OBJECT_ACL_NOT_SUPPORTED: + case CSSM_ERRCODE_OBJECT_ACL_REQUIRED: + case CSSM_ERRCODE_INVALID_ACL_SUBJECT_VALUE: + case CSSM_ERRCODE_ACL_SUBJECT_TYPE_NOT_SUPPORTED: + case CSSM_ERRCODE_INVALID_ACL_EDIT_MODE: + case CSSM_ERRCODE_INVALID_NEW_ACL_ENTRY: + case CSSM_ERRCODE_INVALID_NEW_ACL_OWNER: + return errSecInvalidACL; + case CSSM_ERRCODE_INVALID_ACCESS_CREDENTIALS: + return errSecInvalidAccessCredentials; + case CSSM_ERRCODE_INVALID_ACL_BASE_CERTS: + case CSSM_ERRCODE_ACL_BASE_CERTS_NOT_SUPPORTED: + return errSecInvalidCertificateGroup; + case CSSM_ERRCODE_INVALID_SAMPLE_VALUE: + return errSecInvalidSampleValue; + case CSSM_ERRCODE_SAMPLE_VALUE_NOT_SUPPORTED: + return errSecInvalidSampleValue; + case CSSM_ERRCODE_INVALID_ACL_CHALLENGE_CALLBACK: + return errSecInvalidCallback; + case CSSM_ERRCODE_ACL_CHALLENGE_CALLBACK_FAILED: + return errSecCallbackFailed; + case CSSM_ERRCODE_INVALID_ACL_ENTRY_TAG: + case CSSM_ERRCODE_UNKNOWN_TAG: + return errSecUnknownTag; + case CSSM_ERRCODE_ACL_ENTRY_TAG_NOT_FOUND: + return errSecTagNotFound; + case CSSM_ERRCODE_ACL_CHANGE_FAILED: + return errSecACLChangeFailed; + case CSSM_ERRCODE_ACL_DELETE_FAILED: + return errSecACLDeleteFailed; + case CSSM_ERRCODE_ACL_REPLACE_FAILED: + return errSecACLReplaceFailed; + case CSSM_ERRCODE_ACL_ADD_FAILED: + return errSecACLAddFailed; + case CSSM_ERRCODE_INVALID_CONTEXT_HANDLE: + case CSSM_ERRCODE_INVALID_DB_HANDLE: + case CSSM_ERRCODE_INVALID_CSP_HANDLE: + case CSSM_ERRCODE_INVALID_DL_HANDLE: + case CSSM_ERRCODE_INVALID_CL_HANDLE: + case CSSM_ERRCODE_INVALID_TP_HANDLE: + case CSSM_ERRCODE_INVALID_KR_HANDLE: + case CSSM_ERRCODE_INVALID_AC_HANDLE: + return errSecInvalidHandle; + case CSSM_ERRCODE_INCOMPATIBLE_VERSION: + return errSecIncompatibleVersion; + case CSSM_ERRCODE_INVALID_DATA: + return errSecInvalidData; + case CSSM_ERRCODE_CRL_ALREADY_SIGNED: + return errSecCRLAlreadySigned; + case CSSM_ERRCODE_INVALID_NUMBER_OF_FIELDS: + return errSecInvalidNumberOfFields; + case CSSM_ERRCODE_VERIFICATION_FAILURE: + return errSecVerificationFailure; + case CSSM_ERRCODE_PRIVILEGE_NOT_GRANTED: + return errSecPrivilegeNotGranted; + case CSSM_ERRCODE_INVALID_DB_LIST: + return errSecInvalidDBList; + case CSSM_ERRCODE_UNKNOWN_FORMAT: + return errSecUnknownFormat; + case CSSM_ERRCODE_INVALID_PASSTHROUGH_ID: + return errSecInvalidPassthroughID; + case CSSM_ERRCODE_INVALID_NETWORK_ADDR: + return errSecInvalidNetworkAddress; + case CSSM_ERRCODE_INVALID_CRYPTO_DATA: + return errSecInvalidData; + } + } + switch (osStatus) + { + // Some CSSM errors mapped to OSStatus-type (SnowLeopard and earlier). + // + case CSSMERR_DL_RECORD_NOT_FOUND: + case CSSMERR_APPLETP_CERT_NOT_FOUND_FROM_ISSUER: + case CSSMERR_CSP_PRIVATE_KEY_NOT_FOUND: + return errSecItemNotFound; + case CSSMERR_DL_INVALID_UNIQUE_INDEX_DATA: + case CSSMERR_CSP_PRIVATE_KEY_ALREADY_EXISTS: + case CSSMERR_CSP_KEY_LABEL_ALREADY_EXISTS: + return errSecDuplicateItem; + case CSSMERR_DL_DATABASE_CORRUPT: + return errSecInvalidKeychain; + case CSSMERR_DL_DATASTORE_DOESNOT_EXIST: + return errSecNoSuchKeychain; + case CSSMERR_DL_DATASTORE_ALREADY_EXISTS: + return errSecDuplicateKeychain; + case CSSMERR_APPLEDL_DISK_FULL: + return dskFulErr; + case CSSMERR_DL_INVALID_OPEN_PARAMETERS: + case CSSMERR_APPLEDL_INVALID_OPEN_PARAMETERS: + case CSSMERR_APPLE_DOTMAC_REQ_SERVER_PARAM: + return errSecParam; + case CSSMERR_DL_INVALID_FIELD_NAME: + case CSSMERR_CSSM_INVALID_ATTRIBUTE: + return errSecNoSuchAttr; + case CSSMERR_DL_OS_ACCESS_DENIED: + case CSSMERR_CSP_OS_ACCESS_DENIED: + case CSSMERR_TP_OS_ACCESS_DENIED: + case CSSMERR_AC_OS_ACCESS_DENIED: + case CSSMERR_CL_OS_ACCESS_DENIED: + return wrPermErr; + case CSSMERR_CSSM_BUFFER_TOO_SMALL: + return errSecBufferTooSmall; + case CSSMERR_CSSM_FUNCTION_NOT_IMPLEMENTED: + case CSSMERR_CSP_FUNCTION_NOT_IMPLEMENTED: + case CSSMERR_TP_FUNCTION_NOT_IMPLEMENTED: + case CSSMERR_AC_FUNCTION_NOT_IMPLEMENTED: + case CSSMERR_CL_FUNCTION_NOT_IMPLEMENTED: + case CSSMERR_DL_FUNCTION_NOT_IMPLEMENTED: + case CSSMERR_APPLE_DOTMAC_REQ_SERVER_UNIMPL: + return errSecUnimplemented; + case CSSMERR_CSSM_INTERNAL_ERROR: + case CSSMERR_CSP_INTERNAL_ERROR: + case CSSMERR_TP_INTERNAL_ERROR: + case CSSMERR_AC_INTERNAL_ERROR: + case CSSMERR_CL_INTERNAL_ERROR: + case CSSMERR_DL_INTERNAL_ERROR: + return errSecInternalError; + case CSSMERR_CSSM_MEMORY_ERROR: + case CSSMERR_CSP_MEMORY_ERROR: + case CSSMERR_TP_MEMORY_ERROR: + case CSSMERR_AC_MEMORY_ERROR: + case CSSMERR_CSP_DEVICE_MEMORY_ERROR: + case CSSMERR_CL_MEMORY_ERROR: + case CSSMERR_DL_MEMORY_ERROR: + return errSecMemoryError; + case CSSMERR_CSSM_MDS_ERROR: + case CSSMERR_CSP_MDS_ERROR: + case CSSMERR_TP_MDS_ERROR: + case CSSMERR_AC_MDS_ERROR: + case CSSMERR_CL_MDS_ERROR: + case CSSMERR_DL_MDS_ERROR: + return errSecMDSError; + case CSSMERR_CSSM_INVALID_POINTER: + case CSSMERR_CSP_INVALID_POINTER: + case CSSMERR_TP_INVALID_POINTER: + case CSSMERR_AC_INVALID_POINTER: + case CSSMERR_CL_INVALID_POINTER: + case CSSMERR_DL_INVALID_POINTER: + case CSSMERR_CSSM_INVALID_INPUT_POINTER: + case CSSMERR_CSP_INVALID_INPUT_POINTER: + case CSSMERR_TP_INVALID_INPUT_POINTER: + case CSSMERR_AC_INVALID_INPUT_POINTER: + case CSSMERR_CL_INVALID_INPUT_POINTER: + case CSSMERR_DL_INVALID_INPUT_POINTER: + case CSSMERR_TP_INVALID_DB_LIST_POINTER: + case CSSMERR_AC_INVALID_DB_LIST_POINTER: + case CSSMERR_DL_INVALID_DB_LIST_POINTER: + case CSSMERR_TP_INVALID_CERTGROUP_POINTER: + case CSSMERR_TP_INVALID_CERT_POINTER: + case CSSMERR_TP_INVALID_CRL_POINTER: + case CSSMERR_TP_INVALID_FIELD_POINTER: + case CSSMERR_CSP_INVALID_KEY_POINTER: + case CSSMERR_TP_INVALID_CALLERAUTH_CONTEXT_POINTER: + case CSSMERR_TP_INVALID_IDENTIFIER_POINTER: + case CSSMERR_TP_INVALID_CRLGROUP_POINTER: + case CSSMERR_TP_INVALID_TUPLEGROUP_POINTER: + case CSSMERR_CL_INVALID_CERTGROUP_POINTER: + case CSSMERR_CL_INVALID_CERT_POINTER: + case CSSMERR_CL_INVALID_CRL_POINTER: + case CSSMERR_CL_INVALID_FIELD_POINTER: + case CSSMERR_CL_INVALID_BUNDLE_POINTER: + case CSSMERR_CSSM_INVALID_OUTPUT_POINTER: + case CSSMERR_CSP_INVALID_OUTPUT_POINTER: + case CSSMERR_TP_INVALID_OUTPUT_POINTER: + case CSSMERR_AC_INVALID_OUTPUT_POINTER: + case CSSMERR_CL_INVALID_OUTPUT_POINTER: + case CSSMERR_DL_INVALID_OUTPUT_POINTER: + return errSecInvalidPointer; + case CSSMERR_CSSM_FUNCTION_FAILED: + case CSSMERR_CSP_FUNCTION_FAILED: + case CSSMERR_TP_FUNCTION_FAILED: + case CSSMERR_AC_FUNCTION_FAILED: + case CSSMERR_CL_FUNCTION_FAILED: + case CSSMERR_DL_FUNCTION_FAILED: + return errSecFunctionFailed; + case CSSMERR_CSP_INVALID_DATA: + case CSSMERR_TP_INVALID_DATA: + case CSSMERR_AC_INVALID_DATA: + case CSSMERR_CL_INVALID_DATA: + case CSSMERR_CSP_INVALID_CRYPTO_DATA: + case CSSMERR_CSP_INVALID_DATA_COUNT: + case CSSMERR_TP_INVALID_ACTION_DATA: + return errSecInvalidData; + case CSSMERR_TP_INVALID_DB_LIST: + case CSSMERR_AC_INVALID_DB_LIST: + return errSecInvalidDBList; + case CSSMERR_CSP_INVALID_PASSTHROUGH_ID: + case CSSMERR_TP_INVALID_PASSTHROUGH_ID: + case CSSMERR_AC_INVALID_PASSTHROUGH_ID: + case CSSMERR_CL_INVALID_PASSTHROUGH_ID: + case CSSMERR_DL_INVALID_PASSTHROUGH_ID: + return errSecInvalidPassthroughID; + case CSSMERR_TP_INVALID_CSP_HANDLE: + case CSSMERR_TP_INVALID_CL_HANDLE: + case CSSMERR_TP_INVALID_DL_HANDLE: + case CSSMERR_AC_INVALID_TP_HANDLE: + case CSSMERR_AC_INVALID_DL_HANDLE: + case CSSMERR_DL_INVALID_DL_HANDLE: + case CSSMERR_AC_INVALID_CL_HANDLE: + case CSSMERR_DL_INVALID_CL_HANDLE: + case CSSMERR_DL_INVALID_CSP_HANDLE: + case CSSMERR_TP_INVALID_DB_HANDLE: + case CSSMERR_CSSM_INVALID_ADDIN_HANDLE: + case CSSMERR_CSSM_INVALID_CONTEXT_HANDLE: + case CSSMERR_CL_INVALID_CACHE_HANDLE: + case CSSMERR_CL_INVALID_RESULTS_HANDLE: + case CSSMERR_DL_INVALID_RESULTS_HANDLE: + case CSSMERR_TP_INVALID_KEYCACHE_HANDLE: + case CSSMERR_CSP_INVALID_CONTEXT_HANDLE: + case CSSMERR_TP_INVALID_CONTEXT_HANDLE: + case CSSMERR_AC_INVALID_CONTEXT_HANDLE: + case CSSMERR_CL_INVALID_CONTEXT_HANDLE: + return errSecInvalidHandle; + case CSSMERR_TP_CRL_ALREADY_SIGNED: + case CSSMERR_CL_CRL_ALREADY_SIGNED: + return errSecCRLAlreadySigned; + case CSSMERR_TP_INVALID_NUMBER_OF_FIELDS: + case CSSMERR_CL_INVALID_NUMBER_OF_FIELDS: + return errSecInvalidNumberOfFields; + case CSSMERR_TP_VERIFICATION_FAILURE: + case CSSMERR_CL_VERIFICATION_FAILURE: + return errSecVerificationFailure; + case CSSMERR_TP_INVALID_NETWORK_ADDR: + case CSSMERR_DL_INVALID_NETWORK_ADDR: + return errSecInvalidNetworkAddress; + case CSSMERR_TP_UNKNOWN_TAG: + case CSSMERR_CL_UNKNOWN_TAG: + case CSSMERR_CSP_INVALID_ACL_ENTRY_TAG: + case CSSMERR_DL_INVALID_ACL_ENTRY_TAG: + case CSSMERR_DL_INVALID_SELECTION_TAG: + return errSecUnknownTag; + case CSSMERR_CSP_INVALID_SIGNATURE: + case CSSMERR_TP_INVALID_SIGNATURE: + return errSecInvalidSignature; + case CSSMERR_CSSM_USER_CANCELED: + case CSSMERR_CSP_USER_CANCELED: + case CSSMERR_TP_USER_CANCELED: + case CSSMERR_AC_USER_CANCELED: + case CSSMERR_CL_USER_CANCELED: + case CSSMERR_DL_USER_CANCELED: + return userCanceledErr; + case CSSMERR_CSSM_NO_USER_INTERACTION: + case CSSMERR_CSP_NO_USER_INTERACTION: + case CSSMERR_TP_NO_USER_INTERACTION: + case CSSMERR_AC_NO_USER_INTERACTION: + case CSSMERR_CL_NO_USER_INTERACTION: + case CSSMERR_DL_NO_USER_INTERACTION: + return errSecInteractionNotAllowed; + case CSSMERR_CSSM_IN_DARK_WAKE: + case CSSMERR_CSP_IN_DARK_WAKE: + case CSSMERR_TP_IN_DARK_WAKE: + case CSSMERR_AC_IN_DARK_WAKE: + case CSSMERR_CL_IN_DARK_WAKE: + case CSSMERR_DL_IN_DARK_WAKE: + return errSecInDarkWake; + case CSSMERR_CSSM_SERVICE_NOT_AVAILABLE: + case CSSMERR_CSP_SERVICE_NOT_AVAILABLE: + case CSSMERR_TP_SERVICE_NOT_AVAILABLE: + case CSSMERR_AC_SERVICE_NOT_AVAILABLE: + case CSSMERR_CL_SERVICE_NOT_AVAILABLE: + case CSSMERR_DL_SERVICE_NOT_AVAILABLE: + return errSecServiceNotAvailable; + case CSSMERR_CSSM_INSUFFICIENT_CLIENT_IDENTIFICATION: + case CSSMERR_CSP_INSUFFICIENT_CLIENT_IDENTIFICATION: + case CSSMERR_TP_INSUFFICIENT_CLIENT_IDENTIFICATION: + case CSSMERR_AC_INSUFFICIENT_CLIENT_IDENTIFICATION: + case CSSMERR_CL_INSUFFICIENT_CLIENT_IDENTIFICATION: + case CSSMERR_DL_INSUFFICIENT_CLIENT_IDENTIFICATION: + return errSecInsufficientClientID; + case CSSMERR_CSSM_DEVICE_RESET: + case CSSMERR_CSP_DEVICE_RESET: + case CSSMERR_TP_DEVICE_RESET: + case CSSMERR_AC_DEVICE_RESET: + case CSSMERR_CL_DEVICE_RESET: + case CSSMERR_DL_DEVICE_RESET: + return errSecDeviceReset; + case CSSMERR_CSSM_DEVICE_FAILED: + case CSSMERR_CSP_DEVICE_FAILED: + case CSSMERR_TP_DEVICE_FAILED: + case CSSMERR_AC_DEVICE_FAILED: + case CSSMERR_CL_DEVICE_FAILED: + case CSSMERR_DL_DEVICE_FAILED: + return errSecDeviceFailed; + case CSSMERR_APPLE_DOTMAC_REQ_SERVER_AUTH: + case CSSMERR_CSSM_EMM_AUTHENTICATE_FAILED: + case CSSMERR_CSSM_ADDIN_AUTHENTICATE_FAILED: + case CSSMERR_CSP_OPERATION_AUTH_DENIED: + case CSSMERR_CSP_OBJECT_USE_AUTH_DENIED: + case CSSMERR_CSP_OBJECT_MANIP_AUTH_DENIED: + case CSSMERR_TP_AUTHENTICATION_FAILED: + case CSSMERR_DL_OPERATION_AUTH_DENIED: + case CSSMERR_DL_OBJECT_USE_AUTH_DENIED: + case CSSMERR_DL_OBJECT_MANIP_AUTH_DENIED: + return errAuthorizationDenied; + case CSSMERR_CSSM_SCOPE_NOT_SUPPORTED: + case CSSMERR_CL_SCOPE_NOT_SUPPORTED: + case CSSMERR_CL_INVALID_SCOPE: + return errSecInvalidScope; + case CSSMERR_TP_INVALID_NAME: + case CSSMERR_DL_INVALID_DB_NAME: + return errSecInvalidName; + case CSSMERR_APPLETP_BAD_CERT_FROM_ISSUER: + case CSSMERR_TP_INVALID_CERTIFICATE: + case CSSMERR_TP_INVALID_ANCHOR_CERT: + case CSSMERR_APPLETP_CRL_INVALID_ANCHOR_CERT: + case CSSMERR_APPLETP_OCSP_INVALID_ANCHOR_CERT: + return errSecInvalidCertificateRef; + case CSSMERR_CSP_ACL_ENTRY_TAG_NOT_FOUND: + case CSSMERR_DL_ACL_ENTRY_TAG_NOT_FOUND: + return errSecTagNotFound; + case CSSMERR_DL_UNSUPPORTED_QUERY: + case CSSMERR_DL_INVALID_QUERY: + return errSecInvalidQuery; + case CSSMERR_CSP_INVALID_ACL_CHALLENGE_CALLBACK: + case CSSMERR_TP_INVALID_CALLBACK: + case CSSMERR_DL_INVALID_ACL_CHALLENGE_CALLBACK: + return errSecInvalidCallback; + case CSSMERR_CSP_ACL_CHALLENGE_CALLBACK_FAILED: + case CSSMERR_CSP_CRYPTO_DATA_CALLBACK_FAILED: + case CSSMERR_DL_ACL_CHALLENGE_CALLBACK_FAILED: + return errSecCallbackFailed; + case CSSMERR_TP_INVALID_CERTGROUP: + case CSSMERR_TP_CERTGROUP_INCOMPLETE: + case CSSMERR_DL_INVALID_ACL_BASE_CERTS: + case CSSMERR_DL_ACL_BASE_CERTS_NOT_SUPPORTED: + case CSSMERR_CSP_INVALID_ACL_BASE_CERTS: + return errSecInvalidCertificateGroup; + case CSSMERR_CSP_ACL_DELETE_FAILED: + case CSSMERR_DL_ACL_DELETE_FAILED: + return errSecACLDeleteFailed; + case CSSMERR_CSP_ACL_REPLACE_FAILED: + case CSSMERR_DL_ACL_REPLACE_FAILED: + return errSecACLReplaceFailed; + case CSSMERR_CSP_ACL_ADD_FAILED: + case CSSMERR_DL_ACL_ADD_FAILED: + return errSecACLAddFailed; + case CSSMERR_DL_ACL_CHANGE_FAILED: + case CSSMERR_CSP_ACL_CHANGE_FAILED: + return errSecACLChangeFailed; + case CSSMERR_CSSM_PRIVILEGE_NOT_GRANTED: + case CSSMERR_CSP_PRIVILEGE_NOT_GRANTED: + return errSecPrivilegeNotGranted; + case CSSMERR_CSP_INVALID_ACCESS_CREDENTIALS: + case CSSMERR_DL_INVALID_ACCESS_CREDENTIALS: + return errSecInvalidAccessCredentials; + case CSSMERR_DL_INVALID_RECORD_INDEX: + case CSSMERR_DL_INVALID_RECORDTYPE: + case CSSMERR_DL_UNSUPPORTED_RECORDTYPE: + case CSSMERR_DL_INVALID_RECORD_UID: + case CSSMERR_DL_STALE_UNIQUE_RECORD: + return errSecInvalidRecord; + case CSSMERR_CSP_INVALID_KEY: + case CSSMERR_CSP_INVALID_KEY_REFERENCE: + case CSSMERR_CSP_INVALID_KEY_CLASS: + return errSecInvalidKeyRef; + case CSSMERR_CSP_OBJECT_ACL_NOT_SUPPORTED: + case CSSMERR_CSP_OBJECT_ACL_REQUIRED: + case CSSMERR_CSP_ACL_BASE_CERTS_NOT_SUPPORTED: + case CSSMERR_CSP_INVALID_ACL_SUBJECT_VALUE: + case CSSMERR_CSP_ACL_SUBJECT_TYPE_NOT_SUPPORTED: + case CSSMERR_DL_OBJECT_ACL_NOT_SUPPORTED: + case CSSMERR_DL_OBJECT_ACL_REQUIRED: + case CSSMERR_DL_INVALID_ACL_SUBJECT_VALUE: + case CSSMERR_DL_ACL_SUBJECT_TYPE_NOT_SUPPORTED: + case CSSMERR_DL_INVALID_NEW_ACL_ENTRY: + case CSSMERR_DL_INVALID_NEW_ACL_OWNER: + case CSSMERR_DL_INVALID_ACL_EDIT_MODE: + case CSSMERR_CSP_INVALID_ACL_EDIT_MODE: + case CSSMERR_CSP_INVALID_NEW_ACL_ENTRY: + case CSSMERR_CSP_INVALID_NEW_ACL_OWNER: + return errSecInvalidACL; + case CSSMERR_CSP_INVALID_SAMPLE_VALUE: + case CSSMERR_DL_INVALID_SAMPLE_VALUE: + case CSSMERR_CSP_SAMPLE_VALUE_NOT_SUPPORTED: + case CSSMERR_DL_SAMPLE_VALUE_NOT_SUPPORTED: + return errSecInvalidSampleValue; + case CSSMERR_TP_UNKNOWN_FORMAT: + case CSSMERR_CL_UNKNOWN_FORMAT: + return errSecUnknownFormat; + case CSSMERR_CSP_APPLE_ADD_APPLICATION_ACL_SUBJECT: + return errSecAppleAddAppACLSubject; + case CSSMERR_CSP_APPLE_PUBLIC_KEY_INCOMPLETE: + return errSecApplePublicKeyIncomplete; + case CSSMERR_CSP_APPLE_SIGNATURE_MISMATCH: + return errSecAppleSignatureMismatch; + case CSSMERR_CSP_APPLE_INVALID_KEY_START_DATE: + return errSecAppleInvalidKeyStartDate; + case CSSMERR_CSP_APPLE_INVALID_KEY_END_DATE: + return errSecAppleInvalidKeyEndDate; + case CSSMERR_CSPDL_APPLE_DL_CONVERSION_ERROR: + return errSecConversionError; + case CSSMERR_CSP_APPLE_SSLv2_ROLLBACK: + return errSecAppleSSLv2Rollback; + case CSSMERR_APPLEDL_QUOTA_EXCEEDED: + return errSecQuotaExceeded; + case CSSMERR_APPLEDL_FILE_TOO_BIG: + return errSecFileTooBig; + case CSSMERR_APPLEDL_INVALID_DATABASE_BLOB: + return errSecInvalidDatabaseBlob; + case CSSMERR_APPLEDL_INVALID_KEY_BLOB: + return errSecInvalidKeyBlob; + case CSSMERR_APPLEDL_INCOMPATIBLE_DATABASE_BLOB: + return errSecIncompatibleDatabaseBlob; + case CSSMERR_APPLEDL_INCOMPATIBLE_KEY_BLOB: + return errSecIncompatibleKeyBlob; + case CSSMERR_APPLETP_HOSTNAME_MISMATCH: + return errSecHostNameMismatch; + case CSSMERR_APPLETP_UNKNOWN_CRITICAL_EXTEN: + return errSecUnknownCriticalExtensionFlag; + case CSSMERR_APPLETP_NO_BASIC_CONSTRAINTS: + return errSecNoBasicConstraints; + case CSSMERR_APPLETP_INVALID_AUTHORITY_ID: + return errSecInvalidAuthorityKeyID; + case CSSMERR_APPLETP_INVALID_SUBJECT_ID: + return errSecInvalidSubjectKeyID; + case CSSMERR_APPLETP_INVALID_KEY_USAGE: + return errSecInvalidKeyUsageForPolicy; + case CSSMERR_APPLETP_INVALID_EXTENDED_KEY_USAGE: + return errSecInvalidExtendedKeyUsage; + case CSSMERR_APPLETP_INVALID_ID_LINKAGE: + return errSecInvalidIDLinkage; + case CSSMERR_APPLETP_PATH_LEN_CONSTRAINT: + return errSecPathLengthConstraintExceeded; + case CSSMERR_APPLETP_INVALID_ROOT: + return errSecInvalidRoot; + case CSSMERR_APPLETP_CRL_EXPIRED: + return errSecCRLExpired; + case CSSMERR_APPLETP_CRL_NOT_VALID_YET: + return errSecCRLNotValidYet; + case CSSMERR_APPLETP_CRL_NOT_FOUND: + return errSecCRLNotFound; + case CSSMERR_APPLETP_CRL_SERVER_DOWN: + return errSecCRLServerDown; + case CSSMERR_APPLETP_CRL_BAD_URI: + return errSecCRLBadURI; + case CSSMERR_APPLETP_UNKNOWN_CERT_EXTEN: + return errSecUnknownCertExtension; + case CSSMERR_APPLETP_UNKNOWN_CRL_EXTEN: + return errSecUnknownCRLExtension; + case CSSMERR_APPLETP_CRL_NOT_TRUSTED: + return errSecCRLNotTrusted; + case CSSMERR_APPLETP_CRL_POLICY_FAIL: + return errSecCRLPolicyFailed; + case CSSMERR_APPLETP_IDP_FAIL: + return errSecIDPFailure; + case CSSMERR_APPLETP_SMIME_EMAIL_ADDRS_NOT_FOUND: + return errSecSMIMEEmailAddressesNotFound; + case CSSMERR_APPLETP_SMIME_BAD_EXT_KEY_USE: + return errSecSMIMEBadExtendedKeyUsage; + case CSSMERR_APPLETP_SMIME_BAD_KEY_USE: + return errSecSMIMEBadKeyUsage; + case CSSMERR_APPLETP_SMIME_KEYUSAGE_NOT_CRITICAL: + return errSecSMIMEKeyUsageNotCritical; + case CSSMERR_APPLETP_SMIME_NO_EMAIL_ADDRS: + return errSecSMIMENoEmailAddress; + case CSSMERR_APPLETP_SMIME_SUBJ_ALT_NAME_NOT_CRIT: + return errSecSMIMESubjAltNameNotCritical; + case CSSMERR_APPLETP_SSL_BAD_EXT_KEY_USE: + return errSecSSLBadExtendedKeyUsage; + case CSSMERR_APPLETP_OCSP_BAD_RESPONSE: + return errSecOCSPBadResponse; + case CSSMERR_APPLETP_OCSP_BAD_REQUEST: + return errSecOCSPBadRequest; + case CSSMERR_APPLETP_OCSP_UNAVAILABLE: + return errSecOCSPUnavailable; + case CSSMERR_APPLETP_OCSP_STATUS_UNRECOGNIZED: + return errSecOCSPStatusUnrecognized; + case CSSMERR_APPLETP_INCOMPLETE_REVOCATION_CHECK: + return errSecIncompleteCertRevocationCheck; + case CSSMERR_APPLETP_NETWORK_FAILURE: + return errSecNetworkFailure; + case CSSMERR_APPLETP_OCSP_NOT_TRUSTED: + return errSecOCSPNotTrustedToAnchor; + case CSSMERR_APPLETP_OCSP_SIG_ERROR: + return errSecOCSPSignatureError; + case CSSMERR_APPLETP_OCSP_NO_SIGNER: + return errSecOCSPNoSigner; + case CSSMERR_APPLETP_OCSP_RESP_MALFORMED_REQ: + return errSecOCSPResponderMalformedReq; + case CSSMERR_APPLETP_OCSP_RESP_INTERNAL_ERR: + return errSecOCSPResponderInternalError; + case CSSMERR_APPLETP_OCSP_RESP_TRY_LATER: + return errSecOCSPResponderTryLater; + case CSSMERR_APPLETP_OCSP_RESP_SIG_REQUIRED: + return errSecOCSPResponderSignatureRequired; + case CSSMERR_APPLETP_OCSP_RESP_UNAUTHORIZED: + return errSecOCSPResponderUnauthorized; + case CSSMERR_APPLETP_OCSP_NONCE_MISMATCH: + return errSecOCSPResponseNonceMismatch; + case CSSMERR_APPLETP_CS_BAD_CERT_CHAIN_LENGTH: + return errSecCodeSigningBadCertChainLength; + case CSSMERR_APPLETP_CS_NO_BASIC_CONSTRAINTS: + return errSecCodeSigningNoBasicConstraints; + case CSSMERR_APPLETP_CS_BAD_PATH_LENGTH: + return errSecCodeSigningBadPathLengthConstraint; + case CSSMERR_APPLETP_CS_NO_EXTENDED_KEY_USAGE: + return errSecCodeSigningNoExtendedKeyUsage; + case CSSMERR_APPLETP_CODE_SIGN_DEVELOPMENT: + return errSecCodeSigningDevelopment; + case CSSMERR_APPLETP_RS_BAD_CERT_CHAIN_LENGTH: + return errSecResourceSignBadCertChainLength; + case CSSMERR_APPLETP_RS_BAD_EXTENDED_KEY_USAGE: + return errSecResourceSignBadExtKeyUsage; + case CSSMERR_APPLETP_TRUST_SETTING_DENY: + return errSecTrustSettingDeny; + case CSSMERR_APPLETP_INVALID_EMPTY_SUBJECT: + return errSecInvalidSubjectName; + case CSSMERR_APPLETP_UNKNOWN_QUAL_CERT_STATEMENT: + return errSecUnknownQualifiedCertStatement; + case CSSMERR_APPLETP_MISSING_REQUIRED_EXTENSION: + return errSecMissingRequiredExtension; + case CSSMERR_APPLETP_EXT_KEYUSAGE_NOT_CRITICAL: + return errSecExtendedKeyUsageNotCritical; + case CSSMERR_APPLE_DOTMAC_REQ_QUEUED: + return errSecMobileMeRequestQueued; + case CSSMERR_APPLE_DOTMAC_REQ_REDIRECT: + return errSecMobileMeRequestRedirected; + case CSSMERR_APPLE_DOTMAC_REQ_SERVER_ERR: + return errSecMobileMeServerError; + case CSSMERR_APPLE_DOTMAC_REQ_SERVER_NOT_AVAIL: + return errSecMobileMeServerNotAvailable; + case CSSMERR_APPLE_DOTMAC_REQ_SERVER_ALREADY_EXIST: + return errSecMobileMeServerAlreadyExists; + case CSSMERR_APPLE_DOTMAC_REQ_SERVER_SERVICE_ERROR: + return errSecMobileMeServerServiceErr; + case CSSMERR_APPLE_DOTMAC_REQ_IS_PENDING: + return errSecMobileMeRequestAlreadyPending; + case CSSMERR_APPLE_DOTMAC_NO_REQ_PENDING: + return errSecMobileMeNoRequestPending; + case CSSMERR_APPLE_DOTMAC_CSR_VERIFY_FAIL: + return errSecMobileMeCSRVerifyFailure; + case CSSMERR_APPLE_DOTMAC_FAILED_CONSISTENCY_CHECK: + return errSecMobileMeFailedConsistencyCheck; + case CSSMERR_CSSM_NOT_INITIALIZED: + return errSecNotInitialized; + case CSSMERR_CSSM_INVALID_HANDLE_USAGE: + return errSecInvalidHandleUsage; + case CSSMERR_CSSM_PVC_REFERENT_NOT_FOUND: + return errSecPVCReferentNotFound; + case CSSMERR_CSSM_FUNCTION_INTEGRITY_FAIL: + return errSecFunctionIntegrityFail; + case CSSMERR_CSSM_SELF_CHECK_FAILED: + case CSSMERR_CSP_SELF_CHECK_FAILED: + return errSecSelfCheckFailed; + case CSSMERR_CSSM_MODULE_MANIFEST_VERIFY_FAILED: + return errSecModuleManifestVerifyFailed; + case CSSMERR_CSSM_INVALID_GUID: + return errSecInvalidGUID; + case CSSMERR_CSSM_INCOMPATIBLE_VERSION: + return errSecIncompatibleVersion; + case CSSMERR_CSSM_PVC_ALREADY_CONFIGURED: + return errSecPVCAlreadyConfigured; + case CSSMERR_CSSM_INVALID_PVC: + return errSecInvalidPVC; + case CSSMERR_CSSM_EMM_LOAD_FAILED: + return errSecEMMLoadFailed; + case CSSMERR_CSSM_EMM_UNLOAD_FAILED: + return errSecEMMUnloadFailed; + case CSSMERR_CSSM_ADDIN_LOAD_FAILED: + return errSecAddinLoadFailed; + case CSSMERR_CSSM_INVALID_KEY_HIERARCHY: + return errSecInvalidKeyHierarchy; + case CSSMERR_CSSM_ADDIN_UNLOAD_FAILED: + return errSecAddinUnloadFailed; + case CSSMERR_CSSM_LIB_REF_NOT_FOUND: + return errSecLibraryReferenceNotFound; + case CSSMERR_CSSM_INVALID_ADDIN_FUNCTION_TABLE: + return errSecInvalidAddinFunctionTable; + case CSSMERR_CSSM_INVALID_SERVICE_MASK: + return errSecInvalidServiceMask; + case CSSMERR_CSSM_MODULE_NOT_LOADED: + return errSecModuleNotLoaded; + case CSSMERR_CSSM_INVALID_SUBSERVICEID: + return errSecInvalidSubServiceID; + case CSSMERR_CSSM_ATTRIBUTE_NOT_IN_CONTEXT: + return errSecAttributeNotInContext; + case CSSMERR_CSSM_MODULE_MANAGER_INITIALIZE_FAIL: + return errSecModuleManagerInitializeFailed; + case CSSMERR_CSSM_MODULE_MANAGER_NOT_FOUND: + return errSecModuleManagerNotFound; + case CSSMERR_CSSM_EVENT_NOTIFICATION_CALLBACK_NOT_FOUND: + return errSecEventNotificationCallbackNotFound; + case CSSMERR_CSP_INPUT_LENGTH_ERROR: + return errSecInputLengthError; + case CSSMERR_CSP_OUTPUT_LENGTH_ERROR: + return errSecOutputLengthError; + case CSSMERR_CSP_PRIVILEGE_NOT_SUPPORTED: + return errSecPrivilegeNotSupported; + case CSSMERR_CSP_DEVICE_ERROR: + return errSecDeviceError; + case CSSMERR_CSP_ATTACH_HANDLE_BUSY: + return errSecAttachHandleBusy; + case CSSMERR_CSP_NOT_LOGGED_IN: + return errSecNotLoggedIn; + case CSSMERR_CSP_ALGID_MISMATCH: + return errSecAlgorithmMismatch; + case CSSMERR_CSP_KEY_USAGE_INCORRECT: + return errSecKeyUsageIncorrect; + case CSSMERR_CSP_KEY_BLOB_TYPE_INCORRECT: + return errSecKeyBlobTypeIncorrect; + case CSSMERR_CSP_KEY_HEADER_INCONSISTENT: + return errSecKeyHeaderInconsistent; + case CSSMERR_CSP_UNSUPPORTED_KEY_FORMAT: + return errSecUnsupportedKeyFormat; + case CSSMERR_CSP_UNSUPPORTED_KEY_SIZE: + return errSecUnsupportedKeySize; + case CSSMERR_CSP_INVALID_KEYUSAGE_MASK: + return errSecInvalidKeyUsageMask; + case CSSMERR_CSP_UNSUPPORTED_KEYUSAGE_MASK: + return errSecUnsupportedKeyUsageMask; + case CSSMERR_CSP_INVALID_KEYATTR_MASK: + return errSecInvalidKeyAttributeMask; + case CSSMERR_CSP_UNSUPPORTED_KEYATTR_MASK: + return errSecUnsupportedKeyAttributeMask; + case CSSMERR_CSP_INVALID_KEY_LABEL: + return errSecInvalidKeyLabel; + case CSSMERR_CSP_UNSUPPORTED_KEY_LABEL: + return errSecUnsupportedKeyLabel; + case CSSMERR_CSP_INVALID_KEY_FORMAT: + return errSecInvalidKeyFormat; + case CSSMERR_CSP_VECTOR_OF_BUFS_UNSUPPORTED: + return errSecUnsupportedVectorOfBuffers; + case CSSMERR_CSP_INVALID_INPUT_VECTOR: + return errSecInvalidInputVector; + case CSSMERR_CSP_INVALID_OUTPUT_VECTOR: + return errSecInvalidOutputVector; + case CSSMERR_CSP_INVALID_CONTEXT: + return errSecInvalidContext; + case CSSMERR_CSP_INVALID_ALGORITHM: + return errSecInvalidAlgorithm; + case CSSMERR_CSP_INVALID_ATTR_KEY: + return errSecInvalidAttributeKey; + case CSSMERR_CSP_MISSING_ATTR_KEY: + return errSecMissingAttributeKey; + case CSSMERR_CSP_INVALID_ATTR_INIT_VECTOR: + return errSecInvalidAttributeInitVector; + case CSSMERR_CSP_MISSING_ATTR_INIT_VECTOR: + return errSecMissingAttributeInitVector; + case CSSMERR_CSP_INVALID_ATTR_SALT: + return errSecInvalidAttributeSalt; + case CSSMERR_CSP_MISSING_ATTR_SALT: + return errSecMissingAttributeSalt; + case CSSMERR_CSP_INVALID_ATTR_PADDING: + return errSecInvalidAttributePadding; + case CSSMERR_CSP_MISSING_ATTR_PADDING: + return errSecMissingAttributePadding; + case CSSMERR_CSP_INVALID_ATTR_RANDOM: + return errSecInvalidAttributeRandom; + case CSSMERR_CSP_MISSING_ATTR_RANDOM: + return errSecMissingAttributeRandom; + case CSSMERR_CSP_INVALID_ATTR_SEED: + return errSecInvalidAttributeSeed; + case CSSMERR_CSP_MISSING_ATTR_SEED: + return errSecMissingAttributeSeed; + case CSSMERR_CSP_INVALID_ATTR_PASSPHRASE: + return errSecInvalidAttributePassphrase; + case CSSMERR_CSP_MISSING_ATTR_PASSPHRASE: + return errSecMissingAttributePassphrase; + case CSSMERR_CSP_INVALID_ATTR_KEY_LENGTH: + return errSecInvalidAttributeKeyLength; + case CSSMERR_CSP_MISSING_ATTR_KEY_LENGTH: + return errSecMissingAttributeKeyLength; + case CSSMERR_CSP_INVALID_ATTR_BLOCK_SIZE: + return errSecInvalidAttributeBlockSize; + case CSSMERR_CSP_MISSING_ATTR_BLOCK_SIZE: + return errSecMissingAttributeBlockSize; + case CSSMERR_CSP_INVALID_ATTR_OUTPUT_SIZE: + return errSecInvalidAttributeOutputSize; + case CSSMERR_CSP_MISSING_ATTR_OUTPUT_SIZE: + return errSecMissingAttributeOutputSize; + case CSSMERR_CSP_INVALID_ATTR_ROUNDS: + return errSecInvalidAttributeRounds; + case CSSMERR_CSP_MISSING_ATTR_ROUNDS: + return errSecMissingAttributeRounds; + case CSSMERR_CSP_INVALID_ATTR_ALG_PARAMS: + return errSecInvalidAlgorithmParms; + case CSSMERR_CSP_MISSING_ATTR_ALG_PARAMS: + return errSecMissingAlgorithmParms; + case CSSMERR_CSP_INVALID_ATTR_LABEL: + return errSecInvalidAttributeLabel; + case CSSMERR_CSP_MISSING_ATTR_LABEL: + return errSecMissingAttributeLabel; + case CSSMERR_CSP_INVALID_ATTR_KEY_TYPE: + return errSecInvalidAttributeKeyType; + case CSSMERR_CSP_MISSING_ATTR_KEY_TYPE: + return errSecMissingAttributeKeyType; + case CSSMERR_CSP_INVALID_ATTR_MODE: + return errSecInvalidAttributeMode; + case CSSMERR_CSP_MISSING_ATTR_MODE: + return errSecMissingAttributeMode; + case CSSMERR_CSP_INVALID_ATTR_EFFECTIVE_BITS: + return errSecInvalidAttributeEffectiveBits; + case CSSMERR_CSP_MISSING_ATTR_EFFECTIVE_BITS: + return errSecMissingAttributeEffectiveBits; + case CSSMERR_CSP_INVALID_ATTR_START_DATE: + return errSecInvalidAttributeStartDate; + case CSSMERR_CSP_MISSING_ATTR_START_DATE: + return errSecMissingAttributeStartDate; + case CSSMERR_CSP_INVALID_ATTR_END_DATE: + return errSecInvalidAttributeEndDate; + case CSSMERR_CSP_MISSING_ATTR_END_DATE: + return errSecMissingAttributeEndDate; + case CSSMERR_CSP_INVALID_ATTR_VERSION: + return errSecInvalidAttributeVersion; + case CSSMERR_CSP_MISSING_ATTR_VERSION: + return errSecMissingAttributeVersion; + case CSSMERR_CSP_INVALID_ATTR_PRIME: + return errSecInvalidAttributePrime; + case CSSMERR_CSP_MISSING_ATTR_PRIME: + return errSecMissingAttributePrime; + case CSSMERR_CSP_INVALID_ATTR_BASE: + return errSecInvalidAttributeBase; + case CSSMERR_CSP_MISSING_ATTR_BASE: + return errSecMissingAttributeBase; + case CSSMERR_CSP_INVALID_ATTR_SUBPRIME: + return errSecInvalidAttributeSubprime; + case CSSMERR_CSP_MISSING_ATTR_SUBPRIME: + return errSecMissingAttributeSubprime; + case CSSMERR_CSP_INVALID_ATTR_ITERATION_COUNT: + return errSecInvalidAttributeIterationCount; + case CSSMERR_CSP_MISSING_ATTR_ITERATION_COUNT: + return errSecMissingAttributeIterationCount; + case CSSMERR_CSP_INVALID_ATTR_DL_DB_HANDLE: + return errSecInvalidAttributeDLDBHandle; + case CSSMERR_CSP_MISSING_ATTR_DL_DB_HANDLE: + return errSecMissingAttributeDLDBHandle; + case CSSMERR_CSP_INVALID_ATTR_ACCESS_CREDENTIALS: + return errSecInvalidAttributeAccessCredentials; + case CSSMERR_CSP_MISSING_ATTR_ACCESS_CREDENTIALS: + return errSecMissingAttributeAccessCredentials; + case CSSMERR_CSP_INVALID_ATTR_PUBLIC_KEY_FORMAT: + return errSecInvalidAttributePublicKeyFormat; + case CSSMERR_CSP_MISSING_ATTR_PUBLIC_KEY_FORMAT: + return errSecMissingAttributePublicKeyFormat; + case CSSMERR_CSP_INVALID_ATTR_PRIVATE_KEY_FORMAT: + return errSecInvalidAttributePrivateKeyFormat; + case CSSMERR_CSP_MISSING_ATTR_PRIVATE_KEY_FORMAT: + return errSecMissingAttributePrivateKeyFormat; + case CSSMERR_CSP_INVALID_ATTR_SYMMETRIC_KEY_FORMAT: + return errSecInvalidAttributeSymmetricKeyFormat; + case CSSMERR_CSP_MISSING_ATTR_SYMMETRIC_KEY_FORMAT: + return errSecMissingAttributeSymmetricKeyFormat; + case CSSMERR_CSP_INVALID_ATTR_WRAPPED_KEY_FORMAT: + return errSecInvalidAttributeWrappedKeyFormat; + case CSSMERR_CSP_MISSING_ATTR_WRAPPED_KEY_FORMAT: + return errSecMissingAttributeWrappedKeyFormat; + case CSSMERR_CSP_STAGED_OPERATION_IN_PROGRESS: + return errSecStagedOperationInProgress; + case CSSMERR_CSP_STAGED_OPERATION_NOT_STARTED: + return errSecStagedOperationNotStarted; + case CSSMERR_CSP_VERIFY_FAILED: + return errSecVerifyFailed; + case CSSMERR_CSP_QUERY_SIZE_UNKNOWN: + return errSecQuerySizeUnknown; + case CSSMERR_CSP_BLOCK_SIZE_MISMATCH: + return errSecBlockSizeMismatch; + case CSSMERR_CSP_PUBLIC_KEY_INCONSISTENT: + return errSecPublicKeyInconsistent; + case CSSMERR_CSP_DEVICE_VERIFY_FAILED: + return errSecDeviceVerifyFailed; + case CSSMERR_CSP_INVALID_LOGIN_NAME: + return errSecInvalidLoginName; + case CSSMERR_CSP_ALREADY_LOGGED_IN: + return errSecAlreadyLoggedIn; + case CSSMERR_CSP_INVALID_DIGEST_ALGORITHM: + return errSecInvalidDigestAlgorithm; + case CSSMERR_TP_INVALID_CRLGROUP: + return errSecInvalidCRLGroup; + case CSSMERR_TP_CERTIFICATE_CANT_OPERATE: + return errSecCertificateCannotOperate; + case CSSMERR_TP_CERT_EXPIRED: + return errSecCertificateExpired; + case CSSMERR_TP_CERT_NOT_VALID_YET: + return errSecCertificateNotValidYet; + case CSSMERR_TP_CERT_REVOKED: + return errSecCertificateRevoked; + case CSSMERR_TP_CERT_SUSPENDED: + return errSecCertificateSuspended; + case CSSMERR_TP_INSUFFICIENT_CREDENTIALS: + return errSecInsufficientCredentials; + case CSSMERR_TP_INVALID_ACTION: + return errSecInvalidAction; + case CSSMERR_TP_INVALID_AUTHORITY: + return errSecInvalidAuthority; + case CSSMERR_TP_VERIFY_ACTION_FAILED: + return errSecVerifyActionFailed; + case CSSMERR_TP_INVALID_CERT_AUTHORITY: + case CSSMERR_APPLETP_INVALID_CA: + return errSecInvalidCertAuthority; + case CSSMERR_TP_INVALID_CRL_AUTHORITY: + return errSecInvaldCRLAuthority; + case CSSMERR_TP_INVALID_CRL_ENCODING: + return errSecInvalidCRLEncoding; + case CSSMERR_TP_INVALID_CRL_TYPE: + return errSecInvalidCRLType; + case CSSMERR_TP_INVALID_CRL: + return errSecInvalidCRL; + case CSSMERR_TP_INVALID_FORM_TYPE: + return errSecInvalidFormType; + case CSSMERR_TP_INVALID_ID: + return errSecInvalidID; + case CSSMERR_TP_INVALID_IDENTIFIER: + return errSecInvalidIdentifier; + case CSSMERR_TP_INVALID_INDEX: + return errSecInvalidIndex; + case CSSMERR_TP_INVALID_POLICY_IDENTIFIERS: + return errSecInvalidPolicyIdentifiers; + case CSSMERR_TP_INVALID_TIMESTRING: + return errSecInvalidTimeString; + case CSSMERR_TP_INVALID_REASON: + return errSecInvalidReason; + case CSSMERR_TP_INVALID_REQUEST_INPUTS: + return errSecInvalidRequestInputs; + case CSSMERR_TP_INVALID_RESPONSE_VECTOR: + return errSecInvalidResponseVector; + case CSSMERR_TP_INVALID_STOP_ON_POLICY: + return errSecInvalidStopOnPolicy; + case CSSMERR_TP_INVALID_TUPLE: + return errSecInvalidTuple; + case CSSMERR_TP_NOT_SIGNER: + return errSecNotSigner; + case CSSMERR_TP_NOT_TRUSTED: + return errSecNotTrusted; + case CSSMERR_TP_NO_DEFAULT_AUTHORITY: + return errSecNoDefaultAuthority; + case CSSMERR_TP_REJECTED_FORM: + return errSecRejectedForm; + case CSSMERR_TP_REQUEST_LOST: + return errSecRequestLost; + case CSSMERR_TP_REQUEST_REJECTED: + return errSecRequestRejected; + case CSSMERR_TP_UNSUPPORTED_ADDR_TYPE: + return errSecUnsupportedAddressType; + case CSSMERR_TP_UNSUPPORTED_SERVICE: + return errSecUnsupportedService; + case CSSMERR_TP_INVALID_TUPLEGROUP: + return errSecInvalidTupleGroup; + case CSSMERR_AC_INVALID_BASE_ACLS: + return errSecInvalidBaseACLs; + case CSSMERR_AC_INVALID_TUPLE_CREDENTIALS: + return errSecInvalidTupleCredendtials; + case CSSMERR_AC_INVALID_ENCODING: + return errSecInvalidEncoding; + case CSSMERR_AC_INVALID_VALIDITY_PERIOD: + return errSecInvalidValidityPeriod; + case CSSMERR_AC_INVALID_REQUESTOR: + return errSecInvalidRequestor; + case CSSMERR_AC_INVALID_REQUEST_DESCRIPTOR: + return errSecRequestDescriptor; + case CSSMERR_CL_INVALID_BUNDLE_INFO: + return errSecInvalidBundleInfo; + case CSSMERR_CL_INVALID_CRL_INDEX: + return errSecInvalidCRLIndex; + case CSSMERR_CL_NO_FIELD_VALUES: + return errSecNoFieldValues; + case CSSMERR_DL_UNSUPPORTED_FIELD_FORMAT: + return errSecUnsupportedFieldFormat; + case CSSMERR_DL_UNSUPPORTED_INDEX_INFO: + return errSecUnsupportedIndexInfo; + case CSSMERR_DL_UNSUPPORTED_LOCALITY: + return errSecUnsupportedLocality; + case CSSMERR_DL_UNSUPPORTED_NUM_ATTRIBUTES: + return errSecUnsupportedNumAttributes; + case CSSMERR_DL_UNSUPPORTED_NUM_INDEXES: + return errSecUnsupportedNumIndexes; + case CSSMERR_DL_UNSUPPORTED_NUM_RECORDTYPES: + return errSecUnsupportedNumRecordTypes; + case CSSMERR_DL_FIELD_SPECIFIED_MULTIPLE: + return errSecFieldSpecifiedMultiple; + case CSSMERR_DL_INCOMPATIBLE_FIELD_FORMAT: + return errSecIncompatibleFieldFormat; + case CSSMERR_DL_INVALID_PARSING_MODULE: + return errSecInvalidParsingModule; + case CSSMERR_DL_DB_LOCKED: + return errSecDatabaseLocked; + case CSSMERR_DL_DATASTORE_IS_OPEN: + return errSecDatastoreIsOpen; + case CSSMERR_DL_MISSING_VALUE: + return errSecMissingValue; + case CSSMERR_DL_UNSUPPORTED_QUERY_LIMITS: + return errSecUnsupportedQueryLimits; + case CSSMERR_DL_UNSUPPORTED_NUM_SELECTION_PREDS: + return errSecUnsupportedNumSelectionPreds; + case CSSMERR_DL_UNSUPPORTED_OPERATOR: + return errSecUnsupportedOperator; + case CSSMERR_DL_INVALID_DB_LOCATION: + return errSecInvalidDBLocation; + case CSSMERR_DL_INVALID_ACCESS_REQUEST: + return errSecInvalidAccessRequest; + case CSSMERR_DL_INVALID_INDEX_INFO: + return errSecInvalidIndexInfo; + case CSSMERR_DL_INVALID_NEW_OWNER: + return errSecInvalidNewOwner; + case CSSMERR_DL_INVALID_MODIFY_MODE: + return errSecInvalidModifyMode; + case CSSMERR_DL_RECORD_MODIFIED: + return errSecRecordModified; + case CSSMERR_DL_ENDOFDATA: + return errSecEndOfData; + case CSSMERR_DL_INVALID_VALUE: + return errSecInvalidValue; + case CSSMERR_DL_MULTIPLE_VALUES_UNSUPPORTED: + return errSecMultipleValuesUnsupported; + default: + return osStatus; + } +} diff --git a/libsecurity_keychain/lib/SecBase.h b/libsecurity_keychain/lib/SecBase.h new file mode 100644 index 00000000..9255e2c3 --- /dev/null +++ b/libsecurity_keychain/lib/SecBase.h @@ -0,0 +1,619 @@ +/* + * Copyright (c) 2000-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 SecBase + SecBase contains common declarations for the Security functions. +*/ + +#ifndef _SECURITY_SECBASE_H_ +#define _SECURITY_SECBASE_H_ + +#include + +#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 errSecParam One or more parameters passed to a function were not valid. +@constant errSecAllocate Failed to allocate memory. +@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. */ + errSecParam = -50, /* One or more parameters passed to a function were not valid. */ + errSecAllocate = -108, /* Failed to allocate memory. */ + + 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/libsecurity_keychain/lib/SecBase64P.c new file mode 100644 index 00000000..61ba69ff --- /dev/null +++ b/libsecurity_keychain/lib/SecBase64P.c @@ -0,0 +1,489 @@ +/* ///////////////////////////////////////////////////////////////////////////// + * File: b64.c + * + * Purpose: Implementation file for the b64 library + * + * Created: 18th October 2004 + * Updated: 2nd August 2006 + * + * Home: http://synesis.com.au/software/ + * + * Copyright (c) 2004-2006, Matthew Wilson and Synesis Software + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * - Neither the name(s) of Matthew Wilson and Synesis Software nor the names of + * any contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * ////////////////////////////////////////////////////////////////////////// */ + + +/** \file b64.c Implementation file for the b64 library + */ + +#include "SecBase64P.h" + +#include +#include + +/* ///////////////////////////////////////////////////////////////////////////// + * Constants and definitions + */ + +#ifndef B64_DOCUMENTATION_SKIP_SECTION +# define NUM_PLAIN_DATA_BYTES (3) +# define NUM_ENCODED_DATA_BYTES (4) +#endif /* !B64_DOCUMENTATION_SKIP_SECTION */ + +/* ///////////////////////////////////////////////////////////////////////////// + * Warnings + */ + +#if defined(_MSC_VER) && \ + _MSC_VER < 1000 +# pragma warning(disable : 4705) +#endif /* _MSC_VER < 1000 */ + +/* ///////////////////////////////////////////////////////////////////////////// + * Data + */ + +static const char b64_chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +static const signed char b64_indexes[] = +{ + /* 0 - 31 / 0x00 - 0x1f */ + -1, -1, -1, -1, -1, -1, -1, -1 + , -1, -1, -1, -1, -1, -1, -1, -1 + , -1, -1, -1, -1, -1, -1, -1, -1 + , -1, -1, -1, -1, -1, -1, -1, -1 + /* 32 - 63 / 0x20 - 0x3f */ + , -1, -1, -1, -1, -1, -1, -1, -1 + , -1, -1, -1, 62, -1, -1, -1, 63 /* ... , '+', ... '/' */ + , 52, 53, 54, 55, 56, 57, 58, 59 /* '0' - '7' */ + , 60, 61, -1, -1, -1, -1, -1, -1 /* '8', '9', ... */ + /* 64 - 95 / 0x40 - 0x5f */ + , -1, 0, 1, 2, 3, 4, 5, 6 /* ..., 'A' - 'G' */ + , 7, 8, 9, 10, 11, 12, 13, 14 /* 'H' - 'O' */ + , 15, 16, 17, 18, 19, 20, 21, 22 /* 'P' - 'W' */ + , 23, 24, 25, -1, -1, -1, -1, -1 /* 'X', 'Y', 'Z', ... */ + /* 96 - 127 / 0x60 - 0x7f */ + , -1, 26, 27, 28, 29, 30, 31, 32 /* ..., 'a' - 'g' */ + , 33, 34, 35, 36, 37, 38, 39, 40 /* 'h' - 'o' */ + , 41, 42, 43, 44, 45, 46, 47, 48 /* 'p' - 'w' */ + , 49, 50, 51, -1, -1, -1, -1, -1 /* 'x', 'y', 'z', ... */ + + , -1, -1, -1, -1, -1, -1, -1, -1 + , -1, -1, -1, -1, -1, -1, -1, -1 + , -1, -1, -1, -1, -1, -1, -1, -1 + , -1, -1, -1, -1, -1, -1, -1, -1 + + , -1, -1, -1, -1, -1, -1, -1, -1 + , -1, -1, -1, -1, -1, -1, -1, -1 + , -1, -1, -1, -1, -1, -1, -1, -1 + , -1, -1, -1, -1, -1, -1, -1, -1 + + , -1, -1, -1, -1, -1, -1, -1, -1 + , -1, -1, -1, -1, -1, -1, -1, -1 + , -1, -1, -1, -1, -1, -1, -1, -1 + , -1, -1, -1, -1, -1, -1, -1, -1 + + , -1, -1, -1, -1, -1, -1, -1, -1 + , -1, -1, -1, -1, -1, -1, -1, -1 + , -1, -1, -1, -1, -1, -1, -1, -1 + , -1, -1, -1, -1, -1, -1, -1, -1 +}; + +/* ///////////////////////////////////////////////////////////////////////////// + * Helper functions + */ + +/** This function reads in 3 bytes at a time, and translates them into 4 + * characters. + */ +static size_t SecBase64Encode_( unsigned char const *src + , size_t srcSize + , char *const dest + , size_t destLen + , unsigned lineLen + , SecBase64Result *rc) +{ + size_t total = ((srcSize + (NUM_PLAIN_DATA_BYTES - 1)) / NUM_PLAIN_DATA_BYTES) * NUM_ENCODED_DATA_BYTES; + + assert(NULL != rc); + *rc = kSecB64_R_OK; + + if(lineLen > 0) + { + unsigned numLines = (total + (lineLen - 1)) / lineLen; + + total += 2 * (numLines - 1); + } + + if(NULL == dest) + { + return total; + } + else if(destLen < total) + { + *rc = kSecB64_R_INSUFFICIENT_BUFFER; + + return 0; + } + else + { + char *p = dest; + char *end = dest + destLen; + size_t len = 0; + + for(; NUM_PLAIN_DATA_BYTES <= srcSize; srcSize -= NUM_PLAIN_DATA_BYTES) + { + char characters[NUM_ENCODED_DATA_BYTES]; + + /* + * + * | 0 | 1 | 2 | + * + * | | | | + * | | | | | | | + * | | | | | | | | | | | | | + * | | | | | | | | | | | | | | | | | | | | | | | | | + * + * | 0 | 1 | 2 | 3 | + * + */ + + /* characters[0] is the 6 left-most bits of src[0] */ + characters[0] = (char)((src[0] & 0xfc) >> 2); + /* characters[0] is the right-most 2 bits of src[0] and the left-most 4 bits of src[1] */ + characters[1] = (char)(((src[0] & 0x03) << 4) + ((src[1] & 0xf0) >> 4)); + /* characters[0] is the right-most 4 bits of src[1] and the 2 left-most bits of src[2] */ + characters[2] = (char)(((src[1] & 0x0f) << 2) + ((src[2] & 0xc0) >> 6)); + /* characters[3] is the right-most 6 bits of src[2] */ + characters[3] = (char)(src[2] & 0x3f); + +#ifndef __WATCOMC__ + assert(characters[0] >= 0 && characters[0] < 64); + assert(characters[1] >= 0 && characters[1] < 64); + assert(characters[2] >= 0 && characters[2] < 64); + assert(characters[3] >= 0 && characters[3] < 64); +#endif /* __WATCOMC__ */ + + src += NUM_PLAIN_DATA_BYTES; + *p++ = b64_chars[(unsigned char)characters[0]]; + assert(NULL != strchr(b64_chars, *(p-1))); + ++len; + assert(len != lineLen); + + *p++ = b64_chars[(unsigned char)characters[1]]; + assert(NULL != strchr(b64_chars, *(p-1))); + ++len; + assert(len != lineLen); + + *p++ = b64_chars[(unsigned char)characters[2]]; + assert(NULL != strchr(b64_chars, *(p-1))); + ++len; + assert(len != lineLen); + + *p++ = b64_chars[(unsigned char)characters[3]]; + assert(NULL != strchr(b64_chars, *(p-1))); + + if( ++len == lineLen && + p != end) + { + *p++ = '\r'; + *p++ = '\n'; + len = 0; + } + } + + if(0 != srcSize) + { + /* Deal with the overspill, by boosting it up to three bytes (using 0s) + * and then appending '=' for any missing characters. + * + * This is done into a temporary buffer, so we can call ourselves and + * have the output continue to be written direct to the destination. + */ + + unsigned char dummy[NUM_PLAIN_DATA_BYTES]; + size_t i; + + for(i = 0; i < srcSize; ++i) + { + dummy[i] = *src++; + } + + for(; i < NUM_PLAIN_DATA_BYTES; ++i) + { + dummy[i] = '\0'; + } + + SecBase64Encode_(&dummy[0], NUM_PLAIN_DATA_BYTES, p, NUM_ENCODED_DATA_BYTES * (1 + 2), 0, rc); + + for(p += 1 + srcSize; srcSize++ < NUM_PLAIN_DATA_BYTES; ) + { + *p++ = '='; + } + } + + return total; + } +} + +/** This function reads in a character string in 4-character chunks, and writes + * out the converted form in 3-byte chunks to the destination. + */ +static size_t SecBase64Decode_( char const *src + , size_t srcLen + , unsigned char *dest + , size_t destSize + , unsigned flags + , char const **badChar + , SecBase64Result *rc) +{ + const size_t wholeChunks = (srcLen / NUM_ENCODED_DATA_BYTES); + const size_t remainderBytes = (srcLen % NUM_ENCODED_DATA_BYTES); + size_t maxTotal = (wholeChunks + (0 != remainderBytes)) * NUM_PLAIN_DATA_BYTES; + unsigned char *dest_ = dest; + + ((void)remainderBytes); + + assert(NULL != badChar); + assert(NULL != rc); + + *badChar = NULL; + *rc = kSecB64_R_OK; + + if(NULL == dest) + { + return maxTotal; + } + else if(destSize < maxTotal) + { + *rc = kSecB64_R_INSUFFICIENT_BUFFER; + + return 0; + } + else + { + /* Now we iterate through the src, collecting together four characters + * at a time from the Base-64 alphabet, until the end-point is reached. + * + * + */ + + char const *begin = src; + char const *const end = begin + srcLen; + size_t currIndex = 0; + size_t numPads = 0; + signed char indexes[NUM_ENCODED_DATA_BYTES]; /* 4 */ + + for(; begin != end; ++begin) + { + const char ch = *begin; + + if('=' == ch) + { + assert(currIndex < NUM_ENCODED_DATA_BYTES); + + indexes[currIndex++] = '\0'; + + ++numPads; + } + else + { + signed char ix = b64_indexes[(unsigned char)ch]; + + if(-1 == ix) + { + switch(ch) + { + case ' ': + case '\t': + case '\b': + case '\v': + if(kSecB64_F_STOP_ON_UNEXPECTED_WS & flags) + { + *rc = kSecB64_R_DATA_ERROR; + *badChar = begin; + return 0; + } + else + { + /* Fall through */ + } + case '\r': + case '\n': + continue; + default: + if(kSecB64_F_STOP_ON_UNKNOWN_CHAR & flags) + { + *rc = kSecB64_R_DATA_ERROR; + *badChar = begin; + return 0; + } + else + { + continue; + } + } + } + else + { + numPads = 0; + + assert(currIndex < NUM_ENCODED_DATA_BYTES); + + indexes[currIndex++] = ix; + } + } + + if(NUM_ENCODED_DATA_BYTES == currIndex) + { + unsigned char bytes[NUM_PLAIN_DATA_BYTES]; /* 3 */ + + bytes[0] = (unsigned char)((indexes[0] << 2) + ((indexes[1] & 0x30) >> 4)); + + currIndex = 0; + + *dest++ = bytes[0]; + if(2 != numPads) + { + bytes[1] = (unsigned char)(((indexes[1] & 0xf) << 4) + ((indexes[2] & 0x3c) >> 2)); + + *dest++ = bytes[1]; + + if(1 != numPads) + { + bytes[2] = (unsigned char)(((indexes[2] & 0x3) << 6) + indexes[3]); + + *dest++ = bytes[2]; + } + } + if(0 != numPads) + { + break; + } + } + } + + return (size_t)(dest - dest_); + } +} + +/* ///////////////////////////////////////////////////////////////////////////// + * API functions + */ + +size_t SecBase64Encode(void const *src, size_t srcSize, char *dest, size_t destLen) +{ + /* Use Null Object (Variable) here for rc, so do not need to check + * elsewhere. + */ + SecBase64Result rc_; + + return SecBase64Encode_((unsigned char const*)src, srcSize, dest, destLen, 0, &rc_); +} + +size_t SecBase64Encode2( void const *src + , size_t srcSize + , char *dest + , size_t destLen + , unsigned flags + , int lineLen /* = -1 */ + , SecBase64Result *rc /* = NULL */) +{ + /* Use Null Object (Variable) here for rc, so do not need to check + * elsewhere + */ + SecBase64Result rc_; + if(NULL == rc) + { + rc = &rc_; + } + + switch(kSecB64_F_LINE_LEN_MASK & flags) + { + case kSecB64_F_LINE_LEN_USE_PARAM: + if(lineLen >= 0) + { + break; + } + /* Fall through to 64 */ + case kSecB64_F_LINE_LEN_64: + lineLen = 64; + break; + case kSecB64_F_LINE_LEN_76: + lineLen = 76; + break; + default: + assert(!"Bad line length flag specified to SecBase64Encode2()"); + case kSecB64_F_LINE_LEN_INFINITE: + lineLen = 0; + break; + } + + assert(0 == (lineLen % 4)); + + return SecBase64Encode_((unsigned char const*)src, srcSize, dest, destLen, (unsigned)lineLen, rc); +} + +size_t SecBase64Decode(char const *src, size_t srcLen, void *dest, size_t destSize) +{ + /* Use Null Object (Variable) here for rc and badChar, so do not need to + * check elsewhere. + */ + char const *badChar_; + SecBase64Result rc_; + + return SecBase64Decode_(src, srcLen, (unsigned char*)dest, destSize, kSecB64_F_STOP_ON_NOTHING, &badChar_, &rc_); +} + +size_t SecBase64Decode2( char const *src + , size_t srcLen + , void *dest + , size_t destSize + , unsigned flags + , char const **badChar /* = NULL */ + , SecBase64Result *rc /* = NULL */) +{ + char const *badChar_; + SecBase64Result rc_; + + /* Use Null Object (Variable) here for rc and badChar, so do not need to + * check elsewhere. + */ + if(NULL == badChar) + { + badChar = &badChar_; + } + if(NULL == rc) + { + rc = &rc_; + } + + return SecBase64Decode_(src, srcLen, (unsigned char*)dest, destSize, flags, badChar, rc); +} + +/* ////////////////////////////////////////////////////////////////////////// */ diff --git a/libsecurity_keychain/lib/SecBase64P.h b/libsecurity_keychain/lib/SecBase64P.h new file mode 100644 index 00000000..bfc0b797 --- /dev/null +++ b/libsecurity_keychain/lib/SecBase64P.h @@ -0,0 +1,247 @@ +/* ///////////////////////////////////////////////////////////////////////////// + * File: b64/b64.h + * + * Purpose: Header file for the b64 library + * + * Created: 18th October 2004 + * Updated: 2nd August 2006 + * + * Thanks: To Adam McLaurin, for ideas regarding the SecBase64Decode2() and SecBase64Encode2(). + * + * Home: http://synesis.com.au/software/ + * + * Copyright (c) 2004-2006, Matthew Wilson and Synesis Software + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * - Neither the name(s) of Matthew Wilson and Synesis Software nor the names of + * any contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * ////////////////////////////////////////////////////////////////////////// */ + + +/** \file b64/b64.h + * + * \brief [C/C++] Header file for the b64 library. + */ + +#ifndef _SEC_BASE64_H_ +#define _SEC_BASE64_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* ///////////////////////////////////////////////////////////////////////////// + * Enumerations + */ + +/** \brief Return codes (from SecBase64Encode2() / SecBase64Decode2()) + */ +enum +{ + kSecB64_R_OK = 0, /*!< operation was successful. */ + kSecB64_R_INSUFFICIENT_BUFFER = 1, /*!< The given translation buffer was not of sufficient size. */ + kSecB64_R_TRUNCATED_INPUT = 2, /*!< The input did not represent a fully formed stream of octet couplings. */ + kSecB64_R_DATA_ERROR = 3 /*!< invalid data. */ +}; + +typedef uint32_t SecBase64Result; + +/** \brief Coding behaviour modification flags (for SecBase64Encode2() / SecBase64Decode2()) + */ +enum +{ + kSecB64_F_LINE_LEN_USE_PARAM = 0x0000 /*!< Uses the lineLen parameter to SecBase64Encode2(). Ignored by SecBase64Decode2(). */ + , kSecB64_F_LINE_LEN_INFINITE = 0x0001 /*!< Ignores the lineLen parameter to SecBase64Encode2(). Line length is infinite. Ignored by SecBase64Decode2(). */ + , kSecB64_F_LINE_LEN_64 = 0x0002 /*!< Ignores the lineLen parameter to SecBase64Encode2(). Line length is 64. Ignored by SecBase64Decode2(). */ + , kSecB64_F_LINE_LEN_76 = 0x0003 /*!< Ignores the lineLen parameter to SecBase64Encode2(). Line length is 76. Ignored by SecBase64Decode2(). */ + , kSecB64_F_LINE_LEN_MASK = 0x000f /*!< Mask for testing line length flags to SecBase64Encode2(). Ignored by SecBase64Encode2(). */ + , kSecB64_F_STOP_ON_NOTHING = 0x0000 /*!< Decoding ignores all invalid characters in the input data. Ignored by SecBase64Encode2(). */ + , kSecB64_F_STOP_ON_UNKNOWN_CHAR = 0x0100 /*!< Causes decoding to break if any non-Base-64 [a-zA-Z0-9=+/], non-whitespace character is encountered. Ignored by SecBase64Encode2(). */ + , kSecB64_F_STOP_ON_UNEXPECTED_WS = 0x0200 /*!< Causes decoding to break if any unexpected whitespace is encountered. Ignored by SecBase64Encode2(). */ + , kSecB64_F_STOP_ON_BAD_CHAR = 0x0300 /*!< Causes decoding to break if any non-Base-64 [a-zA-Z0-9=+/] character is encountered. Ignored by SecBase64Encode2(). */ +}; + +typedef uint32_t SecBase64Flags; + +/* ///////////////////////////////////////////////////////////////////////////// + * Functions + */ + +#if 0 +static inline size_t SecBase64EncodedSize(size_t srcSize, size_t lineLen) { + size_t total = (((srcSize) + 2) / 3) * 4; + size_t lineLen = (lineLen); + if (lineLen > 0) { + size_t numLines = (total + (lineLen - 1)) / lineLen; + total += 2 * (numLines - 1); + } + return total; +} +#endif + +/** \brief Encodes a block of binary data into base64 + * + * \param src Pointer to the block to be encoded. May not be NULL, except when + * \c dest is NULL, in which case it is ignored. + * \param srcSize Length of block to be encoded + * \param dest Pointer to the buffer into which the result is to be written. May + * be NULL, in which case the function returns the required length + * \param destLen Length of the buffer into which the result is to be written. Must + * be at least as large as that indicated by the return value from + * \c SecBase64Encode()(NULL, srcSize, NULL, 0). + * + * \return 0 if the size of the buffer was insufficient, or the length of the + * converted buffer was longer than \c destLen + * + * \note The function returns the required length if \c dest is NULL + * + * \note The function returns the required length if \c dest is NULL. The returned size + * might be larger than the actual required size, but will never be smaller. + * + * \note Threading: The function is fully re-entrant. + */ +size_t SecBase64Encode(void const *src, size_t srcSize, char *dest, size_t destLen); + +/** \brief Encodes a block of binary data into base64 + * + * \param src Pointer to the block to be encoded. May not be NULL, except when + * \c dest is NULL, in which case it is ignored. + * \param srcSize Length of block to be encoded + * \param dest Pointer to the buffer into which the result is to be written. May + * be NULL, in which case the function returns the required length + * \param destLen Length of the buffer into which the result is to be written. Must + * be at least as large as that indicated by the return value from + * \c SecBase64Encode()(NULL, srcSize, NULL, 0). + * \param flags A combination of the SecBase64Flags enumeration, that moderate the + * behaviour of the function + * \param lineLen If the flags parameter contains kSecB64_F_LINE_LEN_USE_PARAM, then + * this parameter represents the length of the lines into which the encoded form is split, + * with a hard line break ('\\r\\n'). If this value is 0, then the line is not + * split. If it is <0, then the RFC-1113 recommended line length of 64 is used + * \param rc The return code representing the status of the operation. May be NULL. + * + * \return 0 if the size of the buffer was insufficient, or the length of the + * converted buffer was longer than \c destLen + * + * \note The function returns the required length if \c dest is NULL. The returned size + * might be larger than the actual required size, but will never be smaller. + * + * \note Threading: The function is fully re-entrant. + */ +size_t SecBase64Encode2( void const *src + , size_t srcSize + , char *dest + , size_t destLen + , unsigned flags + , int lineLen /* = 0 */ + , SecBase64Result *rc /* = NULL */); + +/** \brief Decodes a sequence of base64 into a block of binary data + * + * \param src Pointer to the base64 block to be decoded. May not be NULL, except when + * \c dest is NULL, in which case it is ignored. If \c dest is NULL, and \c src is + * not NULL, then the returned value is calculated exactly, otherwise a value + * is returned that is guaranteed to be large enough to hold the decoded block. + * + * \param srcLen Length of block to be encoded. Must be an integral of 4, the base64 + * encoding quantum, otherwise the base64 block is assumed to be invalid + * \param dest Pointer to the buffer into which the result is to be written. May + * be NULL, in which case the function returns the required length + * \param destSize Length of the buffer into which the result is to be written. Must + * be at least as large as that indicated by the return value from + * \c SecBase64Decode(src, srcSize, NULL, 0), even in the case where the encoded form + * contains a number of characters that will be ignored, resulting in a lower total + * length of converted form. + * + * \return 0 if the size of the buffer was insufficient, or the length of the + * converted buffer was longer than \c destSize + * + * \note The function returns the required length if \c dest is NULL. The returned size + * might be larger than the actual required size, but will never be smaller. + * + * \note \anchor anchor__4_characters The behaviour of both + * \link b64::SecBase64Encode2 SecBase64Encode2()\endlink + * and + * \link b64::SecBase64Decode2 SecBase64Decode2()\endlink + * are undefined if the line length is not a multiple of 4. + * + * \note Threading: The function is fully re-entrant. + */ +size_t SecBase64Decode(char const *src, size_t srcLen, void *dest, size_t destSize); + +/** \brief Decodes a sequence of base64 into a block of binary data + * + * \param src Pointer to the base64 block to be decoded. May not be NULL, except when + * \c dest is NULL, in which case it is ignored. If \c dest is NULL, and \c src is + * not NULL, then the returned value is calculated exactly, otherwise a value + * is returned that is guaranteed to be large enough to hold the decoded block. + * + * \param srcLen Length of block to be encoded. Must be an integral of 4, the base64 + * encoding quantum, otherwise the base64 block is assumed to be invalid + * \param dest Pointer to the buffer into which the result is to be written. May + * be NULL, in which case the function returns the required length + * \param destSize Length of the buffer into which the result is to be written. Must + * be at least as large as that indicated by the return value from + * \c SecBase64Decode(src, srcSize, NULL, 0), even in the case where the encoded form + * contains a number of characters that will be ignored, resulting in a lower total + * length of converted form. + * \param flags A combination of the SecBase64Flags enumeration, that moderate the + * behaviour of the function. + * \param rc The return code representing the status of the operation. May be NULL. + * \param badChar If the flags parameter does not contain kSecB64_F_STOP_ON_NOTHING, this + * parameter specifies the address of a pointer that will be set to point to any + * character in the sequence that stops the parsing, as dictated by the flags + * parameter. May be NULL. + * + * \return 0 if the size of the buffer was insufficient, or the length of the + * converted buffer was longer than \c destSize, or a bad character stopped parsing. + * + * \note The function returns the required length if \c dest is NULL. The returned size + * might be larger than the actual required size, but will never be smaller. + * + * \note The behaviour of both + * \link b64::SecBase64Encode2 SecBase64Encode2()\endlink + * and + * \link b64::SecBase64Decode2 SecBase64Decode2()\endlink + * are undefined if the line length is not a multiple of 4. + * + * \note Threading: The function is fully re-entrant. + */ +size_t SecBase64Decode2( char const *src + , size_t srcLen + , void *dest + , size_t destSize + , unsigned flags + , char const **badChar /* = NULL */ + , SecBase64Result *rc /* = NULL */); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _SEC_BASE64_H_ */ diff --git a/libsecurity_keychain/lib/SecBaseP.h b/libsecurity_keychain/lib/SecBaseP.h new file mode 100644 index 00000000..1259d65c --- /dev/null +++ b/libsecurity_keychain/lib/SecBaseP.h @@ -0,0 +1,91 @@ +/* + * 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@ + */ + +/*! + @header SecBase + SecBase contains common declarations for the Security functions. +*/ + +#ifndef _SECURITY_SECBASEP_H_ +#define _SECURITY_SECBASEP_H_ + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + +/*! + @typedef SecCertificateRef + @abstract CFType representing a X.509 certificate, see + SecCertificate.h for details. +*/ +typedef struct __SecCertificate *SecCertificateRefP; + +/*! + @typedef SecIdentityRef + @abstract CFType representing an identity, which contains + a SecKeyRef and an ascociated SecCertificateRef, see + SecIdentity.h for details. +*/ +typedef struct __SecIdentity *SecIdentityRefP; + +/*! + @typedef SecKeyRef + @abstract CFType representing an asymetric key, see + SecKey.h for details. +*/ +typedef struct __SecKey *SecKeyRefP; + +/*********************************************** + *** 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. +*/ + +#if 0 +enum +{ + errSecSuccess = 0, /* No error. */ + errSecUnimplemented = -4, /* Function or operation not implemented. */ + errSecParam = -50, /* One or more parameters passed to a function where not valid. */ + errSecAllocate = -108, /* Failed to allocate memory. */ + 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. */ +}; +#endif + +#if defined(__cplusplus) +} +#endif + +#endif /* !_SECURITY_SECBASEP_H_ */ diff --git a/libsecurity_keychain/lib/SecBasePriv.h b/libsecurity_keychain/lib/SecBasePriv.h new file mode 100644 index 00000000..869b8edb --- /dev/null +++ b/libsecurity_keychain/lib/SecBasePriv.h @@ -0,0 +1,91 @@ +/* + * 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/SecBridge.h b/libsecurity_keychain/lib/SecBridge.h new file mode 100644 index 00000000..5626f81e --- /dev/null +++ b/libsecurity_keychain/lib/SecBridge.h @@ -0,0 +1,69 @@ +/* + * 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@ + */ + +#ifndef _SECURITY_SECBRIDGE_H_ +#define _SECURITY_SECBRIDGE_H_ + +#include +#include +#include "SecBasePriv.h" +#include +#include +#include + +using namespace KeychainCore; + +// +// API boilerplate macros. These provide a frame for C++ code that is impermeable to exceptions. +// Usage: +// BEGIN_API +// ... your C++ code here ... +// END_API // returns CSSM_RETURN on exception +// END_API0 // returns nothing (void) on exception +// END_API1(bad) // return (bad) on exception +// END_API2(name) // like END_API, with API name as debug scope for printing function result +// END_API3(name, bad) // like END_API1, with API name as debug scope for printing function result +// +#define BEGIN_SECAPI \ + OSStatus __secapiresult = noErr; \ + try { +#define END_SECAPI }\ + catch (const MacOSError &err) { __secapiresult=err.osStatus(); } \ + catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); } \ + catch (const std::bad_alloc &) { __secapiresult=memFullErr; } \ + catch (...) { __secapiresult=internalComponentErr; } \ + return __secapiresult; +#define END_SECAPI1(BAD_RETURN_VAL) \ + } \ + catch (...) \ + { \ + __secapiresult=BAD_RETURN_VAL; \ + } \ + return __secapiresult; +#define END_SECAPI1(BAD_RETURN_VAL) }\ + catch (...) { __secapiresult=BAD_RETURN_VAL; } \ + return __secapiresult; +#define END_SECAPI0 }\ + catch (...) { return; } + +#endif /* !_SECURITY_SECBRIDGE_H_ */ diff --git a/libsecurity_keychain/lib/SecCFTypes.cpp b/libsecurity_keychain/lib/SecCFTypes.cpp new file mode 100644 index 00000000..025b6bb7 --- /dev/null +++ b/libsecurity_keychain/lib/SecCFTypes.cpp @@ -0,0 +1,70 @@ +/* + * 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@ + */ + +// +// SecCFTypes.cpp - CF runtime interface +// + +#include +#include + +namespace Security +{ + +namespace KeychainCore +{ + +SecCFTypes & +gTypes() +{ + static ModuleNexus nexus; + + return nexus(); +} + +} // end namespace KeychainCore + +} // end namespace Security + +using namespace KeychainCore; + +SecCFTypes::SecCFTypes() : + Access("SecAccess"), + ACL("SecACL"), + Certificate("SecCertificate"), + CertificateRequest("SecCertificateRequest"), + Identity("SecIdentity"), + IdentityCursor("SecIdentitySearch"), + ItemImpl("SecKeychainItem"), + KCCursorImpl("SecKeychainSearch"), + KeychainImpl("SecKeychain"), + KeyItem("SecKey"), + PasswordImpl("SecPassword"), + Policy("SecPolicy"), + PolicyCursor("SecPolicySearch"), + Trust("SecTrust"), + TrustedApplication("SecTrustedApplication"), + ExtendedAttribute("SecKeychainItemExtendedAttributes") +{ +} + diff --git a/libsecurity_keychain/lib/SecCFTypes.h b/libsecurity_keychain/lib/SecCFTypes.h new file mode 100644 index 00000000..f58133f1 --- /dev/null +++ b/libsecurity_keychain/lib/SecCFTypes.h @@ -0,0 +1,107 @@ +/* + * 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@ + */ + +// +// SecCFTypes.h - CF runtime interface +// +#ifndef _SECURITY_SECCFTYPES_H_ +#define _SECURITY_SECCFTYPES_H_ + +#include +#include +#include + +namespace Security +{ + +namespace KeychainCore +{ + +/* Singleton that registers all the CFClass instances with the CFRuntime. + + To make something a CFTypeRef you need to make the actual object inheirit from SecCFObject and provide implementation of the virtual functions in that class. + + In addition to that you need to define an opque type for the C API like: + typedef struct __OpaqueYourObject *YourObjectRef; + + Add an instance of CFClass to the public section of SecCFTypes below to get it registered with the CFRuntime. + CFClass yourObject; + + XXX + In your C++ code you should use SecPointer to refer to instances of your class. SecPointers are just like autopointers and implement * and -> semantics. They refcount the underlying object. So to create an instance or your new object you would do something like: + + SecPointer instance(new YourObject()); + + SecPointers have copy semantics and if you subclass SecPointer and define a operator < on the subclass you can even safely store instances of your class in stl containers. + + Use then like this: + instance->somemethod(); + or if you want a reference to the underlying object: + YourObject &object = *instance; + if you want a pointer to the underlying object: + YourObject *object = instance.get(); + + In the API glue you will need to use: + SecPointer instance; + [...] get the instance somehow + return instance->handle(); + to return an opaque handle (the is a CFTypeRef) to your object. + + when you obtain an object as input use: + SecYourObjectRef ref; + SecPointer instance = YourObject::required(ref); + to get a SecPointer to an instance of your object from the external CFTypeRef. +*/ +class SecCFTypes +{ +public: + SecCFTypes(); + +public: + /* Add new instances of CFClass here that you want registered with the CF runtime. */ + CFClass Access; + CFClass ACL; + CFClass Certificate; + CFClass CertificateRequest; + CFClass Identity; + CFClass IdentityCursor; + CFClass ItemImpl; + CFClass KCCursorImpl; + CFClass KeychainImpl; + CFClass KeyItem; + CFClass PasswordImpl; + CFClass Policy; + CFClass PolicyCursor; + CFClass Trust; + CFClass TrustedApplication; + CFClass ExtendedAttribute; +}; + +extern SecCFTypes &gTypes(); + +} // end namespace KeychainCore + +} // end namespace Security + + +#endif // !_SECURITY_SECCFTYPES_H_ diff --git a/libsecurity_keychain/lib/SecCertificate.cpp b/libsecurity_keychain/lib/SecCertificate.cpp new file mode 100644 index 00000000..1f0494b7 --- /dev/null +++ b/libsecurity_keychain/lib/SecCertificate.cpp @@ -0,0 +1,901 @@ +/* + * 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@ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "SecBridge.h" + +// %%% used by SecCertificate{Copy,Set}Preference +#include +#include +#include +#include +#include +#include "CertificateValues.h" +#include "SecCertificateP.h" + +extern CSSM_KEYUSE ConvertArrayToKeyUsage(CFArrayRef usage); + + +using namespace CssmClient; + +CFTypeID +SecCertificateGetTypeID(void) +{ + BEGIN_SECAPI + + return gTypes().Certificate.typeID; + + END_SECAPI1(_kCFRuntimeNotATypeID) +} + + +OSStatus +SecCertificateCreateFromData(const CSSM_DATA *data, CSSM_CERT_TYPE type, CSSM_CERT_ENCODING encoding, SecCertificateRef *certificate) +{ + BEGIN_SECAPI + + SecPointer certificatePtr(new Certificate(Required(data), type, encoding)); + Required(certificate) = certificatePtr->handle(); + + END_SECAPI +} + +/* new in 10.6 */ +SecCertificateRef +SecCertificateCreateWithData(CFAllocatorRef allocator, CFDataRef data) +{ + SecCertificateRef certificate = NULL; + OSStatus __secapiresult; + try { + CSSM_DATA cssmCertData; + cssmCertData.Length = (data) ? (CSSM_SIZE)CFDataGetLength(data) : 0; + cssmCertData.Data = (data) ? (uint8 *)CFDataGetBytePtr(data) : NULL; + + //NOTE: there isn't yet a Certificate constructor which accepts a CFAllocatorRef + SecPointer certificatePtr(new Certificate(cssmCertData, CSSM_CERT_X_509v3, CSSM_CERT_ENCODING_DER)); + certificate = certificatePtr->handle(); + + __secapiresult=noErr; + } + catch (const MacOSError &err) { __secapiresult=err.osStatus(); } + catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); } + catch (const std::bad_alloc &) { __secapiresult=memFullErr; } + catch (...) { __secapiresult=internalComponentErr; } + return certificate; +} + +OSStatus +SecCertificateAddToKeychain(SecCertificateRef certificate, SecKeychainRef keychain) +{ + BEGIN_SECAPI + + Item item(Certificate::required(certificate)); + Keychain::optional(keychain)->add(item); + + END_SECAPI +} + +OSStatus +SecCertificateGetData(SecCertificateRef certificate, CSSM_DATA_PTR data) +{ + BEGIN_SECAPI + + Required(data) = Certificate::required(certificate)->data(); + + END_SECAPI +} + +/* new in 10.6 */ +CFDataRef +SecCertificateCopyData(SecCertificateRef certificate) +{ + CFDataRef data = NULL; + OSStatus __secapiresult; + try { + CssmData output = Certificate::required(certificate)->data(); + CFIndex length = (CFIndex)output.length(); + const UInt8 *bytes = (const UInt8 *)output.data(); + if (length && bytes) { + data = CFDataCreate(NULL, bytes, length); + } + __secapiresult=noErr; + } + catch (const MacOSError &err) { __secapiresult=err.osStatus(); } + catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); } + catch (const std::bad_alloc &) { __secapiresult=memFullErr; } + catch (...) { __secapiresult=internalComponentErr; } + return data; +} + +OSStatus +SecCertificateGetType(SecCertificateRef certificate, CSSM_CERT_TYPE *certificateType) +{ + BEGIN_SECAPI + + Required(certificateType) = Certificate::required(certificate)->type(); + + END_SECAPI +} + + +OSStatus +SecCertificateGetSubject(SecCertificateRef certificate, const CSSM_X509_NAME **subject) +{ + BEGIN_SECAPI + + Required(subject) = Certificate::required(certificate)->subjectName(); + + END_SECAPI +} + + +OSStatus +SecCertificateGetIssuer(SecCertificateRef certificate, const CSSM_X509_NAME **issuer) +{ + BEGIN_SECAPI + + Required(issuer) = Certificate::required(certificate)->issuerName(); + + END_SECAPI +} + + +OSStatus +SecCertificateGetCLHandle(SecCertificateRef certificate, CSSM_CL_HANDLE *clHandle) +{ + BEGIN_SECAPI + + Required(clHandle) = Certificate::required(certificate)->clHandle(); + + END_SECAPI +} + +/* + * 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) +{ + BEGIN_SECAPI + + Certificate::required(certificate)->inferLabel(false, + &Required(label)); + + END_SECAPI +} + +OSStatus +SecCertificateCopyPublicKey(SecCertificateRef certificate, SecKeyRef *key) +{ + BEGIN_SECAPI + + Required(key) = Certificate::required(certificate)->publicKey()->handle(); + + END_SECAPI +} + +OSStatus +SecCertificateGetAlgorithmID(SecCertificateRef certificate, const CSSM_X509_ALGORITHM_IDENTIFIER **algid) +{ + BEGIN_SECAPI + + Required(algid) = Certificate::required(certificate)->algorithmID(); + + END_SECAPI +} + +OSStatus +SecCertificateCopyCommonName(SecCertificateRef certificate, CFStringRef *commonName) +{ + BEGIN_SECAPI + + Required(commonName) = Certificate::required(certificate)->commonName(); + + END_SECAPI +} + +/* new in 10.6 */ +CFStringRef +SecCertificateCopySubjectSummary(SecCertificateRef certificate) +{ + CFStringRef summary = NULL; + OSStatus __secapiresult; + try { + Certificate::required(certificate)->inferLabel(false, &summary); + + __secapiresult=noErr; + } + catch (const MacOSError &err) { __secapiresult=err.osStatus(); } + catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); } + catch (const std::bad_alloc &) { __secapiresult=memFullErr; } + catch (...) { __secapiresult=internalComponentErr; } + return summary; +} + +OSStatus +SecCertificateCopySubjectComponent(SecCertificateRef certificate, const CSSM_OID *component, CFStringRef *result) +{ + BEGIN_SECAPI + + Required(result) = Certificate::required(certificate)->distinguishedName(&CSSMOID_X509V1SubjectNameCStruct, component); + + END_SECAPI +} + +OSStatus +SecCertificateGetCommonName(SecCertificateRef certificate, CFStringRef *commonName) +{ + // deprecated SPI signature; replaced by SecCertificateCopyCommonName + return SecCertificateCopyCommonName(certificate, commonName); +} + +OSStatus +SecCertificateGetEmailAddress(SecCertificateRef certificate, CFStringRef *emailAddress) +{ + BEGIN_SECAPI + + Required(emailAddress) = Certificate::required(certificate)->copyFirstEmailAddress(); + + END_SECAPI +} + +OSStatus +SecCertificateCopyEmailAddresses(SecCertificateRef certificate, CFArrayRef *emailAddresses) +{ + BEGIN_SECAPI + + Required(emailAddresses) = Certificate::required(certificate)->copyEmailAddresses(); + + END_SECAPI +} + +OSStatus +SecCertificateCopyFieldValues(SecCertificateRef certificate, const CSSM_OID *field, CSSM_DATA_PTR **fieldValues) +{ +/* Return a zero terminated list of CSSM_DATA_PTR's with the values of the field specified by field. Caller must call releaseFieldValues to free the storage allocated by this call. */ + BEGIN_SECAPI + + Required(fieldValues) = Certificate::required(certificate)->copyFieldValues(Required(field)); + + END_SECAPI +} + +OSStatus +SecCertificateReleaseFieldValues(SecCertificateRef certificate, const CSSM_OID *field, CSSM_DATA_PTR *fieldValues) +{ + BEGIN_SECAPI + + Certificate::required(certificate)->releaseFieldValues(Required(field), fieldValues); + + END_SECAPI +} + +OSStatus +SecCertificateCopyFirstFieldValue(SecCertificateRef certificate, const CSSM_OID *field, CSSM_DATA_PTR *fieldValue) +{ + BEGIN_SECAPI + + Required(fieldValue) = Certificate::required(certificate)->copyFirstFieldValue(Required(field)); + + END_SECAPI +} + +OSStatus +SecCertificateReleaseFirstFieldValue(SecCertificateRef certificate, const CSSM_OID *field, CSSM_DATA_PTR fieldValue) +{ + BEGIN_SECAPI + + Certificate::required(certificate)->releaseFieldValue(Required(field), fieldValue); + + END_SECAPI +} + +OSStatus +SecCertificateFindByIssuerAndSN(CFTypeRef keychainOrArray,const CSSM_DATA *issuer, + const CSSM_DATA *serialNumber, SecCertificateRef *certificate) +{ + BEGIN_SECAPI + + StorageManager::KeychainList keychains; + globals().storageManager.optionalSearchList(keychainOrArray, keychains); + Required(certificate) = Certificate::findByIssuerAndSN(keychains, CssmData::required(issuer), CssmData::required(serialNumber))->handle(); + + END_SECAPI +} + +OSStatus +SecCertificateFindBySubjectKeyID(CFTypeRef keychainOrArray, const CSSM_DATA *subjectKeyID, + SecCertificateRef *certificate) +{ + BEGIN_SECAPI + + StorageManager::KeychainList keychains; + globals().storageManager.optionalSearchList(keychainOrArray, keychains); + Required(certificate) = Certificate::findBySubjectKeyID(keychains, CssmData::required(subjectKeyID))->handle(); + + END_SECAPI +} + +OSStatus +SecCertificateFindByEmail(CFTypeRef keychainOrArray, const char *emailAddress, SecCertificateRef *certificate) +{ + BEGIN_SECAPI + + StorageManager::KeychainList keychains; + globals().storageManager.optionalSearchList(keychainOrArray, keychains); + Required(certificate) = Certificate::findByEmail(keychains, emailAddress)->handle(); + + END_SECAPI +} + +OSStatus +SecKeychainSearchCreateForCertificateByIssuerAndSN(CFTypeRef keychainOrArray, const CSSM_DATA *issuer, + const CSSM_DATA *serialNumber, SecKeychainSearchRef *searchRef) +{ + BEGIN_SECAPI + + Required(searchRef); + + StorageManager::KeychainList keychains; + globals().storageManager.optionalSearchList(keychainOrArray, keychains); + KCCursor cursor(Certificate::cursorForIssuerAndSN(keychains, CssmData::required(issuer), CssmData::required(serialNumber))); + *searchRef = cursor->handle(); + + END_SECAPI +} + +OSStatus +SecKeychainSearchCreateForCertificateByIssuerAndSN_CF(CFTypeRef keychainOrArray, CFDataRef issuer, + CFDataRef serialNumber, SecKeychainSearchRef *searchRef) +{ + BEGIN_SECAPI + + Required(searchRef); + + StorageManager::KeychainList keychains; + globals().storageManager.optionalSearchList(keychainOrArray, keychains); + Required(issuer); + Required(serialNumber); + KCCursor cursor(Certificate::cursorForIssuerAndSN_CF(keychains, issuer, serialNumber)); + *searchRef = cursor->handle(); + + END_SECAPI +} + +OSStatus +SecKeychainSearchCreateForCertificateBySubjectKeyID(CFTypeRef keychainOrArray, const CSSM_DATA *subjectKeyID, + SecKeychainSearchRef *searchRef) +{ + BEGIN_SECAPI + + Required(searchRef); + + StorageManager::KeychainList keychains; + globals().storageManager.optionalSearchList(keychainOrArray, keychains); + KCCursor cursor(Certificate::cursorForSubjectKeyID(keychains, CssmData::required(subjectKeyID))); + *searchRef = cursor->handle(); + + END_SECAPI +} + +OSStatus +SecKeychainSearchCreateForCertificateByEmail(CFTypeRef keychainOrArray, const char *emailAddress, + SecKeychainSearchRef *searchRef) +{ + BEGIN_SECAPI + + Required(searchRef); + + StorageManager::KeychainList keychains; + globals().storageManager.optionalSearchList(keychainOrArray, keychains); + KCCursor cursor(Certificate::cursorForEmail(keychains, emailAddress)); + *searchRef = cursor->handle(); + + END_SECAPI +} + +/* NOT EXPORTED YET; copied from SecurityInterface but could be useful in the future. +CSSM_CSP_HANDLE +SecGetAppleCSPHandle() +{ + BEGIN_SECAPI + return CSP(gGuidAppleCSP)->handle(); + END_SECAPI1(NULL); +} + +CSSM_CL_HANDLE +SecGetAppleCLHandle() +{ + BEGIN_SECAPI + return CL(gGuidAppleX509CL)->handle(); + END_SECAPI1(NULL); +} +*/ + +CSSM_RETURN +SecDigestGetData (CSSM_ALGORITHMS alg, CSSM_DATA* digest, const CSSM_DATA* data) +{ + BEGIN_SECAPI + // sanity checking + if (!digest || !digest->Data || !digest->Length || !data || !data->Data || !data->Length) + return paramErr; + + CSP csp(gGuidAppleCSP); + Digest context(csp, alg); + CssmData input(data->Data, data->Length); + CssmData output(digest->Data, digest->Length); + + context.digest(input, output); + digest->Length = output.length(); + + return CSSM_OK; + END_SECAPI1(1); +} + +/* determine whether a cert is self-signed */ +OSStatus SecCertificateIsSelfSigned( + SecCertificateRef certificate, + Boolean *isSelfSigned) /* RETURNED */ +{ + BEGIN_SECAPI + + *isSelfSigned = Certificate::required(certificate)->isSelfSigned(); + + END_SECAPI +} + +OSStatus +SecCertificateCopyPreference( + CFStringRef name, + CSSM_KEYUSE keyUsage, + SecCertificateRef *certificate) +{ + BEGIN_SECAPI + + Required(name); + Required(certificate); + StorageManager::KeychainList keychains; + globals().storageManager.getSearchList(keychains); + KCCursor cursor(keychains, kSecGenericPasswordItemClass, NULL); + + char idUTF8[MAXPATHLEN]; + if (!CFStringGetCString(name, idUTF8, sizeof(idUTF8)-1, kCFStringEncodingUTF8)) + idUTF8[0] = (char)'\0'; + CssmData service(const_cast(idUTF8), strlen(idUTF8)); + FourCharCode itemType = 'cprf'; + cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecServiceItemAttr), service); + cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecTypeItemAttr), itemType); + if (keyUsage) + cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecScriptCodeItemAttr), (sint32)keyUsage); + + Item prefItem; + if (!cursor->next(prefItem)) + MacOSError::throwMe(errSecItemNotFound); + + // get persistent certificate reference + SecKeychainAttribute itemAttrs[] = { { kSecGenericItemAttr, 0, NULL } }; + SecKeychainAttributeList itemAttrList = { sizeof(itemAttrs) / sizeof(itemAttrs[0]), itemAttrs }; + prefItem->getContent(NULL, &itemAttrList, NULL, NULL); + + // find certificate, given persistent reference data + CFDataRef pItemRef = CFDataCreateWithBytesNoCopy(NULL, (const UInt8 *)itemAttrs[0].data, itemAttrs[0].length, kCFAllocatorNull); + SecKeychainItemRef certItemRef = nil; + OSStatus status = SecKeychainItemCopyFromPersistentReference(pItemRef, &certItemRef); //%%% need to make this a method of ItemImpl + prefItem->freeContent(&itemAttrList, NULL); + if (pItemRef) + CFRelease(pItemRef); + if (status) + return status; + + *certificate = (SecCertificateRef)certItemRef; + + END_SECAPI +} + +SecCertificateRef +SecCertificateCopyPreferred( + CFStringRef name, + CFArrayRef keyUsage) +{ + // This function will look for a matching preference in the following order: + // - matches the name and the supplied key use + // - matches the name and the special 'ANY' key use + // - matches the name with no key usage constraint + + SecCertificateRef certRef = NULL; + CSSM_KEYUSE keyUse = ConvertArrayToKeyUsage(keyUsage); + OSStatus status = SecCertificateCopyPreference(name, keyUse, &certRef); + if (status != noErr && keyUse != CSSM_KEYUSE_ANY) + status = SecCertificateCopyPreference(name, CSSM_KEYUSE_ANY, &certRef); + if (status != noErr && keyUse != 0) + status = SecCertificateCopyPreference(name, 0, &certRef); + + return certRef; +} + +OSStatus +SecCertificateFindPreferenceItemWithNameAndKeyUsage( + CFTypeRef keychainOrArray, + CFStringRef name, + int32_t keyUsage, + SecKeychainItemRef *itemRef) +{ + BEGIN_SECAPI + + StorageManager::KeychainList keychains; + globals().storageManager.optionalSearchList(keychainOrArray, keychains); + KCCursor cursor(keychains, kSecGenericPasswordItemClass, NULL); + + char idUTF8[MAXPATHLEN]; + idUTF8[0] = (char)'\0'; + if (name) + { + if (!CFStringGetCString(name, idUTF8, sizeof(idUTF8)-1, kCFStringEncodingUTF8)) + idUTF8[0] = (char)'\0'; + } + size_t idUTF8Len = strlen(idUTF8); + if (!idUTF8Len) + MacOSError::throwMe(paramErr); + + CssmData service(const_cast(idUTF8), idUTF8Len); + cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecServiceItemAttr), service); + cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecTypeItemAttr), (FourCharCode)'cprf'); + if (keyUsage) + cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecScriptCodeItemAttr), (sint32)keyUsage); + + Item item; + if (!cursor->next(item)) + MacOSError::throwMe(errSecItemNotFound); + + if (itemRef) + *itemRef=item->handle(); + + END_SECAPI +} + +OSStatus SecCertificateDeletePreferenceItemWithNameAndKeyUsage( + CFTypeRef keychainOrArray, + CFStringRef name, + int32_t keyUsage) +{ + // when a specific key usage is passed, we'll only match & delete that pref; + // when a key usage of 0 is passed, all matching prefs should be deleted. + // maxUsages represents the most matches there could theoretically be, so + // cut things off at that point if we're still finding items (if they can't + // be deleted for some reason, we'd never break out of the loop.) + + OSStatus status; + SecKeychainItemRef item = NULL; + int count = 0, maxUsages = 12; + while (++count <= maxUsages && + (status = SecCertificateFindPreferenceItemWithNameAndKeyUsage(keychainOrArray, name, keyUsage, &item)) == noErr) { + status = SecKeychainItemDelete(item); + CFRelease(item); + item = NULL; + } + + // it's not an error if the item isn't found + return (status == errSecItemNotFound) ? noErr : status; +} + +OSStatus SecCertificateSetPreference( + SecCertificateRef certificate, + CFStringRef name, + CSSM_KEYUSE keyUsage, + CFDateRef date) +{ + if (!name) { + return paramErr; + } + if (!certificate) { + // treat NULL certificate as a request to clear the preference + // (note: if keyUsage is 0, this clears all key usage prefs for name) + return SecCertificateDeletePreferenceItemWithNameAndKeyUsage(NULL, name, keyUsage); + } + + BEGIN_SECAPI + + // determine the account attribute + // + // This attribute must be synthesized from certificate label + pref item type + key usage, + // as only the account and service attributes can make a generic keychain item unique. + // For 'iprf' type items (but not 'cprf'), we append a trailing space. This insures that + // we can save a certificate preference if an identity preference already exists for the + // given service name, and vice-versa. + // If the key usage is 0 (i.e. the normal case), we omit the appended key usage string. + // + CFStringRef labelStr = nil; + Certificate::required(certificate)->inferLabel(false, &labelStr); + if (!labelStr) { + MacOSError::throwMe(errSecDataTooLarge); // data is "in a format which cannot be displayed" + } + CFIndex accountUTF8Len = CFStringGetMaximumSizeForEncoding(CFStringGetLength(labelStr), kCFStringEncodingUTF8) + 1; + const char *templateStr = "%s [key usage 0x%X]"; + const int keyUsageMaxStrLen = 8; + accountUTF8Len += strlen(templateStr) + keyUsageMaxStrLen; + char accountUTF8[accountUTF8Len]; + if (!CFStringGetCString(labelStr, accountUTF8, accountUTF8Len-1, kCFStringEncodingUTF8)) + accountUTF8[0] = (char)'\0'; + if (keyUsage) + snprintf(accountUTF8, accountUTF8Len-1, templateStr, accountUTF8, keyUsage); + CssmData account(const_cast(accountUTF8), strlen(accountUTF8)); + CFRelease(labelStr); + + // service attribute (name provided by the caller) + CFIndex serviceUTF8Len = CFStringGetMaximumSizeForEncoding(CFStringGetLength(name), kCFStringEncodingUTF8) + 1;; + char serviceUTF8[serviceUTF8Len]; + if (!CFStringGetCString(name, serviceUTF8, serviceUTF8Len-1, kCFStringEncodingUTF8)) + serviceUTF8[0] = (char)'\0'; + CssmData service(const_cast(serviceUTF8), strlen(serviceUTF8)); + + // look for existing preference item, in case this is an update + StorageManager::KeychainList keychains; + globals().storageManager.getSearchList(keychains); + KCCursor cursor(keychains, kSecGenericPasswordItemClass, NULL); + FourCharCode itemType = 'cprf'; + cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecServiceItemAttr), service); + cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecTypeItemAttr), itemType); + if (keyUsage) + cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecScriptCodeItemAttr), (sint32)keyUsage); + if (date) + ; // %%%TBI + + Item item(kSecGenericPasswordItemClass, 'aapl', 0, NULL, false); + bool add = (!cursor->next(item)); + // at this point, we either have a new item to add or an existing item to update + + // set item attribute values + item->setAttribute(Schema::attributeInfo(kSecServiceItemAttr), service); + item->setAttribute(Schema::attributeInfo(kSecTypeItemAttr), itemType); + item->setAttribute(Schema::attributeInfo(kSecAccountItemAttr), account); + item->setAttribute(Schema::attributeInfo(kSecScriptCodeItemAttr), (sint32)keyUsage); + item->setAttribute(Schema::attributeInfo(kSecLabelItemAttr), service); + + // date + if (date) + ; // %%%TBI + + // generic attribute (store persistent certificate reference) + CFDataRef pItemRef = nil; + Certificate::required(certificate)->copyPersistentReference(pItemRef); + if (!pItemRef) { + MacOSError::throwMe(errSecInvalidItemRef); + } + const UInt8 *dataPtr = CFDataGetBytePtr(pItemRef); + CFIndex dataLen = CFDataGetLength(pItemRef); + CssmData pref(const_cast(reinterpret_cast(dataPtr)), dataLen); + item->setAttribute(Schema::attributeInfo(kSecGenericItemAttr), pref); + CFRelease(pItemRef); + + if (add) { + Keychain keychain = nil; + try { + keychain = globals().storageManager.defaultKeychain(); + if (!keychain->exists()) + MacOSError::throwMe(errSecNoSuchKeychain); // Might be deleted or not available at this time. + } + catch(...) { + keychain = globals().storageManager.defaultKeychainUI(item); + } + + try { + keychain->add(item); + } + catch (const MacOSError &err) { + if (err.osStatus() != errSecDuplicateItem) + throw; // if item already exists, fall through to update + } + } + item->update(); + + END_SECAPI +} + +OSStatus SecCertificateSetPreferred( + SecCertificateRef certificate, + CFStringRef name, + CFArrayRef keyUsage) +{ + CSSM_KEYUSE keyUse = ConvertArrayToKeyUsage(keyUsage); + return SecCertificateSetPreference(certificate, name, keyUse, NULL); +} + +CFDictionaryRef SecCertificateCopyValues(SecCertificateRef certificate, CFArrayRef keys, CFErrorRef *error) +{ + CFDictionaryRef result = NULL; + OSStatus __secapiresult; + try + { + CertificateValues cv(certificate); + result = cv.copyFieldValues(keys,error); + __secapiresult=0; + } + catch (const MacOSError &err) { __secapiresult=err.osStatus(); } + catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); } + catch (const std::bad_alloc &) { __secapiresult=memFullErr; } + catch (...) { __secapiresult=internalComponentErr; } + return result; +} + +CFStringRef SecCertificateCopyLongDescription(CFAllocatorRef alloc, SecCertificateRef certificate, CFErrorRef *error) +{ + return SecCertificateCopyShortDescription(alloc, certificate, error); +} + +CFStringRef SecCertificateCopyShortDescription(CFAllocatorRef alloc, SecCertificateRef certificate, CFErrorRef *error) +{ + CFStringRef result = NULL; + OSStatus __secapiresult; + try + { + __secapiresult = SecCertificateInferLabel(certificate, &result); + } + catch (const MacOSError &err) { __secapiresult=err.osStatus(); } + catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); } + catch (const std::bad_alloc &) { __secapiresult=memFullErr; } + catch (...) { __secapiresult=internalComponentErr; } + if (error!=NULL && __secapiresult!=noErr) + { + *error = CFErrorCreate(kCFAllocatorDefault, kCFErrorDomainOSStatus, + __secapiresult ? __secapiresult : CSSM_ERRCODE_INTERNAL_ERROR, NULL); + } + return result; +} + +CFDataRef SecCertificateCopySerialNumber(SecCertificateRef certificate, CFErrorRef *error) +{ + CFDataRef result = NULL; + OSStatus __secapiresult; + try + { + CertificateValues cv(certificate); + result = cv.copySerialNumber(error); + __secapiresult=0; + } + catch (const MacOSError &err) { __secapiresult=err.osStatus(); } + catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); } + catch (const std::bad_alloc &) { __secapiresult=memFullErr; } + catch (...) { __secapiresult=internalComponentErr; } + return result; +} + +CFDataRef SecCertificateCopyNormalizedIssuerContent(SecCertificateRef certificate, CFErrorRef *error) +{ + CFDataRef result = NULL; + OSStatus __secapiresult; + try + { + CertificateValues cv(certificate); + result = cv.getNormalizedIssuerContent(error); + __secapiresult=0; + } + catch (const MacOSError &err) { __secapiresult=err.osStatus(); } + catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); } + catch (const std::bad_alloc &) { __secapiresult=memFullErr; } + catch (...) { __secapiresult=internalComponentErr; } + return result; +} + +CFDataRef SecCertificateCopyNormalizedSubjectContent(SecCertificateRef certificate, CFErrorRef *error) +{ + CFDataRef result = NULL; + OSStatus __secapiresult; + try + { + CertificateValues cv(certificate); + result = cv.getNormalizedSubjectContent(error); + __secapiresult=0; + } + catch (const MacOSError &err) { __secapiresult=err.osStatus(); } + catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); } + catch (const std::bad_alloc &) { __secapiresult=memFullErr; } + catch (...) { __secapiresult=internalComponentErr; } + return result; +} + +bool SecCertificateIsValidX(SecCertificateRef certificate, CFAbsoluteTime verifyTime) +{ + bool result = NULL; + OSStatus __secapiresult; + try + { + CFErrorRef error = NULL; + CertificateValues cv(certificate); + result = cv.SecCertificateIsValidX(verifyTime, &error); + __secapiresult=0; + } + catch (const MacOSError &err) { __secapiresult=err.osStatus(); } + catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); } + catch (const std::bad_alloc &) { __secapiresult=memFullErr; } + catch (...) { __secapiresult=internalComponentErr; } + return result; +} + +/* new in 10.8 */ +SecCertificateRef SecCertificateCreateWithBytes(CFAllocatorRef allocator, + const UInt8 *bytes, CFIndex length) +{ + SecCertificateRef certificate = NULL; + OSStatus __secapiresult; + try { + CSSM_DATA cssmCertData = { (CSSM_SIZE)length, (uint8 *)bytes }; + + //NOTE: there isn't yet a Certificate constructor which accepts a CFAllocatorRef + SecPointer certificatePtr(new Certificate(cssmCertData, CSSM_CERT_X_509v3, CSSM_CERT_ENCODING_DER)); + certificate = certificatePtr->handle(); + + __secapiresult=noErr; + } + catch (const MacOSError &err) { __secapiresult=err.osStatus(); } + catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); } + catch (const std::bad_alloc &) { __secapiresult=memFullErr; } + catch (...) { __secapiresult=internalComponentErr; } + return certificate; +} + +/* new in 10.8 */ +CFIndex SecCertificateGetLength(SecCertificateRef certificate) +{ + CFIndex length = 0; + OSStatus __secapiresult; + try { + CssmData output = Certificate::required(certificate)->data(); + length = (CFIndex)output.length(); + __secapiresult=noErr; + } + catch (const MacOSError &err) { __secapiresult=err.osStatus(); } + catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); } + catch (const std::bad_alloc &) { __secapiresult=memFullErr; } + catch (...) { __secapiresult=internalComponentErr; } + return length; +} + +/* new in 10.8 */ +const UInt8 *SecCertificateGetBytePtr(SecCertificateRef certificate) +{ + const UInt8 *bytes = NULL; + OSStatus __secapiresult; + try { + CssmData output = Certificate::required(certificate)->data(); + bytes = (const UInt8 *)output.data(); + __secapiresult=noErr; + } + catch (const MacOSError &err) { __secapiresult=err.osStatus(); } + catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); } + catch (const std::bad_alloc &) { __secapiresult=memFullErr; } + catch (...) { __secapiresult=internalComponentErr; } + return bytes; +} + diff --git a/libsecurity_keychain/lib/SecCertificate.h b/libsecurity_keychain/lib/SecCertificate.h new file mode 100644 index 00000000..2e43b9bf --- /dev/null +++ b/libsecurity_keychain/lib/SecCertificate.h @@ -0,0 +1,466 @@ +/* + * 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 == noErr) && (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 == noErr) && (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/libsecurity_keychain/lib/SecCertificateBundle.cpp new file mode 100644 index 00000000..fde9bb43 --- /dev/null +++ b/libsecurity_keychain/lib/SecCertificateBundle.cpp @@ -0,0 +1,82 @@ +/* + * 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@ + */ + +#include + +#include "SecBridge.h" + +#if defined(__cplusplus) +extern "C" { +#endif +// misspelled function name is declared here so symbol won't be stripped +OSStatus SecCertifcateBundleExport( + CFArrayRef itemList, + CSSM_CERT_BUNDLE_TYPE type, + CSSM_CERT_BUNDLE_ENCODING encodingType, + CSSM_DATA* data); +#if defined(__cplusplus) +} +#endif + + +OSStatus +SecCertificateBundleImport( + SecKeychainRef keychain, + const CSSM_CERT_BUNDLE* bundle, + CSSM_CERT_BUNDLE_TYPE type, + CSSM_CERT_BUNDLE_ENCODING encodingType, + CFArrayRef keychainListToSkipDuplicates) +{ + BEGIN_SECAPI + + MacOSError::throwMe(unimpErr);//%%%for now + + END_SECAPI +} + + +OSStatus +SecCertificateBundleExport( + CFArrayRef certificates, + CSSM_CERT_BUNDLE_TYPE type, + CSSM_CERT_BUNDLE_ENCODING encodingType, + CSSM_DATA* data) +{ + BEGIN_SECAPI + + MacOSError::throwMe(unimpErr);//%%%for now + + END_SECAPI +} + +// note: misspelled function name is still exported as a precaution; +// can remove this after deprecation +OSStatus +SecCertifcateBundleExport( + CFArrayRef itemList, + CSSM_CERT_BUNDLE_TYPE type, + CSSM_CERT_BUNDLE_ENCODING encodingType, + CSSM_DATA* data) +{ + return SecCertificateBundleExport(itemList, type, encodingType, data); +} diff --git a/libsecurity_keychain/lib/SecCertificateBundle.h b/libsecurity_keychain/lib/SecCertificateBundle.h new file mode 100644 index 00000000..3929d8ec --- /dev/null +++ b/libsecurity_keychain/lib/SecCertificateBundle.h @@ -0,0 +1,77 @@ +/* + * 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 SecCertificateBundle + The functions provided in SecCertificateBundle implement a way to issue a certificate request to a + certificate authority. +*/ + +#ifndef _SECURITY_SECCERTIFICATEBUNDLE_H_ +#define _SECURITY_SECCERTIFICATEBUNDLE_H_ + +#include +#include +#include + +#if defined(__cplusplus) +extern "C" { +#endif + +/*! + @function SecCertificateBundleImport + @abstract Imports one or more certificates into a keychain with the specified encoding and bundle type. + @param keychain The destination keychain for the import. Specify NULL for the default keychain. + @param bundle A pointer to the bundle data. + @param type The bundle type as defined in cssmtype.h. + @param encodingType The bundle encoding type as defined in cssmtype.h. + @param keychainListToSkipDuplicates A reference to an array of keychains. These keychains contain certificates that shouldn't be duplicated during the import. + @result A result code. See "Security Error Codes" (SecBase.h). +*/ +OSStatus SecCertificateBundleImport( + SecKeychainRef keychain, + const CSSM_CERT_BUNDLE* bundle, + CSSM_CERT_BUNDLE_TYPE type, + CSSM_CERT_BUNDLE_ENCODING encodingType, + CFArrayRef keychainListToSkipDuplicates); + +/*! + @function SecCertificateBundleExport + @abstract Exports one or more certificates into a bundle with the specified encoding and bundle type. + @param certificates An array of certificate and keychain items used to help build the bundle. + @param type The bundle type as defined in cssmtype.h. If the bundle type is unknown, an attempt will be made to determine the type for you. + @param encodingType The encoding type as defined in cssmtype.h. + @param data A pointer to data. On return, this points to the bundle data. + @result A result code. See "Security Error Codes" (SecBase.h). +*/ +OSStatus SecCertificateBundleExport( + CFArrayRef certificates, + CSSM_CERT_BUNDLE_TYPE type, + CSSM_CERT_BUNDLE_ENCODING encodingType, + CSSM_DATA* data); + +#if defined(__cplusplus) +} +#endif + +#endif /* !_SECURITY_SECCERTIFICATEBUNDLE_H_ */ diff --git a/libsecurity_keychain/lib/SecCertificateInternalP.h b/libsecurity_keychain/lib/SecCertificateInternalP.h new file mode 100644 index 00000000..1c6b2692 --- /dev/null +++ b/libsecurity_keychain/lib/SecCertificateInternalP.h @@ -0,0 +1,311 @@ +/* + * 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@ + */ + +/* + SecCertificateInternal.h +*/ + +#ifndef _SECURITY_SECCERTIFICATEINTERNAL_H_ +#define _SECURITY_SECCERTIFICATEINTERNAL_H_ + +//#include +#include "SecCertificatePrivP.h" +#include "certextensionsP.h" +#include + +#if defined(__cplusplus) +extern "C" { +#endif + +CFDataRef SecCertificateGetAuthorityKeyID(SecCertificateRefP certificate); +CFDataRef SecCertificateGetSubjectKeyID(SecCertificateRefP certificate); + +/* Return an array of CFURLRefs each of which is an crl distribution point for + this certificate. */ +CFArrayRef SecCertificateGetCRLDistributionPoints(SecCertificateRefP certificate); + +/* Return an array of CFURLRefs each of which is an ocspResponder for this + certificate. */ +CFArrayRef SecCertificateGetOCSPResponders(SecCertificateRefP certificate); + +/* Return an array of CFURLRefs each of which is an caIssuer for this + certificate. */ +CFArrayRef SecCertificateGetCAIssuers(SecCertificateRefP certificate); + +/* Dump certificate for debugging. */ +void SecCertificateShow(SecCertificateRefP certificate); + +/* Return the DER encoded issuer sequence for the receiving certificates issuer. */ +CFDataRef SecCertificateCopyIssuerSequence(SecCertificateRefP certificate); + +/* Return the DER encoded subject sequence for the receiving certificates subject. */ +CFDataRef SecCertificateCopySubjectSequence(SecCertificateRefP certificate); + +/* Return the content of a DER encoded X.501 name (without the tag and length + fields) for the receiving certificates issuer. */ +CFDataRef SecCertificateGetNormalizedIssuerContent(SecCertificateRefP certificate); + +/* Return the content of a DER encoded X.501 name (without the tag and length + fields) for the receiving certificates subject. */ +CFDataRef SecCertificateGetNormalizedSubjectContent(SecCertificateRefP certificate); + +CFDataRef SecDERItemCopySequence(DERItem *content); + +/* Return true iff the certificate has a subject. */ +bool SecCertificateHasSubject(SecCertificateRefP certificate); +/* Return true iff the certificate has a critical subject alt name. */ +bool SecCertificateHasCriticalSubjectAltName(SecCertificateRefP certificate); + +/* Return true if certificate contains one or more critical extensions we + are unable to parse. */ +bool SecCertificateHasUnknownCriticalExtension(SecCertificateRefP certificate); + +/* Return true iff certificate is valid as of verifyTime. */ +bool SecCertificateIsValid(SecCertificateRefP certificate, + CFAbsoluteTime verifyTime); + +/* Return an attribute dictionary used to store this item in a keychain. */ +CFDictionaryRef SecCertificateCopyAttributeDictionary( + SecCertificateRefP certificate); + +/* Return a certificate from the attribute dictionary that was used to store + this item in a keychain. */ +SecCertificateRefP SecCertificateCreateFromAttributeDictionary( + CFDictionaryRef refAttributes); + +/* Return a SecKeyRef for the public key embedded in the cert. */ +SecKeyRefP SecCertificateCopyPublicKeyP(SecCertificateRefP certificate); + +/* Return the SecCEBasicConstraints extension for this certificate if it + has one. */ +const SecCEBasicConstraints * +SecCertificateGetBasicConstraints(SecCertificateRefP certificate); + +/* Return the SecCEPolicyConstraints extension for this certificate if it + has one. */ +const SecCEPolicyConstraints * +SecCertificateGetPolicyConstraints(SecCertificateRefP certificate); + +/* Return a dictionary from CFDataRef to CFArrayRef of CFDataRef + representing the policyMapping extension of this certificate. */ +CFDictionaryRef +SecCertificateGetPolicyMappings(SecCertificateRefP certificate); + +/* Return the SecCECertificatePolicies extension for this certificate if it + has one. */ +const SecCECertificatePolicies * +SecCertificateGetCertificatePolicies(SecCertificateRefP certificate); + +/* Returns UINT32_MAX if InhibitAnyPolicy extension is not present or invalid, + returns the value of the SkipCerts field of the InhibitAnyPolicy extension + otherwise. */ +uint32_t +SecCertificateGetInhibitAnyPolicySkipCerts(SecCertificateRefP certificate); + +/* Return the public key algorithm and parameters for certificate. */ +const DERAlgorithmId *SecCertificateGetPublicKeyAlgorithm( + SecCertificateRefP certificate); + +/* Return the raw public key data for certificate. */ +const DERItem *SecCertificateGetPublicKeyData(SecCertificateRefP certificate); + +#pragma mark - +#pragma mark Certificate Operations + +OSStatus SecCertificateIsSignedBy(SecCertificateRefP certificate, + SecKeyRefP issuerKey); + +#pragma mark - +#pragma mark Certificate Creation + +#ifdef OPTIONAL_METHODS +/* Return a certificate for the PEM representation of this certificate. + Return NULL the passed in der_certificate is not a valid DER encoded X.509 + certificate, and return a CFError by reference. It is the + responsibility of the caller to release the CFError. */ +SecCertificateRefP SecCertificateCreateWithPEM(CFAllocatorRef allocator, + CFStringRef pem_certificate); + +/* Return a CFStringRef containing the the pem representation of this + certificate. */ +CFStringRef SecCertificateGetPEM(SecCertificateRefP der_certificate); + +#endif /* OPTIONAL_METHODS */ + +#if 0 +/* Complete the certificate chain of this certificate, setting the parent + certificate for each certificate along they way. Return 0 if the + system is able to find all the certificates to complete the certificate + chain either in the passed in other_certificates array or in the user or + the systems keychain(s). + If the certifcates issuer chain can not be completed, this function + will return an error status code. + NOTE: This function does not verify whether the certificate is trusted it's + main use is just to ensure that anyone using this certificate upstream will + have access to a complete (or as complete as possible in the case of + something going wrong) certificate chain. */ +OSStatus SecCertificateCompleteChain(SecCertificateRefP certificate, + CFArrayRef other_certificates); +#endif + +#if 0 + +/*! + @function SecCertificateGetVersionNumber + @abstract Retrieves the version of a given certificate as a CFNumberRef. + @param certificate A reference to the certificate from which to obtain the certificate version. + @result A CFNumberRef representing the certificate version. The following values are currently known to be returned, but more may be added in the future: + 1: X509v1 + 2: X509v2 + 3: X509v3 +*/ +CFNumberRef SecCertificateGetVersionNumber(SecCertificateRefP certificate); + +/*! + @function SecCertificateGetSerialDER + @abstract Retrieves the serial number of a given certificate in DER encoding. + @param certificate A reference to the certificate from which to obtain the serial number. + @result A CFDataRef containing the DER encoded serial number of the certificate, minus the tag and length fields. +*/ +CFDataRef SecCertificateGetSerialDER(SecCertificateRefP certificate); + + +/*! + @function SecCertificateGetSerialString + @abstract Retrieves the serial number of a given certificate in human readable form. + @param certificate A reference to the certificate from which to obtain the serial number. + @result A CFStringRef containing the human readable serial number of the certificate in decimal form. +*/ +CFStringRef SecCertificateGetSerialString(SecCertificateRefP certificate); + + + +CFDataRef SecCertificateGetPublicKeyDER(SecCertificateRefP certificate); +CFDataRef SecCertificateGetPublicKeySHA1FingerPrint(SecCertificateRefP certificate); +CFDataRef SecCertificateGetPublicKeyMD5FingerPrint(SecCertificateRefP certificate); +CFDataRef SecCertificateGetSignatureAlgorithmDER(SecCertificateRefP certificate); +CFDataRef SecCertificateGetSignatureAlgorithmName(SecCertificateRefP certificate); +CFStringRef SecCertificateGetSignatureAlgorithmOID(SecCertificateRefP certificate); +CFDataRef SecCertificateGetSignatureDER(SecCertificateRefP certificate); +CFDataRef SecCertificateGetSignatureAlgorithmParametersDER(SecCertificateRefP certificate); + +/* plist top level array is orderd list of key/value pairs */ +CFArrayRef SecCertificateGetSignatureAlgorithmParametersArray(SecCertificateRefP certificate); + +#if 0 +/* This cert is signed by it's parent? */ +bool SecCertificateIsSignatureValid(SecCertificateRefP certificate); + +/* This cert is signed by it's parent and so on until no parent certificate can be found? */ +bool SecCertificateIsIssuerChainValid(SecCertificateRefP certificate, CFArrayRef additionalCertificatesToSearch); + +/* This cert is signed by it's parent and so on until no parent certificate can be found? */ +bool SecCertificateIsSignatureChainValid(SecCertificateRefP certificate); + +/* This cert is signed by it's parent and so on until a certiicate in anchors can be found. */ +bool SecCertificateIssuerChainHasAnchorIn(SecCertificateRefP certificate, CFArrayRef anchors); + +/* This cert is signed by it's parent and so on until a certiicate in anchors can be found. */ +bool SecCertificateSignatureChainHasAnchorIn(SecCertificateRefP certificate, CFArrayRef anchors); + +bool SecCertificateIsSelfSigned(SecCertificateRefP certificate); +#endif + + +/* The entire certificate in DER encoding including the outer tag and length fields. */ +CFDataRef SecCertificateGetDER(SecCertificateRefP certificate); + +/* Returns the status code of the last failed call for this certificate on this thread. */ +OSStatus SecCertificateGetStatus(SecCertificateRefP certificate); + +CFDataRef SecCertificateGetIssuerDER(SecCertificateRefP certificate); +CFDataRef SecCertificateGetNormalizedIssuerDER(SecCertificateRef certificate); + +/* Return the issuer as an X509 name encoded in an array. Each element in this array is an array. Each inner array has en even number of elements. Each pair of elements in the inner array represents a key and a value. The key is a string and the value is also a string. Elements in the outer array should be considered ordered while pairs in the inner array should not. */ +CFArrayRef SecCertificateGetIssuerArray(SecCertificateRefP certificate); + + +CFDataRef SecCertificateGetSubjectDER(SecCertificateRefP certificate); +CFDataRef SecCertificateGetNormalizedSubjectDER(SecCertificateRefP certificate); +/* See SecCertificateGetIssuerArray for a description of the returned array. */ +CFArrayRef SecCertificateGetSubjectArray(SecCertificateRefP certificate); + +CFDateRef SecCertificateGetNotValidBeforeDate(SecCertificateRefP certificate); +CFDateRef SecCertificateGetNotValidDateDate(SecCertificateRefP certificate); + + +#if 0 + +CFIndex SecCertificateGetExtensionCount(SecCertificateRefP certificate, index); +CFDataRef SecCertificateGetExtensionAtIndexDER(SecCertificateRefP certificate, CFIndex index); +bool SecCertificateIsExtensionAtIndexCritical(SecCertificateRefP certificate, CFIndex index); + +/* array see email example. */ +CFArrayRef SecCertificateGetExtensionAtIndexParamsArray(SecCertificateRefP certificate, CFIndex index); + +CFStringRef SecCertificateGetExtensionAtIndexName(SecCertificateRefP certificate, CFIndex index); +CFStringRef SecCertificateGetExtensionAtIndexOID(SecCertificateRefP certificate, CFIndex index); + +#else + +/* Return an array with all of this certificates SecCertificateExtensionRefs. */ +CFArrayRef SecCertificateGetExtensions(SecCertificateRefP certificate); + +/* Return the SecCertificateExtensionRef for the extension with the given oid. Return NULL if it does not exist or if an error occours call SecCertificateGetStatus() to see if an error occured or not. */ +SecCertificateExtensionRef SecCertificateGetExtensionWithOID(SecCertificateRefP certificate, CFDataRef oid); + +CFDataRef SecCertificateExtensionGetDER(SecCertificateExtensionRef extension, CFDataRef oid); +CFStringRef SecCertificateExtensionName(SecCertificateExtensionRef extension); +CFDataRef SecCertificateExtensionGetOIDDER(SecCertificateExtensionRef extension, CFDataRef oid); +CFStringRef SecCertificateExtensionGetOIDString(SecCertificateExtensionRef extension, CFDataRef oid); +bool SecCertificateExtensionIsCritical(SecCertificateExtensionRef extension); +CFArrayRef SecCertificateExtensionGetContentDER(SecCertificateExtensionRef extension); + +/* Return the content of extension as an array. The array has en even number of elements. Each pair of elements in the array represents a key and a value. The key is a string and the value is either a string, or dictionary or an array of key value pairs like the outer array. */ +CFArrayRef SecCertificateExtensionGetContentArray(SecCertificateExtensionRef extension); + +#endif /* 0 */ + +#endif /* 0 */ + + +void appendProperty(CFMutableArrayRef properties, + CFStringRef propertyType, CFStringRef label, CFTypeRef value); + +/* Utility functions. */ +CFStringRef SecDERItemCopyOIDDecimalRepresentation(CFAllocatorRef allocator, + const DERItem *oid); +CFDataRef createNormalizedX501Name(CFAllocatorRef allocator, + const DERItem *x501name); + +/* Decode a choice of UTCTime or GeneralizedTime to a CFAbsoluteTime. Return + an absoluteTime if the date was valid and properly decoded. Return + NULL_TIME otherwise. */ +CFAbsoluteTime SecAbsoluteTimeFromDateContent(DERTag tag, const uint8_t *bytes, + size_t length); + +#if defined(__cplusplus) +} +#endif + +#endif /* !_SECURITY_SECCERTIFICATEINTERNAL_H_ */ diff --git a/libsecurity_keychain/lib/SecCertificateOIDs.h b/libsecurity_keychain/lib/SecCertificateOIDs.h new file mode 100644 index 00000000..076e76ba --- /dev/null +++ b/libsecurity_keychain/lib/SecCertificateOIDs.h @@ -0,0 +1,168 @@ +/* + * 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 SecCertificateOIDs + These constants are used to access entries in the dictionary returned by + SecCertificateCopyValues, which are the parsed field from a certificate. +*/ + +#ifndef _SECURITY_SECCERTIFICATEOIDS_H_ +#define _SECURITY_SECCERTIFICATEOIDS_H_ + +#include +#include +#include + +#if defined(__cplusplus) +extern "C" { +#endif + +extern CFTypeRef kSecOIDADC_CERT_POLICY __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDAPPLE_CERT_POLICY __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDAPPLE_EKU_CODE_SIGNING __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDAPPLE_EKU_CODE_SIGNING_DEV __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDAPPLE_EKU_ICHAT_ENCRYPTION __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDAPPLE_EKU_ICHAT_SIGNING __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDAPPLE_EKU_RESOURCE_SIGNING __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDAPPLE_EKU_SYSTEM_IDENTITY __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDAPPLE_EXTENSION __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDAPPLE_EXTENSION_ADC_APPLE_SIGNING __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDAPPLE_EXTENSION_ADC_DEV_SIGNING __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDAPPLE_EXTENSION_APPLE_SIGNING __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDAPPLE_EXTENSION_CODE_SIGNING __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDAPPLE_EXTENSION_INTERMEDIATE_MARKER __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDAPPLE_EXTENSION_WWDR_INTERMEDIATE __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDAPPLE_EXTENSION_ITMS_INTERMEDIATE __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDAPPLE_EXTENSION_AAI_INTERMEDIATE __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDAPPLE_EXTENSION_APPLEID_INTERMEDIATE __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDAuthorityInfoAccess __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDAuthorityKeyIdentifier __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDBasicConstraints __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDBiometricInfo __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDCSSMKeyStruct __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDCertIssuer __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDCertificatePolicies __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDClientAuth __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDCollectiveStateProvinceName __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDCollectiveStreetAddress __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDCommonName __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDCountryName __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDCrlDistributionPoints __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDCrlNumber __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDCrlReason __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDDOTMAC_CERT_EMAIL_ENCRYPT __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDDOTMAC_CERT_EMAIL_SIGN __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDDOTMAC_CERT_EXTENSION __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDDOTMAC_CERT_IDENTITY __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDDOTMAC_CERT_POLICY __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDDeltaCrlIndicator __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDDescription __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDEKU_IPSec __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDEmailAddress __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDEmailProtection __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDExtendedKeyUsage __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDExtendedKeyUsageAny __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDExtendedUseCodeSigning __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDGivenName __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDHoldInstructionCode __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDInvalidityDate __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDIssuerAltName __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDIssuingDistributionPoint __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDIssuingDistributionPoints __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDKERBv5_PKINIT_KP_CLIENT_AUTH __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDKERBv5_PKINIT_KP_KDC __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDKeyUsage __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDLocalityName __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDMS_NTPrincipalName __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDMicrosoftSGC __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDNameConstraints __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDNetscapeCertSequence __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDNetscapeCertType __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDNetscapeSGC __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDOCSPSigning __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDOrganizationName __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDOrganizationalUnitName __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDPolicyConstraints __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDPolicyMappings __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDPrivateKeyUsagePeriod __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDQC_Statements __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDSerialNumber __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDServerAuth __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDStateProvinceName __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDStreetAddress __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDSubjectAltName __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDSubjectDirectoryAttributes __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDSubjectEmailAddress __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDSubjectInfoAccess __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDSubjectKeyIdentifier __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDSubjectPicture __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDSubjectSignatureBitmap __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDSurname __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDTimeStamping __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDTitle __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDUseExemptions __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDX509V1CertificateIssuerUniqueId __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDX509V1CertificateSubjectUniqueId __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDX509V1IssuerName __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDX509V1IssuerNameCStruct __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDX509V1IssuerNameLDAP __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDX509V1IssuerNameStd __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDX509V1SerialNumber __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDX509V1Signature __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDX509V1SignatureAlgorithm __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDX509V1SignatureAlgorithmParameters __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDX509V1SignatureAlgorithmTBS __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDX509V1SignatureCStruct __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDX509V1SignatureStruct __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDX509V1SubjectName __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDX509V1SubjectNameCStruct __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDX509V1SubjectNameLDAP __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDX509V1SubjectNameStd __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDX509V1SubjectPublicKey __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDX509V1SubjectPublicKeyAlgorithm __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDX509V1SubjectPublicKeyAlgorithmParameters __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDX509V1SubjectPublicKeyCStruct __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDX509V1ValidityNotAfter __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDX509V1ValidityNotBefore __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDX509V1Version __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDX509V3Certificate __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDX509V3CertificateCStruct __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDX509V3CertificateExtensionCStruct __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDX509V3CertificateExtensionCritical __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDX509V3CertificateExtensionId __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDX509V3CertificateExtensionStruct __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDX509V3CertificateExtensionType __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDX509V3CertificateExtensionValue __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDX509V3CertificateExtensionsCStruct __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDX509V3CertificateExtensionsStruct __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDX509V3CertificateNumberOfExtensions __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDX509V3SignedCertificate __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDX509V3SignedCertificateCStruct __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecOIDSRVName __OSX_AVAILABLE_STARTING(__MAC_10_8, __IPHONE_NA); + +#if defined(__cplusplus) +} +#endif + +#endif /* !_SECURITY_SECCERTIFICATEOIDS_H_ */ diff --git a/libsecurity_keychain/lib/SecCertificateP.c b/libsecurity_keychain/lib/SecCertificateP.c new file mode 100644 index 00000000..2fe84161 --- /dev/null +++ b/libsecurity_keychain/lib/SecCertificateP.c @@ -0,0 +1,4711 @@ +/* + * 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@ + */ + +/* + * SecCertificate.c - CoreFoundation based certificate object + */ + + +//#include +#include "SecCertificateInternalP.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "SecBasePriv.h" + +#include "SecRSAKeyP.h" +#include "SecFrameworkP.h" +#include "SecItem.h" +#include "SecItemPriv.h" +#include +#include "debuggingP.h" +#include +#include +#include +#include "SecInternalP.h" +#include "SecBase64P.h" + +typedef struct SecCertificateExtension { + DERItem extnID; + bool critical; + DERItem extnValue; +} SecCertificateExtension; + +#if 0 +typedef struct KnownExtension { + bool critical; + DERItem extnValue; +} KnownExtension; + +enum { + kSecSelfSignedUnknown = 0, + kSecSelfSignedFalse, + kSecSelfSignedTrue, +}; +#endif + +struct __SecCertificate { + CFRuntimeBase _base; + + DERItem _der; /* Entire certificate in DER form. */ + DERItem _tbs; /* To Be Signed cert DER bytes. */ + DERAlgorithmId _sigAlg; /* Top level signature algorithm. */ + DERItem _signature; /* The content of the sig bit string. */ + + UInt8 _version; + DERItem _serialNum; /* Integer. */ + DERAlgorithmId _tbsSigAlg; /* sig alg MUST be same as _sigAlg. */ + DERItem _issuer; /* Sequence of RDN. */ + CFAbsoluteTime _notBefore; + CFAbsoluteTime _notAfter; + DERItem _subject; /* Sequence of RDN. */ + DERAlgorithmId _algId; /* oid and params of _pubKeyDER. */ + DERItem _pubKeyDER; /* contents of bit string */ + DERItem _issuerUniqueID; /* bit string, optional */ + DERItem _subjectUniqueID; /* bit string, optional */ + +#if 0 + /* Known extensions if the certificate contains them, + extnValue.length will be > 0. */ + KnownExtension _authorityKeyID; + + /* This extension is used to uniquely identify a certificate from among + several that have the same subject name. If the extension is not + present, its value is calculated by performing a SHA-1 hash of the + certificate's DER encoded subjectPublicKeyInfo, as recommended by + PKIX. */ + KnownExtension _subjectKeyID; + KnownExtension _keyUsage; + KnownExtension _extendedKeyUsage; + KnownExtension _basicConstraints; + KnownExtension _netscapeCertType; + KnownExtension _subjectAltName; + KnownExtension _qualCertStatements; + +#endif + bool _foundUnknownCriticalExtension; + + /* Well known certificate extensions. */ + SecCEBasicConstraints _basicConstraints; + SecCEPolicyConstraints _policyConstraints; + CFDictionaryRef _policyMappings; + SecCECertificatePolicies _certificatePolicies; + + /* If InhibitAnyPolicy extension is not present or invalid UINT32_MAX, + value of the SkipCerts field of the InhibitAnyPolicy extension + otherwise. */ + uint32_t _inhibitAnyPolicySkipCerts; + + /* If KeyUsage extension is not present this is 0, otherwise it's + the value of the extension. */ + SecKeyUsage _keyUsage; + + /* OCTECTS of SubjectKeyIdentifier extensions KeyIdentifier. + Length = 0 if not present. */ + DERItem _subjectKeyIdentifier; + + /* OCTECTS of AuthorityKeyIdentifier extensions KeyIdentifier. + Length = 0 if not present. */ + DERItem _authorityKeyIdentifier; + /* AuthorityKeyIdentifier extension _authorityKeyIdentifierIssuer and + _authorityKeyIdentifierSerialNumber have non zero length if present. + Both are either present or absent together. */ + DERItem _authorityKeyIdentifierIssuer; + DERItem _authorityKeyIdentifierSerialNumber; + + /* Subject alt name extension, if present. Not malloced, it's just a + pointer to an element in the _extensions array. */ + const SecCertificateExtension *_subjectAltName; + + /* Parsed extension values. */ + + /* Array of CFURLRefs containing the URI values of crlDistributionPoints. */ + CFMutableArrayRef _crlDistributionPoints; + + /* Array of CFURLRefs containing the URI values of accessLocations of each + id-ad-ocsp AccessDescription in the Authority Information Access + extension. */ + CFMutableArrayRef _ocspResponders; + + /* Array of CFURLRefs containing the URI values of accessLocations of each + id-ad-caIssuers AccessDescription in the Authority Information Access + extension. */ + CFMutableArrayRef _caIssuers; + + /* All other (non known) extensions. The _extensions array is malloced. */ + CFIndex _extensionCount; + SecCertificateExtension *_extensions; + + /* Optional cached fields. */ + SecKeyRef _pubKey; + CFDataRef _der_data; + CFArrayRef _properties; + CFDataRef _serialNumber; + CFDataRef _normalizedIssuer; + CFDataRef _normalizedSubject; + CFDataRef _authorityKeyID; + CFDataRef _subjectKeyID; + + CFDataRef _sha1Digest; + uint8_t _isSelfSigned; + +}; + +/* Public Constants for property list keys. */ +CFStringRef kSecPropertyKeyType = CFSTR("type"); +CFStringRef kSecPropertyKeyLabel = CFSTR("label"); +CFStringRef kSecPropertyKeyLocalizedLabel = CFSTR("localized label"); +CFStringRef kSecPropertyKeyValue = CFSTR("value"); + +/* Public Constants for property list values. */ +CFStringRef kSecPropertyTypeWarning = CFSTR("warning"); +CFStringRef kSecPropertyTypeError = CFSTR("error"); +CFStringRef kSecPropertyTypeSuccess = CFSTR("success"); +CFStringRef kSecPropertyTypeTitle = CFSTR("title"); +CFStringRef kSecPropertyTypeSection = CFSTR("section"); +CFStringRef kSecPropertyTypeData = CFSTR("data"); +CFStringRef kSecPropertyTypeString = CFSTR("string"); +CFStringRef kSecPropertyTypeURL = CFSTR("url"); +CFStringRef kSecPropertyTypeDate = CFSTR("date"); + +/* Extension parsing routine. */ +typedef void (*SecCertificateExtensionParser)(SecCertificateRefP certificate, + const SecCertificateExtension *extn); + +/* CFRuntime regsitration 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; + +/* Forward declartions of static functions. */ +static CFStringRef SecCertificateDescribe(CFTypeRef cf); +static void SecCertificateDestroy(CFTypeRef cf); +static bool derDateGetAbsoluteTime(const DERItem *dateChoice, + CFAbsoluteTime *absTime); + +/* Static functions. */ +static CFStringRef SecCertificateDescribe(CFTypeRef cf) { + SecCertificateRefP certificate = (SecCertificateRefP)cf; + return CFStringCreateWithFormat(kCFAllocatorDefault, NULL, + CFSTR(""), certificate, + SecCertificateCopySubjectSummaryP(certificate), + SecCertificateCopyIssuerSummary(certificate)); +} + +static void SecCertificateDestroy(CFTypeRef cf) { + SecCertificateRefP certificate = (SecCertificateRefP)cf; + if (certificate->_certificatePolicies.policies) + free(certificate->_certificatePolicies.policies); + CFReleaseSafe(certificate->_policyMappings); + CFReleaseSafe(certificate->_crlDistributionPoints); + CFReleaseSafe(certificate->_ocspResponders); + CFReleaseSafe(certificate->_caIssuers); + if (certificate->_extensions) { + free(certificate->_extensions); + } + CFReleaseSafe(certificate->_pubKey); + CFReleaseSafe(certificate->_der_data); + CFReleaseSafe(certificate->_properties); + CFReleaseSafe(certificate->_serialNumber); + CFReleaseSafe(certificate->_normalizedIssuer); + CFReleaseSafe(certificate->_normalizedSubject); + CFReleaseSafe(certificate->_authorityKeyID); + CFReleaseSafe(certificate->_subjectKeyID); + CFReleaseSafe(certificate->_sha1Digest); +} + +static Boolean SecCertificateEqual(CFTypeRef cf1, CFTypeRef cf2) { + SecCertificateRefP cert1 = (SecCertificateRefP)cf1; + SecCertificateRefP cert2 = (SecCertificateRefP)cf2; + if (cert1 == cert2) + return true; + if (!cert2 || cert1->_der.length != cert2->_der.length) + return false; + return !memcmp(cert1->_der.data, cert2->_der.data, cert1->_der.length); +} + +/* Hash of the certificate is der length + signature length + last 4 bytes + of signature. */ +static CFHashCode SecCertificateHash(CFTypeRef cf) { + SecCertificateRefP certificate = (SecCertificateRefP)cf; + uint32_t der_length = certificate->_der.length; + uint32_t sig_length = certificate->_signature.length; + uint32_t ix = (sig_length > 4) ? sig_length - 4 : 0; + CFHashCode hashCode = 0; + for (; ix < sig_length; ++ix) + hashCode = (hashCode << 8) + certificate->_signature.data[ix]; + + return (hashCode + der_length + sig_length); +} + +#if 1 + +/************************************************************************/ +/************************* General Name Parsing *************************/ +/************************************************************************/ + +typedef OSStatus (*parseGeneralNameCallback)(void *context, + SecCEGeneralNameType type, const DERItem *value); + + +/* + 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 } + */ +static OSStatus parseGeneralNameContentProperty(DERTag tag, + const DERItem *generalNameContent, + void *context, parseGeneralNameCallback callback) { + switch (tag) { + case ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 0: + return callback(context, GNT_OtherName, generalNameContent); + case ASN1_CONTEXT_SPECIFIC | 1: + return callback(context, GNT_RFC822Name, generalNameContent); + case ASN1_CONTEXT_SPECIFIC | 2: + return callback(context, GNT_DNSName, generalNameContent); + case ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 3: + return callback(context, GNT_X400Address, generalNameContent); + case ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 4: + return callback(context, GNT_DirectoryName, generalNameContent); + case ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 5: + return callback(context, GNT_EdiPartyName, generalNameContent); + case ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 6: + { + /* Technically I don't think this is valid, but there are certs out + in the wild that use a constructed IA5String. In particular the + VeriSign Time Stamping Authority CA.cer does this. */ + DERDecodedInfo uriContent; + require_noerr(DERDecodeItem(generalNameContent, &uriContent), badDER); + require(uriContent.tag == ASN1_IA5_STRING, badDER); + return callback(context, GNT_URI, &uriContent.content); + } + case ASN1_CONTEXT_SPECIFIC | 6: + return callback(context, GNT_URI, generalNameContent); + case ASN1_CONTEXT_SPECIFIC | 7: + return callback(context, GNT_IPAddress, generalNameContent); + case ASN1_CONTEXT_SPECIFIC | 8: + return callback(context, GNT_RegisteredID, generalNameContent); + default: + goto badDER; + } +badDER: + return errSecInvalidCertificate; +} + +static OSStatus parseGeneralNamesContent(const DERItem *generalNamesContent, + void *context, parseGeneralNameCallback callback) { + DERSequence gnSeq; + DERReturn drtn = DERDecodeSeqContentInit(generalNamesContent, &gnSeq); + require_noerr_quiet(drtn, badDER); + DERDecodedInfo generalNameContent; + while ((drtn = DERDecodeSeqNext(&gnSeq, &generalNameContent)) == + DR_Success) { + OSStatus status = parseGeneralNameContentProperty( + generalNameContent.tag, &generalNameContent.content, context, + callback); + if (status) + return status; + } + require_quiet(drtn == DR_EndOfSequence, badDER); + return noErr; + +badDER: + return errSecInvalidCertificate; +} + +static OSStatus parseGeneralNames(const DERItem *generalNames, void *context, + parseGeneralNameCallback callback) { + DERDecodedInfo generalNamesContent; + DERReturn drtn = DERDecodeItem(generalNames, &generalNamesContent); + require_noerr_quiet(drtn, badDER); + require_quiet(generalNamesContent.tag == ASN1_CONSTR_SEQUENCE, badDER); + return parseGeneralNamesContent(&generalNamesContent.content, context, + callback); +badDER: + return errSecInvalidCertificate; +} + +#else + +/* + GeneralName ::= CHOICE { + otherName [0] OtherName, + rfc822Name [1] IA5String, + dNSName [2] IA5String, + x400Address [3] ORAddress, + directoryName [4] Name, + ediPartyName [5] EDIPartyName, + uniformResourceIdentifier [6] IA5String, + iPAddress [7] OCTET STRING, + registeredID [8] OBJECT IDENTIFIER} + + EDIPartyName ::= SEQUENCE { + nameAssigner [0] DirectoryString OPTIONAL, + partyName [1] DirectoryString } + */ +static OSStatus parseGeneralNameContentProperty(DERTag tag, + const DERItem *generalNameContent, SecCEGeneralName *generalName) { + switch (tag) { + case ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 0: + generalName->nameType = GNT_OtherName; + generalName->berEncoded = true; + generalName->name = *generalNameContent; + break; + case ASN1_CONTEXT_SPECIFIC | 1: + /* IA5String. */ + generalName->nameType = GNT_RFC822Name; + generalName->berEncoded = false; + generalName->name = *generalNameContent; + break; + case ASN1_CONTEXT_SPECIFIC | 2: + /* IA5String. */ + generalName->nameType = GNT_DNSName; + generalName->berEncoded = false; + generalName->name = *generalNameContent; + break; + case ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 3: + generalName->nameType = GNT_X400Address; + generalName->berEncoded = true; + generalName->name = *generalNameContent; + break; + case ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 4: + generalName->nameType = GNT_DirectoryName; + generalName->berEncoded = true; + generalName->name = *generalNameContent; + break; + case ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 5: + generalName->nameType = GNT_EdiPartyName; + generalName->berEncoded = true; + generalName->name = *generalNameContent; + break; + case ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 6: + { + /* Technically I don't think this is valid, but there are certs out + in the wild that use a constructed IA5String. In particular the + VeriSign Time Stamping Authority CA.cer does this. */ + DERDecodedInfo decoded; + require_noerr(DERDecodeItem(generalNameContent, &decoded), badDER); + require(decoded.tag == ASN1_IA5_STRING, badDER); + generalName->nameType = GNT_URI; + generalName->berEncoded = false; + generalName->name = decoded.content; + break; + } + case ASN1_CONTEXT_SPECIFIC | 6: + generalName->nameType = GNT_URI; + generalName->berEncoded = false; + generalName->name = *generalNameContent; + break; + case ASN1_CONTEXT_SPECIFIC | 7: + /* @@@ This is the IP Address as an OCTECT STRING. For IPv4 it's + 8 octects, addr/mask for ipv6 it's 32. */ + generalName->nameType = GNT_IPAddress; + generalName->berEncoded = false; + generalName->name = *generalNameContent; + break; + case ASN1_CONTEXT_SPECIFIC | 8: + /* name is the content of an OID. */ + generalName->nameType = GNT_RegisteredID; + generalName->berEncoded = false; + generalName->name = *generalNameContent; + break; + default: + goto badDER; + break; + } + return noErr; +badDER: + return errSecInvalidCertificate; +} + +/* + GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName + */ +static OSStatus parseGeneralNamesContent(const DERItem *generalNamesContent, + CFIndex *count, SecCEGeneralName **name) { + SecCEGeneralName *generalNames = NULL; + DERSequence gnSeq; + DERReturn drtn = DERDecodeSeqContentInit(generalNamesContent, &gnSeq); + require_noerr_quiet(drtn, badDER); + DERDecodedInfo generalNameContent; + CFIndex generalNamesCount = 0; + while ((drtn = DERDecodeSeqNext(&gnSeq, &generalNameContent)) == + DR_Success) { + ++generalNamesCount; + } + require_quiet(drtn == DR_EndOfSequence, badDER); + + require(generalNames = calloc(generalNamesCount, sizeof(SecCEGeneralName)), + badDER); + DERDecodeSeqContentInit(generalNamesContent, &gnSeq); + CFIndex ix = 0; + while ((drtn = DERDecodeSeqNext(&gnSeq, &generalNameContent)) == + DR_Success) { + if (!parseGeneralNameContentProperty(generalNameContent.tag, + &generalNameContent.content, &generalNames[ix])) { + goto badDER; + } + ++ix; + } + *count = generalNamesCount; + *name = generalNames; + return noErr; + +badDER: + if (generalNames) + free(generalNames); + return errSecInvalidCertificate; +} + +static OSStatus parseGeneralNames(const DERItem *generalNames, + CFIndex *count, SecCEGeneralName **name) { + DERDecodedInfo generalNamesContent; + DERReturn drtn = DERDecodeItem(generalNames, &generalNamesContent); + require_noerr_quiet(drtn, badDER); + require_quiet(generalNamesContent.tag == ASN1_CONSTR_SEQUENCE, + badDER); + parseGeneralNamesContent(&generalNamesContent.content, count, name); + return noErr; +badDER: + return errSecInvalidCertificate; +} +#endif + +/************************************************************************/ +/************************** X.509 Name Parsing **************************/ +/************************************************************************/ + +typedef OSStatus (*parseX501NameCallback)(void *context, const DERItem *type, + const DERItem *value, CFIndex rdnIX); + +static OSStatus parseRDNContent(const DERItem *rdnSetContent, void *context, + parseX501NameCallback callback) { + DERSequence rdn; + DERReturn drtn = DERDecodeSeqContentInit(rdnSetContent, &rdn); + require_noerr_quiet(drtn, badDER); + DERDecodedInfo atvContent; + CFIndex rdnIX = 0; + while ((drtn = DERDecodeSeqNext(&rdn, &atvContent)) == DR_Success) { + require_quiet(atvContent.tag == ASN1_CONSTR_SEQUENCE, badDER); + DERAttributeTypeAndValue atv; + drtn = DERParseSequenceContent(&atvContent.content, + DERNumAttributeTypeAndValueItemSpecs, + DERAttributeTypeAndValueItemSpecs, + &atv, sizeof(atv)); + require_noerr_quiet(drtn, badDER); + require_quiet(atv.type.length != 0, badDER); + OSStatus status = callback(context, &atv.type, &atv.value, rdnIX++); + if (status) + return status; + } + require_quiet(drtn == DR_EndOfSequence, badDER); + + return noErr; +badDER: + return errSecInvalidCertificate; +} + +static OSStatus parseX501NameContent(const DERItem *x501NameContent, void *context, + parseX501NameCallback callback) { + DERSequence derSeq; + DERReturn drtn = DERDecodeSeqContentInit(x501NameContent, &derSeq); + require_noerr_quiet(drtn, badDER); + DERDecodedInfo currDecoded; + while ((drtn = DERDecodeSeqNext(&derSeq, &currDecoded)) == DR_Success) { + require_quiet(currDecoded.tag == ASN1_CONSTR_SET, badDER); + OSStatus status = parseRDNContent(&currDecoded.content, context, + callback); + if (status) + return status; + } + require_quiet(drtn == DR_EndOfSequence, badDER); + + return noErr; + +badDER: + return errSecInvalidCertificate; +} + +static OSStatus parseX501Name(const DERItem *x501Name, void *context, + parseX501NameCallback callback) { + DERDecodedInfo x501NameContent; + if (DERDecodeItem(x501Name, &x501NameContent) || + x501NameContent.tag != ASN1_CONSTR_SEQUENCE) { + return errSecInvalidCertificate; + } else { + return parseX501NameContent(&x501NameContent.content, context, + callback); + } +} + +/************************************************************************/ +/********************** Extension Parsing Routines **********************/ +/************************************************************************/ + +static void SecCEPSubjectKeyIdentifier(SecCertificateRefP certificate, + const SecCertificateExtension *extn) { + secdebug("cert", "critical: %s", extn->critical ? "yes" : "no"); + DERDecodedInfo keyIdentifier; + DERReturn drtn = DERDecodeItem(&extn->extnValue, &keyIdentifier); + require_noerr_quiet(drtn, badDER); + require_quiet(keyIdentifier.tag == ASN1_OCTET_STRING, badDER); + certificate->_subjectKeyIdentifier = keyIdentifier.content; + + return; +badDER: + secdebug(NULL, "Invalid SubjectKeyIdentifier Extension"); +} + +static void SecCEPKeyUsage(SecCertificateRefP certificate, + const SecCertificateExtension *extn) { + secdebug("cert", "critical: %s", extn->critical ? "yes" : "no"); + SecKeyUsage keyUsage = extn->critical ? kSecKeyUsageCritical : 0; + DERDecodedInfo bitStringContent; + DERReturn drtn = DERDecodeItem(&extn->extnValue, &bitStringContent); + require_noerr_quiet(drtn, badDER); + require_quiet(bitStringContent.tag == ASN1_BIT_STRING, badDER); + DERSize len = bitStringContent.content.length - 1; + require_quiet(len == 1 || len == 2, badDER); + DERByte numUnusedBits = bitStringContent.content.data[0]; + require_quiet(numUnusedBits < 8, badDER); + /* Flip the bits in the bit string so the first bit in the lsb. */ + uint_fast16_t bits = 8 * len - numUnusedBits; + uint_fast16_t value = bitStringContent.content.data[1]; + uint_fast16_t mask; + if (len > 1) { + value = (value << 8) + bitStringContent.content.data[2]; + mask = 0x8000; + } else { + mask = 0x80; + } + uint_fast16_t ix; + for (ix = 0; ix < bits; ++ix) { + if (value & mask) { + keyUsage |= 1 << ix; + } + mask >>= 1; + } + certificate->_keyUsage = keyUsage; + return; +badDER: + certificate->_keyUsage = kSecKeyUsageUnspecified; +} + +static void SecCEPPrivateKeyUsagePeriod(SecCertificateRefP certificate, + const SecCertificateExtension *extn) { + secdebug("cert", "critical: %s", extn->critical ? "yes" : "no"); +} + +static void SecCEPSubjectAltName(SecCertificateRefP certificate, + const SecCertificateExtension *extn) { + secdebug("cert", "critical: %s", extn->critical ? "yes" : "no"); + certificate->_subjectAltName = extn; +} + +static void SecCEPIssuerAltName(SecCertificateRefP certificate, + const SecCertificateExtension *extn) { + secdebug("cert", "critical: %s", extn->critical ? "yes" : "no"); +} + +static void SecCEPBasicConstraints(SecCertificateRefP certificate, + const SecCertificateExtension *extn) { + secdebug("cert", "critical: %s", extn->critical ? "yes" : "no"); + DERBasicConstraints basicConstraints; + require_noerr_quiet(DERParseSequence(&extn->extnValue, + DERNumBasicConstraintsItemSpecs, DERBasicConstraintsItemSpecs, + &basicConstraints, sizeof(basicConstraints)), badDER); + require_noerr_quiet(DERParseBoolean(&basicConstraints.cA, false, + &certificate->_basicConstraints.isCA), badDER); + if (basicConstraints.pathLenConstraint.length != 0) { + require_noerr_quiet(DERParseInteger( + &basicConstraints.pathLenConstraint, + &certificate->_basicConstraints.pathLenConstraint), badDER); + certificate->_basicConstraints.pathLenConstraintPresent = true; + } + certificate->_basicConstraints.present = true; + certificate->_basicConstraints.critical = extn->critical; + return; +badDER: + certificate->_basicConstraints.present = false; + secdebug(NULL, "Invalid BasicConstraints Extension"); +} + +static void SecCEPCrlDistributionPoints(SecCertificateRefP certificate, + const SecCertificateExtension *extn) { + secdebug("cert", "critical: %s", extn->critical ? "yes" : "no"); +} + +/* + 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 } +*/ +static void SecCEPCertificatePolicies(SecCertificateRefP certificate, + const SecCertificateExtension *extn) { + secdebug("cert", "critical: %s", extn->critical ? "yes" : "no"); + DERTag tag; + DERSequence piSeq; + SecCEPolicyInformation *policies = NULL; + DERReturn drtn = DERDecodeSeqInit(&extn->extnValue, &tag, &piSeq); + require_noerr_quiet(drtn, badDER); + require_quiet(tag == ASN1_CONSTR_SEQUENCE, badDER); + DERDecodedInfo piContent; + DERSize policy_count = 0; + while ((drtn = DERDecodeSeqNext(&piSeq, &piContent)) == DR_Success) { + require_quiet(piContent.tag == ASN1_CONSTR_SEQUENCE, badDER); + policy_count++; + } + require_quiet(drtn == DR_EndOfSequence, badDER); + policies = (SecCEPolicyInformation *)malloc(sizeof(SecCEPolicyInformation) + * policy_count); + DERDecodeSeqInit(&extn->extnValue, &tag, &piSeq); + DERSize policy_ix = 0; + while ((drtn = DERDecodeSeqNext(&piSeq, &piContent)) == DR_Success) { + DERPolicyInformation pi; + drtn = DERParseSequenceContent(&piContent.content, + DERNumPolicyInformationItemSpecs, + DERPolicyInformationItemSpecs, + &pi, sizeof(pi)); + require_noerr_quiet(drtn, badDER); + policies[policy_ix].policyIdentifier = pi.policyIdentifier; + policies[policy_ix++].policyQualifiers = pi.policyQualifiers; + } + certificate->_certificatePolicies.present = true; + certificate->_certificatePolicies.critical = extn->critical; + certificate->_certificatePolicies.numPolicies = policy_count; + certificate->_certificatePolicies.policies = policies; + return; +badDER: + if (policies) + free(policies); + certificate->_certificatePolicies.present = false; + secdebug(NULL, "Invalid CertificatePolicies Extension"); +} + +/* + id-ce-policyMappings OBJECT IDENTIFIER ::= { id-ce 33 } + + PolicyMappings ::= SEQUENCE SIZE (1..MAX) OF SEQUENCE { + issuerDomainPolicy CertPolicyId, + subjectDomainPolicy CertPolicyId } +*/ +#if 0 +static void SecCEPPolicyMappings(SecCertificateRefP certificate, + const SecCertificateExtension *extn) { + secdebug("cert", "critical: %s", extn->critical ? "yes" : "no"); + DERTag tag; + DERSequence pmSeq; + SecCEPolicyMapping *mappings = NULL; + DERReturn drtn = DERDecodeSeqInit(&extn->extnValue, &tag, &pmSeq); + require_noerr_quiet(drtn, badDER); + require_quiet(tag == ASN1_CONSTR_SEQUENCE, badDER); + DERDecodedInfo pmContent; + DERSize mapping_count = 0; + while ((drtn = DERDecodeSeqNext(&pmSeq, &pmContent)) == DR_Success) { + require_quiet(pmContent.tag == ASN1_CONSTR_SEQUENCE, badDER); + mapping_count++; + } + mappings = (SecCEPolicyMapping *)malloc(sizeof(SecCEPolicyMapping) + * mapping_count); + DERDecodeSeqInit(&extn->extnValue, &tag, &pmSeq); + DERSize mapping_ix = 0; + while ((drtn = DERDecodeSeqNext(&pmSeq, &pmContent)) == DR_Success) { + DERPolicyMapping pm; + drtn = DERParseSequenceContent(&pmContent.content, + DERNumPolicyMappingItemSpecs, + DERPolicyMappingItemSpecs, + &pm, sizeof(pm)); + require_noerr_quiet(drtn, badDER); + mappings[mapping_ix].issuerDomainPolicy = pm.issuerDomainPolicy; + mappings[mapping_ix++].subjectDomainPolicy = pm.subjectDomainPolicy; + } + require_quiet(drtn == DR_EndOfSequence, badDER); + certificate->_policyMappings.present = true; + certificate->_policyMappings.critical = extn->critical; + certificate->_policyMappings.numMappings = mapping_count; + certificate->_policyMappings.mappings = mappings; + return; +badDER: + if (mappings) + free(mappings); + CFReleaseSafe(mappings); + certificate->_policyMappings.present = false; + secdebug(NULL, "Invalid CertificatePolicies Extension"); +} +#else +static void SecCEPPolicyMappings(SecCertificateRefP certificate, + const SecCertificateExtension *extn) { + secdebug("cert", "critical: %s", extn->critical ? "yes" : "no"); + DERTag tag; + DERSequence pmSeq; + CFMutableDictionaryRef mappings = 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);; + while ((drtn = DERDecodeSeqNext(&pmSeq, &pmContent)) == DR_Success) { + require_quiet(pmContent.tag == ASN1_CONSTR_SEQUENCE, badDER); + DERPolicyMapping pm; + drtn = DERParseSequenceContent(&pmContent.content, + DERNumPolicyMappingItemSpecs, + 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, + pm.subjectDomainPolicy.data, pm.subjectDomainPolicy.length), badDER); + CFMutableArrayRef sdps = + (CFMutableArrayRef)CFDictionaryGetValue(mappings, idp); + if (sdps) { + CFArrayAppendValue(sdps, sdp); + } else { + require_quiet(sdps = CFArrayCreateMutable(kCFAllocatorDefault, 0, + &kCFTypeArrayCallBacks), badDER); + CFDictionarySetValue(mappings, idp, sdps); + CFRelease(sdps); + } + } + require_quiet(drtn == DR_EndOfSequence, badDER); + certificate->_policyMappings = mappings; + return; +badDER: + CFReleaseSafe(mappings); + certificate->_policyMappings = NULL; + secdebug(NULL, "Invalid CertificatePolicies Extension"); +} +#endif + +/* +AuthorityKeyIdentifier ::= SEQUENCE { + keyIdentifier [0] KeyIdentifier OPTIONAL, + authorityCertIssuer [1] GeneralNames OPTIONAL, + authorityCertSerialNumber [2] CertificateSerialNumber OPTIONAL } + -- authorityCertIssuer and authorityCertSerialNumber MUST both + -- be present or both be absent + +KeyIdentifier ::= OCTET STRING +*/ +static void SecCEPAuthorityKeyIdentifier(SecCertificateRefP certificate, + const SecCertificateExtension *extn) { + secdebug("cert", "critical: %s", extn->critical ? "yes" : "no"); + DERAuthorityKeyIdentifier akid; + DERReturn drtn; + drtn = DERParseSequence(&extn->extnValue, + DERNumAuthorityKeyIdentifierItemSpecs, + DERAuthorityKeyIdentifierItemSpecs, + &akid, sizeof(akid)); + require_noerr_quiet(drtn, badDER); + if (akid.keyIdentifier.length) { + certificate->_authorityKeyIdentifier = akid.keyIdentifier; + } + if (akid.authorityCertIssuer.length || + akid.authorityCertSerialNumber.length) { + require_quiet(akid.authorityCertIssuer.length && + akid.authorityCertSerialNumber.length, badDER); + /* Perhaps put in a subsection called Authority Certificate Issuer. */ + certificate->_authorityKeyIdentifierIssuer = akid.authorityCertIssuer; + certificate->_authorityKeyIdentifierSerialNumber = akid.authorityCertSerialNumber; + } + + return; +badDER: + secdebug(NULL, "Invalid AuthorityKeyIdentifier Extension"); +} + +static void SecCEPPolicyConstraints(SecCertificateRefP certificate, + const SecCertificateExtension *extn) { + secdebug("cert", "critical: %s", extn->critical ? "yes" : "no"); + DERPolicyConstraints pc; + DERReturn drtn; + drtn = DERParseSequence(&extn->extnValue, + DERNumPolicyConstraintsItemSpecs, + DERPolicyConstraintsItemSpecs, + &pc, sizeof(pc)); + require_noerr_quiet(drtn, badDER); + if (pc.requireExplicitPolicy.length) { + require_noerr_quiet(DERParseInteger( + &pc.requireExplicitPolicy, + &certificate->_policyConstraints.requireExplicitPolicy), badDER); + certificate->_policyConstraints.requireExplicitPolicyPresent = true; + } + if (pc.inhibitPolicyMapping.length) { + require_noerr_quiet(DERParseInteger( + &pc.inhibitPolicyMapping, + &certificate->_policyConstraints.inhibitPolicyMapping), badDER); + certificate->_policyConstraints.inhibitPolicyMappingPresent = true; + } + + certificate->_policyConstraints.present = true; + certificate->_policyConstraints.critical = extn->critical; + + return; +badDER: + certificate->_policyConstraints.present = false; + secdebug(NULL, "Invalid PolicyConstraints Extension"); +} + +static void SecCEPExtendedKeyUsage(SecCertificateRefP certificate, + const SecCertificateExtension *extn) { + secdebug("cert", "critical: %s", extn->critical ? "yes" : "no"); +} + +/* + InhibitAnyPolicy ::= SkipCerts + + SkipCerts ::= INTEGER (0..MAX) +*/ +static void SecCEPInhibitAnyPolicy(SecCertificateRefP certificate, + const SecCertificateExtension *extn) { + secdebug("cert", "critical: %s", extn->critical ? "yes" : "no"); + require_noerr_quiet(DERParseInteger( + &extn->extnValue, + &certificate->_inhibitAnyPolicySkipCerts), badDER); + return; +badDER: + certificate->_inhibitAnyPolicySkipCerts = UINT32_MAX; + secdebug(NULL, "Invalid InhibitAnyPolicy Extension"); +} + +/* + id-pe-authorityInfoAccess OBJECT IDENTIFIER ::= { id-pe 1 } + + AuthorityInfoAccessSyntax ::= + SEQUENCE SIZE (1..MAX) OF AccessDescription + + AccessDescription ::= SEQUENCE { + accessMethod OBJECT IDENTIFIER, + accessLocation GeneralName } + + id-ad OBJECT IDENTIFIER ::= { id-pkix 48 } + + id-ad-caIssuers OBJECT IDENTIFIER ::= { id-ad 2 } + + id-ad-ocsp OBJECT IDENTIFIER ::= { id-ad 1 } + */ +static void SecCEPAuthorityInfoAccess(SecCertificateRefP certificate, + const SecCertificateExtension *extn) { + secdebug("cert", "critical: %s", extn->critical ? "yes" : "no"); + DERTag tag; + DERSequence adSeq; + DERReturn drtn = DERDecodeSeqInit(&extn->extnValue, &tag, &adSeq); + require_noerr_quiet(drtn, badDER); + require_quiet(tag == ASN1_CONSTR_SEQUENCE, badDER); + DERDecodedInfo adContent; + while ((drtn = DERDecodeSeqNext(&adSeq, &adContent)) == DR_Success) { + require_quiet(adContent.tag == ASN1_CONSTR_SEQUENCE, badDER); + DERAccessDescription ad; + drtn = DERParseSequenceContent(&adContent.content, + DERNumAccessDescriptionItemSpecs, + DERAccessDescriptionItemSpecs, + &ad, sizeof(ad)); + require_noerr_quiet(drtn, badDER); + CFMutableArrayRef *urls; + if (DEROidCompare(&ad.accessMethod, &oidAdOCSP)) + urls = &certificate->_ocspResponders; + else if (DEROidCompare(&ad.accessMethod, &oidAdCAIssuer)) + urls = &certificate->_caIssuers; + else + continue; + + DERDecodedInfo generalNameContent; + drtn = DERDecodeItem(&ad.accessLocation, &generalNameContent); + require_noerr_quiet(drtn, badDER); + switch (generalNameContent.tag) { +#if 0 + case ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 6: + /* Technically I don't think this is valid, but there are certs out + in the wild that use a constructed IA5String. In particular the + VeriSign Time Stamping Authority CA.cer does this. */ +#endif + case ASN1_CONTEXT_SPECIFIC | 6: + { + CFURLRef url = CFURLCreateWithBytes(kCFAllocatorDefault, + generalNameContent.content.data, generalNameContent.content.length, + kCFStringEncodingASCII, NULL); + if (url) { + if (!*urls) + *urls = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); + CFArrayAppendValue(*urls, url); + CFRelease(url); + } + break; + } + default: + secdebug("cert", "bad general name for id-ad-ocsp AccessDescription t: 0x%02x v: %.*s", + generalNameContent.tag, generalNameContent.content.length, generalNameContent.content.data); + goto badDER; + break; + } + } + require_quiet(drtn == DR_EndOfSequence, badDER); + return; +badDER: + secdebug("cert", "failed to parse Authority Information Access extension"); +} + +static void SecCEPSubjectInfoAccess(SecCertificateRefP certificate, + const SecCertificateExtension *extn) { + secdebug("cert", "critical: %s", extn->critical ? "yes" : "no"); +} + +static void SecCEPNetscapeCertType(SecCertificateRefP certificate, + const SecCertificateExtension *extn) { + secdebug("cert", "critical: %s", extn->critical ? "yes" : "no"); +} + +static void SecCEPEntrustVersInfo(SecCertificateRefP certificate, + const SecCertificateExtension *extn) { + secdebug("cert", "critical: %s", extn->critical ? "yes" : "no"); +} + +/* Dictionary key callback for comparing to DERItems. */ +static Boolean SecDERItemEqual(const void *value1, const void *value2) { + return DEROidCompare((const DERItem *)value1, (const DERItem *)value2); +} + +/* Dictionary key callback calculating the hash of a DERItem. */ +static CFHashCode SecDERItemHash(const void *value) { + const DERItem *derItem = (const DERItem *)value; + CFHashCode hash = derItem->length; + DERSize ix = derItem->length > 8 ? derItem->length - 8 : 0; + for (; ix < derItem->length; ++ix) { + hash = (hash << 9) + (hash >> 23) + derItem->data[ix]; + } + + return hash; +} + +/* Dictionary key callbacks using the above 2 functions. */ +static const CFDictionaryKeyCallBacks SecDERItemKeyCallBacks = { + 0, /* version */ + NULL, /* retain */ + NULL, /* release */ + NULL, /* copyDescription */ + SecDERItemEqual, /* equal */ + 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); + + /* Build a dictionary that maps from extension OIDs to callback functions + which can parse the extension of the type given. */ + static const void *extnOIDs[] = { + &oidSubjectKeyIdentifier, + &oidKeyUsage, + &oidPrivateKeyUsagePeriod, + &oidSubjectAltName, + &oidIssuerAltName, + &oidBasicConstraints, + &oidCrlDistributionPoints, + &oidCertificatePolicies, + &oidPolicyMappings, + &oidAuthorityKeyIdentifier, + &oidPolicyConstraints, + &oidExtendedKeyUsage, + &oidInhibitAnyPolicy, + &oidAuthorityInfoAccess, + &oidSubjectInfoAccess, + &oidNetscapeCertType, + &oidEntrustVersInfo + }; + static const void *extnParsers[] = { + SecCEPSubjectKeyIdentifier, + SecCEPKeyUsage, + SecCEPPrivateKeyUsagePeriod, + SecCEPSubjectAltName, + SecCEPIssuerAltName, + SecCEPBasicConstraints, + SecCEPCrlDistributionPoints, + SecCEPCertificatePolicies, + SecCEPPolicyMappings, + SecCEPAuthorityKeyIdentifier, + SecCEPPolicyConstraints, + SecCEPExtendedKeyUsage, + SecCEPInhibitAnyPolicy, + SecCEPAuthorityInfoAccess, + SecCEPSubjectInfoAccess, + SecCEPNetscapeCertType, + SecCEPEntrustVersInfo + }; + gExtensionParsers = CFDictionaryCreate(kCFAllocatorDefault, extnOIDs, + extnParsers, sizeof(extnOIDs) / sizeof(*extnOIDs), + &SecDERItemKeyCallBacks, NULL); +} + +/* Given the contents of an X.501 Name return the contents of a normalized + X.501 name. */ +CFDataRef createNormalizedX501Name(CFAllocatorRef allocator, + const DERItem *x501name) { + CFMutableDataRef result = CFDataCreateMutable(allocator, x501name->length); + CFIndex length = x501name->length; + CFDataSetLength(result, length); + UInt8 *base = CFDataGetMutableBytePtr(result); + + DERSequence rdnSeq; + DERReturn drtn = DERDecodeSeqContentInit(x501name, &rdnSeq); + + require_noerr_quiet(drtn, badDER); + DERDecodedInfo rdn; + + /* Always points to last rdn tag. */ + const DERByte *rdnTag = rdnSeq.nextItem; + /* Offset relative to base of current rdn set tag. */ + CFIndex rdnTagLocation = 0; + while ((drtn = DERDecodeSeqNext(&rdnSeq, &rdn)) == DR_Success) { + require_quiet(rdn.tag == ASN1_CONSTR_SET, badDER); + /* We don't allow empty RDNs. */ + require_quiet(rdn.content.length != 0, badDER); + /* Length of the tag and length of the current rdn. */ + CFIndex rdnTLLength = rdn.content.data - rdnTag; + CFIndex rdnContentLength = rdn.content.length; + /* Copy the tag and length of the RDN. */ + memcpy(base + rdnTagLocation, rdnTag, rdnTLLength); + + DERSequence atvSeq; + drtn = DERDecodeSeqContentInit(&rdn.content, &atvSeq); + DERDecodedInfo atv; + /* Always points to tag of current atv sequence. */ + const DERByte *atvTag = atvSeq.nextItem; + /* Offset relative to base of current atv sequence tag. */ + CFIndex atvTagLocation = rdnTagLocation + rdnTLLength; + while ((drtn = DERDecodeSeqNext(&atvSeq, &atv)) == DR_Success) { + require_quiet(atv.tag == ASN1_CONSTR_SEQUENCE, badDER); + /* Length of the tag and length of the current atv. */ + CFIndex atvTLLength = atv.content.data - atvTag; + CFIndex atvContentLength = atv.content.length; + /* Copy the tag and length of the atv and the atv itself. */ + memcpy(base + atvTagLocation, atvTag, + atvTLLength + atv.content.length); + + /* Now decode the atv sequence. */ + DERAttributeTypeAndValue atvPair; + drtn = DERParseSequenceContent(&atv.content, + DERNumAttributeTypeAndValueItemSpecs, + DERAttributeTypeAndValueItemSpecs, + &atvPair, sizeof(atvPair)); + require_noerr_quiet(drtn, badDER); + require_quiet(atvPair.type.length != 0, badDER); + DERDecodedInfo value; + drtn = DERDecodeItem(&atvPair.value, &value); + require_noerr_quiet(drtn, badDER); + + /* (c) attribute values in PrintableString are not case sensitive + (e.g., "Marianne Swanson" is the same as "MARIANNE SWANSON"); and + + (d) attribute values in PrintableString are compared after + removing leading and trailing white space and converting internal + substrings of one or more consecutive white space characters to a + single space. */ + if (value.tag == ASN1_PRINTABLE_STRING) { + /* Offset relative to base of current value tag. */ + CFIndex valueTagLocation = atvTagLocation + atvPair.value.data - atvTag; + CFIndex valueTLLength = value.content.data - atvPair.value.data; + CFIndex valueContentLength = value.content.length; + + /* Now copy all the bytes, but convert to upper case while + doing so and convert multiple whitespace chars into a + single space. */ + bool lastWasBlank = false; + CFIndex valueLocation = valueTagLocation + valueTLLength; + CFIndex valueCurrentLocation = valueLocation; + CFIndex ix; + for (ix = 0; ix < valueContentLength; ++ix) { + UInt8 ch = value.content.data[ix]; + if (isblank(ch)) { + if (lastWasBlank) { + continue; + } else { + /* Don't insert a space for first character + we encounter. */ + if (valueCurrentLocation > valueLocation) { + base[valueCurrentLocation++] = ' '; + } + lastWasBlank = true; + } + } else { + lastWasBlank = false; + if ('a' <= ch && ch <= 'z') { + base[valueCurrentLocation++] = ch + 'A' - 'a'; + } else { + base[valueCurrentLocation++] = ch; + } + } + } + /* Finally if lastWasBlank remove the trailing space. */ + if (lastWasBlank && valueCurrentLocation > valueLocation) { + valueCurrentLocation--; + } + /* Adjust content length to normalized length. */ + valueContentLength = valueCurrentLocation - valueLocation; + + /* Number of bytes by which the length should be shorted. */ + CFIndex lengthDiff = value.content.length - valueContentLength; + if (lengthDiff == 0) { + /* Easy case no need to adjust lengths. */ + } else { + /* Hard work we need to go back and fix up length fields + for: + 1) The value itself. + 2) The ATV Sequence containing type/value + 3) The RDN Set containing one or more atv pairs. + 4) The result. + */ + + /* Step 1 fix up length of value. */ + /* Length of value tag and length minus the tag. */ + DERSize newValueTLLength = valueTLLength - 1; + drtn = DEREncodeLength(valueContentLength, + base + valueTagLocation + 1, &newValueTLLength); + /* Add the length of the tag back in. */ + newValueTLLength++; + CFIndex valueLLDiff = valueTLLength - newValueTLLength; + if (valueLLDiff) { + /* The size of the length field changed, let's slide + the value back by valueLLDiff bytes. */ + memmove(base + valueTagLocation + newValueTLLength, + base + valueTagLocation + valueTLLength, + valueContentLength); + /* The length diff for the enclosing object. */ + lengthDiff += valueLLDiff; + } + + /* Step 2 fix up length of the enclosing ATV Sequence. */ + atvContentLength -= lengthDiff; + DERSize newATVTLLength = atvTLLength - 1; + drtn = DEREncodeLength(atvContentLength, + base + atvTagLocation + 1, &newATVTLLength); + /* Add the length of the tag back in. */ + newATVTLLength++; + CFIndex atvLLDiff = atvTLLength - newATVTLLength; + if (atvLLDiff) { + /* The size of the length field changed, let's slide + the value back by valueLLDiff bytes. */ + memmove(base + atvTagLocation + newATVTLLength, + base + atvTagLocation + atvTLLength, + atvContentLength); + /* The length diff for the enclosing object. */ + lengthDiff += atvLLDiff; + atvTLLength = newATVTLLength; + } + + /* Step 3 fix up length of enclosing RDN Set. */ + rdnContentLength -= lengthDiff; + DERSize newRDNTLLength = rdnTLLength - 1; + drtn = DEREncodeLength(rdnContentLength, + base + rdnTagLocation + 1, &newRDNTLLength); + /* Add the length of the tag back in. */ + newRDNTLLength++; + CFIndex rdnLLDiff = rdnTLLength - newRDNTLLength; + if (rdnLLDiff) { + /* The size of the length field changed, let's slide + the value back by valueLLDiff bytes. */ + memmove(base + rdnTagLocation + newRDNTLLength, + base + rdnTagLocation + rdnTLLength, + rdnContentLength); + /* The length diff for the enclosing object. */ + lengthDiff += rdnLLDiff; + rdnTLLength = newRDNTLLength; + + /* Adjust the locations that might have changed due to + this slide. */ + atvTagLocation -= rdnLLDiff; + } + } + } + atvTagLocation += atvTLLength + atvContentLength; + atvTag = atvSeq.nextItem; + } + rdnTagLocation += rdnTLLength + rdnContentLength; + rdnTag = rdnSeq.nextItem; + } + require_quiet(drtn == DR_EndOfSequence, badDER); + /* Truncate the result to the proper length. */ + CFDataSetLength(result, rdnTagLocation); + + return result; + +badDER: + CFRelease(result); + return NULL; +} + +/* AUDIT[securityd]: + certificate->_der is a caller provided data of any length (might be 0). + + Top level certificate decode. + */ +static bool SecCertificateParse(SecCertificateRefP certificate) +{ + DERReturn drtn; + + check(certificate); + CFAllocatorRef allocator = CFGetAllocator(certificate); + + /* top level decode */ + DERSignedCertCrl signedCert; + drtn = DERParseSequence(&certificate->_der, DERNumSignedCertCrlItemSpecs, + DERSignedCertCrlItemSpecs, &signedCert, + sizeof(signedCert)); + require_noerr_quiet(drtn, badCert); + /* Store tbs since we need to digest it for verification later on. */ + certificate->_tbs = signedCert.tbs; + + /* decode the TBSCert - it was saved in full DER form */ + DERTBSCert tbsCert; + drtn = DERParseSequence(&signedCert.tbs, + DERNumTBSCertItemSpecs, DERTBSCertItemSpecs, + &tbsCert, sizeof(tbsCert)); + require_noerr_quiet(drtn, badCert); + + /* sequence we're given: decode the signedCerts Signature Algorithm. */ + /* This MUST be the same as the certificate->_tbsSigAlg with the exception + of the params field. */ + drtn = DERParseSequenceContent(&signedCert.sigAlg, + DERNumAlgorithmIdItemSpecs, DERAlgorithmIdItemSpecs, + &certificate->_sigAlg, sizeof(certificate->_sigAlg)); + require_noerr_quiet(drtn, badCert); + + /* The contents of signedCert.sig is a bit string whose contents + are the signature itself. */ + DERByte numUnusedBits; + drtn = DERParseBitString(&signedCert.sig, + &certificate->_signature, &numUnusedBits); + require_noerr_quiet(drtn, badCert); + + /* Now decode the tbsCert. */ + + /* First we turn the optional version into an int. */ + if (tbsCert.version.length) { + DERDecodedInfo decoded; + drtn = DERDecodeItem(&tbsCert.version, &decoded); + require_noerr_quiet(drtn, badCert); + require_quiet(decoded.tag == ASN1_INTEGER, badCert); + require_quiet(decoded.content.length == 1, badCert); + certificate->_version = decoded.content.data[0]; + require_quiet(certificate->_version > 0, badCert); + require_quiet(certificate->_version < 3, badCert); + } else { + certificate->_version = 0; + } + + /* The serial number is in the tbsCert.serialNum - it was saved in + INTEGER form without the tag and length. */ + certificate->_serialNum = tbsCert.serialNum; + certificate->_serialNumber = CFDataCreate(allocator, + tbsCert.serialNum.data, tbsCert.serialNum.length); + + /* sequence we're given: decode the tbsCerts TBS Signature Algorithm. */ + drtn = DERParseSequenceContent(&tbsCert.tbsSigAlg, + DERNumAlgorithmIdItemSpecs, DERAlgorithmIdItemSpecs, + &certificate->_tbsSigAlg, sizeof(certificate->_tbsSigAlg)); + require_noerr_quiet(drtn, badCert); + + /* The issuer is in the tbsCert.issuer - it's a sequence without the tag + and length fields. */ + certificate->_issuer = tbsCert.issuer; + certificate->_normalizedIssuer = createNormalizedX501Name(allocator, + &tbsCert.issuer); + + /* sequence we're given: decode the tbsCerts Validity sequence. */ + DERValidity validity; + drtn = DERParseSequenceContent(&tbsCert.validity, + DERNumValidityItemSpecs, DERValidityItemSpecs, + &validity, sizeof(validity)); + require_noerr_quiet(drtn, badCert); + require_quiet(derDateGetAbsoluteTime(&validity.notBefore, + &certificate->_notBefore), badCert); + require_quiet(derDateGetAbsoluteTime(&validity.notAfter, + &certificate->_notAfter), badCert); + + /* The subject is in the tbsCert.subject - it's a sequence without the tag + and length fields. */ + certificate->_subject = tbsCert.subject; + certificate->_normalizedSubject = createNormalizedX501Name(allocator, + &tbsCert.subject); + + /* sequence we're given: encoded DERSubjPubKeyInfo */ + DERSubjPubKeyInfo pubKeyInfo; + drtn = DERParseSequenceContent(&tbsCert.subjectPubKey, + DERNumSubjPubKeyInfoItemSpecs, DERSubjPubKeyInfoItemSpecs, + &pubKeyInfo, sizeof(pubKeyInfo)); + require_noerr_quiet(drtn, badCert); + + /* sequence we're given: decode the pubKeyInfos DERAlgorithmId */ + drtn = DERParseSequenceContent(&pubKeyInfo.algId, + DERNumAlgorithmIdItemSpecs, DERAlgorithmIdItemSpecs, + &certificate->_algId, sizeof(certificate->_algId)); + require_noerr_quiet(drtn, badCert); + + /* Now we can figure out the key's algorithm id and params based on + certificate->_algId.oid. */ + + /* The contents of pubKeyInfo.pubKey is a bit string whose contents + are a PKCS1 format RSA key. */ + drtn = DERParseBitString(&pubKeyInfo.pubKey, + &certificate->_pubKeyDER, &numUnusedBits); + require_noerr_quiet(drtn, badCert); + + /* The contents of tbsCert.issuerID is a bit string. */ + certificate->_issuerUniqueID = tbsCert.issuerID; + + /* The contents of tbsCert.subjectID is a bit string. */ + certificate->_subjectUniqueID = tbsCert.subjectID; + + /* Extensions. */ + if (tbsCert.extensions.length) { + CFIndex extensionCount = 0; + DERSequence derSeq; + DERTag tag; + drtn = DERDecodeSeqInit(&tbsCert.extensions, &tag, + &derSeq); + require_noerr_quiet(drtn, badCert); + require_quiet(tag == ASN1_CONSTR_SEQUENCE, badCert); + DERDecodedInfo currDecoded; + while ((drtn = DERDecodeSeqNext(&derSeq, &currDecoded)) == DR_Success) { +#if 0 +/* ! = MUST recognize ? = SHOULD recognize +*/ + + KnownExtension _subjectKeyID; /* ?SubjectKeyIdentifier id-ce 14 */ + KnownExtension _keyUsage; /* !KeyUsage id-ce 15 */ + KnownExtension _subjectAltName; /* !SubjectAltName id-ce 17 */ + KnownExtension _basicConstraints; /* !BasicConstraints id-ce 19 */ + KnownExtension _authorityKeyID; /* ?AuthorityKeyIdentifier id-ce 35 */ + KnownExtension _extKeyUsage; /* !ExtKeyUsage id-ce 37 */ + KnownExtension _netscapeCertType; /* 2.16.840.1.113730.1.1 netscape 1 1 */ + KnownExtension _qualCertStatements; /* QCStatements id-pe 3 */ + + KnownExtension _issuerAltName; /* IssuerAltName id-ce 18 */ + KnownExtension _nameConstraints; /* !NameConstraints id-ce 30 */ + KnownExtension _cRLDistributionPoints; /* CRLDistributionPoints id-ce 31 */ + KnownExtension _certificatePolicies; /* !CertificatePolicies id-ce 32 */ + KnownExtension _policyMappings; /* ?PolicyMappings id-ce 33 */ + KnownExtension _policyConstraints; /* !PolicyConstraints id-ce 36 */ + KnownExtension _freshestCRL; /* FreshestCRL id-ce 46 */ + KnownExtension _inhibitAnyPolicy; /* !InhibitAnyPolicy id-ce 54 */ + + KnownExtension _authorityInfoAccess; /* AuthorityInfoAccess id-pe 1 */ + KnownExtension _subjectInfoAccess; /* SubjectInfoAccess id-pe 11 */ +#endif + + extensionCount++; + } + require_quiet(drtn == DR_EndOfSequence, badCert); + + /* Put some upper limit on the number of extentions allowed. */ + require_quiet(extensionCount < 10000, badCert); + certificate->_extensionCount = extensionCount; + certificate->_extensions = + malloc(sizeof(SecCertificateExtension) * extensionCount); + + CFIndex ix = 0; + drtn = DERDecodeSeqInit(&tbsCert.extensions, &tag, &derSeq); + require_noerr_quiet(drtn, badCert); + for (ix = 0; ix < extensionCount; ++ix) { + drtn = DERDecodeSeqNext(&derSeq, &currDecoded); + require_quiet(drtn == DR_Success || + (ix == extensionCount - 1 && drtn == DR_EndOfSequence), badCert); + require_quiet(currDecoded.tag == ASN1_CONSTR_SEQUENCE, badCert); + DERExtension extn; + drtn = DERParseSequenceContent(&currDecoded.content, + DERNumExtensionItemSpecs, DERExtensionItemSpecs, + &extn, sizeof(extn)); + require_noerr_quiet(drtn, badCert); + /* Copy stuff into certificate->extensions[ix]. */ + certificate->_extensions[ix].extnID = extn.extnID; + require_noerr_quiet(drtn = DERParseBoolean(&extn.critical, false, + &certificate->_extensions[ix].critical), badCert); + certificate->_extensions[ix].extnValue = extn.extnValue; + + SecCertificateExtensionParser parser = + (SecCertificateExtensionParser)CFDictionaryGetValue( + gExtensionParsers, &certificate->_extensions[ix].extnID); + if (parser) { + /* Invoke the parser. */ + parser(certificate, &certificate->_extensions[ix]); + } else if (certificate->_extensions[ix].critical) { + secdebug("cert", "Found unknown critical extension"); + certificate->_foundUnknownCriticalExtension = true; + } else { + secdebug("cert", "Found unknown non critical extension"); + } + } + } + + return true; + +badCert: + return false; +} + + +/* Public API functions. */ +CFTypeID SecCertificateGetTypeIDP(void) { + pthread_once(&kSecCertificateRegisterClass, SecCertificateRegisterClass); + return kSecCertificateTypeID; +} + +SecCertificateRefP SecCertificateCreateWithBytesP(CFAllocatorRef allocator, + const UInt8 *der_bytes, CFIndex der_length) { + check(der_bytes); + check(der_length); + CFIndex size = sizeof(struct __SecCertificate) + der_length; + SecCertificateRefP result = (SecCertificateRefP)_CFRuntimeCreateInstance( + allocator, SecCertificateGetTypeIDP(), size - sizeof(CFRuntimeBase), 0); + if (result) { + memset((char*)result + sizeof(result->_base), 0, + sizeof(*result) - sizeof(result->_base)); + result->_der.data = ((DERByte *)result + sizeof(*result)); + result->_der.length = der_length; + memcpy(result->_der.data, der_bytes, der_length); + if (!SecCertificateParse(result)) { + CFRelease(result); + return NULL; + } + } + return result; +} + +/* @@@ Placeholder until iap submits a binary is fixed. */ +SecCertificateRefP SecCertificateCreate(CFAllocatorRef allocator, + const UInt8 *der_bytes, CFIndex der_length); + +SecCertificateRefP SecCertificateCreate(CFAllocatorRef allocator, + const UInt8 *der_bytes, CFIndex der_length) { + return SecCertificateCreateWithBytesP(allocator, der_bytes, der_length); +} +/* @@@ End of placeholder. */ + +/* AUDIT[securityd](done): + der_certificate is a caller provided data of any length (might be 0), only + its cf type has been checked. + */ +SecCertificateRefP SecCertificateCreateWithDataP(CFAllocatorRef allocator, + CFDataRef der_certificate) { + check(der_certificate); + CFIndex size = sizeof(struct __SecCertificate); + SecCertificateRefP result = (SecCertificateRefP)_CFRuntimeCreateInstance( + allocator, SecCertificateGetTypeIDP(), size - sizeof(CFRuntimeBase), 0); + if (result) { + memset((char*)result + sizeof(result->_base), 0, size - sizeof(result->_base)); + result->_der_data = CFDataCreateCopy(allocator, der_certificate); + result->_der.data = (DERByte *)CFDataGetBytePtr(result->_der_data); + result->_der.length = CFDataGetLength(result->_der_data); + if (!SecCertificateParse(result)) { + CFRelease(result); + return NULL; + } + } + return result; +} + +CFDataRef SecCertificateCopyDataP(SecCertificateRefP certificate) { + check(certificate); + CFDataRef result; + if (certificate->_der_data) { + CFRetain(certificate->_der_data); + result = certificate->_der_data; + } else { + result = CFDataCreate(CFGetAllocator(certificate), + certificate->_der.data, certificate->_der.length); +#if 0 + /* FIXME: If we wish to cache result we need to lock the certificate. + Also this create 2 copies of the certificate data which is somewhat + suboptimal. */ + CFRetain(result); + certificate->_der_data = result; +#endif + } + + return result; +} + +CFIndex SecCertificateGetLengthP(SecCertificateRefP certificate) { + return certificate->_der.length; +} + +const UInt8 *SecCertificateGetBytePtrP(SecCertificateRefP certificate) { + return certificate->_der.data; +} + +/* From rfc3280 - Appendix B. ASN.1 Notes + + Object Identifiers (OIDs) are used throughout this specification to + identify certificate policies, public key and signature algorithms, + certificate extensions, etc. There is no maximum size for OIDs. + This specification mandates support for OIDs which have arc elements + with values that are less than 2^28, that is, they MUST be between 0 + and 268,435,455, inclusive. This allows each arc element to be + represented within a single 32 bit word. Implementations MUST also + support OIDs where the length of the dotted decimal (see [RFC 2252], + section 4.1) string representation can be up to 100 bytes + (inclusive). Implementations MUST be able to handle OIDs with up to + 20 elements (inclusive). CAs SHOULD NOT issue certificates which + contain OIDs that exceed these requirements. Likewise, CRL issuers + SHOULD NOT issue CRLs which contain OIDs that exceed these + requirements. +*/ + +/* Oids longer than this are considered invalid. */ +#define MAX_OID_SIZE 32 + +CFStringRef SecDERItemCopyOIDDecimalRepresentation(CFAllocatorRef allocator, + const DERItem *oid) { + + if (oid->length == 0) { + return SecFrameworkCopyLocalizedString(CFSTR(""), + CFSTR("SecCertificate")); + } + if (oid->length > MAX_OID_SIZE) { + return SecFrameworkCopyLocalizedString(CFSTR("Oid too long"), + CFSTR("SecCertificate")); + } + + CFMutableStringRef result = CFStringCreateMutable(allocator, 0); + + // The first two levels are encoded into one byte, since the root level + // has only 3 nodes (40*x + y). However if x = joint-iso-itu-t(2) then + // y may be > 39, so we have to add special-case handling for this. + uint32_t x = oid->data[0] / 40; + uint32_t y = oid->data[0] % 40; + if (x > 2) + { + // Handle special case for large y if x = 2 + y += (x - 2) * 40; + x = 2; + } + CFStringAppendFormat(result, NULL, CFSTR("%u.%u"), x, y); + + uint32_t value = 0; + for (x = 1; x < oid->length; ++x) + { + value = (value << 7) | (oid->data[x] & 0x7F); + /* @@@ value may not span more than 4 bytes. */ + /* A max number of 20 values is allowed. */ + if (!(oid->data[x] & 0x80)) + { + CFStringAppendFormat(result, NULL, CFSTR(".%lu"), value); + value = 0; + } + } + return result; +} + +static CFStringRef copyLocalizedOidDescription(CFAllocatorRef allocator, + const DERItem *oid) { + if (oid->length == 0) { + return SecFrameworkCopyLocalizedString(CFSTR(""), + CFSTR("SecCertificate")); + } + + /* Build the key we use to lookup the localized OID description. */ + CFMutableStringRef oidKey = CFStringCreateMutable(allocator, + oid->length * 3 + 5); + CFStringAppendFormat(oidKey, NULL, CFSTR("06 %02X"), oid->length); + DERSize ix; + for (ix = 0; ix < oid->length; ++ix) + CFStringAppendFormat(oidKey, NULL, CFSTR(" %02X"), oid->data[ix]); + + CFStringRef name = SecFrameworkCopyLocalizedString(oidKey, CFSTR("OID")); + if (CFEqual(oidKey, name)) { + CFRelease(name); + name = SecDERItemCopyOIDDecimalRepresentation(allocator, oid); + } + CFRelease(oidKey); + + return name; +} + +/* Return the ipAddress as a dotted quad for ipv4 or as 8 colon separated + 4 digit hex strings for ipv6. Return NULL if the passed in IP doesn't + have a length of exactly 4 or 16 octects. */ +static CFStringRef copyIPAddressContentDescription(CFAllocatorRef allocator, + const DERItem *ip) { + /* @@@ This is the IP Address as an OCTECT STRING. For IPv4 it's + 4 octects addr, or 8 octects, addr/mask for ipv6 it's + 16 octects addr, or 32 octects addr/mask. */ + CFStringRef value = NULL; + if (ip->length == 4) { + value = CFStringCreateWithFormat(allocator, NULL, + CFSTR("%u.%u.%u.%u"), + ip->data[0], ip->data[1], ip->data[2], ip->data[3]); + } else if (ip->length == 16) { + value = CFStringCreateWithFormat(allocator, NULL, + CFSTR("%02x%02x:%02x%02x:%02x%02x:%02x%02x:" + "%02x%02x:%02x%02x:%02x%02x:%02x%02x"), + ip->data[0], ip->data[1], ip->data[2], ip->data[3], + ip->data[4], ip->data[5], ip->data[6], ip->data[7], + ip->data[8], ip->data[9], ip->data[10], ip->data[11], + ip->data[12], ip->data[13], ip->data[14], ip->data[15]); + } + + return value; +} + +#if 0 +static CFStringRef copyFullOidDescription(CFAllocatorRef allocator, + const DERItem *oid) { + CFStringRef decimal = SecDERItemCopyOIDDecimalRepresentation(allocator, oid); + CFStringRef name = copyLocalizedOidDescription(allocator, oid); + CFStringRef oid_string = CFStringCreateWithFormat(allocator, NULL, + CFSTR("%@ (%@)"), name, decimal); + CFRelease(name); + CFRelease(decimal); + return oid_string; +} +#endif + +void appendProperty(CFMutableArrayRef properties, + CFStringRef propertyType, CFStringRef label, CFTypeRef value) { + CFDictionaryRef property; + if (label) { + CFStringRef localizedLabel = SecFrameworkCopyLocalizedString(label, + CFSTR("SecCertificate")); + const void *all_keys[4]; + all_keys[0] = kSecPropertyKeyType; + all_keys[1] = kSecPropertyKeyLabel; + all_keys[2] = kSecPropertyKeyLocalizedLabel; + all_keys[3] = kSecPropertyKeyValue; + const void *property_values[] = { + propertyType, + label, + localizedLabel, + value, + }; + property = CFDictionaryCreate(CFGetAllocator(properties), + all_keys, property_values, value ? 4 : 3, + &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + CFRelease(localizedLabel); + } else { + const void *nolabel_keys[2]; + nolabel_keys[0] = kSecPropertyKeyType; + nolabel_keys[1] = kSecPropertyKeyValue; + const void *property_values[] = { + propertyType, + value, + }; + property = CFDictionaryCreate(CFGetAllocator(properties), + nolabel_keys, property_values, 2, + &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + } + + CFArrayAppendValue(properties, property); + CFRelease(property); +} + +/* YYMMDDhhmmZ */ +#define UTC_TIME_NOSEC_ZULU_LEN 11 +/* YYMMDDhhmmssZ */ +#define UTC_TIME_ZULU_LEN 13 +/* YYMMDDhhmmssThhmm */ +#define UTC_TIME_LOCALIZED_LEN 17 +/* YYYYMMDDhhmmssZ */ +#define GENERALIZED_TIME_ZULU_LEN 15 +/* YYYYMMDDhhmmssThhmm */ +#define GENERALIZED_TIME_LOCALIZED_LEN 19 + +/* Parse 2 digits at (*p)[0] and (*p)[1] and return the result. Also + advance *p by 2. */ +static inline SInt32 parseDecimalPair(const DERByte **p) { + const DERByte *cp = *p; + *p += 2; + return 10 * (cp[0] - '0') + cp[1] - '0'; +} + +/* 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. */ +CFAbsoluteTime SecAbsoluteTimeFromDateContent(DERTag tag, const uint8_t *bytes, + size_t length) { + check(bytes); + if (length == 0) + return NULL_TIME; + + bool isUtcLength = false; + bool isLocalized = false; + bool noSeconds = false; + switch (length) { + case UTC_TIME_NOSEC_ZULU_LEN: /* YYMMDDhhmmZ */ + isUtcLength = true; + noSeconds = true; + break; + case UTC_TIME_ZULU_LEN: /* YYMMDDhhmmssZ */ + isUtcLength = true; + break; + case GENERALIZED_TIME_ZULU_LEN: /* YYYYMMDDhhmmssZ */ + break; + case UTC_TIME_LOCALIZED_LEN: /* YYMMDDhhmmssThhmm (where T=[+,-]) */ + isUtcLength = true; + /*DROPTHROUGH*/ + case GENERALIZED_TIME_LOCALIZED_LEN:/* YYYYMMDDhhmmssThhmm (where T=[+,-]) */ + isLocalized = true; + break; + default: /* unknown format */ + return NULL_TIME; + } + + /* Make sure the der tag fits the thing inside it. */ + if (tag == ASN1_UTC_TIME) { + if (!isUtcLength) + return NULL_TIME; + } else if (tag == ASN1_GENERALIZED_TIME) { + if (isUtcLength) + return NULL_TIME; + } else { + return NULL_TIME; + } + + const DERByte *cp = bytes; + /* Check that all characters are digits, except if localized the timezone + indicator or if not localized the 'Z' at the end. */ + DERSize ix; + for (ix = 0; ix < length; ++ix) { + if (!(isdigit(cp[ix]))) { + if ((isLocalized && ix == length - 5 && + (cp[ix] == '+' || cp[ix] == '-')) || + (!isLocalized && ix == length - 1 && cp[ix] == 'Z')) { + continue; + } + return NULL_TIME; + } + } + + /* Initialize the fields in a gregorian date struct. */ + CFGregorianDate gdate; + if (isUtcLength) { + SInt32 year = parseDecimalPair(&cp); + if (year < 50) { + /* 0 <= year < 50 : assume century 21 */ + gdate.year = 2000 + year; + } else if (year < 70) { + /* 50 <= year < 70 : illegal per PKIX */ + return false; + } else { + /* 70 < year <= 99 : assume century 20 */ + gdate.year = 1900 + year; + } + } else { + gdate.year = 100 * parseDecimalPair(&cp) + parseDecimalPair(&cp); + } + gdate.month = parseDecimalPair(&cp); + gdate.day = parseDecimalPair(&cp); + gdate.hour = parseDecimalPair(&cp); + gdate.minute = parseDecimalPair(&cp); + if (noSeconds) { + gdate.second = 0; + } else { + gdate.second = parseDecimalPair(&cp); + } + + CFTimeInterval timeZoneOffset = 0; + if (isLocalized) { + /* ZONE INDICATOR */ + SInt32 multiplier = *cp++ == '+' ? 60 : -60; + timeZoneOffset = multiplier * + (parseDecimalPair(&cp) + 60 * parseDecimalPair(&cp)); + } else { + timeZoneOffset = 0; + } + + secdebug("dateparse", + "date %.*s year: %04d-%02d-%02d %02d:%02d:%02.f %+05.f", + length, bytes, gdate.year, gdate.month, + gdate.day, gdate.hour, gdate.minute, gdate.second, + timeZoneOffset / 60); + + if (!CFGregorianDateIsValid(gdate, kCFGregorianAllUnits)) + return false; + CFTimeZoneRef timeZone = CFTimeZoneCreateWithTimeIntervalFromGMT(NULL, + timeZoneOffset); + if (!timeZone) + return NULL_TIME; + CFAbsoluteTime absTime = CFGregorianDateGetAbsoluteTime(gdate, timeZone); + CFRelease(timeZone); + return absTime; +} + +static bool derDateContentGetAbsoluteTime(DERTag tag, const DERItem *date, + CFAbsoluteTime *pabsTime) { + CFAbsoluteTime absTime = SecAbsoluteTimeFromDateContent(tag, date->data, + date->length); + if (absTime == NULL_TIME) + return false; + + *pabsTime = absTime; + return true; +} + +/* 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, + CFAbsoluteTime *absTime) { + check(dateChoice); + check(absTime); + if (dateChoice->length == 0) + return false; + + DERDecodedInfo decoded; + if (DERDecodeItem(dateChoice, &decoded)) + return false; + + return derDateContentGetAbsoluteTime(decoded.tag, &decoded.content, + absTime); +} + +static void appendDataProperty(CFMutableArrayRef properties, + CFStringRef label, const DERItem *der_data) { + CFDataRef data = CFDataCreate(CFGetAllocator(properties), + der_data->data, der_data->length); + appendProperty(properties, kSecPropertyTypeData, label, data); + CFRelease(data); +} + +static void appendUnparsedProperty(CFMutableArrayRef properties, + CFStringRef label, const DERItem *der_data) { + CFStringRef newLabel = CFStringCreateWithFormat(CFGetAllocator(properties), + NULL, CFSTR("Unparsed %@"), label); + appendDataProperty(properties, newLabel, der_data); + CFRelease(newLabel); +} + +static void appendInvalidProperty(CFMutableArrayRef properties, + CFStringRef label, const DERItem *der_data) { + CFStringRef newLabel = CFStringCreateWithFormat(CFGetAllocator(properties), + NULL, CFSTR("Invalid %@"), label); + appendDataProperty(properties, newLabel, der_data); + CFRelease(newLabel); +} + +static void appendDateContentProperty(CFMutableArrayRef properties, + CFStringRef label, DERTag tag, const DERItem *dateContent) { + CFAbsoluteTime absTime; + if (!derDateContentGetAbsoluteTime(tag, dateContent, &absTime)) { + /* Date decode failure insert hex bytes instead. */ + return appendInvalidProperty(properties, label, dateContent); + } + CFDateRef date = CFDateCreate(CFGetAllocator(properties), absTime); + appendProperty(properties, kSecPropertyTypeDate, label, date); + CFRelease(date); +} + +static void appendDateProperty(CFMutableArrayRef properties, + CFStringRef label, CFAbsoluteTime absTime) { + CFDateRef date = CFDateCreate(CFGetAllocator(properties), absTime); + appendProperty(properties, kSecPropertyTypeDate, label, date); + CFRelease(date); +} + +static void appendIPAddressContentProperty(CFMutableArrayRef properties, + CFStringRef label, const DERItem *ip) { + CFStringRef value = + copyIPAddressContentDescription(CFGetAllocator(properties), ip); + if (value) { + appendProperty(properties, kSecPropertyTypeString, label, value); + CFRelease(value); + } else { + appendUnparsedProperty(properties, label, ip); + } +} + +static void appendURLContentProperty(CFMutableArrayRef properties, + CFStringRef label, const DERItem *urlContent) { + CFURLRef url = CFURLCreateWithBytes(CFGetAllocator(properties), + urlContent->data, urlContent->length, kCFStringEncodingASCII, NULL); + if (url) { + appendProperty(properties, kSecPropertyTypeURL, label, url); + CFRelease(url); + } else { + appendInvalidProperty(properties, label, urlContent); + } +} + +static void appendURLProperty(CFMutableArrayRef properties, + CFStringRef label, const DERItem *url) { + DERDecodedInfo decoded; + DERReturn drtn; + + drtn = DERDecodeItem(url, &decoded); + if (drtn || decoded.tag != ASN1_IA5_STRING) { + appendInvalidProperty(properties, label, url); + } else { + appendURLContentProperty(properties, label, &decoded.content); + } +} + +static void appendOIDProperty(CFMutableArrayRef properties, + CFStringRef label, const DERItem *oid) { + CFStringRef oid_string = copyLocalizedOidDescription(CFGetAllocator(properties), + oid); + appendProperty(properties, kSecPropertyTypeString, label, oid_string); + CFRelease(oid_string); +} + +static void appendAlgorithmProperty(CFMutableArrayRef properties, + CFStringRef label, const DERAlgorithmId *algorithm) { + CFMutableArrayRef alg_props = + CFArrayCreateMutable(CFGetAllocator(properties), 0, + &kCFTypeArrayCallBacks); + appendOIDProperty(alg_props, CFSTR("Algorithm"), &algorithm->oid); + if (algorithm->params.length) { + if (algorithm->params.length == 2 && + algorithm->params.data[0] == ASN1_NULL && + algorithm->params.data[1] == 0) { + /* @@@ Localize or perhaps skip it? */ + appendProperty(alg_props, kSecPropertyTypeString, + CFSTR("Parameters"), CFSTR("none")); + } else { + appendUnparsedProperty(alg_props, CFSTR("Parameters"), + &algorithm->params); + } + } + appendProperty(properties, kSecPropertyTypeSection, label, alg_props); + CFRelease(alg_props); +} + +static CFStringRef copyHexDescription(CFAllocatorRef allocator, + const DERItem *blob) { + CFIndex ix, length = blob->length /* < 24 ? blob->length : 24 */; + CFMutableStringRef string = CFStringCreateMutable(allocator, + blob->length * 3 - 1); + for (ix = 0; ix < length; ++ix) + if (ix == 0) + CFStringAppendFormat(string, NULL, CFSTR("%02X"), blob->data[ix]); + else + CFStringAppendFormat(string, NULL, CFSTR(" %02X"), blob->data[ix]); + + return string; +} + +static CFStringRef copyBlobString(CFAllocatorRef allocator, + CFStringRef blobType, CFStringRef quanta, const DERItem *blob) { + CFStringRef blobFormat = SecFrameworkCopyLocalizedString( + CFSTR("%@; %d %@; data = %@"), CFSTR("SecCertificate") + /*, "format string for encoded field data (e.g. Sequence; 128 bytes; " + "data = 00 00 ...)" */); + CFStringRef hex = copyHexDescription(allocator, blob); + CFStringRef result = CFStringCreateWithFormat(allocator, NULL, + blobFormat, blobType, blob->length, quanta, hex); + CFRelease(hex); + CFRelease(blobFormat); + + return result; +} + +static CFStringRef copyContentString(CFAllocatorRef allocator, + const DERItem *string, CFStringEncoding encoding, + bool printableOnly) { + /* Strip potential bogus trailing zero from printable strings. */ + DERSize length = string->length; + if (length && string->data[length - 1] == 0) { + /* Don't mess with the length of UTF16 strings though. */ + if (encoding != kCFStringEncodingUTF16) + length--; + } + /* A zero length string isn't considered printable. */ + if (!length && printableOnly) + return NULL; + + /* Passing true for the 5th paramater to CFStringCreateWithBytes() makes + it treat kCFStringEncodingUTF16 as big endian by default, whereas + passing false makes it treat it as native endian by default. */ + CFStringRef result = CFStringCreateWithBytes(allocator, string->data, + length, encoding, encoding == kCFStringEncodingUTF16); + if (result) + return result; + + return printableOnly ? NULL : copyHexDescription(allocator, string); +} + +/* From rfc3280 - Appendix B. ASN.1 Notes + + CAs MUST force the serialNumber to be a non-negative integer, that + is, the sign bit in the DER encoding of the INTEGER value MUST be + zero - this can be done by adding a leading (leftmost) `00'H octet if + necessary. This removes a potential ambiguity in mapping between a + string of octets and an integer value. + + As noted in section 4.1.2.2, serial numbers can be expected to + contain long integers. Certificate users MUST be able to handle + serialNumber values up to 20 octets in length. Conformant CAs MUST + NOT use serialNumber values longer than 20 octets. +*/ + +/* Return the given numeric data as a string: decimal up to 64 bits, + hex otherwise. */ +static CFStringRef copyIntegerContentDescription(CFAllocatorRef allocator, + const DERItem *integer) { + uint64_t value = 0; + CFIndex ix, length = integer->length; + + if (length == 0 || length > 8) + return copyHexDescription(allocator, integer); + + for(ix = 0; ix < length; ++ix) { + value <<= 8; + value += integer->data[ix]; + } + + return CFStringCreateWithFormat(allocator, NULL, CFSTR("%llu"), value); +} + +static CFStringRef copyDERThingContentDescription(CFAllocatorRef allocator, + DERTag tag, const DERItem *derThing, bool printableOnly) { + switch(tag) { + case ASN1_INTEGER: + case ASN1_BOOLEAN: + return printableOnly ? NULL : copyIntegerContentDescription(allocator, derThing); + case ASN1_PRINTABLE_STRING: + case ASN1_IA5_STRING: + return copyContentString(allocator, derThing, kCFStringEncodingASCII, printableOnly); + case ASN1_UTF8_STRING: + case ASN1_GENERAL_STRING: + case ASN1_UNIVERSAL_STRING: + return copyContentString(allocator, derThing, kCFStringEncodingUTF8, printableOnly); + case ASN1_T61_STRING: // 20, also BER_TAG_TELETEX_STRING + case ASN1_VIDEOTEX_STRING: // 21 + case ASN1_VISIBLE_STRING: // 26 + return copyContentString(allocator, derThing, kCFStringEncodingISOLatin1, printableOnly); + case ASN1_BMP_STRING: // 30 + return copyContentString(allocator, derThing, kCFStringEncodingUTF16, printableOnly); + case ASN1_OCTET_STRING: + return printableOnly ? NULL : copyBlobString(allocator, CFSTR("Byte string"), CFSTR("bytes"), + derThing); + //return copyBlobString(BYTE_STRING_STR, BYTES_STR, derThing); + case ASN1_BIT_STRING: + return printableOnly ? NULL : copyBlobString(allocator, CFSTR("Bit string"), CFSTR("bits"), + derThing); + case (DERByte)ASN1_CONSTR_SEQUENCE: + return printableOnly ? NULL : copyBlobString(allocator, CFSTR("Sequence"), CFSTR("bytes"), + derThing); + case (DERByte)ASN1_CONSTR_SET: + return printableOnly ? NULL : copyBlobString(allocator, CFSTR("Set"), CFSTR("bytes"), + derThing); + case ASN1_OBJECT_ID: + return printableOnly ? NULL : copyLocalizedOidDescription(allocator, derThing); + default: + /* @@@ Localize. */ + /* "format string for undisplayed field data with a given DER tag" */ + return printableOnly ? NULL : CFStringCreateWithFormat(allocator, NULL, + CFSTR("not displayed (tag = %d; length %d)"), + tag, derThing->length); + } +} + +static CFStringRef copyDERThingDescription(CFAllocatorRef allocator, + const DERItem *derThing, bool printableOnly) { + DERDecodedInfo decoded; + DERReturn drtn; + + drtn = DERDecodeItem(derThing, &decoded); + if (drtn) { + return printableOnly ? NULL : copyHexDescription(allocator, derThing); + } else { + return copyDERThingContentDescription(allocator, decoded.tag, + &decoded.content, false); + } +} + +static void appendDERThingProperty(CFMutableArrayRef properties, + CFStringRef label, const DERItem *derThing) { + CFStringRef value = copyDERThingDescription(CFGetAllocator(properties), + derThing, false); + appendProperty(properties, kSecPropertyTypeString, label, value); + CFRelease(value); +} + +static OSStatus appendRDNProperty(void *context, const DERItem *rdnType, + const DERItem *rdnValue, CFIndex rdnIX) { + CFMutableArrayRef properties = (CFMutableArrayRef)context; + if (rdnIX > 0) { + /* If there is more than one value pair we create a subsection for the + second pair, and append things to the subsection for subsequent + pairs. */ + CFIndex lastIX = CFArrayGetCount(properties) - 1; + CFTypeRef lastValue = CFArrayGetValueAtIndex(properties, lastIX); + if (rdnIX == 1) { + /* Since this is the second rdn pair for a given rdn, we setup a + new subsection for this rdn. We remove the first property + from the properties array and make it the first element in the + subsection instead. */ + CFMutableArrayRef rdn_props = CFArrayCreateMutable( + CFGetAllocator(properties), 0, &kCFTypeArrayCallBacks); + CFArrayAppendValue(rdn_props, lastValue); + CFArrayRemoveValueAtIndex(properties, lastIX); + appendProperty(properties, kSecPropertyTypeSection, NULL, rdn_props); + properties = rdn_props; + } else { + /* Since this is the third or later rdn pair we have already + created a subsection in the top level properties array. Instead + of appending to that directly we append to the array inside the + subsection. */ + properties = (CFMutableArrayRef)CFDictionaryGetValue( + (CFDictionaryRef)lastValue, kSecPropertyKeyValue); + } + } + + /* Finally we append the new rdn value to the property array. */ + CFStringRef label = copyLocalizedOidDescription(CFGetAllocator(properties), + rdnType); + if (label) { + appendDERThingProperty(properties, label, rdnValue); + CFRelease(label); + return noErr; + } else { + return errSecInvalidCertificate; + } +} + +static CFArrayRef createPropertiesForRDNContent(CFAllocatorRef allocator, + const DERItem *rdnSetContent) { + CFMutableArrayRef properties = CFArrayCreateMutable(allocator, 0, + &kCFTypeArrayCallBacks); + OSStatus status = parseRDNContent(rdnSetContent, properties, + appendRDNProperty); + if (status) { + CFArrayRemoveAllValues(properties); + appendInvalidProperty(properties, CFSTR("RDN"), rdnSetContent); + } + + return properties; +} + +/* + From rfc3739 - 3.1.2. Subject + + When parsing the subject here are some tips for a short name of the cert. + Choice I: commonName + Choice II: givenName + Choice III: pseudonym + + The commonName attribute value SHALL, when present, contain a name + of the subject. This MAY be in the subject's preferred + presentation format, or a format preferred by the CA, or some + other format. Pseudonyms, nicknames, and names with spelling + other than defined by the registered name MAY be used. To + understand the nature of the name presented in commonName, + complying applications MAY have to examine present values of the + givenName and surname attributes, or the pseudonym attribute. + +*/ +static CFArrayRef createPropertiesForX501NameContent(CFAllocatorRef allocator, + const DERItem *x501NameContent) { + CFMutableArrayRef properties = CFArrayCreateMutable(allocator, 0, + &kCFTypeArrayCallBacks); + OSStatus status = parseX501NameContent(x501NameContent, properties, + appendRDNProperty); + if (status) { + CFArrayRemoveAllValues(properties); + appendInvalidProperty(properties, CFSTR("X.501 Name"), x501NameContent); + } + + return properties; +} + +static CFArrayRef createPropertiesForX501Name(CFAllocatorRef allocator, + const DERItem *x501Name) { + CFMutableArrayRef properties = CFArrayCreateMutable(allocator, 0, + &kCFTypeArrayCallBacks); + OSStatus status = parseX501Name(x501Name, properties, appendRDNProperty); + if (status) { + CFArrayRemoveAllValues(properties); + appendInvalidProperty(properties, CFSTR("X.501 Name"), x501Name); + } + + return properties; +} + +static void appendIntegerProperty(CFMutableArrayRef properties, + CFStringRef label, const DERItem *integer) { + CFStringRef string = copyIntegerContentDescription( + CFGetAllocator(properties), integer); + appendProperty(properties, kSecPropertyTypeString, label, string); + CFRelease(string); +} + +static void appendBoolProperty(CFMutableArrayRef properties, + CFStringRef label, bool boolean) { + appendProperty(properties, kSecPropertyTypeString, + label, boolean ? CFSTR("Yes") : CFSTR("No")); +} + +static void appendBooleanProperty(CFMutableArrayRef properties, + CFStringRef label, const DERItem *boolean, bool defaultValue) { + bool result; + DERReturn drtn = DERParseBoolean(boolean, defaultValue, &result); + if (drtn) { + /* Couldn't parse boolean; dump the raw unparsed data as hex. */ + appendInvalidProperty(properties, label, boolean); + } else { + appendBoolProperty(properties, label, result); + } +} + +static void appendBitStringContentNames(CFMutableArrayRef properties, + CFStringRef label, const DERItem *bitStringContent, + const CFStringRef *names, CFIndex namesCount) { + DERSize len = bitStringContent->length - 1; + require_quiet(len == 1 || len == 2, badDER); + DERByte numUnusedBits = bitStringContent->data[0]; + require_quiet(numUnusedBits < 8, badDER); + uint_fast16_t bits = 8 * len - numUnusedBits; + require_quiet(bits <= (uint_fast16_t)namesCount, badDER); + uint_fast16_t value = bitStringContent->data[1]; + uint_fast16_t mask; + if (len > 1) { + value = (value << 8) + bitStringContent->data[2]; + mask = 0x8000; + } else { + mask = 0x80; + } + uint_fast16_t ix; + bool didOne = false; + CFMutableStringRef string = + CFStringCreateMutable(CFGetAllocator(properties), 0); + for (ix = 0; ix < bits; ++ix) { + if (value & mask) { + if (didOne) { + CFStringAppend(string, CFSTR(", ")); + } else { + didOne = true; + } + CFStringAppend(string, names[ix]); + } + mask >>= 1; + } + appendProperty(properties, kSecPropertyTypeString, label, string); + CFRelease(string); + return; +badDER: + appendInvalidProperty(properties, label, bitStringContent); +} + +static void appendBitStringNames(CFMutableArrayRef properties, + CFStringRef label, const DERItem *bitString, + const CFStringRef *names, CFIndex namesCount) { + DERDecodedInfo bitStringContent; + DERReturn drtn = DERDecodeItem(bitString, &bitStringContent); + require_noerr_quiet(drtn, badDER); + require_quiet(bitStringContent.tag == ASN1_BIT_STRING, badDER); + appendBitStringContentNames(properties, label, &bitStringContent.content, + names, namesCount); + return; +badDER: + appendInvalidProperty(properties, label, bitString); +} + +#if 0 +typedef uint16_t SecKeyUsage; + +#define kSecKeyUsageDigitalSignature 0x8000 +#define kSecKeyUsageNonRepudiation 0x4000 +#define kSecKeyUsageKeyEncipherment 0x2000 +#define kSecKeyUsageDataEncipherment 0x1000 +#define kSecKeyUsageKeyAgreement 0x0800 +#define kSecKeyUsageKeyCertSign 0x0400 +#define kSecKeyUsageCRLSign 0x0200 +#define kSecKeyUsageEncipherOnly 0x0100 +#define kSecKeyUsageDecipherOnly 0x0080 + +/* + KeyUsage ::= BIT STRING { + digitalSignature (0), + nonRepudiation (1), + keyEncipherment (2), + dataEncipherment (3), + keyAgreement (4), + keyCertSign (5), + cRLSign (6), + encipherOnly (7), + decipherOnly (8) } + */ +static void appendKeyUsage(CFMutableArrayRef properties, + const DERItem *extnValue) { + if ((extnValue->length != 4 && extnValue->length != 5) || + extnValue->data[0] != ASN1_BIT_STRING || + extnValue->data[1] < 2 || extnValue->data[1] > 3 || + extnValue->data[2] > 7) { + appendInvalidProperty(properties, CFSTR("KeyUsage Extension"), + extnValue); + } else { + CFMutableStringRef string = + CFStringCreateMutable(CFGetAllocator(properties), 0); + SecKeyUsage usage = (extnValue->data[3] << 8); + if (extnValue->length == 5) + usage += extnValue->data[4]; + secdebug("keyusage", "keyusage: %04X", usage); + static const CFStringRef usageNames[] = { + CFSTR("Digital Signature"), + CFSTR("Non-Repudiation"), + CFSTR("Key Encipherment"), + CFSTR("Data Encipherment"), + CFSTR("Key Agreement"), + CFSTR("Cert Sign"), + CFSTR("CRL Sign"), + CFSTR("Encipher"), + CFSTR("Decipher"), + }; + bool didOne = false; + SecKeyUsage mask = kSecKeyUsageDigitalSignature; + CFIndex ix, bits = (extnValue->data[1] - 1) * 8 - extnValue->data[2]; + for (ix = 0; ix < bits; ++ix) { + if (usage & mask) { + if (didOne) { + CFStringAppend(string, CFSTR(", ")); + } else { + didOne = true; + } + /* @@@ Localize usageNames[ix]. */ + CFStringAppend(string, usageNames[ix]); + } + mask >>= 1; + } + appendProperty(properties, kSecPropertyTypeString, CFSTR("Usage"), + string); + CFRelease(string); + } +} +#else +static void appendKeyUsage(CFMutableArrayRef properties, + const DERItem *extnValue) { + static const CFStringRef usageNames[] = { + CFSTR("Digital Signature"), + CFSTR("Non-Repudiation"), + CFSTR("Key Encipherment"), + CFSTR("Data Encipherment"), + CFSTR("Key Agreement"), + CFSTR("Cert Sign"), + CFSTR("CRL Sign"), + CFSTR("Encipher Only"), + CFSTR("Decipher Only") + }; + appendBitStringNames(properties, CFSTR("Usage"), extnValue, + usageNames, sizeof(usageNames) / sizeof(*usageNames)); +} +#endif + +static void appendPrivateKeyUsagePeriod(CFMutableArrayRef properties, + const DERItem *extnValue) { + DERPrivateKeyUsagePeriod pkup; + DERReturn drtn = DERParseSequence(extnValue, + DERNumPrivateKeyUsagePeriodItemSpecs, DERPrivateKeyUsagePeriodItemSpecs, + &pkup, sizeof(pkup)); + require_noerr_quiet(drtn, badDER); + if (pkup.notBefore.length) { + appendDateContentProperty(properties, CFSTR("Not Valid Before"), + ASN1_GENERALIZED_TIME, &pkup.notBefore); + } + if (pkup.notAfter.length) { + appendDateContentProperty(properties, CFSTR("Not Valid After"), + ASN1_GENERALIZED_TIME, &pkup.notAfter); + } + return; +badDER: + appendInvalidProperty(properties, CFSTR("Private Key Usage Period"), + extnValue); +} + +static void appendStringContentProperty(CFMutableArrayRef properties, + CFStringRef label, const DERItem *stringContent, + CFStringEncoding encoding) { + CFStringRef string = CFStringCreateWithBytes(CFGetAllocator(properties), + stringContent->data, stringContent->length, encoding, FALSE); + if (string) { + appendProperty(properties, kSecPropertyTypeString, label, string); + CFRelease(string); + } else { + appendInvalidProperty(properties, label, stringContent); + } +} + +/* + OtherName ::= SEQUENCE { + type-id OBJECT IDENTIFIER, + value [0] EXPLICIT ANY DEFINED BY type-id } +*/ +static void appendOtherNameContentProperty(CFMutableArrayRef properties, + const DERItem *otherNameContent) { + DEROtherName on; + DERReturn drtn = DERParseSequenceContent(otherNameContent, + DERNumOtherNameItemSpecs, DEROtherNameItemSpecs, + &on, sizeof(on)); + require_noerr_quiet(drtn, badDER); + CFAllocatorRef allocator = CFGetAllocator(properties); + CFStringRef oid_string = copyLocalizedOidDescription(allocator, + &on.typeIdentifier); + CFStringRef value_string = copyDERThingDescription(allocator, &on.value, false); + if (value_string) + appendProperty(properties, kSecPropertyTypeString, oid_string, + value_string); + else + appendUnparsedProperty(properties, oid_string, &on.value); + + return; +badDER: + appendInvalidProperty(properties, CFSTR("Other Name"), otherNameContent); +} + +/* + GeneralName ::= CHOICE { + otherName [0] OtherName, + rfc822Name [1] IA5String, + dNSName [2] IA5String, + x400Address [3] ORAddress, + directoryName [4] Name, + ediPartyName [5] EDIPartyName, + uniformResourceIdentifier [6] IA5String, + iPAddress [7] OCTET STRING, + registeredID [8] OBJECT IDENTIFIER} + + EDIPartyName ::= SEQUENCE { + nameAssigner [0] DirectoryString OPTIONAL, + partyName [1] DirectoryString } + */ +static bool appendGeneralNameContentProperty(CFMutableArrayRef properties, + DERTag tag, const DERItem *generalName) { + switch (tag) { + case ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 0: + appendOtherNameContentProperty(properties, generalName); + break; + case ASN1_CONTEXT_SPECIFIC | 1: + /* IA5String. */ + appendStringContentProperty(properties, CFSTR("Email Address"), + generalName, kCFStringEncodingASCII); + break; + case ASN1_CONTEXT_SPECIFIC | 2: + /* IA5String. */ + appendStringContentProperty(properties, CFSTR("DNS Name"), generalName, + kCFStringEncodingASCII); + break; + case ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 3: + appendUnparsedProperty(properties, CFSTR("X.400 Address"), + generalName); + break; + case ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 4: + { + CFArrayRef directory_plist = + createPropertiesForX501Name(CFGetAllocator(properties), + generalName); + appendProperty(properties, kSecPropertyTypeSection, + CFSTR("Directory Name"), directory_plist); + CFRelease(directory_plist); + break; + } + case ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 5: + appendUnparsedProperty(properties, CFSTR("EDI Party Name"), + generalName); + break; + case ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 6: + /* Technically I don't think this is valid, but there are certs out + in the wild that use a constructed IA5String. In particular the + VeriSign Time Stamping Authority CA.cer does this. */ + appendURLProperty(properties, CFSTR("URI"), generalName); + break; + case ASN1_CONTEXT_SPECIFIC | 6: + appendURLContentProperty(properties, CFSTR("URI"), generalName); + break; + case ASN1_CONTEXT_SPECIFIC | 7: + appendIPAddressContentProperty(properties, CFSTR("IP Address"), + generalName); + break; + case ASN1_CONTEXT_SPECIFIC | 8: + appendOIDProperty(properties, CFSTR("Registered ID"), generalName); + break; + default: + goto badDER; + break; + } + return true; +badDER: + return false; +} + +static void appendGeneralNameProperty(CFMutableArrayRef properties, + const DERItem *generalName) { + DERDecodedInfo generalNameContent; + DERReturn drtn = DERDecodeItem(generalName, &generalNameContent); + require_noerr_quiet(drtn, badDER); + if (appendGeneralNameContentProperty(properties, generalNameContent.tag, + &generalNameContent.content)) + return; +badDER: + appendInvalidProperty(properties, CFSTR("General Name"), generalName); +} + + +/* + GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName + */ +static void appendGeneralNamesContent(CFMutableArrayRef properties, + const DERItem *generalNamesContent) { + DERSequence gnSeq; + DERReturn drtn = DERDecodeSeqContentInit(generalNamesContent, &gnSeq); + require_noerr_quiet(drtn, badDER); + DERDecodedInfo generalNameContent; + while ((drtn = DERDecodeSeqNext(&gnSeq, &generalNameContent)) == + DR_Success) { + if (!appendGeneralNameContentProperty(properties, + generalNameContent.tag, &generalNameContent.content)) { + goto badDER; + } + } + require_quiet(drtn == DR_EndOfSequence, badDER); + return; +badDER: + appendInvalidProperty(properties, CFSTR("General Names"), + generalNamesContent); +} + +static void appendGeneralNames(CFMutableArrayRef properties, + const DERItem *generalNames) { + DERDecodedInfo generalNamesContent; + DERReturn drtn = DERDecodeItem(generalNames, &generalNamesContent); + require_noerr_quiet(drtn, badDER); + require_quiet(generalNamesContent.tag == ASN1_CONSTR_SEQUENCE, + badDER); + appendGeneralNamesContent(properties, &generalNamesContent.content); + return; +badDER: + appendInvalidProperty(properties, CFSTR("General Names"), generalNames); +} + +/* +BasicConstraints ::= SEQUENCE { + cA BOOLEAN DEFAULT FALSE, + pathLenConstraint INTEGER (0..MAX) OPTIONAL } +*/ +static void appendBasicConstraints(CFMutableArrayRef properties, + const DERItem *extnValue) { + DERBasicConstraints basicConstraints; + DERReturn drtn = DERParseSequence(extnValue, + DERNumBasicConstraintsItemSpecs, DERBasicConstraintsItemSpecs, + &basicConstraints, sizeof(basicConstraints)); + require_noerr_quiet(drtn, badDER); + + appendBooleanProperty(properties, CFSTR("Certificate Authority"), + &basicConstraints.cA, false); + + if (basicConstraints.pathLenConstraint.length != 0) { + appendIntegerProperty(properties, CFSTR("Path Length Constraint"), + &basicConstraints.pathLenConstraint); + } + return; +badDER: + appendInvalidProperty(properties, CFSTR("Basic Constraints"), extnValue); +} + +/* + CRLDistPointsSyntax ::= SEQUENCE SIZE (1..MAX) OF DistributionPoint + + 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), + privilegeWithdrawn (7), + aACompromise (8) } +*/ +static void appendCrlDistributionPoints(CFMutableArrayRef properties, + const DERItem *extnValue) { + CFAllocatorRef allocator = CFGetAllocator(properties); + DERTag tag; + DERSequence dpSeq; + DERReturn drtn = DERDecodeSeqInit(extnValue, &tag, &dpSeq); + require_noerr_quiet(drtn, badDER); + require_quiet(tag == ASN1_CONSTR_SEQUENCE, badDER); + DERDecodedInfo dpSeqContent; + while ((drtn = DERDecodeSeqNext(&dpSeq, &dpSeqContent)) == DR_Success) { + require_quiet(dpSeqContent.tag == ASN1_CONSTR_SEQUENCE, badDER); + DERDistributionPoint dp; + drtn = DERParseSequenceContent(&dpSeqContent.content, + DERNumDistributionPointItemSpecs, + DERDistributionPointItemSpecs, + &dp, sizeof(dp)); + require_noerr_quiet(drtn, badDER); + if (dp.distributionPoint.length) { + DERDecodedInfo distributionPointName; + drtn = DERDecodeItem(&dp.distributionPoint, &distributionPointName); + require_noerr_quiet(drtn, badDER); + if (distributionPointName.tag == + (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 0)) { + /* Full Name */ + appendGeneralNamesContent(properties, + &distributionPointName.content); + } else if (distributionPointName.tag == + (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 1)) { + CFArrayRef rdn_props = createPropertiesForRDNContent(allocator, + &dp.reasons); + appendProperty(properties, kSecPropertyTypeSection, + CFSTR("Name Relative To CRL Issuer"), rdn_props); + CFRelease(rdn_props); + } else { + goto badDER; + } + } + if (dp.reasons.length) { + static const CFStringRef reasonNames[] = { + CFSTR("Unused"), + CFSTR("Key Compromise"), + CFSTR("CA Compromise"), + CFSTR("Affiliation Changed"), + CFSTR("Superseded"), + CFSTR("Cessation Of Operation"), + CFSTR("Certificate Hold"), + CFSTR("Priviledge Withdrawn"), + CFSTR("AA Compromise") + }; + appendBitStringContentNames(properties, CFSTR("Reasons"), + &dp.reasons, + reasonNames, sizeof(reasonNames) / sizeof(*reasonNames)); + } + if (dp.cRLIssuer.length) { + CFMutableArrayRef crlIssuer = CFArrayCreateMutable(allocator, 0, + &kCFTypeArrayCallBacks); + appendProperty(properties, kSecPropertyTypeSection, + CFSTR("CRL Issuer"), crlIssuer); + CFRelease(crlIssuer); + appendGeneralNames(crlIssuer, &dp.cRLIssuer); + } + } + require_quiet(drtn == DR_EndOfSequence, badDER); + return; +badDER: + appendInvalidProperty(properties, CFSTR("Crl Distribution Points"), + extnValue); +} + +/* Decode a sequence of integers into a comma separated list of ints. */ +static void appendIntegerSequenceContent(CFMutableArrayRef properties, + CFStringRef label, const DERItem *intSequenceContent) { + CFAllocatorRef allocator = CFGetAllocator(properties); + DERSequence intSeq; + DERReturn drtn = DERDecodeSeqContentInit(intSequenceContent, &intSeq); + require_noerr_quiet(drtn, badDER); + DERDecodedInfo intContent; + CFMutableStringRef value = NULL; + while ((drtn = DERDecodeSeqNext(&intSeq, &intContent)) + == DR_Success) { + require_quiet(intContent.tag == ASN1_INTEGER, badDER); + CFStringRef intDesc = copyIntegerContentDescription( + allocator, &intContent.content); + if (value) { + CFStringAppendFormat(value, NULL, CFSTR(", %@"), intDesc); + } else { + value = CFStringCreateMutableCopy(allocator, 0, intDesc); + } + CFRelease(intDesc); + } + require_quiet(drtn == DR_EndOfSequence, badDER); + if (value) { + appendProperty(properties, kSecPropertyTypeString, + CFSTR("Notice Numbers"), value); + CFRelease(value); + return; + } + /* DROPTHOUGH if !value. */ +badDER: + appendInvalidProperty(properties, label, intSequenceContent); +} + +static void appendCertificatePolicies(CFMutableArrayRef properties, + const DERItem *extnValue) { + CFAllocatorRef allocator = CFGetAllocator(properties); + DERTag tag; + DERSequence piSeq; + DERReturn drtn = DERDecodeSeqInit(extnValue, &tag, &piSeq); + require_noerr_quiet(drtn, badDER); + require_quiet(tag == ASN1_CONSTR_SEQUENCE, badDER); + DERDecodedInfo piContent; + int pin = 1; + while ((drtn = DERDecodeSeqNext(&piSeq, &piContent)) == DR_Success) { + require_quiet(piContent.tag == ASN1_CONSTR_SEQUENCE, badDER); + DERPolicyInformation pi; + drtn = DERParseSequenceContent(&piContent.content, + DERNumPolicyInformationItemSpecs, + DERPolicyInformationItemSpecs, + &pi, sizeof(pi)); + require_noerr_quiet(drtn, badDER); + CFStringRef piLabel = CFStringCreateWithFormat(allocator, NULL, + CFSTR("Policy Identifier #%d"), pin++); + appendOIDProperty(properties, piLabel, &pi.policyIdentifier); + CFRelease(piLabel); + if (pi.policyQualifiers.length == 0) + continue; + + DERSequence pqSeq; + drtn = DERDecodeSeqContentInit(&pi.policyQualifiers, &pqSeq); + require_noerr_quiet(drtn, badDER); + DERDecodedInfo pqContent; + int pqn = 1; + while ((drtn = DERDecodeSeqNext(&pqSeq, &pqContent)) == DR_Success) { + DERPolicyQualifierInfo pqi; + drtn = DERParseSequenceContent(&pqContent.content, + DERNumPolicyQualifierInfoItemSpecs, + DERPolicyQualifierInfoItemSpecs, + &pqi, sizeof(pqi)); + require_noerr_quiet(drtn, badDER); + DERDecodedInfo qualifierContent; + drtn = DERDecodeItem(&pqi.qualifier, &qualifierContent); + require_noerr_quiet(drtn, badDER); + CFStringRef pqLabel = CFStringCreateWithFormat(allocator, NULL, + CFSTR("Policy Qualifier #%d"), pqn++); + appendOIDProperty(properties, pqLabel, &pqi.policyQualifierID); + CFRelease(pqLabel); + if (DEROidCompare(&oidQtCps, &pqi.policyQualifierID)) { + require_quiet(qualifierContent.tag == ASN1_IA5_STRING, badDER); + appendURLContentProperty(properties, + CFSTR("CPS URI"), + &qualifierContent.content); + } else if (DEROidCompare(&oidQtUNotice, &pqi.policyQualifierID)) { + require_quiet(qualifierContent.tag == ASN1_CONSTR_SEQUENCE, badDER); + DERUserNotice un; + drtn = DERParseSequenceContent(&qualifierContent.content, + DERNumUserNoticeItemSpecs, + DERUserNoticeItemSpecs, + &un, sizeof(un)); + require_noerr_quiet(drtn, badDER); + if (un.noticeRef.length) { + DERNoticeReference nr; + drtn = DERParseSequenceContent(&un.noticeRef, + DERNumNoticeReferenceItemSpecs, + DERNoticeReferenceItemSpecs, + &nr, sizeof(nr)); + require_noerr_quiet(drtn, badDER); + appendDERThingProperty(properties, + CFSTR("Organization"), + &nr.organization); + appendIntegerSequenceContent(properties, + CFSTR("Notice Numbers"), &nr.noticeNumbers); + } + if (un.explicitText.length) { + appendDERThingProperty(properties, CFSTR("Explicit Text"), + &un.explicitText); + } + } else { + appendUnparsedProperty(properties, CFSTR("Qualifier"), + &pqi.qualifier); + } + } + } + require_quiet(drtn == DR_EndOfSequence, badDER); + return; +badDER: + appendInvalidProperty(properties, CFSTR("Certificate Policies"), + extnValue); +} + +static void appendSubjectKeyIdentifier(CFMutableArrayRef properties, + const DERItem *extnValue) { + DERReturn drtn; + DERDecodedInfo keyIdentifier; + drtn = DERDecodeItem(extnValue, &keyIdentifier); + require_noerr_quiet(drtn, badDER); + require_quiet(keyIdentifier.tag == ASN1_OCTET_STRING, badDER); + appendDataProperty(properties, CFSTR("Key Identifier"), + &keyIdentifier.content); + + return; +badDER: + appendInvalidProperty(properties, CFSTR("Invalid Subject Key Identifier"), + extnValue); +} + +/* +AuthorityKeyIdentifier ::= SEQUENCE { + keyIdentifier [0] KeyIdentifier OPTIONAL, + authorityCertIssuer [1] GeneralNames OPTIONAL, + authorityCertSerialNumber [2] CertificateSerialNumber OPTIONAL } + -- authorityCertIssuer and authorityCertSerialNumber MUST both + -- be present or both be absent + +KeyIdentifier ::= OCTET STRING +*/ +static void appendAuthorityKeyIdentifier(CFMutableArrayRef properties, + const DERItem *extnValue) { + DERAuthorityKeyIdentifier akid; + DERReturn drtn; + drtn = DERParseSequence(extnValue, + DERNumAuthorityKeyIdentifierItemSpecs, + DERAuthorityKeyIdentifierItemSpecs, + &akid, sizeof(akid)); + require_noerr_quiet(drtn, badDER); + if (akid.keyIdentifier.length) { + appendDataProperty(properties, CFSTR("Key Identifier"), + &akid.keyIdentifier); + } + if (akid.authorityCertIssuer.length || + akid.authorityCertSerialNumber.length) { + require_quiet(akid.authorityCertIssuer.length && + akid.authorityCertSerialNumber.length, badDER); + /* Perhaps put in a subsection called Authority Certificate Issuer. */ + appendGeneralNamesContent(properties, + &akid.authorityCertIssuer); + appendIntegerProperty(properties, + CFSTR("Authority Certificate Serial Number"), + &akid.authorityCertSerialNumber); + } + + return; +badDER: + appendInvalidProperty(properties, CFSTR("Authority Key Identifier"), + extnValue); +} + +/* + PolicyConstraints ::= SEQUENCE { + requireExplicitPolicy [0] SkipCerts OPTIONAL, + inhibitPolicyMapping [1] SkipCerts OPTIONAL } + + SkipCerts ::= INTEGER (0..MAX) +*/ +static void appendPolicyConstraints(CFMutableArrayRef properties, + const DERItem *extnValue) { + DERPolicyConstraints pc; + DERReturn drtn; + drtn = DERParseSequence(extnValue, + DERNumPolicyConstraintsItemSpecs, + DERPolicyConstraintsItemSpecs, + &pc, sizeof(pc)); + require_noerr_quiet(drtn, badDER); + if (pc.requireExplicitPolicy.length) { + appendIntegerProperty(properties, + CFSTR("Require Explicit Policy"), &pc.requireExplicitPolicy); + } + if (pc.inhibitPolicyMapping.length) { + appendIntegerProperty(properties, + CFSTR("Inhibit Policy Mapping"), &pc.inhibitPolicyMapping); + } + + return; + +badDER: + appendInvalidProperty(properties, CFSTR("Policy Constraints"), extnValue); +} + +/* +extendedKeyUsage EXTENSION ::= { + SYNTAX SEQUENCE SIZE (1..MAX) OF KeyPurposeId + IDENTIFIED BY id-ce-extKeyUsage } + +KeyPurposeId ::= OBJECT IDENTIFIER +*/ +static void appendExtendedKeyUsage(CFMutableArrayRef properties, + const DERItem *extnValue) { + DERTag tag; + DERSequence derSeq; + DERReturn drtn = DERDecodeSeqInit(extnValue, &tag, &derSeq); + require_noerr_quiet(drtn, badDER); + require_quiet(tag == ASN1_CONSTR_SEQUENCE, badDER); + DERDecodedInfo currDecoded; + while ((drtn = DERDecodeSeqNext(&derSeq, &currDecoded)) == DR_Success) { + require_quiet(currDecoded.tag == ASN1_OBJECT_ID, badDER); + appendOIDProperty(properties, CFSTR("Purpose"), + &currDecoded.content); + } + require_quiet(drtn == DR_EndOfSequence, badDER); + return; +badDER: + appendInvalidProperty(properties, CFSTR("Extended Key Usage"), extnValue); +} + +/* + id-pe-authorityInfoAccess OBJECT IDENTIFIER ::= { id-pe 1 } + + AuthorityInfoAccessSyntax ::= + SEQUENCE SIZE (1..MAX) OF AccessDescription + + AccessDescription ::= SEQUENCE { + accessMethod OBJECT IDENTIFIER, + accessLocation GeneralName } + + id-ad OBJECT IDENTIFIER ::= { id-pkix 48 } + + id-ad-caIssuers OBJECT IDENTIFIER ::= { id-ad 2 } + + id-ad-ocsp OBJECT IDENTIFIER ::= { id-ad 1 } +*/ +static void appendInfoAccess(CFMutableArrayRef properties, + const DERItem *extnValue) { + DERTag tag; + DERSequence adSeq; + DERReturn drtn = DERDecodeSeqInit(extnValue, &tag, &adSeq); + require_noerr_quiet(drtn, badDER); + require_quiet(tag == ASN1_CONSTR_SEQUENCE, badDER); + DERDecodedInfo adContent; + while ((drtn = DERDecodeSeqNext(&adSeq, &adContent)) == DR_Success) { + require_quiet(adContent.tag == ASN1_CONSTR_SEQUENCE, badDER); + DERAccessDescription ad; + drtn = DERParseSequenceContent(&adContent.content, + DERNumAccessDescriptionItemSpecs, + DERAccessDescriptionItemSpecs, + &ad, sizeof(ad)); + require_noerr_quiet(drtn, badDER); + appendOIDProperty(properties, CFSTR("Access Method"), + &ad.accessMethod); + //CFSTR("Access Location"); + appendGeneralNameProperty(properties, &ad.accessLocation); + } + require_quiet(drtn == DR_EndOfSequence, badDER); + return; +badDER: + appendInvalidProperty(properties, CFSTR("Authority Information Access"), + extnValue); +} + +static void appendNetscapeCertType(CFMutableArrayRef properties, + const DERItem *extnValue) { + static const CFStringRef certTypes[] = { + CFSTR("SSL client"), + CFSTR("SSL server"), + CFSTR("S/MIME"), + CFSTR("Object Signing"), + CFSTR("Reserved"), + CFSTR("SSL CA"), + CFSTR("S/MIME CA"), + CFSTR("Object Signing CA") + }; + appendBitStringNames(properties, CFSTR("Usage"), extnValue, + certTypes, sizeof(certTypes) / sizeof(*certTypes)); +} + +#if 0 +static void appendEntrustVersInfo(CFMutableArrayRef properties, + const DERItem *extnValue) { +} + +/* + * The list of Qualified Cert Statement statementIds we understand, even though + * we don't actually do anything with them; if these are found in a Qualified + * Cert Statement that's critical, we can truthfully say "yes we understand this". + */ +static const CSSM_OID_PTR knownQualifiedCertStatements[] = +{ + /* id-qcs := { id-pkix 11 } */ + (const CSSM_OID_PTR)&CSSMOID_OID_QCS_SYNTAX_V1, /* id-qcs 1 */ + (const CSSM_OID_PTR)&CSSMOID_OID_QCS_SYNTAX_V2, /* id-qcs 2 */ + (const CSSM_OID_PTR)&CSSMOID_ETSI_QCS_QC_COMPLIANCE, + (const CSSM_OID_PTR)&CSSMOID_ETSI_QCS_QC_LIMIT_VALUE, + (const CSSM_OID_PTR)&CSSMOID_ETSI_QCS_QC_RETENTION, + (const CSSM_OID_PTR)&CSSMOID_ETSI_QCS_QC_SSCD +}; +#define NUM_KNOWN_QUAL_CERT_STATEMENTS (sizeof(knownQualifiedCertStatements) / sizeof(CSSM_OID_PTR)) +*/ +static void appendQCCertStatements(CFMutableArrayRef properties, + const DERItem *extnValue) { +} + +#endif + +static bool appendPrintableDERSequence(CFMutableArrayRef properties, + CFStringRef label, const DERItem *sequence) { + DERTag tag; + DERSequence derSeq; + DERReturn drtn = DERDecodeSeqInit(sequence, &tag, &derSeq); + require_noerr_quiet(drtn, badSequence); + require_quiet(tag == ASN1_CONSTR_SEQUENCE, badSequence); + DERDecodedInfo currDecoded; + bool appendedSomething = false; + while ((drtn = DERDecodeSeqNext(&derSeq, &currDecoded)) == DR_Success) { + switch (currDecoded.tag) + { + case 0: // 0 + case ASN1_SEQUENCE: // 16 + case ASN1_SET: // 17 + // skip constructed object lengths + break; + + case ASN1_UTF8_STRING: // 12 + case ASN1_NUMERIC_STRING: // 18 + case ASN1_PRINTABLE_STRING: // 19 + case ASN1_T61_STRING: // 20, also ASN1_TELETEX_STRING + case ASN1_VIDEOTEX_STRING: // 21 + case ASN1_IA5_STRING: // 22 + case ASN1_GRAPHIC_STRING: // 25 + case ASN1_VISIBLE_STRING: // 26, also ASN1_ISO646_STRING + case ASN1_GENERAL_STRING: // 27 + case ASN1_UNIVERSAL_STRING: // 28 + { + CFStringRef string = + copyDERThingContentDescription(CFGetAllocator(properties), + currDecoded.tag, &currDecoded.content, false); + //CFStringRef cleanString = copyStringRemovingPercentEscapes(string); + + appendProperty(properties, kSecPropertyTypeString, label, + string); + CFRelease(string); + appendedSomething = true; + break; + } + default: + break; + } + } + require_quiet(drtn == DR_EndOfSequence, badSequence); + return appendedSomething; +badSequence: + return false; +} + +static void appendExtension(CFMutableArrayRef parent, + const SecCertificateExtension *extn) { + CFAllocatorRef allocator = CFGetAllocator(parent); + CFMutableArrayRef properties = CFArrayCreateMutable(allocator, 0, + &kCFTypeArrayCallBacks); + const DERItem + *extnID = &extn->extnID, + *extnValue = &extn->extnValue; + + appendBoolProperty(properties, CFSTR("Critical"), extn->critical); + +#if 1 + bool handeled = true; + /* Extensions that we know how to handle ourselves... */ + if (extnID->length == oidSubjectKeyIdentifier.length && + !memcmp(extnID->data, oidSubjectKeyIdentifier.data, extnID->length - 1)) + { + switch (extnID->data[extnID->length - 1]) { + case 14: /* SubjectKeyIdentifier id-ce 14 */ + appendSubjectKeyIdentifier(properties, extnValue); + break; + case 15: /* KeyUsage id-ce 15 */ + appendKeyUsage(properties, extnValue); + break; + case 16: /* PrivateKeyUsagePeriod id-ce 16 */ + appendPrivateKeyUsagePeriod(properties, extnValue); + break; + case 17: /* SubjectAltName id-ce 17 */ + case 18: /* IssuerAltName id-ce 18 */ + appendGeneralNames(properties, extnValue); + break; + case 19: /* BasicConstraints id-ce 19 */ + appendBasicConstraints(properties, extnValue); + break; + case 30: /* NameConstraints id-ce 30 */ + handeled = false; + break; + case 31: /* CRLDistributionPoints id-ce 31 */ + appendCrlDistributionPoints(properties, extnValue); + break; + case 32: /* CertificatePolicies id-ce 32 */ + appendCertificatePolicies(properties, extnValue); + break; + case 33: /* PolicyMappings id-ce 33 */ + handeled = false; + break; + case 35: /* AuthorityKeyIdentifier id-ce 35 */ + appendAuthorityKeyIdentifier(properties, extnValue); + break; + case 36: /* PolicyConstraints id-ce 36 */ + appendPolicyConstraints(properties, extnValue); + break; + case 37: /* ExtKeyUsage id-ce 37 */ + appendExtendedKeyUsage(properties, extnValue); + break; + case 46: /* FreshestCRL id-ce 46 */ + handeled = false; + break; + case 54: /* InhibitAnyPolicy id-ce 54 */ + handeled = false; + break; + default: + handeled = false; + break; + } + } else if (extnID->length == oidAuthorityInfoAccess.length && + !memcmp(extnID->data, oidAuthorityInfoAccess.data, extnID->length - 1)) + { + switch (extnID->data[extnID->length - 1]) { + case 1: /* AuthorityInfoAccess id-pe 1 */ + appendInfoAccess(properties, extnValue); + break; + case 3: /* QCStatements id-pe 3 */ + handeled = false; + break; + case 11: /* SubjectInfoAccess id-pe 11 */ + appendInfoAccess(properties, extnValue); + break; + default: + handeled = false; + break; + } + } else if (DEROidCompare(extnID, &oidNetscapeCertType)) { + /* 2.16.840.1.113730.1.1 netscape 1 1 */ + appendNetscapeCertType(properties, extnValue); + } else { + handeled = false; + } + + if (!handeled) { + /* Try to parse and display printable string(s). */ + if (appendPrintableDERSequence(properties, CFSTR("Data"), extnValue)) { + /* Nothing to do here appendPrintableDERSequence did the work. */ + } else { + /* Couldn't parse extension; dump the raw unparsed data as hex. */ + appendUnparsedProperty(properties, CFSTR("Data"), extnValue); + } + } +#else + /* Extensions that we know how to handle ourselves... */ + if (DEROidCompare(extnID, &oidSubjectKeyIdentifier)) { + appendSubjectKeyIdentifier(properties, extnValue); + } else if (DEROidCompare(extnID, &oidKeyUsage)) { + appendKeyUsage(properties, extnValue); + } else if (DEROidCompare(extnID, &oidPrivateKeyUsagePeriod)) { + appendPrivateKeyUsagePeriod(properties, extnValue); + } else if (DEROidCompare(extnID, &oidSubjectAltName)) { + appendGeneralNames(properties, extnValue); + } else if (DEROidCompare(extnID, &oidIssuerAltName)) { + appendGeneralNames(properties, extnValue); + } else if (DEROidCompare(extnID, &oidBasicConstraints)) { + appendBasicConstraints(properties, extnValue); + } else if (DEROidCompare(extnID, &oidCrlDistributionPoints)) { + appendCrlDistributionPoints(properties, extnValue); + } else if (DEROidCompare(extnID, &oidCertificatePolicies)) { + appendCertificatePolicies(properties, extnValue); + } else if (DEROidCompare(extnID, &oidAuthorityKeyIdentifier)) { + appendAuthorityKeyIdentifier(properties, extnValue); + } else if (DEROidCompare(extnID, &oidPolicyConstraints)) { + appendPolicyConstraints(properties, extnValue); + } else if (DEROidCompare(extnID, &oidExtendedKeyUsage)) { + appendExtendedKeyUsage(properties, extnValue); + } else if (DEROidCompare(extnID, &oidAuthorityInfoAccess)) { + appendInfoAccess(properties, extnValue); + } else if (DEROidCompare(extnID, &oidSubjectInfoAccess)) { + appendInfoAccess(properties, extnValue); + } else if (DEROidCompare(extnID, &oidNetscapeCertType)) { + appendNetscapeCertType(properties, extnValue); +#if 0 + } else if (DEROidCompare(extnID, &oidEntrustVersInfo)) { + appendEntrustVersInfo(properties, extnValue); +#endif + } else + /* Try to parse and display printable string(s). */ + if (appendPrintableDERSequence(properties, CFSTR("Data"), extnValue)) { + /* Nothing to do here appendPrintableDERSequence did the work. */ + } else { + /* Couldn't parse extension; dump the raw unparsed data as hex. */ + appendUnparsedProperty(properties, CFSTR("Data"), extnValue); + } +#endif + CFStringRef oid_string = copyLocalizedOidDescription(allocator, extnID); + appendProperty(parent, kSecPropertyTypeSection, oid_string, properties); + CFRelease(oid_string); + CFRelease(properties); +} + +/* Different types of summary types from least desired to most desired. */ +enum SummaryType { + kSummaryTypeNone, + kSummaryTypePrintable, + kSummaryTypeOrganizationName, + kSummaryTypeOrganizationalUnitName, + kSummaryTypeCommonName, +}; + +struct Summary { + enum SummaryType type; + CFStringRef summary; + CFStringRef description; +}; + +static OSStatus obtainSummaryFromX501Name(void *context, + const DERItem *type, const DERItem *value, CFIndex rdnIX) { + struct Summary *summary = (struct Summary *)context; + enum SummaryType stype = kSummaryTypeNone; + CFStringRef string = NULL; + if (DEROidCompare(type, &oidCommonName)) { + /* We skip Common Names that have generic values. */ + const char tfm[] = "Thawte Freemail Member"; + if ((value->length == sizeof(tfm) + 1) && + !memcmp(value->data + 2, tfm, sizeof(tfm) - 1)) { + return noErr; + } + stype = kSummaryTypeCommonName; + } else if (DEROidCompare(type, &oidOrganizationalUnitName)) { + stype = kSummaryTypeOrganizationalUnitName; + } else if (DEROidCompare(type, &oidOrganizationName)) { + stype = kSummaryTypeOrganizationName; + } else if (DEROidCompare(type, &oidDescription)) { + if (!summary->description) { + summary->description = string = copyDERThingDescription(kCFAllocatorDefault, value, true); + CFRetain(string); + } + stype = kSummaryTypePrintable; + } else { + stype = kSummaryTypePrintable; + } + + /* Use the first field we encounter of the highest priority type. */ + if (summary->type < stype) { + if (!string) { + string = copyDERThingDescription(kCFAllocatorDefault, value, true); + } + + if (string) { + CFReleaseSafe(summary->summary); + summary->summary = string; + summary->type = stype; + } + } else { + CFReleaseSafe(string); + } + + return noErr; +} + +CFStringRef SecCertificateCopySubjectSummaryP(SecCertificateRefP certificate) { + struct Summary summary = {}; + parseX501NameContent(&certificate->_subject, &summary, obtainSummaryFromX501Name); + /* If we found a description and a common name we change the summary to + CommonName (Description). */ + if (summary.description) { + if (summary.type == kSummaryTypeCommonName) { + CFStringRef newSummary = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, + CFSTR("%@ (%@)"), summary.summary, summary.description); + CFRelease(summary.summary); + summary.summary = newSummary; + } + CFRelease(summary.description); + } + + if (!summary.summary) { + /* If we didn't find a suitable printable string in the subject at all, we try + the first email address in the certificate instead. */ + CFArrayRef names = SecCertificateCopyRFC822Names(certificate); + if (!names) { + /* If we didn't find any email addresses in the certificate, we try finding + a DNS name instead. */ + names = SecCertificateCopyDNSNames(certificate); + } + if (names) { + summary.summary = CFArrayGetValueAtIndex(names, 0); + CFRetain(summary.summary); + CFRelease(names); + } + } + + return summary.summary; +} + +CFStringRef SecCertificateCopyIssuerSummary(SecCertificateRefP certificate) { + struct Summary summary = {}; + parseX501NameContent(&certificate->_issuer, &summary, obtainSummaryFromX501Name); + /* If we found a description and a common name we change the summary to + CommonName (Description). */ + if (summary.description) { + if (summary.type == kSummaryTypeCommonName) { + CFStringRef newSummary = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, + CFSTR("%@ (%@)"), summary.summary, summary.description); + CFRelease(summary.summary); + summary.summary = newSummary; + } + CFRelease(summary.description); + } + + return summary.summary; +} + +/* Return the earliest date on which all certificates in this chain are still + valid. */ +static CFAbsoluteTime SecCertificateGetChainsLastValidity( + SecCertificateRefP certificate) { + CFAbsoluteTime earliest = certificate->_notAfter; +#if 0 + while (certificate->_parent) { + certificate = certificate->_parent; + if (earliest > certificate->_notAfter) + earliest = certificate->_notAfter; + } +#endif + + return earliest; +} + +/* Return the latest date on which all certificates in this chain will be + valid. */ +static CFAbsoluteTime SecCertificateGetChainsFirstValidity( + SecCertificateRefP certificate) { + CFAbsoluteTime latest = certificate->_notBefore; +#if 0 + while (certificate->_parent) { + certificate = certificate->_parent; + if (latest < certificate->_notBefore) + latest = certificate->_notBefore; + } +#endif + + return latest; +} + +bool SecCertificateIsValid(SecCertificateRefP certificate, + CFAbsoluteTime verifyTime) { + check(certificate); + return certificate->_notBefore <= verifyTime && + verifyTime <= certificate->_notAfter; +} + +CFIndex SecCertificateVersion(SecCertificateRefP certificate) { + return certificate->_version + 1; +} + +CFAbsoluteTime SecCertificateNotValidBefore(SecCertificateRefP certificate) { + return certificate->_notBefore; +} + +CFAbsoluteTime SecCertificateNotValidAfter(SecCertificateRefP certificate) { + return certificate->_notAfter; +} + +CFMutableArrayRef SecCertificateCopySummaryProperties( + SecCertificateRefP certificate, CFAbsoluteTime verifyTime) { + CFAllocatorRef allocator = CFGetAllocator(certificate); + CFMutableArrayRef summary = CFArrayCreateMutable(allocator, 0, + &kCFTypeArrayCallBacks); + + /* First we put the subject summary name. */ + CFStringRef ssummary = SecCertificateCopySubjectSummaryP(certificate); + if (ssummary) { + appendProperty(summary, kSecPropertyTypeTitle, + NULL, ssummary); + CFRelease(ssummary); + } +#if 0 + CFStringRef isummary = CFSTR("Issuer Summary"); + appendProperty(summary, kSecPropertyTypeString, + CFSTR("Issued By"), isummary); + CFRelease(isummary); +#endif + + /* Let see if this certificate is currently valid. */ + CFStringRef label; + CFAbsoluteTime when; + CFStringRef message; + CFStringRef ptype; + if (verifyTime > certificate->_notAfter) { + label = CFSTR("Expired"); + when = certificate->_notAfter; + ptype = kSecPropertyTypeError; + message = CFSTR("This certificate has expired"); + } else if (certificate->_notBefore > verifyTime) { + label = CFSTR("Valid from"); + when = certificate->_notBefore; + ptype = kSecPropertyTypeError; + message = CFSTR("This certificate is not yet valid"); + } else { + CFAbsoluteTime last = SecCertificateGetChainsLastValidity(certificate); + CFAbsoluteTime first = SecCertificateGetChainsFirstValidity(certificate); + if (verifyTime > last) { + label = CFSTR("Expired"); + when = last; + ptype = kSecPropertyTypeError; + message = CFSTR("This certificate has an issuer that has expired"); + } else if (verifyTime < first) { + label = CFSTR("Valid from"); + when = first; + ptype = kSecPropertyTypeError; + message = CFSTR("This certificate has an issuer that is not yet valid"); + } else { + label = CFSTR("Expires"); + when = certificate->_notAfter; + ptype = kSecPropertyTypeSuccess; + message = CFSTR("This certificate is valid"); + } + } + + appendDateProperty(summary, label, when); + appendProperty(summary, ptype, NULL, message); + + return summary; +} + +CFArrayRef SecCertificateCopyProperties(SecCertificateRefP certificate) { + if (!certificate->_properties) { + CFAllocatorRef allocator = CFGetAllocator(certificate); + CFMutableArrayRef properties = CFArrayCreateMutable(allocator, 0, + &kCFTypeArrayCallBacks); + + /* First we put the Subject Name in the property list. */ + CFArrayRef subject_plist = createPropertiesForX501NameContent(allocator, + &certificate->_subject); + appendProperty(properties, kSecPropertyTypeSection, + CFSTR("Subject Name"), subject_plist); + CFRelease(subject_plist); + +#if 0 + /* Put Normalized subject in for testing. */ + if (certificate->_normalizedSubject) { + DERItem nsubject = { + (DERByte *)CFDataGetBytePtr(certificate->_normalizedSubject), + CFDataGetLength(certificate->_normalizedSubject) + }; + CFArrayRef nsubject_plist = createPropertiesForX501NameContent(allocator, + &nsubject); + appendProperty(properties, kSecPropertyTypeSection, + CFSTR("Normalized Subject Name"), nsubject_plist); + CFRelease(nsubject_plist); + } +#endif + + /* Next we put the Issuer Name in the property list. */ + CFArrayRef issuer_plist = createPropertiesForX501NameContent(allocator, + &certificate->_issuer); + appendProperty(properties, kSecPropertyTypeSection, + CFSTR("Issuer Name"), issuer_plist); + CFRelease(issuer_plist); + +#if 0 + /* Certificate version/type. */ + bool isRoot = false; + CFStringRef typeString = CFStringCreateWithFormat(allocator, NULL, + CFSTR("X.509 version %d %scertificate"), + certificate->_version + 1, isRoot ? "root " : ""); + appendProperty(properties, kSecPropertyTypeString, + CFSTR("Certificate Type"), typeString); + CFRelease(typeString); +#endif + + /* Version */ + CFStringRef versionString = CFStringCreateWithFormat(allocator, + NULL, CFSTR("%d"), certificate->_version + 1); + appendProperty(properties, kSecPropertyTypeString, + CFSTR("Version"), versionString); + CFRelease(versionString); + + /* Serial Number */ + if (certificate->_serialNum.length) { + appendIntegerProperty(properties, CFSTR("Serial Number"), + &certificate->_serialNum); + } + + /* Signature algorithm. */ +#if 0 + appendAlgorithmProperty(properties, CFSTR("Signature Algorithm"), + &certificate->_sigAlg); +#endif + appendAlgorithmProperty(properties, CFSTR("Signature Algorithm"), + &certificate->_tbsSigAlg); + + + /* Validity dates. */ + appendDateProperty(properties, CFSTR("Not Valid Before"), + certificate->_notBefore); + appendDateProperty(properties, CFSTR("Not Valid After"), + certificate->_notAfter); + + if (certificate->_subjectUniqueID.length) { + appendDataProperty(properties, CFSTR("Subject Unique ID"), + &certificate->_subjectUniqueID); + } + if (certificate->_issuerUniqueID.length) { + appendDataProperty(properties, CFSTR("Issuer Unique ID"), + &certificate->_issuerUniqueID); + } + + /* Public key algorithm. */ + appendAlgorithmProperty(properties, CFSTR("Public Key Algorithm"), + &certificate->_algId); + + /* Consider breaking down an RSA public key into modulus and + exponent? */ + appendDataProperty(properties, CFSTR("Public Key Data"), + &certificate->_pubKeyDER); + /* @@@ Key Size. */ + /* @@@ Key Usage. */ + + appendDataProperty(properties, CFSTR("Signature"), + &certificate->_signature); + + CFIndex ix; + for (ix = 0; ix < certificate->_extensionCount; ++ix) { + appendExtension(properties, &certificate->_extensions[ix]); + } + + /* @@@ Key Fingerprints. */ + + certificate->_properties = properties; + } + + CFRetain(certificate->_properties); + return certificate->_properties; +} + +CFDataRef SecCertificateCopySerialNumberP( + SecCertificateRefP certificate) { + if (certificate->_serialNumber) { + CFRetain(certificate->_serialNumber); + } + return certificate->_serialNumber; +} + +CFDataRef SecCertificateGetNormalizedIssuerContent( + SecCertificateRefP certificate) { + return certificate->_normalizedIssuer; +} + +CFDataRef SecCertificateGetNormalizedSubjectContent( + SecCertificateRefP certificate) { + DERItem tmpdi; + tmpdi.data = (DERByte *)CFDataGetBytePtr(certificate->_normalizedSubject); + tmpdi.length = CFDataGetLength(certificate->_normalizedSubject); + + return SecDERItemCopySequence(&tmpdi); +} + +CFDataRef SecCertificateGetNormalizedIssuer( + SecCertificateRefP certificate) { + DERItem tmpdi; + tmpdi.data = (DERByte *)CFDataGetBytePtr(certificate->_normalizedIssuer); + tmpdi.length = CFDataGetLength(certificate->_normalizedIssuer); + + return SecDERItemCopySequence(&tmpdi); +} + +CFDataRef SecCertificateGetNormalizedSubject( + SecCertificateRefP certificate) { + return certificate->_normalizedSubject; +} + +/* Verify that certificate was signed by issuerKey. */ +OSStatus SecCertificateIsSignedByP(SecCertificateRefP certificate, + SecKeyRefP issuerKey) { + /* Setup algId in SecAsn1AlgId format. */ + SecAsn1AlgId algId; + algId.algorithm.Length = certificate->_tbsSigAlg.oid.length; + algId.algorithm.Data = certificate->_tbsSigAlg.oid.data; + algId.parameters.Length = certificate->_tbsSigAlg.params.length; + algId.parameters.Data = certificate->_tbsSigAlg.params.data; + +#warning implementation empty +#if 0 + OSStatus status = SecKeyDigestAndVerify(issuerKey, &algId, + certificate->_tbs.data, certificate->_tbs.length, + certificate->_signature.data, certificate->_signature.length); + if (status) { + secdebug("verify", "signature verify failed: %d", status); + return errSecNotSigner; + } +#endif + + return noErr; +} + +#if 0 +static OSStatus SecCertificateIsIssuedBy(SecCertificateRefP certificate, + SecCertificateRefP issuer, bool signatureCheckOnly) { + if (!signatureCheckOnly) { + /* It turns out we don't actually need to use normalized subject and + issuer according to rfc2459. */ + + /* If present we should check issuerID against the issuer subjectID. */ + + /* If we have an AuthorityKeyIdentifier extension that has a keyIdentifier + then we should look for a SubjectKeyIdentifier in the issuer + certificate. + If we have a authorityCertSerialNumber we can use that for chaining. + If we have a authorityCertIssuer we can use that? (or not) */ + + /* Verify that this cert was issued by issuer. Do so by chaining + either issuerID to subjectID or normalized issuer to normalized + subject. */ + CFDataRef normalizedIssuer = + SecCertificateGetNormalizedIssuerContent(certificate); + CFDataRef normalizedIssuerSubject = + SecCertificateGetNormalizedSubjectContent(issuer); + if (normalizedIssuer && normalizedIssuerSubject && + !CFEqual(normalizedIssuer, normalizedIssuerSubject)) + return errSecIssuerMismatch; + } + + /* Next verify that this cert was signed by issuer. */ + SecKeyRef issuerKey = SecCertificateGetPublicKey(issuer); + + /* Get the encodedDigestInfo from the digest of the subject's TBSCert */ + /* FIXME: We sould cache this (or at least the digest) until we find + a suitable issuer. */ + uint8_t signedData[DER_SHA1_DIGEST_INFO_LEN]; + CFIndex signedDataLength; + CertVerifyReturn crtn; + if (DEROidCompare(&certificate->_tbsSigAlg.oid, &oidSha1Rsa)) { + signedDataLength = DER_SHA1_DIGEST_INFO_LEN; + crtn = sha1DigestInfo(&certificate->_tbs, signedData); + } else if(DEROidCompare(&certificate->_tbsSigAlg.oid, &oidMd5Rsa)) { + signedDataLength = DER_MD_DIGEST_INFO_LEN; + crtn = mdDigestInfo(WD_MD5, &certificate->_tbs, signedData); + } else if(DEROidCompare(&certificate->_tbsSigAlg.oid, &oidMd2Rsa)) { + signedDataLength = DER_MD_DIGEST_INFO_LEN; + crtn = mdDigestInfo(WD_MD2, &certificate->_tbs, signedData); + } else { + secdebug("verify", "unsupported algorithm"); + return errSecUnsupportedAlgorithm; + } + if (crtn) { + secdebug("verify", "*DigestInfo returned: %d", crtn); + /* FIXME: Do proper error code translation. */ + return errSecUnsupportedAlgorithm; + } + + OSStatus status = SecKeyRawVerify(issuerKey, kSecPaddingPKCS1, + signedData, signedDataLength, + certificate->_signature.data, certificate->_signature.length); + if (status) { + secdebug("verify", "signature verify failed: %d", status); + return errSecNotSigner; + } + + return noErr; +} + +static OSStatus _SecCertificateSetParent(SecCertificateRefP certificate, + SecCertificateRefP issuer, bool signatureCheckOnly) { + check(issuer); + if (certificate->_parent) { + /* Setting a certificates issuer twice is only allowed if the new + issuer is equal to the current one. */ + return issuer && CFEqual(certificate->_parent, issuer); + } + +#if 0 + OSStatus status = SecCertificateIsIssuedBy(certificate, issuer, + signatureCheckOnly); +#else + OSStatus status = noErr; +#endif + if (!status) { + if (CFEqual(certificate, issuer)) { + /* We don't retain ourselves cause that would be bad mojo, + however we do record that we are properly self signed. */ + certificate->_isSelfSigned = kSecSelfSignedTrue; + secdebug("cert", "set self as parent"); + return noErr; + } + + CFRetain(issuer); + certificate->_parent = issuer; + certificate->_isSelfSigned = kSecSelfSignedFalse; + } + + return status; +} + +static bool SecCertificateIsSelfSigned(SecCertificateRefP certificate) { + if (certificate->_isSelfSigned == kSecSelfSignedUnknown) { + certificate->_isSelfSigned = + (SecCertificateIsIssuedBy(certificate, certificate, false) ? + kSecSelfSignedTrue : kSecSelfSignedFalse); + } + + return certificate->_isSelfSigned == kSecSelfSignedTrue; +} + +/* Return true iff we were able to set our own parent from one of the + certificates in other_certificates, return false otherwise. If + signatureCheckOnly is true, we can skip the subject == issuer or + authorityKeyIdentifier tests. */ +static bool SecCertificateSetParentFrom(SecCertificateRefP certificate, + CFArrayRef other_certificates, bool signatureCheckOnly) { + CFIndex count = CFArrayGetCount(other_certificates); + CFIndex ix; + for (ix = 0; ix < count; ++ix) { + SecCertificateRefP candidate = (SecCertificateRefP) + CFArrayGetValueAtIndex(other_certificates, ix); + if (_SecCertificateSetParent(certificate, candidate, + signatureCheckOnly)) + return true; + } + return false; +} + +/* Lookup the parent of certificate in the keychain and set it. */ +static bool SecCertificateFindParent(SecCertificateRefP certificate) { + /* FIXME: Search for things other than just subject of our issuer if we + have a subjectID or authorityKeyIdentifier. */ + CFDataRef normalizedIssuer = + SecCertificateGetNormalizedIssuerContent(certificate); + const void *keys[] = { + kSecClass, + kSecReturnRef, + kSecMatchLimit, + kSecAttrSubject + }, + *values[] = { + kSecClassCertificate, + kCFBooleanTrue, + kSecMatchLimitAll, + normalizedIssuer + }; + CFDictionaryRef query = CFDictionaryCreate(NULL, keys, values, 4, + &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + CFTypeRef results; + OSStatus status = SecItemCopyMatching(query, &results); + CFRelease(query); + if (status) { + secdebug("cert", "SecCertificateFindParent: SecItemCopyMatching: %d", + status); + return false; + } + CFArrayRef certs = (CFArrayRef)results; + /* Since we already know the certificates we are providing as candidates + have been checked for subject matching, we can ask + SecCertificateSetParentFrom to skip everything except the signature + checks. */ + bool result = SecCertificateSetParentFrom(certificate, certs, true); + CFRelease(certs); + return result; +} + +OSStatus SecCertificateCompleteChain(SecCertificateRefP certificate, + CFArrayRef other_certificates) { + for (;;) { + if (certificate->_parent == NULL) { + if (SecCertificateIsSelfSigned(certificate)) + return noErr; + if (!other_certificates || + !SecCertificateSetParentFrom(certificate, other_certificates,\ + false)) { + if (!SecCertificateFindParent(certificate)) + return errSecIssuerNotFound; + } + } + certificate = certificate->_parent; + } +} +#endif + +static OSStatus appendIPAddressesFromGeneralNames(void *context, + SecCEGeneralNameType gnType, const DERItem *generalName) { + CFMutableArrayRef ipAddresses = (CFMutableArrayRef)context; + if (gnType == GNT_IPAddress) { + CFStringRef string = copyIPAddressContentDescription( + kCFAllocatorDefault, generalName); + if (string) { + CFArrayAppendValue(ipAddresses, string); + CFRelease(string); + } else { + return errSecInvalidCertificate; + } + } + return noErr; +} + +CFArrayRef SecCertificateCopyIPAddresses(SecCertificateRefP certificate) { + /* These can only exist in the subject alt name. */ + if (!certificate->_subjectAltName) + return NULL; + + CFMutableArrayRef ipAddresses = CFArrayCreateMutable(kCFAllocatorDefault, + 0, &kCFTypeArrayCallBacks); + OSStatus status = parseGeneralNames(&certificate->_subjectAltName->extnValue, + ipAddresses, appendIPAddressesFromGeneralNames); + if (status || CFArrayGetCount(ipAddresses) == 0) { + CFRelease(ipAddresses); + ipAddresses = NULL; + } + return ipAddresses; +} + +static OSStatus appendDNSNamesFromGeneralNames(void *context, SecCEGeneralNameType gnType, + const DERItem *generalName) { + CFMutableArrayRef dnsNames = (CFMutableArrayRef)context; + if (gnType == GNT_DNSName) { + CFStringRef string = CFStringCreateWithBytes(kCFAllocatorDefault, + generalName->data, generalName->length, + kCFStringEncodingUTF8, FALSE); + if (string) { + CFArrayAppendValue(dnsNames, string); + CFRelease(string); + } else { + return errSecInvalidCertificate; + } + } + return noErr; +} + +/* Return true if the passed in string matches the + Preferred name syntax from sections 2.3.1. in RFC 1035. + With the added check that we disallow empty dns names. + Also in order to support wildcard DNSNames we allow for the '*' + character anywhere in a dns component where we currently allow + a letter. + + ::= | " " + + ::=